cfengine-2.2.10/0000777000175000001440000000000011170173454010356 500000000000000cfengine-2.2.10/configure0000744000175000001440000274334011170173246012213 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.63. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH if test "x$CONFIG_SHELL" = x; then if (eval ":") 2>/dev/null; then as_have_required=yes else as_have_required=no fi if test $as_have_required = yes && (eval ": (as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=\$LINENO as_lineno_2=\$LINENO test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" && test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; } ") 2> /dev/null; then : else as_candidate_shells= as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. case $as_dir in /*) for as_base in sh bash ksh sh5; do as_candidate_shells="$as_candidate_shells $as_dir/$as_base" done;; esac done IFS=$as_save_IFS for as_shell in $as_candidate_shells $SHELL; do # Try only shells that exist, to save several forks. if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { ("$as_shell") 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : _ASEOF }; then CONFIG_SHELL=$as_shell as_have_required=yes if { "$as_shell" 2> /dev/null <<\_ASEOF if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi : (as_func_return () { (exit $1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = "$1" ); then : else exitcode=1 echo positional parameters were not saved. fi test $exitcode = 0) || { (exit 1); exit 1; } ( as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; } _ASEOF }; then break fi fi done if test "x$CONFIG_SHELL" != x; then for as_var in BASH_ENV ENV do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done export CONFIG_SHELL exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} fi if test $as_have_required = no; then echo This script requires a shell more modern than all the echo shells that I found on your system. Please install a echo modern shell, or manually run the script under such a echo shell if you do have one. { (exit 1); exit 1; } fi fi fi (eval "as_func_return () { (exit \$1) } as_func_success () { as_func_return 0 } as_func_failure () { as_func_return 1 } as_func_ret_success () { return 0 } as_func_ret_failure () { return 1 } exitcode=0 if as_func_success; then : else exitcode=1 echo as_func_success failed. fi if as_func_failure; then exitcode=1 echo as_func_failure succeeded. fi if as_func_ret_success; then : else exitcode=1 echo as_func_ret_success failed. fi if as_func_ret_failure; then exitcode=1 echo as_func_ret_failure succeeded. fi if ( set x; as_func_ret_success y && test x = \"\$1\" ); then : else exitcode=1 echo positional parameters were not saved. fi test \$exitcode = 0") || { echo No shell found that supports shell functions. echo Please tell bug-autoconf@gnu.org about your system, echo including any error possibly output before this message. echo This can help us improve future autoconf versions. echo Configuration will now proceed without shell functions. } as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$lt_ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` ;; esac ECHO=${lt_ECHO-echo} if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then # Yippee, $ECHO works! : else # Restart under the correct shell. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <<_LT_EOF $* _LT_EOF exit 0 fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$lt_ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if { echo_test_string=`eval $cmd`; } 2>/dev/null && { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null then break fi done fi if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$ECHO" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. ECHO='print -r' elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} else # Try using printf. ECHO='printf %s\n' if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL ECHO="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. ECHO=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. lt_ECHO=$ECHO if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" fi exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= ac_unique_file="src/cfagent.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_config_libobj_dir=pub ac_subst_vars='LTLIBOBJS BUILD_DOC_FALSE BUILD_DOC_TRUE HOSTNAME GCC_CFLAG NOWRAP EIGHTBIT LIB_SELINUX OPENSSL_LIB_LIB OPENSSL_LIB_CPPFLAGS OPENSSL_LIB_LDFLAGS BERKELEY_DB_LIB BERKELEY_DB_CFLAGS BERKELEY_DB_LDFLAGS GETCONF PS2PDF DVIPS TEXI2DVI LATEX GETLOADAVG_LIBS KMEM_GROUP NEED_SETGID LIBOBJS CPP OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL lt_ECHO AR OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED LIBTOOL RANLIB YFLAGS YACC LEXLIB LEX_OUTPUT_ROOT LEX PTHREAD_CPPFLAGS PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_gnu_ld enable_libtool_lock with_berkeleydb with_openssl with_pcre enable_DCE enable_selinux with_workdir with_docs ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS YACC YFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2 { (exit 1); exit 1; }; } ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2 { (exit 1); exit 1; }; } ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2 { (exit 1); exit 1; }; } ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2 { (exit 1); exit 1; }; } ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) { $as_echo "$as_me: error: unrecognized option: $ac_option Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && { $as_echo "$as_me: error: invalid variable name: $ac_envvar" >&2 { (exit 1); exit 1; }; } eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` { $as_echo "$as_me: error: missing argument to $ac_option" >&2 { (exit 1); exit 1; }; } fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) { $as_echo "$as_me: error: unrecognized options: $ac_unrecognized_opts" >&2 { (exit 1); exit 1; }; } ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac { $as_echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 { (exit 1); exit 1; }; } done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || { $as_echo "$as_me: error: working directory cannot be determined" >&2 { (exit 1); exit 1; }; } test "X$ac_ls_di" = "X$ac_pwd_ls_di" || { $as_echo "$as_me: error: pwd does not report name of working directory" >&2 { (exit 1); exit 1; }; } # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." { $as_echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 { (exit 1); exit 1; }; } fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || { $as_echo "$as_me: error: $ac_msg" >&2 { (exit 1); exit 1; }; } pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors --enable-shared[=PKGS] build shared libraries [default=no] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-DCE support for DCE and ACLs --enable-selinux Enable use of the SELINUX libraries Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-berkeleydb=PATH directory where BerkeleyDB exists --with-openssl=PATH directory where OpenSSL exists --with-pcre[=PATH] directory where Perl compatible regex exists (optionally in PATH) --with-workdir=WORKDIR default internal for trusted cache --with-docs build the documentation Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS C/C++/Objective C preprocessor flags, e.g. -I if you have headers in a nonstandard directory YACC The `Yet Another C Compiler' implementation to use. Defaults to the first program found out of: `bison -y', `byacc', `yacc'. YFLAGS The list of arguments that will be passed by default to $YACC. This script will default YFLAGS to the empty string to avoid a default value of `-d' given by some make applications. CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.63 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.63. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; 2) ac_configure_args1="$ac_configure_args1 '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac done done $as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } $as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo cat <<\_ASBOX ## ---------------- ## ## Cache variables. ## ## ---------------- ## _ASBOX echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo cat <<\_ASBOX ## ----------------- ## ## Output variables. ## ## ----------------- ## _ASBOX echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then cat <<\_ASBOX ## ------------------- ## ## File substitutions. ## ## ------------------- ## _ASBOX echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then cat <<\_ASBOX ## ----------- ## ## confdefs.h. ## ## ----------- ## _ASBOX echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then ac_site_file1=$CONFIG_SITE elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test -r "$ac_site_file"; then { $as_echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special # files actually), so we avoid doing that. if test -f "$cache_file"; then { $as_echo "$as_me:$LINENO: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:$LINENO: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:$LINENO: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:$LINENO: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:$LINENO: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} { { $as_echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 $as_echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} { (exit 1); exit 1; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then { { $as_echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5 $as_echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;} { (exit 1); exit 1; }; } fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || { { $as_echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5 $as_echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;} { (exit 1); exit 1; }; } { $as_echo "$as_me:$LINENO: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if test "${ac_cv_build+set}" = set; then $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && { { $as_echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 $as_echo "$as_me: error: cannot guess build type; you must specify one" >&2;} { (exit 1); exit 1; }; } ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5 $as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;} { (exit 1); exit 1; }; } fi { $as_echo "$as_me:$LINENO: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical build" >&5 $as_echo "$as_me: error: invalid value of canonical build" >&2;} { (exit 1); exit 1; }; };; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:$LINENO: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if test "${ac_cv_host+set}" = set; then $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5 $as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;} { (exit 1); exit 1; }; } fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical host" >&5 $as_echo "$as_me: error: invalid value of canonical host" >&2;} { (exit 1); exit 1; }; };; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:$LINENO: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if test "${ac_cv_target+set}" = set; then $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5 $as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;} { (exit 1); exit 1; }; } fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_target" >&5 $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical target" >&5 $as_echo "$as_me: error: invalid value of canonical target" >&2;} { (exit 1); exit 1; }; };; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- am__api_version='1.10' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:$LINENO: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:$LINENO: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". { { $as_echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&5 $as_echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken alias in your environment" >&2;} { (exit 1); exit 1; }; } fi test "$2" = conftest.file ) then # Ok. : else { { $as_echo "$as_me:$LINENO: error: newly created file is older than distributed files! Check your system clock" >&5 $as_echo "$as_me: error: newly created file is older than distributed files! Check your system clock" >&2;} { (exit 1); exit 1; }; } fi { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= { $as_echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} fi { $as_echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if test "${ac_cv_path_mkdir+set}" = set; then $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. test -d ./--version && rmdir ./--version MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:$LINENO: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } mkdir_p="$MKDIR_P" case $mkdir_p in [\\/$]* | ?:[\\/]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AWK+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:$LINENO: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then { { $as_echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 $as_echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} { (exit 1); exit 1; }; } fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE=cfengine VERSION=2.2.10 cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:$LINENO: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. AMTAR=${AMTAR-"${am_missing_run}tar"} am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' ac_config_headers="$ac_config_headers src/conf.h" # # Add to the default list of places in LDFLAGS to compensate for # ... the configure default value of LIBS on some systems # for x in /usr/lib64 /usr/local/gnu/lib /usr/local/gnulib /opt/dce/lib /sw/lib do if test -d "$x"; then y=`expr " $LDFLAGS " : ".* -L$x "` if test $y -eq 0; then LDFLAGS="$LDFLAGS -L$x" fi fi done # # Add to the default list of places in CPPFLAGS to match LDFLAGS above # for x in /usr/local/gnu/include /opt/dce/include /sw/include do if test -d "$x"; then y=`expr " $CPPFLAGS " : ".* -I$x "` if test $y -eq 0; then CPPFLAGS="$CPPFLAGS -I$x" fi fi done DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi { $as_echo "$as_me:$LINENO: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 $as_echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } # Provide some information about the compiler. $as_echo "$as_me:$LINENO: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { (ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi { $as_echo "$as_me:$LINENO: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } if test -z "$ac_file"; then $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: C compiler cannot create executables See \`config.log' for more details." >&5 $as_echo "$as_me: error: C compiler cannot create executables See \`config.log' for more details." >&2;} { (exit 77); exit 77; }; }; } fi ac_exeext=$ac_cv_exeext # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:$LINENO: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } # FIXME: These cross compiler hacks should be removed for Autoconf 3.0 # If not cross compiling, check that we can run a simple program. if test "$cross_compiling" != yes; then if { ac_try='./$ac_file' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } fi fi fi { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } { $as_echo "$as_me:$LINENO: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } { $as_echo "$as_me:$LINENO: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute suffix of executables: cannot compile and link See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } fi rm -f conftest$ac_cv_exeext { $as_echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT { $as_echo "$as_me:$LINENO: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if test "${ac_cv_objext+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot compute suffix of object files: cannot compile See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:$LINENO: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:$LINENO: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS$PTHREAD_CPPFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $PTHREAD_CPPFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" { $as_echo "$as_me:$LINENO: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 $as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_join (); int main () { return pthread_join (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then acx_pthread_ok=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # pthread: Linux, etcetera # --thread-safe: KAI C++ case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthread or # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) { $as_echo "$as_me:$LINENO: checking whether pthreads work without any flags" >&5 $as_echo_n "checking whether pthreads work without any flags... " >&6; } ;; -*) { $as_echo "$as_me:$LINENO: checking whether pthreads work with $flag" >&5 $as_echo_n "checking whether pthreads work with $flag... " >&6; } PTHREAD_CFLAGS="$flag" PTHREAD_CPPFLAGS="$flag" ;; *) { $as_echo "$as_me:$LINENO: checking for the pthreads library -l$flag" >&5 $as_echo_n "checking for the pthreads library -l$flag... " >&6; } PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CPPFLAGS="$CFLAGS $PTHREAD_CPPFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then acx_pthread_ok=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" { $as_echo "$as_me:$LINENO: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" PTHREAD_CPPFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CFLAGS $PTHREAD_CPPFLAGS" # Detect AIX lossage: threads are created detached by default # and the JOINABLE attribute has a nonstandard name (UNDETACHED). { $as_echo "$as_me:$LINENO: checking for joinable pthread attribute" >&5 $as_echo_n "checking for joinable pthread attribute... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { int attr=PTHREAD_CREATE_JOINABLE; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ok=PTHREAD_CREATE_JOINABLE else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ok=unknown fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test x"$ok" = xunknown; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { int attr=PTHREAD_CREATE_UNDETACHED; ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ok=PTHREAD_CREATE_UNDETACHED else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ok=unknown fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then cat >>confdefs.h <<\_ACEOF #define PTHREAD_CREATE_JOINABLE $ok _ACEOF fi { $as_echo "$as_me:$LINENO: result: ${ok}" >&5 $as_echo "${ok}" >&6; } if test x"$ok" = xunknown; then { $as_echo "$as_me:$LINENO: WARNING: we do not know how to create joinable pthreads" >&5 $as_echo "$as_me: WARNING: we do not know how to create joinable pthreads" >&2;} fi { $as_echo "$as_me:$LINENO: checking if more special flags are required for pthreads" >&5 $as_echo_n "checking if more special flags are required for pthreads... " >&6; } flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; # -D_REENTRANT is actually implied by -pthread in Tru64 5.1, # at least. *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac { $as_echo "$as_me:$LINENO: result: ${flag}" >&5 $as_echo "${flag}" >&6; } if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" PTHREAD_CPPFLAGS="$flag $PTHREAD_CPPFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" # More AIX lossage: must compile with cc_r # Extract the first word of "cc_r", so it can be a program name with args. set dummy cc_r; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_PTHREAD_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$PTHREAD_CC"; then ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_PTHREAD_CC="cc_r" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_PTHREAD_CC" && ac_cv_prog_PTHREAD_CC="${CC}" fi fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC if test -n "$PTHREAD_CC"; then { $as_echo "$as_me:$LINENO: result: $PTHREAD_CC" >&5 $as_echo "$PTHREAD_CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi else PTHREAD_CC="$CC" fi # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then cat >>confdefs.h <<\_ACEOF #define HAVE_PTHREAD 1 _ACEOF : else acx_pthread_ok=no fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$PTHREAD_CC CFLAGS="$PTHREAD_CFLAGS $CFLAGS" CPPFLAGS="$PTHREAD_CPPFLAGS $CPPFLAGS" LDFLAGS="$PTHREAD_LDFLAGS $LDFLAGS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:$LINENO: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_CC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&5 $as_echo "$as_me: error: no acceptable C compiler found in \$PATH See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } # Provide some information about the compiler. $as_echo "$as_me:$LINENO: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 { (ac_try="$ac_compiler --version >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler --version >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -v >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler -v >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { (ac_try="$ac_compiler -V >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compiler -V >&5") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { $as_echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if test "${ac_cv_c_compiler_gnu+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_compiler_gnu=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if test "${ac_cv_prog_cc_g+set}" = set; then $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 CFLAGS="" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_g=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if test "${ac_cv_prog_cc_c89+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_prog_cc_c89=$ac_arg else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:$LINENO: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:$LINENO: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi for ac_prog in flex lex do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_LEX+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$LEX"; then ac_cv_prog_LEX="$LEX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_LEX="$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LEX=$ac_cv_prog_LEX if test -n "$LEX"; then { $as_echo "$as_me:$LINENO: result: $LEX" >&5 $as_echo "$LEX" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$LEX" && break done test -n "$LEX" || LEX=":" if test "x$LEX" != "x:"; then cat >conftest.l <<_ACEOF %% a { ECHO; } b { REJECT; } c { yymore (); } d { yyless (1); } e { yyless (input () != 0); } f { unput (yytext[0]); } . { BEGIN INITIAL; } %% #ifdef YYTEXT_POINTER extern char *yytext; #endif int main (void) { return ! yylex () + ! yywrap (); } _ACEOF { (ac_try="$LEX conftest.l" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$LEX conftest.l") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { $as_echo "$as_me:$LINENO: checking lex output file root" >&5 $as_echo_n "checking lex output file root... " >&6; } if test "${ac_cv_prog_lex_root+set}" = set; then $as_echo_n "(cached) " >&6 else if test -f lex.yy.c; then ac_cv_prog_lex_root=lex.yy elif test -f lexyy.c; then ac_cv_prog_lex_root=lexyy else { { $as_echo "$as_me:$LINENO: error: cannot find output from $LEX; giving up" >&5 $as_echo "$as_me: error: cannot find output from $LEX; giving up" >&2;} { (exit 1); exit 1; }; } fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_lex_root" >&5 $as_echo "$ac_cv_prog_lex_root" >&6; } LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root if test -z "${LEXLIB+set}"; then { $as_echo "$as_me:$LINENO: checking lex library" >&5 $as_echo_n "checking lex library... " >&6; } if test "${ac_cv_lib_lex+set}" = set; then $as_echo_n "(cached) " >&6 else ac_save_LIBS=$LIBS ac_cv_lib_lex='none needed' for ac_lib in '' -lfl -ll; do LIBS="$ac_lib $ac_save_LIBS" cat >conftest.$ac_ext <<_ACEOF `cat $LEX_OUTPUT_ROOT.c` _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_lex=$ac_lib else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext test "$ac_cv_lib_lex" != 'none needed' && break done LIBS=$ac_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_lex" >&5 $as_echo "$ac_cv_lib_lex" >&6; } test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex fi { $as_echo "$as_me:$LINENO: checking whether yytext is a pointer" >&5 $as_echo_n "checking whether yytext is a pointer... " >&6; } if test "${ac_cv_prog_lex_yytext_pointer+set}" = set; then $as_echo_n "(cached) " >&6 else # POSIX says lex can declare yytext either as a pointer or an array; the # default is implementation-dependent. Figure out which it is, since # not all implementations provide the %pointer and %array declarations. ac_cv_prog_lex_yytext_pointer=no ac_save_LIBS=$LIBS LIBS="$LEXLIB $ac_save_LIBS" cat >conftest.$ac_ext <<_ACEOF #define YYTEXT_POINTER 1 `cat $LEX_OUTPUT_ROOT.c` _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_prog_lex_yytext_pointer=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_lex_yytext_pointer" >&5 $as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; } if test $ac_cv_prog_lex_yytext_pointer = yes; then cat >>confdefs.h <<\_ACEOF #define YYTEXT_POINTER 1 _ACEOF fi rm -f conftest.l $LEX_OUTPUT_ROOT.c fi if test "$LEX" = :; then LEX=${am_missing_run}flex fi for ac_prog in 'bison -y' byacc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_YACC+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$YACC"; then ac_cv_prog_YACC="$YACC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_YACC="$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi YACC=$ac_cv_prog_YACC if test -n "$YACC"; then { $as_echo "$as_me:$LINENO: result: $YACC" >&5 $as_echo "$YACC" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$YACC" && break done test -n "$YACC" || YACC="yacc" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:$LINENO: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test "${ac_cv_path_install+set}" = set; then $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in ./ | .// | /cC/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:$LINENO: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' if test "x$CC" != xcc; then { $as_echo "$as_me:$LINENO: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } else { $as_echo "$as_me:$LINENO: checking whether cc understands -c and -o together" >&5 $as_echo_n "checking whether cc understands -c and -o together... " >&6; } fi set dummy $CC; ac_cc=`$as_echo "$2" | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # We do the test twice because some compilers refuse to overwrite an # existing .o file with -o, though they will create one. ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -f conftest2.$ac_objext && { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then eval ac_cv_prog_cc_${ac_cc}_c_o=yes if test "x$CC" != xcc; then # Test first that cc exists at all. if { ac_try='cc -c conftest.$ac_ext >&5' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -f conftest2.$ac_objext && { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # cc works too. : else # cc exists but doesn't like -o. eval ac_cv_prog_cc_${ac_cc}_c_o=no fi fi fi else eval ac_cv_prog_cc_${ac_cc}_c_o=no fi rm -f core conftest* fi if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } cat >>confdefs.h <<\_ACEOF #define NO_MINUS_C_MINUS_O 1 _ACEOF fi # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC ac_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=no fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:$LINENO: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.2.6' macro_revision='1.3012' ltmain="$ac_aux_dir/ltmain.sh" { $as_echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if test "${ac_cv_path_SED+set}" = set; then $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed $as_unset ac_script || ac_script= if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then { { $as_echo "$as_me:$LINENO: error: no acceptable sed could be found in \$PATH" >&5 $as_echo "$as_me: error: no acceptable sed could be found in \$PATH" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if test "${ac_cv_path_GREP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then { { $as_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 $as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:$LINENO: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if test "${ac_cv_path_EGREP+set}" = set; then $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then { { $as_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 $as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:$LINENO: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if test "${ac_cv_path_FGREP+set}" = set; then $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break ac_count=`expr $ac_count + 1` if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then { { $as_echo "$as_me:$LINENO: error: no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5 $as_echo "$as_me: error: no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;} { (exit 1); exit 1; }; } fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:$LINENO: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:$LINENO: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:$LINENO: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if test "${lt_cv_path_LD+set}" = set; then $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && { { $as_echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 $as_echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} { (exit 1); exit 1; }; } { $as_echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if test "${lt_cv_prog_gnu_ld+set}" = set; then $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:$LINENO: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if test "${lt_cv_path_NM+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$ac_tool_prefix"; then for ac_prog in "dumpbin -symbols" "link -dump -symbols" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_DUMPBIN+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:$LINENO: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in "dumpbin -symbols" "link -dump -symbols" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:$LINENO: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if test "${lt_cv_nm_interface+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:6288: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:6291: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:6294: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:$LINENO: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:$LINENO: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if test "${lt_cv_sys_max_cmd_len+set}" = set; then $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ = "XX$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:$LINENO: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:$LINENO: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:$LINENO: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:$LINENO: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:$LINENO: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if test "${lt_cv_ld_reload_flag+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_OBJDUMP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:$LINENO: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:$LINENO: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if test "${lt_cv_deplibs_check_method+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_AR+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR="${ac_tool_prefix}ar" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:$LINENO: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_AR+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_AR="ar" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_STRIP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:$LINENO: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_RANLIB+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:$LINENO: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then # Now try to grab the symbols. nlist=conftest.nm if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ const struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:$LINENO: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:$LINENO: result: ok" >&5 $as_echo "ok" >&6; } fi # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 7499 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if test "${lt_cv_cc_needs_belf+set}" = set; then $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_cv_cc_needs_belf=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 lt_cv_cc_needs_belf=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_DSYMUTIL+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:$LINENO: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_NMEDIT+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:$LINENO: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_LIPO+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:$LINENO: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_OTOOL+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:$LINENO: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_OTOOL64+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:$LINENO: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:$LINENO: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:$LINENO: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if test "${lt_cv_apple_cc_single_mod+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:$LINENO: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:$LINENO: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if test "${lt_cv_ld_exported_symbols_list+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_cv_ld_exported_symbols_list=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 lt_cv_ld_exported_symbols_list=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:$LINENO: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test "${ac_cv_prog_CPP+set}" = set; then $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:$LINENO: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Broken: fails on valid input. continue fi rm -f conftest.err conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then # Broken: success on invalid input. continue else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&5 $as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -rf conftest.dSYM rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-static was given. if test "${enable_static+set}" = set; then enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then withval=$with_pic; pic_mode="$withval" else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:$LINENO: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if test "${lt_cv_objdir+set}" = set; then $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if test "${lt_cv_path_MAGIC_CMD+set}" = set; then $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:$LINENO: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if test "${lt_cv_path_MAGIC_CMD+set}" = set; then $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag=' -fno-builtin' { $as_echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:9322: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:9326: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= { $as_echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl*) # IBM XL C 8.0/Fortran 10.1 on PPC lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 $as_echo "$lt_prog_compiler_pic" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if test "${lt_cv_prog_compiler_pic_works+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:9661: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:9665: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:$LINENO: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if test "${lt_cv_prog_compiler_static_works+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:9766: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:9770: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if test "${lt_cv_prog_compiler_c_o+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:9821: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:9825: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:$LINENO: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag= tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld='-rpath $libdir' archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes=yes ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported whole_archive_flag_spec='' link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=echo archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat >conftest.$ac_ext <<_ACEOF int foo(void) {} _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:$LINENO: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\"") >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then archive_cmds_need_lc=no else archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* { $as_echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 $as_echo "$archive_cmds_need_lc" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` else lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then shlibpath_overrides_runpath=yes fi else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:$LINENO: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:$LINENO: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_dl_dlopen=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = x""yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) { $as_echo "$as_me:$LINENO: checking for shl_load" >&5 $as_echo_n "checking for shl_load... " >&6; } if test "${ac_cv_func_shl_load+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define shl_load to an innocuous variant, in case declares shl_load. For example, HP-UX 11i declares gettimeofday. */ #define shl_load innocuous_shl_load /* System header to define __stub macros and hopefully few prototypes, which can conflict with char shl_load (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef shl_load /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_shl_load || defined __stub___shl_load choke me #endif int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_shl_load=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_shl_load=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 $as_echo "$ac_cv_func_shl_load" >&6; } if test "x$ac_cv_func_shl_load" = x""yes; then lt_cv_dlopen="shl_load" else { $as_echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if test "${ac_cv_lib_dld_shl_load+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_dld_shl_load=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_shl_load=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = x""yes; then lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else { $as_echo "$as_me:$LINENO: checking for dlopen" >&5 $as_echo_n "checking for dlopen... " >&6; } if test "${ac_cv_func_dlopen+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define dlopen to an innocuous variant, in case declares dlopen. For example, HP-UX 11i declares gettimeofday. */ #define dlopen innocuous_dlopen /* System header to define __stub macros and hopefully few prototypes, which can conflict with char dlopen (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef dlopen /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_dlopen || defined __stub___dlopen choke me #endif int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_dlopen=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_dlopen=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 $as_echo "$ac_cv_func_dlopen" >&6; } if test "x$ac_cv_func_dlopen" = x""yes; then lt_cv_dlopen="dlopen" else { $as_echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if test "${ac_cv_lib_dl_dlopen+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_dl_dlopen=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dl_dlopen=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = x""yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if test "${ac_cv_lib_svld_dlopen+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_svld_dlopen=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_svld_dlopen=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = x""yes; then lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if test "${ac_cv_lib_dld_dld_link+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_dld_dld_link=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dld_dld_link=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = x""yes; then lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if test "${lt_cv_dlopen_self+set}" = set; then $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line 12621 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if test "${lt_cv_dlopen_self_static+set}" = set; then $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line 12717 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:$LINENO: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:$LINENO: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:$LINENO: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:$LINENO: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: ac_have_func=no # yes means we've found a way to get the load average. # Make sure getloadavg.c is where it belongs, at configure-time. test -f "$srcdir/$ac_config_libobj_dir/getloadavg.c" || { { $as_echo "$as_me:$LINENO: error: $srcdir/$ac_config_libobj_dir/getloadavg.c is missing" >&5 $as_echo "$as_me: error: $srcdir/$ac_config_libobj_dir/getloadavg.c is missing" >&2;} { (exit 1); exit 1; }; } ac_save_LIBS=$LIBS # Check for getloadavg, but be sure not to touch the cache variable. ({ $as_echo "$as_me:$LINENO: checking for getloadavg" >&5 $as_echo_n "checking for getloadavg... " >&6; } if test "${ac_cv_func_getloadavg+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define getloadavg to an innocuous variant, in case declares getloadavg. For example, HP-UX 11i declares gettimeofday. */ #define getloadavg innocuous_getloadavg /* System header to define __stub macros and hopefully few prototypes, which can conflict with char getloadavg (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef getloadavg /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getloadavg (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_getloadavg || defined __stub___getloadavg choke me #endif int main () { return getloadavg (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_getloadavg=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_getloadavg=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_getloadavg" >&5 $as_echo "$ac_cv_func_getloadavg" >&6; } if test "x$ac_cv_func_getloadavg" = x""yes; then exit 0 else exit 1 fi ) && ac_have_func=yes # On HPUX9, an unprivileged user can get load averages through this function. for ac_func in pstat_getdynamic do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 $as_echo_n "checking for $ac_func... " >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then eval "$as_ac_var=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # Solaris has libkstat which does not require root. { $as_echo "$as_me:$LINENO: checking for kstat_open in -lkstat" >&5 $as_echo_n "checking for kstat_open in -lkstat... " >&6; } if test "${ac_cv_lib_kstat_kstat_open+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lkstat $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char kstat_open (); int main () { return kstat_open (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_kstat_kstat_open=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_kstat_kstat_open=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_kstat_kstat_open" >&5 $as_echo "$ac_cv_lib_kstat_kstat_open" >&6; } if test "x$ac_cv_lib_kstat_kstat_open" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBKSTAT 1 _ACEOF LIBS="-lkstat $LIBS" fi test $ac_cv_lib_kstat_kstat_open = yes && ac_have_func=yes # Some systems with -lutil have (and need) -lkvm as well, some do not. # On Solaris, -lkvm requires nlist from -lelf, so check that first # to get the right answer into the cache. # For kstat on solaris, we need libelf to force the definition of SVR4 below. if test $ac_have_func = no; then { $as_echo "$as_me:$LINENO: checking for elf_begin in -lelf" >&5 $as_echo_n "checking for elf_begin in -lelf... " >&6; } if test "${ac_cv_lib_elf_elf_begin+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lelf $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char elf_begin (); int main () { return elf_begin (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_elf_elf_begin=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_elf_elf_begin=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_elf_elf_begin" >&5 $as_echo "$ac_cv_lib_elf_elf_begin" >&6; } if test "x$ac_cv_lib_elf_elf_begin" = x""yes; then LIBS="-lelf $LIBS" fi fi if test $ac_have_func = no; then { $as_echo "$as_me:$LINENO: checking for kvm_open in -lkvm" >&5 $as_echo_n "checking for kvm_open in -lkvm... " >&6; } if test "${ac_cv_lib_kvm_kvm_open+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lkvm $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char kvm_open (); int main () { return kvm_open (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_kvm_kvm_open=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_kvm_kvm_open=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_kvm_kvm_open" >&5 $as_echo "$ac_cv_lib_kvm_kvm_open" >&6; } if test "x$ac_cv_lib_kvm_kvm_open" = x""yes; then LIBS="-lkvm $LIBS" fi # Check for the 4.4BSD definition of getloadavg. { $as_echo "$as_me:$LINENO: checking for getloadavg in -lutil" >&5 $as_echo_n "checking for getloadavg in -lutil... " >&6; } if test "${ac_cv_lib_util_getloadavg+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lutil $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getloadavg (); int main () { return getloadavg (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_util_getloadavg=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_util_getloadavg=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_util_getloadavg" >&5 $as_echo "$ac_cv_lib_util_getloadavg" >&6; } if test "x$ac_cv_lib_util_getloadavg" = x""yes; then LIBS="-lutil $LIBS" ac_have_func=yes ac_cv_func_getloadavg_setgid=yes fi fi if test $ac_have_func = no; then # There is a commonly available library for RS/6000 AIX. # Since it is not a standard part of AIX, it might be installed locally. ac_getloadavg_LIBS=$LIBS LIBS="-L/usr/local/lib $LIBS" { $as_echo "$as_me:$LINENO: checking for getloadavg in -lgetloadavg" >&5 $as_echo_n "checking for getloadavg in -lgetloadavg... " >&6; } if test "${ac_cv_lib_getloadavg_getloadavg+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lgetloadavg $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getloadavg (); int main () { return getloadavg (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_getloadavg_getloadavg=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_getloadavg_getloadavg=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_getloadavg_getloadavg" >&5 $as_echo "$ac_cv_lib_getloadavg_getloadavg" >&6; } if test "x$ac_cv_lib_getloadavg_getloadavg" = x""yes; then LIBS="-lgetloadavg $LIBS" else LIBS=$ac_getloadavg_LIBS fi fi # Make sure it is really in the library, if we think we found it, # otherwise set up the replacement function. for ac_func in getloadavg do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 $as_echo_n "checking for $ac_func... " >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then eval "$as_ac_var=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else case " $LIBOBJS " in *" getloadavg.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS getloadavg.$ac_objext" ;; esac cat >>confdefs.h <<\_ACEOF #define C_GETLOADAVG 1 _ACEOF # Figure out what our getloadavg.c needs. ac_have_func=no if test "${ac_cv_header_sys_dg_sys_info_h+set}" = set; then { $as_echo "$as_me:$LINENO: checking for sys/dg_sys_info.h" >&5 $as_echo_n "checking for sys/dg_sys_info.h... " >&6; } if test "${ac_cv_header_sys_dg_sys_info_h+set}" = set; then $as_echo_n "(cached) " >&6 fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_sys_dg_sys_info_h" >&5 $as_echo "$ac_cv_header_sys_dg_sys_info_h" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking sys/dg_sys_info.h usability" >&5 $as_echo_n "checking sys/dg_sys_info.h usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking sys/dg_sys_info.h presence" >&5 $as_echo_n "checking sys/dg_sys_info.h presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: sys/dg_sys_info.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: sys/dg_sys_info.h: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: sys/dg_sys_info.h: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: sys/dg_sys_info.h: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: sys/dg_sys_info.h: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: sys/dg_sys_info.h: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/dg_sys_info.h: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: sys/dg_sys_info.h: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for sys/dg_sys_info.h" >&5 $as_echo_n "checking for sys/dg_sys_info.h... " >&6; } if test "${ac_cv_header_sys_dg_sys_info_h+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_header_sys_dg_sys_info_h=$ac_header_preproc fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_sys_dg_sys_info_h" >&5 $as_echo "$ac_cv_header_sys_dg_sys_info_h" >&6; } fi if test "x$ac_cv_header_sys_dg_sys_info_h" = x""yes; then ac_have_func=yes cat >>confdefs.h <<\_ACEOF #define DGUX 1 _ACEOF { $as_echo "$as_me:$LINENO: checking for dg_sys_info in -ldgc" >&5 $as_echo_n "checking for dg_sys_info in -ldgc... " >&6; } if test "${ac_cv_lib_dgc_dg_sys_info+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldgc $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dg_sys_info (); int main () { return dg_sys_info (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_dgc_dg_sys_info=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dgc_dg_sys_info=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dgc_dg_sys_info" >&5 $as_echo "$ac_cv_lib_dgc_dg_sys_info" >&6; } if test "x$ac_cv_lib_dgc_dg_sys_info" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBDGC 1 _ACEOF LIBS="-ldgc $LIBS" fi fi if test "${ac_cv_header_locale_h+set}" = set; then { $as_echo "$as_me:$LINENO: checking for locale.h" >&5 $as_echo_n "checking for locale.h... " >&6; } if test "${ac_cv_header_locale_h+set}" = set; then $as_echo_n "(cached) " >&6 fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 $as_echo "$ac_cv_header_locale_h" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking locale.h usability" >&5 $as_echo_n "checking locale.h usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking locale.h presence" >&5 $as_echo_n "checking locale.h presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: locale.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: locale.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: locale.h: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: locale.h: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: locale.h: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: locale.h: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: locale.h: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: locale.h: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: locale.h: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: locale.h: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: locale.h: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: locale.h: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: locale.h: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for locale.h" >&5 $as_echo_n "checking for locale.h... " >&6; } if test "${ac_cv_header_locale_h+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_header_locale_h=$ac_header_preproc fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_locale_h" >&5 $as_echo "$ac_cv_header_locale_h" >&6; } fi for ac_func in setlocale do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 $as_echo_n "checking for $ac_func... " >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then eval "$as_ac_var=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done # We cannot check for , because Solaris 2 does not use dwarf (it # uses stabs), but it is still SVR4. We cannot check for because # Irix 4.0.5F has the header but not the library. if test $ac_have_func = no && test "$ac_cv_lib_elf_elf_begin" = yes; then ac_have_func=yes cat >>confdefs.h <<\_ACEOF #define SVR4 1 _ACEOF fi if test $ac_have_func = no; then if test "${ac_cv_header_inq_stats_cpustats_h+set}" = set; then { $as_echo "$as_me:$LINENO: checking for inq_stats/cpustats.h" >&5 $as_echo_n "checking for inq_stats/cpustats.h... " >&6; } if test "${ac_cv_header_inq_stats_cpustats_h+set}" = set; then $as_echo_n "(cached) " >&6 fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_inq_stats_cpustats_h" >&5 $as_echo "$ac_cv_header_inq_stats_cpustats_h" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking inq_stats/cpustats.h usability" >&5 $as_echo_n "checking inq_stats/cpustats.h usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking inq_stats/cpustats.h presence" >&5 $as_echo_n "checking inq_stats/cpustats.h presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: inq_stats/cpustats.h: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: inq_stats/cpustats.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: inq_stats/cpustats.h: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: inq_stats/cpustats.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: inq_stats/cpustats.h: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: inq_stats/cpustats.h: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: inq_stats/cpustats.h: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: inq_stats/cpustats.h: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: inq_stats/cpustats.h: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: inq_stats/cpustats.h: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: inq_stats/cpustats.h: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: inq_stats/cpustats.h: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: inq_stats/cpustats.h: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: inq_stats/cpustats.h: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: inq_stats/cpustats.h: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: inq_stats/cpustats.h: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for inq_stats/cpustats.h" >&5 $as_echo_n "checking for inq_stats/cpustats.h... " >&6; } if test "${ac_cv_header_inq_stats_cpustats_h+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_header_inq_stats_cpustats_h=$ac_header_preproc fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_inq_stats_cpustats_h" >&5 $as_echo "$ac_cv_header_inq_stats_cpustats_h" >&6; } fi if test "x$ac_cv_header_inq_stats_cpustats_h" = x""yes; then ac_have_func=yes cat >>confdefs.h <<\_ACEOF #define UMAX 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define UMAX4_3 1 _ACEOF fi fi if test $ac_have_func = no; then if test "${ac_cv_header_sys_cpustats_h+set}" = set; then { $as_echo "$as_me:$LINENO: checking for sys/cpustats.h" >&5 $as_echo_n "checking for sys/cpustats.h... " >&6; } if test "${ac_cv_header_sys_cpustats_h+set}" = set; then $as_echo_n "(cached) " >&6 fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_sys_cpustats_h" >&5 $as_echo "$ac_cv_header_sys_cpustats_h" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking sys/cpustats.h usability" >&5 $as_echo_n "checking sys/cpustats.h usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking sys/cpustats.h presence" >&5 $as_echo_n "checking sys/cpustats.h presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: sys/cpustats.h: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: sys/cpustats.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/cpustats.h: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: sys/cpustats.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: sys/cpustats.h: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: sys/cpustats.h: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/cpustats.h: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: sys/cpustats.h: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/cpustats.h: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: sys/cpustats.h: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/cpustats.h: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: sys/cpustats.h: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/cpustats.h: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: sys/cpustats.h: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: sys/cpustats.h: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: sys/cpustats.h: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for sys/cpustats.h" >&5 $as_echo_n "checking for sys/cpustats.h... " >&6; } if test "${ac_cv_header_sys_cpustats_h+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_header_sys_cpustats_h=$ac_header_preproc fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_sys_cpustats_h" >&5 $as_echo "$ac_cv_header_sys_cpustats_h" >&6; } fi if test "x$ac_cv_header_sys_cpustats_h" = x""yes; then ac_have_func=yes; cat >>confdefs.h <<\_ACEOF #define UMAX 1 _ACEOF fi fi if test $ac_have_func = no; then for ac_header in mach/mach.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done fi for ac_header in nlist.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF { $as_echo "$as_me:$LINENO: checking for struct nlist.n_un.n_name" >&5 $as_echo_n "checking for struct nlist.n_un.n_name... " >&6; } if test "${ac_cv_member_struct_nlist_n_un_n_name+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static struct nlist ac_aggr; if (ac_aggr.n_un.n_name) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_nlist_n_un_n_name=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main () { static struct nlist ac_aggr; if (sizeof ac_aggr.n_un.n_name) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_nlist_n_un_n_name=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_member_struct_nlist_n_un_n_name=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_member_struct_nlist_n_un_n_name" >&5 $as_echo "$ac_cv_member_struct_nlist_n_un_n_name" >&6; } if test "x$ac_cv_member_struct_nlist_n_un_n_name" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_NLIST_N_UN_N_NAME 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define NLIST_NAME_UNION 1 _ACEOF fi fi done fi done # Some definitions of getloadavg require that the program be installed setgid. { $as_echo "$as_me:$LINENO: checking whether getloadavg requires setgid" >&5 $as_echo_n "checking whether getloadavg requires setgid... " >&6; } if test "${ac_cv_func_getloadavg_setgid+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "$srcdir/$ac_config_libobj_dir/getloadavg.c" #ifdef LDAV_PRIVILEGED Yowza Am I SETGID yet #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "Yowza Am I SETGID yet" >/dev/null 2>&1; then ac_cv_func_getloadavg_setgid=yes else ac_cv_func_getloadavg_setgid=no fi rm -f conftest* fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_getloadavg_setgid" >&5 $as_echo "$ac_cv_func_getloadavg_setgid" >&6; } if test $ac_cv_func_getloadavg_setgid = yes; then NEED_SETGID=true cat >>confdefs.h <<\_ACEOF #define GETLOADAVG_PRIVILEGED 1 _ACEOF else NEED_SETGID=false fi if test $ac_cv_func_getloadavg_setgid = yes; then { $as_echo "$as_me:$LINENO: checking group of /dev/kmem" >&5 $as_echo_n "checking group of /dev/kmem... " >&6; } if test "${ac_cv_group_kmem+set}" = set; then $as_echo_n "(cached) " >&6 else # On Solaris, /dev/kmem is a symlink. Get info on the real file. ac_ls_output=`ls -lgL /dev/kmem 2>/dev/null` # If we got an error (system does not support symlinks), try without -L. test -z "$ac_ls_output" && ac_ls_output=`ls -lg /dev/kmem` ac_cv_group_kmem=`$as_echo "$ac_ls_output" \ | sed -ne 's/[ ][ ]*/ /g; s/^.[sSrwx-]* *[0-9]* *\([^0-9]*\) *.*/\1/; / /s/.* //;p;'` fi { $as_echo "$as_me:$LINENO: result: $ac_cv_group_kmem" >&5 $as_echo "$ac_cv_group_kmem" >&6; } KMEM_GROUP=$ac_cv_group_kmem fi if test "x$ac_save_LIBS" = x; then GETLOADAVG_LIBS=$LIBS else GETLOADAVG_LIBS=`$as_echo "$LIBS" | sed "s|$ac_save_LIBS||"` fi LIBS=$ac_save_LIBS # Extract the first word of "latex", so it can be a program name with args. set dummy latex; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_path_LATEX+set}" = set; then $as_echo_n "(cached) " >&6 else case $LATEX in [\\/]* | ?:[\\/]*) ac_cv_path_LATEX="$LATEX" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_LATEX="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_LATEX" && ac_cv_path_LATEX="false" ;; esac fi LATEX=$ac_cv_path_LATEX if test -n "$LATEX"; then { $as_echo "$as_me:$LINENO: result: $LATEX" >&5 $as_echo "$LATEX" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "texi2dvi", so it can be a program name with args. set dummy texi2dvi; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_path_TEXI2DVI+set}" = set; then $as_echo_n "(cached) " >&6 else case $TEXI2DVI in [\\/]* | ?:[\\/]*) ac_cv_path_TEXI2DVI="$TEXI2DVI" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_TEXI2DVI="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_TEXI2DVI" && ac_cv_path_TEXI2DVI="false" ;; esac fi TEXI2DVI=$ac_cv_path_TEXI2DVI if test -n "$TEXI2DVI"; then { $as_echo "$as_me:$LINENO: result: $TEXI2DVI" >&5 $as_echo "$TEXI2DVI" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "dvips", so it can be a program name with args. set dummy dvips; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_path_DVIPS+set}" = set; then $as_echo_n "(cached) " >&6 else case $DVIPS in [\\/]* | ?:[\\/]*) ac_cv_path_DVIPS="$DVIPS" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_DVIPS="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_DVIPS" && ac_cv_path_DVIPS="false" ;; esac fi DVIPS=$ac_cv_path_DVIPS if test -n "$DVIPS"; then { $as_echo "$as_me:$LINENO: result: $DVIPS" >&5 $as_echo "$DVIPS" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "makeinfo", so it can be a program name with args. set dummy makeinfo; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_path_MAKEINFO+set}" = set; then $as_echo_n "(cached) " >&6 else case $MAKEINFO in [\\/]* | ?:[\\/]*) ac_cv_path_MAKEINFO="$MAKEINFO" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_MAKEINFO="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_MAKEINFO" && ac_cv_path_MAKEINFO="false" ;; esac fi MAKEINFO=$ac_cv_path_MAKEINFO if test -n "$MAKEINFO"; then { $as_echo "$as_me:$LINENO: result: $MAKEINFO" >&5 $as_echo "$MAKEINFO" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "ps2pdf", so it can be a program name with args. set dummy ps2pdf; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_path_PS2PDF+set}" = set; then $as_echo_n "(cached) " >&6 else case $PS2PDF in [\\/]* | ?:[\\/]*) ac_cv_path_PS2PDF="$PS2PDF" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_PS2PDF="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_PS2PDF" && ac_cv_path_PS2PDF="false" ;; esac fi PS2PDF=$ac_cv_path_PS2PDF if test -n "$PS2PDF"; then { $as_echo "$as_me:$LINENO: result: $PS2PDF" >&5 $as_echo "$PS2PDF" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "getconf", so it can be a program name with args. set dummy getconf; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_path_GETCONF+set}" = set; then $as_echo_n "(cached) " >&6 else case $GETCONF in [\\/]* | ?:[\\/]*) ac_cv_path_GETCONF="$GETCONF" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_GETCONF="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_GETCONF" && ac_cv_path_GETCONF="false" ;; esac fi GETCONF=$ac_cv_path_GETCONF if test -n "$GETCONF"; then { $as_echo "$as_me:$LINENO: result: $GETCONF" >&5 $as_echo "$GETCONF" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:$LINENO: checking for main in -lm" >&5 $as_echo_n "checking for main in -lm... " >&6; } if test "${ac_cv_lib_m_main+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_m_main=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_m_main=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_m_main" >&5 $as_echo "$ac_cv_lib_m_main" >&6; } if test "x$ac_cv_lib_m_main" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF LIBS="-lm $LIBS" fi { $as_echo "$as_me:$LINENO: checking for door_create" >&5 $as_echo_n "checking for door_create... " >&6; } if test "${ac_cv_func_door_create+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define door_create to an innocuous variant, in case declares door_create. For example, HP-UX 11i declares gettimeofday. */ #define door_create innocuous_door_create /* System header to define __stub macros and hopefully few prototypes, which can conflict with char door_create (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef door_create /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char door_create (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_door_create || defined __stub___door_create choke me #endif int main () { return door_create (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_door_create=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_door_create=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_door_create" >&5 $as_echo "$ac_cv_func_door_create" >&6; } if test "x$ac_cv_func_door_create" = x""yes; then door fi { $as_echo "$as_me:$LINENO: checking for setsockopt" >&5 $as_echo_n "checking for setsockopt... " >&6; } if test "${ac_cv_func_setsockopt+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define setsockopt to an innocuous variant, in case declares setsockopt. For example, HP-UX 11i declares gettimeofday. */ #define setsockopt innocuous_setsockopt /* System header to define __stub macros and hopefully few prototypes, which can conflict with char setsockopt (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef setsockopt /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char setsockopt (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_setsockopt || defined __stub___setsockopt choke me #endif int main () { return setsockopt (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_setsockopt=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_setsockopt=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_setsockopt" >&5 $as_echo "$ac_cv_func_setsockopt" >&6; } if test "x$ac_cv_func_setsockopt" = x""yes; then : else { $as_echo "$as_me:$LINENO: checking for setsockopt in -lsocket" >&5 $as_echo_n "checking for setsockopt in -lsocket... " >&6; } if test "${ac_cv_lib_socket_setsockopt+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char setsockopt (); int main () { return setsockopt (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_socket_setsockopt=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_socket_setsockopt=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_socket_setsockopt" >&5 $as_echo "$ac_cv_lib_socket_setsockopt" >&6; } if test "x$ac_cv_lib_socket_setsockopt" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBSOCKET 1 _ACEOF LIBS="-lsocket $LIBS" fi fi { $as_echo "$as_me:$LINENO: checking for gethostent" >&5 $as_echo_n "checking for gethostent... " >&6; } if test "${ac_cv_func_gethostent+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define gethostent to an innocuous variant, in case declares gethostent. For example, HP-UX 11i declares gettimeofday. */ #define gethostent innocuous_gethostent /* System header to define __stub macros and hopefully few prototypes, which can conflict with char gethostent (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef gethostent /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostent (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_gethostent || defined __stub___gethostent choke me #endif int main () { return gethostent (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_gethostent=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_gethostent=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_gethostent" >&5 $as_echo "$ac_cv_func_gethostent" >&6; } if test "x$ac_cv_func_gethostent" = x""yes; then : else { $as_echo "$as_me:$LINENO: checking for gethostent in -lnsl" >&5 $as_echo_n "checking for gethostent in -lnsl... " >&6; } if test "${ac_cv_lib_nsl_gethostent+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostent (); int main () { return gethostent (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_nsl_gethostent=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_nsl_gethostent=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_gethostent" >&5 $as_echo "$ac_cv_lib_nsl_gethostent" >&6; } if test "x$ac_cv_lib_nsl_gethostent" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBNSL 1 _ACEOF LIBS="-lnsl $LIBS" fi fi { $as_echo "$as_me:$LINENO: checking for getaddrinfo" >&5 $as_echo_n "checking for getaddrinfo... " >&6; } if test "${ac_cv_func_getaddrinfo+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define getaddrinfo to an innocuous variant, in case declares getaddrinfo. For example, HP-UX 11i declares gettimeofday. */ #define getaddrinfo innocuous_getaddrinfo /* System header to define __stub macros and hopefully few prototypes, which can conflict with char getaddrinfo (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef getaddrinfo /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getaddrinfo (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_getaddrinfo || defined __stub___getaddrinfo choke me #endif int main () { return getaddrinfo (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_getaddrinfo=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_getaddrinfo=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_getaddrinfo" >&5 $as_echo "$ac_cv_func_getaddrinfo" >&6; } if test "x$ac_cv_func_getaddrinfo" = x""yes; then : else { $as_echo "$as_me:$LINENO: checking for getaddrinfo in -lsocket" >&5 $as_echo_n "checking for getaddrinfo in -lsocket... " >&6; } if test "${ac_cv_lib_socket_getaddrinfo+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getaddrinfo (); int main () { return getaddrinfo (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_socket_getaddrinfo=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_socket_getaddrinfo=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_socket_getaddrinfo" >&5 $as_echo "$ac_cv_lib_socket_getaddrinfo" >&6; } if test "x$ac_cv_lib_socket_getaddrinfo" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBSOCKET 1 _ACEOF LIBS="-lsocket $LIBS" fi fi { $as_echo "$as_me:$LINENO: checking for library containing socket" >&5 $as_echo_n "checking for library containing socket... " >&6; } if test "${ac_cv_search_socket+set}" = set; then $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF for ac_lib in '' socket; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_search_socket=$ac_res else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_socket+set}" = set; then break fi done if test "${ac_cv_search_socket+set}" = set; then : else ac_cv_search_socket=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_search_socket" >&5 $as_echo "$ac_cv_search_socket" >&6; } ac_res=$ac_cv_search_socket if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else { $as_echo "$as_me:$LINENO: checking for socket in -lnsl" >&5 $as_echo_n "checking for socket in -lnsl... " >&6; } if test "${ac_cv_lib_nsl_socket+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl -lsocket $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_nsl_socket=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_nsl_socket=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_nsl_socket" >&5 $as_echo "$ac_cv_lib_nsl_socket" >&6; } if test "x$ac_cv_lib_nsl_socket" = x""yes; then LIBS="$LIBS -lsocket -lnsl" fi fi # Check whether --with-berkeleydb was given. if test "${with_berkeleydb+set}" = set; then withval=$with_berkeleydb; BERKELEY_DB_DIR=$with_berkeleydb else BERKELEY_DB_DIR=default fi { $as_echo "$as_me:$LINENO: checking for BerkeleyDB location in $BERKELEY_DB_DIR" >&5 $as_echo_n "checking for BerkeleyDB location in $BERKELEY_DB_DIR... " >&6; } if test "x$BERKELEY_DB_DIR" = "xno" ; then { $as_echo "$as_me:$LINENO: result: " >&5 $as_echo "" >&6; } { { $as_echo "$as_me:$LINENO: error: This release of cfengine requires a version of BerkeleyDB 4.4 or later" >&5 $as_echo "$as_me: error: This release of cfengine requires a version of BerkeleyDB 4.4 or later" >&2;} { (exit 1); exit 1; }; } else if test "x$BERKELEY_DB_DIR" = "xdefault" ; then for v in BerkeleyDB.4.2 BerkeleyDB.4.3 BerkeleyDB.4.4 BerkeleyDB.4.5 BerkeleyDB.4.6 BerkeleyDB.4.7; do for d in $prefix /opt /usr/local /usr; do test -d "$d/$v" && BERKELEY_DB_DIR="$d/$v" done done fi if test "x$BERKELEY_DB_DIR" = "xdefault" ; then for d in $prefix /opt /usr/local /usr; do for v in db-4 db4 db3 db db40; do if test -f "$d/include/$v/db.h" ; then echo "Found header in $d/include/$v " test "x$d" != "x/usr" && BERKELEY_DB_LDFLAGS="-L$d/lib" BERKELEY_DB_CFLAGS="-I$d/include/$v" late_LIBS=$LIBS # In RedHat 8, for instance, we have /usr/include/db4 # and libdb-4.0.a. Debian has /usr/lib/libdb-4.1.a, for # instance. Look for the appropriate library. if test $v = db4 -o $v = db40; then save_CFLAGS="$CFLAGS" save_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $BERKELEY_DB_CFLAGS" LDFLAGS="$LDFLAGS $BERKELEY_DB_LDFLAGS" { $as_echo "$as_me:$LINENO: checking for library containing db_create" >&5 $as_echo_n "checking for library containing db_create... " >&6; } if test "${ac_cv_search_db_create+set}" = set; then $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char db_create (); int main () { return db_create (); ; return 0; } _ACEOF for ac_lib in '' db-4 db4 db-4.7 db-4.6 db-4.5 db-4.4 db-4.3 db-4.2 db-4.1 db-4.0; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_search_db_create=$ac_res else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_db_create+set}" = set; then break fi done if test "${ac_cv_search_db_create+set}" = set; then : else ac_cv_search_db_create=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_search_db_create" >&5 $as_echo "$ac_cv_search_db_create" >&6; } ac_res=$ac_cv_search_db_create if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" BERKELEY_DB_LIB=$ac_cv_search_db_create fi CFLAGS="$save_CFLAGS" LDFLAGS="$save_LDFLAGS" else BERKELEY_DB_LIB="-l$v" fi LIBS=$late_LIBS { $as_echo "$as_me:$LINENO: result: $d" >&5 $as_echo "$d" >&6; } break fi done test "x$BERKELEY_DB_LIB" != "x" && break if test -f "$d/include/db.h"; then if test "x$d" != "x/usr"; then BERKELEY_DB_LDFLAGS="-L$d/lib64 -L$d/lib" BERKELEY_DB_CFLAGS="-I$d/include" fi BERKELEY_DB_LIB="-ldb" { $as_echo "$as_me:$LINENO: result: $d" >&5 $as_echo "$d" >&6; } break fi done if test "x$BERKELEY_DB_LIB" = "x" ; then { { $as_echo "$as_me:$LINENO: error: Cannot find BerkeleyDB" >&5 $as_echo "$as_me: error: Cannot find BerkeleyDB" >&2;} { (exit 1); exit 1; }; } fi elif test -f "$BERKELEY_DB_DIR/include/db.h";then case "$target_os" in solaris*) #If we are staticlly linking the BDB files, we do not want a #-R flag. If .so's are present, assume we are dynamic linking if test -n "`ls $BERKELEY_DB_DIR/lib/*.so 2>/dev/null`" then BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib -R$BERKELEY_DB_DIR/lib" else BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib" fi;; *) BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib";; esac BERKELEY_DB_CFLAGS="-I$BERKELEY_DB_DIR/include" BERKELEY_DB_LIB="-ldb" { $as_echo "$as_me:$LINENO: result: $BERKELEY_DB_DIR" >&5 $as_echo "$BERKELEY_DB_DIR" >&6; } elif test -d "$BERKELEY_DB_DIR"; then BERKELEY_DB_CFLAGS="-I$BERKELEY_DB_DIR/include" for v in . db47 db46 db45 db44 db43 db42 db41 db40 db4 db33 db32 db3 db; do if test -f "$BERKELEY_DB_DIR/include/$v/db.h"; then BERKELEY_DB_CFLAGS="-I$BERKELEY_DB_DIR/include/$v" break fi done BERKELEY_DB_LIB="-ldb" for v in db-4.7 db4.7 db47 db-4.6 db4.6 db46 db-4.5 db4.5 db45 db-4.4 db4.4 db44; do if test -f "$BERKELEY_DB_DIR/lib/lib$v.so"; then BERKELEY_DB_LIB="-l$v" break fi if test -f "$BERKELEY_DB_DIR/lib64/lib$v.so"; then BERKELEY_DB_LIB="-l$v" break fi done case "$target_os" in solaris*) #If we are staticlly linking the BDB files, we do not want a #-R flag. If .so's are present, assume we are dynamic linking if test -n "`ls $BERKELEY_DB_DIR/lib/*.so 2>/dev/null`" then BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib -R$BERKELEY_DB_DIR/lib" else BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib" fi;; *) BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib";; esac { $as_echo "$as_me:$LINENO: result: $BERKELEY_DB_DIR" >&5 $as_echo "$BERKELEY_DB_DIR" >&6; } else { { $as_echo "$as_me:$LINENO: error: Cannot find BerkeleyDB" >&5 $as_echo "$as_me: error: Cannot find BerkeleyDB" >&2;} { (exit 1); exit 1; }; } fi cat >>confdefs.h <<\_ACEOF #define USE_BERKELEY_DB 1 _ACEOF BERKELEY_DB_SAVE_LDFLAGS=$LDFLAGS BERKELEY_DB_SAVE_CPPFLAGS=$CPPFLAGS BERKELEY_DB_SAVE_LIBS=$LIBS LDFLAGS="$LDFLAGS $BERKELEY_DB_LDFLAGS" CFLAGS="$CFLAGS $BERKELEY_DB_CFLAGS" LIBS="$LIBS $BERKELEY_DB_LIB" { $as_echo "$as_me:$LINENO: checking Berkeley DB Version" >&5 $as_echo_n "checking Berkeley DB Version... " >&6; } if test "$cross_compiling" = yes; then { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main(void) { printf("%d.%d.%d ",DB_VERSION_MAJOR,DB_VERSION_MINOR,DB_VERSION_PATCH); if (DB_VERSION_MAJOR < 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 2)) exit(1); exit(0); } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then { $as_echo "$as_me:$LINENO: result: OK" >&5 $as_echo "OK" >&6; } else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { $as_echo "$as_me:$LINENO: error: This release of cfengine requires BerkeleyDB 3.2 or later" >&5 $as_echo "$as_me: error: This release of cfengine requires BerkeleyDB 3.2 or later" >&2;} { (exit 1); exit 1; }; } fi rm -rf conftest.dSYM rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: checking Berkeley DB API" >&5 $as_echo_n "checking Berkeley DB API... " >&6; } if test "$cross_compiling" = yes; then { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main(void) { printf("%d.%d.%d ",DB_VERSION_MAJOR,DB_VERSION_MINOR,DB_VERSION_PATCH); if (DB_VERSION_MAJOR < 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 1)) exit(1); exit(0); } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then { $as_echo "$as_me:$LINENO: result: OK" >&5 $as_echo "OK" >&6; } else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) cat >>confdefs.h <<\_ACEOF #define CF_OLD_DB 1 _ACEOF fi rm -rf conftest.dSYM rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: checking for db_create in -ldb" >&5 $as_echo_n "checking for db_create in -ldb... " >&6; } if test "${ac_cv_lib_db_db_create+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldb $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char db_create (); int main () { return db_create (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_db_db_create=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_db_db_create=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_db_db_create" >&5 $as_echo "$ac_cv_lib_db_db_create" >&6; } if test "x$ac_cv_lib_db_db_create" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBDB 1 _ACEOF LIBS="-ldb $LIBS" fi LDFLAGS=$BERKELEY_DB_SAVE_LDFLAGS CPPFLAGS=$BERKELEY_DB_SAVE_CPPFLAGS LIBS=$BERKELEY_DB_SAVE_LIBS fi ### ### Search for openssl ### # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then withval=$with_openssl; OPENSSL_LIB_DIR=$with_openssl else OPENSSL_LIB_DIR=default fi { $as_echo "$as_me:$LINENO: checking for OpenSSL location" >&5 $as_echo_n "checking for OpenSSL location... " >&6; } if test x"$OPENSSL_LIB_DIR" = xno ; then { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:$LINENO: error: This release of cfengine requires OpenSSL 0.9.7 or later" >&5 $as_echo "$as_me: error: This release of cfengine requires OpenSSL 0.9.7 or later" >&2;} { (exit 1); exit 1; }; } else if test x"$OPENSSL_LIB_DIR" = xdefault ; then for d in $prefix /opt/ssl /usr/local/ssl /usr/local /usr; do if test -f "$d/include/openssl/opensslv.h"; then OPENSSL_LIB_LDFLAGS="-L$d/lib64 -L$d/lib" OPENSSL_LIB_CPPFLAGS="-I$d/include" OPENSSL_LIB_LIB="-lcrypto" { $as_echo "$as_me:$LINENO: result: $d" >&5 $as_echo "$d" >&6; } break fi done if test x"$OPENSSL_LIB_LIB" = x ; then { { $as_echo "$as_me:$LINENO: error: Cannot find OpenSSL" >&5 $as_echo "$as_me: error: Cannot find OpenSSL" >&2;} { (exit 1); exit 1; }; } fi elif test -f "$OPENSSL_LIB_DIR/include/openssl/ssl.h";then case "$target_os" in solaris*) #If we are staticlly linking the SSL files, we do not want a #-R flag. If .so's are present, assume we are dynamic linking if test -n "`ls $OPENSSL_LIB_DIR/lib/*.so 2>/dev/null`" then OPENSSL_LIB_LDFLAGS="-L$OPENSSL_LIB_DIR/lib -R$OPENSSL_LIB_DIR/lib" else OPENSSL_LIB_LDFLAGS="-L$OPENSSL_LIB_DIR/lib" fi;; *) OPENSSL_LIB_LDFLAGS="-L$OPENSSL_LIB_DIR/lib";; esac OPENSSL_LIB_CPPFLAGS="-I$OPENSSL_LIB_DIR/include" OPENSSL_LIB_LIB="-lcrypto" { $as_echo "$as_me:$LINENO: result: $OPENSSL_LIB_DIR" >&5 $as_echo "$OPENSSL_LIB_DIR" >&6; } else { { $as_echo "$as_me:$LINENO: error: Cannot find OpenSSL" >&5 $as_echo "$as_me: error: Cannot find OpenSSL" >&2;} { (exit 1); exit 1; }; } fi cat >>confdefs.h <<\_ACEOF #define USE_OPENSSL_LIB 1 _ACEOF OPENSSL_SAVE_LDFLAGS=$LDFLAGS OPENSSL_SAVE_CPPFLAGS=$CPPFLAGS OPENSSL_SAVE_LIBS=$LIBS LDFLAGS="$LDFLAGS $OPENSSL_LIB_LDFLAGS" CPPFLAGS="$CPPFLAGS $OPENSSL_LIB_CPPFLAGS" LIBS="$LIBS $OPENSSL_LIB_LIB" { $as_echo "$as_me:$LINENO: checking OpenSSL Version" >&5 $as_echo_n "checking OpenSSL Version... " >&6; } if test "$cross_compiling" = yes; then { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling See \`config.log' for more details." >&5 $as_echo "$as_me: error: cannot run test program while cross compiling See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; }; } else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include int main(void) { if (OPENSSL_VERSION_NUMBER < 0x0090602fL) exit(1); exit(0); } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then { $as_echo "$as_me:$LINENO: result: OK" >&5 $as_echo "OK" >&6; } else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) { { $as_echo "$as_me:$LINENO: error: This release of cfengine requires openssl 0.9.7 or later" >&5 $as_echo "$as_me: error: This release of cfengine requires openssl 0.9.7 or later" >&2;} { (exit 1); exit 1; }; } fi rm -rf conftest.dSYM rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: checking for main in -lcrypto" >&5 $as_echo_n "checking for main in -lcrypto... " >&6; } if test "${ac_cv_lib_crypto_main+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcrypto $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_crypto_main=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_crypto_main=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_crypto_main" >&5 $as_echo "$ac_cv_lib_crypto_main" >&6; } if test "x$ac_cv_lib_crypto_main" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBCRYPTO 1 _ACEOF LIBS="-lcrypto $LIBS" fi LDFLAGS=$OPENSSL_SAVE_LDFLAGS CPPFLAGS=$OPENSSL_SAVE_CPPFLAGS LIBS=$OPENSSL_SAVE_LIBS fi # Check whether --with-pcre was given. if test "${with_pcre+set}" = set; then withval=$with_pcre; { $as_echo "$as_me:$LINENO: checking pcre" >&5 $as_echo_n "checking pcre... " >&6; } if test "x$withval" != "xno" ; then if test "x$withval" != "xyes" ; then if test "x$withval" = "xdefault" ; then for d in $prefix /usr/local /usr; do if test -f "$d/include/pcreposix.h" ; then CPPFLAGS="$CPPFLAGS -I$d/include" LDFLAGS="$LDFLAGS -L$d/lib" PCRE_LIB="-lpcreposix" { $as_echo "$as_me:$LINENO: result: $d" >&5 $as_echo "$d" >&6; } break fi done if test x"$PCRE_LIB" = x ; then { { $as_echo "$as_me:$LINENO: error: Cannot find PCRE" >&5 $as_echo "$as_me: error: Cannot find PCRE" >&2;} { (exit 1); exit 1; }; } fi else if test -f "${withval}/include/pcreposix.h" ; then CPPFLAGS="$CPPFLAGS -I${withval}/include" LDFLAGS="$LDFLAGS -L${withval}/lib" { $as_echo "$as_me:$LINENO: result: \"${withval}\"" >&5 $as_echo "\"${withval}\"" >&6; } else { { $as_echo "$as_me:$LINENO: error: Cannot find PCRE" >&5 $as_echo "$as_me: error: Cannot find PCRE" >&2;} { (exit 1); exit 1; }; } fi fi else { $as_echo "$as_me:$LINENO: result: \"yes\"" >&5 $as_echo "\"yes\"" >&6; } fi LIBS="$LIBS -lpcreposix" cat >>confdefs.h <<\_ACEOF #define USE_PCRE 1 _ACEOF fi fi { $as_echo "$as_me:$LINENO: checking for main in -lrx" >&5 $as_echo_n "checking for main in -lrx... " >&6; } if test "${ac_cv_lib_rx_main+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrx $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_rx_main=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_rx_main=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_rx_main" >&5 $as_echo "$ac_cv_lib_rx_main" >&6; } if test "x$ac_cv_lib_rx_main" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBRX 1 _ACEOF LIBS="-lrx $LIBS" fi { $as_echo "$as_me:$LINENO: checking for main in -lrt" >&5 $as_echo_n "checking for main in -lrt... " >&6; } if test "${ac_cv_lib_rt_main+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lrt $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_rt_main=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_rt_main=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_rt_main" >&5 $as_echo "$ac_cv_lib_rt_main" >&6; } if test "x$ac_cv_lib_rt_main" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBRT 1 _ACEOF LIBS="-lrt $LIBS" fi for ac_header in unistd.h stdlib.h sys/loadavg.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/mount.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in utime.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in time.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/time.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in malloc.h sys/malloc.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in vfs.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/vfs.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/sockio.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/statvfs.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/statfs.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/param.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in fcntl.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/filesys.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dustat.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in regex.h rxposix.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/systeminfo.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sys/acl.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_stdc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF rm -f conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { ac_try='./conftest$ac_exeext' { (case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then : else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ( exit $ac_status ) ac_cv_header_stdc=no fi rm -rf conftest.dSYM rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext fi fi fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then cat >>confdefs.h <<\_ACEOF #define STDC_HEADERS 1 _ACEOF fi { $as_echo "$as_me:$LINENO: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if test "${ac_cv_header_time+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_time=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then cat >>confdefs.h <<\_ACEOF #define TIME_WITH_SYS_TIME 1 _ACEOF fi { $as_echo "$as_me:$LINENO: checking for sys/wait.h that is POSIX.1 compatible" >&5 $as_echo_n "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } if test "${ac_cv_header_sys_wait_h+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main () { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_header_sys_wait_h=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_header_sys_wait_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_sys_wait_h" >&5 $as_echo "$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_SYS_WAIT_H 1 _ACEOF fi ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_hdr that defines DIR" >&5 $as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then eval "$as_ac_Header=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { $as_echo "$as_me:$LINENO: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if test "${ac_cv_search_opendir+set}" = set; then $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_search_opendir=$ac_res else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_opendir+set}" = set; then break fi done if test "${ac_cv_search_opendir+set}" = set; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { $as_echo "$as_me:$LINENO: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if test "${ac_cv_search_opendir+set}" = set; then $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_search_opendir=$ac_res else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext if test "${ac_cv_search_opendir+set}" = set; then break fi done if test "${ac_cv_search_opendir+set}" = set; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi { $as_echo "$as_me:$LINENO: checking for mode_t" >&5 $as_echo_n "checking for mode_t... " >&6; } if test "${ac_cv_type_mode_t+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_type_mode_t=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if (sizeof (mode_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if (sizeof ((mode_t))) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_mode_t=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_type_mode_t" >&5 $as_echo "$ac_cv_type_mode_t" >&6; } if test "x$ac_cv_type_mode_t" = x""yes; then : else cat >>confdefs.h <<_ACEOF #define mode_t int _ACEOF fi { $as_echo "$as_me:$LINENO: checking for size_t" >&5 $as_echo_n "checking for size_t... " >&6; } if test "${ac_cv_type_size_t+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_type_size_t=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if (sizeof (size_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if (sizeof ((size_t))) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_size_t=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_type_size_t" >&5 $as_echo "$ac_cv_type_size_t" >&6; } if test "x$ac_cv_type_size_t" = x""yes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi { $as_echo "$as_me:$LINENO: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if test "${ac_cv_type_uid_t+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:$LINENO: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then cat >>confdefs.h <<\_ACEOF #define uid_t int _ACEOF cat >>confdefs.h <<\_ACEOF #define gid_t int _ACEOF fi { $as_echo "$as_me:$LINENO: checking for pid_t" >&5 $as_echo_n "checking for pid_t... " >&6; } if test "${ac_cv_type_pid_t+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_type_pid_t=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if (sizeof (pid_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if (sizeof ((pid_t))) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_pid_t=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_type_pid_t" >&5 $as_echo "$ac_cv_type_pid_t" >&6; } if test "x$ac_cv_type_pid_t" = x""yes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi { $as_echo "$as_me:$LINENO: checking for clockid_t" >&5 $as_echo_n "checking for clockid_t... " >&6; } if test "${ac_cv_type_clockid_t+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_type_clockid_t=no cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if (sizeof (clockid_t)) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default int main () { if (sizeof ((clockid_t))) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_type_clockid_t=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_type_clockid_t" >&5 $as_echo "$ac_cv_type_clockid_t" >&6; } if test "x$ac_cv_type_clockid_t" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_CLOCKID_T 1 _ACEOF fi { $as_echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if test "${ac_cv_c_const+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset cs; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_c_const=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then cat >>confdefs.h <<\_ACEOF #define const /**/ _ACEOF fi for ac_func in getcwd getnetgrent waitpid seteuid setegid setreuid setregid do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 $as_echo_n "checking for $ac_func... " >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then eval "$as_ac_var=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in uname gethostname realpath regcomp chflags do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 $as_echo_n "checking for $ac_func... " >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then eval "$as_ac_var=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in strstr strsep putenv drand48 srand48 getaddrinfo do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 $as_echo_n "checking for $ac_func... " >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then eval "$as_ac_var=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in bcopy mkfifo statfs statvfs door qsort do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 $as_echo_n "checking for $ac_func... " >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then eval "$as_ac_var=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in sysinfo setsid strdup strrchr strerror snprintf sysconf do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 $as_echo_n "checking for $ac_func... " >&6; } if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define $ac_func to an innocuous variant, in case declares $ac_func. For example, HP-UX 11i declares gettimeofday. */ #define $ac_func innocuous_$ac_func /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $ac_func (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $ac_func /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $ac_func (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$ac_func || defined __stub___$ac_func choke me #endif int main () { return $ac_func (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then eval "$as_ac_var=yes" else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 eval "$as_ac_var=no" fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi ac_res=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } as_val=`eval 'as_val=${'$as_ac_var'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:$LINENO: checking for struct sockaddr.sa_len" >&5 $as_echo_n "checking for struct sockaddr.sa_len... " >&6; } if test "${ac_cv_member_struct_sockaddr_sa_len+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { static struct sockaddr ac_aggr; if (ac_aggr.sa_len) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_sockaddr_sa_len=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include #include int main () { static struct sockaddr ac_aggr; if (sizeof ac_aggr.sa_len) return 0; ; return 0; } _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_cv_member_struct_sockaddr_sa_len=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_member_struct_sockaddr_sa_len=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_member_struct_sockaddr_sa_len" >&5 $as_echo "$ac_cv_member_struct_sockaddr_sa_len" >&6; } if test "x$ac_cv_member_struct_sockaddr_sa_len" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_STRUCT_SOCKADDR_SA_LEN 1 _ACEOF fi rtry=none { $as_echo "$as_me:$LINENO: checking for either struct rtentry or struct ortentry" >&5 $as_echo_n "checking for either struct rtentry or struct ortentry... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "rtentry" >/dev/null 2>&1; then rtry=rtentry fi rm -f conftest* if test "$rtry" = rtentry; then cat >>confdefs.h <<\_ACEOF #define HAVE_RTENTRY 1 _ACEOF fi cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "ortentry" >/dev/null 2>&1; then rtry=ortentry fi rm -f conftest* if test "$rtry" = ortentry; then cat >>confdefs.h <<\_ACEOF #define HAVE_ORTENTRY 1 _ACEOF fi { $as_echo "$as_me:$LINENO: result: $rtry" >&5 $as_echo "$rtry" >&6; } lfsresult=no { $as_echo "$as_me:$LINENO: checking whether to compile with large file support" >&5 $as_echo_n "checking whether to compile with large file support... " >&6; } if test "$GETCONF" != "false"; then lfscflags=`$GETCONF LFS_CFLAGS 2>/dev/null` if test -n "$lfscflags"; then CFLAGS="$CFLAGS $lfscflags" lfsresult=yes fi lfsldflags=`$GETCONF LFS_LDFLAGS 2>/dev/null` test -n "$lfsldflags" && LDFLAGS="$LDFLAGS $lfsldflags" fi { $as_echo "$as_me:$LINENO: result: $lfsresult" >&5 $as_echo "$lfsresult" >&6; } { $as_echo "$as_me:$LINENO: checking for main in -lpthread" >&5 $as_echo_n "checking for main in -lpthread... " >&6; } if test "${ac_cv_lib_pthread_main+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_pthread_main=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread_main=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_main" >&5 $as_echo "$ac_cv_lib_pthread_main" >&6; } if test "x$ac_cv_lib_pthread_main" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" fi if test "$ac_cv_lib_pthread_main" = "yes"; then for ac_header in pthread.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sched.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done fi { $as_echo "$as_me:$LINENO: checking for lchown" >&5 $as_echo_n "checking for lchown... " >&6; } if test "${ac_cv_func_lchown+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define lchown to an innocuous variant, in case declares lchown. For example, HP-UX 11i declares gettimeofday. */ #define lchown innocuous_lchown /* System header to define __stub macros and hopefully few prototypes, which can conflict with char lchown (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef lchown /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lchown (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_lchown || defined __stub___lchown choke me #endif int main () { return lchown (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_lchown=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_lchown=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_lchown" >&5 $as_echo "$ac_cv_func_lchown" >&6; } if test "x$ac_cv_func_lchown" = x""yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_LCHOWN 1 _ACEOF fi { $as_echo "$as_me:$LINENO: checking for pthread_attr_setstacksize" >&5 $as_echo_n "checking for pthread_attr_setstacksize... " >&6; } if test "${ac_cv_func_pthread_attr_setstacksize+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define pthread_attr_setstacksize to an innocuous variant, in case declares pthread_attr_setstacksize. For example, HP-UX 11i declares gettimeofday. */ #define pthread_attr_setstacksize innocuous_pthread_attr_setstacksize /* System header to define __stub macros and hopefully few prototypes, which can conflict with char pthread_attr_setstacksize (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef pthread_attr_setstacksize /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_attr_setstacksize (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_pthread_attr_setstacksize || defined __stub___pthread_attr_setstacksize choke me #endif int main () { return pthread_attr_setstacksize (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_pthread_attr_setstacksize=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_pthread_attr_setstacksize=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_pthread_attr_setstacksize" >&5 $as_echo "$ac_cv_func_pthread_attr_setstacksize" >&6; } if test "x$ac_cv_func_pthread_attr_setstacksize" = x""yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1 _ACEOF else { $as_echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5 $as_echo_n "checking for pthread_create in -lpthread... " >&6; } if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_pthread_pthread_create=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread_pthread_create=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5 $as_echo "$ac_cv_lib_pthread_pthread_create" >&6; } if test "x$ac_cv_lib_pthread_pthread_create" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" fi fi { $as_echo "$as_me:$LINENO: checking for pthread_sigmask" >&5 $as_echo_n "checking for pthread_sigmask... " >&6; } if test "${ac_cv_func_pthread_sigmask+set}" = set; then $as_echo_n "(cached) " >&6 else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Define pthread_sigmask to an innocuous variant, in case declares pthread_sigmask. For example, HP-UX 11i declares gettimeofday. */ #define pthread_sigmask innocuous_pthread_sigmask /* System header to define __stub macros and hopefully few prototypes, which can conflict with char pthread_sigmask (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef pthread_sigmask /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_sigmask (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_pthread_sigmask || defined __stub___pthread_sigmask choke me #endif int main () { return pthread_sigmask (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_func_pthread_sigmask=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_func_pthread_sigmask=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:$LINENO: result: $ac_cv_func_pthread_sigmask" >&5 $as_echo "$ac_cv_func_pthread_sigmask" >&6; } if test "x$ac_cv_func_pthread_sigmask" = x""yes; then cat >>confdefs.h <<\_ACEOF #define HAVE_PTHREAD_SIGMASK 1 _ACEOF else { $as_echo "$as_me:$LINENO: checking for pthread_create in -lpthread" >&5 $as_echo_n "checking for pthread_create in -lpthread... " >&6; } if test "${ac_cv_lib_pthread_pthread_create+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_create (); int main () { return pthread_create (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_pthread_pthread_create=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthread_pthread_create=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_pthread_pthread_create" >&5 $as_echo "$ac_cv_lib_pthread_pthread_create" >&6; } if test "x$ac_cv_lib_pthread_pthread_create" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREAD 1 _ACEOF LIBS="-lpthread $LIBS" fi fi # Check whether --enable-DCE was given. if test "${enable_DCE+set}" = set; then enableval=$enable_DCE; case "$enableval" in no) ;; *) { $as_echo "$as_me:$LINENO: checking for main in -lthread" >&5 $as_echo_n "checking for main in -lthread... " >&6; } if test "${ac_cv_lib_thread_main+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_thread_main=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_thread_main=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_thread_main" >&5 $as_echo "$ac_cv_lib_thread_main" >&6; } if test "x$ac_cv_lib_thread_main" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBTHREAD 1 _ACEOF LIBS="-lthread $LIBS" fi { $as_echo "$as_me:$LINENO: checking for main in -ldce" >&5 $as_echo_n "checking for main in -ldce... " >&6; } if test "${ac_cv_lib_dce_main+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldce $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_dce_main=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_dce_main=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_dce_main" >&5 $as_echo "$ac_cv_lib_dce_main" >&6; } if test "x$ac_cv_lib_dce_main" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBDCE 1 _ACEOF LIBS="-ldce $LIBS" fi for ac_header in dce/daclif.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in pthread.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in sched.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ;; esac fi # Check whether --enable-selinux was given. if test "${enable_selinux+set}" = set; then enableval=$enable_selinux; cat >>confdefs.h <<\_ACEOF #define WITH_SELINUX 1 _ACEOF LIB_SELINUX="-lselinux" LIBS="$LIBS $LIB_SELINUX" fi if test "$srcdir" != "."; then CPPFLAGS="$CPPFLAGS -I`pwd`/src" fi case "$target_os" in sunos3*) cat >>confdefs.h <<\_ACEOF #define SUN3 1 _ACEOF ;; sunos4*) cat >>confdefs.h <<\_ACEOF #define SUN4 1 _ACEOF ;; solaris2.4*) cat >>confdefs.h <<\_ACEOF #define SOLARIS 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define HAVE_SYS_ACL_H /**/ _ACEOF CPPFLAGS="-w $CPPFLAGS" LIBS="$LIBS -lelf" ;; solaris2.5*) cat >>confdefs.h <<\_ACEOF #define SOLARIS 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define _POSIX_C_SOURCE 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define __EXTENSIONS__ 1 _ACEOF LIBS="$LIBS -lelf -lsec" ;; solaris2*) cat >>confdefs.h <<\_ACEOF #define SOLARIS 1 _ACEOF cat >>confdefs.h <<\_ACEOF #define __BIT_TYPES_DEFINED__ 1 _ACEOF # avoid conflict with db.h cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _POSIX_C_SOURCE 1 #include int main () { ; return 0; } _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then cat >>confdefs.h <<\_ACEOF #define _POSIX_C_SOURCE 1 _ACEOF else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 cat >>confdefs.h <<\_ACEOF #define _POSIX_C_SOURCE 200112loL _ACEOF fi rm -f conftest.err conftest.$ac_ext cat >>confdefs.h <<\_ACEOF #define __EXTENSIONS__ 1 _ACEOF LIBS="$LIBS -lelf -lsec" ;; ultrix*) cat >>confdefs.h <<\_ACEOF #define ULTRIX 1 _ACEOF ;; hpux*|hp-ux*) cat >>confdefs.h <<\_ACEOF #define HPuUX 1 _ACEOF if test "$GCC" != "yes"; then cat >>confdefs.h <<\_ACEOF #define REGEX_MALLOC 1 _ACEOF fi LIBS="$LIBS -lc" { $as_echo "$as_me:$LINENO: checking for main in -lPW" >&5 $as_echo_n "checking for main in -lPW... " >&6; } if test "${ac_cv_lib_PW_main+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lPW $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_PW_main=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_PW_main=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_PW_main" >&5 $as_echo "$ac_cv_lib_PW_main" >&6; } if test "x$ac_cv_lib_PW_main" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBPW 1 _ACEOF LIBS="-lPW $LIBS" fi ;; aix*) cat >>confdefs.h <<\_ACEOF #define AIX 1 _ACEOF CPPFLAGS="$CPPFLAGS -w" { $as_echo "$as_me:$LINENO: checking for main in -lpthreads" >&5 $as_echo_n "checking for main in -lpthreads... " >&6; } if test "${ac_cv_lib_pthreads_main+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpthreads $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_pthreads_main=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_pthreads_main=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_pthreads_main" >&5 $as_echo "$ac_cv_lib_pthreads_main" >&6; } if test "x$ac_cv_lib_pthreads_main" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBPTHREADS 1 _ACEOF LIBS="-lpthreads $LIBS" fi if test "${ac_cv_header_pthreads_h+set}" = set; then { $as_echo "$as_me:$LINENO: checking for pthreads.h" >&5 $as_echo_n "checking for pthreads.h... " >&6; } if test "${ac_cv_header_pthreads_h+set}" = set; then $as_echo_n "(cached) " >&6 fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_pthreads_h" >&5 $as_echo "$ac_cv_header_pthreads_h" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking pthreads.h usability" >&5 $as_echo_n "checking pthreads.h usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking pthreads.h presence" >&5 $as_echo_n "checking pthreads.h presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: pthreads.h: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: pthreads.h: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: pthreads.h: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: pthreads.h: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: pthreads.h: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: pthreads.h: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: pthreads.h: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: pthreads.h: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: pthreads.h: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: pthreads.h: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: pthreads.h: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: pthreads.h: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: pthreads.h: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: pthreads.h: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: pthreads.h: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: pthreads.h: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for pthreads.h" >&5 $as_echo_n "checking for pthreads.h... " >&6; } if test "${ac_cv_header_pthreads_h+set}" = set; then $as_echo_n "(cached) " >&6 else ac_cv_header_pthreads_h=$ac_header_preproc fi { $as_echo "$as_me:$LINENO: result: $ac_cv_header_pthreads_h" >&5 $as_echo "$ac_cv_header_pthreads_h" >&6; } fi ;; osf*) cat >>confdefs.h <<\_ACEOF #define OSF 1 _ACEOF if test "$GCC" = yes; then { $as_echo "$as_me:$LINENO: WARNING: pthreads may not work with GCC under Tru64" >&5 $as_echo "$as_me: WARNING: pthreads may not work with GCC under Tru64" >&2;} { $as_echo "$as_me:$LINENO: WARNING: If you get build errors mentioning PTHREADDEFAULTS etc.," >&5 $as_echo "$as_me: WARNING: If you get build errors mentioning PTHREADDEFAULTS etc.," >&2;} { $as_echo "$as_me:$LINENO: WARNING: re-configure with CC=cc." >&5 $as_echo "$as_me: WARNING: re-configure with CC=cc." >&2;} fi ;; irix6*) # rtentry is detected OK on a 6.5.19 system. cat >>confdefs.h <<\_ACEOF #define HAVE_ORTENTRY 1 _ACEOF # Have to hack this for 6.* owing to bug cat >>confdefs.h <<\_ACEOF #define IRIX 1 _ACEOF CFLAGS="$CFLAGS -w" ;; irix4*) cat >>confdefs.h <<\_ACEOF #define IRIX 1 _ACEOF CFLAGS="$CFLAGS -w" LIBS="$LIBS -lsun" ;; irix*) cat >>confdefs.h <<\_ACEOF #define IRIX 1 _ACEOF CFLAGS="$CFLAGS -w" ;; linux*) cat >>confdefs.h <<\_ACEOF #define LINUX 1 _ACEOF { $as_echo "$as_me:$LINENO: checking for yp_get_default_domain in -lnss_nis" >&5 $as_echo_n "checking for yp_get_default_domain in -lnss_nis... " >&6; } if test "${ac_cv_lib_nss_nis_yp_get_default_domain+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnss_nis $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char yp_get_default_domain (); int main () { return yp_get_default_domain (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_nss_nis_yp_get_default_domain=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_nss_nis_yp_get_default_domain=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_nss_nis_yp_get_default_domain" >&5 $as_echo "$ac_cv_lib_nss_nis_yp_get_default_domain" >&6; } if test "x$ac_cv_lib_nss_nis_yp_get_default_domain" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBNSS_NIS 1 _ACEOF LIBS="-lnss_nis $LIBS" fi ;; freebsd*|dragonfly*) cat >>confdefs.h <<\_ACEOF #define FREEBSD 1 _ACEOF CFLAGS="$CFLAGS -pthread -D_THREAD_SAFE -DBUILDTIN_GCC_THREAD" for ac_header in pthread.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ;; netbsd*) cat >>confdefs.h <<\_ACEOF #define NETBSD 1 _ACEOF ;; newsos*) cat >>confdefs.h <<\_ACEOF #define NEWS_OS 1 _ACEOF ;; bsd/os*) cat >>confdefs.h <<\_ACEOF #define BSDOS 1 _ACEOF ;; bsd*) cat >>confdefs.h <<\_ACEOF #define BSD43 1 _ACEOF ;; aos*) cat >>confdefs.h <<\_ACEOF #define AOS 1 _ACEOF ;; nextstep*) cat >>confdefs.h <<\_ACEOF #define NEXTSTEP 1 _ACEOF ;; unicos*) cat >>confdefs.h <<\_ACEOF #define CFCRAY 1 _ACEOF ;; cray*) cat >>confdefs.h <<\_ACEOF #define CFCRAY 1 _ACEOF ;; qnx*) cat >>confdefs.h <<\_ACEOF #define CFQNX 1 _ACEOF ;; openbsd*|obsd*) cat >>confdefs.h <<\_ACEOF #define OPENBSD 1 _ACEOF ;; gnu*) cat >>confdefs.h <<\_ACEOF #define CFGNU 1 _ACEOF ;; sysv4.2MP|unix_sv*) cat >>confdefs.h <<\_ACEOF #define UNIXWARE 1 _ACEOF { $as_echo "$as_me:$LINENO: checking for main in -lthread" >&5 $as_echo_n "checking for main in -lthread... " >&6; } if test "${ac_cv_lib_thread_main+set}" = set; then $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lthread $LIBS" cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ int main () { return main (); ; return 0; } _ACEOF rm -f conftest.$ac_objext conftest$ac_exeext if { (ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_link") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then ac_cv_lib_thread_main=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_cv_lib_thread_main=no fi rm -rf conftest.dSYM rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:$LINENO: result: $ac_cv_lib_thread_main" >&5 $as_echo "$ac_cv_lib_thread_main" >&6; } if test "x$ac_cv_lib_thread_main" = x""yes; then cat >>confdefs.h <<_ACEOF #define HAVE_LIBTHREAD 1 _ACEOF LIBS="-lthread $LIBS" fi if test "$ac_cv_lib_thread_main" = "yes"; then for ac_header in thread.h do as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 $as_echo_n "checking $ac_header usability... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ $ac_includes_default #include <$ac_header> _ACEOF rm -f conftest.$ac_objext if { (ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_compile") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then ac_header_compiler=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 $as_echo_n "checking $ac_header presence... " >&6; } cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include <$ac_header> _ACEOF if { (ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" $as_echo "$ac_try_echo") >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 ac_status=$? grep -v '^ *+' conftest.er1 >conftest.err rm -f conftest.er1 cat conftest.err >&5 $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } >/dev/null && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then ac_header_preproc=yes else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_header_preproc=no fi rm -f conftest.err conftest.$ac_ext { $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in yes:no: ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} ac_header_preproc=yes ;; no:yes:* ) { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 $as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 $as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} ;; esac { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 $as_echo_n "checking for $ac_header... " >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then $as_echo_n "(cached) " >&6 else eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi as_val=`eval 'as_val=${'$as_ac_Header'} $as_echo "$as_val"'` if test "x$as_val" = x""yes; then cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done fi ;; cygwin*) cat >>confdefs.h <<\_ACEOF #define NT 1 _ACEOF ;; sco*) cat >>confdefs.h <<\_ACEOF #define SCO 1 _ACEOF ;; darwin*) cat >>confdefs.h <<\_ACEOF #define DARWIN 1 _ACEOF LDFLAGS="-Xlinker -m $LDFLAGS" ;; *) { { $as_echo "$as_me:$LINENO: error: Unknown system type $target_os" >&5 $as_echo "$as_me: error: Unknown system type $target_os" >&2;} { (exit 1); exit 1; }; } ;; esac # Check whether --with-workdir was given. if test "${with_workdir+set}" = set; then withval=$with_workdir; if test x$withval != x ; then WORKDIR=$withval else WORKDIR=/var/cfengine fi cat >>confdefs.h <<_ACEOF #define WORKDIR "${WORKDIR}" _ACEOF else WORKDIR=/var/cfengine cat >>confdefs.h <<_ACEOF #define WORKDIR "${WORKDIR}" _ACEOF fi { $as_echo "$as_me:$LINENO: checking 8-bit support in Flex" >&5 $as_echo_n "checking 8-bit support in Flex... " >&6; } if test "$LEX" = "flex"; then EIGHTBIT="\200-\377" { $as_echo "$as_me:$LINENO: result: 8-bit support added" >&5 $as_echo "8-bit support added" >&6; } NOWRAP="%option noyywrap" else { $as_echo "$as_me:$LINENO: result: no 8-bit support" >&5 $as_echo "no 8-bit support" >&6; } NOWRAP="" fi LIBS="-L../pub -lcfpub $LIBS" { $as_echo "$as_me:$LINENO: checking Checking for GCC Specific compile flags" >&5 $as_echo_n "checking Checking for GCC Specific compile flags... " >&6; } if test x"$GCC" = "xyes"; then GCC_CFLAG="-g -O2 -Wreturn-type -Wmissing-prototypes -Wuninitialized" { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } else GCC_CFLAG="" { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "hostname", so it can be a program name with args. set dummy hostname; ac_word=$2 { $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if test "${ac_cv_path_HOSTNAME+set}" = set; then $as_echo_n "(cached) " >&6 else case $HOSTNAME in [\\/]* | ?:[\\/]*) ac_cv_path_HOSTNAME="$HOSTNAME" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_HOSTNAME="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_HOSTNAME" && ac_cv_path_HOSTNAME="""" ;; esac fi HOSTNAME=$ac_cv_path_HOSTNAME if test -n "$HOSTNAME"; then { $as_echo "$as_me:$LINENO: result: $HOSTNAME" >&5 $as_echo "$HOSTNAME" >&6; } else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi cat >>confdefs.h <<_ACEOF #define AUTOCONF_HOSTNAME "`$HOSTNAME`" _ACEOF cat >>confdefs.h <<_ACEOF #define AUTOCONF_SYSNAME "$target_os" _ACEOF { $as_echo "$as_me:$LINENO: checking Checking for Xen cpuid-based HVM detection" >&5 $as_echo_n "checking Checking for Xen cpuid-based HVM detection... " >&6; } if test x"$GCC" = "xyes"; then case $host_cpu in i[3456]86*|x86_64*) cat >>confdefs.h <<\_ACEOF #define XEN_CPUID_SUPPORT 1 _ACEOF { $as_echo "$as_me:$LINENO: result: yes" >&5 $as_echo "yes" >&6; } ;; *) { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } ;; esac else { $as_echo "$as_me:$LINENO: result: no" >&5 $as_echo "no" >&6; } fi # Check whether --with-docs was given. if test "${with_docs+set}" = set; then withval=$with_docs; want_doc=true else want_doc=false fi if test x$want_doc = xtrue; then BUILD_DOC_TRUE= BUILD_DOC_FALSE='#' else BUILD_DOC_TRUE='#' BUILD_DOC_FALSE= fi ac_config_files="$ac_config_files pub/Makefile src/Makefile doc/Makefile contrib/Makefile inputs/Makefile Makefile src/cflex.l" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) $as_unset $ac_var ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes (double-quote # substitution turns \\\\ into \\, and sed turns \\ into \). sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then test "x$cache_file" != "x/dev/null" && { $as_echo "$as_me:$LINENO: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} cat confcache >$cache_file else { $as_echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext" ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&5 $as_echo "$as_me: error: conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 $as_echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 $as_echo "$as_me: error: conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi if test -z "${BUILD_DOC_TRUE}" && test -z "${BUILD_DOC_FALSE}"; then { { $as_echo "$as_me:$LINENO: error: conditional \"BUILD_DOC\" was never defined. Usually this means the macro was only invoked conditionally." >&5 $as_echo "$as_me: error: conditional \"BUILD_DOC\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi : ${CONFIG_STATUS=./config.status} ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} cat >$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ## --------------------- ## ## M4sh Initialization. ## ## --------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # PATH needs CR # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Support unset when possible. if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then as_unset=unset else as_unset=false fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. case $0 in *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 { (exit 1); exit 1; } fi # Work around bugs in pre-3.0 UWIN ksh. for as_var in ENV MAIL MAILPATH do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # Required to use basename. if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi # Name of the executable. as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # CDPATH. $as_unset CDPATH as_lineno_1=$LINENO as_lineno_2=$LINENO test "x$as_lineno_1" != "x$as_lineno_2" && test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || { # Create $as_me.lineno as a copy of $as_myself, but with $LINENO # uniformly replaced by the line number. The first 'sed' inserts a # line-number line after each line using $LINENO; the second 'sed' # does the real work. The second script uses 'N' to pair each # line-number line with the line containing $LINENO, and appends # trailing '-' during substitution so that $LINENO is not a special # case at line end. # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the # scripts with optimization help from Paolo Bonzini. Blame Lee # E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 { (exit 1); exit 1; }; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in -n*) case `echo 'x\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. *) ECHO_C='\c';; esac;; *) ECHO_N='-n';; esac if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p=: else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.63. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files from templates according to the current configuration. Usage: $0 [OPTION]... [FILE]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.63, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2008 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac CONFIG_FILES="$CONFIG_FILES '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac CONFIG_HEADERS="$CONFIG_HEADERS '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header { $as_echo "$as_me: error: ambiguous option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; };; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) { $as_echo "$as_me: error: unrecognized option: $1 Try \`$0 --help' for more information." >&2 { (exit 1); exit 1; }; } ;; *) ac_config_targets="$ac_config_targets $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # Quote evaled strings. for var in SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ AR \ AR_FLAGS \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ SHELL \ ECHO \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_wl \ lt_prog_compiler_pic \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ fix_srcfile_path \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Fix-up fallback echo if it was mangled by the above quoting rules. case \$lt_ECHO in *'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` ;; esac ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "src/conf.h") CONFIG_HEADERS="$CONFIG_HEADERS src/conf.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "pub/Makefile") CONFIG_FILES="$CONFIG_FILES pub/Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "contrib/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;; "inputs/Makefile") CONFIG_FILES="$CONFIG_FILES inputs/Makefile" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/cflex.l") CONFIG_FILES="$CONFIG_FILES src/cflex.l" ;; *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 $as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;} { (exit 1); exit 1; }; };; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= trap 'exit_status=$? { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status ' 0 trap '{ (exit 1); exit 1; }' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || { $as_echo "$as_me: cannot create a temporary directory in ." >&2 { (exit 1); exit 1; } } # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=' ' ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 $as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 $as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 $as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\).*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\).*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ || { { $as_echo "$as_me:$LINENO: error: could not setup config files machinery" >&5 $as_echo "$as_me: error: could not setup config files machinery" >&2;} { (exit 1); exit 1; }; } _ACEOF # VPATH may cause trouble with some makes, so we remove $(srcdir), # ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=/{ s/:*\$(srcdir):*/:/ s/:*\${srcdir}:*/:/ s/:*@srcdir@:*/:/ s/^\([^=]*=[ ]*\):*/\1/ s/:*$// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_t=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_t"; then break elif $ac_last_try; then { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_HEADERS" >&5 $as_echo "$as_me: error: could not make $CONFIG_HEADERS" >&2;} { (exit 1); exit 1; }; } else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 { { $as_echo "$as_me:$LINENO: error: could not setup config headers machinery" >&5 $as_echo "$as_me: error: could not setup config headers machinery" >&2;} { (exit 1); exit 1; }; } fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) { { $as_echo "$as_me:$LINENO: error: invalid tag $ac_tag" >&5 $as_echo "$as_me: error: invalid tag $ac_tag" >&2;} { (exit 1); exit 1; }; };; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || { { $as_echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5 $as_echo "$as_me: error: cannot find input file: $ac_f" >&2;} { (exit 1); exit 1; }; };; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac ac_file_inputs="$ac_file_inputs '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:$LINENO: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$tmp/stdin" \ || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 $as_echo "$as_me: error: could not create $ac_file" >&2;} { (exit 1); exit 1; }; } ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir="$ac_dir" case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 $as_echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p ' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 $as_echo "$as_me: error: could not create $ac_file" >&2;} { (exit 1); exit 1; }; } test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined." >&2;} rm -f "$tmp/stdin" case $ac_file in -) cat "$tmp/out" && rm -f "$tmp/out";; *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; esac \ || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 $as_echo "$as_me: error: could not create $ac_file" >&2;} { (exit 1); exit 1; }; } ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" } >"$tmp/config.h" \ || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 $as_echo "$as_me: error: could not create $ac_file" >&2;} { (exit 1); exit 1; }; } if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:$LINENO: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$tmp/config.h" "$ac_file" \ || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5 $as_echo "$as_me: error: could not create $ac_file" >&2;} { (exit 1); exit 1; }; } fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ || { { $as_echo "$as_me:$LINENO: error: could not create -" >&5 $as_echo "$as_me: error: could not create -" >&2;} { (exit 1); exit 1; }; } fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:$LINENO: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` { as_dir=$dirpart/$fdir case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5 $as_echo "$as_me: error: cannot create directory $as_dir" >&2;} { (exit 1); exit 1; }; }; } # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == "file_magic". file_magic_cmd=$lt_file_magic_cmd # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name of the directory that contains temporary libtool files. objdir=$objdir # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that does not interpret backslashes. ECHO=$lt_ECHO # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into a binary # during linking. This must work even if \$libdir does not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path=$lt_fix_srcfile_path # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) case $xsi_shell in yes) cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac } # func_basename file func_basename () { func_basename_result="${1##*/}" } # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}" } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). func_stripname () { # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"} } # func_opt_split func_opt_split () { func_opt_split_opt=${1%%=*} func_opt_split_arg=${1#*=} } # func_lo2o object func_lo2o () { case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac } # func_xform libobj-or-source func_xform () { func_xform_result=${1%.*}.lo } # func_arith arithmetic-term... func_arith () { func_arith_result=$(( $* )) } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=${#1} } _LT_EOF ;; *) # Bourne compatible functions. cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_basename file func_basename () { func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; esac } # sed scripts: my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' my_sed_long_arg='1s/^-[^=]*=//' # func_opt_split func_opt_split () { func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` } # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` } # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` } # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "$@"` } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } _LT_EOF esac case $lt_shell_append in yes) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$1+=\$2" } _LT_EOF ;; *) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$1=\$$1\$2" } _LT_EOF ;; esac sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag { (exit 0); exit 0; } _ACEOF chmod +x $CONFIG_STATUS ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || { { $as_echo "$as_me:$LINENO: error: write failure creating $CONFIG_STATUS" >&5 $as_echo "$as_me: error: write failure creating $CONFIG_STATUS" >&2;} { (exit 1); exit 1; }; } # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || { (exit 1); exit 1; } fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:$LINENO: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi { $as_echo "$as_me:$LINENO: WARNING: =====================================================" >&5 $as_echo "$as_me: WARNING: =====================================================" >&2;} { $as_echo "$as_me:$LINENO: WARNING: " >&5 $as_echo "$as_me: WARNING: " >&2;} { $as_echo "$as_me:$LINENO: WARNING: DFS users should use --enable-DCE" >&5 $as_echo "$as_me: WARNING: DFS users should use --enable-DCE" >&2;} { $as_echo "$as_me:$LINENO: WARNING: " >&5 $as_echo "$as_me: WARNING: " >&2;} { $as_echo "$as_me:$LINENO: WARNING: Cfengine depends on the Berkeley db and OpenSSL " >&5 $as_echo "$as_me: WARNING: Cfengine depends on the Berkeley db and OpenSSL " >&2;} { $as_echo "$as_me:$LINENO: WARNING: Most recent versions are always recommended " >&5 $as_echo "$as_me: WARNING: Most recent versions are always recommended " >&2;} { $as_echo "$as_me:$LINENO: WARNING: =====================================================" >&5 $as_echo "$as_me: WARNING: =====================================================" >&2;} rm -f src/cfparse.c src/cfparse.h { $as_echo "$as_me:$LINENO: result: DONE: Configuration done. Run make/gmake to build cfengine." >&5 $as_echo "DONE: Configuration done. Run make/gmake to build cfengine." >&6; } cfengine-2.2.10/acconfig.h0000644000175000001440000000421210202123447012203 00000000000000/* cfengine for GNU Copyright (C) 1995/6 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ @TOP@ /* The old route entry structure in newer BSDs */ #undef HAVE_ORTENTRY /* Do we ahve any route entry structure ? */ #undef HAVE_RTENTRY /* Whether to use the local REGEX functions */ #undef REGEX_MALLOC /* Whether to use LCHOWN to change ownerships */ #undef HAVE_LCHOWN /* Whether the thread library has setmask */ #undef HAVE_PTHREAD_SIGMASK /* Whether the thread library has setstacksize */ #undef HAVE_PTHREAD_ATTR_SETSTACKSIZE /* Whether libdb has db_open */ #undef HAVE_DB_CREATE /* Does the host have /var/run directory? */ #undef HAVE_VAR_RUN /* Special OS defines */ #undef SUN3 #undef SUN4 #undef SOLARIS #undef ULTRIX #undef HPuUX #undef AIX #undef OSF #undef IRIX #undef LINUX #undef DEBIAN #undef FREEBSD #undef NETBSD #undef NEWS_OS #undef BSDOS #undef BSD43 #undef AOS #undef SCO #undef NEXTSTEP #undef CFCRAY #undef CFQNX #undef CFGNU #undef UNIXWARE #undef OPENBSD #undef HAVE_SYS_ACL_H #undef NOTBROKEN #undef NT #undef DARWIN /* SVR4 header stuff */ #undef __EXTENSIONS__ #undef _POSIX_C_SOURCE /* Solaris 2.6 */ #undef __BIT_TYPES_DEFINED__ /* LOCK and LOG directories */ #undef WORKDIR /* Special CFEngine symbols */ #undef AUTOCONF_HOSTNAME #undef AUTOCONF_SYSNAME cfengine-2.2.10/pub/0000777000175000001440000000000011170173454011144 500000000000000cfengine-2.2.10/pub/getopt1.c0000644000175000001440000001046110202123437012600 00000000000000/* getopt_long and getopt_long_only entry points for GNU getopt. Copyright (C) 1987, 88, 89, 90, 91, 92, 1993, 1994 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "getopt.h" #if !defined (__STDC__) || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined (_LIBC) || !defined (__GNU_LIBRARY__) /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ #include #else char *getenv (); #endif #ifndef NULL #define NULL 0 #endif int getopt_long (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. If an option that starts with '-' (not '--') doesn't match a long option, but does match a short option, it is parsed as a short option instead. */ int getopt_long_only (argc, argv, options, long_options, opt_index) int argc; char *const *argv; const char *options; const struct option *long_options; int *opt_index; { return _getopt_internal (argc, argv, options, long_options, opt_index, 1); } #endif /* _LIBC or not __GNU_LIBRARY__. */ #ifdef TEST #include int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; int option_index = 0; static struct option long_options[] = { {"add", 1, 0, 0}, {"append", 0, 0, 0}, {"delete", 1, 0, 0}, {"verbose", 0, 0, 0}, {"create", 0, 0, 0}, {"file", 1, 0, 0}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "abc:d:0123456789", long_options, &option_index); if (c == EOF) break; switch (c) { case 0: printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case 'd': printf ("option d with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ cfengine-2.2.10/pub/snprintf.c0000644000175000001440000012200610202123437013057 00000000000000/* * snprintf.c - a portable implementation of snprintf * * AUTHOR * Mark Martinec , April 1999. * * Copyright 1999, Mark Martinec. All rights reserved. * * TERMS AND CONDITIONS * This program is free software; you can redistribute it and/or modify * it under the terms of the "Frontier Artistic License" which comes * with this Kit. * * 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 Frontier Artistic License for more details. * * You should have received a copy of the Frontier Artistic License * with this Kit in the file named LICENSE.txt . * If not, I'll be glad to provide one. * * FEATURES * - careful adherence to specs regarding flags, field width and precision; * - good performance for large string handling (large format, large * argument or large paddings). Performance is similar to system's sprintf * and in several cases significantly better (make sure you compile with * optimizations turned on, tell the compiler the code is strict ANSI * if necessary to give it more freedom for optimizations); * - return value semantics per ISO/IEC 9899:1999 ("ISO C99"); * - written in standard ISO/ANSI C - requires an ANSI C compiler. * * SUPPORTED CONVERSION SPECIFIERS AND DATA TYPES * * This snprintf only supports the following conversion specifiers: * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) * with flags: '-', '+', ' ', '0' and '#'. * An asterisk is supported for field width as well as precision. * * Length modifiers 'h' (short int), 'l' (long int), * and 'll' (long long int) are supported. * NOTE: * If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the * length modifier 'll' is recognized but treated the same as 'l', * which may cause argument value truncation! Defining * SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also * handles length modifier 'll'. long long int is a language extension * which may not be portable. * * Conversion of numeric data (conversion specifiers d, u, o, x, X, p) * with length modifiers (none or h, l, ll) is left to the system routine * sprintf, but all handling of flags, field width and precision as well as * c and s conversions is done very carefully by this portable routine. * If a string precision (truncation) is specified (e.g. %.8s) it is * guaranteed the string beyond the specified precision will not be referenced. * * Length modifiers h, l and ll are ignored for c and s conversions (data * types wint_t and wchar_t are not supported). * * The following common synonyms for conversion characters are supported: * - i is a synonym for d * - D is a synonym for ld, explicit length modifiers are ignored * - U is a synonym for lu, explicit length modifiers are ignored * - O is a synonym for lo, explicit length modifiers are ignored * The D, O and U conversion characters are nonstandard, they are supported * for backward compatibility only, and should not be used for new code. * * The following is specifically NOT supported: * - flag ' (thousands' grouping character) is recognized but ignored * - numeric conversion specifiers: f, e, E, g, G and synonym F, * as well as the new a and A conversion specifiers * - length modifier 'L' (long double) and 'q' (quad - use 'll' instead) * - wide character/string conversions: lc, ls, and nonstandard * synonyms C and S * - writeback of converted string length: conversion character n * - the n$ specification for direct reference to n-th argument * - locales * * It is permitted for str_m to be zero, and it is permitted to specify NULL * pointer for resulting string argument if str_m is zero (as per ISO C99). * * The return value is the number of characters which would be generated * for the given input, excluding the trailing null. If this value * is greater or equal to str_m, not all characters from the result * have been stored in str, output bytes beyond the (str_m-1) -th character * are discarded. If str_m is greater than zero it is guaranteed * the resulting string will be null-terminated. * * NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1, * but is different from some older and vendor implementations, * and is also different from XPG, XSH5, SUSv2 specifications. * For historical discussion on changes in the semantics and standards * of snprintf see printf(3) man page in the Linux programmers manual. * * Routines asprintf and vasprintf return a pointer (in the ptr argument) * to a buffer sufficiently large to hold the resulting string. This pointer * should be passed to free(3) to release the allocated storage when it is * no longer needed. If sufficient space cannot be allocated, these functions * will return -1 and set ptr to be a NULL pointer. These two routines are a * GNU C library extensions (glibc). * * Routines asnprintf and vasnprintf are similar to asprintf and vasprintf, * yet, like snprintf and vsnprintf counterparts, will write at most str_m-1 * characters into the allocated output string, the last character in the * allocated buffer then gets the terminating null. If the formatted string * length (the return value) is greater than or equal to the str_m argument, * the resulting string was truncated and some of the formatted characters * were discarded. These routines present a handy way to limit the amount * of allocated memory to some sane value. * * AVAILABILITY * http://www.ijs.si/software/snprintf/ * * REVISION HISTORY * 1999-04 V0.9 Mark Martinec * - initial version, some modifications after comparing printf * man pages for Digital Unix 4.0, Solaris 2.6 and HPUX 10, * and checking how Perl handles sprintf (differently!); * 1999-04-09 V1.0 Mark Martinec * - added main test program, fixed remaining inconsistencies, * added optional (long long int) support; * 1999-04-12 V1.1 Mark Martinec * - support the 'p' conversion (pointer to void); * - if a string precision is specified * make sure the string beyond the specified precision * will not be referenced (e.g. by strlen); * 1999-04-13 V1.2 Mark Martinec * - support synonyms %D=%ld, %U=%lu, %O=%lo; * - speed up the case of long format string with few conversions; * 1999-06-30 V1.3 Mark Martinec * - fixed runaway loop (eventually crashing when str_l wraps * beyond 2^31) while copying format string without * conversion specifiers to a buffer that is too short * (thanks to Edwin Young for * spotting the problem); * - added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR) * to snprintf.h * 2000-02-14 V2.0 (never released) Mark Martinec * - relaxed license terms: The Artistic License now applies. * You may still apply the GNU GENERAL PUBLIC LICENSE * as was distributed with previous versions, if you prefer; * - changed REVISION HISTORY dates to use ISO 8601 date format; * - added vsnprintf (patch also independently proposed by * Caolan McNamara 2000-05-04, and Keith M Willenson 2000-06-01) * 2000-06-27 V2.1 Mark Martinec * - removed POSIX check for str_m<1; value 0 for str_m is * allowed by ISO C99 (and GNU C library 2.1) - (pointed out * on 2000-05-04 by Caolan McNamara, caolan@ csn dot ul dot ie). * Besides relaxed license this change in standards adherence * is the main reason to bump up the major version number; * - added nonstandard routines asnprintf, vasnprintf, asprintf, * vasprintf that dynamically allocate storage for the * resulting string; these routines are not compiled by default, * see comments where NEED_V?ASN?PRINTF macros are defined; * - autoconf contributed by Caolan McNamara * 2000-10-06 V2.2 Mark Martinec * - BUG FIX: the %c conversion used a temporary variable * that was no longer in scope when referenced, * possibly causing incorrect resulting character; * - BUG FIX: make precision and minimal field width unsigned * to handle huge values (2^31 <= n < 2^32) correctly; * also be more careful in the use of signed/unsigned/size_t * internal variables - probably more careful than many * vendor implementations, but there may still be a case * where huge values of str_m, precision or minimal field * could cause incorrect behaviour; * - use separate variables for signed/unsigned arguments, * and for short/int, long, and long long argument lengths * to avoid possible incompatibilities on certain * computer architectures. Also use separate variable * arg_sign to hold sign of a numeric argument, * to make code more transparent; * - some fiddling with zero padding and "0x" to make it * Linux compatible; * - systematically use macros fast_memcpy and fast_memset * instead of case-by-case hand optimization; determine some * breakeven string lengths for different architectures; * - terminology change: 'format' -> 'conversion specifier', * 'C9x' -> 'ISO/IEC 9899:1999 ("ISO C99")', * 'alternative form' -> 'alternate form', * 'data type modifier' -> 'length modifier'; * - several comments rephrased and new ones added; * - make compiler not complain about 'credits' defined but * not used; */ #include "../src/conf.h" #ifndef HAVE_SNPRINTF # include "snprintf.h" #endif /* Define HAVE_SNPRINTF if your system already has snprintf and vsnprintf. * * If HAVE_SNPRINTF is defined this module will not produce code for * snprintf and vsnprintf, unless PREFER_PORTABLE_SNPRINTF is defined as well, * causing this portable version of snprintf to be called portable_snprintf * (and portable_vsnprintf). */ /* #define HAVE_SNPRINTF */ /* Define PREFER_PORTABLE_SNPRINTF if your system does have snprintf and * vsnprintf but you would prefer to use the portable routine(s) instead. * In this case the portable routine is declared as portable_snprintf * (and portable_vsnprintf) and a macro 'snprintf' (and 'vsnprintf') * is defined to expand to 'portable_v?snprintf' - see file snprintf.h . * Defining this macro is only useful if HAVE_SNPRINTF is also defined, * but does does no harm if defined nevertheless. */ /* #define PREFER_PORTABLE_SNPRINTF */ /* Define SNPRINTF_LONGLONG_SUPPORT if you want to support * data type (long long int) and length modifier 'll' (e.g. %lld). * If undefined, 'll' is recognized but treated as a single 'l'. * * If the system's sprintf does not handle 'll' * the SNPRINTF_LONGLONG_SUPPORT must not be defined! * * This is off by default as (long long int) is a language extension. */ /* #define SNPRINTF_LONGLONG_SUPPORT */ /* Define NEED_SNPRINTF_ONLY if you only need snprintf, and not vsnprintf. * If NEED_SNPRINTF_ONLY is defined, the snprintf will be defined directly, * otherwise both snprintf and vsnprintf routines will be defined * and snprintf will be a simple wrapper around vsnprintf, at the expense * of an extra procedure call. */ /* #define NEED_SNPRINTF_ONLY */ /* Define NEED_V?ASN?PRINTF macros if you need library extension * routines asprintf, vasprintf, asnprintf, vasnprintf respectively, * and your system library does not provide them. They are all small * wrapper routines around portable_vsnprintf. Defining any of the four * NEED_V?ASN?PRINTF macros automatically turns off NEED_SNPRINTF_ONLY * and turns on PREFER_PORTABLE_SNPRINTF. * * Watch for name conflicts with the system library if these routines * are already present there. * * NOTE: vasprintf and vasnprintf routines need va_copy() from stdarg.h, as * specified by C99, to be able to traverse the same list of arguments twice. * I don't know of any other standard and portable way of achieving the same. * With some versions of gcc you may use __va_copy(). You might even get away * with "ap2 = ap", in this case you must not call va_end(ap2) ! * #define va_copy(ap2,ap) ap2 = ap */ /* #define NEED_ASPRINTF */ /* #define NEED_ASNPRINTF */ /* #define NEED_VASPRINTF */ /* #define NEED_VASNPRINTF */ /* Define the following macros if desired: * SOLARIS_COMPATIBLE, SOLARIS_BUG_COMPATIBLE, * HPUX_COMPATIBLE, HPUX_BUG_COMPATIBLE, LINUX_COMPATIBLE, * DIGITAL_UNIX_COMPATIBLE, DIGITAL_UNIX_BUG_COMPATIBLE, * PERL_COMPATIBLE, PERL_BUG_COMPATIBLE, * * - For portable applications it is best not to rely on peculiarities * of a given implementation so it may be best not to define any * of the macros that select compatibility and to avoid features * that vary among the systems. * * - Selecting compatibility with more than one operating system * is not strictly forbidden but is not recommended. * * - 'x'_BUG_COMPATIBLE implies 'x'_COMPATIBLE . * * - 'x'_COMPATIBLE refers to (and enables) a behaviour that is * documented in a sprintf man page on a given operating system * and actually adhered to by the system's sprintf (but not on * most other operating systems). It may also refer to and enable * a behaviour that is declared 'undefined' or 'implementation specific' * in the man page but a given implementation behaves predictably * in a certain way. * * - 'x'_BUG_COMPATIBLE refers to (and enables) a behaviour of system's sprintf * that contradicts the sprintf man page on the same operating system. * * - I do not claim that the 'x'_COMPATIBLE and 'x'_BUG_COMPATIBLE * conditionals take into account all idiosyncrasies of a particular * implementation, there may be other incompatibilities. */ /* ============================================= */ /* NO USER SERVICABLE PARTS FOLLOWING THIS POINT */ /* ============================================= */ #define PORTABLE_SNPRINTF_VERSION_MAJOR 2 #define PORTABLE_SNPRINTF_VERSION_MINOR 2 #if defined(NEED_ASPRINTF) || defined(NEED_ASNPRINTF) || defined(NEED_VASPRINTF) || defined(NEED_VASNPRINTF) # if defined(NEED_SNPRINTF_ONLY) # undef NEED_SNPRINTF_ONLY # endif # if !defined(PREFER_PORTABLE_SNPRINTF) # define PREFER_PORTABLE_SNPRINTF # endif #endif #if defined(SOLARIS_BUG_COMPATIBLE) && !defined(SOLARIS_COMPATIBLE) #define SOLARIS_COMPATIBLE #endif #if defined(HPUX_BUG_COMPATIBLE) && !defined(HPUX_COMPATIBLE) #define HPUX_COMPATIBLE #endif #if defined(DIGITAL_UNIX_BUG_COMPATIBLE) && !defined(DIGITAL_UNIX_COMPATIBLE) #define DIGITAL_UNIX_COMPATIBLE #endif #if defined(PERL_BUG_COMPATIBLE) && !defined(PERL_COMPATIBLE) #define PERL_COMPATIBLE #endif #if defined(LINUX_BUG_COMPATIBLE) && !defined(LINUX_COMPATIBLE) #define LINUX_COMPATIBLE #endif #include #include #include #include #include #include #include #ifdef isdigit #undef isdigit #endif #define isdigit(c) ((c) >= '0' && (c) <= '9') /* For copying strings longer or equal to 'breakeven_point' * it is more efficient to call memcpy() than to do it inline. * The value depends mostly on the processor architecture, * but also on the compiler and its optimization capabilities. * The value is not critical, some small value greater than zero * will be just fine if you don't care to squeeze every drop * of performance out of the code. * * Small values favor memcpy, large values favor inline code. */ #if defined(__alpha__) || defined(__alpha) # define breakeven_point 2 /* AXP (DEC Alpha) - gcc or cc or egcs */ #endif #if defined(__i386__) || defined(__i386) # define breakeven_point 12 /* Intel Pentium/Linux - gcc 2.96 */ #endif #if defined(__hppa) # define breakeven_point 10 /* HP-PA - gcc */ #endif #if defined(__sparc__) || defined(__sparc) # define breakeven_point 33 /* Sun Sparc 5 - gcc 2.8.1 */ #endif /* some other values of possible interest: */ /* #define breakeven_point 8 */ /* VAX 4000 - vaxc */ /* #define breakeven_point 19 */ /* VAX 4000 - gcc 2.7.0 */ #ifndef breakeven_point # define breakeven_point 6 /* some reasonable one-size-fits-all value */ #endif #define fast_memcpy(d,s,n) \ { register size_t nn = (size_t)(n); \ if (nn >= breakeven_point) memcpy((d), (s), nn); \ else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ register char *dd; register const char *ss; \ for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } } #define fast_memset(d,c,n) \ { register size_t nn = (size_t)(n); \ if (nn >= breakeven_point) memset((d), (int)(c), nn); \ else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ register char *dd; register const int cc=(int)(c); \ for (dd=(d); nn>0; nn--) *dd++ = cc; } } /* prototypes */ #if defined(NEED_ASPRINTF) int asprintf (char **ptr, const char *fmt, /*args*/ ...); #endif #if defined(NEED_VASPRINTF) int vasprintf (char **ptr, const char *fmt, va_list ap); #endif #if defined(NEED_ASNPRINTF) int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...); #endif #if defined(NEED_VASNPRINTF) int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap); #endif #if defined(HAVE_SNPRINTF) /* declare our portable snprintf routine under name portable_snprintf */ /* declare our portable vsnprintf routine under name portable_vsnprintf */ #else /* declare our portable routines under names snprintf and vsnprintf */ #define portable_snprintf snprintf #if !defined(NEED_SNPRINTF_ONLY) #define portable_vsnprintf vsnprintf #endif #endif #if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); #if !defined(NEED_SNPRINTF_ONLY) int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap); #endif #endif /* declarations */ static char credits[] = "\n\ @(#)snprintf.c, v2.2: Mark Martinec, \n\ @(#)snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.\n\ @(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n"; #if defined(NEED_ASPRINTF) int asprintf(char **ptr, const char *fmt, /*args*/ ...) { va_list ap; size_t str_m; int str_l; *ptr = NULL; va_start(ap, fmt); /* measure the required size */ str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap); va_end(ap); assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ *ptr = (char *) malloc(str_m = (size_t)str_l + 1); if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } else { int str_l2; va_start(ap, fmt); str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); va_end(ap); assert(str_l2 == str_l); } return str_l; } #endif #if defined(NEED_VASPRINTF) int vasprintf(char **ptr, const char *fmt, va_list ap) { size_t str_m; int str_l; *ptr = NULL; { va_list ap2; va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/ va_end(ap2); } assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ *ptr = (char *) malloc(str_m = (size_t)str_l + 1); if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } else { int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); assert(str_l2 == str_l); } return str_l; } #endif #if defined(NEED_ASNPRINTF) int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...) { va_list ap; int str_l; *ptr = NULL; va_start(ap, fmt); /* measure the required size */ str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap); va_end(ap); assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */ /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */ if (str_m == 0) { /* not interested in resulting string, just return size */ } else { *ptr = (char *) malloc(str_m); if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } else { int str_l2; va_start(ap, fmt); str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); va_end(ap); assert(str_l2 == str_l); } } return str_l; } #endif #if defined(NEED_VASNPRINTF) int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap) { int str_l; *ptr = NULL; { va_list ap2; va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/ va_end(ap2); } assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */ /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */ if (str_m == 0) { /* not interested in resulting string, just return size */ } else { *ptr = (char *) malloc(str_m); if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } else { int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); assert(str_l2 == str_l); } } return str_l; } #endif /* * If the system does have snprintf and the portable routine is not * specifically required, this module produces no code for snprintf/vsnprintf. */ #if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) #if !defined(NEED_SNPRINTF_ONLY) int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) { va_list ap; int str_l; va_start(ap, fmt); str_l = portable_vsnprintf(str, str_m, fmt, ap); va_end(ap); return str_l; } #endif #if defined(NEED_SNPRINTF_ONLY) int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) { #else int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) { #endif #if defined(NEED_SNPRINTF_ONLY) va_list ap; #endif size_t str_l = 0; const char *p = fmt; /* In contrast with POSIX, the ISO C99 now says * that str can be NULL and str_m can be 0. * This is more useful than the old: if (str_m < 1) return -1; */ #if defined(NEED_SNPRINTF_ONLY) va_start(ap, fmt); #endif if (!p) p = ""; while (*p) { if (*p != '%') { /* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */ /* but the following code achieves better performance for cases * where format string is long and contains few conversions */ const char *q = strchr(p+1,'%'); size_t n = !q ? strlen(p) : (q-p); if (str_l < str_m) { size_t avail = str_m-str_l; fast_memcpy(str+str_l, p, (n>avail?avail:n)); } p += n; str_l += n; } else { const char *starting_p; size_t min_field_width = 0, precision = 0; int zero_padding = 0, precision_specified = 0, justify_left = 0; int alternate_form = 0, force_sign = 0; int space_for_positive = 1; /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored. */ char length_modifier = '\0'; /* allowed values: \0, h, l, L */ char tmp[32];/* temporary buffer for simple numeric->string conversion */ const char *str_arg; /* string address in case of string argument */ size_t str_arg_l; /* natural field width of arg without padding and sign */ unsigned char uchar_arg; /* unsigned char argument value - only defined for c conversion. N.B. standard explicitly states the char argument for the c conversion is unsigned */ size_t number_of_zeros_to_pad = 0; /* number of zeros to be inserted for numeric conversions as required by the precision or minimal field width */ size_t zero_padding_insertion_ind = 0; /* index into tmp where zero padding is to be inserted */ char fmt_spec = '\0'; /* current conversion specifier character */ str_arg = credits;/* just to make compiler happy (defined but not used)*/ str_arg = NULL; starting_p = p; p++; /* skip '%' */ /* parse flags */ while (*p == '0' || *p == '-' || *p == '+' || *p == ' ' || *p == '#' || *p == '\'') { switch (*p) { case '0': zero_padding = 1; break; case '-': justify_left = 1; break; case '+': force_sign = 1; space_for_positive = 0; break; case ' ': force_sign = 1; /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */ #ifdef PERL_COMPATIBLE /* ... but in Perl the last of ' ' and '+' applies */ space_for_positive = 1; #endif break; case '#': alternate_form = 1; break; case '\'': break; } p++; } /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */ /* parse field width */ if (*p == '*') { int j; p++; j = va_arg(ap, int); if (j >= 0) min_field_width = j; else { min_field_width = -j; justify_left = 1; } } else if (isdigit((int)(*p))) { /* size_t could be wider than unsigned int; make sure we treat argument like common implementations do */ unsigned int uj = *p++ - '0'; while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); min_field_width = uj; } /* parse precision */ if (*p == '.') { p++; precision_specified = 1; if (*p == '*') { int j = va_arg(ap, int); p++; if (j >= 0) precision = j; else { precision_specified = 0; precision = 0; /* NOTE: * Solaris 2.6 man page claims that in this case the precision * should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page * claim that this case should be treated as unspecified precision, * which is what we do here. */ } } else if (isdigit((int)(*p))) { /* size_t could be wider than unsigned int; make sure we treat argument like common implementations do */ unsigned int uj = *p++ - '0'; while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); precision = uj; } } /* parse 'h', 'l' and 'll' length modifiers */ if (*p == 'h' || *p == 'l') { length_modifier = *p; p++; if (length_modifier == 'l' && *p == 'l') { /* double l = long long */ #ifdef SNPRINTF_LONGLONG_SUPPORT length_modifier = '2'; /* double l encoded as '2' */ #else length_modifier = 'l'; /* treat it as a single 'l' */ #endif p++; } } fmt_spec = *p; /* common synonyms: */ switch (fmt_spec) { case 'i': fmt_spec = 'd'; break; case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; default: break; } /* get parameter value, do initial processing */ switch (fmt_spec) { case '%': /* % behaves similar to 's' regarding flags and field widths */ case 'c': /* c behaves similar to 's' regarding flags and field widths */ case 's': length_modifier = '\0'; /* wint_t and wchar_t not supported */ /* the result of zero padding flag with non-numeric conversion specifier*/ /* is undefined. Solaris and HPUX 10 does zero padding in this case, */ /* Digital Unix and Linux does not. */ #if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE) zero_padding = 0; /* turn zero padding off for string conversions */ #endif str_arg_l = 1; switch (fmt_spec) { case '%': str_arg = p; break; case 'c': { int j = va_arg(ap, int); uchar_arg = (unsigned char) j; /* standard demands unsigned char */ str_arg = (const char *) &uchar_arg; break; } case 's': str_arg = va_arg(ap, const char *); if (!str_arg) str_arg_l = 0; /* make sure not to address string beyond the specified precision !!! */ else if (!precision_specified) str_arg_l = strlen(str_arg); /* truncate string if necessary as requested by precision */ else if (precision == 0) str_arg_l = 0; else { /* memchr on HP does not like n > 2^31 !!! */ const char *q = memchr(str_arg, '\0', precision <= 0x7fffffff ? precision : 0x7fffffff); str_arg_l = !q ? precision : (q-str_arg); } break; default: break; } break; case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': { /* NOTE: the u, o, x, X and p conversion specifiers imply the value is unsigned; d implies a signed value */ int arg_sign = 0; /* 0 if numeric argument is zero (or if pointer is NULL for 'p'), +1 if greater than zero (or nonzero for unsigned arguments), -1 if negative (unsigned argument is never negative) */ int int_arg = 0; unsigned int uint_arg = 0; /* only defined for length modifier h, or for no length modifiers */ long int long_arg = 0; unsigned long int ulong_arg = 0; /* only defined for length modifier l */ void *ptr_arg = NULL; /* pointer argument value -only defined for p conversion */ #ifdef SNPRINTF_LONGLONG_SUPPORT long long int long_long_arg = 0; unsigned long long int ulong_long_arg = 0; /* only defined for length modifier ll */ #endif if (fmt_spec == 'p') { /* HPUX 10: An l, h, ll or L before any other conversion character * (other than d, i, u, o, x, or X) is ignored. * Digital Unix: * not specified, but seems to behave as HPUX does. * Solaris: If an h, l, or L appears before any other conversion * specifier (other than d, i, u, o, x, or X), the behavior * is undefined. (Actually %hp converts only 16-bits of address * and %llp treats address as 64-bit data which is incompatible * with (void *) argument on a 32-bit system). */ #ifdef SOLARIS_COMPATIBLE # ifdef SOLARIS_BUG_COMPATIBLE /* keep length modifiers even if it represents 'll' */ # else if (length_modifier == '2') length_modifier = '\0'; # endif #else length_modifier = '\0'; #endif ptr_arg = va_arg(ap, void *); if (ptr_arg != NULL) arg_sign = 1; } else if (fmt_spec == 'd') { /* signed */ switch (length_modifier) { case '\0': case 'h': /* It is non-portable to specify a second argument of char or short * to va_arg, because arguments seen by the called function * are not char or short. C converts char and short arguments * to int before passing them to a function. */ int_arg = va_arg(ap, int); if (int_arg > 0) arg_sign = 1; else if (int_arg < 0) arg_sign = -1; break; case 'l': long_arg = va_arg(ap, long int); if (long_arg > 0) arg_sign = 1; else if (long_arg < 0) arg_sign = -1; break; #ifdef SNPRINTF_LONGLONG_SUPPORT case '2': long_long_arg = va_arg(ap, long long int); if (long_long_arg > 0) arg_sign = 1; else if (long_long_arg < 0) arg_sign = -1; break; #endif } } else { /* unsigned */ switch (length_modifier) { case '\0': case 'h': uint_arg = va_arg(ap, unsigned int); if (uint_arg) arg_sign = 1; break; case 'l': ulong_arg = va_arg(ap, unsigned long int); if (ulong_arg) arg_sign = 1; break; #ifdef SNPRINTF_LONGLONG_SUPPORT case '2': ulong_long_arg = va_arg(ap, unsigned long long int); if (ulong_long_arg) arg_sign = 1; break; #endif } } str_arg = tmp; str_arg_l = 0; /* NOTE: * For d, i, u, o, x, and X conversions, if precision is specified, * the '0' flag should be ignored. This is so with Solaris 2.6, * Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. */ #ifndef PERL_COMPATIBLE if (precision_specified) zero_padding = 0; #endif if (fmt_spec == 'd') { if (force_sign && arg_sign >= 0) tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; /* leave negative numbers for sprintf to handle, to avoid handling tricky cases like (short int)(-32768) */ #ifdef LINUX_COMPATIBLE } else if (fmt_spec == 'p' && force_sign && arg_sign > 0) { tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; #endif } else if (alternate_form) { if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') ) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; } /* alternate form should have no effect for p conversion, but ... */ #ifdef HPUX_COMPATIBLE else if (fmt_spec == 'p' /* HPUX 10: for an alternate form of p conversion, * a nonzero result is prefixed by 0x. */ #ifndef HPUX_BUG_COMPATIBLE /* Actually it uses 0x prefix even for a zero value. */ && arg_sign != 0 #endif ) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; } #endif } zero_padding_insertion_ind = str_arg_l; if (!precision_specified) precision = 1; /* default precision is 1 */ if (precision == 0 && arg_sign == 0 #if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE) && fmt_spec != 'p' /* HPUX 10 man page claims: With conversion character p the result of * converting a zero value with a precision of zero is a null string. * Actually HP returns all zeroes, and Linux returns "(nil)". */ #endif ) { /* converted to null string */ /* When zero value is formatted with an explicit precision 0, the resulting formatted string is empty (d, i, u, o, x, X, p). */ } else { char f[5]; int f_l = 0; f[f_l++] = '%'; /* construct a simple format string for sprintf */ if (!length_modifier) { } else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; } else f[f_l++] = length_modifier; f[f_l++] = fmt_spec; f[f_l++] = '\0'; if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg); else if (fmt_spec == 'd') { /* signed */ switch (length_modifier) { case '\0': case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break; case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break; #ifdef SNPRINTF_LONGLONG_SUPPORT case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break; #endif } } else { /* unsigned */ switch (length_modifier) { case '\0': case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break; case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break; #ifdef SNPRINTF_LONGLONG_SUPPORT case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break; #endif } } /* include the optional minus sign and possible "0x" in the region before the zero padding insertion point */ if (zero_padding_insertion_ind < str_arg_l && tmp[zero_padding_insertion_ind] == '-') { zero_padding_insertion_ind++; } if (zero_padding_insertion_ind+1 < str_arg_l && tmp[zero_padding_insertion_ind] == '0' && (tmp[zero_padding_insertion_ind+1] == 'x' || tmp[zero_padding_insertion_ind+1] == 'X') ) { zero_padding_insertion_ind += 2; } } { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; if (alternate_form && fmt_spec == 'o' #ifdef HPUX_COMPATIBLE /* ("%#.o",0) -> "" */ && (str_arg_l > 0) #endif #ifdef DIGITAL_UNIX_BUG_COMPATIBLE /* ("%#o",0) -> "00" */ #else /* unless zero is already the first character */ && !(zero_padding_insertion_ind < str_arg_l && tmp[zero_padding_insertion_ind] == '0') #endif ) { /* assure leading zero for alternate-form octal numbers */ if (!precision_specified || precision < num_of_digits+1) { /* precision is increased to force the first character to be zero, except if a zero value is formatted with an explicit precision of zero */ precision = num_of_digits+1; precision_specified = 1; } } /* zero padding to specified precision? */ if (num_of_digits < precision) number_of_zeros_to_pad = precision - num_of_digits; } /* zero padding to specified minimal field width? */ if (!justify_left && zero_padding) { int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); if (n > 0) number_of_zeros_to_pad += n; } break; } default: /* unrecognized conversion specifier, keep format string as-is*/ zero_padding = 0; /* turn zero padding off for non-numeric convers. */ #ifndef DIGITAL_UNIX_COMPATIBLE justify_left = 1; min_field_width = 0; /* reset flags */ #endif #if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE) /* keep the entire format string unchanged */ str_arg = starting_p; str_arg_l = p - starting_p; /* well, not exactly so for Linux, which does something inbetween, * and I don't feel an urge to imitate it: "%+++++hy" -> "%+y" */ #else /* discard the unrecognized conversion, just keep * * the unrecognized conversion character */ str_arg = p; str_arg_l = 0; #endif if (*p) str_arg_l++; /* include invalid conversion specifier unchanged if not at end-of-string */ break; } if (*p) p++; /* step over the just processed conversion specifier */ /* insert padding to the left as requested by min_field_width; this does not include the zero padding in case of numerical conversions*/ if (!justify_left) { /* left padding with blank or zero */ int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); if (n > 0) { if (str_l < str_m) { size_t avail = str_m-str_l; fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n)); } str_l += n; } } /* zero padding as requested by the precision or by the minimal field width * for numeric conversions required? */ if (number_of_zeros_to_pad <= 0) { /* will not copy first part of numeric right now, * * force it to be copied later in its entirety */ zero_padding_insertion_ind = 0; } else { /* insert first part of numerics (sign or '0x') before zero padding */ int n = zero_padding_insertion_ind; if (n > 0) { if (str_l < str_m) { size_t avail = str_m-str_l; fast_memcpy(str+str_l, str_arg, (n>avail?avail:n)); } str_l += n; } /* insert zero padding as requested by the precision or min field width */ n = number_of_zeros_to_pad; if (n > 0) { if (str_l < str_m) { size_t avail = str_m-str_l; fast_memset(str+str_l, '0', (n>avail?avail:n)); } str_l += n; } } /* insert formatted string * (or as-is conversion specifier for unknown conversions) */ { int n = str_arg_l - zero_padding_insertion_ind; if (n > 0) { if (str_l < str_m) { size_t avail = str_m-str_l; fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind, (n>avail?avail:n)); } str_l += n; } } /* insert right padding */ if (justify_left) { /* right blank padding to the field width */ int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); if (n > 0) { if (str_l < str_m) { size_t avail = str_m-str_l; fast_memset(str+str_l, ' ', (n>avail?avail:n)); } str_l += n; } } } } #if defined(NEED_SNPRINTF_ONLY) va_end(ap); #endif if (str_m > 0) { /* make sure the string is null-terminated even at the expense of overwriting the last character (shouldn't happen, but just in case) */ str[str_l <= str_m-1 ? str_l : str_m-1] = '\0'; } /* Return the number of characters formatted (excluding trailing null * character), that is, the number of characters that would have been * written to the buffer if it were large enough. * * The value of str_l should be returned, but str_l is of unsigned type * size_t, and snprintf is int, possibly leading to an undetected * integer overflow, resulting in a negative return value, which is illegal. * Both XSH5 and ISO C99 (at least the draft) are silent on this issue. * Should errno be set to EOVERFLOW and EOF returned in this case??? */ return (int) str_l; } #endif cfengine-2.2.10/pub/getloadavg.c0000644000175000001440000006241110245021410013327 00000000000000/* Get the system load averages. Copyright (C) 1985, 86, 87, 88, 89, 91, 92, 93, 1994, 1995, 1997 Free Software Foundation, Inc. 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, 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. */ /* Compile-time symbols that this file uses: HAVE_PSTAT_GETDYNAMIC Define this if your system has the pstat_getdynamic function. I think it is unique to HPUX9. The best way to get the definition is through the AC_FUNC_GETLOADAVG macro that comes with autoconf 2.13 or newer. If that isn't an option, then just put AC_CHECK_FUNCS(pstat_getdynamic) in your configure.in file. FIXUP_KERNEL_SYMBOL_ADDR() Adjust address in returned struct nlist. KERNEL_FILE Pathname of the kernel to nlist. LDAV_CVT() Scale the load average from the kernel. Returns a double. LDAV_SYMBOL Name of kernel symbol giving load average. LOAD_AVE_TYPE Type of the load average array in the kernel. Must be defined unless one of apollo, DGUX, NeXT, or UMAX is defined; or we have libkstat; otherwise, no load average is available. NLIST_STRUCT Include nlist.h, not a.out.h, and the nlist n_name element is a pointer, not an array. NLIST_NAME_UNION struct nlist has an n_un member, not n_name. LINUX_LDAV_FILE [__linux__]: File containing load averages. Specific system predefines this file uses, aside from setting default values if not emacs: apollo BSD Real BSD, not just BSD-like. convex DGUX eunice UNIX emulator under VMS. hpux __MSDOS__ No-op for MSDOS. NeXT sgi sequent Sequent Dynix 3.x.x (BSD) _SEQUENT_ Sequent DYNIX/ptx 1.x.x (SYSV) sony_news NEWS-OS (works at least for 4.1C) UMAX UMAX4_3 VMS WINDOWS32 No-op for Windows95/NT. __linux__ Linux: assumes /proc filesystem mounted. Support from Michael K. Johnson. __NetBSD__ NetBSD: assumes /kern filesystem mounted. In addition, to avoid nesting many #ifdefs, we internally set LDAV_DONE to indicate that the load average has been computed. We also #define LDAV_PRIVILEGED if a program will require special installation to be able to call getloadavg. */ /* This should always be first. */ #include "../src/conf.h" #ifdef HAVE_NLIST_H /* What autoconf defines. */ # undef NLIST_STRUCT # define NLIST_STRUCT #endif #include /* Both the Emacs and non-Emacs sections want this. Some configuration files' definitions for the LOAD_AVE_CVT macro (like sparc.h's) use macros like FSCALE, defined here. */ #if defined (unix) || defined (__unix) # include #endif /* Exclude all the code except the test program at the end if the system has its own `getloadavg' function. The declaration of `errno' is needed by the test program as well as the function itself, so it comes first. */ #include #ifndef errno extern int errno; #endif #ifndef HAVE_GETLOADAVG /* The existing Emacs configuration files define a macro called LOAD_AVE_CVT, which accepts a value of type LOAD_AVE_TYPE, and returns the load average multiplied by 100. What we actually want is a macro called LDAV_CVT, which returns the load average as an unmultiplied double. For backwards compatibility, we'll define LDAV_CVT in terms of LOAD_AVE_CVT, but future machine config files should just define LDAV_CVT directly. */ # if !defined(LDAV_CVT) && defined(LOAD_AVE_CVT) # define LDAV_CVT(n) (LOAD_AVE_CVT (n) / 100.0) # endif # if !defined (BSD) && defined (ultrix) /* Ultrix behaves like BSD on Vaxen. */ # define BSD # endif # ifdef NeXT /* NeXT in the 2.{0,1,2} releases defines BSD in , which conflicts with the definition understood in this file, that this really is BSD. */ # undef BSD /* NeXT defines FSCALE in . However, we take FSCALE being defined to mean that the nlist method should be used, which is not true. */ # undef FSCALE # endif /* Same issues as for NeXT apply to the HURD-based GNU system. */ # ifdef __GNU__ # undef BSD # undef FSCALE # endif /* __GNU__ */ /* Set values that are different from the defaults, which are set a little farther down with #ifndef. */ /* Some shorthands. */ # if defined (HPUX) && !defined (hpux) # define hpux # endif # if defined (__hpux) && !defined (hpux) # define hpux # endif # if defined (__sun) && !defined (sun) # define sun # endif # if defined(hp300) && !defined(hpux) # define MORE_BSD # endif # if defined(ultrix) && defined(mips) # define decstation # endif # if defined (__SVR4) && !defined (SVR4) # define SVR4 # endif # if (defined(sun) && defined(SVR4)) || defined (SOLARIS2) # define SUNOS_5 # endif # if defined (__osf__) && (defined (__alpha) || defined (__alpha__)) # define OSF_ALPHA # include # include # include # include # endif # if defined (__osf__) && (defined (mips) || defined (__mips__)) # define OSF_MIPS # include # endif /* UTek's /bin/cc on the 4300 has no architecture specific cpp define by default, but _MACH_IND_SYS_TYPES is defined in . Combine that with a couple of other things and we'll have a unique match. */ # if !defined (tek4300) && defined (unix) && defined (m68k) && defined (mc68000) && defined (mc68020) && defined (_MACH_IND_SYS_TYPES) # define tek4300 /* Define by emacs, but not by other users. */ # endif /* VAX C can't handle multi-line #ifs, or lines longer than 256 chars. */ # ifndef LOAD_AVE_TYPE # ifdef MORE_BSD # define LOAD_AVE_TYPE long # endif # ifdef sun # define LOAD_AVE_TYPE long # endif # ifdef decstation # define LOAD_AVE_TYPE long # endif # ifdef _SEQUENT_ # define LOAD_AVE_TYPE long # endif # ifdef sgi # define LOAD_AVE_TYPE long # endif # ifdef SVR4 # define LOAD_AVE_TYPE long # endif # ifdef sony_news # define LOAD_AVE_TYPE long # endif # ifdef sequent # define LOAD_AVE_TYPE long # endif # ifdef OSF_ALPHA # define LOAD_AVE_TYPE long # endif # if defined (ardent) && defined (titan) # define LOAD_AVE_TYPE long # endif # ifdef tek4300 # define LOAD_AVE_TYPE long # endif # if defined(alliant) && defined(i860) /* Alliant FX/2800 */ # define LOAD_AVE_TYPE long # endif # ifdef _AIX # define LOAD_AVE_TYPE long # endif # ifdef convex # define LOAD_AVE_TYPE double # ifndef LDAV_CVT # define LDAV_CVT(n) (n) # endif # endif # endif /* No LOAD_AVE_TYPE. */ # ifdef OSF_ALPHA /* defines an incorrect value for FSCALE on Alpha OSF/1, according to ghazi@noc.rutgers.edu. */ # undef FSCALE # define FSCALE 1024.0 # endif # if defined(alliant) && defined(i860) /* Alliant FX/2800 */ /* defines an incorrect value for FSCALE on an Alliant FX/2800 Concentrix 2.2, according to ghazi@noc.rutgers.edu. */ # undef FSCALE # define FSCALE 100.0 # endif # ifndef FSCALE /* SunOS and some others define FSCALE in sys/param.h. */ # ifdef MORE_BSD # define FSCALE 2048.0 # endif # if defined(MIPS) || defined(SVR4) || defined(decstation) # define FSCALE 256 # endif # if defined (sgi) || defined (sequent) /* Sometimes both MIPS and sgi are defined, so FSCALE was just defined above under #ifdef MIPS. But we want the sgi value. */ # undef FSCALE # define FSCALE 1000.0 # endif # if defined (ardent) && defined (titan) # define FSCALE 65536.0 # endif # ifdef tek4300 # define FSCALE 100.0 # endif # ifdef _AIX # define FSCALE 65536.0 # endif # endif /* Not FSCALE. */ # if !defined (LDAV_CVT) && defined (FSCALE) # define LDAV_CVT(n) (((double) (n)) / FSCALE) # endif # if defined(sgi) || (defined(mips) && !defined(BSD)) # define FIXUP_KERNEL_SYMBOL_ADDR(nl) ((nl)[0].n_value &= ~(1 << 31)) # endif # if !defined (KERNEL_FILE) && defined (sequent) # define KERNEL_FILE "/dynix" # endif # if !defined (KERNEL_FILE) && defined (hpux) # define KERNEL_FILE "/hp-ux" # endif # if !defined(KERNEL_FILE) && (defined(_SEQUENT_) || defined(MIPS) || defined(SVR4) || defined(ISC) || defined (sgi) || (defined (ardent) && defined (titan))) # define KERNEL_FILE "/unix" # endif # if !defined (LDAV_SYMBOL) && defined (alliant) # define LDAV_SYMBOL "_Loadavg" # endif # if !defined(LDAV_SYMBOL) && ((defined(hpux) && !defined(hp9000s300)) || defined(_SEQUENT_) || defined(SVR4) || defined(ISC) || defined(sgi) || (defined (ardent) && defined (titan)) || defined (_AIX)) # define LDAV_SYMBOL "avenrun" # endif # ifdef HAVE_UNISTD_H # include # endif # include /* LOAD_AVE_TYPE should only get defined if we're going to use the nlist method. */ # if !defined(LOAD_AVE_TYPE) && (defined(BSD) || defined(LDAV_CVT) || defined(KERNEL_FILE) || defined(LDAV_SYMBOL)) # define LOAD_AVE_TYPE double # endif # ifdef LOAD_AVE_TYPE # ifndef VMS # ifndef __linux__ # ifndef NLIST_STRUCT # include # else /* NLIST_STRUCT */ # include # endif /* NLIST_STRUCT */ # ifdef SUNOS_5 # include //# include # include # endif # if defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) # include # endif # ifndef KERNEL_FILE # define KERNEL_FILE "/vmunix" # endif /* KERNEL_FILE */ # ifndef LDAV_SYMBOL # define LDAV_SYMBOL "_avenrun" # endif /* LDAV_SYMBOL */ # endif /* __linux__ */ # else /* VMS */ # ifndef eunice # include # include # else /* eunice */ # include # endif /* eunice */ # endif /* VMS */ # ifndef LDAV_CVT # define LDAV_CVT(n) ((double) (n)) # endif /* !LDAV_CVT */ # endif /* LOAD_AVE_TYPE */ # if defined(__GNU__) && !defined (NeXT) /* Note that NeXT Openstep defines __GNU__ even though it should not. */ /* GNU system acts much like NeXT, for load average purposes, but not exactly. */ # define NeXT # define host_self mach_host_self # endif # ifdef NeXT # ifdef HAVE_MACH_MACH_H # include # else # include # endif # endif /* NeXT */ # ifdef sgi # include # endif /* sgi */ # ifdef UMAX # include # include # include # include # include # ifdef UMAX_43 # include # include # include # include # include # else /* Not UMAX_43. */ # include # include # include # include # include # include # endif /* Not UMAX_43. */ # endif /* UMAX */ # ifdef DGUX # include # endif # if defined(HAVE_FCNTL_H) || defined(_POSIX_VERSION) # include # else # include # endif /* Avoid static vars inside a function since in HPUX they dump as pure. */ # ifdef NeXT static processor_set_t default_set; static int getloadavg_initialized; # endif /* NeXT */ # ifdef UMAX static unsigned int cpus = 0; static unsigned int samples; # endif /* UMAX */ # ifdef DGUX static struct dg_sys_info_load_info load_info; /* what-a-mouthful! */ # endif /* DGUX */ #if !defined(HAVE_LIBKSTAT) && defined(LOAD_AVE_TYPE) /* File descriptor open to /dev/kmem or VMS load ave driver. */ static int channel; /* Nonzero iff channel is valid. */ static int getloadavg_initialized; /* Offset in kmem to seek to read load average, or 0 means invalid. */ static long offset; #if !defined(VMS) && !defined(sgi) && !defined(__linux__) static struct nlist nl[2]; #endif /* Not VMS or sgi */ #ifdef SUNOS_5 static kvm_t *kd; #endif /* SUNOS_5 */ #endif /* LOAD_AVE_TYPE && !HAVE_LIBKSTAT */ /* Put the 1 minute, 5 minute and 15 minute load averages into the first NELEM elements of LOADAVG. Return the number written (never more than 3, but may be less than NELEM), or -1 if an error occurred. */ int getloadavg (loadavg, nelem) double loadavg[]; int nelem; { int elem = 0; /* Return value. */ # ifdef NO_GET_LOAD_AVG # define LDAV_DONE /* Set errno to zero to indicate that there was no particular error; this function just can't work at all on this system. */ errno = 0; elem = -1; # endif # if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT) /* Use libkstat because we don't have to be root. */ # define LDAV_DONE kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *kn; kc = kstat_open (); if (kc == 0) return -1; ksp = kstat_lookup (kc, "unix", 0, "system_misc"); if (ksp == 0 ) return -1; if (kstat_read (kc, ksp, 0) == -1) return -1; kn = kstat_data_lookup (ksp, "avenrun_1min"); if (kn == 0) { /* Return -1 if no load average information is available. */ nelem = 0; elem = -1; } if (nelem >= 1) loadavg[elem++] = (double) kn->value.ul/FSCALE; if (nelem >= 2) { kn = kstat_data_lookup (ksp, "avenrun_5min"); if (kn != 0) { loadavg[elem++] = (double) kn->value.ul/FSCALE; if (nelem >= 3) { kn = kstat_data_lookup (ksp, "avenrun_15min"); if (kn != 0) loadavg[elem++] = (double) kn->value.ul/FSCALE; } } } kstat_close (kc); # endif /* HAVE_LIBKSTAT */ # if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC) /* Use pstat_getdynamic() because we don't have to be root. */ # define LDAV_DONE # undef LOAD_AVE_TYPE struct pst_dynamic dyn_info; if (pstat_getdynamic (&dyn_info, sizeof (dyn_info), 0, 0) < 0) return -1; if (nelem > 0) loadavg[elem++] = dyn_info.psd_avg_1_min; if (nelem > 1) loadavg[elem++] = dyn_info.psd_avg_5_min; if (nelem > 2) loadavg[elem++] = dyn_info.psd_avg_15_min; # endif /* hpux && HAVE_PSTAT_GETDYNAMIC */ # if !defined (LDAV_DONE) && defined (__linux__) # define LDAV_DONE # undef LOAD_AVE_TYPE # ifndef LINUX_LDAV_FILE # define LINUX_LDAV_FILE "/proc/loadavg" # endif char ldavgbuf[40]; double load_ave[3]; int fd, count; fd = open (LINUX_LDAV_FILE, O_RDONLY); if (fd == -1) return -1; count = read (fd, ldavgbuf, 40); (void) close (fd); if (count <= 0) return -1; count = sscanf (ldavgbuf, "%lf %lf %lf", &load_ave[0], &load_ave[1], &load_ave[2]); if (count < 1) return -1; for (elem = 0; elem < nelem && elem < count; elem++) loadavg[elem] = load_ave[elem]; return elem; # endif /* __linux__ */ # if !defined (LDAV_DONE) && defined (__NetBSD__) # define LDAV_DONE # undef LOAD_AVE_TYPE # ifndef NETBSD_LDAV_FILE # define NETBSD_LDAV_FILE "/kern/loadavg" # endif unsigned long int load_ave[3], scale; int count; FILE *fp; fp = fopen (NETBSD_LDAV_FILE, "r"); if (fp == NULL) return -1; count = fscanf (fp, "%lu %lu %lu %lu\n", &load_ave[0], &load_ave[1], &load_ave[2], &scale); (void) fclose (fp); if (count != 4) return -1; for (elem = 0; elem < nelem; elem++) loadavg[elem] = (double) load_ave[elem] / (double) scale; return elem; # endif /* __NetBSD__ */ # if !defined (LDAV_DONE) && defined (NeXT) # define LDAV_DONE /* The NeXT code was adapted from iscreen 3.2. */ host_t host; struct processor_set_basic_info info; unsigned info_count; /* We only know how to get the 1-minute average for this system, so even if the caller asks for more than 1, we only return 1. */ if (!getloadavg_initialized) { if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS) getloadavg_initialized = 1; } if (getloadavg_initialized) { info_count = PROCESSOR_SET_BASIC_INFO_COUNT; if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host, (processor_set_info_t) &info, &info_count) != KERN_SUCCESS) getloadavg_initialized = 0; else { if (nelem > 0) loadavg[elem++] = (double) info.load_average / LOAD_SCALE; } } if (!getloadavg_initialized) return -1; # endif /* NeXT */ # if !defined (LDAV_DONE) && defined (UMAX) # define LDAV_DONE /* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not have a /dev/kmem. Information about the workings of the running kernel can be gathered with inq_stats system calls. We only know how to get the 1-minute average for this system. */ struct proc_summary proc_sum_data; struct stat_descr proc_info; double load; register unsigned int i, j; if (cpus == 0) { register unsigned int c, i; struct cpu_config conf; struct stat_descr desc; desc.sd_next = 0; desc.sd_subsys = SUBSYS_CPU; desc.sd_type = CPUTYPE_CONFIG; desc.sd_addr = (char *) &conf; desc.sd_size = sizeof conf; if (inq_stats (1, &desc)) return -1; c = 0; for (i = 0; i < conf.config_maxclass; ++i) { struct class_stats stats; bzero ((char *) &stats, sizeof stats); desc.sd_type = CPUTYPE_CLASS; desc.sd_objid = i; desc.sd_addr = (char *) &stats; desc.sd_size = sizeof stats; if (inq_stats (1, &desc)) return -1; c += stats.class_numcpus; } cpus = c; samples = cpus < 2 ? 3 : (2 * cpus / 3); } proc_info.sd_next = 0; proc_info.sd_subsys = SUBSYS_PROC; proc_info.sd_type = PROCTYPE_SUMMARY; proc_info.sd_addr = (char *) &proc_sum_data; proc_info.sd_size = sizeof (struct proc_summary); proc_info.sd_sizeused = 0; if (inq_stats (1, &proc_info) != 0) return -1; load = proc_sum_data.ps_nrunnable; j = 0; for (i = samples - 1; i > 0; --i) { load += proc_sum_data.ps_nrun[j]; if (j++ == PS_NRUNSIZE) j = 0; } if (nelem > 0) loadavg[elem++] = load / samples / cpus; # endif /* UMAX */ # if !defined (LDAV_DONE) && defined (DGUX) # define LDAV_DONE /* This call can return -1 for an error, but with good args it's not supposed to fail. The first argument is for no apparent reason of type `long int *'. */ dg_sys_info ((long int *) &load_info, DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0); if (nelem > 0) loadavg[elem++] = load_info.one_minute; if (nelem > 1) loadavg[elem++] = load_info.five_minute; if (nelem > 2) loadavg[elem++] = load_info.fifteen_minute; # endif /* DGUX */ # if !defined (LDAV_DONE) && defined (apollo) # define LDAV_DONE /* Apollo code from lisch@mentorg.com (Ray Lischner). This system call is not documented. The load average is obtained as three long integers, for the load average over the past minute, five minutes, and fifteen minutes. Each value is a scaled integer, with 16 bits of integer part and 16 bits of fraction part. I'm not sure which operating system first supported this system call, but I know that SR10.2 supports it. */ extern void proc1_$get_loadav (); unsigned long load_ave[3]; proc1_$get_loadav (load_ave); if (nelem > 0) loadavg[elem++] = load_ave[0] / 65536.0; if (nelem > 1) loadavg[elem++] = load_ave[1] / 65536.0; if (nelem > 2) loadavg[elem++] = load_ave[2] / 65536.0; # endif /* apollo */ # if !defined (LDAV_DONE) && defined (OSF_MIPS) # define LDAV_DONE struct tbl_loadavg load_ave; table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave)); loadavg[elem++] = (load_ave.tl_lscale == 0 ? load_ave.tl_avenrun.d[0] : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale)); # endif /* OSF_MIPS */ # if !defined (LDAV_DONE) && (defined (__MSDOS__) || defined (WINDOWS32)) # define LDAV_DONE /* A faithful emulation is going to have to be saved for a rainy day. */ for ( ; elem < nelem; elem++) { loadavg[elem] = 0.0; } # endif /* __MSDOS__ || WINDOWS32 */ # if !defined (LDAV_DONE) && defined (OSF_ALPHA) # define LDAV_DONE struct tbl_loadavg load_ave; table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave)); for (elem = 0; elem < nelem; elem++) loadavg[elem] = (load_ave.tl_lscale == 0 ? load_ave.tl_avenrun.d[elem] : (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale)); # endif /* OSF_ALPHA */ # if !defined (LDAV_DONE) && defined (VMS) /* VMS specific code -- read from the Load Ave driver. */ LOAD_AVE_TYPE load_ave[3]; static int getloadavg_initialized = 0; # ifdef eunice struct { int dsc$w_length; char *dsc$a_pointer; } descriptor; # endif /* Ensure that there is a channel open to the load ave device. */ if (!getloadavg_initialized) { /* Attempt to open the channel. */ # ifdef eunice descriptor.dsc$w_length = 18; descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE"; # else $DESCRIPTOR (descriptor, "LAV0:"); # endif if (sys$assign (&descriptor, &channel, 0, 0) & 1) getloadavg_initialized = 1; } /* Read the load average vector. */ if (getloadavg_initialized && !(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0, load_ave, 12, 0, 0, 0, 0) & 1)) { sys$dassgn (channel); getloadavg_initialized = 0; } if (!getloadavg_initialized) return -1; # endif /* VMS */ # if !defined (LDAV_DONE) && defined(LOAD_AVE_TYPE) && !defined(VMS) /* UNIX-specific code -- read the average from /dev/kmem. */ # define LDAV_PRIVILEGED /* This code requires special installation. */ LOAD_AVE_TYPE load_ave[3]; /* Get the address of LDAV_SYMBOL. */ if (offset == 0) { # ifndef sgi # ifndef NLIST_STRUCT strcpy (nl[0].n_name, LDAV_SYMBOL); strcpy (nl[1].n_name, ""); # else /* NLIST_STRUCT */ # ifdef NLIST_NAME_UNION nl[0].n_un.n_name = LDAV_SYMBOL; nl[1].n_un.n_name = 0; # else /* not NLIST_NAME_UNION */ nl[0].n_name = LDAV_SYMBOL; nl[1].n_name = 0; # endif /* not NLIST_NAME_UNION */ # endif /* NLIST_STRUCT */ # ifndef SUNOS_5 if ( # if !(defined (_AIX) && !defined (ps2)) nlist (KERNEL_FILE, nl) # else /* _AIX */ knlist (nl, 1, sizeof (nl[0])) # endif >= 0) /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i. */ { # ifdef FIXUP_KERNEL_SYMBOL_ADDR FIXUP_KERNEL_SYMBOL_ADDR (nl); # endif offset = nl[0].n_value; } # endif /* !SUNOS_5 */ # else /* sgi */ int ldav_off; ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN); if (ldav_off != -1) offset = (long) ldav_off & 0x7fffffff; # endif /* sgi */ } /* Make sure we have /dev/kmem open. */ if (!getloadavg_initialized) { # ifndef SUNOS_5 channel = open ("/dev/kmem", 0); if (channel >= 0) { /* Set the channel to close on exec, so it does not litter any child's descriptor table. */ # ifdef F_SETFD # ifndef FD_CLOEXEC # define FD_CLOEXEC 1 # endif (void) fcntl (channel, F_SETFD, FD_CLOEXEC); # endif getloadavg_initialized = 1; } # else /* SUNOS_5 */ /* We pass 0 for the kernel, corefile, and swapfile names to use the currently running kernel. */ kd = kvm_open (0, 0, 0, O_RDONLY, 0); if (kd != 0) { /* nlist the currently running kernel. */ kvm_nlist (kd, nl); offset = nl[0].n_value; getloadavg_initialized = 1; } # endif /* SUNOS_5 */ } /* If we can, get the load average values. */ if (offset && getloadavg_initialized) { /* Try to read the load. */ # ifndef SUNOS_5 if (lseek (channel, offset, 0) == -1L || read (channel, (char *) load_ave, sizeof (load_ave)) != sizeof (load_ave)) { close (channel); getloadavg_initialized = 0; } # else /* SUNOS_5 */ if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave)) != sizeof (load_ave)) { kvm_close (kd); getloadavg_initialized = 0; } # endif /* SUNOS_5 */ } if (offset == 0 || !getloadavg_initialized) return -1; # endif /* LOAD_AVE_TYPE and not VMS */ # if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS. */ if (nelem > 0) loadavg[elem++] = LDAV_CVT (load_ave[0]); if (nelem > 1) loadavg[elem++] = LDAV_CVT (load_ave[1]); if (nelem > 2) loadavg[elem++] = LDAV_CVT (load_ave[2]); # define LDAV_DONE # endif /* !LDAV_DONE && LOAD_AVE_TYPE */ # ifdef LDAV_DONE return elem; # else /* Set errno to zero to indicate that there was no particular error; this function just can't work at all on this system. */ errno = 0; return -1; # endif } #endif /* ! HAVE_GETLOADAVG */ #ifdef TEST int main (argc, argv) int argc; char **argv; { int naptime = 0; if (argc > 1) naptime = atoi (argv[1]); while (1) { double avg[3]; int loads; errno = 0; /* Don't be misled if it doesn't set errno. */ loads = getloadavg (avg, 3); if (loads == -1) { perror ("Error getting load average"); exit (1); } if (loads > 0) printf ("1-minute: %f ", avg[0]); if (loads > 1) printf ("5-minute: %f ", avg[1]); if (loads > 2) printf ("15-minute: %f ", avg[2]); if (loads > 0) putchar ('\n'); if (naptime == 0) break; sleep (naptime); } exit (0); } #endif /* TEST */ cfengine-2.2.10/pub/gnuregex.h0000644000175000001440000004451710202123440013051 00000000000000/* Definitions for data structures and routines for the regular expression library, version 0.12. Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __REGEXP_LIBRARY_H__ #define __REGEXP_LIBRARY_H__ /* POSIX says that must be included (by the caller) before . */ #ifdef VMS /* VMS doesn't have `size_t' in , even though POSIX says it should be there. */ #include #endif /* The following bits are used to determine the regexp syntax we recognize. The set/not-set meanings are chosen so that Emacs syntax remains the value 0. The bits are given in alphabetical order, and the definitions shifted by one from the previous bit; thus, when we add or remove a bit, only one other definition need change. */ typedef unsigned reg_syntax_t; /* If this bit is not set, then \ inside a bracket expression is literal. If set, then such a \ quotes the following character. */ #define RE_BACKSLASH_ESCAPE_IN_LISTS (1) /* If this bit is not set, then + and ? are operators, and \+ and \? are literals. If set, then \+ and \? are operators and + and ? are literals. */ #define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) /* If this bit is set, then character classes are supported. They are: [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. If not set, then character classes are not supported. */ #define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) /* If this bit is set, then ^ and $ are always anchors (outside bracket expressions, of course). If this bit is not set, then it depends: ^ is an anchor if it is at the beginning of a regular expression or after an open-group or an alternation operator; $ is an anchor if it is at the end of a regular expression, or before a close-group or an alternation operator. This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because POSIX draft 11.2 says that * etc. in leading positions is undefined. We already implemented a previous draft which made those constructs invalid, though, so we haven't changed the code back. */ #define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) /* If this bit is set, then special characters are always special regardless of where they are in the pattern. If this bit is not set, then special characters are special only in some contexts; otherwise they are ordinary. Specifically, * + ? and intervals are only special when not after the beginning, open-group, or alternation operator. */ #define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) /* If this bit is set, then *, +, ?, and { cannot be first in an re or immediately after an alternation or begin-group operator. */ #define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) /* If this bit is set, then . matches newline. If not set, then it doesn't. */ #define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) /* If this bit is set, then . doesn't match NUL. If not set, then it does. */ #define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) /* If this bit is set, nonmatching lists [^...] do not match newline. If not set, they do. */ #define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) /* If this bit is set, either \{...\} or {...} defines an interval, depending on RE_NO_BK_BRACES. If not set, \{, \}, {, and } are literals. */ #define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) /* If this bit is set, +, ? and | aren't recognized as operators. If not set, they are. */ #define RE_LIMITED_OPS (RE_INTERVALS << 1) /* If this bit is set, newline is an alternation operator. If not set, newline is literal. */ #define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) /* If this bit is set, then `{...}' defines an interval, and \{ and \} are literals. If not set, then `\{...\}' defines an interval. */ #define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) /* If this bit is set, (...) defines a group, and \( and \) are literals. If not set, \(...\) defines a group, and ( and ) are literals. */ #define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) /* If this bit is set, then \ matches . If not set, then \ is a back-reference. */ #define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) /* If this bit is set, then | is an alternation operator, and \| is literal. If not set, then \| is an alternation operator, and | is literal. */ #define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) /* If this bit is set, then an ending range point collating higher than the starting range point, as in [z-a], is invalid. If not set, then when ending range point collates higher than the starting range point, the range is ignored. */ #define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) /* If this bit is set, then an unmatched ) is ordinary. If not set, then an unmatched ) is invalid. */ #define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) /* This global variable defines the particular regexp syntax to use (for some interfaces). When a regexp is compiled, the syntax used is stored in the pattern buffer, so changing this does not affect already-compiled regexps. */ extern reg_syntax_t re_syntax_options; /* Define combinations of the above bits for the standard possibilities. (The [[[ comments delimit what gets put into the Texinfo file, so don't delete them!) */ /* [[[begin syntaxes]]] */ #define RE_SYNTAX_EMACS 0 #define RE_SYNTAX_AWK \ (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ | RE_UNMATCHED_RIGHT_PAREN_ORD) #define RE_SYNTAX_POSIX_AWK \ (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS) #define RE_SYNTAX_GREP \ (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ | RE_NEWLINE_ALT) #define RE_SYNTAX_EGREP \ (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ | RE_NO_BK_VBAR) #define RE_SYNTAX_POSIX_EGREP \ (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES) /* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ #define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC #define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC /* Syntax bits common to both basic and extended POSIX regex syntax. */ #define _RE_SYNTAX_POSIX_COMMON \ (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ | RE_INTERVALS | RE_NO_EMPTY_RANGES) #define RE_SYNTAX_POSIX_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM) /* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this isn't minimal, since other operators, such as \`, aren't disabled. */ #define RE_SYNTAX_POSIX_MINIMAL_BASIC \ (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) #define RE_SYNTAX_POSIX_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ | RE_UNMATCHED_RIGHT_PAREN_ORD) /* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added. */ #define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ | RE_NO_BK_PARENS | RE_NO_BK_REFS \ | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) /* [[[end syntaxes]]] */ /* Maximum number of duplicates an interval can allow. Some systems (erroneously) define this in other header files, but we want our value, so remove any previous define. */ #ifdef RE_DUP_MAX #undef RE_DUP_MAX #endif #define RE_DUP_MAX ((1 << 15) - 1) /* POSIX `cflags' bits (i.e., information for `regcomp'). */ /* If this bit is set, then use extended regular expression syntax. If not set, then use basic regular expression syntax. */ #define REG_EXTENDED 1 /* If this bit is set, then ignore case when matching. If not set, then case is significant. */ #define REG_ICASE (REG_EXTENDED << 1) /* If this bit is set, then anchors do not match at newline characters in the string. If not set, then anchors do match at newlines. */ #define REG_NEWLINE (REG_ICASE << 1) /* If this bit is set, then report only success or fail in regexec. If not set, then returns differ between not matching and errors. */ #define REG_NOSUB (REG_NEWLINE << 1) /* POSIX `eflags' bits (i.e., information for regexec). */ /* If this bit is set, then the beginning-of-line operator doesn't match the beginning of the string (presumably because it's not the beginning of a line). If not set, then the beginning-of-line operator does match the beginning of the string. */ #define REG_NOTBOL 1 /* Like REG_NOTBOL, except for the end-of-line. */ #define REG_NOTEOL (1 << 1) /* If any error codes are removed, changed, or added, update the `re_error_msg' table in regex.c. */ typedef enum { REG_NOERROR = 0, /* Success. */ REG_NOMATCH, /* Didn't find a match (for regexec). */ /* POSIX regcomp return error codes. (In the order listed in the standard.) */ REG_BADPAT, /* Invalid pattern. */ REG_ECOLLATE, /* Not implemented. */ REG_ECTYPE, /* Invalid character class name. */ REG_EESCAPE, /* Trailing backslash. */ REG_ESUBREG, /* Invalid back reference. */ REG_EBRACK, /* Unmatched left bracket. */ REG_EPAREN, /* Parenthesis imbalance. */ REG_EBRACE, /* Unmatched \{. */ REG_BADBR, /* Invalid contents of \{\}. */ REG_ERANGE, /* Invalid range end. */ REG_ESPACE, /* Ran out of memory. */ REG_BADRPT, /* No preceding re for repetition op. */ /* Error codes we've added. */ REG_EEND, /* Premature end. */ REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ } reg_errcode_t; /* This data structure represents a compiled pattern. Before calling the pattern compiler, the fields `buffer', `allocated', `fastmap', `translate', and `no_sub' can be set. After the pattern has been compiled, the `re_nsub' field is available. All other fields are private to the regex routines. */ struct re_pattern_buffer { /* [[[begin pattern_buffer]]] */ /* Space that holds the compiled pattern. It is declared as `unsigned char *' because its elements are sometimes used as array indexes. */ unsigned char *buffer; /* Number of bytes to which `buffer' points. */ unsigned long allocated; /* Number of bytes actually used in `buffer'. */ unsigned long used; /* Syntax setting with which the pattern was compiled. */ reg_syntax_t syntax; /* Pointer to a fastmap, if any, otherwise zero. re_search uses the fastmap, if there is one, to skip over impossible starting points for matches. */ char *fastmap; /* Either a translate table to apply to all characters before comparing them, or zero for no translation. The translation is applied to a pattern when it is compiled and to a string when it is matched. */ char *translate; /* Number of subexpressions found by the compiler. */ size_t re_nsub; /* Zero if this pattern cannot match the empty string, one else. Well, in truth it's used only in `re_search_2', to see whether or not we should use the fastmap, so we don't set this absolutely perfectly; see `re_compile_fastmap' (the `duplicate' case). */ unsigned can_be_null : 1; /* If REGS_UNALLOCATED, allocate space in the `regs' structure for `max (RE_NREGS, re_nsub + 1)' groups. If REGS_REALLOCATE, reallocate space if necessary. If REGS_FIXED, use what's there. */ #define REGS_UNALLOCATED 0 #define REGS_REALLOCATE 1 #define REGS_FIXED 2 unsigned regs_allocated : 2; /* Set to zero when `regex_compile' compiles a pattern; set to one by `re_compile_fastmap' if it updates the fastmap. */ unsigned fastmap_accurate : 1; /* If set, `re_match_2' does not return information about subexpressions. */ unsigned no_sub : 1; /* If set, a beginning-of-line anchor doesn't match at the beginning of the string. */ unsigned not_bol : 1; /* Similarly for an end-of-line anchor. */ unsigned not_eol : 1; /* If true, an anchor at a newline matches. */ unsigned newline_anchor : 1; /* [[[end pattern_buffer]]] */ }; typedef struct re_pattern_buffer regex_t; /* search.c (search_buffer) in Emacs needs this one opcode value. It is defined both in `regex.c' and here. */ #define RE_EXACTN_VALUE 1 /* Type for byte offsets within the string. POSIX mandates this. */ typedef int regoff_t; /* This is the structure we store register match data in. See regex.texinfo for a full description of what registers match. */ struct re_registers { unsigned num_regs; regoff_t *start; regoff_t *end; }; /* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, `re_match_2' returns information about at least this many registers the first time a `regs' structure is passed. */ #ifndef RE_NREGS #define RE_NREGS 30 #endif /* POSIX specification for registers. Aside from the different names than `re_registers', POSIX uses an array of structures, instead of a structure of arrays. */ typedef struct { regoff_t rm_so; /* Byte offset from string's start to substring's start. */ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ } regmatch_t; /* Declarations for routines. */ /* To avoid duplicating every routine declaration -- once with a prototype (if we are ANSI), and once without (if we aren't) -- we use the following macro to declare argument types. This unfortunately clutters up the declarations a bit, but I think it's worth it. */ #if __STDC__ #define _RE_ARGS(args) args #else /* not __STDC__ */ #define _RE_ARGS(args) () #endif /* not __STDC__ */ /* Sets the current default syntax to SYNTAX, and return the old syntax. You can also simply assign to the `re_syntax_options' variable. */ extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax)); /* Compile the regular expression PATTERN, with length LENGTH and syntax given by the global `re_syntax_options', into the buffer BUFFER. Return NULL if successful, and an error string if not. */ /* Mark: remove const from constchar here */ extern char *re_compile_pattern _RE_ARGS (( char *pattern, int length, struct re_pattern_buffer *buffer)); /* Compile a fastmap for the compiled pattern in BUFFER; used to accelerate searches. Return 0 if successful and -2 if was an internal error. */ extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer)); /* Search in the string STRING (with length LENGTH) for the pattern compiled into BUFFER. Start searching at position START, for RANGE characters. Return the starting position of the match, -1 for no match, or -2 for an internal error. Also return register information in REGS (if REGS and BUFFER->no_sub are nonzero). */ extern int re_search _RE_ARGS ((struct re_pattern_buffer *buffer, char *string, int length, int start, int range, struct re_registers *regs)); /* Like `re_search', but search in the concatenation of STRING1 and STRING2. Also, stop searching at index START + STOP. */ extern int re_search_2 _RE_ARGS ((struct re_pattern_buffer *buffer, char *string1, int length1, char *string2, int length2, int start, int range, struct re_registers *regs, int stop)); /* Like `re_search', but return how many characters in STRING the regexp in BUFFER matched, starting at position START. */ extern int re_match _RE_ARGS ((struct re_pattern_buffer *buffer, char *string, int length, int start, struct re_registers *regs)); /* Relates to `re_match' as `re_search_2' relates to `re_search'. */ extern int re_match_2 _RE_ARGS ((struct re_pattern_buffer *buffer, char *string1, int length1, char *string2, int length2, int start, struct re_registers *regs, int stop)); /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated with malloc, and must each be at least `NUM_REGS * sizeof (regoff_t)' bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ extern void re_set_registers _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs, unsigned num_regs, regoff_t *starts, regoff_t *ends)); /* 4.2 bsd compatibility. */ #if !defined(FREEBSD) && !defined(IRIX) && !defined(NETBSD) && !defined(OPENBSD) extern char *re_comp _RE_ARGS (( char *)); extern int re_exec _RE_ARGS (( char *)); #endif /* POSIX compatibility. */ extern int regcomp _RE_ARGS ((regex_t *preg, char *pattern, int cflags)); extern int regexec _RE_ARGS (( regex_t *preg, char *string, size_t nmatch, regmatch_t pmatch[], int eflags)); extern size_t regerror _RE_ARGS ((int errcode, regex_t *preg, char *errbuf, size_t errbuf_size)); extern void regfree _RE_ARGS ((regex_t *preg)); #endif /* not __REGEXP_LIBRARY_H__ */ /* Local variables: make-backup-files: t version-control: t trim-versions-without-asking: nil End: */ cfengine-2.2.10/pub/full-write.c0000644000175000001440000000306510202123440013303 00000000000000/* full-write.c -- an interface to write that retries after interrupts Copyright (C) 1993, 1994 Free Software Foundation, Inc. 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. Copied largely from GNU C's cccp.c. */ #include "../src/conf.h" #include "../src/cf.defs.h" #include #ifdef HAVE_UNISTD_H #include #endif #include #ifndef STDC_HEADERS extern int errno; #endif /* Write LEN bytes at PTR to descriptor DESC, retrying if interrupted. Return LEN upon success, write's (negative) error code otherwise. */ int cf_full_write (desc,ptr,len) int desc; char *ptr; size_t len; { int total_written; total_written = 0; while (len > 0) { int written = write (desc,ptr,len); if (written < 0) { if (errno == EINTR) { continue; } return written; } total_written += written; ptr += written; len -= written; } return total_written; } cfengine-2.2.10/pub/global.h0000644000175000001440000000153710202123437012466 00000000000000/* GLOBAL.H - RSAREF types and constants */ /* PROTOTYPES should be set to one if and only if the compiler supports function argument prototyping. The following sets PROTOTYPES according to whether or not we are compiling with an ANSI compiler. */ #ifdef __STDC__ # define PROTOTYPES 1 #else # ifdef __cplusplus # define PROTOTYPES 1 # else # define PROTOTYPES 0 # endif #endif /* POINTER defines a generic pointer type */ typedef unsigned char *POINTER; /* UINT2 defines a two byte word */ typedef unsigned short int UINT2; /* UINT4 defines a four byte word */ typedef unsigned long int UINT4; /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it returns an empty list. */ #if PROTOTYPES #define PROTO_LIST(list) list #else #define PROTO_LIST(list) () #endif cfengine-2.2.10/pub/regex.c0000644000175000001440000047350310202123440012333 00000000000000/* Extended regular expression matching and search library, version 0.12. (Implements POSIX draft P10003.2/D11.2, except for internationalization features.) Copyright (C) 1993 Free Software Foundation, Inc. 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* AIX requires this to be the first thing in the file. */ #include "../src/conf.h" #if defined (_AIX) && !defined (REGEX_MALLOC) #pragma alloca #endif #if defined(HAVE_REGEX_H) || defined(HAVE_LIBRX) /* Nothing */ #else #define _GNU_SOURCE #define HAVE_STRING_H 1 #define HAVE_ALLOCA_H 0 /* We need this for `regex.h', and perhaps for the Emacs include files. */ #include #include "gnuregex.h" /* The `emacs' switch turns on certain matching commands that make sense only in Emacs. */ #ifdef emacs #include "lisp.h" #include "buffer.h" #include "syntax.h" /* Emacs uses `NULL' as a predicate. */ #undef NULL #else /* not emacs */ /* We used to test for `BSTRING' here, but only GCC and Emacs define `BSTRING', as far as I know, and neither of them use this code. */ #ifndef bcmp #define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) #endif #ifndef bcopy #define bcopy(s, d, n) memcpy ((d), (s), (n)) #endif #ifndef bzero #define bzero(s, n) memset ((s), 0, (n)) #endif #ifdef STDC_HEADERS #include #else char *malloc (); char *realloc (); #endif /* Define the syntax stuff for \<, \>, etc. */ /* This must be nonzero for the wordchar and notwordchar pattern commands in re_match_2. */ #ifndef Sword #define Sword 1 #endif #ifdef SYNTAX_TABLE extern char *re_syntax_table; #else /* not SYNTAX_TABLE */ /* How many characters in the character set. */ #define CHAR_SET_SIZE 256 static char re_syntax_table[CHAR_SET_SIZE]; static void init_syntax_once () { register int c; static int done = 0; if (done) return; bzero (re_syntax_table, sizeof re_syntax_table); for (c = 'a'; c <= 'z'; c++) re_syntax_table[c] = Sword; for (c = 'A'; c <= 'Z'; c++) re_syntax_table[c] = Sword; for (c = '0'; c <= '9'; c++) re_syntax_table[c] = Sword; re_syntax_table['_'] = Sword; done = 1; } #endif /* not SYNTAX_TABLE */ #define SYNTAX(c) re_syntax_table[c] #endif /* not emacs */ /* Get the interface, including the syntax bits. */ /* #include "regex.h" */ /* isalpha etc. are used for the character classes. */ #include #ifndef isascii #define isascii(c) 1 #endif #ifdef isblank #define ISBLANK(c) (isascii (c) && isblank (c)) #else #define ISBLANK(c) ((c) == ' ' || (c) == '\t') #endif #ifdef isgraph #define ISGRAPH(c) (isascii (c) && isgraph (c)) #else #define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c)) #endif #define ISPRINT(c) (isascii (c) && isprint (c)) #define ISDIGIT(c) (isascii (c) && isdigit (c)) #define ISALNUM(c) (isascii (c) && isalnum (c)) #define ISALPHA(c) (isascii (c) && isalpha (c)) #define ISCNTRL(c) (isascii (c) && iscntrl (c)) #define ISLOWER(c) (isascii (c) && islower (c)) #define ISPUNCT(c) (isascii (c) && ispunct (c)) #define ISSPACE(c) (isascii (c) && isspace (c)) #define ISUPPER(c) (isascii (c) && isupper (c)) #define ISXDIGIT(c) (isascii (c) && isxdigit (c)) #ifndef NULL #define NULL (void *)0 #endif /* We remove any previous definition of `SIGN_EXTEND_CHAR', since ours (we hope) works properly with all combinations of machines, compilers, `char' and `unsigned char' argument types. (Per Bothner suggested the basic approach.) */ #undef SIGN_EXTEND_CHAR #if __STDC__ #define SIGN_EXTEND_CHAR(c) ((signed char) (c)) #else /* not __STDC__ */ /* As in Harbison and Steele. */ #define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) #endif /* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we use `alloca' instead of `malloc'. This is because using malloc in re_search* or re_match* could cause memory leaks when C-g is used in Emacs; also, malloc is slower and causes storage fragmentation. On the other hand, malloc is more portable, and easier to debug. Because we sometimes use alloca, some routines have to be macros, not functions -- `alloca'-allocated space disappears at the end of the function it is called in. */ #ifdef REGEX_MALLOC #define REGEX_ALLOCATE malloc #define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) #else /* not REGEX_MALLOC */ /* Emacs already defines alloca, sometimes. */ #ifndef alloca /* Make alloca work the best possible way. */ #ifdef __GNUC__ #define alloca __builtin_alloca #else /* not __GNUC__ */ #if HAVE_ALLOCA_H #include #else /* not __GNUC__ or HAVE_ALLOCA_H */ #ifndef _AIX /* Already did AIX, up at the top. */ char *alloca (); #endif /* not _AIX */ #endif /* not HAVE_ALLOCA_H */ #endif /* not __GNUC__ */ #endif /* not alloca */ #define REGEX_ALLOCATE alloca /* Assumes a `char *destination' variable. */ #define REGEX_REALLOCATE(source, osize, nsize) \ (destination = (char *) alloca (nsize), \ bcopy (source, destination, osize), \ destination) #endif /* not REGEX_MALLOC */ /* True if `size1' is non-NULL and PTR is pointing anywhere inside `string1' or just past its end. This works if PTR is NULL, which is a good thing. */ #define FIRST_STRING_P(ptr) \ (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) /* (Re)Allocate N items of type T using malloc, or fail. */ #define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) #define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) #define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) #define BYTEWIDTH 8 /* In bits. */ #define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) typedef char boolean; #define false 0 #define true 1 /* These are the command codes that appear in compiled regular expressions. Some opcodes are followed by argument bytes. A command code can specify any interpretation whatsoever for its arguments. Zero bytes may appear in the compiled regular expression. The value of `exactn' is needed in search.c (search_buffer) in Emacs. So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of `exactn' we use here must also be 1. */ typedef enum { no_op = 0, /* Followed by one byte giving n, then by n literal bytes. */ exactn = 1, /* Matches any (more or less) character. */ anychar, /* Matches any one char belonging to specified set. First following byte is number of bitmap bytes. Then come bytes for a bitmap saying which chars are in. Bits in each byte are ordered low-bit-first. A character is in the set if its bit is 1. A character too large to have a bit in the map is automatically not in the set. */ charset, /* Same parameters as charset, but match any character that is not one of those specified. */ charset_not, /* Start remembering the text that is matched, for storing in a register. Followed by one byte with the register number, in the range 0 to one less than the pattern buffer's re_nsub field. Then followed by one byte with the number of groups inner to this one. (This last has to be part of the start_memory only because we need it in the on_failure_jump of re_match_2.) */ start_memory, /* Stop remembering the text that is matched and store it in a memory register. Followed by one byte with the register number, in the range 0 to one less than `re_nsub' in the pattern buffer, and one byte with the number of inner groups, just like `start_memory'. (We need the number of inner groups here because we don't have any easy way of finding the corresponding start_memory when we're at a stop_memory.) */ stop_memory, /* Match a duplicate of something remembered. Followed by one byte containing the register number. */ duplicate, /* Fail unless at beginning of line. */ begline, /* Fail unless at end of line. */ endline, /* Succeeds if at beginning of buffer (if emacs) or at beginning of string to be matched (if not). */ begbuf, /* Analogously, for end of buffer/string. */ endbuf, /* Followed by two byte relative address to which to jump. */ jump, /* Same as jump, but marks the end of an alternative. */ jump_past_alt, /* Followed by two-byte relative address of place to resume at in case of failure. */ on_failure_jump, /* Like on_failure_jump, but pushes a placeholder instead of the current string position when executed. */ on_failure_keep_string_jump, /* Throw away latest failure point and then jump to following two-byte relative address. */ pop_failure_jump, /* Change to pop_failure_jump if know won't have to backtrack to match; otherwise change to jump. This is used to jump back to the beginning of a repeat. If what follows this jump clearly won't match what the repeat does, such that we can be sure that there is no use backtracking out of repetitions already matched, then we change it to a pop_failure_jump. Followed by two-byte address. */ maybe_pop_jump, /* Jump to following two-byte address, and push a dummy failure point. This failure point will be thrown away if an attempt is made to use it for a failure. A `+' construct makes this before the first repeat. Also used as an intermediary kind of jump when compiling an alternative. */ dummy_failure_jump, /* Push a dummy failure point and continue. Used at the end of alternatives. */ push_dummy_failure, /* Followed by two-byte relative address and two-byte number n. After matching N times, jump to the address upon failure. */ succeed_n, /* Followed by two-byte relative address, and two-byte number n. Jump to the address N times, then fail. */ jump_n, /* Set the following two-byte relative address to the subsequent two-byte number. The address *includes* the two bytes of number. */ set_number_at, wordchar, /* Matches any word-constituent character. */ notwordchar, /* Matches any char that is not a word-constituent. */ wordbeg, /* Succeeds if at word beginning. */ wordend, /* Succeeds if at word end. */ wordbound, /* Succeeds if at a word boundary. */ notwordbound /* Succeeds if not at a word boundary. */ #ifdef emacs ,before_dot, /* Succeeds if before point. */ at_dot, /* Succeeds if at point. */ after_dot, /* Succeeds if after point. */ /* Matches any character whose syntax is specified. Followed by a byte which contains a syntax code, e.g., Sword. */ syntaxspec, /* Matches any character whose syntax is not that specified. */ notsyntaxspec #endif /* emacs */ } re_opcode_t; /* Common operations on the compiled pattern. */ /* Store NUMBER in two contiguous bytes starting at DESTINATION. */ #define STORE_NUMBER(destination, number) \ do { \ (destination)[0] = (number) & 0377; \ (destination)[1] = (number) >> 8; \ } while (0) /* Same as STORE_NUMBER, except increment DESTINATION to the byte after where the number is stored. Therefore, DESTINATION must be an lvalue. */ #define STORE_NUMBER_AND_INCR(destination, number) \ do { \ STORE_NUMBER (destination, number); \ (destination) += 2; \ } while (0) /* Put into DESTINATION a number stored in two contiguous bytes starting at SOURCE. */ #define EXTRACT_NUMBER(destination, source) \ do { \ (destination) = *(source) & 0377; \ (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ } while (0) #ifdef DEBUG static void extract_number (dest, source) int *dest; unsigned char *source; { int temp = SIGN_EXTEND_CHAR (*(source + 1)); *dest = *source & 0377; *dest += temp << 8; } #ifndef EXTRACT_MACROS /* To debug the macros. */ #undef EXTRACT_NUMBER #define EXTRACT_NUMBER(dest, src) extract_number (&dest, src) #endif /* not EXTRACT_MACROS */ #endif /* DEBUG */ /* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. SOURCE must be an lvalue. */ #define EXTRACT_NUMBER_AND_INCR(destination, source) \ do { \ EXTRACT_NUMBER (destination, source); \ (source) += 2; \ } while (0) #ifdef DEBUG static void extract_number_and_incr (destination, source) int *destination; unsigned char **source; { extract_number (destination, *source); *source += 2; } #ifndef EXTRACT_MACROS #undef EXTRACT_NUMBER_AND_INCR #define EXTRACT_NUMBER_AND_INCR(dest, src) \ extract_number_and_incr (&dest, &src) #endif /* not EXTRACT_MACROS */ #endif /* DEBUG */ /* If DEBUG is defined, Regex prints many voluminous messages about what it is doing (if the variable `debug' is nonzero). If linked with the main program in `iregex.c', you can enter patterns and strings interactively. And if linked with the main program in `main.c' and the other test files, you can run the already-written tests. */ #ifdef DEBUG /* We use standard I/O for debugging. */ #include /* It is useful to test things that ``must'' be true when debugging. */ #include static int debug = 0; #define DEBUG_STATEMENT(e) e #define DEBUG_PRINT1(x) if (debug) printf (x) #define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) #define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) #define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) #define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ if (debug) print_partial_compiled_pattern (s, e) #define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ if (debug) print_double_string (w, s1, sz1, s2, sz2) extern void printchar (); /* Print the fastmap in human-readable form. */ void print_fastmap (fastmap) char *fastmap; { unsigned was_a_range = 0; unsigned i = 0; while (i < (1 << BYTEWIDTH)) { if (fastmap[i++]) { was_a_range = 0; printchar (i - 1); while (i < (1 << BYTEWIDTH) && fastmap[i]) { was_a_range = 1; i++; } if (was_a_range) { printf ("-"); printchar (i - 1); } } } putchar ('\n'); } /* Print a compiled pattern string in human-readable form, starting at the START pointer into it and ending just before the pointer END. */ void print_partial_compiled_pattern (start, end) unsigned char *start; unsigned char *end; { int mcnt, mcnt2; unsigned char *p = start; unsigned char *pend = end; if (start == NULL) { printf ("(null)\n"); return; } /* Loop over pattern commands. */ while (p < pend) { switch ((re_opcode_t) *p++) { case no_op: printf ("/no_op"); break; case exactn: mcnt = *p++; printf ("/exactn/%d", mcnt); do { putchar ('/'); printchar (*p++); } while (--mcnt); break; case start_memory: mcnt = *p++; printf ("/start_memory/%d/%d", mcnt, *p++); break; case stop_memory: mcnt = *p++; printf ("/stop_memory/%d/%d", mcnt, *p++); break; case duplicate: printf ("/duplicate/%d", *p++); break; case anychar: printf ("/anychar"); break; case charset: case charset_not: { register int c; printf ("/charset%s", (re_opcode_t) *(p - 1) == charset_not ? "_not" : ""); assert (p + *p < pend); for (c = 0; c < *p; c++) { unsigned bit; unsigned char map_byte = p[1 + c]; putchar ('/'); for (bit = 0; bit < BYTEWIDTH; bit++) if (map_byte & (1 << bit)) printchar (c * BYTEWIDTH + bit); } p += 1 + *p; break; } case begline: printf ("/begline"); break; case endline: printf ("/endline"); break; case on_failure_jump: extract_number_and_incr (&mcnt, &p); printf ("/on_failure_jump/0/%d", mcnt); break; case on_failure_keep_string_jump: extract_number_and_incr (&mcnt, &p); printf ("/on_failure_keep_string_jump/0/%d", mcnt); break; case dummy_failure_jump: extract_number_and_incr (&mcnt, &p); printf ("/dummy_failure_jump/0/%d", mcnt); break; case push_dummy_failure: printf ("/push_dummy_failure"); break; case maybe_pop_jump: extract_number_and_incr (&mcnt, &p); printf ("/maybe_pop_jump/0/%d", mcnt); break; case pop_failure_jump: extract_number_and_incr (&mcnt, &p); printf ("/pop_failure_jump/0/%d", mcnt); break; case jump_past_alt: extract_number_and_incr (&mcnt, &p); printf ("/jump_past_alt/0/%d", mcnt); break; case jump: extract_number_and_incr (&mcnt, &p); printf ("/jump/0/%d", mcnt); break; case succeed_n: extract_number_and_incr (&mcnt, &p); extract_number_and_incr (&mcnt2, &p); printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2); break; case jump_n: extract_number_and_incr (&mcnt, &p); extract_number_and_incr (&mcnt2, &p); printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2); break; case set_number_at: extract_number_and_incr (&mcnt, &p); extract_number_and_incr (&mcnt2, &p); printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2); break; case wordbound: printf ("/wordbound"); break; case notwordbound: printf ("/notwordbound"); break; case wordbeg: printf ("/wordbeg"); break; case wordend: printf ("/wordend"); #ifdef emacs case before_dot: printf ("/before_dot"); break; case at_dot: printf ("/at_dot"); break; case after_dot: printf ("/after_dot"); break; case syntaxspec: printf ("/syntaxspec"); mcnt = *p++; printf ("/%d", mcnt); break; case notsyntaxspec: printf ("/notsyntaxspec"); mcnt = *p++; printf ("/%d", mcnt); break; #endif /* emacs */ case wordchar: printf ("/wordchar"); break; case notwordchar: printf ("/notwordchar"); break; case begbuf: printf ("/begbuf"); break; case endbuf: printf ("/endbuf"); break; default: printf ("?%d", *(p-1)); } } printf ("/\n"); } void print_compiled_pattern (bufp) struct re_pattern_buffer *bufp; { unsigned char *buffer = bufp->buffer; print_partial_compiled_pattern (buffer, buffer + bufp->used); printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated); if (bufp->fastmap_accurate && bufp->fastmap) { printf ("fastmap: "); print_fastmap (bufp->fastmap); } printf ("re_nsub: %d\t", bufp->re_nsub); printf ("regs_alloc: %d\t", bufp->regs_allocated); printf ("can_be_null: %d\t", bufp->can_be_null); printf ("newline_anchor: %d\n", bufp->newline_anchor); printf ("no_sub: %d\t", bufp->no_sub); printf ("not_bol: %d\t", bufp->not_bol); printf ("not_eol: %d\t", bufp->not_eol); printf ("syntax: %d\n", bufp->syntax); /* Perhaps we should print the translate table? */ } void print_double_string (where, string1, size1, string2, size2) const char *where; const char *string1; const char *string2; int size1; int size2; { unsigned this_char; if (where == NULL) printf ("(null)"); else { if (FIRST_STRING_P (where)) { for (this_char = where - string1; this_char < size1; this_char++) printchar (string1[this_char]); where = string2; } for (this_char = where - string2; this_char < size2; this_char++) printchar (string2[this_char]); } } #else /* not DEBUG */ #undef assert #define assert(e) #define DEBUG_STATEMENT(e) #define DEBUG_PRINT1(x) #define DEBUG_PRINT2(x1, x2) #define DEBUG_PRINT3(x1, x2, x3) #define DEBUG_PRINT4(x1, x2, x3, x4) #define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) #define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) #endif /* not DEBUG */ /* Set by `re_set_syntax' to the current regexp syntax to recognize. Can also be assigned to arbitrarily: each pattern buffer stores its own syntax, so it can be changed between regex compilations. */ reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS; /* Specify the precise syntax of regexps for compilation. This provides for compatibility for various utilities which historically have different, incompatible syntaxes. The argument SYNTAX is a bit mask comprised of the various bits defined in regex.h. We return the old syntax. */ reg_syntax_t re_set_syntax (syntax) reg_syntax_t syntax; { reg_syntax_t ret = re_syntax_options; re_syntax_options = syntax; return ret; } /* This table gives an error message for each of the error codes listed in regex.h. Obviously the order here has to be same as there. */ static char *re_error_msg[] = { NULL, /* REG_NOERROR */ "No match", /* REG_NOMATCH */ "Invalid regular expression", /* REG_BADPAT */ "Invalid collation character", /* REG_ECOLLATE */ "Invalid character class name", /* REG_ECTYPE */ "Trailing backslash", /* REG_EESCAPE */ "Invalid back reference", /* REG_ESUBREG */ "Unmatched [ or [^", /* REG_EBRACK */ "Unmatched ( or \\(", /* REG_EPAREN */ "Unmatched \\{", /* REG_EBRACE */ "Invalid content of \\{\\}", /* REG_BADBR */ "Invalid range end", /* REG_ERANGE */ "Memory exhausted", /* REG_ESPACE */ "Invalid preceding regular expression", /* REG_BADRPT */ "Premature end of regular expression", /* REG_EEND */ "Regular expression too big", /* REG_ESIZE */ "Unmatched ) or \\)", /* REG_ERPAREN */ }; /* Subroutine declarations and macros for regex_compile. */ static void store_op1 (), store_op2 (); static void insert_op1 (), insert_op2 (); static boolean at_begline_loc_p (), at_endline_loc_p (); static boolean group_in_compile_stack (); static reg_errcode_t compile_range (); /* Fetch the next character in the uncompiled pattern---translating it if necessary. Also cast from a signed character in the constant string passed to us by the user to an unsigned char that we can use as an array index (in, e.g., `translate'). */ #define PATFETCH(c) \ do {if (p == pend) return REG_EEND; \ c = (unsigned char) *p++; \ if (translate) c = translate[c]; \ } while (0) /* Fetch the next character in the uncompiled pattern, with no translation. */ #define PATFETCH_RAW(c) \ do {if (p == pend) return REG_EEND; \ c = (unsigned char) *p++; \ } while (0) /* Go backwards one character in the pattern. */ #define PATUNFETCH p-- /* If `translate' is non-null, return translate[D], else just D. We cast the subscript to translate because some data is declared as `char *', to avoid warnings when a string constant is passed. But when we use a character as a subscript we must make it unsigned. */ #define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d)) /* Macros for outputting the compiled pattern into `buffer'. */ /* If the buffer isn't allocated when it comes in, use this. */ #define INIT_BUF_SIZE 32 /* Make sure we have at least N more bytes of space in buffer. */ #define GET_BUFFER_SPACE(n) \ while (b - bufp->buffer + (n) > bufp->allocated) \ EXTEND_BUFFER () /* Make sure we have one more byte of buffer space and then add C to it. */ #define BUF_PUSH(c) \ do { \ GET_BUFFER_SPACE (1); \ *b++ = (unsigned char) (c); \ } while (0) /* Ensure we have two more bytes of buffer space and then append C1 and C2. */ #define BUF_PUSH_2(c1, c2) \ do { \ GET_BUFFER_SPACE (2); \ *b++ = (unsigned char) (c1); \ *b++ = (unsigned char) (c2); \ } while (0) /* As with BUF_PUSH_2, except for three bytes. */ #define BUF_PUSH_3(c1, c2, c3) \ do { \ GET_BUFFER_SPACE (3); \ *b++ = (unsigned char) (c1); \ *b++ = (unsigned char) (c2); \ *b++ = (unsigned char) (c3); \ } while (0) /* Store a jump with opcode OP at LOC to location TO. We store a relative address offset by the three bytes the jump itself occupies. */ #define STORE_JUMP(op, loc, to) \ store_op1 (op, loc, (to) - (loc) - 3) /* Likewise, for a two-argument jump. */ #define STORE_JUMP2(op, loc, to, arg) \ store_op2 (op, loc, (to) - (loc) - 3, arg) /* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ #define INSERT_JUMP(op, loc, to) \ insert_op1 (op, loc, (to) - (loc) - 3, b) /* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ #define INSERT_JUMP2(op, loc, to, arg) \ insert_op2 (op, loc, (to) - (loc) - 3, arg, b) /* This is not an arbitrary limit: the arguments which represent offsets into the pattern are two bytes long. So if 2^16 bytes turns out to be too small, many things would have to change. */ #define MAX_BUF_SIZE (1L << 16) /* Extend the buffer by twice its current size via realloc and reset the pointers that pointed into the old block to point to the correct places in the new one. If extending the buffer results in it being larger than MAX_BUF_SIZE, then flag memory exhausted. */ #define EXTEND_BUFFER() \ do { \ unsigned char *old_buffer = bufp->buffer; \ if (bufp->allocated == MAX_BUF_SIZE) \ return REG_ESIZE; \ bufp->allocated <<= 1; \ if (bufp->allocated > MAX_BUF_SIZE) \ bufp->allocated = MAX_BUF_SIZE; \ bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\ if (bufp->buffer == NULL) \ return REG_ESPACE; \ /* If the buffer moved, move all the pointers into it. */ \ if (old_buffer != bufp->buffer) \ { \ b = (b - old_buffer) + bufp->buffer; \ begalt = (begalt - old_buffer) + bufp->buffer; \ if (fixup_alt_jump) \ fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\ if (laststart) \ laststart = (laststart - old_buffer) + bufp->buffer; \ if (pending_exact) \ pending_exact = (pending_exact - old_buffer) + bufp->buffer; \ } \ } while (0) /* Since we have one byte reserved for the register number argument to {start,stop}_memory, the maximum number of groups we can report things about is what fits in that byte. */ #define MAX_REGNUM 255 /* But patterns can have more than `MAX_REGNUM' registers. We just ignore the excess. */ typedef unsigned regnum_t; /* Macros for the compile stack. */ /* Since offsets can go either forwards or backwards, this type needs to be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ typedef int pattern_offset_t; typedef struct { pattern_offset_t begalt_offset; pattern_offset_t fixup_alt_jump; pattern_offset_t inner_group_offset; pattern_offset_t laststart_offset; regnum_t regnum; } compile_stack_elt_t; typedef struct { compile_stack_elt_t *stack; unsigned size; unsigned avail; /* Offset of next open position. */ } compile_stack_type; #define INIT_COMPILE_STACK_SIZE 32 #define COMPILE_STACK_EMPTY (compile_stack.avail == 0) #define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) /* The next available element. */ #define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) /* Set the bit for character C in a list. */ #define SET_LIST_BIT(c) \ (b[((unsigned char) (c)) / BYTEWIDTH] \ |= 1 << (((unsigned char) c) % BYTEWIDTH)) /* Get the next unsigned number in the uncompiled pattern. */ #define GET_UNSIGNED_NUMBER(num) \ { if (p != pend) \ { \ PATFETCH (c); \ while (ISDIGIT (c)) \ { \ if (num < 0) \ num = 0; \ num = num * 10 + c - '0'; \ if (p == pend) \ break; \ PATFETCH (c); \ } \ } \ } #define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ #define IS_CHAR_CLASS(string) \ (STREQ (string, "alpha") || STREQ (string, "upper") \ || STREQ (string, "lower") || STREQ (string, "digit") \ || STREQ (string, "alnum") || STREQ (string, "xdigit") \ || STREQ (string, "space") || STREQ (string, "print") \ || STREQ (string, "punct") || STREQ (string, "graph") \ || STREQ (string, "cntrl") || STREQ (string, "blank")) /* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. Returns one of error codes defined in `regex.h', or zero for success. Assumes the `allocated' (and perhaps `buffer') and `translate' fields are set in BUFP on entry. If it succeeds, results are put in BUFP (if it returns an error, the contents of BUFP are undefined): `buffer' is the compiled pattern; `syntax' is set to SYNTAX; `used' is set to the length of the compiled pattern; `fastmap_accurate' is zero; `re_nsub' is the number of subexpressions in PATTERN; `not_bol' and `not_eol' are zero; The `fastmap' and `newline_anchor' fields are neither examined nor set. */ static reg_errcode_t regex_compile (pattern, size, syntax, bufp) char *pattern; int size; reg_syntax_t syntax; struct re_pattern_buffer *bufp; { /* We fetch characters from PATTERN here. Even though PATTERN is `char *' (i.e., signed), we declare these variables as unsigned, so they can be reliably used as array indices. */ register unsigned char c, c1; /* A random tempory spot in PATTERN. */ char *p1; /* Points to the end of the buffer, where we should append. */ register unsigned char *b; /* Keeps track of unclosed groups. */ compile_stack_type compile_stack; /* Points to the current (ending) position in the pattern. */ char *p = pattern; char *pend = pattern + size; /* How to translate the characters in the pattern. */ char *translate = bufp->translate; /* Address of the count-byte of the most recently inserted `exactn' command. This makes it possible to tell if a new exact-match character can be added to that command or if the character requires a new `exactn' command. */ unsigned char *pending_exact = 0; /* Address of start of the most recently finished expression. This tells, e.g., postfix * where to find the start of its operand. Reset at the beginning of groups and alternatives. */ unsigned char *laststart = 0; /* Address of beginning of regexp, or inside of last group. */ unsigned char *begalt; /* Place in the uncompiled pattern (i.e., the {) to which to go back if the interval is invalid. */ char *beg_interval; /* Address of the place where a forward jump should go to the end of the containing expression. Each alternative of an `or' -- except the last -- ends with a forward jump of this sort. */ unsigned char *fixup_alt_jump = 0; /* Counts open-groups as they are encountered. Remembered for the matching close-group on the compile stack, so the same register number is put in the stop_memory as the start_memory. */ regnum_t regnum = 0; #ifdef DEBUG DEBUG_PRINT1 ("\nCompiling pattern: "); if (debug) { unsigned debug_count; for (debug_count = 0; debug_count < size; debug_count++) printchar (pattern[debug_count]); putchar ('\n'); } #endif /* DEBUG */ /* Initialize the compile stack. */ compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); if (compile_stack.stack == NULL) return REG_ESPACE; compile_stack.size = INIT_COMPILE_STACK_SIZE; compile_stack.avail = 0; /* Initialize the pattern buffer. */ bufp->syntax = syntax; bufp->fastmap_accurate = 0; bufp->not_bol = bufp->not_eol = 0; /* Set `used' to zero, so that if we return an error, the pattern printer (for debugging) will think there's no pattern. We reset it at the end. */ bufp->used = 0; /* Always count groups, whether or not bufp->no_sub is set. */ bufp->re_nsub = 0; #if !defined (emacs) && !defined (SYNTAX_TABLE) /* Initialize the syntax table. */ init_syntax_once (); #endif if (bufp->allocated == 0) { if (bufp->buffer) { /* If zero allocated, but buffer is non-null, try to realloc enough space. This loses if buffer's address is bogus, but that is the user's responsibility. */ RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char); } else { /* Caller did not allocate a buffer. Do it for them. */ bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char); } if (!bufp->buffer) return REG_ESPACE; bufp->allocated = INIT_BUF_SIZE; } begalt = b = bufp->buffer; /* Loop through the uncompiled pattern until we're at the end. */ while (p != pend) { PATFETCH (c); switch (c) { case '^': { if ( /* If at start of pattern, it's an operator. */ p == pattern + 1 /* If context independent, it's an operator. */ || syntax & RE_CONTEXT_INDEP_ANCHORS /* Otherwise, depends on what's come before. */ || at_begline_loc_p (pattern, p, syntax)) BUF_PUSH (begline); else goto normal_char; } break; case '$': { if ( /* If at end of pattern, it's an operator. */ p == pend /* If context independent, it's an operator. */ || syntax & RE_CONTEXT_INDEP_ANCHORS /* Otherwise, depends on what's next. */ || at_endline_loc_p (p, pend, syntax)) BUF_PUSH (endline); else goto normal_char; } break; case '+': case '?': if ((syntax & RE_BK_PLUS_QM) || (syntax & RE_LIMITED_OPS)) goto normal_char; handle_plus: case '*': /* If there is no previous pattern... */ if (!laststart) { if (syntax & RE_CONTEXT_INVALID_OPS) return REG_BADRPT; else if (!(syntax & RE_CONTEXT_INDEP_OPS)) goto normal_char; } { /* Are we optimizing this jump? */ boolean keep_string_p = false; /* 1 means zero (many) matches is allowed. */ char zero_times_ok = 0, many_times_ok = 0; /* If there is a sequence of repetition chars, collapse it down to just one (the right one). We can't combine interval operators with these because of, e.g., `a{2}*', which should only match an even number of `a's. */ for (;;) { zero_times_ok |= c != '+'; many_times_ok |= c != '?'; if (p == pend) break; PATFETCH (c); if (c == '*' || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) ; else if (syntax & RE_BK_PLUS_QM && c == '\\') { if (p == pend) return REG_EESCAPE; PATFETCH (c1); if (!(c1 == '+' || c1 == '?')) { PATUNFETCH; PATUNFETCH; break; } c = c1; } else { PATUNFETCH; break; } /* If we get here, we found another repeat character. */ } /* Star, etc. applied to an empty pattern is equivalent to an empty pattern. */ if (!laststart) break; /* Now we know whether or not zero matches is allowed and also whether or not two or more matches is allowed. */ if (many_times_ok) { /* More than one repetition is allowed, so put in at the end a backward relative jump from `b' to before the next jump we're going to put in below (which jumps from laststart to after this jump). But if we are at the `*' in the exact sequence `.*\n', insert an unconditional jump backwards to the ., instead of the beginning of the loop. This way we only push a failure point once, instead of every time through the loop. */ assert (p - 1 > pattern); /* Allocate the space for the jump. */ GET_BUFFER_SPACE (3); /* We know we are not at the first character of the pattern, because laststart was nonzero. And we've already incremented `p', by the way, to be the character after the `*'. Do we have to do something analogous here for null bytes, because of RE_DOT_NOT_NULL? */ if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') && zero_times_ok && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') && !(syntax & RE_DOT_NEWLINE)) { /* We have .*\n. */ STORE_JUMP (jump, b, laststart); keep_string_p = true; } else /* Anything else. */ STORE_JUMP (maybe_pop_jump, b, laststart - 3); /* We've added more stuff to the buffer. */ b += 3; } /* On failure, jump from laststart to b + 3, which will be the end of the buffer after this jump is inserted. */ GET_BUFFER_SPACE (3); INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump : on_failure_jump, laststart, b + 3); pending_exact = 0; b += 3; if (!zero_times_ok) { /* At least one repetition is required, so insert a `dummy_failure_jump' before the initial `on_failure_jump' instruction of the loop. This effects a skip over that instruction the first time we hit that loop. */ GET_BUFFER_SPACE (3); INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6); b += 3; } } break; case '.': laststart = b; BUF_PUSH (anychar); break; case '[': { boolean had_char_class = false; if (p == pend) return REG_EBRACK; /* Ensure that we have enough space to push a charset: the opcode, the length count, and the bitset; 34 bytes in all. */ GET_BUFFER_SPACE (34); laststart = b; /* We test `*p == '^' twice, instead of using an if statement, so we only need one BUF_PUSH. */ BUF_PUSH (*p == '^' ? charset_not : charset); if (*p == '^') p++; /* Remember the first position in the bracket expression. */ p1 = p; /* Push the number of bytes in the bitmap. */ BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); /* Clear the whole map. */ bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); /* charset_not matches newline according to a syntax bit. */ if ((re_opcode_t) b[-2] == charset_not && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) SET_LIST_BIT ('\n'); /* Read in characters and ranges, setting map bits. */ for (;;) { if (p == pend) return REG_EBRACK; PATFETCH (c); /* \ might escape characters inside [...] and [^...]. */ if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') { if (p == pend) return REG_EESCAPE; PATFETCH (c1); SET_LIST_BIT (c1); continue; } /* Could be the end of the bracket expression. If it's not (i.e., when the bracket expression is `[]' so far), the ']' character bit gets set way below. */ if (c == ']' && p != p1 + 1) break; /* Look ahead to see if it's a range when the last thing was a character class. */ if (had_char_class && c == '-' && *p != ']') return REG_ERANGE; /* Look ahead to see if it's a range when the last thing was a character: if this is a hyphen not at the beginning or the end of a list, then it's the range operator. */ if (c == '-' && !(p - 2 >= pattern && p[-2] == '[') && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') && *p != ']') { reg_errcode_t ret = compile_range (&p, pend, translate, syntax, b); if (ret != REG_NOERROR) return ret; } else if (p[0] == '-' && p[1] != ']') { /* This handles ranges made up of characters only. */ reg_errcode_t ret; /* Move past the `-'. */ PATFETCH (c1); ret = compile_range (&p, pend, translate, syntax, b); if (ret != REG_NOERROR) return ret; } /* See if we're at the beginning of a possible character class. */ else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') { /* Leave room for the null. */ char str[CHAR_CLASS_MAX_LENGTH + 1]; PATFETCH (c); c1 = 0; /* If pattern is `[[:'. */ if (p == pend) return REG_EBRACK; for (;;) { PATFETCH (c); if (c == ':' || c == ']' || p == pend || c1 == CHAR_CLASS_MAX_LENGTH) break; str[c1++] = c; } str[c1] = '\0'; /* If isn't a word bracketed by `[:' and:`]': undo the ending character, the letters, and leave the leading `:' and `[' (but set bits for them). */ if (c == ':' && *p == ']') { int ch; boolean is_alnum = STREQ (str, "alnum"); boolean is_alpha = STREQ (str, "alpha"); boolean is_blank = STREQ (str, "blank"); boolean is_cntrl = STREQ (str, "cntrl"); boolean is_digit = STREQ (str, "digit"); boolean is_graph = STREQ (str, "graph"); boolean is_lower = STREQ (str, "lower"); boolean is_print = STREQ (str, "print"); boolean is_punct = STREQ (str, "punct"); boolean is_space = STREQ (str, "space"); boolean is_upper = STREQ (str, "upper"); boolean is_xdigit = STREQ (str, "xdigit"); if (!IS_CHAR_CLASS (str)) return REG_ECTYPE; /* Throw away the ] at the end of the character class. */ PATFETCH (c); if (p == pend) return REG_EBRACK; for (ch = 0; ch < 1 << BYTEWIDTH; ch++) { if ( (is_alnum && ISALNUM (ch)) || (is_alpha && ISALPHA (ch)) || (is_blank && ISBLANK (ch)) || (is_cntrl && ISCNTRL (ch)) || (is_digit && ISDIGIT (ch)) || (is_graph && ISGRAPH (ch)) || (is_lower && ISLOWER (ch)) || (is_print && ISPRINT (ch)) || (is_punct && ISPUNCT (ch)) || (is_space && ISSPACE (ch)) || (is_upper && ISUPPER (ch)) || (is_xdigit && ISXDIGIT (ch))) SET_LIST_BIT (ch); } had_char_class = true; } else { c1++; while (c1--) PATUNFETCH; SET_LIST_BIT ('['); SET_LIST_BIT (':'); had_char_class = false; } } else { had_char_class = false; SET_LIST_BIT (c); } } /* Discard any (non)matching list bytes that are all 0 at the end of the map. Decrease the map-length byte too. */ while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) b[-1]--; b += b[-1]; } break; case '(': if (syntax & RE_NO_BK_PARENS) goto handle_open; else goto normal_char; case ')': if (syntax & RE_NO_BK_PARENS) goto handle_close; else goto normal_char; case '\n': if (syntax & RE_NEWLINE_ALT) goto handle_alt; else goto normal_char; case '|': if (syntax & RE_NO_BK_VBAR) goto handle_alt; else goto normal_char; case '{': if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) goto handle_interval; else goto normal_char; case '\\': if (p == pend) return REG_EESCAPE; /* Do not translate the character after the \, so that we can distinguish, e.g., \B from \b, even if we normally would translate, e.g., B to b. */ PATFETCH_RAW (c); switch (c) { case '(': if (syntax & RE_NO_BK_PARENS) goto normal_backslash; handle_open: bufp->re_nsub++; regnum++; if (COMPILE_STACK_FULL) { RETALLOC (compile_stack.stack, compile_stack.size << 1, compile_stack_elt_t); if (compile_stack.stack == NULL) return REG_ESPACE; compile_stack.size <<= 1; } /* These are the values to restore when we hit end of this group. They are all relative offsets, so that if the whole pattern moves because of realloc, they will still be valid. */ COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer; COMPILE_STACK_TOP.fixup_alt_jump = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer; COMPILE_STACK_TOP.regnum = regnum; /* We will eventually replace the 0 with the number of groups inner to this one. But do not push a start_memory for groups beyond the last one we can represent in the compiled pattern. */ if (regnum <= MAX_REGNUM) { COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2; BUF_PUSH_3 (start_memory, regnum, 0); } compile_stack.avail++; fixup_alt_jump = 0; laststart = 0; begalt = b; /* If we've reached MAX_REGNUM groups, then this open won't actually generate any code, so we'll have to clear pending_exact explicitly. */ pending_exact = 0; break; case ')': if (syntax & RE_NO_BK_PARENS) goto normal_backslash; if (COMPILE_STACK_EMPTY) if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) goto normal_backslash; else return REG_ERPAREN; handle_close: if (fixup_alt_jump) { /* Push a dummy failure point at the end of the alternative for a possible future `pop_failure_jump' to pop. See comments at `push_dummy_failure' in `re_match_2'. */ BUF_PUSH (push_dummy_failure); /* We allocated space for this jump when we assigned to `fixup_alt_jump', in the `handle_alt' case below. */ STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); } /* See similar code for backslashed left paren above. */ if (COMPILE_STACK_EMPTY) if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) goto normal_char; else return REG_ERPAREN; /* Since we just checked for an empty stack above, this ``can't happen''. */ assert (compile_stack.avail != 0); { /* We don't just want to restore into `regnum', because later groups should continue to be numbered higher, as in `(ab)c(de)' -- the second group is #2. */ regnum_t this_group_regnum; compile_stack.avail--; begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset; fixup_alt_jump = COMPILE_STACK_TOP.fixup_alt_jump ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 : 0; laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset; this_group_regnum = COMPILE_STACK_TOP.regnum; /* If we've reached MAX_REGNUM groups, then this open won't actually generate any code, so we'll have to clear pending_exact explicitly. */ pending_exact = 0; /* We're at the end of the group, so now we know how many groups were inside this one. */ if (this_group_regnum <= MAX_REGNUM) { unsigned char *inner_group_loc = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset; *inner_group_loc = regnum - this_group_regnum; BUF_PUSH_3 (stop_memory, this_group_regnum, regnum - this_group_regnum); } } break; case '|': /* `\|'. */ if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) goto normal_backslash; handle_alt: if (syntax & RE_LIMITED_OPS) goto normal_char; /* Insert before the previous alternative a jump which jumps to this alternative if the former fails. */ GET_BUFFER_SPACE (3); INSERT_JUMP (on_failure_jump, begalt, b + 6); pending_exact = 0; b += 3; /* The alternative before this one has a jump after it which gets executed if it gets matched. Adjust that jump so it will jump to this alternative's analogous jump (put in below, which in turn will jump to the next (if any) alternative's such jump, etc.). The last such jump jumps to the correct final destination. A picture: _____ _____ | | | | | v | v a | b | c If we are at `b', then fixup_alt_jump right now points to a three-byte space after `a'. We'll put in the jump, set fixup_alt_jump to right after `b', and leave behind three bytes which we'll fill in when we get to after `c'. */ if (fixup_alt_jump) STORE_JUMP (jump_past_alt, fixup_alt_jump, b); /* Mark and leave space for a jump after this alternative, to be filled in later either by next alternative or when know we're at the end of a series of alternatives. */ fixup_alt_jump = b; GET_BUFFER_SPACE (3); b += 3; laststart = 0; begalt = b; break; case '{': /* If \{ is a literal. */ if (!(syntax & RE_INTERVALS) /* If we're at `\{' and it's not the open-interval operator. */ || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) || (p - 2 == pattern && p == pend)) goto normal_backslash; handle_interval: { /* If got here, then the syntax allows intervals. */ /* At least (most) this many matches must be made. */ int lower_bound = -1, upper_bound = -1; beg_interval = p - 1; if (p == pend) { if (syntax & RE_NO_BK_BRACES) goto unfetch_interval; else return REG_EBRACE; } GET_UNSIGNED_NUMBER (lower_bound); if (c == ',') { GET_UNSIGNED_NUMBER (upper_bound); if (upper_bound < 0) upper_bound = RE_DUP_MAX; } else /* Interval such as `{1}' => match exactly once. */ upper_bound = lower_bound; if (lower_bound < 0 || upper_bound > RE_DUP_MAX || lower_bound > upper_bound) { if (syntax & RE_NO_BK_BRACES) goto unfetch_interval; else return REG_BADBR; } if (!(syntax & RE_NO_BK_BRACES)) { if (c != '\\') return REG_EBRACE; PATFETCH (c); } if (c != '}') { if (syntax & RE_NO_BK_BRACES) goto unfetch_interval; else return REG_BADBR; } /* We just parsed a valid interval. */ /* If it's invalid to have no preceding re. */ if (!laststart) { if (syntax & RE_CONTEXT_INVALID_OPS) return REG_BADRPT; else if (syntax & RE_CONTEXT_INDEP_OPS) laststart = b; else goto unfetch_interval; } /* If the upper bound is zero, don't want to succeed at all; jump from `laststart' to `b + 3', which will be the end of the buffer after we insert the jump. */ if (upper_bound == 0) { GET_BUFFER_SPACE (3); INSERT_JUMP (jump, laststart, b + 3); b += 3; } /* Otherwise, we have a nontrivial interval. When we're all done, the pattern will look like: set_number_at set_number_at succeed_n jump_n (The upper bound and `jump_n' are omitted if `upper_bound' is 1, though.) */ else { /* If the upper bound is > 1, we need to insert more at the end of the loop. */ unsigned nbytes = 10 + (upper_bound > 1) * 10; GET_BUFFER_SPACE (nbytes); /* Initialize lower bound of the `succeed_n', even though it will be set during matching by its attendant `set_number_at' (inserted next), because `re_compile_fastmap' needs to know. Jump to the `jump_n' we might insert below. */ INSERT_JUMP2 (succeed_n, laststart, b + 5 + (upper_bound > 1) * 5, lower_bound); b += 5; /* Code to initialize the lower bound. Insert before the `succeed_n'. The `5' is the last two bytes of this `set_number_at', plus 3 bytes of the following `succeed_n'. */ insert_op2 (set_number_at, laststart, 5, lower_bound, b); b += 5; if (upper_bound > 1) { /* More than one repetition is allowed, so append a backward jump to the `succeed_n' that starts this interval. When we've reached this during matching, we'll have matched the interval once, so jump back only `upper_bound - 1' times. */ STORE_JUMP2 (jump_n, b, laststart + 5, upper_bound - 1); b += 5; /* The location we want to set is the second parameter of the `jump_n'; that is `b-2' as an absolute address. `laststart' will be the `set_number_at' we're about to insert; `laststart+3' the number to set, the source for the relative address. But we are inserting into the middle of the pattern -- so everything is getting moved up by 5. Conclusion: (b - 2) - (laststart + 3) + 5, i.e., b - laststart. We insert this at the beginning of the loop so that if we fail during matching, we'll reinitialize the bounds. */ insert_op2 (set_number_at, laststart, b - laststart, upper_bound - 1, b); b += 5; } } pending_exact = 0; beg_interval = NULL; } break; unfetch_interval: /* If an invalid interval, match the characters as literals. */ assert (beg_interval); p = beg_interval; beg_interval = NULL; /* normal_char and normal_backslash need `c'. */ PATFETCH (c); if (!(syntax & RE_NO_BK_BRACES)) { if (p > pattern && p[-1] == '\\') goto normal_backslash; } goto normal_char; #ifdef emacs /* There is no way to specify the before_dot and after_dot operators. rms says this is ok. --karl */ case '=': BUF_PUSH (at_dot); break; case 's': laststart = b; PATFETCH (c); BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); break; case 'S': laststart = b; PATFETCH (c); BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); break; #endif /* emacs */ case 'w': laststart = b; BUF_PUSH (wordchar); break; case 'W': laststart = b; BUF_PUSH (notwordchar); break; case '<': BUF_PUSH (wordbeg); break; case '>': BUF_PUSH (wordend); break; case 'b': BUF_PUSH (wordbound); break; case 'B': BUF_PUSH (notwordbound); break; case '`': BUF_PUSH (begbuf); break; case '\'': BUF_PUSH (endbuf); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (syntax & RE_NO_BK_REFS) goto normal_char; c1 = c - '0'; if (c1 > regnum) return REG_ESUBREG; /* Can't back reference to a subexpression if inside of it. */ if (group_in_compile_stack (compile_stack, c1)) goto normal_char; laststart = b; BUF_PUSH_2 (duplicate, c1); break; case '+': case '?': if (syntax & RE_BK_PLUS_QM) goto handle_plus; else goto normal_backslash; default: normal_backslash: /* You might think it would be useful for \ to mean not to translate; but if we don't translate it it will never match anything. */ c = TRANSLATE (c); goto normal_char; } break; default: /* Expects the character in `c'. */ normal_char: /* If no exactn currently being built. */ if (!pending_exact /* If last exactn not at current position. */ || pending_exact + *pending_exact + 1 != b /* We have only one byte following the exactn for the count. */ || *pending_exact == (1 << BYTEWIDTH) - 1 /* If followed by a repetition operator. */ || *p == '*' || *p == '^' || ((syntax & RE_BK_PLUS_QM) ? *p == '\\' && (p[1] == '+' || p[1] == '?') : (*p == '+' || *p == '?')) || ((syntax & RE_INTERVALS) && ((syntax & RE_NO_BK_BRACES) ? *p == '{' : (p[0] == '\\' && p[1] == '{')))) { /* Start building a new exactn. */ laststart = b; BUF_PUSH_2 (exactn, 0); pending_exact = b - 1; } BUF_PUSH (c); (*pending_exact)++; break; } /* switch (c) */ } /* while p != pend */ /* Through the pattern now. */ if (fixup_alt_jump) STORE_JUMP (jump_past_alt, fixup_alt_jump, b); if (!COMPILE_STACK_EMPTY) return REG_EPAREN; free (compile_stack.stack); /* We have succeeded; set the length of the buffer. */ bufp->used = b - bufp->buffer; #ifdef DEBUG if (debug) { DEBUG_PRINT1 ("\nCompiled pattern: "); print_compiled_pattern (bufp); } #endif /* DEBUG */ return REG_NOERROR; } /* regex_compile */ /* Subroutines for `regex_compile'. */ /* Store OP at LOC followed by two-byte integer parameter ARG. */ static void store_op1 (op, loc, arg) re_opcode_t op; unsigned char *loc; int arg; { *loc = (unsigned char) op; STORE_NUMBER (loc + 1, arg); } /* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ static void store_op2 (op, loc, arg1, arg2) re_opcode_t op; unsigned char *loc; int arg1, arg2; { *loc = (unsigned char) op; STORE_NUMBER (loc + 1, arg1); STORE_NUMBER (loc + 3, arg2); } /* Copy the bytes from LOC to END to open up three bytes of space at LOC for OP followed by two-byte integer parameter ARG. */ static void insert_op1 (op, loc, arg, end) re_opcode_t op; unsigned char *loc; int arg; unsigned char *end; { register unsigned char *pfrom = end; register unsigned char *pto = end + 3; while (pfrom != loc) *--pto = *--pfrom; store_op1 (op, loc, arg); } /* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ static void insert_op2 (op, loc, arg1, arg2, end) re_opcode_t op; unsigned char *loc; int arg1, arg2; unsigned char *end; { register unsigned char *pfrom = end; register unsigned char *pto = end + 5; while (pfrom != loc) *--pto = *--pfrom; store_op2 (op, loc, arg1, arg2); } /* P points to just after a ^ in PATTERN. Return true if that ^ comes after an alternative or a begin-subexpression. We assume there is at least one character before the ^. */ static boolean at_begline_loc_p (pattern, p, syntax) char *pattern, *p; reg_syntax_t syntax; { char *prev = p - 2; boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; return /* After a subexpression? */ (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) /* After an alternative? */ || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); } /* The dual of at_begline_loc_p. This one is for $. We assume there is at least one character after the $, i.e., `P < PEND'. */ static boolean at_endline_loc_p (p, pend, syntax) char *p, *pend; int syntax; { char *next = p; boolean next_backslash = *next == '\\'; char *next_next; if(p + 1 < pend) next_next=p + 1; else next_next=NULL; return /* Before a subexpression? */ (syntax & RE_NO_BK_PARENS ? *next == ')' : next_backslash && next_next && *next_next == ')') /* Before an alternative? */ || (syntax & RE_NO_BK_VBAR ? *next == '|' : next_backslash && next_next && *next_next == '|'); } /* Returns true if REGNUM is in one of COMPILE_STACK's elements and false if it's not. */ static boolean group_in_compile_stack (compile_stack, regnum) compile_stack_type compile_stack; regnum_t regnum; { int this_element; for (this_element = compile_stack.avail - 1; this_element >= 0; this_element--) if (compile_stack.stack[this_element].regnum == regnum) return true; return false; } /* Read the ending character of a range (in a bracket expression) from the uncompiled pattern *P_PTR (which ends at PEND). We assume the starting character is in `P[-2]'. (`P[-1]' is the character `-'.) Then we set the translation of all bits between the starting and ending characters (inclusive) in the compiled pattern B. Return an error code. We use these short variable names so we can use the same macros as `regex_compile' itself. */ static reg_errcode_t compile_range (p_ptr, pend, translate, syntax, b) char **p_ptr, *pend; char *translate; reg_syntax_t syntax; unsigned char *b; { unsigned this_char; char *p = *p_ptr; int range_start, range_end; if (p == pend) return REG_ERANGE; /* Even though the pattern is a signed `char *', we need to fetch with unsigned char *'s; if the high bit of the pattern character is set, the range endpoints will be negative if we fetch using a signed char *. We also want to fetch the endpoints without translating them; the appropriate translation is done in the bit-setting loop below. */ range_start = ((unsigned char *) p)[-2]; range_end = ((unsigned char *) p)[0]; /* Have to increment the pointer into the pattern string, so the caller isn't still at the ending character. */ (*p_ptr)++; /* If the start is after the end, the range is empty. */ if (range_start > range_end) return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; /* Here we see why `this_char' has to be larger than an `unsigned char' -- the range is inclusive, so if `range_end' == 0xff (assuming 8-bit characters), we would otherwise go into an infinite loop, since all characters <= 0xff. */ for (this_char = range_start; this_char <= range_end; this_char++) { SET_LIST_BIT (TRANSLATE (this_char)); } return REG_NOERROR; } /* Failure stack declarations and macros; both re_compile_fastmap and re_match_2 use a failure stack. These have to be macros because of REGEX_ALLOCATE. */ /* Number of failure points for which to initially allocate space when matching. If this number is exceeded, we allocate more space, so it is not a hard limit. */ #ifndef INIT_FAILURE_ALLOC #define INIT_FAILURE_ALLOC 5 #endif /* Roughly the maximum number of failure points on the stack. Would be exactly that if always used MAX_FAILURE_SPACE each time we failed. This is a variable only so users of regex can assign to it; we never change it ourselves. */ int re_max_failures = 2000; typedef unsigned char *fail_stack_elt_t; typedef struct { fail_stack_elt_t *stack; unsigned size; unsigned avail; /* Offset of next open position. */ } fail_stack_type; #define FAIL_STACK_EMPTY() (fail_stack.avail == 0) #define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) #define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) #define FAIL_STACK_TOP() (fail_stack.stack[fail_stack.avail]) /* Initialize `fail_stack'. Do `return -2' if the alloc fails. */ #define INIT_FAIL_STACK() \ do { \ fail_stack.stack = (fail_stack_elt_t *) \ REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \ \ if (fail_stack.stack == NULL) \ return -2; \ \ fail_stack.size = INIT_FAILURE_ALLOC; \ fail_stack.avail = 0; \ } while (0) /* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. Return 1 if succeeds, and 0 if either ran out of memory allocating space for it or it was already too large. REGEX_REALLOCATE requires `destination' be declared. */ #define DOUBLE_FAIL_STACK(fail_stack) \ ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS \ ? 0 \ : ((fail_stack).stack = (fail_stack_elt_t *) \ REGEX_REALLOCATE ((fail_stack).stack, \ (fail_stack).size * sizeof (fail_stack_elt_t), \ ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)), \ \ (fail_stack).stack == NULL \ ? 0 \ : ((fail_stack).size <<= 1, \ 1))) /* Push PATTERN_OP on FAIL_STACK. Return 1 if was able to do so and 0 if ran out of memory allocating space to do so. */ #define PUSH_PATTERN_OP(pattern_op, fail_stack) \ ((FAIL_STACK_FULL () \ && !DOUBLE_FAIL_STACK (fail_stack)) \ ? 0 \ : ((fail_stack).stack[(fail_stack).avail++] = pattern_op, \ 1)) /* This pushes an item onto the failure stack. Must be a four-byte value. Assumes the variable `fail_stack'. Probably should only be called from within `PUSH_FAILURE_POINT'. */ #define PUSH_FAILURE_ITEM(item) \ fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item /* The complement operation. Assumes `fail_stack' is nonempty. */ #define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail] /* Used to omit pushing failure point id's when we're not debugging. */ #ifdef DEBUG #define DEBUG_PUSH PUSH_FAILURE_ITEM #define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM () #else #define DEBUG_PUSH(item) #define DEBUG_POP(item_addr) #endif /* Push the information about the state we will need if we ever fail back to it. Requires variables fail_stack, regstart, regend, reg_info, and num_regs be declared. DOUBLE_FAIL_STACK requires `destination' be declared. Does `return FAILURE_CODE' if runs out of memory. */ #define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ do { \ char *destination; \ /* Must be int, so when we don't save any registers, the arithmetic \ of 0 + -1 isn't done as unsigned. */ \ int this_reg; \ \ DEBUG_STATEMENT (failure_id++); \ DEBUG_STATEMENT (nfailure_points_pushed++); \ DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ \ DEBUG_PRINT2 (" slots needed: %d\n", NUM_FAILURE_ITEMS); \ DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ \ /* Ensure we have enough space allocated for what we will push. */ \ while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ { \ if (!DOUBLE_FAIL_STACK (fail_stack)) \ return failure_code; \ \ DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ (fail_stack).size); \ DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ } \ \ /* Push the info, starting with the registers. */ \ DEBUG_PRINT1 ("\n"); \ \ for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ this_reg++) \ { \ DEBUG_PRINT2 (" Pushing reg: %d\n", this_reg); \ DEBUG_STATEMENT (num_regs_pushed++); \ \ DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ PUSH_FAILURE_ITEM (regstart[this_reg]); \ \ DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ PUSH_FAILURE_ITEM (regend[this_reg]); \ \ DEBUG_PRINT2 (" info: 0x%x\n ", reg_info[this_reg]); \ DEBUG_PRINT2 (" match_null=%d", \ REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ DEBUG_PRINT2 (" matched_something=%d", \ MATCHED_SOMETHING (reg_info[this_reg])); \ DEBUG_PRINT2 (" ever_matched=%d", \ EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ DEBUG_PRINT1 ("\n"); \ PUSH_FAILURE_ITEM (reg_info[this_reg].word); \ } \ \ DEBUG_PRINT2 (" Pushing low active reg: %d\n", lowest_active_reg);\ PUSH_FAILURE_ITEM (lowest_active_reg); \ \ DEBUG_PRINT2 (" Pushing high active reg: %d\n", highest_active_reg);\ PUSH_FAILURE_ITEM (highest_active_reg); \ \ DEBUG_PRINT2 (" Pushing pattern 0x%x: ", pattern_place); \ DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ PUSH_FAILURE_ITEM (pattern_place); \ \ DEBUG_PRINT2 (" Pushing string 0x%x: `", string_place); \ DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ size2); \ DEBUG_PRINT1 ("'\n"); \ PUSH_FAILURE_ITEM (string_place); \ \ DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ DEBUG_PUSH (failure_id); \ } while (0) /* This is the number of items that are pushed and popped on the stack for each register. */ #define NUM_REG_ITEMS 3 /* Individual items aside from the registers. */ #ifdef DEBUG #define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ #else #define NUM_NONREG_ITEMS 4 #endif /* We push at most this many items on the stack. */ #define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS) /* We actually push this many items. */ #define NUM_FAILURE_ITEMS \ ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS \ + NUM_NONREG_ITEMS) /* How many items can still be added to the stack without overflowing it. */ #define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) /* Pops what PUSH_FAIL_STACK pushes. We restore into the parameters, all of which should be lvalues: STR -- the saved data position. PAT -- the saved pattern position. LOW_REG, HIGH_REG -- the highest and lowest active registers. REGSTART, REGEND -- arrays of string positions. REG_INFO -- array of information about each subexpression. Also assumes the variables `fail_stack' and (if debugging), `bufp', `pend', `string1', `size1', `string2', and `size2'. */ #define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ { \ DEBUG_STATEMENT (fail_stack_elt_t failure_id;) \ int this_reg; \ unsigned char *string_temp; \ \ assert (!FAIL_STACK_EMPTY ()); \ \ /* Remove failure points and point to how many regs pushed. */ \ DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ \ assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ \ DEBUG_POP (&failure_id); \ DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ \ /* If the saved string location is NULL, it came from an \ on_failure_keep_string_jump opcode, and we want to throw away the \ saved NULL, thus retaining our current position in the string. */ \ string_temp = POP_FAILURE_ITEM (); \ if (string_temp != NULL) \ str = ( char *) string_temp; \ \ DEBUG_PRINT2 (" Popping string 0x%x: `", str); \ DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ DEBUG_PRINT1 ("'\n"); \ \ pat = (unsigned char *) POP_FAILURE_ITEM (); \ DEBUG_PRINT2 (" Popping pattern 0x%x: ", pat); \ DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ \ /* Restore register info. */ \ high_reg = (unsigned) POP_FAILURE_ITEM (); \ DEBUG_PRINT2 (" Popping high active reg: %d\n", high_reg); \ \ low_reg = (unsigned) POP_FAILURE_ITEM (); \ DEBUG_PRINT2 (" Popping low active reg: %d\n", low_reg); \ \ for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ { \ DEBUG_PRINT2 (" Popping reg: %d\n", this_reg); \ \ reg_info[this_reg].word = POP_FAILURE_ITEM (); \ DEBUG_PRINT2 (" info: 0x%x\n", reg_info[this_reg]); \ \ regend[this_reg] = ( char *) POP_FAILURE_ITEM (); \ DEBUG_PRINT2 (" end: 0x%x\n", regend[this_reg]); \ \ regstart[this_reg] = ( char *) POP_FAILURE_ITEM (); \ DEBUG_PRINT2 (" start: 0x%x\n", regstart[this_reg]); \ } \ \ DEBUG_STATEMENT (nfailure_points_popped++); \ } /* POP_FAILURE_POINT */ /* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible characters can start a string that matches the pattern. This fastmap is used by re_search to skip quickly over impossible starting points. The caller must supply the address of a (1 << BYTEWIDTH)-byte data area as BUFP->fastmap. We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in the pattern buffer. Returns 0 if we succeed, -2 if an internal error. */ int re_compile_fastmap (bufp) struct re_pattern_buffer *bufp; { int j, k; fail_stack_type fail_stack; #ifndef REGEX_MALLOC char *destination; #endif /* We don't push any register information onto the failure stack. */ unsigned num_regs = 0; register char *fastmap = bufp->fastmap; unsigned char *pattern = bufp->buffer; unsigned long size = bufp->used; unsigned char *p = pattern; register unsigned char *pend = pattern + size; /* Assume that each path through the pattern can be null until proven otherwise. We set this false at the bottom of switch statement, to which we get only if a particular path doesn't match the empty string. */ boolean path_can_be_null = true; /* We aren't doing a `succeed_n' to begin with. */ boolean succeed_n_p = false; assert (fastmap != NULL && p != NULL); INIT_FAIL_STACK (); bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ bufp->fastmap_accurate = 1; /* It will be when we're done. */ bufp->can_be_null = 0; while (p != pend || !FAIL_STACK_EMPTY ()) { if (p == pend) { bufp->can_be_null |= path_can_be_null; /* Reset for next path. */ path_can_be_null = true; p = fail_stack.stack[--fail_stack.avail]; } /* We should never be about to go beyond the end of the pattern. */ assert (p < pend); #ifdef SWITCH_ENUM_BUG switch ((int) ((re_opcode_t) *p++)) #else switch ((re_opcode_t) *p++) #endif { /* I guess the idea here is to simply not bother with a fastmap if a backreference is used, since it's too hard to figure out the fastmap for the corresponding group. Setting `can_be_null' stops `re_search_2' from using the fastmap, so that is all we do. */ case duplicate: bufp->can_be_null = 1; return 0; /* Following are the cases which match a character. These end with `break'. */ case exactn: fastmap[p[1]] = 1; break; case charset: for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) fastmap[j] = 1; break; case charset_not: /* Chars beyond end of map must be allowed. */ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) fastmap[j] = 1; for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) fastmap[j] = 1; break; case wordchar: for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) == Sword) fastmap[j] = 1; break; case notwordchar: for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) != Sword) fastmap[j] = 1; break; case anychar: /* `.' matches anything ... */ for (j = 0; j < (1 << BYTEWIDTH); j++) fastmap[j] = 1; /* ... except perhaps newline. */ if (!(bufp->syntax & RE_DOT_NEWLINE)) fastmap['\n'] = 0; /* Return if we have already set `can_be_null'; if we have, then the fastmap is irrelevant. Something's wrong here. */ else if (bufp->can_be_null) return 0; /* Otherwise, have to check alternative paths. */ break; #ifdef emacs case syntaxspec: k = *p++; for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) == (enum syntaxcode) k) fastmap[j] = 1; break; case notsyntaxspec: k = *p++; for (j = 0; j < (1 << BYTEWIDTH); j++) if (SYNTAX (j) != (enum syntaxcode) k) fastmap[j] = 1; break; /* All cases after this match the empty string. These end with `continue'. */ case before_dot: case at_dot: case after_dot: continue; #endif /* not emacs */ case no_op: case begline: case endline: case begbuf: case endbuf: case wordbound: case notwordbound: case wordbeg: case wordend: case push_dummy_failure: continue; case jump_n: case pop_failure_jump: case maybe_pop_jump: case jump: case jump_past_alt: case dummy_failure_jump: EXTRACT_NUMBER_AND_INCR (j, p); p += j; if (j > 0) continue; /* Jump backward implies we just went through the body of a loop and matched nothing. Opcode jumped to should be `on_failure_jump' or `succeed_n'. Just treat it like an ordinary jump. For a * loop, it has pushed its failure point already; if so, discard that as redundant. */ if ((re_opcode_t) *p != on_failure_jump && (re_opcode_t) *p != succeed_n) continue; p++; EXTRACT_NUMBER_AND_INCR (j, p); p += j; /* If what's on the stack is where we are now, pop it. */ if (!FAIL_STACK_EMPTY () && fail_stack.stack[fail_stack.avail - 1] == p) fail_stack.avail--; continue; case on_failure_jump: case on_failure_keep_string_jump: handle_on_failure_jump: EXTRACT_NUMBER_AND_INCR (j, p); /* For some patterns, e.g., `(a?)?', `p+j' here points to the end of the pattern. We don't want to push such a point, since when we restore it above, entering the switch will increment `p' past the end of the pattern. We don't need to push such a point since we obviously won't find any more fastmap entries beyond `pend'. Such a pattern can match the null string, though. */ if (p + j < pend) { if (!PUSH_PATTERN_OP (p + j, fail_stack)) return -2; } else bufp->can_be_null = 1; if (succeed_n_p) { EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ succeed_n_p = false; } continue; case succeed_n: /* Get to the number of times to succeed. */ p += 2; /* Increment p past the n for when k != 0. */ EXTRACT_NUMBER_AND_INCR (k, p); if (k == 0) { p -= 4; succeed_n_p = true; /* Spaghetti code alert. */ goto handle_on_failure_jump; } continue; case set_number_at: p += 4; continue; case start_memory: case stop_memory: p += 2; continue; default: abort (); /* We have listed all the cases. */ } /* switch *p++ */ /* Getting here means we have found the possible starting characters for one path of the pattern -- and that the empty string does not match. We need not follow this path further. Instead, look at the next alternative (remembered on the stack), or quit if no more. The test at the top of the loop does these things. */ path_can_be_null = false; p = pend; } /* while p */ /* Set `can_be_null' for the last path (also the first path, if the pattern is empty). */ bufp->can_be_null |= path_can_be_null; return 0; } /* re_compile_fastmap */ /* Set REGS to hold NUM_REGS registers, storing them in STARTS and ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use this memory for recording register information. STARTS and ENDS must be allocated using the malloc library routine, and must each be at least NUM_REGS * sizeof (regoff_t) bytes long. If NUM_REGS == 0, then subsequent matches should allocate their own register data. Unless this function is called, the first search or match using PATTERN_BUFFER will allocate its own register data, without freeing the old data. */ void re_set_registers (bufp, regs, num_regs, starts, ends) struct re_pattern_buffer *bufp; struct re_registers *regs; unsigned num_regs; regoff_t *starts, *ends; { if (num_regs) { bufp->regs_allocated = REGS_REALLOCATE; regs->num_regs = num_regs; regs->start = starts; regs->end = ends; } else { bufp->regs_allocated = REGS_UNALLOCATED; regs->num_regs = 0; regs->start = regs->end = (regoff_t) 0; } } /* Searching routines. */ /* Like re_search_2, below, but only one string is specified, and doesn't let you say where to stop matching. */ int re_search (bufp, string, size, startpos, range, regs) struct re_pattern_buffer *bufp; char *string; int size, startpos, range; struct re_registers *regs; { return re_search_2 (bufp, NULL, 0, string, size, startpos, range, regs, size); } /* Using the compiled pattern in BUFP->buffer, first tries to match the virtual concatenation of STRING1 and STRING2, starting first at index STARTPOS, then at STARTPOS + 1, and so on. STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. RANGE is how far to scan while trying to match. RANGE = 0 means try only at STARTPOS; in general, the last start tried is STARTPOS + RANGE. In REGS, return the indices of the virtual concatenation of STRING1 and STRING2 that matched the entire BUFP->buffer and its contained subexpressions. Do not consider matching one past the index STOP in the virtual concatenation of STRING1 and STRING2. We return either the position in the strings at which the match was found, -1 if no match, or -2 if error (such as failure stack overflow). */ int re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop) struct re_pattern_buffer *bufp; char *string1, *string2; int size1, size2; int startpos; int range; struct re_registers *regs; int stop; { int val; register char *fastmap = bufp->fastmap; register char *translate = bufp->translate; int total_size = size1 + size2; int endpos = startpos + range; /* Check for out-of-range STARTPOS. */ if (startpos < 0 || startpos > total_size) return -1; /* Fix up RANGE if it might eventually take us outside the virtual concatenation of STRING1 and STRING2. */ if (endpos < -1) range = -1 - startpos; else if (endpos > total_size) range = total_size - startpos; /* If the search isn't to be a backwards one, don't waste time in a search for a pattern that must be anchored. */ if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0) { if (startpos > 0) return -1; else range = 1; } /* Update the fastmap now if not correct already. */ if (fastmap && !bufp->fastmap_accurate) if (re_compile_fastmap (bufp) == -2) return -2; /* Loop through the string, looking for a place to start matching. */ for (;;) { /* If a fastmap is supplied, skip quickly over characters that cannot be the start of a match. If the pattern can match the null string, however, we don't need to skip characters; we want the first null string. */ if (fastmap && startpos < total_size && !bufp->can_be_null) { if (range > 0) /* Searching forwards. */ { register char *d; register int lim = 0; int irange = range; if (startpos < size1 && startpos + range >= size1) lim = range - (size1 - startpos); d = (startpos >= size1 ? string2 - size1 : string1) + startpos; /* Written out as an if-else to avoid testing `translate' inside the loop. */ if (translate) while (range > lim && !fastmap[(unsigned char) translate[(unsigned char) *d++]]) range--; else while (range > lim && !fastmap[(unsigned char) *d++]) range--; startpos += irange - range; } else /* Searching backwards. */ { register char c = (size1 == 0 || startpos >= size1 ? string2[startpos - size1] : string1[startpos]); if (!fastmap[(unsigned char) TRANSLATE (c)]) goto advance; } } /* If can't match the null string, and that's all we have left, fail. */ if (range >= 0 && startpos == total_size && fastmap && !bufp->can_be_null) return -1; val = re_match_2 (bufp, string1, size1, string2, size2, startpos, regs, stop); if (val >= 0) return startpos; if (val == -2) return -2; advance: if (!range) break; else if (range > 0) { range--; startpos++; } else { range++; startpos--; } } return -1; } /* re_search_2 */ /* Declarations and macros for re_match_2. */ static int bcmp_translate (); static boolean alt_match_null_string_p (), common_op_match_null_string_p (), group_match_null_string_p (); /* Structure for per-register (a.k.a. per-group) information. This must not be longer than one word, because we push this value onto the failure stack. Other register information, such as the starting and ending positions (which are addresses), and the list of inner groups (which is a bits list) are maintained in separate variables. We are making a (strictly speaking) nonportable assumption here: that the compiler will pack our bit fields into something that fits into the type of `word', i.e., is something that fits into one item on the failure stack. */ typedef union { fail_stack_elt_t word; struct { /* This field is one if this group can match the empty string, zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ #define MATCH_NULL_UNSET_VALUE 3 unsigned match_null_string_p : 2; unsigned is_active : 1; unsigned matched_something : 1; unsigned ever_matched_something : 1; } bits; } register_info_type; #define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) #define IS_ACTIVE(R) ((R).bits.is_active) #define MATCHED_SOMETHING(R) ((R).bits.matched_something) #define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) /* Call this when have matched a real character; it sets `matched' flags for the subexpressions which we are currently inside. Also records that those subexprs have matched. */ #define SET_REGS_MATCHED() \ do \ { \ unsigned r; \ for (r = lowest_active_reg; r <= highest_active_reg; r++) \ { \ MATCHED_SOMETHING (reg_info[r]) \ = EVER_MATCHED_SOMETHING (reg_info[r]) \ = 1; \ } \ } \ while (0) /* This converts PTR, a pointer into one of the search strings `string1' and `string2' into an offset from the beginning of that string. */ #define POINTER_TO_OFFSET(ptr) \ (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1) /* Registers are set to a sentinel when they haven't yet matched. */ #define REG_UNSET_VALUE ((char *) -1) #define REG_UNSET(e) ((e) == REG_UNSET_VALUE) /* Macros for dealing with the split strings in re_match_2. */ #define MATCHING_IN_FIRST_STRING (dend == end_match_1) /* Call before fetching a character with *d. This switches over to string2 if necessary. */ #define PREFETCH() \ while (d == dend) \ { \ /* End of string2 => fail. */ \ if (dend == end_match_2) \ goto fail; \ /* End of string1 => advance to string2. */ \ d = string2; \ dend = end_match_2; \ } /* Test if at very beginning or at very end of the virtual concatenation of `string1' and `string2'. If only one string, it's `string2'. */ #define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) #define AT_STRINGS_END(d) ((d) == end2) /* Test if D points to a character which is word-constituent. We have two special cases to check for: if past the end of string1, look at the first character in string2; and if before the beginning of string2, look at the last character in string1. */ #define WORDCHAR_P(d) \ (SYNTAX ((d) == end1 ? *string2 \ : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ == Sword) /* Test if the character before D and the one at D differ with respect to being word-constituent. */ #define AT_WORD_BOUNDARY(d) \ (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) /* Free everything we malloc. */ #ifdef REGEX_MALLOC #define FREE_VAR(var) if (var) free (var); var = NULL #define FREE_VARIABLES() \ do { \ FREE_VAR (fail_stack.stack); \ FREE_VAR (regstart); \ FREE_VAR (regend); \ FREE_VAR (old_regstart); \ FREE_VAR (old_regend); \ FREE_VAR (best_regstart); \ FREE_VAR (best_regend); \ FREE_VAR (reg_info); \ FREE_VAR (reg_dummy); \ FREE_VAR (reg_info_dummy); \ } while (0) #else /* not REGEX_MALLOC */ /* Some MIPS systems (at least) want this to free alloca'd storage. */ #define FREE_VARIABLES() alloca (0) #endif /* not REGEX_MALLOC */ /* These values must meet several constraints. They must not be valid register values; since we have a limit of 255 registers (because we use only one byte in the pattern for the register number), we can use numbers larger than 255. They must differ by 1, because of NUM_FAILURE_ITEMS above. And the value for the lowest register must be larger than the value for the highest register, so we do not try to actually save any registers when none are active. */ #define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) #define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) /* Matching routines. */ #ifndef emacs /* Emacs never uses this. */ /* re_match is like re_match_2 except it takes only a single string. */ int re_match (bufp, string, size, pos, regs) struct re_pattern_buffer *bufp; char *string; int size, pos; struct re_registers *regs; { return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size); } #endif /* not emacs */ /* re_match_2 matches the compiled pattern in BUFP against the the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 and SIZE2, respectively). We start matching at POS, and stop matching at STOP. If REGS is non-null and the `no_sub' field of BUFP is nonzero, we store offsets for the substring each group matched in REGS. See the documentation for exactly how many groups we fill. We return -1 if no match, -2 if an internal error (such as the failure stack overflowing). Otherwise, we return the length of the matched substring. */ int re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) struct re_pattern_buffer *bufp; char *string1, *string2; int size1, size2; int pos; struct re_registers *regs; int stop; { /* General temporaries. */ int mcnt; unsigned char *p1; /* Just past the end of the corresponding string. */ char *end1, *end2; /* Pointers into string1 and string2, just past the last characters in each to consider matching. */ char *end_match_1, *end_match_2; /* Where we are in the data, and the end of the current string. */ char *d, *dend; /* Where we are in the pattern, and the end of the pattern. */ unsigned char *p = bufp->buffer; register unsigned char *pend = p + bufp->used; /* We use this to map every character in the string. */ char *translate = bufp->translate; /* Failure point stack. Each place that can handle a failure further down the line pushes a failure point on this stack. It consists of restart, regend, and reg_info for all registers corresponding to the subexpressions we're currently inside, plus the number of such registers, and, finally, two char *'s. The first char * is where to resume scanning the pattern; the second one is where to resume scanning the strings. If the latter is zero, the failure point is a ``dummy''; if a failure happens and the failure point is a dummy, it gets discarded and the next next one is tried. */ fail_stack_type fail_stack; #ifdef DEBUG static unsigned failure_id = 0; unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; #endif /* We fill all the registers internally, independent of what we return, for use in backreferences. The number here includes an element for register zero. */ unsigned num_regs = bufp->re_nsub + 1; /* The currently active registers. */ unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG; unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG; /* Information on the contents of registers. These are pointers into the input strings; they record just what was matched (on this attempt) by a subexpression part of the pattern, that is, the regnum-th regstart pointer points to where in the pattern we began matching and the regnum-th regend points to right after where we stopped matching the regnum-th subexpression. (The zeroth register keeps track of what the whole pattern matches.) */ char **regstart, **regend; /* If a group that's operated upon by a repetition operator fails to match anything, then the register for its start will need to be restored because it will have been set to wherever in the string we are when we last see its open-group operator. Similarly for a register's end. */ char **old_regstart, **old_regend; /* The is_active field of reg_info helps us keep track of which (possibly nested) subexpressions we are currently in. The matched_something field of reg_info[reg_num] helps us tell whether or not we have matched any of the pattern so far this time through the reg_num-th subexpression. These two fields get reset each time through any loop their register is in. */ register_info_type *reg_info; /* The following record the register info as found in the above variables when we find a match better than any we've seen before. This happens as we backtrack through the failure points, which in turn happens only if we have not yet matched the entire string. */ unsigned best_regs_set = false; char **best_regstart, **best_regend; /* Logically, this is `best_regend[0]'. But we don't want to have to allocate space for that if we're not allocating space for anything else (see below). Also, we never need info about register 0 for any of the other register vectors, and it seems rather a kludge to treat `best_regend' differently than the rest. So we keep track of the end of the best match so far in a separate variable. We initialize this to NULL so that when we backtrack the first time and need to test it, it's not garbage. */ char *match_end = NULL; /* Used when we pop values we don't care about. */ char **reg_dummy; register_info_type *reg_info_dummy; #ifdef DEBUG /* Counts the total number of registers pushed. */ unsigned num_regs_pushed = 0; #endif DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); INIT_FAIL_STACK (); /* Do not bother to initialize all the register variables if there are no groups in the pattern, as it takes a fair amount of time. If there are groups, we include space for register 0 (the whole pattern), even though we never use it, since it simplifies the array indexing. We should fix this. */ if (bufp->re_nsub) { regstart = REGEX_TALLOC (num_regs, char *); regend = REGEX_TALLOC (num_regs, char *); old_regstart = REGEX_TALLOC (num_regs, char *); old_regend = REGEX_TALLOC (num_regs, char *); best_regstart = REGEX_TALLOC (num_regs, char *); best_regend = REGEX_TALLOC (num_regs, char *); reg_info = REGEX_TALLOC (num_regs, register_info_type); reg_dummy = REGEX_TALLOC (num_regs, char *); reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type); if (!(regstart && regend && old_regstart && old_regend && reg_info && best_regstart && best_regend && reg_dummy && reg_info_dummy)) { FREE_VARIABLES (); return -2; } } #ifdef REGEX_MALLOC else { /* We must initialize all our variables to NULL, so that `FREE_VARIABLES' doesn't try to free them. */ regstart = regend = old_regstart = old_regend = best_regstart = best_regend = reg_dummy = NULL; reg_info = reg_info_dummy = (register_info_type *) NULL; } #endif /* REGEX_MALLOC */ /* The starting position is bogus. */ if (pos < 0 || pos > size1 + size2) { FREE_VARIABLES (); return -1; } /* Initialize subexpression text positions to -1 to mark ones that no start_memory/stop_memory has been seen for. Also initialize the register information struct. */ for (mcnt = 1; mcnt < num_regs; mcnt++) { regstart[mcnt] = regend[mcnt] = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; IS_ACTIVE (reg_info[mcnt]) = 0; MATCHED_SOMETHING (reg_info[mcnt]) = 0; EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; } /* We move `string1' into `string2' if the latter's empty -- but not if `string1' is null. */ if (size2 == 0 && string1 != NULL) { string2 = string1; size2 = size1; string1 = 0; size1 = 0; } end1 = string1 + size1; end2 = string2 + size2; /* Compute where to stop matching, within the two strings. */ if (stop <= size1) { end_match_1 = string1 + stop; end_match_2 = string2; } else { end_match_1 = end1; end_match_2 = string2 + stop - size1; } /* `p' scans through the pattern as `d' scans through the data. `dend' is the end of the input string that `d' points within. `d' is advanced into the following input string whenever necessary, but this happens before fetching; therefore, at the beginning of the loop, `d' can be pointing at the end of a string, but it cannot equal `string2'. */ if (size1 > 0 && pos <= size1) { d = string1 + pos; dend = end_match_1; } else { d = string2 + pos - size1; dend = end_match_2; } DEBUG_PRINT1 ("The compiled pattern is: "); DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); DEBUG_PRINT1 ("The string to match is: `"); DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); DEBUG_PRINT1 ("'\n"); /* This loops over pattern commands. It exits by returning from the function if the match is complete, or it drops through if the match fails at this starting point in the input data. */ for (;;) { DEBUG_PRINT2 ("\n0x%x: ", p); if (p == pend) { /* End of pattern means we might have succeeded. */ DEBUG_PRINT1 ("end of pattern ... "); /* If we haven't matched the entire string, and we want the longest match, try backtracking. */ if (d != end_match_2) { DEBUG_PRINT1 ("backtracking.\n"); if (!FAIL_STACK_EMPTY ()) { /* More failure points to try. */ boolean same_str_p = (FIRST_STRING_P (match_end) == MATCHING_IN_FIRST_STRING); /* If exceeds best match so far, save it. */ if (!best_regs_set || (same_str_p && d > match_end) || (!same_str_p && !MATCHING_IN_FIRST_STRING)) { best_regs_set = true; match_end = d; DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); for (mcnt = 1; mcnt < num_regs; mcnt++) { best_regstart[mcnt] = regstart[mcnt]; best_regend[mcnt] = regend[mcnt]; } } goto fail; } /* If no failure points, don't restore garbage. */ else if (best_regs_set) { restore_best_regs: /* Restore best match. It may happen that `dend == end_match_1' while the restored d is in string2. For example, the pattern `x.*y.*z' against the strings `x-' and `y-z-', if the two strings are not consecutive in memory. */ DEBUG_PRINT1 ("Restoring best registers.\n"); d = match_end; dend = ((d >= string1 && d <= end1) ? end_match_1 : end_match_2); for (mcnt = 1; mcnt < num_regs; mcnt++) { regstart[mcnt] = best_regstart[mcnt]; regend[mcnt] = best_regend[mcnt]; } } } /* d != end_match_2 */ DEBUG_PRINT1 ("Accepting match.\n"); /* If caller wants register contents data back, do it. */ if (regs && !bufp->no_sub) { /* Have the register data arrays been allocated? */ if (bufp->regs_allocated == REGS_UNALLOCATED) { /* No. So allocate them with malloc. We need one extra element beyond `num_regs' for the `-1' marker GNU code uses. */ regs->num_regs = MAX (RE_NREGS, num_regs + 1); regs->start = TALLOC (regs->num_regs, regoff_t); regs->end = TALLOC (regs->num_regs, regoff_t); if (regs->start == NULL || regs->end == NULL) return -2; bufp->regs_allocated = REGS_REALLOCATE; } else if (bufp->regs_allocated == REGS_REALLOCATE) { /* Yes. If we need more elements than were already allocated, reallocate them. If we need fewer, just leave it alone. */ if (regs->num_regs < num_regs + 1) { regs->num_regs = num_regs + 1; RETALLOC (regs->start, regs->num_regs, regoff_t); RETALLOC (regs->end, regs->num_regs, regoff_t); if (regs->start == NULL || regs->end == NULL) return -2; } } else assert (bufp->regs_allocated == REGS_FIXED); /* Convert the pointer data in `regstart' and `regend' to indices. Register zero has to be set differently, since we haven't kept track of any info for it. */ if (regs->num_regs > 0) { regs->start[0] = pos; regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1 : d - string2 + size1); } /* Go through the first `min (num_regs, regs->num_regs)' registers, since that is all we initialized. */ for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++) { if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) regs->start[mcnt] = regs->end[mcnt] = -1; else { regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]); regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]); } } /* If the regs structure we return has more elements than were in the pattern, set the extra elements to -1. If we (re)allocated the registers, this is the case, because we always allocate enough to have at least one -1 at the end. */ for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++) regs->start[mcnt] = regs->end[mcnt] = -1; } /* regs && !bufp->no_sub */ FREE_VARIABLES (); DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", nfailure_points_pushed, nfailure_points_popped, nfailure_points_pushed - nfailure_points_popped); DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); mcnt = d - pos - (MATCHING_IN_FIRST_STRING ? string1 : string2 - size1); DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); return mcnt; } /* Otherwise match next pattern command. */ #ifdef SWITCH_ENUM_BUG switch ((int) ((re_opcode_t) *p++)) #else switch ((re_opcode_t) *p++) #endif { /* Ignore these. Used to ignore the n of succeed_n's which currently have n == 0. */ case no_op: DEBUG_PRINT1 ("EXECUTING no_op.\n"); break; /* Match the next n pattern characters exactly. The following byte in the pattern defines n, and the n bytes after that are the characters to match. */ case exactn: mcnt = *p++; DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); /* This is written out as an if-else so we don't waste time testing `translate' inside the loop. */ if (translate) { do { PREFETCH (); if (translate[(unsigned char) *d++] != (char) *p++) goto fail; } while (--mcnt); } else { do { PREFETCH (); if (*d++ != (char) *p++) goto fail; } while (--mcnt); } SET_REGS_MATCHED (); break; /* Match any character except possibly a newline or a null. */ case anychar: DEBUG_PRINT1 ("EXECUTING anychar.\n"); PREFETCH (); if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) goto fail; SET_REGS_MATCHED (); DEBUG_PRINT2 (" Matched `%d'.\n", *d); d++; break; case charset: case charset_not: { register unsigned char c; boolean not = (re_opcode_t) *(p - 1) == charset_not; DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); PREFETCH (); c = TRANSLATE (*d); /* The character to match. */ /* Cast to `unsigned' instead of `unsigned char' in case the bit list is a full 32 bytes long. */ if (c < (unsigned) (*p * BYTEWIDTH) && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) not = !not; p += 1 + *p; if (!not) goto fail; SET_REGS_MATCHED (); d++; break; } /* The beginning of a group is represented by start_memory. The arguments are the register number in the next byte, and the number of groups inner to this one in the next. The text matched within the group is recorded (in the internal registers data structure) under the register number. */ case start_memory: DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]); /* Find out if this group can match the empty string. */ p1 = p; /* To send to group_match_null_string_p. */ if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) REG_MATCH_NULL_STRING_P (reg_info[*p]) = group_match_null_string_p (&p1, pend, reg_info); /* Save the position in the string where we were the last time we were at this open-group operator in case the group is operated upon by a repetition operator, e.g., with `(a*)*b' against `ab'; then we want to ignore where we are now in the string in case this attempt to match fails. */ old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) ? REG_UNSET (regstart[*p]) ? d : regstart[*p] : regstart[*p]; DEBUG_PRINT2 (" old_regstart: %d\n", POINTER_TO_OFFSET (old_regstart[*p])); regstart[*p] = d; DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); IS_ACTIVE (reg_info[*p]) = 1; MATCHED_SOMETHING (reg_info[*p]) = 0; /* This is the new highest active register. */ highest_active_reg = *p; /* If nothing was active before, this is the new lowest active register. */ if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) lowest_active_reg = *p; /* Move past the register number and inner group count. */ p += 2; break; /* The stop_memory opcode represents the end of a group. Its arguments are the same as start_memory's: the register number, and the number of inner groups. */ case stop_memory: DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]); /* We need to save the string position the last time we were at this close-group operator in case the group is operated upon by a repetition operator, e.g., with `((a*)*(b*)*)*' against `aba'; then we want to ignore where we are now in the string in case this attempt to match fails. */ old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) ? REG_UNSET (regend[*p]) ? d : regend[*p] : regend[*p]; DEBUG_PRINT2 (" old_regend: %d\n", POINTER_TO_OFFSET (old_regend[*p])); regend[*p] = d; DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); /* This register isn't active anymore. */ IS_ACTIVE (reg_info[*p]) = 0; /* If this was the only register active, nothing is active anymore. */ if (lowest_active_reg == highest_active_reg) { lowest_active_reg = NO_LOWEST_ACTIVE_REG; highest_active_reg = NO_HIGHEST_ACTIVE_REG; } else { /* We must scan for the new highest active register, since it isn't necessarily one less than now: consider (a(b)c(d(e)f)g). When group 3 ends, after the f), the new highest active register is 1. */ unsigned char r = *p - 1; while (r > 0 && !IS_ACTIVE (reg_info[r])) r--; /* If we end up at register zero, that means that we saved the registers as the result of an `on_failure_jump', not a `start_memory', and we jumped to past the innermost `stop_memory'. For example, in ((.)*) we save registers 1 and 2 as a result of the *, but when we pop back to the second ), we are at the stop_memory 1. Thus, nothing is active. */ if (r == 0) { lowest_active_reg = NO_LOWEST_ACTIVE_REG; highest_active_reg = NO_HIGHEST_ACTIVE_REG; } else highest_active_reg = r; } /* If just failed to match something this time around with a group that's operated on by a repetition operator, try to force exit from the ``loop'', and restore the register information for this group that we had before trying this last match. */ if ((!MATCHED_SOMETHING (reg_info[*p]) || (re_opcode_t) p[-3] == start_memory) && (p + 2) < pend) { boolean is_a_jump_n = false; p1 = p + 2; mcnt = 0; switch ((re_opcode_t) *p1++) { case jump_n: is_a_jump_n = true; case pop_failure_jump: case maybe_pop_jump: case jump: case dummy_failure_jump: EXTRACT_NUMBER_AND_INCR (mcnt, p1); if (is_a_jump_n) p1 += 2; break; default: /* do nothing */ ; } p1 += mcnt; /* If the next operation is a jump backwards in the pattern to an on_failure_jump right before the start_memory corresponding to this stop_memory, exit from the loop by forcing a failure after pushing on the stack the on_failure_jump's jump in the pattern, and d. */ if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump && (re_opcode_t) p1[3] == start_memory && p1[4] == *p) { /* If this group ever matched anything, then restore what its registers were before trying this last failed match, e.g., with `(a*)*b' against `ab' for regstart[1], and, e.g., with `((a*)*(b*)*)*' against `aba' for regend[3]. Also restore the registers for inner groups for, e.g., `((a*)(b*))*' against `aba' (register 3 would otherwise get trashed). */ if (EVER_MATCHED_SOMETHING (reg_info[*p])) { unsigned r; EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; /* Restore this and inner groups' (if any) registers. */ for (r = *p; r < *p + *(p + 1); r++) { regstart[r] = old_regstart[r]; /* xx why this test? */ if ((int) old_regend[r] >= (int) regstart[r]) regend[r] = old_regend[r]; } } p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); PUSH_FAILURE_POINT (p1 + mcnt, d, -2); goto fail; } } /* Move past the register number and the inner group count. */ p += 2; break; /* \ has been turned into a `duplicate' command which is followed by the numeric value of as the register number. */ case duplicate: { register char *d2, *dend2; int regno = *p++; /* Get which register to match against. */ DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); /* Can't back reference a group which we've never matched. */ if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) goto fail; /* Where in input to try to start matching. */ d2 = regstart[regno]; /* Where to stop matching; if both the place to start and the place to stop matching are in the same string, then set to the place to stop, otherwise, for now have to use the end of the first string. */ dend2 = ((FIRST_STRING_P (regstart[regno]) == FIRST_STRING_P (regend[regno])) ? regend[regno] : end_match_1); for (;;) { /* If necessary, advance to next segment in register contents. */ while (d2 == dend2) { if (dend2 == end_match_2) break; if (dend2 == regend[regno]) break; /* End of string1 => advance to string2. */ d2 = string2; dend2 = regend[regno]; } /* At end of register contents => success */ if (d2 == dend2) break; /* If necessary, advance to next segment in data. */ PREFETCH (); /* How many characters left in this segment to match. */ mcnt = dend - d; /* Want how many consecutive characters we can match in one shot, so, if necessary, adjust the count. */ if (mcnt > dend2 - d2) mcnt = dend2 - d2; /* Compare that many; failure if mismatch, else move past them. */ if (translate ? bcmp_translate (d, d2, mcnt, translate) : bcmp (d, d2, mcnt)) goto fail; d += mcnt, d2 += mcnt; } } break; /* begline matches the empty string at the beginning of the string (unless `not_bol' is set in `bufp'), and, if `newline_anchor' is set, after newlines. */ case begline: DEBUG_PRINT1 ("EXECUTING begline.\n"); if (AT_STRINGS_BEG (d)) { if (!bufp->not_bol) break; } else if (d[-1] == '\n' && bufp->newline_anchor) { break; } /* In all other cases, we fail. */ goto fail; /* endline is the dual of begline. */ case endline: DEBUG_PRINT1 ("EXECUTING endline.\n"); if (AT_STRINGS_END (d)) { if (!bufp->not_eol) break; } /* We have to ``prefetch'' the next character. */ else if ((d == end1 ? *string2 : *d) == '\n' && bufp->newline_anchor) { break; } goto fail; /* Match at the very beginning of the data. */ case begbuf: DEBUG_PRINT1 ("EXECUTING begbuf.\n"); if (AT_STRINGS_BEG (d)) break; goto fail; /* Match at the very end of the data. */ case endbuf: DEBUG_PRINT1 ("EXECUTING endbuf.\n"); if (AT_STRINGS_END (d)) break; goto fail; /* on_failure_keep_string_jump is used to optimize `.*\n'. It pushes NULL as the value for the string on the stack. Then `pop_failure_point' will keep the current value for the string, instead of restoring it. To see why, consider matching `foo\nbar' against `.*\n'. The .* matches the foo; then the . fails against the \n. But the next thing we want to do is match the \n against the \n; if we restored the string value, we would be back at the foo. Because this is used only in specific cases, we don't need to check all the things that `on_failure_jump' does, to make sure the right things get saved on the stack. Hence we don't share its code. The only reason to push anything on the stack at all is that otherwise we would have to change `anychar's code to do something besides goto fail in this case; that seems worse than this. */ case on_failure_keep_string_jump: DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); EXTRACT_NUMBER_AND_INCR (mcnt, p); DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); PUSH_FAILURE_POINT (p + mcnt, NULL, -2); break; /* Uses of on_failure_jump: Each alternative starts with an on_failure_jump that points to the beginning of the next alternative. Each alternative except the last ends with a jump that in effect jumps past the rest of the alternatives. (They really jump to the ending jump of the following alternative, because tensioning these jumps is a hassle.) Repeats start with an on_failure_jump that points past both the repetition text and either the following jump or pop_failure_jump back to this on_failure_jump. */ case on_failure_jump: on_failure: DEBUG_PRINT1 ("EXECUTING on_failure_jump"); EXTRACT_NUMBER_AND_INCR (mcnt, p); DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); /* If this on_failure_jump comes right before a group (i.e., the original * applied to a group), save the information for that group and all inner ones, so that if we fail back to this point, the group's information will be correct. For example, in \(a*\)*\1, we need the preceding group, and in \(\(a*\)b*\)\2, we need the inner group. */ /* We can't use `p' to check ahead because we push a failure point to `p + mcnt' after we do this. */ p1 = p; /* We need to skip no_op's before we look for the start_memory in case this on_failure_jump is happening as the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 against aba. */ while (p1 < pend && (re_opcode_t) *p1 == no_op) p1++; if (p1 < pend && (re_opcode_t) *p1 == start_memory) { /* We have a new highest active register now. This will get reset at the start_memory we are about to get to, but we will have saved all the registers relevant to this repetition op, as described above. */ highest_active_reg = *(p1 + 1) + *(p1 + 2); if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) lowest_active_reg = *(p1 + 1); } DEBUG_PRINT1 (":\n"); PUSH_FAILURE_POINT (p + mcnt, d, -2); break; /* A smart repeat ends with `maybe_pop_jump'. We change it to either `pop_failure_jump' or `jump'. */ case maybe_pop_jump: EXTRACT_NUMBER_AND_INCR (mcnt, p); DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); { register unsigned char *p2 = p; /* Compare the beginning of the repeat with what in the pattern follows its end. If we can establish that there is nothing that they would both match, i.e., that we would have to backtrack because of (as in, e.g., `a*a') then we can change to pop_failure_jump, because we'll never have to backtrack. This is not true in the case of alternatives: in `(a|ab)*' we do need to backtrack to the `ab' alternative (e.g., if the string was `ab'). But instead of trying to detect that here, the alternative has put on a dummy failure point which is what we will end up popping. */ /* Skip over open/close-group commands. */ while (p2 + 2 < pend && ((re_opcode_t) *p2 == stop_memory || (re_opcode_t) *p2 == start_memory)) p2 += 3; /* Skip over args, too. */ /* If we're at the end of the pattern, we can change. */ if (p2 == pend) { /* Consider what happens when matching ":\(.*\)" against ":/". I don't really understand this code yet. */ p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT1 (" End of pattern: change to `pop_failure_jump'.\n"); } else if ((re_opcode_t) *p2 == exactn || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) { register unsigned char c = *p2 == (unsigned char) endline ? '\n' : p2[2]; p1 = p + mcnt; /* p1[0] ... p1[2] are the `on_failure_jump' corresponding to the `maybe_finalize_jump' of this case. Examine what follows. */ if ((re_opcode_t) p1[3] == exactn && p1[5] != c) { p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", c, p1[5]); } else if ((re_opcode_t) p1[3] == charset || (re_opcode_t) p1[3] == charset_not) { int not = (re_opcode_t) p1[3] == charset_not; if (c < (unsigned char) (p1[4] * BYTEWIDTH) && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) not = !not; /* `not' is equal to 1 if c would match, which means that we can't change to pop_failure_jump. */ if (!not) { p[-3] = (unsigned char) pop_failure_jump; DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); } } } } p -= 2; /* Point at relative address again. */ if ((re_opcode_t) p[-1] != pop_failure_jump) { p[-1] = (unsigned char) jump; DEBUG_PRINT1 (" Match => jump.\n"); goto unconditional_jump; } /* Note fall through. */ /* The end of a simple repeat has a pop_failure_jump back to its matching on_failure_jump, where the latter will push a failure point. The pop_failure_jump takes off failure points put on by this pop_failure_jump's matching on_failure_jump; we got through the pattern to here from the matching on_failure_jump, so didn't fail. */ case pop_failure_jump: { /* We need to pass separate storage for the lowest and highest registers, even though we don't care about the actual values. Otherwise, we will restore only one register from the stack, since lowest will == highest in `pop_failure_point'. */ unsigned dummy_low_reg, dummy_high_reg; unsigned char *pdummy; char *sdummy; DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); POP_FAILURE_POINT (sdummy, pdummy, dummy_low_reg, dummy_high_reg, reg_dummy, reg_dummy, reg_info_dummy); } /* Note fall through. */ /* Unconditionally jump (without popping any failure points). */ case jump: unconditional_jump: EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); p += mcnt; /* Do the jump. */ DEBUG_PRINT2 ("(to 0x%x).\n", p); break; /* We need this opcode so we can detect where alternatives end in `group_match_null_string_p' et al. */ case jump_past_alt: DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); goto unconditional_jump; /* Normally, the on_failure_jump pushes a failure point, which then gets popped at pop_failure_jump. We will end up at pop_failure_jump, also, and with a pattern of, say, `a+', we are skipping over the on_failure_jump, so we have to push something meaningless for pop_failure_jump to pop. */ case dummy_failure_jump: DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); /* It doesn't matter what we push for the string here. What the code at `fail' tests is the value for the pattern. */ PUSH_FAILURE_POINT (0, 0, -2); goto unconditional_jump; /* At the end of an alternative, we need to push a dummy failure point in case we are followed by a `pop_failure_jump', because we don't want the failure point for the alternative to be popped. For example, matching `(a|ab)*' against `aab' requires that we match the `ab' alternative. */ case push_dummy_failure: DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); /* See comments just above at `dummy_failure_jump' about the two zeroes. */ PUSH_FAILURE_POINT (0, 0, -2); break; /* Have to succeed matching what follows at least n times. After that, handle like `on_failure_jump'. */ case succeed_n: EXTRACT_NUMBER (mcnt, p + 2); DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); assert (mcnt >= 0); /* Originally, this is how many times we HAVE to succeed. */ if (mcnt > 0) { mcnt--; p += 2; STORE_NUMBER_AND_INCR (p, mcnt); DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p, mcnt); } else if (mcnt == 0) { DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", p+2); p[2] = (unsigned char) no_op; p[3] = (unsigned char) no_op; goto on_failure; } break; case jump_n: EXTRACT_NUMBER (mcnt, p + 2); DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); /* Originally, this is how many times we CAN jump. */ if (mcnt) { mcnt--; STORE_NUMBER (p + 2, mcnt); goto unconditional_jump; } /* If don't have to jump any more, skip over the rest of command. */ else p += 4; break; case set_number_at: { DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); EXTRACT_NUMBER_AND_INCR (mcnt, p); p1 = p + mcnt; EXTRACT_NUMBER_AND_INCR (mcnt, p); DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); STORE_NUMBER (p1, mcnt); break; } case wordbound: DEBUG_PRINT1 ("EXECUTING wordbound.\n"); if (AT_WORD_BOUNDARY (d)) break; goto fail; case notwordbound: DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); if (AT_WORD_BOUNDARY (d)) goto fail; break; case wordbeg: DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) break; goto fail; case wordend: DEBUG_PRINT1 ("EXECUTING wordend.\n"); if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) && (!WORDCHAR_P (d) || AT_STRINGS_END (d))) break; goto fail; #ifdef emacs #ifdef emacs19 case before_dot: DEBUG_PRINT1 ("EXECUTING before_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) >= point) goto fail; break; case at_dot: DEBUG_PRINT1 ("EXECUTING at_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) != point) goto fail; break; case after_dot: DEBUG_PRINT1 ("EXECUTING after_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) <= point) goto fail; break; #else /* not emacs19 */ case at_dot: DEBUG_PRINT1 ("EXECUTING at_dot.\n"); if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point) goto fail; break; #endif /* not emacs19 */ case syntaxspec: DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); mcnt = *p++; goto matchsyntax; case wordchar: DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); mcnt = (int) Sword; matchsyntax: PREFETCH (); if (SYNTAX (*d++) != (enum syntaxcode) mcnt) goto fail; SET_REGS_MATCHED (); break; case notsyntaxspec: DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); mcnt = *p++; goto matchnotsyntax; case notwordchar: DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); mcnt = (int) Sword; matchnotsyntax: PREFETCH (); if (SYNTAX (*d++) == (enum syntaxcode) mcnt) goto fail; SET_REGS_MATCHED (); break; #else /* not emacs */ case wordchar: DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); PREFETCH (); if (!WORDCHAR_P (d)) goto fail; SET_REGS_MATCHED (); d++; break; case notwordchar: DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); PREFETCH (); if (WORDCHAR_P (d)) goto fail; SET_REGS_MATCHED (); d++; break; #endif /* not emacs */ default: abort (); } continue; /* Successfully executed one pattern command; keep going. */ /* We goto here if a matching operation fails. */ fail: if (!FAIL_STACK_EMPTY ()) { /* A restart point is known. Restore to that state. */ DEBUG_PRINT1 ("\nFAIL:\n"); POP_FAILURE_POINT (d, p, lowest_active_reg, highest_active_reg, regstart, regend, reg_info); /* If this failure point is a dummy, try the next one. */ if (!p) goto fail; /* If we failed to the end of the pattern, don't examine *p. */ assert (p <= pend); if (p < pend) { boolean is_a_jump_n = false; /* If failed to a backwards jump that's part of a repetition loop, need to pop this failure point and use the next one. */ switch ((re_opcode_t) *p) { case jump_n: is_a_jump_n = true; case maybe_pop_jump: case pop_failure_jump: case jump: p1 = p + 1; EXTRACT_NUMBER_AND_INCR (mcnt, p1); p1 += mcnt; if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) || (!is_a_jump_n && (re_opcode_t) *p1 == on_failure_jump)) goto fail; break; default: /* do nothing */ ; } } if (d >= string1 && d <= end1) dend = end_match_1; } else break; /* Matching at this starting point really fails. */ } /* for (;;) */ if (best_regs_set) goto restore_best_regs; FREE_VARIABLES (); return -1; /* Failure to match. */ } /* re_match_2 */ /* Subroutine definitions for re_match_2. */ /* We are passed P pointing to a register number after a start_memory. Return true if the pattern up to the corresponding stop_memory can match the empty string, and false otherwise. If we find the matching stop_memory, sets P to point to one past its number. Otherwise, sets P to an undefined byte less than or equal to END. We don't handle duplicates properly (yet). */ static boolean group_match_null_string_p (p, end, reg_info) unsigned char **p, *end; register_info_type *reg_info; { int mcnt; /* Point to after the args to the start_memory. */ unsigned char *p1 = *p + 2; while (p1 < end) { /* Skip over opcodes that can match nothing, and return true or false, as appropriate, when we get to one that can't, or to the matching stop_memory. */ switch ((re_opcode_t) *p1) { /* Could be either a loop or a series of alternatives. */ case on_failure_jump: p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); /* If the next operation is not a jump backwards in the pattern. */ if (mcnt >= 0) { /* Go through the on_failure_jumps of the alternatives, seeing if any of the alternatives cannot match nothing. The last alternative starts with only a jump, whereas the rest start with on_failure_jump and end with a jump, e.g., here is the pattern for `a|b|c': /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 /exactn/1/c So, we have to first go through the first (n-1) alternatives and then deal with the last one separately. */ /* Deal with the first (n-1) alternatives, which start with an on_failure_jump (see above) that jumps to right past a jump_past_alt. */ while ((re_opcode_t) p1[mcnt-3] == jump_past_alt) { /* `mcnt' holds how many bytes long the alternative is, including the ending `jump_past_alt' and its number. */ if (!alt_match_null_string_p (p1, p1 + mcnt - 3, reg_info)) return false; /* Move to right after this alternative, including the jump_past_alt. */ p1 += mcnt; /* Break if it's the beginning of an n-th alternative that doesn't begin with an on_failure_jump. */ if ((re_opcode_t) *p1 != on_failure_jump) break; /* Still have to check that it's not an n-th alternative that starts with an on_failure_jump. */ p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); if ((re_opcode_t) p1[mcnt-3] != jump_past_alt) { /* Get to the beginning of the n-th alternative. */ p1 -= 3; break; } } /* Deal with the last alternative: go back and get number of the `jump_past_alt' just before it. `mcnt' contains the length of the alternative. */ EXTRACT_NUMBER (mcnt, p1 - 2); if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info)) return false; p1 += mcnt; /* Get past the n-th alternative. */ } /* if mcnt > 0 */ break; case stop_memory: assert (p1[1] == **p); *p = p1 + 2; return true; default: if (!common_op_match_null_string_p (&p1, end, reg_info)) return false; } } /* while p1 < end */ return false; } /* group_match_null_string_p */ /* Similar to group_match_null_string_p, but doesn't deal with alternatives: It expects P to be the first byte of a single alternative and END one byte past the last. The alternative can contain groups. */ static boolean alt_match_null_string_p (p, end, reg_info) unsigned char *p, *end; register_info_type *reg_info; { int mcnt; unsigned char *p1 = p; while (p1 < end) { /* Skip over opcodes that can match nothing, and break when we get to one that can't. */ switch ((re_opcode_t) *p1) { /* It's a loop. */ case on_failure_jump: p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); p1 += mcnt; break; default: if (!common_op_match_null_string_p (&p1, end, reg_info)) return false; } } /* while p1 < end */ return true; } /* alt_match_null_string_p */ /* Deals with the ops common to group_match_null_string_p and alt_match_null_string_p. Sets P to one after the op and its arguments, if any. */ static boolean common_op_match_null_string_p (p, end, reg_info) unsigned char **p, *end; register_info_type *reg_info; { int mcnt; boolean ret; int reg_no; unsigned char *p1 = *p; switch ((re_opcode_t) *p1++) { case no_op: case begline: case endline: case begbuf: case endbuf: case wordbeg: case wordend: case wordbound: case notwordbound: #ifdef emacs case before_dot: case at_dot: case after_dot: #endif break; case start_memory: reg_no = *p1; assert (reg_no > 0 && reg_no <= MAX_REGNUM); ret = group_match_null_string_p (&p1, end, reg_info); /* Have to set this here in case we're checking a group which contains a group and a back reference to it. */ if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; if (!ret) return false; break; /* If this is an optimized succeed_n for zero times, make the jump. */ case jump: EXTRACT_NUMBER_AND_INCR (mcnt, p1); if (mcnt >= 0) p1 += mcnt; else return false; break; case succeed_n: /* Get to the number of times to succeed. */ p1 += 2; EXTRACT_NUMBER_AND_INCR (mcnt, p1); if (mcnt == 0) { p1 -= 4; EXTRACT_NUMBER_AND_INCR (mcnt, p1); p1 += mcnt; } else return false; break; case duplicate: if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) return false; break; case set_number_at: p1 += 4; default: /* All other opcodes mean we cannot match the empty string. */ return false; } *p = p1; return true; } /* common_op_match_null_string_p */ /* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN bytes; nonzero otherwise. */ static int bcmp_translate (s1, s2, len, translate) unsigned char *s1, *s2; register int len; char *translate; { register unsigned char *p1 = s1, *p2 = s2; while (len) { if (translate[*p1++] != translate[*p2++]) return 1; len--; } return 0; } /* Entry points for GNU code. */ /* re_compile_pattern is the GNU regular expression compiler: it compiles PATTERN (of length SIZE) and puts the result in BUFP. Returns 0 if the pattern was valid, otherwise an error string. Assumes the `allocated' (and perhaps `buffer') and `translate' fields are set in BUFP on entry. We call regex_compile to do the actual compilation. */ /* Mark: removed const from char */ char * re_compile_pattern (pattern, length, bufp) char *pattern; int length; struct re_pattern_buffer *bufp; { reg_errcode_t ret; /* GNU code is written to assume at least RE_NREGS registers will be set (and at least one extra will be -1). */ bufp->regs_allocated = REGS_UNALLOCATED; /* And GNU code determines whether or not to get register information by passing null for the REGS argument to re_match, etc., not by setting no_sub. */ bufp->no_sub = 0; /* Match anchors at newline. */ bufp->newline_anchor = 1; ret = regex_compile (pattern, length, re_syntax_options, bufp); return (char *) re_error_msg[(int) ret]; } /* Entry points compatible with 4.2 BSD regex library. We don't define them if this is an Emacs or POSIX compilation. */ #if !defined (emacs) && !defined (_POSIX_SOURCE) /* BSD has one and only one pattern buffer. */ static struct re_pattern_buffer re_comp_buf; char * re_comp (s) char *s; { reg_errcode_t ret; if (!s) { if (!re_comp_buf.buffer) return "No previous regular expression"; return 0; } if (!re_comp_buf.buffer) { re_comp_buf.buffer = (unsigned char *) malloc (200); if (re_comp_buf.buffer == NULL) return "Memory exhausted"; re_comp_buf.allocated = 200; re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); if (re_comp_buf.fastmap == NULL) return "Memory exhausted"; } /* Since `re_exec' always passes NULL for the `regs' argument, we don't need to initialize the pattern buffer fields which affect it. */ /* Match anchors at newlines. */ re_comp_buf.newline_anchor = 1; ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); /* Yes, we're discarding `const' here. */ return (char *) re_error_msg[(int) ret]; } int re_exec (s) char *s; { int len = strlen (s); return 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); } #endif /* not emacs and not _POSIX_SOURCE */ /* POSIX.2 functions. Don't define these for Emacs. */ #ifndef emacs /* regcomp takes a regular expression as a string and compiles it. PREG is a regex_t *. We do not expect any fields to be initialized, since POSIX says we shouldn't. Thus, we set `buffer' to the compiled pattern; `used' to the length of the compiled pattern; `syntax' to RE_SYNTAX_POSIX_EXTENDED if the REG_EXTENDED bit in CFLAGS is set; otherwise, to RE_SYNTAX_POSIX_BASIC; `newline_anchor' to REG_NEWLINE being set in CFLAGS; `fastmap' and `fastmap_accurate' to zero; `re_nsub' to the number of subexpressions in PATTERN. PATTERN is the address of the pattern string. CFLAGS is a series of bits which affect compilation. If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we use POSIX basic syntax. If REG_NEWLINE is set, then . and [^...] don't match newline. Also, regexec will try a match beginning after every newline. If REG_ICASE is set, then we considers upper- and lowercase versions of letters to be equivalent when matching. If REG_NOSUB is set, then when PREG is passed to regexec, that routine will report only success or failure, and nothing about the registers. It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for the return codes and their meanings.) */ int regcomp (preg, pattern, cflags) regex_t *preg; char *pattern; int cflags; { reg_errcode_t ret; unsigned syntax = (cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; /* regex_compile will allocate the space for the compiled pattern. */ preg->buffer = 0; preg->allocated = 0; /* Don't bother to use a fastmap when searching. This simplifies the REG_NEWLINE case: if we used a fastmap, we'd have to put all the characters after newlines into the fastmap. This way, we just try every character. */ preg->fastmap = 0; if (cflags & REG_ICASE) { unsigned i; preg->translate = (char *) malloc (CHAR_SET_SIZE); if (preg->translate == NULL) return (int) REG_ESPACE; /* Map uppercase characters to corresponding lowercase ones. */ for (i = 0; i < CHAR_SET_SIZE; i++) preg->translate[i] = ISUPPER (i) ? tolower (i) : i; } else preg->translate = NULL; /* If REG_NEWLINE is set, newlines are treated differently. */ if (cflags & REG_NEWLINE) { /* REG_NEWLINE implies neither . nor [^...] match newline. */ syntax &= ~RE_DOT_NEWLINE; syntax |= RE_HAT_LISTS_NOT_NEWLINE; /* It also changes the matching behavior. */ preg->newline_anchor = 1; } else preg->newline_anchor = 0; preg->no_sub = !!(cflags & REG_NOSUB); /* POSIX says a null character in the pattern terminates it, so we can use strlen here in compiling the pattern. */ ret = regex_compile (pattern, strlen (pattern), syntax, preg); /* POSIX doesn't distinguish between an unmatched open-group and an unmatched close-group: both are REG_EPAREN. */ if (ret == REG_ERPAREN) ret = REG_EPAREN; return (int) ret; } /* regexec searches for a given pattern, specified by PREG, in the string STRING. If NMATCH is zero or REG_NOSUB was set in the cflags argument to `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at least NMATCH elements, and we set them to the offsets of the corresponding matched substrings. EFLAGS specifies `execution flags' which affect matching: if REG_NOTBOL is set, then ^ does not match at the beginning of the string; if REG_NOTEOL is set, then $ does not match at the end. We return 0 if we find a match and REG_NOMATCH if not. */ int regexec (preg, string, nmatch, pmatch, eflags) regex_t *preg; char *string; size_t nmatch; regmatch_t pmatch[]; int eflags; { int ret; struct re_registers regs; regex_t private_preg; int len = strlen (string); boolean want_reg_info = !preg->no_sub && nmatch > 0; private_preg = *preg; private_preg.not_bol = !!(eflags & REG_NOTBOL); private_preg.not_eol = !!(eflags & REG_NOTEOL); /* The user has told us exactly how many registers to return information about, via `nmatch'. We have to pass that on to the matching routines. */ private_preg.regs_allocated = REGS_FIXED; if (want_reg_info) { regs.num_regs = nmatch; regs.start = TALLOC (nmatch, regoff_t); regs.end = TALLOC (nmatch, regoff_t); if (regs.start == NULL || regs.end == NULL) return (int) REG_NOMATCH; } /* Perform the searching operation. */ ret = re_search (&private_preg, string, len, /* start: */ 0, /* range: */ len, want_reg_info ? ®s : (struct re_registers *) 0); /* Copy the register information to the POSIX structure. */ if (want_reg_info) { if (ret >= 0) { unsigned r; for (r = 0; r < nmatch; r++) { pmatch[r].rm_so = regs.start[r]; pmatch[r].rm_eo = regs.end[r]; } } /* If we needed the temporary register info, free the space now. */ free (regs.start); free (regs.end); } /* We want zero return to mean success, unlike `re_search'. */ return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; } /* Returns a message corresponding to an error code, ERRCODE, returned from either regcomp or regexec. We don't use PREG here. */ size_t regerror (errcode, preg, errbuf, errbuf_size) int errcode; regex_t *preg; char *errbuf; size_t errbuf_size; { char *msg; size_t msg_size; if (errcode < 0 || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0]))) /* Only error codes returned by the rest of the code should be passed to this routine. If we are given anything else, or if other regex code generates an invalid error code, then the program has a bug. Dump core so we can fix it. */ abort (); msg = re_error_msg[errcode]; /* POSIX doesn't require that we do anything in this case, but why not be nice. */ if (! msg) msg = "Success"; msg_size = strlen (msg) + 1; /* Includes the null. */ if (errbuf_size != 0) { if (msg_size > errbuf_size) { strncpy (errbuf, msg, errbuf_size - 1); errbuf[errbuf_size - 1] = 0; } else strcpy (errbuf, msg); } return msg_size; } /* Free dynamically allocated space used by PREG. */ void regfree (preg) regex_t *preg; { if (preg->buffer != NULL) free (preg->buffer); preg->buffer = NULL; preg->allocated = 0; preg->used = 0; if (preg->fastmap != NULL) free (preg->fastmap); preg->fastmap = NULL; preg->fastmap_accurate = 0; if (preg->translate != NULL) free (preg->translate); preg->translate = NULL; } #endif /* not emacs */ /* Local variables: make-backup-files: t version-control: t trim-versions-without-asking: nil End: */ #endif cfengine-2.2.10/pub/LICENSE.txt0000644000175000001440000001300110206620274012672 00000000000000THE FRONTIER ARTISTIC LICENSE Version 1.0 Copyright © (c) 1999 by Samuel Reynolds. Derived from the "Artistic License" at "OpenSource.org". Submitted to OpenSource.org for Open Source Initiative certification. PREAMBLE The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. DEFINITIONS o "Package" refers to the script, suite, file, or collection of scripts, suites, and/or files distributed by the Copyright Holder, and to derivatives of that Package created through textual modification. o "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. o "Copyright Holder" is whoever is named in the copyright statement or statements for the package. o "You" is you, if you're thinking about copying or distributing this Package. o "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) o "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. TERMS 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes, and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed script, suite, or file stating how and when you changed that script, suite, or file, and provided that you do at least ONE of the following: a) Use the modified Package only within your corporation or organization, or retain the modified Package solely for personal use. b) Place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. c) Rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page (or equivalent) for each non-standard executable that clearly documents how it differs from the Standard Version. d) Make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) Distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) Accompany the distribution with the machine-readable source of the Package with your modifications. c) Accompany any non-standard executables with their corresponding Standard Version executables, give the non-standard executables non-standard names, and clearly document the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) Make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. Scripts, suites, or programs supplied by you that depend on or otherwise make use of this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. cfengine-2.2.10/pub/Makefile.in0000644000175000001440000006255511170173244013137 00000000000000# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = pub DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/conf.h CONFIG_CLEAN_FILES = LIBRARIES = $(noinst_LIBRARIES) ARFLAGS = cru libcfpub_a_AR = $(AR) $(ARFLAGS) libcfpub_a_LIBADD = am_libcfpub_a_OBJECTS = libcfpub_a-getopt.$(OBJEXT) \ libcfpub_a-getopt1.$(OBJEXT) libcfpub_a-full-write.$(OBJEXT) \ libcfpub_a-regex.$(OBJEXT) libcfpub_a-getloadavg.$(OBJEXT) \ libcfpub_a-snprintf.$(OBJEXT) libcfpub_a_OBJECTS = $(am_libcfpub_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libcfpub_a_SOURCES) DIST_SOURCES = $(libcfpub_a_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BERKELEY_DB_CFLAGS = @BERKELEY_DB_CFLAGS@ BERKELEY_DB_LDFLAGS = @BERKELEY_DB_LDFLAGS@ BERKELEY_DB_LIB = @BERKELEY_DB_LIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EIGHTBIT = @EIGHTBIT@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCC_CFLAG = @GCC_CFLAG@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SELINUX = @LIB_SELINUX@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ NOWRAP = @NOWRAP@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_LIB_CPPFLAGS = @OPENSSL_LIB_CPPFLAGS@ OPENSSL_LIB_LDFLAGS = @OPENSSL_LIB_LDFLAGS@ OPENSSL_LIB_LIB = @OPENSSL_LIB_LIB@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PS2PDF = @PS2PDF@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TEXI2DVI = @TEXI2DVI@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = @CFLAGS@ @GCC_CFLAG@ INCLUDES = @BERKELEY_DB_CFLAGS@ @OPENSSL_LIB_CPPFLAGS@ noinst_LIBRARIES = libcfpub.a libcfpub_a_SOURCES = \ getopt.c \ getopt1.c \ full-write.c \ regex.c \ getloadavg.c \ snprintf.c libcfpub_a_CFLAGS = $(AM_CFLAGS) -fPIC EXTRA_DIST = \ getopt.h \ global.h \ gnuregex.h \ snprintf.h \ LICENSE.txt # # Some basic clean ups # MOSTLYCLEANFILES = *~ # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu pub/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu pub/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libcfpub.a: $(libcfpub_a_OBJECTS) $(libcfpub_a_DEPENDENCIES) -rm -f libcfpub.a $(libcfpub_a_AR) libcfpub.a $(libcfpub_a_OBJECTS) $(libcfpub_a_LIBADD) $(RANLIB) libcfpub.a mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfpub_a-full-write.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfpub_a-getloadavg.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfpub_a-getopt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfpub_a-getopt1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfpub_a-regex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfpub_a-snprintf.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< libcfpub_a-getopt.o: getopt.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-getopt.o -MD -MP -MF $(DEPDIR)/libcfpub_a-getopt.Tpo -c -o libcfpub_a-getopt.o `test -f 'getopt.c' || echo '$(srcdir)/'`getopt.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-getopt.Tpo $(DEPDIR)/libcfpub_a-getopt.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='getopt.c' object='libcfpub_a-getopt.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-getopt.o `test -f 'getopt.c' || echo '$(srcdir)/'`getopt.c libcfpub_a-getopt.obj: getopt.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-getopt.obj -MD -MP -MF $(DEPDIR)/libcfpub_a-getopt.Tpo -c -o libcfpub_a-getopt.obj `if test -f 'getopt.c'; then $(CYGPATH_W) 'getopt.c'; else $(CYGPATH_W) '$(srcdir)/getopt.c'; fi` @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-getopt.Tpo $(DEPDIR)/libcfpub_a-getopt.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='getopt.c' object='libcfpub_a-getopt.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-getopt.obj `if test -f 'getopt.c'; then $(CYGPATH_W) 'getopt.c'; else $(CYGPATH_W) '$(srcdir)/getopt.c'; fi` libcfpub_a-getopt1.o: getopt1.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-getopt1.o -MD -MP -MF $(DEPDIR)/libcfpub_a-getopt1.Tpo -c -o libcfpub_a-getopt1.o `test -f 'getopt1.c' || echo '$(srcdir)/'`getopt1.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-getopt1.Tpo $(DEPDIR)/libcfpub_a-getopt1.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='getopt1.c' object='libcfpub_a-getopt1.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-getopt1.o `test -f 'getopt1.c' || echo '$(srcdir)/'`getopt1.c libcfpub_a-getopt1.obj: getopt1.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-getopt1.obj -MD -MP -MF $(DEPDIR)/libcfpub_a-getopt1.Tpo -c -o libcfpub_a-getopt1.obj `if test -f 'getopt1.c'; then $(CYGPATH_W) 'getopt1.c'; else $(CYGPATH_W) '$(srcdir)/getopt1.c'; fi` @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-getopt1.Tpo $(DEPDIR)/libcfpub_a-getopt1.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='getopt1.c' object='libcfpub_a-getopt1.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-getopt1.obj `if test -f 'getopt1.c'; then $(CYGPATH_W) 'getopt1.c'; else $(CYGPATH_W) '$(srcdir)/getopt1.c'; fi` libcfpub_a-full-write.o: full-write.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-full-write.o -MD -MP -MF $(DEPDIR)/libcfpub_a-full-write.Tpo -c -o libcfpub_a-full-write.o `test -f 'full-write.c' || echo '$(srcdir)/'`full-write.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-full-write.Tpo $(DEPDIR)/libcfpub_a-full-write.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='full-write.c' object='libcfpub_a-full-write.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-full-write.o `test -f 'full-write.c' || echo '$(srcdir)/'`full-write.c libcfpub_a-full-write.obj: full-write.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-full-write.obj -MD -MP -MF $(DEPDIR)/libcfpub_a-full-write.Tpo -c -o libcfpub_a-full-write.obj `if test -f 'full-write.c'; then $(CYGPATH_W) 'full-write.c'; else $(CYGPATH_W) '$(srcdir)/full-write.c'; fi` @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-full-write.Tpo $(DEPDIR)/libcfpub_a-full-write.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='full-write.c' object='libcfpub_a-full-write.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-full-write.obj `if test -f 'full-write.c'; then $(CYGPATH_W) 'full-write.c'; else $(CYGPATH_W) '$(srcdir)/full-write.c'; fi` libcfpub_a-regex.o: regex.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-regex.o -MD -MP -MF $(DEPDIR)/libcfpub_a-regex.Tpo -c -o libcfpub_a-regex.o `test -f 'regex.c' || echo '$(srcdir)/'`regex.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-regex.Tpo $(DEPDIR)/libcfpub_a-regex.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='regex.c' object='libcfpub_a-regex.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-regex.o `test -f 'regex.c' || echo '$(srcdir)/'`regex.c libcfpub_a-regex.obj: regex.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-regex.obj -MD -MP -MF $(DEPDIR)/libcfpub_a-regex.Tpo -c -o libcfpub_a-regex.obj `if test -f 'regex.c'; then $(CYGPATH_W) 'regex.c'; else $(CYGPATH_W) '$(srcdir)/regex.c'; fi` @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-regex.Tpo $(DEPDIR)/libcfpub_a-regex.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='regex.c' object='libcfpub_a-regex.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-regex.obj `if test -f 'regex.c'; then $(CYGPATH_W) 'regex.c'; else $(CYGPATH_W) '$(srcdir)/regex.c'; fi` libcfpub_a-getloadavg.o: getloadavg.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-getloadavg.o -MD -MP -MF $(DEPDIR)/libcfpub_a-getloadavg.Tpo -c -o libcfpub_a-getloadavg.o `test -f 'getloadavg.c' || echo '$(srcdir)/'`getloadavg.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-getloadavg.Tpo $(DEPDIR)/libcfpub_a-getloadavg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='getloadavg.c' object='libcfpub_a-getloadavg.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-getloadavg.o `test -f 'getloadavg.c' || echo '$(srcdir)/'`getloadavg.c libcfpub_a-getloadavg.obj: getloadavg.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-getloadavg.obj -MD -MP -MF $(DEPDIR)/libcfpub_a-getloadavg.Tpo -c -o libcfpub_a-getloadavg.obj `if test -f 'getloadavg.c'; then $(CYGPATH_W) 'getloadavg.c'; else $(CYGPATH_W) '$(srcdir)/getloadavg.c'; fi` @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-getloadavg.Tpo $(DEPDIR)/libcfpub_a-getloadavg.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='getloadavg.c' object='libcfpub_a-getloadavg.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-getloadavg.obj `if test -f 'getloadavg.c'; then $(CYGPATH_W) 'getloadavg.c'; else $(CYGPATH_W) '$(srcdir)/getloadavg.c'; fi` libcfpub_a-snprintf.o: snprintf.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-snprintf.o -MD -MP -MF $(DEPDIR)/libcfpub_a-snprintf.Tpo -c -o libcfpub_a-snprintf.o `test -f 'snprintf.c' || echo '$(srcdir)/'`snprintf.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-snprintf.Tpo $(DEPDIR)/libcfpub_a-snprintf.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='snprintf.c' object='libcfpub_a-snprintf.o' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-snprintf.o `test -f 'snprintf.c' || echo '$(srcdir)/'`snprintf.c libcfpub_a-snprintf.obj: snprintf.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -MT libcfpub_a-snprintf.obj -MD -MP -MF $(DEPDIR)/libcfpub_a-snprintf.Tpo -c -o libcfpub_a-snprintf.obj `if test -f 'snprintf.c'; then $(CYGPATH_W) 'snprintf.c'; else $(CYGPATH_W) '$(srcdir)/snprintf.c'; fi` @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfpub_a-snprintf.Tpo $(DEPDIR)/libcfpub_a-snprintf.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='snprintf.c' object='libcfpub_a-snprintf.obj' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfpub_a_CFLAGS) $(CFLAGS) -c -o libcfpub_a-snprintf.obj `if test -f 'snprintf.c'; then $(CYGPATH_W) 'snprintf.c'; else $(CYGPATH_W) '$(srcdir)/snprintf.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LIBRARIES) installdirs: install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-exec-am: install-html: install-html-am install-info: install-info-am install-man: install-pdf: install-pdf-am install-ps: install-ps-am installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLIBRARIES ctags distclean \ distclean-compile distclean-generic distclean-libtool \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-2.2.10/pub/getopt.h0000644000175000001440000001106010202123437012520 00000000000000/* Declarations for getopt. Copyright (C) 1989, 90, 91, 92, 93, 94 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef _GETOPT_H #define _GETOPT_H 1 #define __GETOPT_H__ 1 #ifdef __cplusplus extern "C" { #endif /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ extern int opterr; /* Set to an option character which was unrecognized. */ extern int optopt; /* Describe the long-named options requested by the application. The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector of `struct option' terminated by an element containing a name which is zero. The field `has_arg' is: no_argument (or 0) if the option does not take an argument, required_argument (or 1) if the option requires an argument, optional_argument (or 2) if the option takes an optional argument. If the field `flag' is not NULL, it points to a variable that is set to the value given in the field `val' when the option is found, but left unchanged if the option is not found. To have a long-named option do something other than set an `int' to a compiled-in constant, such as set a value from `optarg', set the option's `flag' field to zero and its `val' field to a nonzero value (the equivalent single-letter option character, if there is one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ struct option { #if defined (__STDC__) && __STDC__ const char *name; #else char *name; #endif /* has_arg can't be an enum because some compilers complain about type mismatches in all the code that assumes it is an int. */ int has_arg; int *flag; int val; }; /* Names for the values of the `has_arg' field of `struct option'. */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 #if defined (__STDC__) && __STDC__ #ifdef __GNU_LIBRARY__ /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ extern int getopt (int argc, char *const *argv, const char *shortopts); #else /* not __GNU_LIBRARY__ */ extern int getopt (); #endif /* __GNU_LIBRARY__ */ extern int getopt_long (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); extern int getopt_long_only (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind); /* Internal only. Users should not call this directly. */ extern int _getopt_internal (int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *longind, int long_only); #else /* not __STDC__ */ extern int getopt (); extern int getopt_long (); extern int getopt_long_only (); extern int _getopt_internal (); #endif /* __STDC__ */ #ifdef __cplusplus } #endif #endif /* _GETOPT_H */ cfengine-2.2.10/pub/snprintf.h0000644000175000001440000000172610245023446013077 00000000000000#ifndef _PORTABLE_SNPRINTF_H_ #define _PORTABLE_SNPRINTF_H_ #define PORTABLE_SNPRINTF_VERSION_MAJOR 2 #define PORTABLE_SNPRINTF_VERSION_MINOR 2 #ifdef HAVE_SNPRINTF #include #else #include #include extern int snprintf(char *, size_t, const char *, /*args*/ ...); extern int vsnprintf(char *, size_t, const char *, va_list); #endif #if defined(HAVE_SNPRINTF) && defined(PREFER_PORTABLE_SNPRINTF) extern int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); extern int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap); #define snprintf portable_snprintf #define vsnprintf portable_vsnprintf #endif extern int asprintf (char **ptr, const char *fmt, /*args*/ ...); extern int vasprintf (char **ptr, const char *fmt, va_list ap); extern int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...); extern int vasnprintf(char **ptr, size_t str_m, const char *fmt, va_list ap); #endif cfengine-2.2.10/pub/Makefile.am0000644000175000001440000000155211001373644013113 00000000000000 AM_CFLAGS = @CFLAGS@ @GCC_CFLAG@ INCLUDES = @BERKELEY_DB_CFLAGS@ @OPENSSL_LIB_CPPFLAGS@ noinst_LIBRARIES = libcfpub.a libcfpub_a_SOURCES = \ getopt.c \ getopt1.c \ full-write.c \ regex.c \ getloadavg.c \ snprintf.c libcfpub_a_CFLAGS = $(AM_CFLAGS) -fPIC EXTRA_DIST = \ getopt.h \ global.h \ gnuregex.h \ snprintf.h \ LICENSE.txt # # Some basic clean ups # MOSTLYCLEANFILES = *~ # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in cfengine-2.2.10/pub/getopt.c0000644000175000001440000005263110202123437012524 00000000000000/* Getopt for GNU. NOTE: getopt is now part of the C library, so if you don't know what "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu before changing it! Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94 Free Software Foundation, Inc. This file is part of the GNU C Library. Its master source is NOT part of the C library, however. The master source lives in /gd/gnu/lib. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* This tells Alpha OSF/1 not to define a getopt prototype in . Ditto for AIX 3.2 and . */ #ifndef _NO_PROTO #define _NO_PROTO #endif #if !defined (__STDC__) || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ #ifndef const #define const #endif #endif #include /* Comment out all this code if we are using the GNU C Library, and are not actually compiling the library itself. This code is part of the GNU C Library, but also included in many other GNU distributions. Compiling and linking in this code is a waste when using the GNU C library (especially if it is a shared library). Rather than having every GNU program understand `configure --with-gnu-libc' and omit the object files, it is simpler to just do this in the source for each such file. */ #if defined (_LIBC) || !defined (__GNU_LIBRARY__) /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ #include #endif /* GNU C library. */ /* This version of `getopt' appears to the caller like standard Unix `getopt' but it behaves differently for the user, since it allows the user to intersperse the options with the other arguments. As `getopt' works, it permutes the elements of ARGV so that, when it is done, all the options precede everything else. Thus all application programs are extended to handle flexible argument order. Setting the environment variable POSIXLY_CORRECT disables permutation. Then the behavior is completely standard. GNU application programs can use a third alternative mode in which they can distinguish the relative order of options and other arguments. */ #include "getopt.h" /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, the argument value is returned here. Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ char *optarg = NULL; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller and for communication between successive calls to `getopt'. On entry to `getopt', zero means this is the first call; initialize. When `getopt' returns EOF, this is the index of the first of the non-option elements that the caller should itself scan. Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ /* XXX 1003.2 says this must be 1 before any call. */ int optind = 0; /* The next char to be scanned in the option-element in which the last option character we returned was found. This allows us to pick up the scan where we left off. If this is zero, or a null string, it means resume the scan by advancing to the next ARGV-element. */ static char *nextchar; /* Callers store zero here to inhibit the error message for unrecognized options. */ int opterr = 1; /* Set to an option character which was unrecognized. This must be initialized on some systems to avoid linking in the system's own getopt implementation. */ int optopt = '?'; /* Describe how to deal with options that follow non-option ARGV-elements. If the caller did not specify anything, the default is REQUIRE_ORDER if the environment variable POSIXLY_CORRECT is defined, PERMUTE otherwise. REQUIRE_ORDER means don't recognize them as options; stop option processing when the first non-option is seen. This is what Unix does. This mode of operation is selected by either setting the environment variable POSIXLY_CORRECT, or using `+' as the first character of the list of option characters. PERMUTE is the default. We permute the contents of ARGV as we scan, so that eventually all the non-options are at the end. This allows options to be given in any order, even with programs that were not written to expect this. RETURN_IN_ORDER is an option available to programs that were written to expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element as if it were the argument of an option with character code 1. Using `-' as the first character of the list of option characters selects this mode of operation. The special argument `--' forces an end of option-scanning regardless of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return EOF with `optind' != ARGC. */ static enum { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ static char *posixly_correct; #ifdef __GNU_LIBRARY__ /* We want to avoid inclusion of string.h with non-GNU libraries because there are many ways it can cause trouble. On some systems, it contains special magic macros that don't work in GCC. */ #include #define my_index strchr #else /* Avoid depending on library functions or files whose names are inconsistent. */ char *getenv (); static char * my_index (str, chr) const char *str; int chr; { while (*str) { if (*str == chr) return (char *) str; str++; } return 0; } /* If using GCC, we can safely declare strlen this way. If not using GCC, it is ok not to declare it. */ #ifdef __GNUC__ /* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h. That was relevant to code that was here before. */ #if !defined (__STDC__) || !__STDC__ /* gcc with -traditional declares the built-in strlen to return int, and has done so at least since version 2.4.5. -- rms. */ extern int strlen (const char *); #endif /* not __STDC__ */ #endif /* __GNUC__ */ #endif /* not __GNU_LIBRARY__ */ /* Handle permutation of arguments. */ /* Describe the part of ARGV that contains non-options that have been skipped. `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is the index after the last of them. */ static int first_nonopt; static int last_nonopt; /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) which contains all the non-options that have been skipped so far. The other is elements [last_nonopt,optind), which contains all the options processed since those non-options were skipped. `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ static void exchange (argv) char **argv; { int bottom = first_nonopt; int middle = last_nonopt; int top = optind; char *tem; /* Exchange the shorter segment with the far end of the longer segment. That puts the shorter segment into the right place. It leaves the longer segment in the right place overall, but it consists of two parts that need to be swapped next. */ while (top > middle && middle > bottom) { if (top - middle > middle - bottom) { /* Bottom segment is the short one. */ int len = middle - bottom; register int i; /* Swap it with the top part of the top segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[top - (middle - bottom) + i]; argv[top - (middle - bottom) + i] = tem; } /* Exclude the moved bottom segment from further swapping. */ top -= len; } else { /* Top segment is the short one. */ int len = top - middle; register int i; /* Swap it with the bottom part of the bottom segment. */ for (i = 0; i < len; i++) { tem = argv[bottom + i]; argv[bottom + i] = argv[middle + i]; argv[middle + i] = tem; } /* Exclude the moved top segment from further swapping. */ bottom += len; } } /* Update records for the slots the non-options now occupy. */ first_nonopt += (optind - last_nonopt); last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ static const char * _getopt_initialize (optstring) const char *optstring; { /* Start processing options with ARGV-element 1 (since ARGV-element 0 is the program name); the sequence of previously skipped non-option ARGV-elements is empty. */ first_nonopt = last_nonopt = optind = 1; nextchar = NULL; posixly_correct = getenv ("POSIXLY_CORRECT"); /* Determine how to handle the ordering of options and nonoptions. */ if (optstring[0] == '-') { ordering = RETURN_IN_ORDER; ++optstring; } else if (optstring[0] == '+') { ordering = REQUIRE_ORDER; ++optstring; } else if (posixly_correct != NULL) ordering = REQUIRE_ORDER; else ordering = PERMUTE; return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. If an element of ARGV starts with '-', and is not exactly "-" or "--", then it is an option element. The characters of this element (aside from the initial '-') are option characters. If `getopt' is called repeatedly, it returns successively each of the option characters from each of the option elements. If `getopt' finds another option character, it returns that character, updating `optind' and `nextchar' so that the next call to `getopt' can resume the scan with the following option character or ARGV-element. If there are no more option characters, `getopt' returns `EOF'. Then `optind' is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) OPTSTRING is a string containing the legitimate option characters. If an option character is seen that is not listed in OPTSTRING, return '?' after printing an error message. If you set `opterr' to zero, the error message is suppressed but we still return '?'. If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in `optarg'. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in `optarg', otherwise `optarg' is set to zero. If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique or is an exact match for some defined option. If they have an argument, it follows the option name in the same ARGV-element, separated from the option name by a `=', or else the in next ARGV-element. When `getopt' finds a long-named option, it returns 0 if that option's `flag' field is nonzero, the value of the option's `val' field if the `flag' field is zero. The elements of ARGV aren't really const, because we permute them. But we pretend they're const in the prototype to be compatible with other systems. LONGOPTS is a vector of `struct option' terminated by an element containing a name which is zero. LONGIND returns the index in LONGOPT of the long-named option found. It is only valid when a long-named option has been found by the most recent call. If LONG_ONLY is nonzero, '-' as well as '--' can introduce long-named options. */ int _getopt_internal (argc, argv, optstring, longopts, longind, long_only) int argc; char *const *argv; const char *optstring; const struct option *longopts; int *longind; int long_only; { optarg = NULL; if (optind == 0) optstring = _getopt_initialize (optstring); if (nextchar == NULL || *nextchar == '\0') { /* Advance to the next ARGV-element. */ if (ordering == PERMUTE) { /* If we have just processed some options following some non-options, exchange them so that the options come first. */ if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (last_nonopt != optind) first_nonopt = optind; /* Skip any additional non-options and extend the range of non-options previously skipped. */ while (optind < argc && (argv[optind][0] != '-' || argv[optind][1] == '\0')) optind++; last_nonopt = optind; } /* The special ARGV-element `--' means premature end of options. Skip it like a null option, then exchange with previous non-options as if it were an option, then skip everything else like a non-option. */ if (optind != argc && !strcmp (argv[optind], "--")) { optind++; if (first_nonopt != last_nonopt && last_nonopt != optind) exchange ((char **) argv); else if (first_nonopt == last_nonopt) first_nonopt = optind; last_nonopt = argc; optind = argc; } /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ if (optind == argc) { /* Set the next-arg-index to point at the non-options that we previously skipped, so the caller will digest them. */ if (first_nonopt != last_nonopt) optind = first_nonopt; return EOF; } /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) { if (ordering == REQUIRE_ORDER) return EOF; optarg = argv[optind++]; return 1; } /* We have found another option-ARGV-element. Skip the initial punctuation. */ nextchar = (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); } /* Decode the current option-ARGV-element. */ /* Check whether the ARGV-element is a long option. If long_only and the ARGV-element has the form "-f", where f is a valid short option, don't consider it an abbreviated form of a long option that starts with f. Otherwise there would be no way to give the -f short option. On the other hand, if there's a long option "fubar" and the ARGV-element is "-fu", do consider that an abbreviation of the long option, just like "--fu", and not "-f" with arg "u". This distinction seems to be the most useful approach. */ if (longopts != NULL && (argv[optind][1] == '-' || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1]))))) { char *nameend; const struct option *p; const struct option *pfound = NULL; int exact = 0; int ambig = 0; int indfound = 0; int option_index; for (nameend = nextchar; *nameend && *nameend != '='; nameend++) /* Do nothing. */ ; /* Test all long options for either exact match or abbreviated matches. */ for (p = longopts, option_index = 0; p->name; p++, option_index++) if (!strncmp (p->name, nextchar, nameend - nextchar)) { if (nameend - nextchar == strlen (p->name)) { /* Exact match found. */ pfound = p; indfound = option_index; exact = 1; break; } else if (pfound == NULL) { /* First nonexact match found. */ pfound = p; indfound = option_index; } else /* Second or later nonexact match found. */ ambig = 1; } if (ambig && !exact) { if (opterr) fprintf (stderr, "%s: option `%s' is ambiguous\n", argv[0], argv[optind]); nextchar += strlen (nextchar); optind++; return '?'; } if (pfound != NULL) { option_index = indfound; optind++; if (*nameend) { /* Don't test has_arg with >, because some C compilers don't allow it to be used on enums. */ if (pfound->has_arg) optarg = nameend + 1; else { if (opterr) { if (argv[optind - 1][1] == '-') /* --option */ fprintf (stderr, "%s: option `--%s' doesn't allow an argument\n", argv[0], pfound->name); else /* +option or -option */ fprintf (stderr, "%s: option `%c%s' doesn't allow an argument\n", argv[0], argv[optind - 1][0], pfound->name); } nextchar += strlen (nextchar); return '?'; } } else if (pfound->has_arg == 1) { if (optind < argc) optarg = argv[optind++]; else { if (opterr) fprintf (stderr, "%s: option `%s' requires an argument\n", argv[0], argv[optind - 1]); nextchar += strlen (nextchar); return optstring[0] == ':' ? ':' : '?'; } } nextchar += strlen (nextchar); if (longind != NULL) *longind = option_index; if (pfound->flag) { *(pfound->flag) = pfound->val; return 0; } return pfound->val; } /* Can't find it as a long option. If this is not getopt_long_only, or the option starts with '--' or is not a valid short option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' || my_index (optstring, *nextchar) == NULL) { if (opterr) { if (argv[optind][1] == '-') /* --option */ fprintf (stderr, "%s: unrecognized option `--%s'\n", argv[0], nextchar); else /* +option or -option */ fprintf (stderr, "%s: unrecognized option `%c%s'\n", argv[0], argv[optind][0], nextchar); } nextchar = (char *) ""; optind++; return '?'; } } /* Look at and handle the next short option-character. */ { char c = *nextchar++; char *temp = my_index (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') ++optind; if (temp == NULL || c == ':') { if (opterr) { if (posixly_correct) /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); else fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c); } optopt = c; return '?'; } if (temp[1] == ':') { if (temp[2] == ':') { /* This is an option that accepts an argument optionally. */ if (*nextchar != '\0') { optarg = nextchar; optind++; } else optarg = NULL; nextchar = NULL; } else { /* This is an option that requires an argument. */ if (*nextchar != '\0') { optarg = nextchar; /* If we end this ARGV-element by taking the rest as an arg, we must advance to the next element now. */ optind++; } else if (optind == argc) { if (opterr) { /* 1003.2 specifies the format of this message. */ fprintf (stderr, "%s: option requires an argument -- %c\n", argv[0], c); } optopt = c; if (optstring[0] == ':') c = ':'; else c = '?'; } else /* We already incremented `optind' once; increment it again when taking next ARGV-elt as argument. */ optarg = argv[optind++]; nextchar = NULL; } } return c; } } int getopt (argc, argv, optstring) int argc; char *const *argv; const char *optstring; { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } #endif /* _LIBC or not __GNU_LIBRARY__. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ int main (argc, argv) int argc; char **argv; { int c; int digit_optind = 0; while (1) { int this_option_optind = optind ? optind : 1; c = getopt (argc, argv, "abc:d:0123456789"); if (c == EOF) break; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (digit_optind != 0 && digit_optind != this_option_optind) printf ("digits occur in two different argv-elements.\n"); digit_optind = this_option_optind; printf ("option %c\n", c); break; case 'a': printf ("option a\n"); break; case 'b': printf ("option b\n"); break; case 'c': printf ("option c with value `%s'\n", optarg); break; case '?': break; default: printf ("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); printf ("\n"); } exit (0); } #endif /* TEST */ cfengine-2.2.10/TODO0000644000175000001440000000501310202123450010743 00000000000000 1. Out of processes strategy. Get cfexecd to remember processes which might be killed, as well as highest process number Put policy into cfagent.conf and save after each run a list of potential candidates. or processes which should not be harmed. If any process has more than XX instances, killl that? 5. What about remembering the stable core of processes, regardless of who owns them? i.e. like pH og cfenvd on the ps table?? Then kill the least permanent ones. 7. SNMP CLI module 9. Rewrite ifconfig stuff - routing sockets - find out the configured IP address for DHCP clients - what happens on multi-homed hosts 10: way of escaping list separator in strings splint *.c +unixlib with cutting out header files - non parsable.. splint -weak client.c +unixlib Copy does not copy an empty directory? Make cfport number configurable? ---- That would be very, very nice indeed! mark@iu.hio.no wrote: >Perhaps an alert function that sends directly to syslog could >be added. Other types of alerts could be generated too, e.g. >SNMP traps. > ---- Looks like Mark is feeling exceptionally benevolent today :-) Here is a short wish list of small features for 2.1 (or some future release) that, while not necessarily enhancing the scope or functionality of Cfengine in any large way, would be very welcome and eliminate some of the "glue" scripts that I (and no doubt many others) use to integrate Cfengine into their environment. In ascending order of implementation (by my estimate, which may be way off): 1) A control: option that allows selection of the syslog facility CFEngine uses, allowing administrators to (for instance) send all cfengine messages to a localN facility. (I already have [locally] a crude compile-time patch for this, email me if you want it.) 2) Corresponding negatives/positives for the various WarnIf and BeginGroup edittools. This would reduce the kludgery sometimes needed to Do The Right Thing. 3) Add options to the alert: functionality to control the medium by which the alert is sent, eg syslog, stderr, pipe into a command, etc. As mentioned below, SNMP would be very attractive although a little more work to implement. #3 and #4 above would involve more cranking on cfengine than I feel brave enough to do, but I'd be happy to work on the first two if there is interest from the list and/or Mark wants a patch for 'em. It seems that variable substitution isn't happening in Setline and AppendIfNoLineMatching strings. cfengine-2.2.10/install-sh0000744000175000001440000001267110202123462012270 00000000000000#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else : fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=$mkdirprog fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then : else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else : fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else : fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else : fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else : fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 cfengine-2.2.10/missing0000744000175000001440000002123110202123462011653 00000000000000#! /bin/sh # Common stub for a few missing GNU programs while installing. # Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. # Originally by Fran,cois Pinard , 1996. # 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, 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. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try \`$0 --help' for more information" exit 1 fi run=: # In the cases where this matters, `missing' is being run in the # srcdir already. if test -f configure.ac; then configure_ac=configure.ac else configure_ac=configure.in fi case "$1" in --run) # Try to run requested program, and just exit if it succeeds. run= shift "$@" && exit 0 ;; esac # If it does not exist, or fails to run (possibly an outdated version), # try to emulate it. case "$1" in -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an error status if there is no known handling for PROGRAM. Options: -h, --help display this help and exit -v, --version output version information and exit --run try to run the given command, and emulate it if it fails Supported PROGRAM values: aclocal touch file \`aclocal.m4' autoconf touch file \`configure' autoheader touch file \`config.h.in' automake touch all \`Makefile.in' files bison create \`y.tab.[ch]', if possible, from existing .[ch] flex create \`lex.yy.c', if possible, from existing .c help2man touch the output file lex create \`lex.yy.c', if possible, from existing .c makeinfo touch the output file tar try tar, gnutar, gtar, then tar without non-portable flags yacc create \`y.tab.[ch]', if possible, from existing .[ch]" ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing 0.3 - GNU automake" ;; -*) echo 1>&2 "$0: Unknown \`$1' option" echo 1>&2 "Try \`$0 --help' for more information" exit 1 ;; aclocal) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." touch aclocal.m4 ;; autoconf) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." touch configure ;; autoheader) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`acconfig.h' or \`${configure_ac}'. You might want to install the \`Autoconf' and \`GNU m4' packages. Grab them from any GNU archive site." files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` test -z "$files" && files="config.h" touch_files= for f in $files; do case "$f" in *:*) touch_files="$touch_files "`echo "$f" | sed -e 's/^[^:]*://' -e 's/:.*//'`;; *) touch_files="$touch_files $f.in";; esac done touch $touch_files ;; automake) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. You might want to install the \`Automake' and \`Perl' packages. Grab them from any GNU archive site." find . -type f -name Makefile.am -print | sed 's/\.am$/.in/' | while read f; do touch "$f"; done ;; bison|yacc) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.y' file. You may need the \`Bison' package in order for those modifications to take effect. You can get \`Bison' from any GNU archive site." rm -f y.tab.c y.tab.h if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.y) SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.c fi SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" y.tab.h fi ;; esac fi if [ ! -f y.tab.h ]; then echo >y.tab.h fi if [ ! -f y.tab.c ]; then echo 'main() { return 0; }' >y.tab.c fi ;; lex|flex) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.l' file. You may need the \`Flex' package in order for those modifications to take effect. You can get \`Flex' from any GNU archive site." rm -f lex.yy.c if [ $# -ne 1 ]; then eval LASTARG="\${$#}" case "$LASTARG" in *.l) SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` if [ -f "$SRCFILE" ]; then cp "$SRCFILE" lex.yy.c fi ;; esac fi if [ ! -f lex.yy.c ]; then echo 'main() { return 0; }' >lex.yy.c fi ;; help2man) echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a dependency of a manual page. You may need the \`Help2man' package in order for those modifications to take effect. You can get \`Help2man' from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` fi if [ -f "$file" ]; then touch $file else test -z "$file" || exec >$file echo ".ab help2man is required to generate this page" exit 1 fi ;; makeinfo) if test -z "$run" && (makeinfo --version > /dev/null 2>&1); then # We have makeinfo, but it failed. exit 1 fi echo 1>&2 "\ WARNING: \`$1' is missing on your system. You should only need it if you modified a \`.texi' or \`.texinfo' file, or any other file indirectly affecting the aspect of the manual. The spurious call might also be the consequence of using a buggy \`make' (AIX, DU, IRIX). You might want to install the \`Texinfo' package or the \`GNU make' package. Grab either from any GNU archive site." file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` if test -z "$file"; then file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` fi touch $file ;; tar) shift if test -n "$run"; then echo 1>&2 "ERROR: \`tar' requires --run" exit 1 fi # We have already tried tar in the generic part. # Look for gnutar/gtar before invocation to avoid ugly error # messages. if (gnutar --version > /dev/null 2>&1); then gnutar ${1+"$@"} && exit 0 fi if (gtar --version > /dev/null 2>&1); then gtar ${1+"$@"} && exit 0 fi firstarg="$1" if shift; then case "$firstarg" in *o*) firstarg=`echo "$firstarg" | sed s/o//` tar "$firstarg" ${1+"$@"} && exit 0 ;; esac case "$firstarg" in *h*) firstarg=`echo "$firstarg" | sed s/h//` tar "$firstarg" ${1+"$@"} && exit 0 ;; esac fi echo 1>&2 "\ WARNING: I can't seem to be able to run \`tar' with the given arguments. You may want to install GNU tar or Free paxutils, or check the command line arguments." exit 1 ;; *) echo 1>&2 "\ WARNING: \`$1' is needed, and you do not seem to have it handy on your system. You might have modified some files without having the proper tools for further handling them. Check the \`README' file, it often tells you about the needed prerequirements for installing this package. You may also peek at any GNU archive site, in case some other package would contain this missing \`$1' program." exit 1 ;; esac exit 0 cfengine-2.2.10/inputs/0000777000175000001440000000000011170173455011701 500000000000000cfengine-2.2.10/inputs/cf.sun4.example0000644000175000001440000000076610202123437014451 00000000000000################################################################# # # cf.sun4 - for iu.hioslo.no # # This file contains SunOS 4.1.x specific patches # ################################################################# ### # # BEGIN cf.sun4 # ### files: sun4:: /etc/passwd m=0644 r=0 o=root g=staff act=fixplain /etc/group m=0644 r=0 o=root g=staff act=fixplain /dev/kmem m=0640 r=0 o=root g=kmem act=warnall ### # # BEGIN cf.sun4 # ### cfengine-2.2.10/inputs/cfservd.conf.example0000644000175000001440000000251310202123437015541 00000000000000######################################################### # # This is a cfd config file # # The access control here follows after any tcpd # control in /etc/hosts.allow and /etc/hosts.deny # ######################################################### # # Could import cf.groups here and use a structure like # in cfengine.conf, cf.main, cf.groups # control: domain = ( iu.hioslo.no ) solaris:: cfrunCommand = ( "/iu/nexus/local/gnu/bin/cfengine" ) linux:: cfrunCommand = ( "/iu/waldo/local/gnu/bin/cfengine" ) # AutoExecInterval = ( 60 ) # AutoExecCommand = ( "/iu/nexus/local/gnu/lib/cfengine/bin/cfwrap /iu/nexus/local/gnu/lib/cfengine/bin/cfhourly") any:: # ChecksumDatabase = ( /tmp/testDATABASEcache ) IfElapsed = ( 1 ) MaxConnections = ( 10 ) ######################################################### admit: # or grant: /iu/nexus/local/gnu/bin/cfengine *.iu.hioslo.no /iu/waldo/local/gnu/bin/cfengine *.iu.hioslo.no /iu/nexus/local *.iu.hioslo.no /iu/nexus/ud dax.iu.hioslo.no /iu/nexus/ua dax.iu.hioslo.no /iu/nexus/u1 dax.iu.hioslo.no /iu/nexus/u2 dax.iu.hioslo.no /iu/nexus/u3 dax.iu.hioslo.no /iu/nexus/u4 dax.iu.hioslo.no dump-truck.iu.hioslo.no /etc *.iu.hioslo.no cfengine-2.2.10/inputs/cfagent.conf.example0000644000175000001440000000356710202123437015526 00000000000000################################################## # # cfagent.conf # # This is a simple file for getting started with # cfengine. It is harmless. If you get cfengine # running with this file, you can build on it. # ################################################## ### # # BEGIN cfagent.conf (Only hard classes in this file ) # ### control: actionsequence = ( files shellcommands copy ) domain = ( example.com ) timezone = ( MET ) smtpserver = ( smtphost.example.org ) # used by cfexecd sysadm = ( admin@example.com ) # where to mail output ###################################################################### resolve: # # Add these name servers to the /etc/resolv.conf file # 129.0.2.10 # local nameserver 129.0.2.156 # backup nameserver ###################################################################### copy: # Get a file from some trusted server, e.g. password sync # To do this, you need to use cfkey to install keys # /etc/shadow mode=0600 server=passwordserver ###################################################################### files: /etc/passwd mode=644 # make sure the file permissions are right owner=root # make sure it's owned by root action=fixall # if anything is wrong, fix it immediately! checksum=md5 # keep a "tripwire" checksum to tell us # if any changes occur here /etc/shadow mode=600 owner=root action=fixall ###################################################################### shellcommands: "/bin/echo Replace me with something useful" Wednesday.Hr00||Saturday.Hr02:: "/usr/local/bin/MyScript" ###################################################################### processes: "inetd" signal=hup "irc" signal=kill ### # # END cfagent.conf # ### cfengine-2.2.10/inputs/cf.chflags.example0000644000175000001440000000166110202123437015162 00000000000000################################################################ # # cf.chflags - tests for exrtra attributes chflags in OpenBSD/*BSD # ################################################################# control: timezone = ( MET CET ) actionsequence = ( files ) ############################################################################ files: /tmp/flags.00 mode=0600 owner=0 group=0 action=touch /tmp/flags.01 mode=0600 owner=0 group=0 flags=uappnd,uchg,uunlnk,nodump,opaque,sappnd,schg,sunlnk action=touch /tmp/flags.02 mode=0600 owner=0 group=0 flags=uappnd,uunlnk,opaque,schg action=touch /tmp/flags.03 mode=0600 owner=0 group=0 flags=uchg,sappnd,sunlnk action=touch /tmp/flags.04 mode=0600 owner=0 group=0 flags=5400037 action=touch cfengine-2.2.10/inputs/cf.ftp.example0000644000175000001440000000534510202123437014347 00000000000000control: actionsequence = ( directories copy editfiles files ) # Define variables ftp = ( /usr/local/ftp ) uid = ( 99 ) # ftp user gid = ( 99 ) # ftp group directories: solaris:: $(ftp)/pub mode=644 owner=root group=other $(ftp)/etc mode=111 owner=root group=other $(ftp)/dev mode=555 owner=root group=other $(ftp)/usr mode=555 owner=root group=other $(ftp)/usr/lib mode=555 owner=root group=other files: solaris:: $(ftp)/etc/passwd mode=644 o=root action=fixplain $(ftp)/etc/shadow mode=400 o=root action=fixplain $(ftp)/pub mode=644 owner=ftp action=fixall recurse=inf copy: solaris:: # Make sure ls is a trusted program by copying # a secure location... /bin/ls dest=$(ftp)/usr/bin/ls mode=111 owner=root type=checksum inform=true syslog=true /etc/netconfig dest=$(ftp)/etc/netconfig mode=444 o=root /devices/pseudo/mm@0:zero dest=$(ftp)/dev/zero mode=666 o=root /devices/pseudo/clone@0:tcp dest=$(ftp)/dev/tcp mode=444 o=root /devices/pseudo/clone@0:udp dest=$(ftp)/dev/udp mode=666 o=root /devices/pseudo/tl@0:ticotsord dest=$(ftp)/dev/ticotsord mode=666 o=root /usr/lib dest=$(ftp)/usr/lib recurse=2 mode=444 owner=root backup=false include=ld.so* include=libc.so* include=libdl.so* include=libmp.so* include=libnsl.so* include=libsocket.so* include=nss_compat.so* include=nss_dns.so* include=nss_files.so* include=nss_nis.so* include=nss_nisplus.so* include=nss_xfn.so* include=straddr.so* /usr/share/lib/zoneinfo dest=$(ftp)/usr/share/lib/zoneinfo mode=444 recurse=2 o=root type=binary editfiles: solaris:: # # Make sure that umask is right for ftpd # or files can be left 666 after upload! # { /etc/rc2.d/S72inetsvc PrependIfNoSuchLine "umask 022" } { $(ftp)/etc/passwd AutoCreate EmptyEntireFilePlease AppendIfNoSuchLine "ftp:x:$(uid):$(gid):Anonymous FTP:$(ftp):/bin/sync" } { $(ftp)/etc/group AutoCreate EmptyEntireFilePlease AppendIfNoSuchLine "ftp::$(gid):" } { $(ftp)/etc/shadow AutoCreate EmptyEntireFilePlease AppendIfNoSuchLine "ftp:NP:6445::::::" } # Finally...useful for chown { /etc/passwd AppendIfNoSuchLine "ftp:x:$(uid):$(gid):Anonymous FTP:$(ftp):/bin/sync" } { /etc/group AppendIfNoSuchLine "ftp::$(gid):" } cfengine-2.2.10/inputs/cf.groups.example0000644000175000001440000000317110202123437015070 00000000000000############################################################## # # cf.groups - for iu.hio.no # # This file contains all group/class definitions # ################################################################# ### # # BEGIN cf.groups # ### groups: # # Define some groups # # pentiumIII with 256MB RAM rom210 = ( daystrom panzerfaust vorlon nirvana nevermore delenn voyager borg mulder duke bajor collective arrakis axis valis ubik ) # pentiumMMX with 32MB RAM rom214 = ( wintermute roog zhora deckard usul tetsuo zodiac ix thistledown jart tleilax axolotl giediprime ) rom21X = ( rom210 rom214 ) # Net75 contains all UNICES on the 128.39.74/255.255.254.0 subnet Net75 = ( cube matrix rom21X ) x86 = ( i386 i486 i586 i686 ) # Intel AllHomeServers = ( nexus cube ) AllBinaryServers = ( nexus cube ) Laptops = ( nomad klein ) WWWServers = ( nexus ) FTPservers = ( nexus daneel cube ) PrimeServers = ( nexus ) SlaveServers = ( quetzalcoatal cube ) NameServers = ( PrimeServers SlaveServers ) PasswdServer = ( nexus ) BackupHost = ( nexus ) sysloghost = ( sigmund ) securehosts = ( nexus matrix sigmund ) PasswordClients = ( any -haddock -nomad -daneel -nexus ) OnTheHour = ( Min00_05 Min05_10 Min10_15 Min15_20 Min20_25 ) All = ( Hr00.OnTheHour ) peaktime = ( Hr10 Hr11 Hr12 Hr13 Hr14 Hr15 ) HalfHour = ( Min30_35 Min35_40 Min40_45 Min45_50 Min50_55 ) DayTime = ( Hr07 Hr08 Hr09 Hr10 Hr11 Hr12 Hr13 Hr14 Hr15 Hr16 Hr17 Hr18 ) CheckIntegrity = ( Hr06.OnTheHour ) ### # # END cf.groups # ### cfengine-2.2.10/inputs/cf.users.example0000644000175000001440000002365110202123437014717 00000000000000########################################## # # cf.users - for iu.hio.no # # This file contains user specific actions # ########################################## ### # # BEGIN cf.users # ### control: # # When making backups of user dirs, don't backup these files # excludecopy = ( *.EXE *.avi *.ZIP *.AVI *.MP3 *.mp3 *.o *.dvi *.rar *.au *.WAV .bin .BIN *.mov *.MOV *.zip *.tar* core a.out *.au *.wav *.exe *.tgz *.viv nystat-* acr-* DOC *.class *.dll *.avi *.ttf *.pcf *.dll *.DLL *.lnk *.xex *.3pm *.piz *.lll *.OBJ cache* .#* ) ########################################################################### filters: { historyfilter NameRegex: ".*history" IsSymLinkTo: "/dev/null" Result: "IsSymLinkTo.NameRegex" DefineClasses: "historyalert" } { setuidfilter Owner: "root" Mode: "+6000" Result: "Owner.Mode" } ########################################################################### ignore: # # Some directories to ignore altogether when copying or checking dl download ########################################################################### tidy: emergency|nexus.Hr20.OnTheHour|cube.Hr20.OnTheHour:: # # Tidy up users' home dirs # # home pat=.Maillock r=inf age=1 # nfs locking error home pat=.nfs* r=inf age=1 home pat=.rhosts age=0 # Security home pat=core r=inf age=0 home pat=a.out r=inf age=1 home p=*% r=inf age=2 home p=*~ r=inf age=2 home p=#* r=inf age=1 home p=.#* r=inf age=1 home p=*.dvi r=inf age=14 type=ctime home p=*.log r=inf age=2 home p=Log.* r=inf age=3 # home p=*.EXE r=inf age=1 home p=*.xex r=inf age=0 # home p=*.exe r=inf age=1 home p=BAK r=inf age=1 home p=log r=inf age=0 type=mtime home p=*.piz r=inf age=1 home p=*.lll r=inf age=1 home p=*.o r=inf age=2 home p=*.aux r=inf age=3 # home p=*.zip r=inf age=2 # home p=*.ZIP r=inf age=2 home p=*.mp3 r=inf age=2 type=mtime home p=*.MP3 r=inf age=2 home p=*.rar r=inf age=1 home p=*.RAR r=inf age=1 home p=*.pm3 r=inf age=0 home p=*.dll r=inf age=2 home p=*.cf-nonalpha r=inf age=0 home p=*.cfsaved r=inf age=0 home/.deleted p=* r=inf age=0 home/.wastebacket p=* r=inf age=14 home/www p=*~ r=inf age=1 home/Desktop/Trash p=* r=inf age=14 home p=*.jpg.vbs r=inf age=0 # LoveBug virus home p=.saves-* age=15 # emacs home p=.ksirc.socket.* age=1 home p=.kss-install.pid.* age=15 # screensaver... # # Clear the big cache files netscape creates # # home/.netscape-cache p=cache????* r=inf age=0 # home/.MCOM-cache p=cache????* r=inf age=0 home/.netscape/cache p=* r=inf age=3 type=atime home/.gimp p=gimpswap* r=inf age=0 dax.Hr17.OnTheHour:: # # Make sure the backup disks don't get full of old stuff # /iu/dax/backup p=* r=inf a=15 /iu/dax/backup p=* r=inf a=0 size=4m /iu/dax/backup2 p=* r=inf a=15 dax.Day28.Hr03.OnTheHour:: /iu/dax/backup p=* r=inf rmdirs=true age=35 /iu/dax/backup2 p=* r=inf rmdirs=true age=35 pax.Hr17.OnTheHour:: /iu/pax/backup p=* r=inf a=15 pax.Day28.Hr03.OnTheHour:: /iu/pax/backup p=* r=inf rmdirs=true age=35 ################################################################# files: AllHomeServers.Rest.Hr01.OnTheHour:: # # Check users files are not writable to the world # and there are no stale links (pointing nowhere) # home mode=-6002 recurse=inf action=fixplain ignore=www ignore=cgi-bin #links=tidy syslog=true inform=true filter=setuidfilter cube.Rest.Hr12.OnTheHour:: /iu/cube recurse=3 action=alert filter=historyfilter nexus.Rest.Hr12.OnTheHour:: /iu/nexus recurse=3 action=alert filter=historyfilter # home/www mode=+644 r=inf action=fixall home/.cshrc mode=755 action=fixall nexus:: # home/www mode=+644 r=inf action=fixall nexus.Hr01.OnTheHour:: # # Some special permission checks # To make life easy for some people... # /iu/nexus/ua/ulfu/www m=+644 recurse=inf action=fixall /iu/nexus/ud/cfengine g=cfengine m=+664 recurse=inf action=fixall ################################################################# copy: AllHomeServers.Hr00.OnTheHour:: # # Make sure each user has an up to date standard # setup. Cshrc just sources in a big standard file # which is kept in ~user/../.setupfiles/cshrc # to reduce disk wastage # $(masterfiles)/lib/Cshrc dest=home/.cshrc $(masterfiles)/lib/tkgrc dest=home/.tkgrc ########################################################################### # # Do a backup of the user disks, excluding crap, no files > 4mb # ########################################################################### dax.Hr03.OnTheHour:: /iu/cube/u1 dest=/iu/dax/backup/u1 r=inf size=<4mb typecheck=false backup=false # Don't backup the backup! server=cube action=silent ignore=WIN95 dax.Hr04.OnTheHour:: /iu/cube/u2 dest=/iu/dax/backup/u2 r=inf size=<4mb typecheck=false backup=false server=cube action=silent ignore=WIN95 dax.Hr05.OnTheHour:: /iu/cube/u3 dest=/iu/dax/backup/u3 r=inf size=<4mb typecheck=false backup=false server=cube action=silent ignore=WIN95 dax.Hr06.OnTheHour:: /iu/cube/u4 dest=/iu/dax/backup/u4 r=inf size=<4mb typecheck=false backup=false server=cube action=silent ignore=WIN95 dax.Hr18.OnTheHour:: /iu/nexus/ua dest=/iu/dax/backup2/ua r=inf size=<4mb backup=false typecheck=false action=silent server=nexus exclude=.* dax.Hr19.OnTheHour:: /iu/nexus/ub dest=/iu/dax/backup2/ub r=inf size=<4mb backup=false typecheck=false action=silent server=nexus exclude=.* dax.Hr20.OnTheHour:: /iu/nexus/uc dest=/iu/dax/backup2/uc r=inf size=<4mb backup=false typecheck=false action=silent server=nexus exclude=.* pax.Hr21.OnTheHour:: /iu/nexus/ud dest=/iu/pax/backup/ud r=inf size=<4mb backup=false typecheck=false action=silent server=nexus exclude=.* ########################################################## # # Make a backup of our local system modifications # ########################################################## dax.Hr01.OnTheHour:: /iu/nexus/local/iu dest=/iu/dax/backup/iu-local r=inf backup=false server=nexus action=silent ignore=apache* ignore=logs ignore=src # /iu/nexus/ECG dest=/iu/dax/backup2/ECG r=inf exclude=*.weekly.* exclude=*.daily.* ignore=ps backup=false server=nexus # pax.Hr01.OnTheHour:: # /home dest=/iu/pax/backup/daneel-home r=inf backup=false server=daneel ######################################################## shellcommands: historyalert:: "/bin/echo History files linked to /dev/null - someone up to no good" nexus:: "/iu/nexus/ua/mysql/passwdskript.php" owner=mysql "/local/iu/bin/Checkusers.sh > /dev/null 2>&1" nexus.Hr07.OnTheHour:: "/iu/nexus/ud/sigmunds/Adm/Prog/dbcontrol.php | /bin/mail sigmunds" owner=sigmunds "/iu/nexus/ud/sigmunds/Adm/Prog/passwdcontrol.php | /bin/mail sigmunds" owner=sigmunds nexus.Day01.Hr08.OnTheHour:: "/local/iu/bin/passwdchecker.pl | /bin/mail sigmunds" ######################################################## processes: "kik1" signal=kill ### # # END cf.users # ### cfengine-2.2.10/inputs/cf.motd.example0000644000175000001440000000155310202123437014516 00000000000000################################################################## # # cf.motd # # This file is used to set the message of the day file on # each host # ################################################################## ##### # # BEGIN cf.motd # ##### control: # # This points to the file containing general text # masterfile = ( /iu/nexus/local/iu/etc/motd-master ) addendum = ( /iu/nexus/local/iu/etc/motd-nexus ) editfiles: { /etc/motd BeginGroupIfFileIsNewer "$(masterfile)" AutoCreate # IncrementPointer "1" DeleteLinesAfterThisMatching ".*" InsertFile "$(masterfile)" EndGroup } nexus:: { /etc/motd BeginGroupIfNoLineContaining "connecting" InsertFile "$(addendum)" EndGroup } files: /etc/motd mode=644 o=root g=root action=fixplain ##### # # END cf.motd # ##### cfengine-2.2.10/inputs/update.conf.example0000644000175000001440000000704310202123437015372 00000000000000####################################################### # # cf.update - for iu.hio.no # ####################################################### ### # # BEGIN cf.update # ### ####################################################################### # # This script distributes the configuration, a simple file so that, # if there are syntax errors in the main config, we can still # distribute a correct configuration to the machines afterwards, even # though the main config won't parse. It is read and run just before the # main configuration is parsed. # ####################################################################### control: actionsequence = ( copy processes tidy ) # Keep this simple and constant domain = ( iu.hio.no ) # Needed for remote copy # # Which host/dir is the master for configuration roll-outs? # policyhost = ( nexus.iu.hio.no ) master_cfinput = ( /iu/nexus/local/iu/cfengine/inputs ) AddInstallable = ( new_cfenvd new_cfservd ) # # Some convenient variables # workdir = ( /var/cfengine ) solaris:: cf_install_dir = ( /iu/nexus/local/sbin ) linux:: cf_install_dir = ( /iu/cube/local/sbin ) ################################################################### # # Spread the load, make sure the servers get done first though # ################################################################### !AllBinaryServers:: SplayTime = ( 1 ) ############################################################################ # # Make sure there is a local copy of the configuration and # the most important binaries in case we have no connectivity # e.g. for mobile stations or during DOS attacks # copy: $(master_cfinput) dest=$(workdir)/inputs r=inf mode=700 type=binary exclude=*.lst exclude=*~ exclude=#* server=$(policyhost) trustkey=true !quetzalcoatal:: $(cf_install_dir)/cfagent dest=$(workdir)/bin/cfagent mode=755 backup=false type=checksum $(cf_install_dir)/cfservd dest=$(workdir)/bin/cfservd mode=755 backup=false type=checksum define=new_cfservd $(cf_install_dir)/cfexecd dest=$(workdir)/bin/cfexecd mode=755 backup=false type=checksum $(cf_install_dir)/cfenvd dest=$(workdir)/bin/cfenvd mode=755 backup=false type=checksum define=new_cfenvd ##################################################################### tidy: # # Cfexecd stores output in this directory. # Make sure we don't build up files and choke on our own words! # $(workdir)/outputs pattern=* age=7 ##################################################################### processes: new_cfservd:: "cfservd" signal=term restart /var/cfengine/bin/cfservd new_cfenvd:: "cfenvd" signal=kill restart "/var/cfengine/bin/cfenvd -H" ### # # END cf.update # ### cfengine-2.2.10/inputs/cf.linux.example0000644000175000001440000001161010202123437014705 00000000000000################################################################# # # cf.linux - for iu.hioslo.no # # This file contains debian linux specific patches # ################################################################# ### # # BEGIN cf.linux # ### ########################################################################### processes: "xntp" matches=1 restart "/usr/sbin/xntpd" useshell=false "inetd" signal=hup restart "/usr/sbin/inetd" useshell=false "cron" matches=>1 restart "/etc/init.d/cron start" useshell=dumb inform=true ########################################################################### files: /usr/bin/lpr o=root m=4755 action=fixplain /etc/printcap m=644 o=root action=fixplain /etc m=0644 include=csh* action=fixplain r=1 /usr/bin/tcsh mode=755 o=root act=fixall /usr/sbin/sendmail mode=4755 o=root act=fixplain # # Cert advisories # /bin/mount m=555 o=root action=fixall /bin/umount m=555 o=root action=fixall # /usr/bin/X11/xlock m=555 o=root action=fixall ####################################################################### disable: /sbin/dip-3.3.7n /etc/sudoers /usr/bin/sudoers ######################################################################## links: /bin/tcsh ->! /usr/bin/tcsh /etc/X11/xdm/xdm-config ->! /local/iu/X11/xdm/xdm-config /etc/X11/Xsession ->! /local/iu/X11/Xsession ######################################################################## editfiles: { /etc/csh.cshrc AppendIfNoSuchLine "setenv TZ 'MET-1MET DST-2,M3.5.0/2,M10.5.0/3'" } { /etc/host.conf PrependIfNoSuchLine "order bind" } { /etc/cron.daily/standard HashCommentLinesContaining "security" } # # ntpd # !borg:: { /etc/init.d/xntp3 BeginGroupIfNoLineMatching ".*ntpdate.*" LocateLineMatching "test.*" IncrementPointer "1" InsertLine "/usr/sbin/ntpdate frey.ifi.uio.no" EndGroup } { /etc/init.d/cron BeginGroupIfNoLineMatching ".*/usr/sbin/start-stop.*" ReplaceAll "start-stop-daemon" With "/usr/sbin/start-stop-daemon" EndGroup } any:: { /etc/inetd.conf AppendIfNoSuchLine "cffix stream tcp nowait root /local/iu/bin/cfinetd cfinetd" } ######################################################################### shellcommands: All:: # # Find/locate database # "/usr/bin/updatedb" "/sbin/ldconfig" any:: "/usr/sbin/rdate nexus >/dev/null 2>&1" # in spite of xntpd # waldo.CPUmax:: # # Disable netscape and gimp if the load is too high. # CPUhigh is 60-90% load, max is 90+. # # "/bin/mv /local/bin/netscape /local/bin/netscape.cf" # "/bin/chmod 0700 /local/bin/netscape.cf" # "/bin/cp /local/bin/netscape.stop /local/bin/netscape" # "/bin/chmod 755 /local/bin/netscape" # "/bin/mv /local/bin/gimp /local/bin/gimp.cf" # "/bin/chmod 0700 /local/bin/gimp.cf" # "/bin/cp /local/bin/gimp.stop /local/bin/gimp" # "/bin/chmod 755 /local/bin/gimp" # waldo.CPUlow|waldo.CPUmedium|waldo.CPUhigh:: # # Enable netscape and gimp if load is acceptable. # # "/bin/mv /local/bin/netscape.cf /local/bin/netscape >/dev/null" # "/bin/chmod 755 /local/bin/netscape" # "/bin/mv /local/bin/gimp.cf /local/bin/gimp >/dev/null" # "/bin/chmod 755 /local/bin/gimp" # IMAPServer:: # # Prune delivery database # # "/bin/su cyrus -c '/local/bin/deliver -E 3'" ######################################################################### directories: # # Make printer spool directories... # /var/spool/virtual-light o=root g=other mode=755 /var/spool/elektro o=root g=other mode=755 /var/spool/ibsen o=root g=other mode=755 ######################################################################### copy: /iu/waldo/local/iu/etc/rc.local dest=/etc/rc2.d/S99rc-local mode=755 /iu/waldo/local/bin/todos dest=/usr/bin/todos mode=755 type=checksum $(masterfiles)/etc/printcap.client dest=/etc/printcap mode=0644 type=checksum $(masterfiles)/etc/S99cfd dest=/etc/rc2.d/S99cfd mode=0755 $(masterfiles)/etc/S99cfd dest=/etc/rc3.d/S99cfd mode=0755 $(masterfiles)/etc/S99cfd dest=/etc/rc4.d/S99cfd mode=0755 $(masterfiles)/etc/S99cfd dest=/etc/rc5.d/S99cfd mode=0755 /iu/nexus/local/gnu/lib/emacs/uio-lisp/hilit19.el dest=/usr/lib/emacs/site-lisp/hilit19.el mode=0644 $(masterfiles)/etc/linux-etc-ld-so-conf dest=/etc/ld.so.conf mode=644 ##################################################################################### tidy: /usr/games pattern=fortune age=0 /usr/lib/xemacs pattern=* r=inf rmdirs=true age=0 /usr/lib/xemacs-19.14 pattern=* r=inf rmdirs=true age=0 /usr/bin pattern=cfengine age=0 ### # # END cf.linux # ### cfengine-2.2.10/inputs/cf.services.example0000644000175000001440000002021610202123437015373 00000000000000############################################################## # # cf.services : local network service configuration # ############################################################### ### # # BEGIN cf.services # ### ############################################################### control: AddInstallable = ( nfs_update ) ############################################################### shellcommands: nexus:: # Clear a bad RPC channel. Someone using a bad port number? "/usr/sbin/shareall" cube.nfs_update:: "/etc/init.d/nfs-server restart > /dev/null 2>&1" ############################################################### copy: /iu/nexus/local/iu/etc/hosts.deny dest=/etc/hosts.deny mode=644 server=nexus !(dax|cube|sigmund):: /iu/nexus/local/iu/etc/hosts.allow dest=/etc/hosts.allow mode=644 server=nexus dax|cube:: /iu/nexus/local/iu/etc/hosts.allow.dax dest=/etc/hosts.allow mode=644 server=nexus sigmund:: /iu/nexus/local/iu/etc/hosts.allow.sigmund dest=/etc/hosts.allow mode=644 server=nexus nexus:: /iu/nexus/local/iu/etc/dfstab dest=/etc/dfs/dfstab /iu/nexus/local/iu/etc/options.tcl dest=/iu/nexus/local/share/tkrat2.0/options.tcl mode=644 cube:: /iu/cube/local/iu/etc/exports.cube dest=/etc/exports mode=644 define=nfs_update /iu/cube/local/iu/etc/options.tcl dest=/iu/cube/local/share/tkrat2.0/options.tcl mode=644 securehosts:: /iu/nexus/local/iu/etc/ssh_banner_message_secure dest=/etc/ssh2/ssh_banner_message mode=644 owner=root group=root 128_39_89.!securehosts:: /iu/nexus/local/iu/etc/ssh_banner_message_89 dest=/etc/ssh2/ssh_banner_message mode=644 owner=root group=root ############################################################### links: nexus:: # Mirroring /etc/rsyncd.conf -> /local/iu/etc/rsyncd.conf ############################################################### editfiles: !rom21X:: { /etc/ssh2/sshd2_config ReplaceAll "PrintMotd.*yes" With "PrintMotd no" ReplaceAll ".*Ssh1Compatibility.*yes.*" With "Ssh1Compatibility no" AppendIfNoSuchLine "Ssh1Compatibility no" HashCommentLinesMatching ".*Sshd1Path.*" DeleteLinesMatching ".*PasswordAuthentication.*" DeleteLinesMatching ".*PubkeyAuthentication.*" DeleteLinesMatching ".*AllowCshrcSourcingWithSubsystems.*" } securehosts:: # Limited access to certain hosts { /etc/ssh2/sshd2_config AppendIfNoSuchLine "AllowGroups drift" AppendIfNoSuchLine "DenyGroups student,ansatt" } 128_39_89.!securehosts.!haddock:: { /etc/ssh2/sshd2_config AppendIfNoSuchLine "AllowGroups drift,ansatt" AppendIfNoSuchLine "DenyGroups student" } haddock:: { /etc/ssh2/sshd2_config DeleteLinesMatching ".*AllowGroups.*" DeleteLinesMatching ".*DenyGroups.*" } 128_39_74.!securehosts.!rom21X:: # Not really necessary as all are allowed by default { /etc/ssh2/sshd2_config AppendIfNoSuchLine "AllowGroups drift,ansatt,student" } !rom21X:: { /etc/ssh2/ssh2_config AppendIfNoSuchLine "AuthenticationSuccessMsg no" } FTPservers:: { /etc/shells AppendIfNoSuchLine "/bin/tcsh" AppendIfNoSuchLine "/bin/bash" AppendIfNoSuchLine "/local/gnu/bin/bash" } !FTPservers:: { /etc/inetd.conf HashCommentLinesContaining "in.ftpd" } !rom21X:: { /etc/inetd.conf DeleteLinesContaining "bootp" DeleteLinesContaining "bootps" AppendIfNoSuchLine "finger stream tcp nowait nobody /local/iu/sbin/tcpd in.fingerd" # AppendIfNoSuchLine "cfinger stream tcp nowait nobody /local/iu/sbin/tcpd in.cfingerd" HashCommentLinesContaining "rshd" HashCommentLinesContaining "pop" HashCommentLinesContaining "swat" } rom21X:: { /etc/inetd.conf AppendIfNoSuchLine "finger stream tcp nowait nobody /usr/sbin/tcpd /local/iu/sbin/in.fingerd" AppendIfNoSuchLine "cfinger stream tcp nowait nobody /usr/sbin/tcpd /local/iu/sbin/in.cfingerd" } nexus:: { /etc/inetd.conf AppendIfNoSuchLine "netbios-ssn stream tcp nowait root /local/sbin/smbd smbd" AppendIfNoSuchLine "netbios-ns dgram udp wait root /local/sbin/nmbd nmbd" AppendIfNoSuchLine "rsync stream tcp nowait root /local/iu/sbin/tcpd rsync --daemon" # HashCommentLinesContaining "telnet" } cube:: { /etc/inetd.conf AppendIfNoSuchLine "netbios-ssn stream tcp nowait.100 root /local/sbin/smbd smbd" AppendIfNoSuchLine "netbios-ns dgram udp wait root /local/sbin/nmbd nmbd" } !sysloghost:: { /etc/syslog.conf AppendIfNoSuchLine "*.warning @loghost" DefineClasses "syslogdhup" } ############################################################### processes: linux:: SetOptionString "aucx" any:: "bootp" signal=kill exclude=rpc.bootparamd "inetd" signal=hup inform=false "cfservd" restart "/usr/local/sbin/cfservd" useshell=false syslogdhup:: "syslogd" signal=hup !rom21X:: "sshd" restart "/local/sbin/sshd" useshell=false inform=true rom21X:: # openssh "sshd" restart "/etc/init.d/ssh restart" any:: "snmp" signal=kill "powerd" signal=kill "mibiisa" signal=kill # nexus.percent_10:: # strategy, problems with stupid named # "named" signal=term restart "/local/sbin/named -u dns" inform=false nexus:: "fingerd" restart "/local/etc/fingerd" useshell=false "mysqld" restart "/local/iu/bin/StartMysql" useshell=false "named" restart "/local/sbin/named -u dns" useshell=false inform=true quetzalcoatal:: "named" restart "/local/sbin/named -u dns -c /local/etc/named.conf.slave" inform=true cube:: # until we can use v9 "named" restart "/local/iu/bind/bin/named -u dns -g nogroup" inform=true NameServers.dns_update:: "named" signal=hup cube.Hr05:: # used kill before, will HUP do? "rpc.mountd" signal=hup # restart "/usr/sbin/rpc.mountd" "rpc.nfsd" signal=hup # restart "/usr/sbin/rpc.nfsd" # sunos_5_6:: # "identd" restart "/local/sbin/identd" inform=true ############################################################### files: PrimeServers:: /local/iu/dns/pz o=dns m=644 act=fixall r=1 exclude=Fixserial /local/iu/dns/pz/Fixserial m=755 action=fixplain SlaveServers:: /local/iu/dns/sz o=dns m=644 act=fixall r=1 NameServers:: /local/iu/logs/admin o=dns m=644 act=fixplain /local/iu/logs/security o=dns m=644 act=fixplain /local/iu/logs/updates o=dns m=644 act=fixplain /local/iu/logs/xfer o=dns m=644 act=fixplain WWWServers.Rest.Hr00.HalfHour:: /local/iu/etc/apache m=644 act=fixall r=inf FTPservers.nexus:: # # Make sure anonymous ftp areas have the correct # protection, or logins won't be able to read # files - or perhaps a security risk. This is # solaris 2 specific... # $(ftp)/pub mode=644 o=root g=other act=fixall $(ftp)/pub mode=644 act=fixall r=inf $(ftp)/etc mode=111 o=root g=other act=fixdirs $(ftp)/usr/bin/ls mode=111 o=root g=other act=fixall $(ftp)/dev mode=555 o=root g=other act=fixall $(ftp)/usr mode=555 o=root g=other act=fixdirs !rom21X:: /etc/ssh2 mode=755 o=root g=root act=fixall # set wrong by install ############################################################### disable: nexus.Sunday.All:: /var/log/xferlog rotate=3 cube.Sunday.All:: /var/log/xferlog rotate=3 # Sunday.nexus:: # /local/etc/fingerdir/userdata rotate=empty ### # # END cf.services # ### cfengine-2.2.10/inputs/cfrun.hosts.example0000644000175000001440000000110310202123437015427 00000000000000# # This is the host list for cfrun # # Only these hosts will be contacted by remote connection # domain=iu.hio.no access=toreo,mark,haugerud,sigmunds nexus # solaris quetzalcoatal dax pax way haddock cube # linux # ta stabile maskiner foerst matrix sigmund daneel # saa maskinene paa studentsalene, de som blir slaatt av... # rom 210 daystrom panzerfaust vorlon nirvana nevermore delenn voyager borg mulder duke bajor collective arrakis axis valis ubik # rom 214 wintermute roog zhora deckard usul tetsuo zodiac ix thistledown jart tleilax axolotl giediprime cfengine-2.2.10/inputs/cf.solaris.example0000644000175000001440000002113010202123437015220 00000000000000################################################################# # # cf.solaris - for iu.hio.no # # This file contains solaris specific patches # ################################################################# ### # # BEGIN cf.solaris # ### directories: # # httpd/netscape want this to exist for some bizarre reason # /usr/lib/X11/nls /var/run /var/spool/lpd ################################################################ tidy: /usr/tmp pattern=* age=1 /etc/rc2.d pattern=S80lp age=0 ################################################################# links: /opt/gnu -> /local/gnu /etc/services ->! /etc/inet/services /usr/bin/perl ->! /local/bin/perl /var/spool/mail -> /var/mail solaris2.7:: /bin/bash -> /local/gnu/bin/bash ############################################################## copy: # # Some standard setup files, can't link because # machine won't boot if their not on / partition. # /local/bin/tcsh dest=/bin/tcsh mode=755 /local/iu/etc/nsswitch.standalone dest=/etc/nsswitch.conf /local/iu/etc/S99rc-local dest=/etc/rc2.d/S99rc-local mode=755 /local/iu/etc/etc_ntp_conf.solaris dest=/etc/ntp.conf mode=644 ############################################################## disable: /etc/.login type=file /bin/rdist /etc/auto_home /etc/auto_master /usr/lib/print/printd nexus:: /usr/openwin/bin/Xsun # See cert vulnerability. setuid! ############################################################## files: # # If this doesn't exist fork will not work and the # system will not even be able to run the /etc/rc # scripts at boottime # /etc/system o=root g=root m=644 action=touch /usr/sbin/mount o=bin g=bin m=555 action=fixplain /usr/sbin/ping m=4555 action=fixplain /etc/passwd m=0644 o=root g=other action=fixplain /etc/shadow m=0600 o=root g=other action=fixplain /etc/defaultrouter m=0644 o=root g=other action=touch /etc/inet m=755 o=root g=other action=fixdirs /var/adm/wtmpx m=0644 o=adm g=adm action=touch # /var/adm/wtmp m=0644 o=root g=adm action=touch # /var/adm/utmp m=0644 o=root g=adm action=fixplain /var/adm/utmpx m=0644 o=root g=bin action=fixplain /tmp m=1777 action=fixdirs /usr/openwin/bin/xdm m=0755 o=root g=bin action=fixplain /usr/dt/bin r=inf m=-6000 action=fixall /usr/bin/tip m=0711 action=fixplain inform=true # bof /usr/openwin/bin/Xsun m=0755 action=fixplain inform=false # bof /usr/openwin/bin/kcms_configure m=0755 action=fixplain inform=false # bof /usr/bin/sparcv7/ipcs m=0555 action=fixplain # bof /usr/bin/sparcv9/ipcs m=0555 action=fixplain # bof /usr/lib/dmi/snmpXdmid m=0000 action=fixplain # bof CA-2001-05 /usr/bin/at m=0755 action=fixplain # string format vuln /usr/sbin/sparcv7/whodo m=0555 action=fixplain # bof bugtraq id 2935 /usr/sbin/sparcv9/whodo m=0555 action=fixplain # bof bugtraq id 2935 solaris2_7:: /usr/bin/mail m=0511 action=fixplain # bof CheckIntegrity.Rest:: /etc o=root,bin,uucp,lp,adm action=warnall r=inf /usr o=root,bin,uucp,lp,adm action=warnall r=inf checksum=md5 ignore=tmp ignore=authdir syslog=true /var/spool/cron/crontabs checksum=md5 r=inf ############################################################## disable: # # CERT security patch # /usr/openwin/bin/kcms_calibrate /usr/openwin/bin/kcms_configure /usr/bin/admintool /etc/rc2.d/S99dtlogin ################################################################ shellcommands: dax|quetzalcoatal:: "/bin/echo hei" AllBinaryServers.Saturday.Hr00:: # # Make sure the man -k / apropos data are up to date # "/usr/bin/catman -M /local/iu/man" "/usr/bin/catman -M /local/man" "/usr/bin/catman -M /local/gnu/man" "/usr/bin/catman -M /local/teTeX/man" any.Hr00.Saturday:: "/usr/bin/catman -M /usr/openwin/share/man" "/usr/bin/catman -M /usr/share/man" any:: "/local/bin/ntpdate cube > /dev/null 2>&1" inform=false (Hr23.HalfHour)|(nexus.percent_10):: # # Update the GNU find/locate database each night # "$(gnu)/bin/updatedb > /dev/null 2>&1" ############################################################## editfiles: # # Makes sure that cfengine will be run by cron # installs itself as a cron job - sneaky! :) # { /var/spool/cron/crontabs/root AutoCreate DeleteLinesMatching "0,30 * * * * /usr/local/sbin/cfexecd -F -L /local/iu/lib:/local/lib/mysql:/local/lib" AppendIfNoSuchLine "0,30 * * * * /usr/local/sbin/cfexecd -F -L /local/iu/lib:/local/lib/mysql:/local/lib:/local/gnu/lib" } # # Solaris configuration for extra logins # { /etc/auto_home DeleteLinesContaining "+" } { /etc/auto_master DeleteLinesContaining "+" } { /etc/system AppendIfNoSuchLine "set pt_cnt=128" AppendIfNoSuchLine "set noexec_user_stack_log = 1" AppendIfNoSuchLine "set noexec_user_stack = 1" } !Net75:: { /etc/netmasks AppendIfNoSuchLine "128.39.89.0 255.255.255.0" } Net75:: { /etc/netmasks AppendIfNoSuchLine "128.39.74.0 255.255.254.0" } any:: { /etc/netmasks DeleteLinesContaining "128.39.0.0" DeleteLinesContaining "128.39 255.255.255.0" } any.!Net75:: { /etc/defaultrouter AppendIfNoSuchLine "128.39.89.1" } Net75:: { /etc/defaultrouter AppendIfNoSuchLine "128.39.74.1" } any:: { /usr/openwin/lib/app-defaults/XConsole AppendIfNoSuchLine "XConsole.autoRaise: on" } # # CERT security patch for vold vulnerability # { /etc/rmmount.conf HashCommentLinesContaining "action cdrom" HashCommentLinesContaining "action floppy" } { /etc/inet/inetd.conf # ReplaceAll "/usr/sbin/in.ftpd" With "/local/iu/sbin/tcpd" # ReplaceAll "/usr/sbin/in.telnetd" With "/local/iu/sbin/tcpd" ReplaceAll "/usr/sbin/in.rshd" With "/local/iu/sbin/tcpd" ReplaceAll "/usr/sbin/in.rlogind" With "/local/iu/sbin/tcpd" HashCommentLinesContaining "rwall" HashCommentLinesContaining "/usr/sbin/in.fingerd" HashCommentLinesContaining "comsat" HashCommentLinesContaining "exec" AppendIfNoSuchLine "talk dgram udp wait root /usr/sbin/in.talkd in.talkd" HashCommentLinesContaining "echo" HashCommentLinesContaining "discard" HashCommentLinesContaining "charge" HashCommentLinesContaining "quotas" HashCommentLinesContaining "users" HashCommentLinesContaining "spray" HashCommentLinesContaining "sadmin" HashCommentLinesContaining "rquota" HashCommentLinesContaining "kcms" HashCommentLinesContaining "comsat" HashCommentLinesContaining "xaudio" HashCommentLinesContaining "uucp" HashCommentLinesContaining "tftp" HashCommentLinesContaining "/dt" HashCommentLinesContaining "tnamed" HashCommentLinesContaining "in.r" HashCommentLinesContaining "kerbd" HashCommentLinesContaining "rpc.rstatd" HashCommentLinesContaining "cachefsd" HashCommentLinesContaining "gssd" # HashCommentLinesContaining "telnet" } # # umask define when inetd starts is inherited by all subprocesses # this makes ftp post files open to the world { /etc/rc2.d/S72inetsvc PrependIfNoSuchLine "umask 022" HashCommentLinesContaining "/usr/sbin/in.named &" } !nexus:: { /etc/vfstab HashCommentLinesContaining "/iu/nexus/u1" HashCommentLinesContaining "/iu/nexus/u2" HashCommentLinesContaining "/iu/nexus/u3" HashCommentLinesContaining "/iu/nexus/u4" } ############################################################################ processes: # # Don't need CDE stuff # "ttdbserverd" signal=kill "dmispd" signal=kill "automount" signal=kill "kwmsound" signal=kill "hpnp" signal=kill "cmsd" signal=kill "nfsd" restart /usr/lib/nfs/nfsd useshell=false "mountd" restart /usr/lib/nfs/mountd useshell=false # xntpd virker ikke lenger... dessuten root exploit # "xntpd" restart "/local/bin/xntpd" useshell=false "xntpd" signal=kill "inetd" matches=>1 restart "/usr/sbin/inetd -s" !(nexus|quetzalcoatal|dax):: "kdm" restart "/local/kde/bin/kdm -nodaemon -config /local/iu/X11/xdm/xdm-config" nexus|quetzalcoatal|dax:: "kdm" signal=kill # quetzalcoatal:: # "sshd" signal=kill ### # # END cf.solaris # ### cfengine-2.2.10/inputs/cf.main.example0000644000175000001440000002210510202123437014473 00000000000000############################################################## # # cf.main - for iu.hio.no # # This file contains generic config stuff # ############################################################## ############### # # BEGIN cf.main # ############### control: Access = ( root ) # Only root should run this site = ( iu ) domain = ( iu.hio.no ) sysadm = ( cfengine@iu.hio.no ) smtpserver = ( nexus.iu.hio.no ) # Welcome to Norway...! timezone = ( MET CET ) # # Where backup files (for copy/tidy) are kept # Repository = ( /var/spool/cfengine ) LockDirectory = ( /var/cfengine ) LogDirectory = ( /var/cfengine ) # # Where extension modules can be found # moduledirectory = ( /var/cfengine/modules ) SpoolDirectories = ( /var/spool/cron/crontabs ) ################################################################### # # Spread the load, make sure the servers get done first though # ################################################################### !AllBinaryServers:: SplayTime = ( 1 ) ################################################################### # # Some local decisions ... # ################################################################### any:: OutputPrefix = ( "cf:$(host)" ) IfElapsed = ( 15 ) # Checks can be repeated only after 15 mins ExpireAfter = ( 240 ) # Hanging checks are killed after 4 hours SensibleSize = ( 1000 ) # Mounted disk looks normal if size > 1000 bytes SensibleCount = ( 2 ) # " if no files > 2 EditfileSize = ( 40000 ) # Will not edit files bigger than this # # Local convention for mounting file systems # e.g. /iu/nexus/u1. Home dirs are u1,u2,u3,u?,ua,ub ... # MountPattern = ( /$(site)/$(host) ) HomePattern = ( u? ) ################################################################### # # Security checks # ################################################################### NonAlphaNumFiles = ( on ) # Warn on filenames with non alphanumic chars FileExtensions = ( c gif jpg ) # Filenames which should NOT be directories # File/dir names which we should NOT be there SuspiciousNames = ( .mo lrk3 lkr3 nuke rootkit cloak zap icepick toneloc .ek wzap clnlog sniff.pid sp.pl ) ChecksumDatabase = ( /var/cfengine/cf.db3 ) # This should be on only when we are updating the db after AUTHORIZED changes ChecksumUpdates = ( on ) ################################################################### # # If we undefine this with cfengine -N longjob # then we switch off all jobs labelled with this class # ################################################################### AddClasses = ( longjob ) AddInstallable = ( rootfull ) AddInstallable = ( pcstudupdate ) AddInstallable = ( dns_update ) AddInstallable = ( syslodgdhup ) ################################################################### # # Macros & constants are inherited downwards in imports # but are not passed up to parent files. Good idea to # define them all here # ################################################################### cfbin = ( /var/cfengine/bin ) checksrc = ( /iu/nexus/ud/mark/comp ) gnu = ( "/local/gnu" ) ftp = ( /local/iu/ftp ) nisfiles = ( /iu/nexus/local/iu/etc ) # Stupid name, since we don't use NIS anymore masterfiles = ( /iu/nexus/local/iu ) ################################################################### # # The action sequence determines the order in which # checks are performed: action.class1.class2... # ################################################################### any:: actionsequence = ( editfiles copy mountall mountinfo checktimezone resolve netconfig unmount shellcommands addmounts links.Prepare files.Prepare directories links.Rest # mailcheck mountall required tidy.IfElapsed120.ExpireAfter240 disable editfiles files.Rest processes ) ################################################################### # # Network configuration. 74+75 are one subnet. 85 is one subnet. # ################################################################### nexus|quetzalcoatal|haddock:: interfacename = ( hme0 ) # A newer type of machine Net75:: netmask = ( 255.255.254.0 ) !Net75:: netmask = ( 255.255.255.0 ) ###################################################################### # # Strategies (mixed, randomised) # ###################################################################### strategies: OnTheHour:: { spread_load percent_10: "1" # These classes get defined in these ratios percent_30: "3" precent_60: "6" } ###################################################################### # # Server relationships for NFS filesystems # ###################################################################### # # Hosts which have home directory disks # homeservers: haddock|daneel:: nexus !haddock.!daneel:: nexus cube # # Hosts which have binary data (software) binservers: solaris:: nexus linux:: cube # # A list of all NFS mountable resources which # are available to *someone* within .iu.hio.no # mountables: any:: cube:/iu/cube/u1 cube:/iu/cube/u2 cube:/iu/cube/u3 cube:/iu/cube/u4 cube:/iu/cube/local nexus:/iu/nexus/local dax:/iu/dax/local nexus:/iu/nexus/local/iu/src 128_39_89|cube|matrix:: nexus:/iu/nexus/ua nexus:/iu/nexus/ub nexus:/iu/nexus/uc nexus:/iu/nexus/ud # # File systems which should be unmounted # and removed (old stuff) # unmount: # when removing mountables... # # NFS mounts which are not covered by binserver/homeserver # miscmounts: # # Even though nexus is software bin-type "solaris" # we need this partition even on non-solaris hosts # because it contains sharable data (for cfengine etc) # linux:: nexus:/iu/nexus/local /iu/nexus/local mode=ro ###################################################################### # # Routing configuration on local net # ###################################################################### broadcast: # # Modern convention for broadcast 1-bits == i.e. .255 # ones defaultroute: (128_39_74|128_39_75):: 128.39.74.1 128_39_89:: 128.39.89.1 ###################################################################### # # DNS configuration. Uninett make this complicated for us # because they own the routers and want to # keep their DNS records themselves # ###################################################################### resolve: NameServers.nexus:: 127.0.0.1 128.39.89.26 # quetx 128.39.74.16 # cube NameServers.!nexus:: 127.0.0.1 # loopback - itself 128.39.89.10 # nexus 128.39.74.16 # cube !NameServers.128_39_89:: 128.39.89.10 # nexus 128.39.89.26 # quetzalcoatal 128.39.74.16 # cube !NameServers.(128_39_74|128_39_75):: 128.39.74.16 # cube 128.39.89.10 # nexus 128.39.89.26 # quetzalcoatal ###################################################################### tidy: # # Some global tidy-ups which all hosts need # !rom21X:: /tmp/ pattern=* recurse=inf age=1 /var/tmp pattern=* recurse=inf age=2 / pattern=core r=1 a=0 /etc pattern=core r=1 a=0 ###################################################################### ignore: # # Don't check or tidy these files/directories in recursive # searches. They need exceptional treatment # # pseudo-filesystems: /dev /proc /devices /kernel ls-R mysql.sock /local/lib/gnu/emacs/lock/ /local/tmp ftp projects /local/bin/top /local/lib/tex/fonts /local/iu/etc /local/etc /local/iu/httpd/conf /usr/tmp/locktelelogic /usr/tmp/lockIDE RootMailLog lock /usr/bin/[ /usr/bin/pico /local/bin/pico # exclude this so we can search for copies (security) # # Emacs lock files etc # !* /local/lib/xemacs # # X11 keeps X server data in /tmp/.X11 # better not delete this! # .X* .Media* ##################################################################### disable: # # These files should never exist on any host # !rom21X:: /etc/hosts.equiv # rlogin security /etc/nologin # Prevents user login ############# # # END cf.main # ############# cfengine-2.2.10/inputs/cfrc.example0000644000175000001440000000007410202123437014076 00000000000000# sun4.maildir: /arfle/barfle/gloop # linux.fstab: /etc/bla cfengine-2.2.10/inputs/Makefile.in0000644000175000001440000002721611170173244013666 00000000000000# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = inputs DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/conf.h CONFIG_CLEAN_FILES = am__installdirs = "$(DESTDIR)$(pkgdatadir)" pkgdataSCRIPT_INSTALL = $(INSTALL_SCRIPT) SCRIPTS = $(pkgdata_SCRIPTS) SOURCES = DIST_SOURCES = DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BERKELEY_DB_CFLAGS = @BERKELEY_DB_CFLAGS@ BERKELEY_DB_LDFLAGS = @BERKELEY_DB_LDFLAGS@ BERKELEY_DB_LIB = @BERKELEY_DB_LIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EIGHTBIT = @EIGHTBIT@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCC_CFLAG = @GCC_CFLAG@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SELINUX = @LIB_SELINUX@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ NOWRAP = @NOWRAP@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_LIB_CPPFLAGS = @OPENSSL_LIB_CPPFLAGS@ OPENSSL_LIB_LDFLAGS = @OPENSSL_LIB_LDFLAGS@ OPENSSL_LIB_LIB = @OPENSSL_LIB_LIB@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PS2PDF = @PS2PDF@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TEXI2DVI = @TEXI2DVI@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ pkgdata_SCRIPTS = \ cf.chflags.example \ cf.freebsd.example \ cf.ftp.example \ cf.groups.example \ cf.linux.example \ cf.main.example \ cf.motd.example \ cf.preconf.example \ cf.services.example \ cf.site.example \ cf.solaris.example \ cf.sun4.example \ cf.users.example \ cfservd.conf.example \ cfagent.conf.example \ cfagent.conf-advanced.example \ update.conf.example \ cfrc.example \ cfrun.hosts.example EXTRA_DIST = $(pkgdata_SCRIPTS) # # Some basic clean ups # MOSTLYCLEANFILES = *~ # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu inputs/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu inputs/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh install-pkgdataSCRIPTS: $(pkgdata_SCRIPTS) @$(NORMAL_INSTALL) test -z "$(pkgdatadir)" || $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" @list='$(pkgdata_SCRIPTS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f $$d$$p; then \ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ echo " $(pkgdataSCRIPT_INSTALL) '$$d$$p' '$(DESTDIR)$(pkgdatadir)/$$f'"; \ $(pkgdataSCRIPT_INSTALL) "$$d$$p" "$(DESTDIR)$(pkgdatadir)/$$f"; \ else :; fi; \ done uninstall-pkgdataSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(pkgdata_SCRIPTS)'; for p in $$list; do \ f=`echo "$$p" | sed 's|^.*/||;$(transform)'`; \ echo " rm -f '$(DESTDIR)$(pkgdatadir)/$$f'"; \ rm -f "$(DESTDIR)$(pkgdatadir)/$$f"; \ done mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(SCRIPTS) installdirs: for dir in "$(DESTDIR)$(pkgdatadir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-pkgdataSCRIPTS install-dvi: install-dvi-am install-exec-am: install-html: install-html-am install-info: install-info-am install-man: install-pdf: install-pdf-am install-ps: install-ps-am installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-pkgdataSCRIPTS .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ distclean distclean-generic distclean-libtool distdir dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-pkgdataSCRIPTS install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ uninstall uninstall-am uninstall-pkgdataSCRIPTS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-2.2.10/inputs/cf.freebsd.example0000644000175000001440000000327210202123437015165 00000000000000################################################################# # # cf.bsd - for iu.hioslo.no # # This file contains bsd specific patches # ################################################################# ### # # BEGIN cf.bsd # ### links: /usr/spool -> /var/spool /local/bin/tcsh -> /bin/tcsh /local/bin/perl -> /usr/bin/perl /usr/lib/sendmail -> /usr/sbin/sendmail ################################################################# files: /usr/tmp mode=1777 owner=root action=fixall ################################################################# editfiles: { /etc/inetd.conf AppendIfNoSuchLine "finger stream tcp nowait daemon /local/etc/in.fingerd in.fingerd" AppendIfNoSuchLine "cfinger stream tcp nowait daemon /local/etc/in.cfingerd in.cfingerd" } # # Comment out all lines to shut up this annoying cfengine-like # script, which sends mail every day!!! # { /etc/crontab HashCommentLinesContaining "daily" HashCommentLinesContaining "weekly" HashCommentLinesContaining "monthly" } ################################################################# directories: # # Make printer spool directories... # /var/spool/VirtualLight o=root g=other mode=755 ######################################################################### copy: $(masterfiles)/etc/printcap.client dest=/etc/printcap mode=0644 ######################################################################### shellcommands: "/local/iu/bin/BSD-pw-update" !Hourly:: "/usr/libexec/locate.updatedb" "/usr/bin/makewhatis /usr/share/man:/usr/X11R6/man:/usr/local/man:/local/gnu/man" ### # # END cf.bsd # ### cfengine-2.2.10/inputs/cf.site.example0000644000175000001440000003627510202123437014530 00000000000000################################################################ # # cf.site - for iu.hio.no # # This file contains site specific data and system policy # ################################################################# ### # # BEGIN cf.site # ### classes: # groups # # If this file exists, then ssh has been installed ok # Setup_SSH_OK = ( '/usr/bin/test -f /etc/ssh2/ssh2_config' ) ################################################################# links: Prepare:: # # "local" software is always mounted /iu/nexus/local # or /iu/cube/local, but we really want these to look # like they are mounted at /usr/local or /local # /local -> /$(site)/$(binserver)/local /usr/local -> /local dax:: # # On dax /iu/dax/local is only a small a partition # large enough to hold the SDT simulation software # which is specially licensed to dax. This fills in # the blanks in /iu/dax/local by linking to nexus. # /iu/dax/local +> /iu/nexus/local # # Different people like to see perl installed # in different places # solaris:: /usr/bin/perl5 -> /local/bin/perl /usr/bin/perl -> /local/bin/perl # So that stupid perl/cgi can find it... /lib/libgdbm.so.1 -> /local/lib/libgdbm.so.1 cube:: /local/etc/fingerdir -> /iu/nexus/local/etc/fingerdir ###################################################################### # Other package installation fixes ###################################################################### nexus:: /local/bin/acroread -> /local/Acrobat4/bin/acroread /local/bin/xmgr -> /local/xmgr/bin/xmgr /local/lib/xemacs/site-lisp/site-start.el -> /iu/nexus/local/iu/lib/EmacsCStyleLisp /iu/nexus/ua/www-data/www/local/latex2html/icons.gif -> /local/latex2html/icons.gif AllBinaryServers:: # # KDE Setup # /local/kde/share/applnk/Graphics/Gimp.kdelnk ->! /iu/nexus/local/iu/lib/KdeSetup/Gimp.kdelnk /local/kde/share/applnk/apps/Internet/TkRat.kdelnk ->! /iu/nexus/local/iu/lib/KdeSetup/TkRat.kdelnk /local/kde/share/applnk/apps/WordProcessing/office.kdelnk ->! /iu/nexus/local/iu/lib/KdeSetup/office.kdelnk /local/kde/share/applnk/apps/Graphic/xmgr.kdelnk ->! /iu/nexus/local/iu/lib/KdeSetup/xmgr.kdelnk /local/kde/share/applnk/apps/Utilities/xterm.kdelnk ->! /iu/nexus/local/iu/lib/KdeSetup/xterm.kdelnk /local/kde/share/applnk/apps/Development/freebuilder.kdelnk ->! /iu/nexus/local/iu/lib/KdeSetup/freebuilder.kdelnk /local/kde/share/config/kpanelrc ->! /iu/nexus/local/iu/lib/KdeSetup/kpanelrc /local/kde/share/config/kdisplayrc ->! /iu/nexus/local/iu/lib/KdeSetup/kdisplayrc /local/kde/share/applnk/apps/Utilities/ical.kdelnk ->! /iu/nexus/local/iu/lib/KdeSetup/ical.kdelnk solaris:: /local/kde/share/applnk/apps/Development/javaworkshop.kdelnk ->! /iu/nexus/local/iu/lib/KdeSetup/javaworkshop.kdelnk # # KDM Setup # nexus:: /local/kde/share/config/kdmrc ->! /iu/nexus/local/iu/lib/kdmrcSolaris cube:: /local/kde/share/config/kdmrc ->! /iu/nexus/local/iu/lib/kdmrcLinux debian.!rom21X:: /etc/rc2.d/S13kdm ->! /iu/nexus/local/iu/etc/S13kdm ############################################################### disable: # # CERT warning, security fix # any:: /usr/lib/expreserve rootfull.solaris:: /var/log/syslog rotate=empty inform=true # Don't allow running the passwd program on any host except nexus & daneel !nexus.!daneel.!rom21X:: /usr/bin/passwd repository=none # solaris:: # /usr/lib/login repository=none inform=true ################################################################# # # Some very basic security file permissions # ################################################################ files: nexus:: /local/iu/Admin r=inf owner=root mode=600 action=fixall CheckIntegrity.Rest.AllBinaryServers:: /iu/$(host)/local owner=root,bin,man,daemon,www-data group=root,daemon,bin,staff,www-data,adm,other,sys action=warnall mode=o-w r=inf checksum=md5 syslog=true ignore=fingerdir ignore=cfengine ignore=var ignore=etc ignore=dns ignore=mail ignore=lprng ignore=src ignore=logs ignore=texmf ignore=log ignore=locks ignore=aliases ignore=conf ignore=servlets exclude=*.log ignore=jserv ignore=real exclude=CheckRealServer ignore=pluto exclude=.bash_history exclude=*.db nexus:: # /iu/nexus/ECG mode=770 g=ecg act=fixall r=inf /etc/passwd o=root checksum=md5 action=fixall nexus.Hr12.OnTheHour:: $(checksrc) o=mark r=inf checksum=md5 action=warnall debian||solaris:: /etc/inetd.conf o=root checksum=md5 action=fixall Prepare.!rom21X:: /.cshrc m=0644 r=0 o=root act=touch /tmp/screens/. m=0755 o=root act=touch /var/spool/cron m=755 act=fixall Prepare.!rom21X:: # openssh... /etc/ssh2/ssh2_config m=644 o=root g=0 act=fixall /etc/ssh2/sshd2_config m=644 o=root g=0 act=fixall nexus:: /local/teTeX/texmf/ls-R m=666 o=root act=fixplain #/local/iu/etc/passwd m=0644 o=root g=other action=fixplain # These files contain passwords to databases /iu/nexus/ua/mysql/UpdateEmployDB.php o=mysql mode=700 action=fixall /iu/nexus/ua/mysql/UpdateStudentDB.php o=mysql mode=700 action=fixall /iu/nexus/ua/mysql/UpdateCalendarDB.php o=mysql mode=700 action=fixall /iu/nexus/ua/mysql/GetAliases.php o=mysql mode=700 action=fixall nexus.Hr18.OnTheHour:: /etc/mnttab m=644 act=fixall # S/KEY installation /etc/skeykeys mode=644 o=root action=touch ################################################################# # # Some routine file tidying # ################################################################# tidy: # # Make sure the file repository doesn't fill up # /var/spool/cfengine pattern=* age=0 # # Nothing needs to be in /tmp more than a day # !rom21X:: /tmp pattern=.* age=1 r=inf /tmp pattern=* age=1 r=inf rmdirs=sub type=mtime Hr05.(nexus|quetzalcoatal):: /local pattern=core age=0 r=inf ignore: latex2html ################################################################# shellcommands: PasswdServer:: # Build and install the BSD compatible passwd file for GNU/Linux # from the master passwd/shadow file on solaris "/local/iu/bin/BuildPasswdFiles" "/local/iu/bin/BuildGroupFiles" nexus.Sunday.Hr15.OnTheHour:: # # See how much rubbish users have accumulated on disks # Sends no automatic warnings even if they exceed 60MB # "$(cfbin)/noseyparker /iu/nexus/ua ${sysadm} nomail" "$(cfbin)/noseyparker /iu/nexus/ub ${sysadm} nomail" "$(cfbin)/noseyparker /iu/nexus/uc ${sysadm} nomail" "$(cfbin)/noseyparker /iu/nexus/ud ${sysadm} nomail" cube.Sunday.Hr16.OnTheHour:: # # See how much rubbish users have accumulated on disks # Sends automatic warnings if they exceed 60MB # "$(cfbin)/noseyparker /iu/cube/u1 ${sysadm} " "$(cfbin)/noseyparker /iu/cube/u2 ${sysadm} " "$(cfbin)/noseyparker /iu/cube/u3 ${sysadm} " "$(cfbin)/noseyparker /iu/cube/u4 ${sysadm} nomail" # # Update the ls-lR database for TeX # nexus.Hr01.OnTheHour:: "/local/iu/bin/TexRehash > /dev/null 2>&1" !Setup_SSH_OK.!rom21X:: # If ssh is not properly installed, install it! "/local/iu/bin/SetupSSH" ############################################################### editfiles: nexus:: # # Disable the reboot/shutdown button on the KDM login # What were they THINKING?! # { /local/iu/lib/kdmrcSolaris ReplaceAll "K Desktop Environment" With "Sun/Solaris" CommentLinesMatching ".*ShutdownButton=RootOnly.*" AppendIfNoSuchLine "ShutdownButton=ConsoleOnly" } { /local/iu/lib/kdmrcLinux ReplaceAll "K Desktop Environment" With "Debian GNU/Linux" CommentLinesMatching ".*ShutdownButton=RootOnly.*" AppendIfNoSuchLine "ShutdownButton=ConsoleOnly" } ###################################################################### required: # # Any host must have a /local, /usr/local fs. Check that # it exists and looks sensible. (i.e. not empty) # If free space falls below 50mb start declare an emergency # as a signal to "tidy" # / freespace=10mb define=rootfull /${site}/${binserver}/local 128_39_89:: /iu/nexus/ua freespace=50mb define=emergency /iu/nexus/ub freespace=50mb define=emergency /iu/nexus/uc freespace=50mb define=emergency /iu/nexus/ud freespace=50mb define=emergency !haddock.!daneel:: /iu/cube/u1 freespace=50mb define=emergency /iu/cube/u2 freespace=50mb define=emergency /iu/cube/u3 freespace=50mb define=emergency /iu/cube/u4 freespace=50mb define=emergency ########################################################################### copy: /iu/nexus/local/iu/etc/keys dest=/var/cfengine/keys mode=400 o=root server=nexus # # make sure the password file is distributed # solaris.PasswordClients:: /etc/passwd dest=/etc/passwd server=nexus type=checksum mode=644 o=root secure=true /etc/shadow dest=/etc/shadow server=nexus type=checksum mode=600 o=root secure=true !solaris.PasswordClients:: /etc/shadow dest=/etc/shadow server=nexus type=checksum mode=640 o=root g=shadow size=>20k nexus:: # The alias-data contains both staff and students /iu/nexus/ua/mysql/aliasdata dest=/local/iu/aliases/aliases o=root g=root mode=644 type=sum define=alias_update # /etc/passwd dest=/iu/nexus/local/iu/etc/passwd mode=644 size=>500 # /etc/shadow dest=/iu/nexus/local/iu/etc/shadow mode=644 size=>50 solaris.!haddock:: $(nisfiles)/group.solaris dest=/etc/group server=nexus mode=644 (debian.PasswordClients)|daystrom:: $(nisfiles)/passwd.slinux dest=/etc/passwd type=checksum server=nexus mode=644 o=root size=>50k $(nisfiles)/group.linux dest=/etc/group server=nexus mode=644 size=>100 # # Some other basic system files are distributed # # any:: # ssh_known_hosts er ssh v1... # $(nisfiles)/ssh_known_hosts dest=/etc/ssh_known_hosts o=root mode=644 !rom21X:: $(nisfiles)/shells dest=/etc/shells mode=644 any:: $(nisfiles)/etc_profile dest=/etc/profile o=root mode=644 solaris:: $(nisfiles)/services dest=/etc/inet/services mode=644 debian:: $(nisfiles)/services dest=/etc/services mode=644 # # Mirror some filesystems, for backup # quetzalcoatal.Hr01.OnTheHour:: /iu/nexus/local dest=/iu/quetzalcoatal/local typecheck=false r=inf server=nexus ignore=src ignore=logs ignore=log ignore=var sigmund.Hr01.OnTheHour:: /iu/cube/local dest=/iu/sigmund/local r=inf server=cube ignore=src ignore=logs ignore=log exclude=httpd.conf ignore=/iu/cube/local/iu/httpd/htdocs ignore=/iu/cube/local/iu/X11 pax.OnTheHour:: # this is really important! /iu/nexus/private dest=/iu/pax/backup/private server=nexus r=inf mode=600 FTPServers:: # # If /etc/shells does not conatin your shell, you # cannot use FTP! # /local/iu/etc/shells dest=/etc/shells m=0644 # debian:: # To prevent the use of kvt ... Modified file invokes xterm instead # /local/iu/etc/kvt.kdelnk dest=/local/kde/share/applnk/Utilities/kvt.kdelnk m=644 ##################################################################### # # Some processes that we do not / do want running # ##################################################################### processes: "cfenvd" restart "/usr/local/sbin/cfenvd" useshell=false "eggdrop" signal=kill # exclude=solluna exclude=holterr "BitchX" signal=kill "enting" signal=kill "bnc" signal=kill "mount -o" signal=term # these should not hang around. If they do, # then the RPC is fucked, pardon my french "cron" signal=hup inform=false # Get cron to reread config file DayTime:: "rc5des" signal=kill "stst" signal=kill linux:: SetOptionString "aucx" any.Hr23:: # # Kill user-processes over a day old. At Hr23 because linux ps - wrongly - # reports processes as a day old when it has started before 00.00 (which isn't # exactly accurate) # "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec" signal=kill include=ftpd include=tcsh include=bash include=xterm include=kio include=kaudio include=maudio include=netscape include=ftp include=tkrat include=pine include=perl include=irc include=kfm include=freebuild include=javac include=/bin/ls include=emacs include=passwd include=ls include=less include=more include=man include=pvm3 include=pvmd3 include=lpr include=communicator include=kbgndwm include=krootwm include=utmp_update include=sdtpm include=sdthelp include=sdtsan include=staroffice include=kvt include=kwm include=server include=konsole include=kghostview include=alarmd include=ssh2 include=ping include=ssh exclude=sshd exclude=sowille exclude=rmserver # Real Streaming Server "maudio" signal=kill "kaudio" signal=kill # # Kill processes which have run on for too long e.g. 999:99 cpu time # Careful - a pattern to match 99:99 will kill everything! # "[0-9][0-9][0-9][0-9]:[0-9][0-9]" signal=term exclude=root exclude=daemon "[0-9][0-9][0-9]:[0-9][0-9]" signal=term exclude=root exclude=daemon Hr05:: # # Make sure these die. The above regex only works half the time! # "ftp" signal=kill "netscape" signal=kill nexus:: "irc" signal=kill # :-) better still, all machines! ###################################################################### # # Define some ACLs useful for www # acl: { WWWacl # For CGI scripts which write to a special directory fstype:posix method:overwrite mask:*:rwx user:*:rwx group:*:r-x other:*:r user:www:=rwx # Need me and www because the file will end up with owner user:mark:=rwx # www as run by httpd # default_mask:=rwx # default_user:=rwx # default_group:=r # default_other:=r } ###################################################################### directories: # Guestbook management (nexus|cube).Hr05:: home/www/cgi-out owner=www ######################################################################## copy: nexus.Hr05:: /local/iu/etc/README.cgi dest=home/www/cgi-out/README.cgi mode=644 o=www backup=false # Cgi scripts can write freely here without being setuid ######### # # END cf.site # ######### cfengine-2.2.10/inputs/cf.preconf.example0000744000175000001440000000246710202123437015215 00000000000000#!/bin/sh # # cf.preconf is an emergency/bootstrap file to get things going # in case cfengine is unable to parse its config file # backupdir=/iu/nexus/local/iu/etc # # If these files don't exist, you might not be able to parse cfengine.conf # if [ ! -s /etc/resolv.conf ]; then echo Patching basics resolv.conf file cat > /etc/resolv.conf << XX domain iu.hio.no nameserver 128.39.89.10 nameserver 158.36.144.156 XX fi # # SVR4 # if [ "$1" = "solaris" ]; then if [ ! -s "/etc/passwd" ]; then echo Patching missing passwd file /bin/cp $backupdir/passwd /etc/passwd fi if [ ! -s "/etc/shadow" ]; then echo Patching missing passwd file /bin/cp $backupdir/shadow /etc/shadow fi if [ ! -s "/etc/group" ]; then echo Patching missing group file /bin/cp $backupdir/group.solaris /etc/group fi if [ "`/bin/egrep dns /etc/nsswitch.conf`" = "" ]; then /bin/cp $backupdir/nsswitch.standalone /etc/nsswitch.conf fi fi # # BSD 4.3 # if [ "$1" = "linux" ]; then if [ ! -s "/etc/passwd" ] then echo Patching missing passwd file /bin/cp $backupdir/passwd.slinux /etc/passwd fi if [ ! -s "/etc/group" ] then echo Patching missing group file /bin/cp $backupdir/group.linux /etc/group fi fi ######## # # END cf.preconf # ######## cfengine-2.2.10/inputs/cfagent.conf-advanced.example0000644000175000001440000000156310202123437017263 00000000000000############################################## # # cfagent.conf # # This file is for root only. # ############################################## ### # # BEGIN cfengine.conf (Only hard classes in this file ) # ### import: # # Split things up to keep things tidy # any:: cf.groups cf.main any.!matrix:: cf.site cf.services cf.motd cf.printer cf.www cf.mail hpux:: cf.hpux debian.!matrix:: cf.debian redhat:: cf.redhat SuSE:: cf.suse solaris:: cf.solaris sun4:: cf.sun4 ultrix:: cf.ultrix freebsd:: cf.freebsd nexus|dax|cube|pax:: cf.users matrix:: cf.matrix ### # # END cfengine.conf # ### cfengine-2.2.10/inputs/Makefile.am0000644000175000001440000000177610202123437013652 00000000000000pkgdata_SCRIPTS = \ cf.chflags.example \ cf.freebsd.example \ cf.ftp.example \ cf.groups.example \ cf.linux.example \ cf.main.example \ cf.motd.example \ cf.preconf.example \ cf.services.example \ cf.site.example \ cf.solaris.example \ cf.sun4.example \ cf.users.example \ cfservd.conf.example \ cfagent.conf.example \ cfagent.conf-advanced.example \ update.conf.example \ cfrc.example \ cfrun.hosts.example EXTRA_DIST = $(pkgdata_SCRIPTS) # # Some basic clean ups # MOSTLYCLEANFILES = *~ # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in cfengine-2.2.10/contrib/0000777000175000001440000000000011170173454012016 500000000000000cfengine-2.2.10/contrib/cfengine.el0000644000175000001440000002650310265661776014055 00000000000000;;; cfengine.el --- An Emacs major-mode for editing cfengine scripts ;;; Copyright (C) 1997 Rolf Ebert ;;; Authors: Rolf Ebert ;;; Keywords: languages ;;; Rolf Ebert's version: cfengine.el-V1_1 ;;; This file is not part of GNU Emacs or XEmacs. ;; cfengine.el 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, or (at your option) ;; any later version. ;; cfengine.el 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 cfengine; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. ;; USAGE: ;; I have the following lines in my .emacs ;; ; autoload when needed ;; (autoload 'cfengine-mode "cfengine" "" t nil) ;; ; start colour highlighting ;; ; if GNU Emacs >= 19.31 ;; ; (global-font-lock-mode t) ;; ; if XEmacs ;; (add-hook 'cfengine-mode-hook 'turn-on-font-lock) ;; ; detect file type by name (cf.*) ;; (setq auto-mode-alist (append '(("cf\\." . cfengine-mode)) ;; auto-mode-alist)) (defvar cfengine-indent 3 "*Defines the size of Cfengine indentation.") (defvar cfengine-mode-abbrev-table nil "Abbrev table used in Cfengine mode.") (define-abbrev-table 'cfengine-mode-abbrev-table ()) (defvar cfengine-mode-map () "Local keymap used for Cfengine mode.") (defvar cfengine-mode-syntax-table nil "Syntax table to be used for editing Cfengine source code.") (defvar cfengine-mode-hook nil "*List of functions to call when Cfengine mode is invoked. This is a good place to add specific bindings.") ;;;------------- ;;; functions ;;;------------- (defun cfengine-xemacs () (or (string-match "Lucid" emacs-version) (string-match "XEmacs" emacs-version))) (defun cfengine-create-syntax-table () "Create the syntax table for Cfengine mode." (setq cfengine-mode-syntax-table (make-syntax-table (standard-syntax-table))) (set-syntax-table cfengine-mode-syntax-table) ;; string ;(modify-syntax-entry ?\" "\"" cfengine-mode-syntax-table) ;(modify-syntax-entry ?\' "\"" cfengine-mode-syntax-table) ;(modify-syntax-entry ?\` "\"" cfengine-mode-syntax-table) (modify-syntax-entry ?\" "." cfengine-mode-syntax-table) (modify-syntax-entry ?\' "." cfengine-mode-syntax-table) (modify-syntax-entry ?\` "." cfengine-mode-syntax-table) ;; comment (modify-syntax-entry ?# "<" cfengine-mode-syntax-table) (modify-syntax-entry ?\f ">" cfengine-mode-syntax-table) (modify-syntax-entry ?\n ">" cfengine-mode-syntax-table) (modify-syntax-entry ?% "." cfengine-mode-syntax-table) (modify-syntax-entry ?: "." cfengine-mode-syntax-table) (modify-syntax-entry ?\; "." cfengine-mode-syntax-table) (modify-syntax-entry ?& "." cfengine-mode-syntax-table) (modify-syntax-entry ?\| "." cfengine-mode-syntax-table) (modify-syntax-entry ?+ "." cfengine-mode-syntax-table) (modify-syntax-entry ?* "." cfengine-mode-syntax-table) (modify-syntax-entry ?/ "." cfengine-mode-syntax-table) (modify-syntax-entry ?= "." cfengine-mode-syntax-table) (modify-syntax-entry ?< "." cfengine-mode-syntax-table) (modify-syntax-entry ?> "." cfengine-mode-syntax-table) (modify-syntax-entry ?$ "." cfengine-mode-syntax-table) (modify-syntax-entry ?. "." cfengine-mode-syntax-table) (modify-syntax-entry ?\\ "." cfengine-mode-syntax-table) (modify-syntax-entry ?- "." cfengine-mode-syntax-table) ;; define what belongs in symbols (modify-syntax-entry ?_ "_" cfengine-mode-syntax-table) ;; define parentheses to match (modify-syntax-entry ?\( "()" cfengine-mode-syntax-table) (modify-syntax-entry ?\) ")(" cfengine-mode-syntax-table) ) ;;;###autoload (defun cfengine-mode () "Cfengine mode is the major mode for editing Cfengine code. Bindings are as follows: Indent line '\\[cfengine-tab]' Indent line, insert newline and indent the new line. '\\[newline-and-indent]' Comments are handled using standard Emacs conventions, including: Start a comment '\\[indent-for-comment]' Comment region '\\[comment-region]' Uncomment region '\\[cfengine-uncomment-region]' Continue comment on next line '\\[indent-new-comment-line]' " (interactive) (kill-all-local-variables) (make-local-variable 'require-final-newline) (setq require-final-newline t) (make-local-variable 'comment-start) (setq comment-start "# ") ;; comment end must be set because it may hold a wrong value if ;; this buffer had been in another mode before. RE (make-local-variable 'comment-end) (setq comment-end "") (make-local-variable 'comment-start-skip) ;; used by autofill (setq comment-start-skip "#+[ \t]*") (make-local-variable 'indent-line-function) (setq indent-line-function 'cfengine-indent-current-function) (make-local-variable 'fill-column) (setq fill-column 75) (make-local-variable 'comment-column) (setq comment-column 40) (make-local-variable 'parse-sexp-ignore-comments) (setq parse-sexp-ignore-comments t) (make-local-variable 'case-fold-search) (setq case-fold-search t) (make-local-variable 'outline-regexp) (setq outline-regexp "[^\n\^M]") (make-local-variable 'outline-level) (setq outline-level 'cfengine-outline-level) (make-local-variable 'fill-paragraph-function) (setq fill-paragraph-function 'cfengine-fill-comment-paragraph) ;;(make-local-variable 'adaptive-fill-regexp) (if (cfengine-xemacs) nil ; XEmacs uses properties (make-local-variable 'font-lock-defaults) (setq font-lock-defaults '((cfengine-font-lock-keywords cfengine-font-lock-keywords-1 cfengine-font-lock-keywords-2) nil t ((?\_ . "w")) beginning-of-line ))) (setq major-mode 'cfengine-mode) (setq mode-name "Cfengine") (use-local-map cfengine-mode-map) (if cfengine-mode-syntax-table (set-syntax-table cfengine-mode-syntax-table) (cfengine-create-syntax-table)) ;; add menu 'Cfengine' to the menu bar ; (cfengine-add-cfengine-menu) (run-hooks 'cfengine-mode-hook)) ;;;----------------------;;; ;;; Behaviour Of TAB Key ;;; ;;;----------------------;;; (defun cfengine-tab () "Do indenting or tabbing according to `cfengine-tab-policy'." (interactive) (cond (1 (cfengine-tab-hard)) ((eq cfengine-tab-policy 'indent-auto) (cfengine-indent-current)) )) (defun cfengine-untab () "Do dedenting or detabbing." (interactive) (cfengine-untab-hard)) (defun cfengine-indent-current-function () "Cfengine mode version of the indent-line-function." (interactive "*") (let ((starting-point (point-marker))) (cfengine-beginning-of-line) (cfengine-tab) (if (< (point) starting-point) (goto-char starting-point)) (set-marker starting-point nil) )) (defun cfengine-tab-hard () "Indent current line to next tab stop." (interactive) (save-excursion (beginning-of-line) (insert-char ? cfengine-indent)) (if (save-excursion (= (point) (progn (beginning-of-line) (point)))) (forward-char cfengine-indent))) (defun cfengine-untab-hard () "indent current line to previous tab stop." (interactive) (let ((bol (save-excursion (progn (beginning-of-line) (point)))) (eol (save-excursion (progn (end-of-line) (point))))) (indent-rigidly bol eol (- 0 cfengine-indent)))) ;;;---------------;;; ;;; Miscellaneous ;;; ;;;---------------;;; (defun cfengine-uncomment-region (beg end) "delete `comment-start' at the beginning of a line in the region." (interactive "r") (comment-region beg end -1)) ;;;----------------------- ;;; define keymap for Cfengine ;;;----------------------- (if (not cfengine-mode-map) (progn (setq cfengine-mode-map (make-sparse-keymap)) ;; Indentation and Formatting (define-key cfengine-mode-map "\C-j" 'cfengine-indent-newline-indent) (define-key cfengine-mode-map "\t" 'cfengine-tab) (if (cfengine-xemacs) (define-key cfengine-mode-map '(shift tab) 'cfengine-untab) (define-key cfengine-mode-map [S-tab] 'cfengine-untab)) ; (define-key cfengine-mode-map "\M-\C-e" 'cfengine-next-procedure) ; (define-key cfengine-mode-map "\M-\C-a" 'cfengine-previous-procedure) ; (define-key cfengine-mode-map "\C-c\C-a" 'cfengine-move-to-start) ; (define-key cfengine-mode-map "\C-c\C-e" 'cfengine-move-to-end) (define-key cfengine-mode-map "\177" 'backward-delete-char-untabify) ;; Use predefined function of emacs19 for comments (RE) (define-key cfengine-mode-map "\C-c;" 'comment-region) (define-key cfengine-mode-map "\C-c:" 'cfengine-uncomment-region) )) ;;;------------------- ;;; define menu 'Cfengine' ;;;------------------- (require 'easymenu) (defun cfengine-add-cfengine-menu () "Adds the menu 'Cfengine' to the menu bar in Cfengine mode." (easy-menu-define cfengine-mode-menu cfengine-mode-map "Menu keymap for Cfengine mode." '("Cfengine" ; ["Next Package" cfengine-next-package t] ; ["Previous Package" cfengine-previous-package t] ; ["Next Procedure" cfengine-next-procedure t] ; ["Previous Procedure" cfengine-previous-procedure t] ; ["Goto Start" cfengine-move-to-start t] ; ["Goto End" cfengine-move-to-end t] ; ["------------------" nil nil] ["Indent Current Line (TAB)" cfengine-indent-current-function t] )) (if (cfengine-xemacs) (progn (easy-menu-add cfengine-mode-menu) (setq mode-popup-menu (cons "Cfengine mode" cfengine-mode-menu))))) ;;;--------------------------------------------------- ;;; support for font-lock ;;;--------------------------------------------------- (defconst cfengine-font-lock-keywords-1 (list ;; actions (list "^[ \t]*\\([a-zA-Z0-9]+\\):[^:]" '(1 font-lock-keyword-face) ) ) "Subdued level highlighting for Cfengine mode.") (defconst cfengine-font-lock-keywords-2 (append cfengine-font-lock-keywords-1 (list ;; ;; classes = alphanum or ().|! '("^[ \t]*\\([a-zA-Z0-9_\\(\\)\\.\\|\\!]+\\)::" (1 font-lock-function-name-face)) ;; ;; variables '("\\$[{(]\\([a-zA-Z0-9_]+\\)[)}]" (1 font-lock-variable-name-face)) )) "Gaudy level highlighting for Cfengine mode.") (defvar cfengine-font-lock-keywords cfengine-font-lock-keywords-2 "Default expressions to highlight in Cfengine mode.") ;; set font-lock properties for XEmacs (if (cfengine-xemacs) (put 'cfengine-mode 'font-lock-defaults '(cfengine-font-lock-keywords nil t ((?\_ . "w")) beginning-of-line))) ;;; ;;; support for outline ;;; ;; used by outline-minor-mode (defun cfengine-outline-level () (save-excursion (skip-chars-forward "\t ") (current-column))) ;;; provide ourself (provide 'cfengine-mode) ;;; cfengine.el ends here cfengine-2.2.10/contrib/cfdoc0000744000175000001440000001012010202123450012710 00000000000000#!/usr/bin/perl # # Copyright (C) 1995 Andrew Ford # # 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. # # cfdoc -- Simple utility to document a cfengine configuration file # (or other configuration file that uses '#' in the first # line to indicate comments). # # Author: # Andrew Ford Email: andrew@icarus.demon.co.uk # Independent Software Consultant WWW: http://www.nhbs.co.uk/aford/aford.html # "Brittany", Wells Road, Tel: +44 1452 770836 Fax: 770835 # Eastcombe, Stroud, GL6 7EE, GB Mobile: +44 385 258278 # # Comments starting in column 0 are regarded as text to be typeset (this # can contain arbitrary markup), while other lines are regarded as code # to be set in a verbatim environment. The default comment indicator is # '#' and verbatim environments are enclosed in \begin{verbatim} and # \end{verbatim} pairs, but this behaviour can be overridden with command # line options. # &parse_cmd_line; &format_file; # Format a file sub format_file { while (<>) { # Start state - look for "#!/" on first line and ignore if found. next if /^\#!(.*)/ && !$state++; chop if /\n$/; # Lines that start with a '#' in the first column are printed # without the '#' # If the previous line was not part of a comment then the # currently open verbatim environment is closed. if (/^$comment_marker\s*(.*)/) { if ($in_code) { print($end_verbatim); $in_code = 0; } print("$1\n"); $blank_lines = 0; } # Other lines are printed in a verbatim environment (which # is opened if not already open). # Blank lines are counted and only output if they apear within # a block of code. else { $blank_lines++, next if /^\s*$/; if (!$in_code) { print($start_verbatim); $in_code = 1; } elsif ($blank_lines) { foreach $i (1 .. $blank_lines) { print("\n"); } $blank_lines = 0; } print("$_\n"); } } print $end_verbatim if $in_code; } # Parse the command line sub parse_cmd_line { $comment_marker = "#"; $latex_start_verbatim = "\\begin{verbatim}\n"; $latex_end_verbatim = "\\end{verbatim}\n"; $html_start_verbatim = "
\n";
    $html_end_verbatim      = "
\n"; $texinfo_start_verbatim = "\@smallexample\n"; $texinfo_end_verbatim = "\@end smallexample\n"; $start_verbatim = $latex_start_verbatim; $end_verbatim = $latex_end_verbatim; $usage = "usage: $0 [options] , June 1995 # # 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, 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. # Prevent date giving response in another language. LANG=C export LANG LC_ALL=C export LC_ALL LC_TIME=C export LC_TIME # Get the extended ls output of the file or directory. # On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. if ls -L /dev/null 1>/dev/null 2>&1; then set - x`ls -L -l -d $1` else set - x`ls -l -d $1` fi # The month is at least the fourth argument # (3 shifts here, the next inside the loop). shift shift shift # Find the month. Next argument is day, followed by the year or time. month= until test $month do shift case $1 in Jan) month=January; nummonth=1;; Feb) month=February; nummonth=2;; Mar) month=March; nummonth=3;; Apr) month=April; nummonth=4;; May) month=May; nummonth=5;; Jun) month=June; nummonth=6;; Jul) month=July; nummonth=7;; Aug) month=August; nummonth=8;; Sep) month=September; nummonth=9;; Oct) month=October; nummonth=10;; Nov) month=November; nummonth=11;; Dec) month=December; nummonth=12;; esac done day=$2 # Here we have to deal with the problem that the ls output gives either # the time of day or the year. case $3 in *:*) set `date`; eval year=\$$# case $2 in Jan) nummonthtod=1;; Feb) nummonthtod=2;; Mar) nummonthtod=3;; Apr) nummonthtod=4;; May) nummonthtod=5;; Jun) nummonthtod=6;; Jul) nummonthtod=7;; Aug) nummonthtod=8;; Sep) nummonthtod=9;; Oct) nummonthtod=10;; Nov) nummonthtod=11;; Dec) nummonthtod=12;; esac # For the first six month of the year the time notation can also # be used for files modified in the last year. if (expr $nummonth \> $nummonthtod) > /dev/null; then year=`expr $year - 1` fi;; *) year=$3;; esac # The result. echo $day $month $year cfengine-2.2.10/LICENSE0000644000175000001440000010516711160206605011303 00000000000000 This program is provided under the terms of the GNU public license (below), with explicit permission to link with the OpenSSL library. (http://www.openssl.org) On some systems, code under the Frontier Artistic License (/pub/snprintf) might become compiled. This is compatible with the GPL. GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. 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 state 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) 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 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program 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, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU 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 Lesser General Public License instead of this License. But first, please read . cfengine-2.2.10/doc/0000777000175000001440000000000011170173463011123 500000000000000cfengine-2.2.10/doc/cfetooldump.80000644000175000001440000001617510261007205013451 00000000000000.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "CFETOOLDUMP 1" .TH CFETOOLDUMP 1 "2004-09-21" "perl v5.8.4" "User Contributed Perl Documentation" .SH "NAME" cfetool dump \- dump the contents of a database in XML format .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBcfetool\fR \fBdump\fR \fIname\fR [\fB\-\-path\fR|\fB\-p\fR\ \fIdirectory\ name\fR] [\fB\-\-file\fR|\fB\-f\fR\ \fIfilename\fR] [\fB\-\-daily\fR|\fB\-d\fR] [\fB\-\-weekly\fR|\fB\-w\fR] [\fB\-\-yearly\fR|\fB\-y\fR] [\fB\-\-verbose\fR|\fB\-v\fR] [\fB\-\-help\fR|\fB\-h\fR] .SH "DESCRIPTION" .IX Header "DESCRIPTION" Prints the contents of the specified database in \s-1XML\s0 format, with comments for human readability. This format can be read by \fBcfetool import\fR. .PP The \fB\-d\fR, \fB\-w\fR, and \fB\-y\fR options specify which databases to include in the dump, and may be combined. If they are all ommitted, the default is to only dump the weekly database. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-\-path\fR|\fB\-p\fR \fIdirectory name\fR" 4 .IX Item "--path|-p directory name" Names the directory in which the database specified by \fIname\fR can be found. .IP "\fB\-\-file\fR|\fB\-f\fR \fIfilename\fR" 4 .IX Item "--file|-f filename" Names a file to print the \s-1XML\s0 to. If this option is omitted, the \s-1XML\s0 will be printed to the standard output stream. .IP "\fB\-\-daily\fR|\fB\-d\fR" 4 .IX Item "--daily|-d" Include the daily pattern database in the dump. .IP "\fB\-\-weekly\fR|\fB\-w\fR" 4 .IX Item "--weekly|-w" Include the weekly pattern database in the dump. .IP "\fB\-\-yearly\fR|\fB\-y\fR" 4 .IX Item "--yearly|-y" Include the yearly pattern database in the dump. .IP "\fB\-\-verbose\fR|\fB\-v\fR" 4 .IX Item "--verbose|-v" Print details of the command's execution to the standard output stream. When using this argument, it is recommended that you also provide the \fB\-f\fR argument, to avoid sharing the standard output stream. .IP "\fB\-\-help\fR|\fB\-h\fR" 4 .IX Item "--help|-h" Print a short help message and then exit. .SH "EXAMPLE" .IX Header "EXAMPLE" .Vb 1 \& % cfetool dump temperature --path /my/path -f temperature.xml .Ve .PP Prints the following to the file \fBtemperature.xml\fR: .PP .Vb 2 \& \& .Ve .PP .Vb 1 \& temperature .Ve .PP .Vb 1 \& 1 .Ve .PP .Vb 1 \& 10 .Ve .PP .Vb 2 \& \& 1 .Ve .PP .Vb 2 \& \& 1093973525 .Ve .PP .Vb 2 \& \& 7.105000 .Ve .PP .Vb 2 \& \& 38.280217 .Ve .PP .Vb 5 \& \& Tue:Hr10:Min30_40 \& 10.150000 \& 13.245750 \& .Ve .PP .Vb 1 \& .Ve .SH "AUTHORS" .IX Header "AUTHORS" The code and documentation were contributed by Stanford Linear Accelerator Center, a department of Stanford University. This documentation was written by .IP "Elizabeth Cassell and" 4 .IX Item "Elizabeth Cassell and" .PD 0 .IP "Alf Wachsmann " 4 .IX Item "Alf Wachsmann " .PD .SH "COPYRIGHT AND DISCLAIMER" .IX Header "COPYRIGHT AND DISCLAIMER" .Vb 3 \& Copyright 2004 Alf Wachsmann and \& Elizabeth Cassell \& All rights reserved. .Ve cfengine-2.2.10/doc/stamp-vti0000644000175000001440000000014511170173455012707 00000000000000@set UPDATED 21 January 2009 @set UPDATED-MONTH January 2009 @set EDITION 2.2.10 @set VERSION 2.2.10 cfengine-2.2.10/doc/cfengine-Tutorial.html0000644000175000001440000133245211170173455015317 00000000000000 Cfengine v2 Tutorial

Cfengine v2 Tutorial


Next: , Previous: (dir), Up: (dir)

Cfengine-Tutorial

COMPLETE TABLE OF CONTENTS

This manual is for version 2.2.10 of cfengine and was last updated on the 24 December 2008.

Summary of contents


Next: , Previous: Top, Up: Top

1 Overview

In this manual the word “host” is used to refer to a single computer system – i.e. a single machine which has a name termed its “hostname”.


Next: , Previous: Overview, Up: Overview

1.1 What is cfengine and who can use it?

Cfengine is a tool for setting up and maintaining computer systems. It consists of several components:

cfagent
An autonomous configuration agent (required).
cfservd
A file server and remote activation service (optional).
cfexecd
A scheduling and report service (recommended).
cfenvd
An anomaly detection service (strongly recommended).
cfrun
A way of activating cfagent remotely (use this as you need to).
cfshow
A way of examining the contents of helper databases (helper).
cfenvgraph
Ancillary tool for cfenvd (helper).
cfkey
Key generation tool (run once on every host).

The agent cfagent can be used without the other programs, but not all of the capabilities of cfengine will be available unless the components are installed and used appropriately.

Cfengine incorporates a declarative language—much higher level than Perl or shell: a single statement can result in many hundreds of operations being performed on multiple hosts. Cfengine is good at performing a lot of common system administration tasks, and allows you to build on its strengths with your own scripts. You can also use it as a netwide front-end for cron. Once you have set up cfengine, you'll be free to use your time doing other things instead of manual configuration.

The main purpose of cfengine is to allow you to create a single system configuration which will allow you to define how every host on your network should be configured, and to do so in an intuitive way – either centralized or decentralized as you prefer. An interpreter runs on every host on your network and parses the master file (or file set). The configuration of each host is checked against this file; then, if you request it, any deviations from the defined configuration are fixed automatically. You do not have to mention every host specifically by name in order to configure them: instead you can refer to the properties which distinguish hosts from one another. Cfengine uses a flexible system of “classes” which helps you to single out a specific group of hosts with a single statement.

Cfengine grew out of the need to control the accumulation of complex shell scripts used in the automation of key system maintenance at University College in Oslo. There were a lot of scripts, written in shell and in Perl, performing system administration tasks such as file tidying, find-database updates, process checking and several other tasks. In a mixed environment, shell scripts work very poorly: shell commands have differing syntax across different operating systems, and the locations and names of key files differ. In fact, the non-uniformity of Unix was a major headache. Scripts were filled with tests to determine what kind of operating system they were being run on, to the point where they became so complicated and unreadable that no one was quite sure what they did anymore. Other scripts were placed only on the systems where they were relevant, out of sight and out of mind. It quickly became clear that our dream solution would be to replace this proliferation of scripts by a single file containing everything to be checked on every host on the network. By defining a new language, this file could hide all of the tests by using classes (a generalized `switch/case' syntax) to label operations and improve the readability greatly. The gradual refinement of this idea resulted in the present day cfengine.

As an inexperienced cfengine user, you will probably find yourself trying to do things as you would have tried to do them in shell or Perl. This is probably not the right way to think when using cfengine. You will need to think in a more `cfengine way'. When reading the manual, keep in mind that cfengine's way of working is to think about what the final result should be like, rather than on how to get there (with shell and Perl you specify what to do, rather than what you would like).

The remainder of this manual assumes that you know a little about BSD and UNIX System V systems and have every day experience in using either the C shell (csh) or the Bourne shell (sh), or their derivatives. If you are experienced in system administration, you might like to skip the earlier chapters and turn straight to the example in the section Example configuration file of the Reference manual. This is the probably quickest way to learn cfengine for the initiated. If you are not so familiar with system administration and would like a more gentle introduction, then we begin here...


Next: , Previous: What is cfengine?, Up: Overview

1.2 Site configuration

To the system administrator of a small network, with just a few workstations or perhaps even a single mainframe system, it might seem superfluous to create a big fuss about the administration of the system. After all, it's easy to `fix' things manually should any problems arise, making a link here, writing a script there and so on — and its probably not even worth writing down what you did because you know that it will always be easy to fix next time around too... But networks have a tendency to expand and—before you know it—you have five different types of operating system and each type of system has to be configured in a special way, you have to make patches to each system and you can't remember whether you fixed that host on the other side of the building... Also, you discover fairly quickly that what you thought of as BSD or System V is not as standard as you thought and that none of your simple scripts that worked on one system work on the others without a considerable amount of hacking and testing. You try writing a script to help you automate the task, but end up with an enormous number of ‘if..then..else..’ tests which make it hard to see what is really going on.

To manage a network with many different flavours of operating system in a systematic way, what is needed is a more disciplined way of making changes which is robust against system re-installation. After all, it would be tragic to spend many hours setting up a system by hand only to lose everything in an unfortunate disk crash a week or even a year later when you have forgotten what you had to do. Upgrades of the operating system software might delete your carefully worked out configuration. What is needed is a separate record of all of the patches required on all of the systems on the network; a record which can be compared to the state of each host at any time and which a suitable engine can use to fix any deviations from that reference standard.

The idea behind cfengine is to focus upon a few key areas of basic system administration and provide a language in which the transparency of a configuration program is optimal. It eliminates the need for lots of tests by allowing you to organize your network according to “classes”. From a single configuration file (or set of files) you can specify how your network should be configured — and cfengine will then parse your file and carry out the instructions, warning or fixing errors as it goes.


Next: , Previous: Site configuration, Up: Overview

1.3 Key Concepts

Some of the important issues in system administration which cfengine can help with.


Next: , Previous: Key concepts, Up: Key concepts

1.3.1 Configuration files and registries

One of the endearing characteristics of BSD and System V systems is that they are configured through human-readable text files. To add a new user to the system you edit /etc/passwd, to add a new disk you must edit /etc/fstab, etc. Many applications are also configured with the help of text files. When installing a new system for the first time, or when changing updating the setup of an old system, you are faced with having to edit lots of files. In some cases you will have to add precisely the same line to the same file on every system in your network as a change is made, so it is handy to have a way of automating this procedure so that you don't have to load every file into an editor by hand and make the changes yourself. This is one of the tasks which cfagent will automate for you.

On Windows systems, configuration data are stored in a system registry. With the right tools, the Windows system registry can also be edited by cfengine, but this requires more care.

1.3.2 Network interface

Each host which you connect to an Ethernet-based network running TCP/IP protocols must have a so-called `net interface'. This network interface must be configured before it will work. Normally, one does this with the help of the ifconfig command. This can also be checked and configured automatically by cfagent.

Network configuration involves telling the interface hardware what the internet (IP) address of your system is, so that it knows which incoming `packets' of data to pay attention to. It involves telling the interface how to interpret the addresses it receives by setting the `netmask' for your network (see below). Finally, you must tell it which dummy address is to be used for messages which are broadcast to all hosts on your network simultaneously (see the Reference Manual).

Cfagent's features are mainly meant for hosts which use static IP addresses; if you are using DHCP clients, then you will not need the net configuration features.

1.3.3 Network File System (NFS) or file distribution?

Probably the first thing you are interested in doing with a network (after you've had your fill of the World-Wide Web) is to make your files available to some or all hosts on the network, no matter where in your corporate empire (or university dungeon) you might be sitting. In other words, if you have a disk which is physically connected to host A, you would like to make the contents of that disk available to hosts B, C, D ..., etc. NFS (the Network FileSystem) makes this possible.

The process works by `filesystems'. A filesystem is one partition of a disk drive – or one unit of disk space which can be accessed by a single `logical device' ‘/dev/something’.

To make a filesystem available to other hosts you have to do three things.

  • On the host the disk is physically connected to you must export the filesystem by adding something to the file /etc/exports. This tells NFS who is allowed to access the disk and who isn't.
  • On the host which is to access the filesystem you must create a mount point. This is a name in the directory tree at which you want to add the files to your local filesystem.
  • On the host which is to access the files you must mount the filesystem onto the mount point. The mount operation is the jargon for telling the system to access the device on which the data are stored. Mounting is analogous to opening a file: files are opened, filesystems are mounted.

Only after all three of these have been done will a filesystem become available across the network. Cfagent will help you with the last two in a very transparent way. You could also use the text-editing facility in cfagent to edit the exports file, but there are other ways to update the exports file using NIS and netgroups, which we shall not go into here. If you are in doubt, look up the manual page on exports(5).

Some sites prefer to minimize the use of NFS filesystems to avoid one machine being dependent on another. They prefer to make a local copy of the files on a remote machine instead. Traditionally, programs like rdist have been used for this purpose. You may also use cfagent to copy files in this way, See Emulating rdist.

1.3.4 Name servers (DNS)

There are two ways to specify addresses on the internet (called IP addresses). One is to use the text address like ‘ftp.uu.net’ and the other is to use the numerical form ‘192.48.96.9’. Alas, there is no direct one-to-one correspondence between the numerical addresses and the textual ones, thus a service (called DNS) is required to map one to the other.

The service is performed by one or more special hosts on the network called name servers. Each host must know how to contact a name server or it will probably hang the first time you give it an IP address. You tell it how to contact a name server by editing the text-file /etc/resolv.conf. This file must contain the domain name for your domain and a list of possible name servers which can be contacted, in order of priority. Since this is a special file which every host must have, you don't have to use the general text file editing facilities in cfagent. You can just define the name servers for each host in the cfagent file and cfagent will do the editing to /etc/resolv.conf automatically. If you want to change the priority of name servers later, or even change the list then a simple change of one or two lines in the configuration file will enable you to reconfigure every host on your network automatically without having to do any editing yourself!


Next: , Previous: Name servers (DNS), Up: Key concepts

1.3.5 Monitoring important files

Security is an important issue on any system. In the busy life of a system administrator, it is not always easy to remember to set the correct access rights on every file; this can result in either a security breach or problems in accessing files.

A common scenario is that you, as administrator, fetch a new package using FTP, compile it and install it without thinking too carefully. Since the owner and permissions of the files in an FTP archive remains those of the program author, it often happens that the software is left lying around with the owner and permissions as set by the author of the program rather than any user name on your system. The userid of the author might be anybody on your system — or perhaps nobody at all! The files should clearly be owned by root and made readable but unwritable by normal users.

Simple accidents and careless actions under stress could result in, for example, the password file being writable to ordinary users. If this were the case, the security of the entire system would be compromised. Cfagent therefore allows you to monitor the permissions, ownership, and general existence of files and directories and, if you wish, to either correct them or warn about them automatically.

1.3.6 Making links

One of the difficulties with having so many different variations on the theme of BSD and System V based operating systems is that similar files are not always where you expect to find them. They have different names or lie in different directories. The usual solution to the problem is to make an alias for these files, or a pointer from one filename to another. The name for such an alias is a symbolic link.

It is often very convenient to make symbolic links. For example, you might want the sendmail configuration file /etc/sendmail.cf to be a link to a global configuration file, say,

     /usr/local/mail/etc/sendmail.cf

on every single host on your network so that there is only one file to edit. If you had to make all of these links yourself, it would take a lifetime. Cfagent will make such a link automatically and check it each time it is run. You can also ask it to tidy up old links which have been left around and no longer point to existing files. If you reinstall your operating system later, it doesn't matter because all your links are defined in your cfagent configuration file, recorded for all time. Cfengine won't forget it, and you won't forget it because the setup is defined in one central place.

Cfagent will also allow you to make hard links to regular files, but not to other kinds of files. A hard link that points to a symbolic link is the same as a hard link to the file the symbolic link points to.


Previous: Key concepts, Up: Overview

1.4 Functionality

The notes above give you a rough idea of what cfengine can be used for. Here is a quick summary of cfagent's capabilities.

  • Check and configure the network interface.
  • Edit textfiles for the system and for all users.
  • Make and maintain symbolic links, including multiple links, using a single command.
  • Check and set the permissions and ownership of files.
  • Tidy (i.e., delete) junk files which clutter the system.
  • Systematic and automated mounting of NFS filesystems.
  • Checking for the presence of important files and filesystems.
  • Controlled execution of user scripts and shell commands.
  • A class-based decision structure.
  • Process management.

How do you run cfagent? You can run it as a cron job, or you can run it manually. You may run cfagent scripts/programs as often as you like. Each time you run a script, cfengine determines whether anything needs to be done — if nothing needs to be done, nothing is done! If you use it to monitor and configure your entire network from a central file-base, then the natural thing is to run cfengine repeatedly with the help of cron and/or cfexecd.


Next: , Previous: Overview, Up: Top

2 Getting started

2.1 What you must have in a cfagent program

A cfagent configuration file for a large network can become long and complex so, before we get down to details, let's try to strip away the complexity and look only to the essentials.

Each cfagent program or configuration file is a list of declarations of items to be checked and perhaps fixed. You begin by creating a file called cfagent.conf. The simplest meaningful file you can create is something like this:

     
     # Comment...
     
     control:
     
       actionsequence = ( links )
     
     links:
     
       /bin -> /usr/bin
     

The example above checks and makes (if necessary) a link from /bin to /usr/bin. Let's examine this example more closely. In a cfengine program:

  • Use of space is unrestricted. You can start new lines wherever you like. You should generally have a space before and after parentheses to avoid confusing the parser.
  • A comment is some text which is ignored by cfengine. The ‘#’ symbol designates a comment and means: ignore the remaining text on this line. A comment symbol must have a space in front of it, or start a new line so that cfengine knows you don't mean the symbol as part of another word.
  • Words which end in a single colon define sections in a program. Under a given section you group together all declarations of a given type. Section names must all be taken from a list defined by the language. You cannot define your own sections.
  • Words which end in two colons are so-called class names. They are used for making decisions in cfengine.
  • Statements which are of the form name=( list ) are used to assign the value on the right hand side to the name on the left hand side of the equals sign.

In simple example above has three of the four types of object described above. The control: section of any program tells cfengine how to behave. In this example it adds the action links to the action sequence. For links you could replace some other action. The essential point is that, if you don't have an action sequence, your cfengine program will do absolutely nothing! The action sequence is a list which tells cfagent what do to and in which order.

The links: section of the file tells cfagent that what follows is a number of links to be made. If you write this part of the file, but forget to add links to the action sequence, then nothing will be done! You can add any number of links in this part of the file and they will all be dealt with in order when—and only when—you write links in the action sequence.

To summarize, you must have:

  • Some declarations which specify things to be done.
  • An action sequence which tells cfagent which sections to process, how many times and in which order they should be processed.

Now let's think a bit about how useful this short example program is. On a SunOS (Solaris) system, where the directory /bin is in fact supposed to be a link, such a check could be useful, but on some other system where /bin is a not a link but a separate directory, this would result in an error message from cfagent, telling you that /bin exists and is not a link. The lesson is that, if we want to use cfagent to make one single program which can be run on any host of any type, then we need some way of restricting the above link so that it only gets checked on SunOS systems. We can write the following:

     
     # Comment...
     
     control:
     
       actionsequence = ( links  )
     
     links:
     
       sun4::
     
            /bin -> /usr/bin
            # other links
     
        osf::
     
            # other links
     

The names which have double colons after them are called classes and they are used to restrict a particular action so that it only gets performed if the host running the program is a member of that class. If you are familiar with C++, this syntax should make you think of classes definitions in C++. Classes works like this: the names above sun4, sun3, osf etc. are all internally defined by cfagent. If a host running, say, the OSF operating system executes the file it automatically becomes a member of the class osf. Since it cannot be a member more than one of the above, this distinguishes between different types of operating system and creates a hidden if..then...else test.

This is the way in which cfagent makes decisions. The key idea is that actions are only carried out if they are in the same class as the host running the program. Classes are dealt with in detail in the next chapter.

Now let's see how to add another kind of action to the action sequence.

     
     # Comment...
     
     control:
     
       actionsequence = ( tidy links )
     
     links:
     
       /bin -> /usr/bin
     
     tidy:
     
        /tmp  pattern=* age=7 recurse=inf
     

We have now added a new kind of declaration called tidy: which deletes files. In the example above, we are looking at files in the directory /tmp which match the pattern ‘*’ and have not been accessed for more than seven days. The search for these files descends recursively down any number of subdirectories.

To make any of this happen we must add the word tidy to the action sequence. If we don't, the declaration will be ignored. Notice also that, regardless of the fact that links: comes before tidy:, the order in the action sequence tells us that all tidy actions will be performed before links:.

The above structure can be repeated to build up a configuration file or script.

2.2 Program structure

To summarize the previous section, here is a sketch of a typical cfagent configuration program showing a sensible structure. The various sections are listed in a sensible order which you would probably use in the action sequence.

An individual section-declaration in the program looks something like this:

     
     action-type:
     
        class1::
     
            list of things to do...
     
        class2::
     
            list of things to do...
     

action-type is one of the following reserved words:

     
        groups, control, copy, homeservers, binservers, mailserver, mountables,
        import, broadcast, resolve, defaultroute, directories, miscmounts,
        files, ignore, tidy, required, links, disable, shellcommands, strategies
        editfiles, processes
     

The order in which declarations occur is not important to cfengine from a syntactical point of view, but some of the above actions define information which you will want to refer to later. All variables, classes, groups etc. must be defined before they are used. That means that it is smart to follow the order above for the sections in the first line of the above list.

The order in which items are declared is not to be confused with the order in which they are executed. This is determined by the actionsequence, (see the reference manual). Probably you will want to coordinate the two so that they match as far as possible. For completeness, here is a complete summary of the structure of a very general cfagent configuration program. The format is free and use of space is unrestricted, though it is always a good idea to put a space in front before and after parentheses when defining variables.

     ######################################################################
     #
     # Example of structure
     #
     ######################################################################
     
     groups:
     
        group1 = ( host host ...  )
        group2 = ( host host ...  )
        ...
     
     ######################################################################
     
     control:
     
        class::
     
        site      =  ( mysite )
        domain    =  ( mydomain )
        ...
     
         actionsequence =
           (
           action name
           ....
           )
     
        mountpattern = ( mountpoint )
        homepattern = ( wildcards matching home directories )
     
        addinstallable = ( foo bar )
        addclasses     = ( foo bar )
     
     ######################################################################
     
     homeservers:
     
        class::
                home servers
     
     binservers:
     
        class::
                binary servers
     
     mailserver:
     
        class::
                mail server
     
     mountables:
     
        class::
     
                list of resources
     
     
     ######################################################################
     
     import:
     
        class::    include file
     
        class::    include file
     
     
     ######################################################################
     
     broadcast:
     
       class::  ones   # or zeros / zeroes
     
     defaultroute:
     
        class::  my-gw
     
     
     ######################################################################
     
     resolve:
     
        any::
     
            list of nameservers
     
     
        ...
     


Next: , Previous: Program structure, Up: Getting started

2.3 Building a distributed configuration

If a configuration is to be specified at one central location, how does it get distributed to many hosts? The simple answer is to get cfengine to distribute the configuration to the hosts. To do that, a separate configuration file is used. Why?

Imagine what would happen if you made a mistake in the configuration, i.e. a syntax error which got distributed to every host. Now all the hosts would be unable to run cfengine, and thereafter unable to download a corrected configuration file. The whole setup would be broken. To prevent this kind of accident, a separate configuration file is used to copy the files and binaries to each host. This configuration should be simple, and should almost never be edited: they key word here is reliability.

2.3.1 Startup update.conf

The file update.conf can have more or less the same form for all sites, looking something like this.

     #######
     #
     # BEGIN update.conf
     #
     # This script distributes the configuration, a simple file so that,
     # if there are syntax errors in the main config, we can still
     # distribute a correct configuration to the machines afterwards, even
     # though the main config won't parse. It is read and run just before the
     # main configuration is parsed.
     #
     #######
     
     control:
     
      actionsequence  = ( copy tidy )  # Keep this simple and constant
     
      domain          = ( iu.hio.no )  # Needed for remote copy
     
      #
      # Which host/dir is the master for configuration roll-outs?
      #
     
      policyhost      = ( nexus.iu.hio.no )
      master_cfinput  = ( /masterfiles/inputs )
     
      #
      # Some convenient variables
      #
     
      workdir         = ( /var/cfengine )
      cf_install_dir  = ( /usr/local/sbin )
     
      # Avoid server contention
     
      SplayTime = ( 5 )
     
     ############################################################################
     
      #
      # Make sure there is a local copy of the configuration and
      # the most important binaries in case we have no connectivity
      # e.g. for mobile stations or during DOS attacks
      #
     
     copy:
     
          $(master_cfinput)            dest=$(workdir)/inputs
                                       r=inf
                                       mode=700
                                       type=binary
                                       exclude=*.lst
                                       exclude=*~
                                       exclude=#*
                                       server=$(policyhost)
     
          $(cf_install_dir)/cfagent    dest=$(workdir)/bin/cfagent
                                       mode=755
                                       backup=false
                                       type=checksum
     
          $(cf_install_dir)/cfservd    dest=$(workdir)/bin/cfservd
                                       mode=755
                                       backup=false
                                       type=checksum
     
          $(cf_install_dir)/cfexecd    dest=$(workdir)/bin/cfexecd
                                       mode=755
                                       backup=false
                                       type=checksum
     
     #####################################################################
     
     tidy:
     
          #
          # Cfexecd stores output in this directory.
          # Make sure we don't build up files and choke on our own words!
          #
     
          $(workdir)/outputs pattern=* age=7
     
     #######
     #
     # END cf.update
     #
     #######
     

2.3.2 Startup cfservd.conf

In order to set up remote distribution from a central server, you will need to start the cfservd service on the host from which the configuration is to be copied, and grant access to the hosts which need to download it. Here is a simple get-started file which does this:

     #########################################################
     #
     # This is a cfservd config file - it is used for the server
     # part of cfengine, for remote file transfers and control
     # over cfengine using the cfrun program.
     #
     #########################################################
     
     control:
     
       domain = ( iu.hio.no )
     
          cfrunCommand = ( "/var/cfengine/bin/cfagent" )
     
      any::
     
       IfElapsed = ( 1 )
       ExpireAfter = ( 15 )
       MaxConnections = ( 50 )
       MultipleConnections = ( true )
     
     #########################################################
     
     grant:
     
        # Grant access to all hosts at example.org.
        # Files should be world readable
     
        /masterfiles/inputs        *.example.org
     
        # Make sure there is permission to execute by cfrun
     
        /var/cfengine/bin/cfagent  *.example.org
     
     ########
     #
     # END cfservd.conf
     #
     ########
     

2.3.3 Where should I put the files?

Where should the files be located? To organize your files, you should think of three potential locations, for different purposes:

  • A version controlled repository for authoring, testing and applying changes to the files. Once a version is approved for release, these master files should be moved on to a publishing area. e.g. /usr/local/masterfiles/cfengine/inputs on `masterhost'.
  • A centralized location, into which you publish your altered and tested configurations. This is the `buffer' location from which each client will download new and tested versions of the master configuration. e.g. /usr/local/masterfiles/cfengine/inputs on `masterhost'. It acts as a buffer between the testing ground and the production location.
  • The Work Directory. This is the production location. It is a location that is normally chosen to be the private directory where cfagent expects to find its configuration files, /var/cfengine/inputs. Your update.conf file has the job of copying from the master location (second bullet) above to this location.

Modules and methods are normally kept in a separate directory than inputs files are kept in, because they require a directory with special authorizations whe executing. This is good practice As long as the update.conf places the master versions in the correct location (usually /var/cfengine/modules) on the local host, all will be okay.

You should not try to copy files directly from a version controlled repository, as you might end up sending out an incomplete or partially tested version of the files to all your hosts.

     
     # Example update.conf
     
     control:
     
        master_cfinput  = ( /usr/local/masterfiles/cfengine/inputs )
        workdir         = ( /var/cfengine )
     
     copy:
     
        # Copy from bullet 2 to bullet 3
     
          $(master_cfinput)            dest=$(workdir)/inputs
                                       r=inf
                                       mode=700
                                       type=binary
                                       exclude=*.lst
                                       exclude=*~
                                       exclude=#*
                                       server=$(policyhost)
                                       trustkey=true
     
          $(master_modules)            dest=$(workdir)/modules
                                       r=inf
                                       mode=700
                                       type=binary
                                       exclude=*.lst
                                       exclude=*~
                                       exclude=#*
                                       server=$(policyhost)
                                       trustkey=true
     

2.4 Optional features in cfagent

Cfagent doesn't do anything unless you ask it to. When you run a cfagent program it generates no output unless it finds something it believes to be wrong. It does not carry out any actions unless they are declared in the action sequence.

If you like, though, you can make cfagent positively chatty. Cfagent can be run with a number of command line options (see the reference manual). If you run the program with the ‘-v’ or ‘--verbose’ options, it will supply you cheerily with a resume of what it is doing. Certain warning messages also get printed in verbose mode, so it is a useful debugging tool.

You can ask cfagent to check lots of things – the timezone for instance, or the domain name. In order for it to check these things, it needs some information from you. All of the switches and options which change the way in which cfagent behaves get specified either on the command line or in the control: section of the control file. Some special control variables are used for this purpose. Here is a short example:

     
     control:
     
       domain   = ( example.org )
       netmask  = ( 255.255.255.0 )
       timezone = ( MET CET )
     
       mountpattern = ( /mydomain/mountpoint )
     
       actionsequence =
          (
          checktimezone     # check time zone
          netconfig         # includes check netmask
          resolve           # includes domain
          mountinfo         # look for mounted disks under mountpattern
          )
     

To get verbose output you must run cfagent with the appropriate command line option ‘--verbose’ or ‘-v’.

Notice that setting values has a special kind of syntax: a variable name, an equals sign and a value in parentheses. This tells you that the quantity of the left hand side assumes the value on the right hand side. There are lots of questions you might ask at this point. The answers to these will be covered as we go along and in the next chapter.

Before leaving this brief advertisement for control parameters, it is worth noting the definition of mountpattern above. This declares a directory in which cfagent expects to find mounted disks. It will be explained in detail later, for now notice that this definition looks rather stupid and inflexible. It would be much better if we could use some kind of variables to define where to look for mounted filesystems. And of course you can...

Having briefly scraped the surface of what cfagent can do, turn to the example and take a look at what a complete program can look like, (see the reference manual). If you understand it, you might like to skip through the rest of the manual until you find what you are looking for. If it looks mysterious, then the next chapter should answer some questions in more depth.

2.5 Invoking cfagent

Cfagent may be invoked in a number of ways. Here are some examples:

     host% cfagent
     
     host% cfagent --file myfile
     
     host% cfagent -f myfile -v -n
     
     host% cfagent --help

The first of these (the default command, with no arguments) causes cfagent to look for a file called cfagent.conf in the directory pointed to by the environment variables CFINPUTS or /var/cfengine/inputs by default, and execute it silently. The second command reads the file myfile and works silently. The third works in verbose mode and the -n option means that no actions should actually be carried out, only warnings should be printed. The final example causes cfagent to print out a list of its command line options. The complete list of options is listed in the summary at the beginning of this manual, or you can see it by giving the -h option, (see the reference manual). In addition to running cfagent with a filename, you can also treat cfagent files as scripts by starting your cfagent program with the standard shell line:

     #!/usr/local/sbin/cfagent -f
     #
     # My config script
     #

Here we assume that you have installed cfengine under the directory /usr/local/sbin. By adding a header like this to the first line of your program and making the file executable with the chmod shell command, you can execute the program just by typing its name—i.e. without mentioning cfengine explicitly at all.

As a novice to cfengine, it is advisable to check all programs with the -n option before trusting them to your system, at least until you are familiar with the behaviour of cfengine. This `safe' option allows you to see what cfengine wants to do, without actually committing yourself to doing it.

2.6 Running cfengine permanently, monitoring and restarting cfexecd

Once you are happy using cfengine, you will want it to run least once per hour on your systems. This is easily achieved by adding the following line to the root crontab file of each system:

     0,30 * * * * /usr/local/sbin/cfexecd -F

This is enough to ensure that cfengine will get run. Any output generated by this job, will be stored in /var/cfengine/outputs. In addition, if you add the following to the file cfagent.conf, the system administrator will be emailed a summary of any output:

     
     control:
     
     smtpserver = ( mailhub.example.org ) # site MTA which can talk smtp
     sysadm     = ( mark@example.org )   # mail address of sysadm
     

Fill in suitable values for these variables. An alternative, or additional way to run cfengine, is to run the cfexecd program is daemon mode (without the ‘-F’) option. In this mode, the daemon lives in the background and sleeps, activating only in accordance with a scheduling policy. The default policy is to run once every hour (equivalent to Min00_05). Here is how you would modify cfagent.conf in order to make the daemon execute cfagent every half-hour:

      control:
     
        # When should cfexecd in daemon mode wake up the agent?
     
        schedule   = ( Min00_05 Min30_35 )

Note that the time specifications are the basic cfengine time classes, See Building flexible time classes. Although one of these methods should suffice, no harm will arise from running both cron and the cfexecd side-by-side. Cfagents locking mechanisms ensure that no contention will occur.

The other components of cfengine can be started by cfagent itself:

     processes:
     
      "cfenvd"  restart "/usr/local/sbin/cfenvd"
      "cfservd" restart "/usr/local/sbin/cfservd"
     

Note that, to start cfexecd by cfengine, one must do this

     processes:
     
      "bin/cfexecd$"  restart "/usr/local/sbin/cfexecd"
     

It's important to use as specific a regular expression as possible in match statements (the path to the program and the regular expression metacharacter $ meaning "end of line", in this example) because bare strings can often match unexpected processes. For instance, using cfexecd by itself will also match a process spawned by cfagent -F, which shows up as /var/cfagent/bin/cfagent -Dfrom_cfexecd in the process table!

2.7 CFINPUTS environment variable

Whenever cfengine looks for a file it asks a question: is the filename an absolute name (that is a name which begins from / like /usr/file), is it a file in the directory in which you invoke cfengine or is it a file which should be searched for in a special place? If you use an absolute filename either on the command line using -f or in the import section of your program (a name which begins with a slash '/'), then cfengine trusts the name of the file you have given and treats it literally. If you specify the name of the file as simple ‘.’ or ‘-’ then cfengine reads its input from the standard input. If you run cfengine without arguments (so that the default filename is cfagent.conf) or you specify a file without a leading slash in the import section, then the value of the environment variable CFINPUTS is prepended to the start of the file name. This allows you to keep your configuration in a standard place, pointed to by CFINPUTS. For example:

     
     host# setenv CFINPUTS /usr/local/masterfiles/cfengine/inputs
     
     host# cfagent -f myfile
     

In this example, cfengine tries to open myfile. in the directory /usr/local/masterfiles/cfengine/inputs. If no value is set for CFINPUTS, then the default location is the trusted cfengine directory /var/cfengine/inputs.

2.8 What to aim for

If you are a beginner to cfengine, you might not be certain exactly how you want to use it. Here are some hints from Dr. Daystrom about how to get things working quickly.

  • Run cfengine from cron every hour on all your systems. Be sure to label long tasks, or tasks which do not need to be performed often by a time class which prevents it from being executed all the time, See Using cfengine as a front-end for cron.

    Running cfengine from cron means that it will be run in parallel on your systems. Cfengine on one host does not have to wait for cfengine on another host to complete.

  • Set up cfservd on all your systems so that cfengine can be executed remotely, so that you can immediately “push" changes to all your hosts with cfrun. Think carefully about whom you wish to give permission to run cfengine from the net, See Configuring cfservd. Set up you cfservd.conf file accordingly. You can also use this daemon to grant access rights for remote file copying.

    Cfrun polls all your hosts serially and gives you a concatenated indexed list of problems on all hosts. The disadvantage with cfrun is that each host has to wait its turn.

  • Don't forget to add cfservd to the system startup scripts, or to inittab so that it starts when you boot your system.
  • Add all your hosts to the cfrun.hosts file. It does not matter that some may be master servers and others clients. The locking mechanisms will protect you from silliness, See Deadlocks and runaway loops. Cfengine will work it out. Cfrun allows you to remotely execute cfengine on groups of hosts which satisfy a list of cfengine classes.

When you have set up these components, you can sit back and edit the configuration files and watch things being done.


Next: , Previous: Getting started, Up: Top

3 More advanced concepts

3.1 Classes

The idea of classes is central to the operation of cfengine. Saying that cfengine is `class orientated' means that it doesn't make decisions using if...then...else constructions the way other languages do, but only carries out an action if the host running the program is in the same class as the action itself. To understand what this means, imagine sorting through a list of all the hosts at your site. Imagine also that you are looking for the class of hosts which belong to the computing department, which run GNU/Linux operating system and which have yellow spots! To figure out whether a particular host satisfies all of these criteria you first delete all of the hosts which are not GNU/Linux, then you delete all of the remaining ones which don't belong to the computing department, then you delete all the remaining ones which don't have yellow spots. If you are on the remaining list, then you are in the class of all computer-science-Linux-yellow-spotted hosts and you can carry out the action.

Cfengine works in this way, narrowing things down by asking if a host is in several classes at the same time. Although some information (like the kind of operating system you are running) can be obtained directly, clearly, to make this work we need to have lists of which hosts belong to the computer department and which ones have yellow spots.

So how does this work in a cfengine program? A program or configuration script consists of a set of declarations for what we refer to as actions which are to be carried out only for certain classes of host. Any host can execute a particular program, but only certain action are extracted — namely those which refer to that particular host. This happens automatically because cfengine builds up a list of the classes to which it belongs as it goes along, so it avoids having to make many decisions over and over again.

By defining classes which classify the hosts on your network in some easy to understand way, you can make a single action apply to many hosts in one go – i.e. just the hosts you need. You can make generic rules for specific type of operating system, you can group together clusters of workstations according to who will be using them and you can paint yellow spots on them – what ever works for you.

A cfengine action looks like this:

     
     action-type:
     
        compound-class::
     
            declaration

A single class can be one of several things:

  • The name of an operating system architecture e.g. ultrix, sun4 etc. This is referred to henceforth as a hard class.
  • The (unqualified) name of a particular host. If your system returns a fully qualified domain name for your host, cfagent truncates it so as to unqualify the name.
  • The name of a user-defined group of hosts.
  • A day of the week (in the form Monday, Tuesday, Wednesday...).
  • An hour of the day (in the form Hr00, Hr01, ... Hr23).
  • Minutes in the hour (in the form Min00, Min17, ... Min45).
  • A five minute interval in the hour (in the form Min00_05, Min05_10, ... Min55_00)
  • A quart hour (in the form Q1, Q2, Q3, Q4)
  • An abbreviated time with quarter hour specified (in the form Hr00_Q1, Hr23_Q4, etc.)
  • A day of the month (in the form Day1 ... Day31).
  • A month (in the form January, February, ... December).
  • A year (in the form Yr1997, Yr2001).
  • An arbitrary user-defined string. (see the reference manual).
  • The ip-address octets of any active interface (in the form ipv4_192_0_0_1, ipv4_192_0_0, ipv4_192_0,ipv4_192).

A compound class is a sequence of simple classes connected by dots or `pipe' symbols (vertical bars). For example:

     
     myclass.sun4.Monday::
     
     sun4|ultrix|osf::
     

A compound class evaluates to `true' if all of the individual classes are separately true, thus in the above example the actions which follow compound_class:: are only carried out if the host concerned is in myclass, is of type sun4 and the day is Monday! In the second example, the host parsing the file must be either of type sun4 or ultrix or osf. In other words, compound classes support two operators: AND and OR, written ‘.’ and ‘|’ respectively. From cfengine version 2.1.1, I bit the bullet and added ‘&’ as a synonym for the AND operator. Cfengine doesn't care how many of these operators you use (since it skips over blank class names), so you could write either

     
     solaris|irix::
     

or

     
     solaris||irix::
     

depending on your taste. On the other hand, the order in which cfengine evaluates AND and OR operations does matter, and the rule is that AND takes priority over OR, so that ‘.’ binds classes together tightly and all AND operations are evaluated before ORing the final results together. This is the usual behaviour in programming languages. You can use round parentheses in cfengine classes to override these preferences.

Cfengine allows you to define switch on and off dummy classes so that you can use them to select certain subsets of action. In particular, note that by defining your own classes, using them to make compound rules of this type, and then switching them on and off, you can also switch on and off the corresponding actions in a controlled way. The command line options -D and -N can be used for this purpose. See also addclasses in the Reference manual. A logical NOT operator has been added to allow you to exclude certain specific hosts in a more flexible way. The logical NOT operator is (as in C and C++) ‘!’. For instance, the following example would allow all hosts except for myhost:

        action:
     
         !myhost::
     
             command

and similarly, so allow all hosts in a user-defined group mygroup, except for myhost, you would write

        action:
     
         mygroup.!myhost::
     
             command

which reads `mygroup AND NOT myhost'. The NOT operator can also be combined with OR. For instance

     
        class1|!class2

would select hosts which were either in class 1, or those which were not in class 2.

Finally, there is a number of reserved classes. The following are hard classes for various operating system architectures. They do not need to be defined because each host knows what operating system it is running. Thus the appropriate one of these will always be defined on each host. Similarly the day of the week is clearly not open to definition, unless you are running cfengine from outer space. The reserved classes are:

     ultrix, sun4, sun3, hpux, hpux10, aix, solaris, osf, irix4, irix, irix64
        sco, freebsd, netbsd, openbsd, bsd4_3, newsos, solarisx86, aos,
               nextstep, bsdos, linux, debian, cray, unix_sv, GnU, NT

If these classes are not sufficient to distinguish the hosts on your network, cfengine provides more specific classes which contain the name and release of the operating system. To find out what these look like for your systems you can run cfengine in `parse-only-verbose' mode:

     
       cfagent -p -v
     

and these will be displayed. For example, Solaris 2.4 systems generate the additional classes sunos_5_4 and sunos_sun4m, sunos_sun4m_5_4.

Cfengine uses both the unqualified and fully host names as classes. Some sites and operating systems use fully qualified names for their hosts. i.e. uname -n returns to full domain qualified hostname. This spoils the class matching algorithms for cfengine, so cfengine automatically truncates names which contain a dot `.' at the first `.' it encounters. If your hostnames contain dots (which do not refer to a domain name, then cfengine will be confused. The moral is: don't have dots in your host names! NOTE: in order to ensure that the fully qualified name of the host becomes a class you must define the domain variable. The dots in this string will be replaced by underscores. In summary, the operator ordering in cfengine classes is as follows:

()
Parentheses override everything.
!
The NOT operator binds tightest.
. &
The AND operator binds more tightly than OR.
|
OR is the weakest operator.

3.2 Variable substitution

When you are building up a configuration file it is very useful to be able to use variables. If you can define your configuration in terms of some key variables, it can be changed more easily later, it is more transparent to the reader of the program and you can also choose to define the variables differently on different types of system. Another way of saying this is that cfengine variables also belong to classes. Cfengine makes use of variables in three ways.

  • Environment variables from the shell
  • Special variables used in cfengine features
  • General macro-string substitution.

Environment variables are fetched directly from the shell on whatever system is running the program. An example of a special variable is the domain variable from the previous section. Straightforward macro substitution allows you to define a symbol name to be replaced by an arbitrary text string. All these definitions (apart from shell environment variables, of course) are made in the control part of the cfengine program:

     
     control:
     
       myvar = ( /usr/local/mydir/lib/very/long/path )   # define macro
     
     ...
     
     links:
     
       $(myvar) -> /another/directory
     

Here we define a macro called myvar, which is later used to define the creation of a link. As promised we can also define class-dependent variables:

     
     control:
     
       sun4:: myvar = ( sun )
       hpux:: myvar = ( HP )
     

Cfagent gives you access to the shell environment variables and allows you to define variables of your own. It also keeps a few special variables which affect the way in which cfengine works. When cfengine expands a variable it looks first at the name in its list of special variables, then in the list of user-defined macros and finally in the shell environment for a match. If none of these are found it expands to the empty string. If you nest macros,

     
     control:
     
       myvar = ( "$(othervar)" )
     

then you must quote the right hand side and ensure that the value is already defined.

You can also import values from the execution of a shell command by prefixing a command with the word exec. This method is deprecated in version 2 and replaced by a function.

     
       control:
     
        # old method
     
        listing = ( "exec /bin/ls -l" )
     
        # new method
     
        listing = ( ExecResult(/bin/ls -l) )
     

This sets the variable `listing' to the output of the command in the quotes. Some other internal functions are

RandomInt(a,b)
Generate a random integer between a and b.
ExecResult(command)
Executes the named shell command and inserts the output into the variable.

For example:

     
     control:
     
      variable2 = ( RandomInt(0,23) )
     
      variable3 = ( ExecResult(/bin/ls -a /opt) )
     

Variables are referred to in either of two different ways, depending on your taste. You can use the forms $(variable) or ${variable}. The variable in braces or parentheses can be the name of any user defined macro, environment variable or one of the following special internal variables.

AllClasses
A long string in the form ‘CFALLCLASSES=class1:class2...’. This variable is a summary of all the defined classes at any given time. It is always kept up to date so that scripts can make use of cfengine's class data.
arch
The current detailed architecture string—an amalgamation of the information from uname. Non-definable.
binserver
The default server for binary data. See NFS resources. Non definable.
class
The currently defined system hard-class (e.g. sun4, hpux). Non-definable.
date
The current date string. Note that if you use this in a shell command it might be interpreted as a list variable, since it contains the default separator ‘:’.
domain
The currently defined domain.
faculty
The faculty or site as defined in control (see site).
fqhost
The fully qualified (DNS/BIND) hostname of the system, which includes the domain name as well.
host
The hostname of the machine running the program.
ipaddress
The numerical form of the internet address of the host currently running cfengine.
MaxCfengines
The maximum number of cfengines which should be allowed to co-exist concurrently on the system. This can prevent excessive load due to unintentional spamming in situations where several cfagents are started independently. The default value is unlimited.
ostype
A short for of $(arch).
OutputPrefix
This quoted string can be used to change the default `cfengine:' prefix on output lines to something else. You might wish to shorten the string, or have a different prefix for different hosts. The value in this variable is appended with the name of the host. The default is equivalent to,
            OutputPrefix = ( "cfengine:$(host):")


RepChar
The character value of the string used by the file repository in constructing unique filenames from path names. This is the character which replaces ‘/’ (see the reference manual).
site
This variable is identical to $(faculty) and may be used interchangeably.
split
The character on which list variables are split (see the reference manual).
sysadm
The name or mail address of the system administrator.
timezone
The current timezone as defined in control.
UnderscoreClasses
If this is set to `on' cfengine uses hard-classes which begin with an underscore, so as to avoid name collisions. See also Runtime Options in the Reference manual.
year
The current year.

These variables are kept special because they play a special role in setting up a system configuration. See Global configurations. You are encouraged to use them to define fully generalized rules in your programs. Variables can be used to advantage in defining filenames, directory names and in passing arguments to shell commands. The judicious use of variables can reduce many definitions to a single one if you plan carefully.

NOTE: the above control variables are not case sensitive, unlike user macros, so you should not define your own macros with these names.

The following variables are also reserved and may be used to produce troublesome special characters in strings.

cr
Expands to the carriage-return character.
dblquote
Expands to a double quote "
dollar
Expands to ‘$’.
lf
Expands to a line-feed character (Unix end of line).
n
Expands to a newline character.
quote
Expands to a single quote '.
spc
Expands simply to a single space. This can be used to place spaces in filenames etc.
tab
Expands to a single tab character.

You can use variables in the following places:

  • In any directory name. The $(binserver) variable is not always appropriate in this context. For instance
     
     links:
     
       osf::
           /$(site)/${host}/directory -> somefile
     
  • In any quoted string. (See shellcommands in the Reference manual).
     shellcommands:
     
       any::
     
        "/bin/echo $(timezone) | /bin/mail $(sysadm)"
        '/bin/echo "double quotes!"'
     

The latter possibility enables cfengine's variables to be passed on to user-defined scripts.

  • To define the values of options passed to various actions, in the form option=$(variable).

Variables can be defined differently under different classes by preceding the definition with a class name. For example:

     control:
     
        sun4::  my_macro = ( User_string_1 )
        irix::  my_macro = ( User_string_2 )
     

Here the value assigned to $(my_macro) depends on which of the classes evaluates to true. This feature can be used to good effect to define the mail address of a suitable system administrator for different groups of host.

     control:
     
      physics::   sysadm = ( mark,fred )
      chemistry:: sysadm = ( localsys@domain )
     

Note, incidentally, that the ‘-a’ option can be used to print out the mail address of the system administrator for any wrapper scripts.

3.3 Undefined variables

Note that macro-variables which are undefined are not expanded as of version 1.6 of cfengine. In earlier versions, undefined variables would be replaced by an empty string, as in Perl. In versions 1.6.x and later, the variable string remains un-substituted, if the varaiable does not exist. For instance,

     
     control:
     
       actionsequence = ( shellcommands )
     
       myvar = ( "test string " )
     
     shellcommands:
     
      "/bin/echo $(myvar) $(myvar2)"
     

results in:

     
     cfengine:host: Executing script /bin/echo test string  $(myvar2)
     cfengine:host:/bin/echo test : sh: syntax error at line 1: `(' unexpected
     cfengine:host: Finished script /bin/echo test string  $(myvar2)
     

This allows variables to be defined on-the-fly by modules.

3.4 Defining classes and making exceptions

Cfengine communicates with itself by passing messages in the form of classes. When a class becomes switched on or off, cfengine's program effectively becomes modified. There are several ways in which you can switch on and off classes. Learning these fully will take some time, and only then will you harness the full power of cfengine.

  • Classes may be defined manually from the command line.
  • Classes may be defined locally in the actionsequence in order to execute only some of the actions within a special category.
  • Classes may become defined if cfengine actually needs to carry out an action to repair the system's configuration.
  • Classes may be defined by user-defined plug-in modules.

Because cfagent works at a very high level, doing very many things for very few lines of code it might seem that some flexibility is lost. When we restrict certain actions to special classes it is occasionally useful to be able to switch off classes temporarily so as to cancel the special actions.

3.4.1 Command line classes

You can define classes of your own which can be switched on and off, either on the command line or from the action sequence. For example, suppose we define a class include. We use addclasses to do this.

     addclasses = ( include othersymbols )

The purpose of this would be to allow certain `excludable actions' to be defined. Actions defined by

     
     any.include::
                    actions
     

will normally be carried out, because we have defined include to be true using addclasses. But if cfagent is run in a restricted mode, in which include is set to false, we can exclude these actions.

So, by defining the symbol include to be false, you can exclude all of the actions which have include as a member. There are two ways in which this can be done, one is to negate a class globally using

     

cfagent -N include

This undefines the class include for the entire duration of the program.

3.4.2 actionsequence classes

Another way to specify actions is to use a class to select only a subset of all the actions defined in the actionsequence. You do this by adding a class name to one on the actions in action sequence by using a dot ‘.’ to separate the words. In this case the symbol only evaluates to `true' for the duration of the action to which it attached. Here is an example:

     
       links.onlysome
       shellcommands.othersymbols.onlysome
     

In the first case onlysome is defined to be true while this instance of links is executed. That means that only actions labelled with the class onlysome will be executed as a result of that statement. In the latter case, both onlysome and othersymbols are defined to be true for the duration of shellcommands.

This syntax would normally be used to omit certain time-consuming actions, such as tidying all home directories. Or perhaps to synchronize certain actions which have to happen in a certain order.

3.4.3 shellcommand classes

For more advanced uses of cfengine you might want to be able to define a class on the basis of the success or failure of a user-program, a shell command or user script. Consider the following example

     
     groups:
     
        have_cc = ( "/bin/test -f /usr/ucb/cc"
                    "/bin/test -f /local/gnu/cc"  )
     

Note that as of version 1.4.0 of cfengine, you may use the word classes as an alias for groups. Whenever cfagent meets an object in a class list or variable, which is surrounded by either single, double quotes or reversed quotes, it attempts to execute the string as a command passed to the Bourne shell. If the resulting command has return code zero (proper exit) then the class on the left hand side of the assignment (in this case ‘have_cc’) will be true. If the command returns any other value (an error number) the result is false. Since groups are the logical OR of their members (it is sufficient that one of the members matches the current system), the class ‘have_cc’ will be defined above if either /usr/ucb/cc or /local/gnu/cc exist, or both.

3.4.4 Feedback classes

Classes may be defined as the result of actions being carried out by cfagent. For example, if a file gets copied, needs to be edited or if diskspace falls under a certain threshhold, cfagent can be made to respond by activating classes at runtime. This allows you to create dynamically responsive programs which react to the changing environment. These classes are defined as part of other statements with clauses of the form

     
       define=classlist
     

Classes like these should generally be declared at the start of a program unless the define statements always precede the actions which use the defined classes, with addinstallable.

3.4.5 Writing plugin modules

If the regular mechanisms for setting classes do not produce the results you require for your configuration, you can write your own routines to concoct the classes of your dreams. Plugin modules are added to cfagent programs from within the actionsequence, (see Reference manual). They allow you to write special code for answering questions which are too complex to answer using the other mechanisms above. This allows you to control classes which will be switched on and the moment at which your module attempts to evaluate the condition of the system.

Modules must lie in a special directory defined by the variable moduledirectory. They must have a name of the form module:mymodule and they must follow a simple protocol. Cfagent will only execute a module which is owned either by root or the user who is running cfagent, if it lies in the special directory and has the special name. A plug-in module may be written in any language, it can return any output you like, but lines which begin with a ‘+’ sign are treated as classes to be defined (like -D), while lines which begin with a ‘-’ sign are treated as classes to be undefined (like -N). Lines starting with ‘=’ are variables/macros to be defined. Any other lines of output are cited by cfagent, so you should normally make your module completely silent. Here is an example module written in perl. First we define the module in the cfagent program:

     
      control:
     
        moduledirectory = ( /local/cfagent/modules )
     
        actionsequence = (
                         files
                         module:myplugin
                         "module:argplugin arg1 arg2"
                         copy
                         )
      ...
        AddInstallables = ( specialclass )
     

Note that the class definitions for the module should also be defined in as AddInstallables, if this is more convenient. NOTE: you must declare the classes before using them in the cfagent configuration, or else those actions will be ignored. Next we write the plugin itself.

     #!/usr/bin/perl
     #
     # module:myplugin
     #
     
       # lots of computation....
     
     if (special-condition)
        {
        print "+specialclass";
        }
     

Modules inherit the environment variables from cfagent and accept arguments, just as a regular shellcommand does.

     #!/bin/sh
     #
     # module:myplugin
     #
     
     /bin/echo $*
     

Cfagent defines the classes as an environment variable so that programs have access to these. E.g. try the following module:

     #!/usr/bin/perl
     
     print "Decoding $ENV{CFALLCLASSES}\n";
     
     @allclasses = split (":","$ENV{CFALLCLASSES}");
     
     while ($c=shift(@allclasses))
       {
       $classes{$c} = 1;
       print "$c is set\n";
       }
     

Modules can define macros in cfagent by outputting strings of the form

     
     =variablename=value
     

When the $(allclasses) variable becomes too large to manipulate conveniently, you can access the complete list of currently defined classes in the file /var/cfengine/state/allclasses.

3.5 The generic class any

The generic wildcard any may be used to stand for any class. Thus instead of assigning actions for the class sun4 only you might define actions for any architecture by specifying:

     
       any::
             actions
     

If you don't specify any class at all then cfengine assumes a default value of any for the class.

3.6 Debugging tips

A useful trick when debugging is to eliminate unwanted actions by changing their class name. Since cfengine assumes that any class it does not understand is the name of some host, it will simply ignore entries it does not recognize. For example:

        myclass::

can be changed to

        Xmyclass::

Since Xmyclass no longer matches any defined classes, and is not the name of any host it will simply be ignored. The -N option can also be used to the same effect. (see Reference manual).

3.7 Access control

It is sometimes convenient to be able to restrict the access of a program to a handful of users. This can be done by adding an access list to the control: section of your program. For example,

     control:
         ...
         access = ( mark root )
     

would cause cfengine to refuse to run the program for any other users except mark and root. Such a restriction would be useful, for instance, if you intended to make set-user-id scripts but only wished certain users to be able to run them. If the access list is absent, all users can execute the program. Note: if you are running cfagent via the cfrun program then cfagent is always started with the same user identity as the cfservd process on the remote host. Normally this is the root user identity. This means that the access keyword will have no effect on the use of the command cfrun.

3.8 Wildcards in directory names

In the two actions files and tidy you define directory names at which file checking or tidying searches should start. One economical feature is that you can define a whole group of directories at which identical searches should start in one fell swoop by making use of wildcards. For example, the directory names

          /usr/*/*
          /bla/*/ab?/bla

represent all of the directories (and only directories) which match the above wildcard strings. Cfagent opens each matching directory and iterates the action over all directories which match.

The symbol ‘?’ matches any single character, whereas ‘*’ matches any number of characters, in accordance with shell file-substitution wildcards. When this notation is used in directory names, it always defines the starting point for a search. It does not tell the command how to search, only where to begin. The pattern directive in tidy can be used to specify patterns when tidying files and under files all files are considered, (see Reference manual),

3.9 Recursive file sweeps/directory traversals

File sweeps are searches through a directory tree in which many files are examined and considered for processing in some way. There are many instances where one uses cfagent to perform a file sweep.

  • As part of a files action, for checking access rights and ownership of files.
  • As part of a tidy action, for checking files for deletion.
  • As part of a copy action, while recursively checking whether to copy a file tree.
  • As part of an editfiles action, while recursively checking whether to edit the files in a tree of files.
The problem with file sweeps is that they can be too sweeping! Often you are not interested in examining every single file in a file tree. You might wish to perform a search
  • excluding certain named directories and their subdirectories with ignore.
  • excluding certain files and directories matching a specific pattern.
  • including only a subset of files matching specific patterns.
  • filter out very specific file types.
The tidy action is slightly different in this respect, since it already always expects to match a specific pattern. One is generally not interested in a search which deletes everything except for a named pattern: this would be too dangerous. For this reason, the syntax of tidy does not allow ignore, include and exclude. It is documented in the section on tidying, (see Reference manual).

Items declared under the global ignore section affect files, copy, links and tidy. For file sweeps within files, copy and links, you may provide private ignore lists using ignore=. The difference between exclude and ignore is that ignore can deal with absolute directories. It prunes directories, while exclude only looks at the files within directories. For file sweeps within files and copy you can specify specific search parameters using the keywords include= and exclude= and as of version 1.6.x filter=. For example,

     files:
     
        /usr/local/bin m=0755 exclude=*.ps action=fixall
     

In this example cfagent searches the entire file tree (omitting any directories listed in the ignore-list and omitting any files ending in the extension .ps), (see Reference manual).

Specifying the include= keyword is slightly different since it automatically restricts the search to only named patterns (using * and ? wildcards), whenever you have one or more instances of it. If you include patterns in this way, cfagent ignores any files which do not match the given patterns. It also ignores any patterns which you have specified in the global ignore-list as well as patterns excluded with exclude=pattern. In other words, exclusions always override inclusions.

If you exclude a pattern or a directory and wish to treat it in some special way, you need to code an explicit check for that pattern as a separate entity. For example, to handle the exluded .ps files above, you would need to code something like this:

     files:
     
        /usr/local/bin m=0644 include=*.ps action=fixall
     

Note: don't be tempted to enclose your wildcards in quotes. The quotes will be treated literally and the pattern might not match the way you would expect. For editfiles the syntax is somewhat different. Here one needs to add lines to the edit stanza:

     
     editfiles:
     
      { /tmp/testdir
     
      Include .*
      Exclude bla.*
      Ignore "."
      Ignore ".."
      Recurse 6
     
      ReplaceAll "search" With "replace"
      }
     


Next: , Previous: File sweeps, Up: More advanced concepts

3.10 Security in Recursive file sweeps

Recursively descending into directories and performing a globally `destructive' change is an inherently risky thing to do, unless you are certain of the directory structure.

Suppose, for instance, that a user with write access to the filesystem added a symbolic link to /etc/passwd, and we were doing a recursive deletion. Suddenly, cfengine becomes a destructive weapon. The default behaviour is that cfengine does not follow symbolic links in recursive descents, for this reason. The option travlinks can be set to true, in order to change this. However, in general, you should never change this option, especially if untrusted users have access to parts of the filesystem, e.g. if you clear /tmp recursively.

Cfagent checks for link race attacks, in which users try to swap a directory for a link, in between system calls, to trick cfagent into believing that a link is a directory, as of version 2.0.3 (and 1.6.4). Note that, even if travlinks is set to true, cfagent will not follow symbolic links that are not owned by the agent user ID; this is to minimize the possibilty of link race attacks, in which users with write access could divert the agent to another part of the filesystem.

3.11 Log files written by cfagent

Cfagent keeps two kinds of log-file privately and it allows you to log its activity to syslog. Syslog logging may be switched on with the Syslog variable, (see Reference manual).

The first log cfagent keeps is for every user (every subdirectory of a home directory filesystem). A file ~/.cfengine.rm keeps a list of all the files which were deleted during the last pass of the tidy function. This is useful for users who want to know files have been removed without their blessing. This helps to identify what is happening on the system in case of accidents.

Another file is built when cfagent searches through file trees in the files action. This is a list of all programs which are setuid root, or setgid root. Since such files are a potential security risk, cfagent always prints a warning when it encounters a new one (one which is not already in its list). This allows the system administrator to keep a watchful eye over new programs which appear and give users root access. The cfengine log is called /var/cfengine/cfengine.log. The file is not readable for general users.

3.12 Quoted strings

In several cfengine commands, you use quoted strings to define a quantity of text which may contain spaces. For example

     
     control:
     
       macro = ( "mycommand" )
     
     editfiles:
     
       { $(HOME)/myfile
     
        AppendIfNoSuchLine 'This text contains space'
       }
     

In each case you may use any one of the three types of quote marks in order to delimit strings,

     
       ' or " or `
     

If you choose, say ", then you may not use this symbol within the string itself. The same goes for the other types of string delimiters. Unlike the shell, cfengine treats these three delimiters in precisely the same way. There is no difference between them. If you need to quote a quoted string, then you should choose a delimiter which does not conflict with the substring before version 2.0.7. From version 2.0.7, you can escape quotes.

     
       qstring = ( "One string\"with substring\" escaped" )
     

Note that you can use special variables for certain symbols in a string See Variable substitution.

3.13 Regular expressions

Regular expressions can be used in cfagent in connection with editfiles and processes to search for lines matching certain expressions. A regular expression is a generalized wildcard. In cfagent wildcards, you can use the characters '*' and '?' to match any character or number of characters. Regular expressions are more complicated than wildcards, but have far more flexibility.

NOTE: the special characters ‘*’ and ‘?’ used in wildcards do not have the same meanings as regular expressions!.

Some regular expressions match only a single string. For example, every string which contains no special characters is a regular expression which matches only a string identical to itself. Thus the regular expression ‘cfengine’ would match only the string "cfengine", not "Cfengine" or "cfengin" etc. Other regular expressions could match more general strings. For instance, the regular expression ‘c*’ matches any number of c's (including none). Thus this expression would match the empty string, "c", "cccc", "ccccccccc", but not "cccx".

Here is a list of regular expression special characters and operators.

\
The backslash character normally has a special purpose: either to introduce a special command, or to tell the expression interpreter that the next character is not to be treated as a special character. The backslash character stands for itself only when protected by square brackets [\] or quoted with a backslash itself ‘\\’.
\b
Matches word boundary operator.
\B
Match within a word (operator).
\<
Match beginning of word.
\>
Match end of word.
\w
Match a character which can be part of a word.
\W
Match a character which cannot be part of a word.
any character
Matches itself.
.
Matches any character
*
Match zero or more instances of the previous object. e.g. ‘c*’. If no object precedes it, it represents a literal asterisk.
+
Match one or more instances of the preceding object.
?
Match zero or one instance of the preceding object.
{ }
Number of matches operator. ‘{5}’ would match exactly 5 instances of the previous object. ‘{6,}’ would match at least 6 instances of the previous object. ‘{7,12}’ would match at least 7 instances of, but no more than 12 instances of the preceding object. Clearly the first number must be less than the second to make a valid search expression.
|
The logical OR operator, OR's any two regular expressions.
[list]
Defines a list of characters which are to be considered as a single object (ORed). e.g. ‘[a-z]’ matches any character in the range a to z, ‘abcd’ matches either a, b, c or d. Most characters are ordinary inside a list, but there are some exceptions: ‘]’ ends the list unless it is the first item, ‘\’ quotes the next character, ‘[:’ and ‘:]’ define a character class operator (see below), and ‘-’ represents a range of characters unless it is the first or last character in the list.
[^list]
Defines a list of characters which are NOT to be matched. i.e. match any character except those in the list.
[:class:]
Defines a class of characters, using the ctype-library.
alnum
Alpha numeric character
alpha
An alphabetic character
blank
A space or a TAB
cntrl
A control character.
digit
0-9
graph
same as print, without space
lower
a lower case letter
print
printable characters (non control characters)
punct
neither control nor alphanumeric symbols
space
space, carriage return, line-feed, vertical tab and form-feed.
upper
upper case letter
xdigit
a hexadecimal digit 0-9, a-f

( )
Groups together any number of operators.
\digit
Back-reference operator (refer to the GNU regex documentation).
^
Match start of a line.
$
Match the end of a line.

Here is a few examples. Remember that some commands look for a regular expression match of part of a string, while others require a match of the entire string (see Reference manual).

     
     ^#        match string beginning with the # symbol
     ^[^#]      match string not beginning with the # symbol
     ^[A-Z].+  match a string beginning with an uppercase letter
               followed by at least one other character
     

3.14 Iterating over lists

Shell list variables are normally defined by joining together a list of directories using a concatenation character such as ‘:’. A typical example of this is the PATH variable:

     
     PATH=/usr/bin:/usr/local/bin:/usr/sbin
     

It is convenient to be able to use such variables to force cfagent to iterative over a list. This gives us a compact way of writing repeated operations and it allows a simple method of communication with the shell environment. For security reasons, iteration is supported only in the following contexts:

  • in the `to' field of a multiple link action,
  • in the `from' field of a copy action,
  • in the directory field of a tidy action,
  • in the directory field of the files action,
  • in the ignore action,
  • in a shell command.

This typically allows communication with PATH-like environment variables in the shell. In these contexts, any variable which has the form of a list joined together by colons will be iterated over at compilation time. Note that you can change the value of the list separator using the Split variable in the control section of the program (see Reference manual).

For example, to link all of the binary files in the PATH environment variable to a single directory, tidying dead links in the process, you would write

     
     control:
     
       actionsequence = ( links tidy )
     
     links:
     
       /allbin +> $(PATH)
     
     tidy:
     
       # Hopefully no-match matches nothing
     
       /allbin pattern=no-match age=0 links=tidy
     

no-match is not a reserved word in cfengine, this is just a string you do not expect to match any file.

Alternatively, you might want to define an internal list using a space as a separator:

     
     control:
     
        Split = ( " " )
     
        mylist = ( "mark ricky bad-dude" )
     
     tidy:
     
        /mnt/home1/$(mylist) pattern=*.cfsaved age=1
     

This example iterates the tidy action over the directories /mnt/home1/mark, /mnt/home1/ricky and /mnt/home1/bad-dude.

The number of list variables in any path or filename should normally be restricted to one or two, since the haphazard combination of two lists will seldom lead to any meaningful pattern. The only obvious exception is perhaps to iterate over a common set of child-directories like bin, lib etc in several different package directories.

4 Designing a global system configuration

This chapter is about building strategies for putting together a site configuration for your entire network.

4.1 General considerations

In order to use any system administration tool successfully, you have to make peace with your system by deciding exactly what you expect and what you are willing to do to achieve the results. You need to decide what you will consider to be acceptable and what is to be considered completely untenable. You need to make these decisions because otherwise you will only be confused later when things don't go the way you expected. Experience shows that the most successful policies for automation involve keeping everything as simple as possible. The more uniform or alike your machines are, the easier they are to run and the happier users are. Sometimes people claim that they need such great flexibility that all their machines should be different. This belief tends to be inversely proportional to the number of machines they run and generally only applies to very special development environments! Usually you will only need one or two machines to be special and most can be made very similar.

Site configuration is about sharing and controlling resources. The resources include disks (filespace), files, data, programs, passwords and physical machines. Before planning your sitewide configuration you should spend some time deciding how you would like things to work.

In the remaining parts of this chapter, you will find some hints and tips about how to proceed, but remember that when push comes to shove, you must make your own choices.

4.2 Using netgroups

If you use the network information service (NIS) on your local network then you may already have defined netgroups consisting of lists of hosts which belong to specific owners at your site. If you have, then you can use these groups within cfengine. This means that you can use the same groups in the /etc/exports file as you use to define the mount groups and classes.

A netgroup is a list of hostnames or user names which are registered in the network information service (NIS) database under a specific name. In our case we shall only be interested in lists of hostnames.

To make a netgroup you need to define a list in the file /etc/netgroup on your NIS server. If you are not the NIS administrator, you will have to ask to have a netgroup installed. The form of a netgroup list of hosts is:

     
     mylist-name      (host1,,) (host2,,) (host3,,) (host4,,)
     
     norway-sun4-host (saga,,) (tor,,) (odin,,)
     foes-linux-hosts (borg,,)
     

Each list item has three entries, but only the first is relevant for a host list. See the manual pages on netgroups for a full explanation of the meaning of these fields.

The usefulness of netgroups is that they can be used to stand for a list of hostnames in system files like /etc/exports. This compresses the amount of text in this file from a long list to a single name. It also means that if you use the same list of hosts from a netgroup inside cfengine when defining groups and classes, you can be sure that you are always using the same list. In particular it means that you don't have to update multiple copies of a list of hosts.

The netgroups can now be used in cfengine programs by using the + or @+ symbols in the groups section. (see Reference manual).

4.3 Files and links

File and link management takes several forms. Actions are divided into three categories called files, tidy and links. The first of these is used to check the existence of, the ownership and permissions of files. The second concerns the systematic deletion of garbage files. The third is a link manager which tests, makes and destroys links. The monitoring of file access bits and ownership can be set up for individual files and for directory trees, with controlled recursion. Files which do not meet the specified criteria can be `fixed' —i.e. automatically set to the correct permissions, or can simply be brought to the attention of the system administrator by a warning. The syntax of such a command is as follows:

     
     files:
     
       class::
     
         /path mode=mode owner=owner group=group
     
              recurse=no-of-levels action=action
     

The directory or file name is the point at which cfagent begins looking for files. From this point the search for files proceeds recursively into subdirectories with a maximum limit set by the recurse directive, and various options for dealing with symbolic links and device boundaries. The mode-string defines the allowed file-mode (by analogy with ‘chmod’) and the owner and group may specify lists of acceptable user-ids and group-ids. The action taken in response to a file which does not meet acceptable criteria is specified in the action directive. It includes warning about or directly fixing all files, or plain files or directories only. Safe defaults exist for these directives so that in practice they may be treated as options.

For example,

     files:
     
       any::
            /usr/*/bin mode=a+rx,o-w own=root r=inf act=fixall
     

which (in abbreviated form) would check recursively all files and directories starting from directories matching the wildcard (e.g. /usr/local/bin, /usr/ucb/bin). By default, fixall causes the permissions and ownership of the files to be fixed without further warning.

One problem with symbolic links is that the files they point to can get deleted leaving a `hanging pointer'. Since cfagent can make many hundreds of links without any effort, there is the danger that, in time, the system could become full of links which don't point anywhere. To combat this problem, you can set the option links=tidy in the files section. If this is set, cfagent will remove any symbolic links which do not point to existing files (see Reference manual).

The creation of symbolic links is illustrated in figure 1 and the checking algorithm was discussed in section 2. In addition to the creation of single links, one may also specify the creation of multiple links with a single command. The command

     links:
     
        binaryhost::
     
           /local/elm/bin +> /local/bin
     

links all of the files in /local/elm/bin to corresponding files in /local/bin. This provides, amongst other things, one simple way of installing software packages in regular `bin' directories without controlling users' PATH variable. A further facility makes use of cfagent's knowledge of available (mounted) binary resources to search for matches to specific links. Readers are referred to the full documentation concerning this feature.

The need to tidy junk files has become increasingly evident during the history of cfengine. Files build up quickly in areas like /tmp, /var/tmp. Many users use these areas for receiving large ftp-files so that their disk usage will not be noticed! To give another example, just in the last few months the arrival of netscape World Wide Web client, with its caching facilities, has flooded hard-disks at Oslo with hundreds of megabytes of WWW files. In addition the regular appearance of core files1 and compilation by-products (‘.o’ files and ‘.log’ files etc.) fills disks with large files which many users do not understand. The problem is easily remedied by a few lines in the cfagent configuration. Files can be deleted if they have not been accessed for n-days. Recursive searches are both possible and highly practical here. In following example:

     tidy:
     
        AllHomeServers::
     
           home                 pattern=core       r=inf age=0
           home/.wastebasket    pattern=*          r=inf age=14
           home/.netscape-cache pattern=cache????* r=inf age=2
           home/.MCOM-cache     pattern=cache????* r=inf age=2
           home/.netscape       pattern=cache????*  r=inf age=2
     

all hosts in the group ‘AllHomeServers’ are instructed to iterate over all users' home directories (using the wildcard home) and look for files matching special patterns. Cfagent tests the access time of files and deletes only files older than the specified limits. Hence all core files, in this example, are deleted immediately, whereas files in the subdirectory .wastebasket are deleted only after they have lain there untouched for 14 days, and so on.

As a system administrator you should, of course, exercise great caution when making rules which can delete users' files. A single slip of the hand can result in a rule which will irretrievably delete files.

When making a `tidy' strategy you should probably coordinate with your backup policy. You should not delete files until after you have taken a backup, so that — if the worst should happen — you are covered against possible accidents.

Cfagent helps to some extent to keep track of what files it deletes. When tidying users' home directories it creates a log file of all files which were deleted on the last tidy operation. This log is called ~/.cfengine.rm.

You might consider tidying certain files only once a week, in which case a command such as

     
     tidy:
     
        AllHomeServers.Sunday::
     
            files to tidy
     

could be useful. Nonsense files, such as `core' files could be tidied every night.

NOTE! Be careful when telling cfagent to delete core files. If you write a wildcard like core*, then you could risk deleting important system files such as core.h.

4.4 Copying files

The administration of a system often requires the copying of files. The reason for this is usually that we would like to distribute a copy of a particular file, from some master location and ensure that all of the copies are up to date. Another use for this is to install software from one directory (perhaps on a CD ROM) to another.

Cfagent helps this process by allowing you to copy a single file or a file tree, from one directory to another, perhaps checking the permissions and owners of a file to adjust the copies in some special way. The files are checked by cfagent using one of two methods.

  • A date-stamp comparison with a master file, using last-change times, can be used to tell cfagent to recopy a file from the master if the master file is newer than the copy.
  • A checksum can be computed for each file and compared with one for the master file. If the contents of the copy file differs in any way from the master, the file will be re-copied.

Cfengine allows you to do the following

  • Copy a single file to another file in a different location, perhaps with a new name, new permissions and a different owner.
  • Copy a single file to all users on the system, changing the owner of the file for each user automatically. (This could be used to distribute and update standard setup files.)
  • Recursively copy an entire file tree, omitting files which match a list of wildcard-patterns, or linking certain files instead of copying.
You can find out more about copying in the reference section.

4.5 Managing processes

Cfagent allows you to check for the existence of processes on your system, send those processes signals (such as kill) and perhaps restart those processes. Typical applications for this are sending cron and inetd the HUP signal, after editing their configuration files, or killing unwanted processes (such as user programs which hog the system at peak usage times).

You can read more about this in the reference section .

4.6 Cfengine's model for NFS-mounted filesystems

Most of the filesystems that you will want to make available across the network are going to fall into one of two categories. In cfengine parlance these are called home directories and binary directories. A home directory is a place where users' login directories are kept. This is traditionally a directory called /home or /users or some subdirectory of these. A binary directory is a place where compiled software is kept. Such files (which do not belong to the pure operating system release) are often placed in a directory called /usr/local or simply /local.

In this chapter we shall consider a scheme for using cfengine to make NFS filesystem management quite painless.

4.6.1 NFS filesystem resources

Using the Network File System (NFS) in a large workstation environment requires a bit of planning. The idea of NFS is to share files on one host with other hosts. In most cases, filesystems to be shared across the network fall into two categories: binary filesystems (those which contain compiled software) and user or home filesystems (which contain users' login areas).

The most simple minded way to share resources would be to mount every resource (each available NFS filesystem) onto every host. To avoid collisions, each filesystem would have to have a unique name. This is one possibility, but not a very intelligent one. As experienced users will realize, cross-mounting too many NFS filesystems is a recipe for all kinds of trouble.

Cfengine offers a simple model which can help you pick out only the resources you need from the list of NFS filesystems. It will then mount them automatically and edit the appropriate filesystem tables. It does this by defining classes of hosts. For instance — you really don't need to mount a binary filesystem for an ultrix system onto an HPUX system. There would be no point — binary resources are architecture or hard-class dependent. But home directories are architecture independent.

Cfengine lets you to define a list of allowed servers for various hosts so that only filesystems from the servers will be considered for mounting!

4.6.2 Unique filesystem mountpoints

The first step towards treating NFS filesystems as network resources is to invent a naming scheme so that every filesystem has a unique name on which it can be mounted. If we don't sort this out now, we could find two or more hosts with a filesystem called /usr/local, both of which we might like to mount since they contain different software.

A simple but extremely useful naming scheme is the following. 2 If you don't like this scheme you can invent your own, but the remainder of the text will encourage you to use this one. If you follow this scheme, exactly as described here, you will never have any problems with mount points. We shall describe the scheme in detail below. Here are some points to digest:

  • When mounting a remote filesystem on your local system, the local and remote directories should always have exactly the same name.
  • The name of every filesystem mountpoint should be unique and tell you something meaningful about where it is located and what its function is.
  • You can always make links from special unique names to more general names like /usr/local. If you this involves compiled software and you do this on one host, you should do it on others which are of the same type.
  • It doesn't matter whether software compiles in the path names of special directories into software as long as you follow the points above.

Each filesystem is given a directory name composed of three parts:

     
     /site/host/contents
     

The first directory (which only exists to create a suitable mountpoint) is the name of your local site. If you are a physics department at a university (with a separate setup) you could call this `physics'. It could be your company name or whatever. The second piece is the name of the host to which the disk space is physically attached. The final piece is the name of the filesystem. Here are some typical examples:

     /physics/einstein/local    # /usr/local for einstein@physics
     /physics/newton/u1         # user partition 1 for newton@physics

On the machines which are home to the `local' partition, it is better to make a link to /usr/local than call the filesystem /usr/local directly. This is because it makes the procedure of organizing the entire network much clearer.

It is worth noting that, when you ask cfagent to mount such a resource, it will automatically make the mount directory and can easily be asked to make a link to /usr/local, so this small amount of extra work is really no work at all.

The whole naming convention is compactly summarized by defining a mount point variable, mountpattern. With the present scheme, this can be defined as

     mountpattern = ( /$(site)/$(host) )

so that it evaluates to the name of the host executing the file regardless of who that may be. This variable is used together with the homepattern pattern variable, which is used to distinguish between home directories and binary resources. (See homepattern in the reference section). You can think of this as being part of the naming convention. In this text, we use the convention u1 u2 u3... for home disks. You could equally well use home1 home2... etc. As long as the name is unique, it doesn't matter.

The full list of named resources should now be listed in the mountables list, which is simply a list of all the resources available for mounting on the network.

4.6.3 How does it work?

Once you have defined your unique names, how does cfagent know what to mount? The idea is now to define a list of servers for each class of hosts.

Suppose we make a binserver declaration:

     
     binservers:
     
       mygroup.sun4::
     
          einstein
          newton
     

This would tell cfagent that it should mount all binary resources from hosts einstein or newton onto any host of type sun4 in the group mygroup. Every filesystem which is listed in mountables and is not a home directory will be mounted.

Home directories and binary resources are kept separate automatically by cfagent, because a home directory is one whose contents-name matches the homepattern pattern variable. See Unique filesystem mountpoints.

A homeserver declaration:

     
     homeservers:
     
       mygroup::
     
          einstein
          newton
          schwinger
          feynman
     

would correspondingly mean mount all the home directory resources on the hosts in the list on all hosts in the group mygroup. Clearly it is unnecessary to distinguish between the architecture platform types of the actual servers for user directories.

In each case, cfagent will mount filesystems, make the appropriate directories for the mount point and edit the filesystem table.


Next: , Previous: How does it work?, Up: NFS resources

4.6.4 Special variables

Once you have mounted a resource on a unique directory, you have access to all of the relevant filesystems on your network — but you really wanted the `local' filesystem to be mounted on /usr/local. All you need do now is to make a link:

     
     links:
     
       any::
     
           /usr/local  -> /$(site)/$(binserver)/local
     

The meaning of this is that, on any host, the directory /usr/local should be a link to the `nearest' binary server's `local' resource. The $(binserver) variable can in principle expand to any binary server in the list. In practice, cfagent goes through the list in order and picks the first filesystem resource which matches.

Could this lead to a collision? Suppose we are on the host `einstein' and we execute the above command. The host `einstein' has a filesystem /physics/einstein/local on its local disk — it is in fact the binary server for the network, so it certainly doesn't need to mount any NFS filesystems. But this is no problem because cfagent automatically treats $(host) as the highest priority binary server for any host. That means that if you have a local filesystem, it will always have priority.

In contrast, if the host `schwinger' ran the command above, it would find no local filesystem called /physics/schwinger/local, so it would go along the list of defined binary servers, find `einstein' and try again. It will succeed in finding `einstein' provided all the binary servers were mounted before the link command is executed. This means that you should structure the actionsequence so that all filesystems are mounted before any links are made.

With a little practice, the cfengine model can lead to an enormous simplification of the issue of NFS-mountable resources.

NOTE: cfengine does not try to export filesystems, only mount already exported filesystems. If you want to automate this procedure also, you can use the editfiles facility to add entries to /etc/exports (see editfiles in the Reference manual). In practice this is very difficult to do and perhaps not desirable.


Previous: Special variables, Up: NFS resources

4.6.5 Example programs for mounting resources

Let's write a very simple configuration for a network with only one server called hal, where all the hosts are of the same operating system type. In such an example we can avoid using classes altogether.

     
     control:
     
       site   = ( univ )
       domain = ( univ.edu )
     
       actionsequence =
          (
          mountall
          mountinfo
          addmounts
          mountall
          links
          )
     
       mountpattern = ( /univ )
       homepattern = ( home? )
     
     binservers:
     
        hal
     
     homeservers:
     
        hal
     
     mailserver:
     
        hal:/var/spool/mail
     
     mountables:
     
        hal:/univ/home1
        hal:/univ/home2
        hal:/univ/local
     
     links:
     
        /usr/local -> /univ/local
     

In this example, we have only one type of host so the configuration is the same for each of them: no class references are required. If we look through the action sequence we see that the program first mounts all the filesystems which are already defined on each host. It does this to be sure that everything which is already set up to be mounted is mounted. Let's assume that there are no problems with this.

The next thing that happens is that mountinfo builds a list of the filesystems which each host has successfully mounted. Then by calling addmounts we ask cfagent to check whether the host is missing any filesystems. What happens is that cfagent first looks to see what servers are defined for each host. In this case all hosts on the network have only one server: hal. Hal is defined as a server for both binary data and `home' data — i.e. users' home directories. The list mountables tells cfagent what filesystems are available over the network for the server hal. There are three filesystems which can be mounted, called /univ/home1, /univ/home2 and /univ/local. Cfagent checks to see whether each of these filesystems is mounted and, if not, it builds the necessary directories, edits the necessary files and mounts the filesystems.

Finally we come to links in the action sequence. This tells cfagent to look at the defined links. There is one link defined: a link from /usr/local to the mounted filesystem /univ/local. Cfagent checks and tries to make the link if necessary. If all goes well, each host on the network should now have at least three filesystems mounted and a link from /usr/local to /univ/local.

Here is another simple example program for checking and automatically mounting an NFS based /usr/local and all home directories onto all hosts on a small network. Here we have several servers and must therefore use some classes.

     #
     #  Mounts
     #
     
     
     control:
     
        site      = ( mysite )
        domain    = ( mysite.country )
        sysadm    = ( mark )
        netmask   = ( 255.255.255.0 )
     
        actionsequence =
           (
           mountall
           mountinfo
           addmounts
           mountall
           links
           )
     
        mountpattern = ( /$(site)/$(host) )
        homepattern   = ( u? )                # u1 u2 u3 etc..
     
     groups:
     
        MyGroup =
           (
           host1
           host2
           binserver1
           binserver2
           )
     
     ######################################################################
     
     homeservers:
     
        MyGroup:: host1
     
     
     binservers:
     
        MyGroup.sun4::   server1
        MyGroup.ultrix:: server2
     
     mailserver:
     
        host1:/usr/spool/mail
     
     mountables:
     
        host1:/mysite/host1/u1
        host1:/mysite/host1/u2
        server1:/mysite/server1/local
        server2:/mysite/server2/local
     
     
     ##########################################################################
     
     links:
     
           /usr/local  -> /${site}/${binserver}/local
     

Let's suppose we run this program on host2 which is an ultrix machine. This host belongs to the class mygroup and the hard-class ultrix. This tells us that its homeserver is host1, its binary server is server2 and its mailserver is host1. Moreover, since the homepattern matches any filesystem ending in u-something, it recognizes the two home directories in the mountables list — and therefore the two binary directories also.

The action sequence starts by mounting all of the filesystems currently in the filesystem table /etc/fstab. It then scans the list of mounted filesystems to find out what is actually mounted. Since the homeserver is host1, we know that our host has to mount all home-filesystems from this server, so it checks for host1:/mysite/host1/u1 and host1:/mysite/host1/u2. If they are not present they are added to /etc/fstab3. Next, we know that the binary server is server1, so we should check for server1:/mysite/server1/local. The mail server is also checked for and added if necessary. Cfagent then tries to mount all filesystems once again, so that the new filesystems should be added.

Note that, in the process of adding the filesystems to /etc/fstab, cfagent creates the directories up to and including the point at which the filesystems should be mounted. If something prevents this — if we try to mount on top of a plain file for instance — then this will result in an error.

Finally, we reach the link section and we try to expand the variables. $(site) expands to mysite. $(binserver) expands first to the hostname (host2), but /mysite/host2/local does not exist, so it then goes to the binserver list, which substitutes server1 for the value of $(binserver). Since /mysite/server1/local does exist and is now mounted, cfagent makes a link to this directory from /usr/local. The script is then completed.

If the script is run again, everything should now be in place so nothing happens. If for some reason it failed the first time, it will fail again. At any rate it will either do the job once and for all or signal an error which must be corrected by human intervention4.

4.7 Using the automounter

The automounter is a daemon based service which replaces static mounting of NFS filesystems with a dynamical model. When the automounter is running, filesystems are mounted only when a user tries to access a file which resides on one of those filesystem. After a given period (usually five minutes) any filesystem which has not been accessed is unmounted. The advantage of this scenario is that hanging servers do not affect the behaviour of hosts which mount their filesystems, unless a specific file is being accessed. In both cases, filesystems must be exported in order to be mountable.

It is not the purpose of this section to explain the use of the automounter in detail, only to offer hints as to how cfengine can be used to simplify and rationalize automount configuration for the already initiated. Let us begin by comparing the behaviour of the automounter with the cfengine model for mounted filesystems.

The automounter is designed to be used together with a global configuration file, distributed by NIS (the network information service). As such, all hosts read the same configuration file. This makes it appear as though all hosts end up mounting every filesystem in the automount configuration database, but this is not so in practice because filesystems are only mounted if required. Thus a system which does not require a filesystem will not attempt to mount it. Moreover, the existence of a global configuration file does not affect which hosts have the right to mount certain filesystems (which is specified by exports or share on the relevant server), thus a request to mount a non-exported filesystem will result in an access denial. The automounter is configured locally on each host in files named /etc/auto_master, auto_direct etc. In the cfengine static mounting scheme, you define a list of binary and home servers. The filesystem table is modified on the basis of these decisions, and filesystems are only added if cfagent deems it appropriate to mount them on a given host. The idea here is to minimize the number of filesystems mounted to those which are known to be required. Again the issue of access permissions must be arranged separately. These filesystems are placed directly in /etc/fstab, or the equivalent for your system.

From cfengine, you can use the automounter instead of the static mount model by

  • omitting addmounts, mountinfo, mountall from the actionsequence, in the control part of your cfengine program,
  • using editfiles to edit the relevant configuration files such as /etc/auto_master, or auto_direct etc,
  • using the AutomountDirectResources command in editfiles to dump the list of cfengine class-based list of mountables into a file of your choice in the correct format for autmount's direct maps,
  • using processes to restart the automounter (send the hangup signal hup), or perhaps stop and restart the daemon by sending the term signal (you should never send the kill signal).
  • using the multiple link facilities to link in indirect mounted filesystems as required, and files or tidy to clean up stale links afterwards,
  • perhaps using copy to distribute basic automount configuration files to multiple systems.

The automounter was created to solve certain problems which cfengine now solves (in the author's opinion) better. For example, the use of the `hosts' map in the automounter mounts filesystems like /usr/local on different (uniquely named) mountpoints for each host in order to avoid name space collisions. Using cfengine and a unique naming scheme, you can achieve the same thing more cleanly, without all of the gratuitous linking and unlinking which the automounter performs by itself. Moreover, the idea of a unique name-space is better practice and more in keeping with new global filesystem ideas such as AFS and DFS. The only advantage of the automounter is that one avoids the annoying error messages from hung servers about "NFS server not responding". In that respect, it seems sensible to use only direct mounts and a unique name space.

Some systems advocate grouping all users' login (home) directories under a common directory called /home or users. The automounter goes through all manner of contortions to achieve this task. If you use a unique naming scheme like the one advocated here, this is a trivial task. You simply arrange to mount or automount all user directories, such as

        /site/host/home1
        /site/host/home2
        ...

and then link them as follows:

     
        /home +> /site/host/home1
        /home +> /site/host/home2
        ...
     

Finally, you should be aware that the automounter does not like to be mixed with static mount and unmount operations. Automounted filesystems take priority over statically mounted filesystems, but the automounter can be confused by manually mounting or unmounting filesystems while it is running.

4.8 Editing Files

A very convenient characteristic of BSD and UNIX System V systems is that they are configured primarily by human-readable textfiles. This makes it easy for humans to configure the system and it also simplifies the automation of the procedure. Most configuration files are line-based text files, a fact which explains the popularity of, for example, the Perl programming language. Cfengine does not attempt to compete with Perl or its peers. Its internal editing functions operate at a higher level which are designed for transparency rather than flexibility. Fortunately most editing operations involve appending a few lines to a file, commenting out certain lines or deleting lines.

For example, some administrators consider the finger service to be a threat to security and want to disable it. This could be done as follows.

     
     editfiles:
     
           { /etc/inetd.conf
     
           HashCommentLinesContaining "finger"
           }
     

Commands containing the word `Comment' are used to `comment out' certain lines from a text-file—i.e. render a line impotent without actually deleting it. Three types of comment were supported originally: shell style (hash) ‘#’, ‘%’ as used in TeX and on AIX systems, and C++-style ‘//’.

A more flexible way of commenting is also possible, using directives which first define strings which signify the start of a comment and the end of a comment. A single command can then be used to render a comment. The default values of the comment-start string is ‘# ’ and the default comment-end string is the empty string. For instance, to define C style comments you could write:

     
       { file
     
       SetCommentStart "/* "
       SetCommentEnd   " */"
     
       # Comment out all lines containing printf!
     
       CommentLinesMatching ".*printf.*"
       }
     

Other applications for these editing commands include monitoring and controlling root-access to hosts by editing files such as .rhosts and setting up standard environment variables in global shell resource files— for example, to set the timezone. You can use the editing feature to update and distribute the message of the day file, or to configure sendmail, (see FAQS and Tips in the Reference manual).

An extremely powerful feature of cfagent is the ability to edit a similar file belonging to every user in the system. For example, as a system administrator, you sometimes need to ensure that users have a sensible login environment. Changes in the system might require all users to define a new environment variable, for instance. This is achieved with the home pseudo-wildcard. If one writes

     
       { home/.cshrc
     
       AppendIfNoSuchLine "# Sys admin/cfengine: put next line here"
       AppendIfNoSuchLine "setenv PRINTER newprinter"
       }
     

then the users' files are checked one-by-one for the given lines of text, and edited if necessary.

Files are loaded into cfagent and edited in memory. They are only saved again if modifications to the file are carried out, in which case the old file is preserved by adding a suffix to the filename. When files are edited, cfagent generates a warning for the administrator's inspection so that the reason for the change can be investigated.

The behaviour of cfagent should not be confused with that of sed or perl. Some functionality is reproduced for convenience, but the specific functions have been chosen on the basis of (i) their readability and (ii) the fact that they are `frequently-required-functions'. A typical file editing session involves the following points:

  • Load file into memory.
  • Is the size of the file within sensible user-definable limits? If not, file could be binary, refuse to edit.
  • Check each editing command and count the number of edits made.
  • If number of edits is greater than zero, rename the old file and save the edited version in its place. Inform about the edit.
  • If no edits are made, do nothing, say nothing.

Equivalent one-line sed operations involve editing the same file perhaps many times to achieve the same results—without the safety checks in addition.

4.9 Disabling and the file repository

The existence of certain files can compromise the integrity of your system and you may wish to ensure that they do not exist. For example, some manufacturers sell their workstations with a ‘+’ symbol in the file /etc/hosts.equiv. This means that anyone in your NIS domain has password free access to the system!! Since this is probably not a good idea, you will want to disable this file by renaming it, or simply deleting it.

     
       disable:
     
          /etc/hosts.equiv
     

Other files compromise the system because they grow so large that they fill an entire disk partition. This is typically true of log files such as the System V files /var/adm/wtmpx and /var/lp/logs/lpsched. Other files like /var/adm/messages get "rotated" by the system so that they do not grow so large as to fill the disk. You can make cfagent rotate these files too, by writing

     
     disable:
     
         Sunday::
     
         /var/lp/logs/lpsched  rotate=3
     

Now, when cfagent is run, it renamed the file lpsched to a file called lpsched.1. It also renames lpsched.1 as lpsched.2 and so on, until a maximum of 3 files are kept. After passing 3, the files `fall off the end' and are deleted permanently. This procedure prevents any log files from growing too large. If you are not interested in keeping back-logs, then you may write rotate=empty and cfagent will simply empty the log file. When ever cfagent disables a file (disable or links with the ‘!’ operator), or saves a new file on top of an old one (copy or editfiles), it makes a backup of the original. Usually disabled files are renamed by appending the string .cfdisabled the filename; copied files are saved by appending the string .cfsaved. It is possible to switch off backup file generation in the copy feature by setting the variable backup=false, but a better way of managing disabled and backed-up files is to use a directory in which you collect all such files for the whole system. This directory is called the file repository and is set in the control part of the program, as follows: In the copy directive, the option backup=timestamp can be used to allow multiple backups. This is useful when using cfengine to make disk backups for users, since it allows multiple versions to co-exist.

     
       control:
     
          repository = ( directory-name )

If this variable is defined, cfagent collects all backup and disabled files (except for rotated files) in this directory, using a unique pathname. You can then inspect these files in the repository and arrange to tidy the repository for old files which are no longer interesting.

4.10 Running user scripts

Above all, the aim of cfengine is to present a simple interface to system administrators. The actions which are built into the engine are aimed at solving the most pressing problems, not at solving every problem. In many cases administrators will still need to write scripts to carry out more specific tasks. These scripts can still be profitably run from cfengine. Variables and macros defined in cfengine can be passed to scripts so that scripts can make maximal advantage of the class based decisions. Also note that, since the days of the week are also classes in cfengine, it is straightforward to run weekly scripts from the cfengine environment (assuming that the configuration program is executed daily). An obvious use for this is to update databases, like the fast-find database one day of the week, or to run quota checks on disks.

     shellcommands:
     
        myhost.Sunday::
     
           "/usr/bin/find/updatedb"
     

Cfengine scripts can be passed variables using normal variable substitution:

     control:
     
        cfbin     = ( /var/cfengine/bin )
        backupdir = ( /iu/dax/backup )
     
     shellcommands:
     
       "$(cfbin)/cfbackup -p -f $(backupdir) -s /iu/nexus/u1"
     

If you need to write a particularly complex script to expand cfagent's capabilities, it might be useful to have full access to the defined classes. You can do this in one of two ways:

  • Pass the variable $(allclasses) to the script. This contains a list of all classes in the form of a string
              
                    CFALLCLASSES=class1:class2:...
              
    

    This variable always contains an up to date list of the defined classes.

  • Use the command line option ‘-u’ or ‘--use-env’. When this is defined, cfagent defines an internal environment variable called ‘CFALLCLASSES’ which contains the same list as above. Unfortunately, System V boxes don't seem to like having to update an environment variable continuously and tend to dump core, so this is not the default behaviour!

4.11 Compressing old log files

In the previous two sections we have looked at how to rotate old log files and how to execute shell commands. If you keep a lot of old log files around on your system, you might want to compress them so that they don't take up so much space. You can do this with a shell command. The example below looks for files matching a shell wildcard. Names of the form file.1, file.2...file.10 will match this wildcard and the compression program sees that they get compressed. The output is dumped to avoid spurious messages.

     
     shellcommands:
     
       "$(gnu)/gzip /var/log/*.[0-9] /var/log/*.[0-9][0-9]  > /dev/null 2>&1"
     

Cfagent will also recognize rotated files if they have been compressed, with suffixes .Z, .gz, .rbz or .rbz.

4.12 Managing ACLs

Access control lists are extended file permissions. They allow you to open or close a file to a named list of users (without having to create a special group for those users). They also allow you to open or close a file for a named list of groups. Several Unix-like operating systems have had access control lists for some time; but they do not seem to have caught on.

There is a number of reasons for this dawdling in the past. The tools for setting ACLs are generally interactive and awkward to use. Because a named list of users would lead to excessive verbosity in an ls -l listing, one does not normally see them. There is therefore the danger that the hidden information would lead to undetected blunders in opening files to the wrong users. ACLs are also different on every vendor's filesystems and they don't work over intersystem NFS. In spite of these reservations, ACLs are a great idea. Here at Oslo College, it seems that users are continually asking how they can open a file just for the one or two persons they wish to collaborate with. They have grown used to Novell/PC networks which embraced the technology from Apollo/NCS much earlier. Previously the Unix answer to users has always been: go ask the system administrator to make a special group for you. Then do the ‘chmod’ thing. And then they would say: so what's so great about this Unix then?

Addressing this lack of standardization has been the job of a POSIX draft committee. Some vendors have made their implementations in the image of this draft. Solaris 2.6 has a good implementation. In spite of this, even these systems have only awkard tools for manipulating ACLs. Not the kind of thing you want to be around much, if you have better things to do. But the incompatibility argument applies only to multiple vendor headbutting. Some institutions who share data on a global basis opt for advanced solutions to network filesystems, such as AFS and DFS. Filesystems such as DCE's DFS make extensive use of file ACLs, and they are not operating system specific. Even so, DFS provides only interactive tools for examining and setting file permissions, and this is of little use to system administrators who would rather relegate that sort of thing to a script.

The need for this kind of thing is clear. Systems which make use of ACLs for security can be brought to their knees by changing a few ACLs. Take the Apollo/Domain OS as an example. All one needs to do to kill the system is to change a few ACLs and forget what they were supposed to be. Suddenly the system is crippled, nothing works. The only solution, if you don't have a backup, is to remove all of the security. Unix has a simpler security philosophy when it comes to the operating system files, but ACLs would be a valuable addition to the security of our data.

A cfagent bare-bones file-checking program looks like this:

     #
     # Free format cfagent program
     #
     
      control:
     
        ActionSequence - ( files )
     
      files:
     
        classes::
     
          /directory/file  mode=644
                           owner=mark,ds
                           group=users,adm
                           acl=zap
                           action=fixplain
     
       # ... more below
     

This program simply checks the permissions and ownership of the named file. The regular file mode, owner and group are specified straightforwardly. The new feature here is the acl directive. It is a deceptively simply looking animal, but it hides a wealth of complexity. The zap is, of course, not an access control list. Rather, cfagent uses a system of aliases to refer to ACLs, so that the clutter of the complex ACL definitions does not impair the clarity of a file command. An ACL alias is defined in a separate part of the program which looks like this:

      # ...contd
     
     
      acl:
     
        { zap
     
        method:append
        fstype:solaris
        user:rmz:rwx
        user:len:r
        }
     

As you can see, an ACL is a compound object—a bundle of information which specifies which users have which permissions. Because ACLs are lists the alias objects must also know whether the items are to be appended to an existing list or whether they are to replace an existing list. Also, since the permission bits, general options and programming interfaces are all different for each type of filesystem, we have to tell cfagent what the filesystem type is.

It is possible to associate several ACL aliases with a file. When cfagent checks a files with ACLs, it reads the existing ACL and compares it to the new one. Files are only modified if they do not conform to the specification in the cfengine program. Let's look at a complete example:

      files:
     
        $(HOME)/myfile acl=acl_alias1 action=fixall
     
      acl:
     
        { acl_alias1
     
        method:append
        fstype:solaris
        user:len:rwx
        }
     

ACLs are viewed in Solaris with the command ‘getfacl’. Suppose that, before running this program, our test-file had permissions

        user:*:rwx
        user:mark:rwx           #effective:r-x
        group:*:r-x              #effective:r-x
        mask:r-x
        other:r-x
        default_user:rw-
        default_group:r--
        default_mask:-w-
        default_other:rwx

After the cfagent run, the ACL would become:

        user:*:rwx
        user:mark:rwx           #effective:r-x
        user:len:rwx            #effective:r-x
        group:*:r-x              #effective:r-x
        mask:r-x
        other:r-x
        default_user:rw-
        default_group:r--
        default_mask:-w-
        default_other:rwx

Suppose we wanted to to remove 'w' bit for user ‘jacobs’, or make sure that it was never there.

     	{ acl_alias1
     
     	method:append
     	fstype:solaris
     	user:jacobs:-w
     	}

Note that the method used here is append. That means that, whatever other access permissions we might have granted on this file, the user ‘jacobs’ (a known cracker) will have no write permissions on the file. Had we used the method overwrite above, we would have eliminated all other access permissions for every user and added the above. If we really wanted to burn ‘jacobs’, we could remove all rights to the file like this

     
       user:jacobs:noaccess
     

The keyword noaccess removes all bits. Note that this is not necessarily the same as doing a -rwx, since some filesystems, like DFS, have more bits than this. Then, if we want to forgive and forget, the ACLs may be removed for jacobs with the syntax

       user:jacobs:default

In Solaris, files inherit default ACLs from the directory they lie in; these are modified by the umask setting to generate their own default mask. DFS ACLs look a little different. They are examined with the ‘acl_edit’ command or with

     dcecp -c acl show <filename>

In order to effect changes to the DFS, you have to perform a DCE login to obtain authentication cookies. The user ‘cell_admin’ is a special user account for administrating a local DFS cell. Suppose we have a file with the following DCE ACL:

       mask_obj:r-x---
       user_obj:rwxcid
       user:cell_admin:r--c-- #effective:r-----
       group_obj:r-x--d       #effective:r-x---
       other_obj:r-x---

Now we want to add ‘wx’ permissions for user ‘cell_admin’, and add new entries with ‘rx’ permissons for group acct-admin and user ‘root’. This is done with the following ACL alias:

     
        { acl_alias2
     
        method:append
        fstype:dfs
        user:/.../iu.hioslo.no/cell_admin:wx
        group:/.../iu.hioslo.no/acct-admin:rx
        user:/.../iu.hioslo.no/root:rx
        user:*:-x
        }
     

The local cell name /.../iu.hioslo.no is required here. Cfagent can not presently change ACLs in other cells remotely, but if your cfengine program covers all of the cell servers, then this is no limitation, since you can still centralize all your ACLs in one place. It is just that the execution and checking takes place at distributed locations. This is the beauty of cfengine. After running cfagent, with the above program snippet, the ACL then becomes:

       mask_obj:r-x---
       user_obj:rwcid
       user:cell_admin:rwxc-- #effective:r-x---
       user:root:r-x---       #effective:r-x---
       group_obj:r-x--d       #effective:r-x---
       group:acct-admin:r-x---
       other_bj:r-x---

For the sake of simplicity we have only used standard Unix bits ‘rwx’ here, but more complicated examples may be found in DFS. For example,

     
      user:mark:+rwx,-cid
     

which sets the read, write, execute flags, but removes the control, insert and delete flags. In the DFS, files inherit the inital object ACL of their parent directory, while new directories inherit the initial container object.

The objects referred to in DFS as user_obj, group_obj and so forth refer to the owner of a file. i.e. they are equivalent to the same commands acting on the user who owns the file concerned. To make the cfengine user-interface less cryptic and more in tune with the POSIX form, we have dropped the ‘_obj’ suffices. A user field of ‘*’ is a simple abbreviation for the owner of the file.

A problem with any system of lists is that one can generate a sequence which does one thing, and then undoes it and redoes something else, all in the same contradictory list. To avoid this kind of accidental interaction, cfengine insists that each user has only one ACE (access control entry), i.e. that all the permissions for a given user be in one entry.

5 Using cfengine as a front end for cron

One of cfengine's strengths is its use of classes to identify systems from a single file or set of files. Many administrators think that it would be nice if the cron daemon also worked in this way. One possible way of setting up cron from a global configuration would be to use the cfengine editfiles facility to edit each cron file separately. A much better way is to use cfengine's time classes to work like a user interface for cron. This allows you to have a single, central cfengine file which contains all the cron jobs on your system without losing any of the fine control which cron affords you. All of the usual advantages apply:

  • It is easier to keep track of what cron jobs are running on the system when you have everything in one place.
  • You can use all of your carefully crafted groups and user-defined classes to identify which host should run which programs.
The central idea behind this scheme is to set up a regular cron job on every system which executes cfagent at frequent intervals. Each time cfagent is started, it evaluates time classes and executes the shell commands defined in its configuration file. In this way we use cfagent as a wrapper for the cron scripts, so that we can use cfengine's classes to control jobs for mulitple hosts. Cfengine's time classes are at least as powerful as cron's time specification possibilities, so this does not restrict you in any way, See Building flexible time classes. The only price is the overhead of parsing the cfengine configuration file. To be more concrete, imagine installing the following crontab file onto every host on your network:

     #
     # Global Cron file
     #
     0,15,30,45 * * * * /usr/local/sbin/cfexecd -F
     

5.1 Structuring cfagent.conf

The structure of cfagent.conf needs to reflect your policy for running jobs on the system. You need to switch on relevant tasks and switch off unwanted tasks depending on the time of day. This can be done in three ways:

  • By placing individual actions under classes which restrict the times at which they are executed,
              
                action:
              
                      Hr00.Min10_15||Hr12.Min45_55::
              
                         Command
              
    
  • By choosing a different actionsequence depending on the time of day.
              
                control:
              
                      Hr00::   # Action-sequence for daily run at midnight
              
                         actionsequence = ( sequence )
              
                     !Hr00::   # Action-sequence otherwise
              
                          actionsequence = ( sequence )
              
    
  • By importing modules based on time classes.
              
                import:
              
                      Hr00:: cf.dailyjobs
              
                      any::  cf.hourlyjobs
              
    

The last of these is the most efficient of the three, since cfengine does not even have to spend time parsing the files for actions which you know you will not want.

5.2 Splaying host times

The trouble with starting every cfagent at the same time using a global cron file is that it might lead to contention or inefficiency. For instance, if a hundred cfagents all suddenly wanted to copy a file from a master source simultaneously this would lead to a big load on the server. We can prevent this from happening by introducing a time delay which is unique for each host and not longer than some given interval. Cfagent uses a hashing algorithm to generate a number between zero and a maximum value in minutes which you define, like this:

     
      # Put this in update.conf, so that the updates are also splayed
     
      control:
     
         SplayTime = ( 10 ) # minutes
     

If this number is non-zero, cfagent goes to sleep after parsing its configuration file and reading the clock. Every machine will go to sleep for a different length of time, which is no longer than the time you specify in minutes. A hashing algorithm, based on the fully qualified name of the host, is used to compute a unique time for hosts. The shorter the interval, the more clustered the hosts will be. The longer the interval, the lighter the load on your servers. This `splaying' of the run times will lighten the load on servers, even if they come from domains not under your control but have a similar cron policy. Splaying can be switched off temporarily with the ‘-q’ or ‘--no-splay’ options.

5.3 Building flexible time classes

Each time cfagent is run, it reads the system clock and defines the following classes based on the time and date:

Yrxx::
The current year, e.g. ‘Yr1997’, ‘Yr2001’. This class is probably not useful very often, but it might help you to turn on the new-year lights, or shine up your systems for the new millenium!
Month::
The current month can be used for defining very long term variations in the system configuration, e.g. ‘January’, ‘February’. These classes could be used to determine when students have their summer vacation, for instance, in order to perform extra tidying, or to specially maintain some administrative policy for the duration of a conference.
Day::
The day of the week may be used as a class, e.g. ‘Monday’, ‘Sunday’.
Dayxx::
A day in the month (date) may be used to single out by date, e.g. the first day of each month defines ‘Day1’, the 21st ‘Day21’ etc.
Hrxx::
An hour of the day, in 24-hour clock notation: ‘Hr00’...‘Hr23’.
Minxx::
The precise minute at which cfagent was started: ‘Min0’ ... ‘Min59’. This is probably not useful alone, but these values may be combined to define arbitrary intervals of time.
Minxx_xx::
The five-minute interval in the hour at which cfagent was executed, in the form ‘Min0_5’, ‘Min5_10’ .. ‘Min55_0’.

Time classes based on the precise minute at which cfagent started are unlikely to be useful, since it is improbable that you will want to ask cron to run cfagent every single minute of every day: there would be no time for anything to complete before it was started again. Moreover, many things could conspire to delay the precise time at which cfagent were started. The real purpose in being able to detect the precise start time is to define composite classes which refer to arbitrary intervals of time. To do this, we use the group or classes action to create an alias for a group of time values. Here are some creative examples:

     
     classes:  # synonym groups:
     
       LunchAndTeaBreaks = ( Hr12 Hr10 Hr15 )
     
       NightShift        = ( Hr22 Hr23 Hr00 Hr01 Hr02 Hr03 Hr04 Hr05 Hr06 )
     
       ConferenceDays    = ( Day26 Day27 Day29 Day30 )
     
       QuarterHours      = ( Min00 Min15 Min30 Min45 )
     
       TimeSlices        = ( Min01 Min02 Min03 Min33 Min34 Min35)
     

In these examples, the left hand sides of the assignments are effectively the ORed result of the right hand side. This if any classes in the parentheses are defined, the left hand side class will become defined. This provides a flexible and readable way of specifying intervals of time within a program, without having to use ‘|’ and ‘.’ operators everywhere.

5.4 Choosing a scheduling interval

How often should you call your global cron script? There are several things to think about:

  • How much fine control do you need? Running cron jobs once each hour is usually enough for most tasks, but you might need to exercise finer control for a few special tasks.
  • Are you going to run the entire cfengine configuration file or a special light-weight file?
  • System latency. How long will it take to load, parse and run the cfengine script?

Cfengine has an intelligent locking and timeout policy which should be sufficient to handle hanging shell commands from previous crons so that no overlap can take place, See Spamming and security.

6 Cfengine and network services

This chapter describes how you can set up a cfengine network service to handle remote file distribution and remote execution of cfengine without having to open your hosts to possible attack using the rsh protocols.

6.1 Cfengine network services

By starting the daemon called cfservd, you can set up a line of communication between hosts, allowing them to exchange files across the network or execute cfengine remotely on another system. Cfengine network services are built around the following components:

cfagent
The configuration engine, whose only contact with the network is via remote copy requests. This component does the hard work of configuring the system based on rules specified in the file cfagent.conf. It does not and cannot grant any access to a system from the network.
cfservd
A daemon which acts as both a file server and a remote-cfagent executor. This daemon authenticates requests from the network and processes them according to rules specified in cfservd.conf. It works as a file server and as a mechanism for starting cfagent on a local host and piping its output back to the network connection.
cfrun
This is a simple initiation program which can be used to run cfagent on a number of remote hosts. It cannot be used to tell cfagent what to do, it can only ask cfagent on the remote host to run the configuration file it already has. Anyone could be allowed to run this program, it does not require any special user privileges. A locking mechanism in cfengine prevents its abuse by spamming.
cfwatch
This program (which is not a part of the distribution: it is left for others to implement) should provide a graphical user interface for watching over the configuration of hosts running cfagent and logging their output.

With these components you can emulate programs like rdist whose job it is to check and maintain copies of files on client machines. You may also decide who has permission to run cfagent and how often it may be run, without giving away any special user privileges.

6.2 How it works

6.2.1 Remote file distribution

This section describes how you can set up cfservd as a remote file server which can result in the distribution of files to client hosts in a more democratic way than with programs like rdist.

An important difference between cfengine and other systems has to do with the way files are distributed. Cfengine uses a `pull' rather than a `push' model for distributing network files. The rdist command, for instance, works by forcing an image of the files on one server machine onto all clients. Files get changed when the server wishes it and the clients have no choice but to live with the consequences. Cfengine cannot force its will onto other hosts in this way, it can only signal them and ask them to collect files if they want to. In other words, cfengine simulates a `push' model by polling each client and running the local cfengine configuration script giving the host the chance to `pull' any updated files from the remote server, but leaving it up to the client machine to decide whether or not it wants to update.

Also, in contrast to programs like rdist which distribute files over many hosts, cfengine does not require any general root access to a system using the .rhosts file or the /etc/hosts.equiv file. It is sufficient to run the daemon as root. You can not run it by adding it to the /etc/inetd.conf file on your system however. The restricted functionality of the daemon protects your system from attempts to execute general commands as the root user using rsh.

To remotely access files on a server, you add the keyword server=host to a copy command. Consider the following example which illustrates how you might distribute a password file from a masterhost to some clients.

     
     copy:
     
       PasswdClients::
     
         /etc/passwd  dest=/etc/passwd owner=root group=0 server=server-host
     

Given that the cfservd daemon is running on server-host, cfagent will make contact with the daemon and attempt to obtain information about the file. During this process, cfengine verifies that the system clocks of the two hosts are reasonably synchronized. If they are not, it will not permit remote copying. If cfagent determines that a file needs to be updated from a remote server it begins copying the remote file to a new file on the same filesystem as the destination-file. This file has the suffix .cfnew. Only when the file has been successfully collected will cfagent make a copy of the old file, (see repository in the Reference manual), and rename the new file into place. This behaviour is designed to avoid race-conditions which can occur during network connections and indeed any operations which take some time. If files were simply copied directly to their new destinations it is conceivable that a network error could interrupt the transfer leaving a corrupted file in place.

Cfagent places a timeout of a few seconds on network connections to avoid hanging processes.

Normally the daemon sleeps, waiting for connections from the network. Such a connection may be initiated by a request for remote files from a running cfengine program on another host, or it might be initiated by the program cfrun which simply asks the host running the daemon to run the cfengine program locally.

6.2.2 Remote execution of cfagent

It is a good idea to execute cfagent by getting cron to run it regularly. This ensures that cfagent will be run even if you are unable to log onto a host to run it yourself. Sometimes however you will want to run cfagent immediately in order to implement a change in configuration as quickly as possible. It would then be inconvenient to have to log onto every host in order to do this manually. A better way would be to issue a simple command which contacted a remote host and ran cfagent, printing the output on your own screen:

     
     myhost% cfrun remote-host -v
     
      output....
     

A simple user interface is provided to accomplish this. cfrun makes a connection to a remote cfservd-daemon and executes cfagent on that system with the privileges of the cfservd-daemon (usually root). This has a two advantages:

  • You avoid having to log in on a remote host in order to reconfigure it.
  • Users other than root can run cfagent to fix any problems with the system.

A potential disadvantage with such a system is that malicious users might be able to run cfagent on remote hosts. The fact that non-root users can execute cfagent is not a problem in itself, after all the most malicious thing they would be able to do would be to check the system configuration and repair any problems. No one can tell cfagent what to do using the cfrun program, it is only possible to run an existing configuration. But a more serious concern is that malicious users might try to run cfagent repeatedly (so-called `spamming') so that a system became burdened with running cfagent constantly, See Spamming and security.

6.2.3 Spamming and security

The term `spamming' refers to the senseless repetition of something in a malicious way intended to drive someone crazy5. In the computer world some malicious users, a bit like `flashers' in the park6 like to run around the net a reveal themselves ad nauseum by sending multiple mail messages or making network connections repeatedly to try to overload systems and people7.

Whenever we open a system to the network, this problem becomes a concern. Cfengine is a tool for making peace with networked systems, not a tool to be manipulated into acts of senseless aggression. The cfservd daemon does make it possible for anyone to connect and run a cfengine process however, so clearly some protection is required from such attacks.

Cfengine's solution to this problem is a locking mechanism. Rather than providing user-based control, cfengine uses a time based locking mechanism which prevents actions from being executed unless a certain minimum time has elapsed since the last time they were executed. By using a lock which is not based on user identity, we protect several interests in one go:

  • Restricting cfengine access to root would prevent regular users, in trouble, from being able to fix problems when the system administrator was unavailable. A time-based lock does not prevent this kind of freedom.
  • Accidents with cron or shell scripts could start cfagent more often than desirable. We also need to protect against such accidents.
  • We can prevent malicious attacks regardless of whom they may come from.

Cfengine is controlled by a series of locks which prevent it from being run too often, and which prevent it from spending too long trying to do its job. The locks work in such a way that you can start several cfengine processes simultaneously without them crashing into each other. Coexisting cfengine processes are also prevented from trying to do the same thing at the same time (we call this `spamming'). You can control two things about each kind of action in the action sequence:

  • The minimum time which should have passed since the last time that action was executed. It will not be executed again until this amount of time has elapsed. (Default time is 1 minute.)
  • The maximum amount of time cfagent should wait for an old instantiation of cfagent to finish before killing it and starting again. (Default time is 120 minutes.)

You can set these values either globally (for all actions) or for each action separately. If you set global and local values, the local values override the global ones. All times are written in units of minutes.

     
        actionsequence
          (
          action.IfElapsedtime-in-mins
          action.ExpireAftertime-in-mins
          )
     

or globally,

     
       control:
     
          IfElapsed   = ( time-in-mins )
     
          ExpireAfter = ( time-in-mins )
     

For example:

     
      control:
     
        actionsequence =
          (
          files.IfElapsed240.ExpireAfter180
          copy
          tidy
          )
     
        IfElapsed = ( 30 )
     

In this example, we treat the files action differently to the others. For all the other actions, cfagent will only execute the files part of the program if 30 minutes have elapsed since it was last run. Since no value is set, the expiry time for actions is 60 minutes, which means that any cfagent process which is still trying to finish up after 60 minutes will be killed automatically by the next cfagent which gets started.

As for the files action: this will only be run if 240 minutes (4 hours) have elapsed since the last run. Similarly, it will not be killed while processing `files' until after 180 minutes (3 hours) have passed.

These locks do not prevent the whole of cfagent from running, only so-called `atoms'. Several different atoms can be run concurrently by different cfagents. Assuming that the time conditions set above allow you to start cfengine, the locks ensure that atoms will never be started by two cfagents at the same time, causing contention and wasting CPU cycles. Atoms are defined to maximize the security of your system and to be efficient. If cfengine were to lock each file it looked at seperately, it would use a large amount of time processing the locks, so it doesn't do that. Instead, it groups things together like this:

copy, editfiles, shellcommands
Each separate command has its own lock. This means that several such actions can be processed concurrently by several cfagent processes. Multiple or recursive copies and edits are treated as a single object.
netconfig, resolve, umount, mailcheck, addmounts, disable, processes
All commands of this action-type are locked simultaneously, since they can lead to contention.
mountall, mountinfo, required, checktimezone
These are not locked at all.

Cfagent creates a directory ~/.cfengine for writing lock files for ordinary users.

The option ‘-K’ or ‘--no-lock’ can be used to switch off the locking checks, but note that when running cfagent remotely via cfservd, this is not possible.

6.2.4 Some points on the cfservd protocol

Cfservd uses a form for host-based authorization. Each atomic operation, such as statting, getting files, reading directories etc, requires a new connection and each connection is verified by a double reverse lookup in the server's DNS records. Single stat structures are cached during the processing of a file.

MD5 checksums are transferred from client to server to avoid loading the server. Even if a user could corrupt the MD5 checksum, he or she would have to get past IP address access control and the worst that could happen would be to get the right version of the file. Again this is in keeping with the idea that users can only harm themselves and not others with cfengine.


Previous: cfservd protocol, Up: How it works

6.2.5 Deadlocks and runaway loops

Whenever we allow concurrent processes to share a resource, we open ourselves up the possibilty of deadlock. This is a situation where two or more processes are locked in a vicious stalemate from which none can escape. Another problem is that it might be possible to start an infinite loop: cfagent starts itself. Cfagent protects you from such loops to a large degree. It should not be possible to make such a loop by accident. The reason for this is the locking mechanism which prevents tasks being repeated too often. If you start a cfagent process which contains a shell-command to start cfagent again, this shell command will be locked, so it will not be possible to run it a second time. So while you might be able to start a second cfagent process, further processes will not be started and you will simply have wasted a little CPU time. When the first cfagent returns, the tasks which the second cfagent completed will not be repeated unless you have set the IfElapsed time or the ExpireAfter time to zero. In general, if you wish to avoid problems like this, you should not disable the locking mechanism by setting these two times to zero.

The possibility of deadlock arises in network connection. Cfengine will not attempt to use the network to copy a file which can be copied internally from some machine to itself. It will always replace the server= directive in a copy with `localhost' to avoid unnecessary network connections. This prevents one kind of deadlock which could occur: namely cfrun executes cfagent on host A (cfservd on host A is then blocked until this completes), but the host A configuration file contains a remote copy from itself to itself. This remote copy would then have to wait for cfservd to unblock, but this would be impossible since cfservd cannot unblock until it has the file. By avoiding remote copies to localhost, this possibility is avoided.

6.3 Configuring cfservd

6.3.1 Installation of cfservd

To install the cfservd daemon component, you will need to register a port for cfengine by adding the following line to the system file /etc/services file

     
        cfengine        5308/tcp
     

You could do this for all hosts by adding the following to your cfengine configuration

     
     editfiles:
     
       { /etc/services
     
        AppendIfNoSuchLine "cfengine        5308/tcp"
       }
     

To start cfservd at boot time, you need to place a line of the following type in your system startup files:

     
     # Start cfengine server
     cfservd
     

Note that cfservd will re-read its configuration file whenever it detects that it has been changed, so you should not have to restart the daemon, not send it the HUP signal as with other daemons.

6.3.2 Configuration file cfservd.conf

The server daemon is controlled by a file called cfservd.conf. The syntax of this configuration file is deliberately modelled on cfengine's own configuration file, but despite the similarities, you cannot mix the contents of the two files.

Though they are not compatible, cfagent.conf and cfservd.conf are similar in several ways:

  • Both files use classes to label entries, so that you may use the same configuration file to control all hosts on your network. This is a convenience which saves you the trouble of maintaining many different files.
  • Both files are searched for using the contents of the variable CFINPUTS.
  • You can use groups and import in both files to break up files into convenient modules and to import common resources, such as lists of groups.

Note that the classes in the cfservd.conf file do not tell you the classes of host which have access to files and directories, but rather which classes of host pay attention to the access and deny commands when the file is parsed.

Host name authentication is not by class or group but by hostname, like the /etc/exports file on most Unix systems. The syntax for the file is as follows:

     
      control:
     
        classes::
     
            domain = ( DNS-domain-name )
     
            cfrunCommand = ( "script/filename" )  # Quoted
     
            MaxConnections = ( maximum number of forked daemons )
     
            IfElapsed = ( time-in-minutes )
     
            DenyBadClocks = ( false )
     
            AllowConnectionsFrom = ( IP numbers )
     
            DenyConnectionsFrom = ( IP numbers )
     
            AllMultipleConnectionsFrom = ( IP numbers )
     
            LogAllConnections = ( false/true )
     
            SkipVerify = ( IP numbers )
     
      groups:
     
        Group definitions
     
      import:
     
        Files to import
     
      admit: | grant:
     
        classes::
     
           /file-or-directory
     
             wildcards/hostnames
     
      deny:
     
        classes::
     
           /file-or-directory
     
             wildcards/hostnames root=hostlist encrypt=true/on
     

See the reference manual for descriptions of these elements. The file consists of a control section and access information. You may use the control section to define any variables which you want to use, for convenience, in the remainder of your file.

Following the control section, comes a list of files or directories and hosts which may access these. If permissions are granted to a directory then all subdirectories are automatically granted also. Note that plain-file symbolic links are not checked for, so you may need to specifically deny access to links if they are plain files, but cfservd does not follow directory symbolic links and give access to files in directories pointed to by these.

Fully qualified hostnames should be used in this file. If host names are unqualified, the current domain is appended to them (do not forget to define the domain name). Authentication calls the Unix function gethostbyname() and so on to identify and verify connecting hosts, so the names in the file must reflect the type on names returned by this function. You may use wildcards in names to match, for instance, all hosts from a particular domain.

Here is an example file

     #####################################################
     #
     # This is a cfservd config file
     #
     #####################################################
     
     groups:
     
       PasswdHost = ( nexus )
     
     #####################################################
     
     control:
     
       #
       # Assuming CFINPUTS is defined
       #
     
       cfrunCommand = ( "/var/cfengine/bin/cfagent" )
     
       variable = ( /usr/local/publicfiles )
     
     #####################################################
     
     admit:   # Can also call this grant:
     
     
         # Note that we must grant access to the
         # agent if we wan to start it remotely with cfrun
     
           /var/cfengine/bin/cfagent
     
        PasswdHost::
     
          /etc/passwd
     
             *.iu.hioslo.no
     
         FtpHost::
     
         # An alternative to ftp, grant anyone
     
            /local/ftp/pub
     
              *
     
         # These file paths must not contain symbolic
         # links. Access control does not follow symlinks.
     
         any::
     
            $CFINPUTS/cfrun.sh
     
              *.iu.hioslo.no
     
     #####################################################
     
     deny:
     
        /etc/services
     
            borg.iu.hioslo.no
     
       /local/ftp
     
            *.pain-in-the-ass.com
     
     

NOTE I: cfservd is not rpc.mountd, access control is by filename, not by device name. Do not assume that files lying in subdirectories are not open for access simply because they lie on a different device. You should give the real path name to file and avoid symbolic links.

NOTE II: access control is per host and per user. User names are assumed to be common to both hosts. There is an implicit trust relationship here. There is no way to verify whether the user on the remote host is the same user as the user with the same name on the local host.

NOTE III: Cfservd requires you to grant access to files without following any symbolic links. You must grant access to the real file or directory in order to access the file object. This is a security feature in case parties with login access to the server could grant access to additional files by having the permission to create symbolic links in a transitory directory, e.g. /tmp.


Next: , Previous: Cfengine network services, Up: Top

7 Security and cfengine

Computer security is about protecting the data and availability of an association of hosts. Briefly, the key words are authentication, privacy, integrity and trust. To understand computer security we have to understand the interrelationships between all of the hosts and services on our networks as well as the ways in which those hosts can be accessed. Tools which allow this kind of management are complex and usually expensive.

7.1 What is security?

For a computer to be secure it must be *physically secure* — if we can get our hands on a host then we are never more than a screwdriver away from all of its assets—but assuming that hosts are physically secure, we then wish to deal with the issues of software security which is a much more difficult topic. Software security is about access control and software reliability. No single tool can make computer systems secure. Major blunders have been made out of the belief that a single product (e.g. a `firewall') would solve the security problem. For instance, a few years ago a cracker deleted all the user directories from a dialup login server belonging to a major Norwegian telecommunications company, from the comfort of his web browser. This was possible, even through a firewall, because the web server on the host concerned was incorrectly configured. The bottom line is that there is no such thing as a secure operating system, firewall or none. What is required is a persistent mixture of vigilence and adaptability.

For many, security is perceived as being synonymous with network privacy or network intrusion. Privacy is one aspect of security, but it is not the network which is our special enemy. Many breaches of security happen from within. There is little difference between the dangers of remote access from the network or direct access from a console: privacy is about access control, no matter where the potential intruder might be. If we focus exclusively on network connectivity we ignore a possible threat from internal employees (e.g. the janitor who is a computer expert and has an axe to grind, or the mischievous son of the director who was left waiting to play mom's office, or perhaps the unthinkable: a disgruntled employee who feels as though his/her talents go unappreciated). Software security is a vast subject, because modern computer systems are complex. It is only exacerbated by the connectivity of the internet which allows millions of people to have a go at breaking into networked systems. What this points to is the fact that a secure environment requires a tight control of access control on every host individually, not merely at specific points such as firewalls.

This article is not a comprehensive guide to security. Rather it is an attempt to illustrate how cfengine can be used to help you automate a level of host integrity on all the hosts of your network. Cfengine is a network configuration tool with two facets. It is a language used to build an `expert system'. An expert system describes the way you would like your hosts and network to look and behave. CFengine is also a software robot which compares the model you have described with what the world really looks like and then sets to work correcting any deviations from that picture. In many ways it is like an immune system, neutralizing and repairing damaged parts. Unlike many shell-script packages for sysadmin, cfengine is a C program which means light on system resources. Also it works on a principle of `convergence'. Convergence means that each time you run cfengine the system should get closer to the model which you have described until eventually when the system is the model, cfengine becomes quiescent, just like an immune system. In the words of one user your hosts `never get worse'. This assumes of course that the model you have is what you really want. Using cfengine, model building becomes synonymous with formulating and formalizing a system policy.

What makes cfengine a security tool is that security policy is a part of system policy: you cannot have one without the other. You will never have security unless you are in control of your network. Cfengine monitors and indeed repairs hosts with simple easily controllable actions. From an automation perspective, security is no different from the general day to day business of system maintenance, you just need to pay more attention to the details. We cannot speak of `have security' and `have not security'. There is always security, it is simply a matter of degree: weak or strong; effective or ineffective.

7.2 A word of warning

Before starting it is only proper to state the obvious. You should never trust anyone's advice about configuration or security without running it past your own grey matter first. The examples provided here are just that: examples. They might apply to you as written and they might need to be modified. You should never accept and use an example without thinking carefully and critically first! Also, in any book of recipies or guide to successful living you know that there are simplified answers to complex questions and you should treat them as such. There is no substitute for real understanding.


Next: , Previous: A word of warning, Up: Security and cfengine

7.3 Automation

Even in the smallest local area network you will want to build a scheme for automating host configuration and maintenance, because networks have a way of growing from one host into many quite quickly. It is therefore important to build a model which scales. A major reason for using cfengine is precisely for scalability. Whether you have one host or a hundred makes little difference. Cfengine is instructed from a central location, but its operation is completely and evenly spread across the network. Each host is responsible for obtaining a copy of the network model from a trusted source and is then responsible for configuring itself without intervention from outside. Unlike some models, cfengine does not have to rely on network communication or remote object models.

We also need integration, or the ability to manage the interrelationships between hosts. It is no good having complete control of one important host and thinking that you are secure. If an intruder can get into any host, he or she is almost certain to get into the ones that matter, especially if you are not looking at all of them. Using cfengine is a good way of forcing yourself to formulate a configuration/security policy and then stick to it. Why cfengine? There are three reasons: i) it forces a discipline of preparation which focuses you on the problems at the right level of detail, ii) it provides you with `secure' scalable automation and a common interface to all your hosts, and iii) it scales to any number of hosts without additional burdens. We'll need to qualify some of these points below.

The first step in security management is to figure out a security policy. That way, you know what *you* mean by security and if that security is breached, you will know what to do. In many cases you can formulate a large part of your security policy as cfengine code. That makes it formal, accurate and it means that it will get done by the robot without requiring any more work on your part.

As an immune system, cfengine will even work fine in a partially connected environment it makes each host responsible for its own state. It is not reliant on network connectivty for remote method invocations or CORBA-style object requests as is, say, Tivoli. All it needs is an authentic copy of the network configuration document stored locally on each host. If this is the case, a detached host will not be left unprotected, at worst it might lag behind in its version of the network configuration.

7.4 Trust

There are many implicit trust relationships in computer systems. It is crucial to understand them. If you do not understand where you are placing your trust, your trust can be exploited by attackers who have thought more carefully than you have.

For example, any NFS server of users' home-directories trusts the root user on the hosts which mount those directories. Some bad accidents are prevented by mapping root to the user nobody on remote systems, but this is not security, only convenience. The root user can always use `su' to becomes any user in its password file and access/change any data within those filesystems. The .rlogin and hosts.equiv files on Unix machines grant root (or other user) privileges to other hosts without the need for authentication.

If you are collecting software from remote servers, you should make sure that they come from a machine that you trust, particularly if they are files which could lead to privileged access to your system. Even checksums are no good unless they also are trustworthy. For example, it would be an extremely foolish idea to copy a binary program such as /bin/ps from a host you know nothing about. This program runs with root privileges. If someone were to replace that version of ps with a Trojan horse command, you would have effectively opened your system to attack. Most users trust anonymous FTP servers where they collect free software. In any remote copy you are setting up an implicit trust relationship. First of all you trust integrity of the host you are collecting files from. Secondly you trust that they have the same username database with regard to access control. The root user on the collecting host has the same rights to read files as the root user on the server. The same applies to any matched user name.


Next: , Previous: Trust, Up: Security and cfengine

7.5 Why trust cfengine?

Cfengine has a very simple trust model. It trusts the integrity of its input file and any data which is explicitly chooses to download. Cfengine places the responsibility on root on the localhost not on any outsiders. *You* can make cfengine destroy your system, just as you can destroy it yourself, but no one else can, so as long as you are careful with the input file you are trusting essentially no-one. We shall qualify this below for remote file copying.

Cfengine assumes that its input file is secure. Apart from that input file, no part of cfengine accepts or uses any configuration information from outside sources. The most one could do from an authenticated network connection is to ask cfengine to carry out (or not) certain parts of its model, thus in the worst case scanario an outside attacker could spoof cfengine into configuring the host correctly. In short, no one except root on the localhost can force cfengine to do anything (unless root access to your system has already been compromised by another route). This means that there is a single point of failure. The input file does not even have to be private as long as it is authentic. No one except you can tell cfengine what to do.

There is a catch though. Cfengine can be used to perform remote file transfer. In remote file transfer one is also forced to trust the integrity of the data received, just as in any remote copy scheme. Although cfengine works hard to authenticate the identity of the host, once the host's identity is verified it cannot verify the accuracy of unknown data it has been asked to receive. Also, as with all remote file transfers, cfengine could be tricked by a DNS spoofing into connecting to an imposter host, so use the IP addresses of hosts, not their names if you don't trust your DNS service. In short, these faults are implicit in remote copying. They do not have to do with cfengine itself. This has nothing to do with encryption as users sometimes believe: encrypted connections do not change these trust relationships—they improve the privacy of the data being transmitted not their accuracy or trustworthiness.

The point of cfengine is normally to have only one global configuration for every host. This needs to be distributed somehow which means that hosts must collect this file from a remote server. This in turn means that you must trust the host which has the master copy of the cfengine configuration file.

7.6 Configuration

The beginning of security is correct host configuration. Even if you have a firewall shielding you from outside intrusion, an incorrectly configured host is a security risk. Host configuration is what cfengine is about, so we could easily write a book on this. Rather than reiterating the extensive documentation, let's just consider a few examples which address actual problems and get down to business without further ado.

A cfengine configuration file is composed of objects with the following syntax (see the cfengine documentation):

       rule-type:
     
         classes-of-host-this-applies-to::
     
               Actual rule 1
               Actual rule 2 ...
     

The rule-types include checking file permissions, editing textfiles, disabling (renaming and removing permissions to) files, controlled execution of scripts and a variety of other things relating to host configuration. Some of the `control' rules are simply flags which switch on complex (read `smart') behaviour. Every cfengine program needs an actionsequence which tells it the order in which bulk configuration operations should be evaluated. e.g.

     
     control:
     
       actionsequence = ( netconfig copy processes editfiles )
     

You should look at the cfengine manual to get started with your configuration.

Let us step through some basic idioms which can repeated in different contexts.

As representative examples we shall take Solaris and GNU/Linux as example operating systems. This is not to single them out as being particularly secure or insecure, it is merely due to their widespread use and for definiteness.

7.7 Disabling and replacing software

One of the simplest things which we are asked to do constantly is to disable dangerous programs as bugs are discovered. CERT security warnings frequently warn about programs with flaws which can compromise a system. In cfengine, disabling a file means renaming it to *.cfdisabled and setting its permission to 600.

      disable:
     
        #
        # CERT security patches
        #
     
        solaris::
     
          /usr/openwin/bin/kcms_calibrate
          /usr/openwin/bin/kcms_configure
          /usr/bin/admintool
          /etc/rc2.d/S99dtlogin
          /usr/lib/expreserve
     
        linux::
     
           /sbin/dip-3.3.7n
           /etc/sudoers
           /usr/bin/sudoers
     

Although this is a trivial matter, the fact that it is automated means that cfengine is checking for this all the time. As long as a host is up and running (connected to the network or not) cfengine will be ensuring the named file is not present.

Another issue is to replace standard vendor programs with drop-in replacements. For example, most admins would like to replace their vendor sendmail with the latest update from Eric Allman's site. One way to do this is to compile the new sendmail into a special directory, separate from vendor files and then to symbolically link the new program into place.

     
      links:
     
        solaris||linux::
     
         /usr/lib/sendmail      ->!  /usr/local/lib/mail/bin/sendmail-8.9.3
         /usr/sbin/sendmail     ->!  /usr/local/lib/mail/bin/sendmail-8.9.3
         /etc/mail/sendmail.cf  ->!  /usr/local/lib/mail/etc/sendmail.cf
     

The exclamation marks mean (by analogy with the csh) that existing file objects should be replaced by links to the named files. Again the integrity of these links is tested every time cfengine runs. If the object /usr/lib/sendmail is not a link to the named file, the old file is moved and a link is made. If the link is okay, nothing happens. After putting the new sendmail in place, you will need to make sure that the restricted shell configuration is in order.

        #
        # Sendmail, restricted shell needs these links
        #
     
        solaris::
     
          # Most of these will only be run on the MailHost
          # but flist (procmail) is run during sending...
     
          /usr/adm/sm.bin/vacation -> /usr/ucb/vacation
          /usr/adm/sm.bin/flist   ->  /home/listmgr/.bin/flist
     
        linux::
     
          /usr/adm/sm.bin/vacation -> /usr/bin/vacation
     

Link management is a particularly useful feature of cfengine. By putting links (actually all system modifications) into the cfengine configuration and never doing anything by hand, you build up a system which is robust to reinstallation. If you lose your host, you just have to run cfengine once or twice to reconstruct it.

Of course, the fundamental tenet of security is to be able to restrict privilege to resources. We therefore need to check the permissions on files. For instance, a recent CERT advisory warned of problems with some free unix mount commands which were setuid root. If we suppose there is a group of hosts called `securehosts' which we don't need to worry about, then we could remove the setuid bits on all other hosts as follows:

     
      files:
     
        !securehosts.linux::
     
           /bin/mount     mode=555 owner=root action=fixall
           /bin/umount    mode=555 owner=root action=fixall
     
        securehosts.linux::
     
           /bin/mount      m=6555 o=root action=fixall
           /bin/umount     m=6555 o=root action=fixall
     

One area where cfengine excels over other tools is in its ascii file editing abilities. Editing textfiles in a non-destructive way is such an important operation that having used it you will wonder how you every managed without it! Here are some simple but real examples of how file editing can be used.

     
      editfiles:
     
        # sun4, who are they kidding?
     
        { /etc/hosts.equiv
     
        HashCommentLinesContaining "+"
        }
     
        #
        # CERT security patch for vold vulnerability
        #
     
        sunos_5_4::
     
           { /etc/rmmount.conf
     
           HashCommentLinesContaining "action cdrom"
           HashCommentLinesContaining "action floppy"
           }
     

TCP wrapper configuration can be managed easily by maintaining a pair of master files on a trusted host. Files of the form

     
      # /etc/hosts.allow (exceptions)
      #
      # Public services
     
      sendmail: ALL
      in.ftpd:  ALL
      sshd:     ALL
     
      # Private services
     
      in.fingerd:  .example.org LOCAL
      in.cfingerd: .example.org LOCAL
      sshdfwd-X11: .example.org LOCAL
     
      # Portmapper has to use IP series
     
      portmap: 128.39.89. 128.39.74. 128.39.75.

and

     
      # /etc/hosts.deny (default)
     
      ALL: ALL
     

may be distributed to each host by cfengine

     copy:
     
      /masterfiles/hosts.deny dest=/etc/hosts.deny
                              mode=644
                              server=trusted
      /masterfiles/hosts.allow dest=/etc/hosts.allow
                               mode=644
                               server=trusted

and installed as follows

      editfiles:
     
           { /etc/inet/inetd.conf
     
           # Make sure we're using tcp wrappers
     
           ReplaceAll "/usr/sbin/in.ftpd"    With "/local/sbin/tcpd"
           ReplaceAll "/usr/sbin/in.telnetd" With "/local/sbin/tcpd"
           ReplaceAll "/usr/sbin/in.rshd"    With "/local/sbin/tcpd"
           ReplaceAll "/usr/sbin/in.rlogind" With "/local/sbin/tcpd"
     
      processes:
     
           "inetd" signal=hup
     

The services which we do not need should be removed altogether. There's no sense in tempting fate:

     
     editfiles:
     
           { /etc/inetd.conf
     
           # Eliminate unwanted services
     
           HashCommentLinesContaining "rwall"
           HashCommentLinesContaining "/usr/sbin/in.fingerd"
           HashCommentLinesContaining "comsat"
           HashCommentLinesContaining "exec"
           HashCommentLinesContaining "talk"
           HashCommentLinesContaining "echo"
           HashCommentLinesContaining "discard"
           HashCommentLinesContaining "charge"
           HashCommentLinesContaining "quotas"
           HashCommentLinesContaining "users"
           HashCommentLinesContaining "spray"
           HashCommentLinesContaining "sadmin"
           HashCommentLinesContaining "rstat"
           HashCommentLinesContaining "kcms"
           HashCommentLinesContaining "comsat"
           HashCommentLinesContaining "xaudio"
           HashCommentLinesContaining "uucp"
           }
     

7.8 Process monitoring

When it comes to process management we are usually interested in three things: i) making sure certain processes are running, ii) making sure some processes are NOT running and iii) sending HUP signals to force configuration updates. To HUP a daemon and make sure that it is running, we write

     processes:
     
      linux::
     
       "inetd"  signal=hup restart "/usr/sbin/inetd"   useshell=false
       "xntp"              restart "/local/sbin/xntpd" useshell=false
     

The useshell option tells cfengine that it should not use a shell to start the program. The idea here is to protect against IFS attacks. Unfortunately some programs require a shell in order to be started, but most do not. This is an extra precaution. When the cron daemon crashes, restarting it can be a problem since it does not close its filed descriptors properly when forking. The dumb-option helps here:

     
       "cron" matches=>1 restart "/etc/init.d/cron start"  useshell=dumb
     

To kill processes which should not be running, we write:

     
      processes:
     
        solaris::
     
        #
        # Don't want CDE stuff or SNMP peepholes...
        #
     
         "ttdbserverd" signal=kill
         "snmpd"       signal=kill
         "mibiisa"     signal=kill
     

A couple of years ago, a broken cracked account was revealed at Oslo College by the following test in the cfengine configuration:

     processes:
     
        # Ping attack ?
     
        "ping"  signal=kill inform=true
     

There are few legimate reasons to run the ping command more than a few times. The chances of cfengine detecting single pings is quite small. But coordinated ping attacks are another story. When it was revealed that a user had twenty ping processes attempting to send large ping packets to hosts in the United States it was obvious the the account had been compromised. Fortunately for the recipient, the ping command was incorrectly phrased and would probably not have been noticed.

     processes:
     
          "sshd"
                       restart "/local/sbin/sshd"
                       useshell=false
     
          "snmp"       signal=kill
          "mibiisa"    signal=kill
     
          "named"      matches=>1
                       restart "/local/bind/bin/named"
                       useshell=false
     
          # Do the network community a service and run this
     
          "identd"   restart "/local/sbin/identd" inform=true
     

Process management also includes the garbage collection which we shall return to briefly.

7.9 Monitoring files

Almost all security programs available are for the monitoring of file integrity. Cfengine also incorporates tools for monitoring files. Here are some of the elements in the faily complex files command:

     
      files:
     
          classes::
     
             /file-object
                               mode=mode
                               owner=uid-list
                               group=gid-list
                               action=fixall/warnall..
                               ignore=pattern
                               include=pattern
                               exclude=pattern
                               checksum=md5
                               syslog=true/on/false/off
     

In additions to these, there are extra flags for BSD filesystems and ways of managing file ACLs for systems like NT. Here are some examples of basic checks on file permissions:

     
      classes:
     
       # Define a class of hosts based on a test...
     
       have_shadow = ( `/bin/test -f /etc/shadow` )
     
       NFSservers = ( server1 server2 )
     
      files:
     
        any::
     
           /etc/passwd mode=0644 o=root  g=other  action=fixplain
     
        have_shadow::
     
           /etc/shadow mode=0400 o=root  g=other  action=fixplain
     
        # Takes a while so do this at midnight and only on servers
     
        NFSservers.Hr00::
     
           /usr/local
                 mode=-0002   Check no files are writable!
                 recurse=inf
                 owner=root,bin
                 group=0,1,2,3,4,5,6,7,staff
                 action=fixall
     

In the last example we parse through a whole file system (recurse=inf) and as a result we get a number of checks for free. Any previously unknown setuid programs are reported as well as any suspicious filenames (see below).

7.10 The setuid log

Cfengine is always on the lookout for files which are setuid or setgid root. It doesn't go actively looking for them uninvited, but whenever you get cfagent to check a file or directory with the files feature, it will make a note of setuid programs it finds there. These are recorded in the file cfengine.host.log which is stored under /var/cfengine or /var/log/cfengine. When new setuid programs are discovered, a warning is printed, but only if you are root. If you ever want a complete list, delete the log file and cfengine will think that all of the setuid programs it finds are new. The log file is not readable by normal users.

7.11 Suspicious filenames

Whenever cfagent opens a directory and scans through files and directories (recursively) (files, tidy, copy), it is also on the lookout for for suspicious filenames, i.e. files like ".. ." containing only space and/or dots. Such files are seldom created by sensible sources, but are often used by crackers to try to hide dangerous programs. Cfagent warns about such files. Although not necessarily a security issue, cfagent will also warn about filenames which contain non-printable characters if desired, and directories which are made to look like plain files by giving them filename extensions.

     
     control:
     
        #
        # Security checks
        #
     
        NonAlphaNumFiles = ( on )
        FileExtensions = ( o a c gif jpg html ) # etc
        SuspiciousNames = ( .mo lrk3 lkr3 )
     

The file extension list may be used to detect concealed directories during these searches, if users create directories which look like common files this will be warned about. Additional suspicious filenames can be checked for automatically as a matter if course. This is commented further below.

The mail spool directory is a common place for users to try to hide dowloaded files. These options inform about files which do not have the name of a user or are not owned by a valid user:

     
      control:
     
        WarnNonOwnerMail = ( true )
        WarnNonUserMail = ( true )  # Warn about mail which is not owned by a user
     

Corresponding commands exist to delete these files without further ado. This can be a useful way of cleaning up after users whose accounts have been removed.

7.12 Checksums and Tripwire functionality

Cfagent can be used to check for changes in files which only something as exacting as an MD5 checksum/digest can detect. If you specify a checksum database and activate checksum verification,

     
     control:
     
       ChecksumUpdates = ( false )
     
     files:
     
         /filename checksum=md5 ....
         /dirname  checksum=md5 recurse=inf....
     
         # If the database isn't secure, nothing is secure...
     
         /var/cfengine/cache.db  mode=600 owner=root action=fixall
     

then cfagent will build a database of file checksums and warn you when files' checksums change. This makes cfagent act like Tripwire (currently only with MD5 checksums). It can be used to show up Trojan horse versions of programs. It should be used sparingly though since database management and MD5 checksum computation are resource intensive operations and this could add significant time to a cfagent run. The ChecksumUpdates variable (normally false) can be set to true to update the checksum database when programs change for valid reasons.

Warnings are all every fine and well, but the spirit of cfengine is not to bother us with warnings, it is to fix things automatically. Warning is a useful supplement, but in security breaches it is better to fix the problem, rather than leaving the host in a dangerous state. If you are worried about the integrity of the system then don't just warn about checksum mismatches here, make an md5 copy comparison against a read-only medium which has correct, trusted version of the file on it. That way if a binary is compromised you will not only warn about it but also repair the damage immediately!

The control variable ChecksumUpdates may be switched to on in order to force cfagent to update its checksum database after warning of a change.

7.13 FileExtensions

This list may be used to define a number of extensions which are regarded as being plain files by the system. As part of the general security checking cfagent will warn about any directories which have names using these extensions. They may be used to conceal directories.

     
       FileExtensions = ( c o gif jpg html )
     

7.14 NonAlphaNumFiles

If enabled, this option causes cfagent to detect and disable files which have purely non-alphanumeric filenames, i.e. files which might be accidental or deliberately concealed. The files are then marked with a suffix .cf-nonalpha and are rendered visible.

     
       NonAlphaNumFiles = ( on )
     

These files can then be tidied (deleted) or disabled by searching for the suffix pattern. Note that alphanumeric means ascii codes less than 32 and greater than 126.

7.15 Defensive garbage collection

We tend to be worried about the fact that crackers will destroy our systems and make them unusable, but many operating systems are programmed to do this to themselves! There are few systems which can survive a full system disk and yet many logging agents go on filling up disks without ever checking to see how full they are getting. In short they choke themselves in a self-styled denial of service attack. Cfagent can help here by rotating logs frequently and by tidying temporary file directories:

     
     disable:
     
       Tuesday.Hr00::
     
        #
        # Disabling these log files weekly prevents them from
        # growing so enormous that they fill the disk!
        #
     
        /local/iu/httpd/logs/access_log   rotate=2
        /local/iu/httpd/logs/agent_log    rotate=2
        /local/iu/httpd/logs/error_log    rotate=2
        /local/iu/httpd/logs/referer_log  rotate=2
     
       FTPserver.Sunday::
     
        /local/iu/logs/xferlog rotate=3
     
     tidy:
     
         /tmp pattern=* age=1
     

Process garbage collection is just as important. There are lot's of reasons why process tables fill up with unterminated processes. One example is faulty X terminal software which does not kill its children at logout. Another is that programs like netscape and pine tend to go into loops from which they never return, gradually loading the system with an ever increasing glacial burden. Just killing old processes can cause your system to spring back from its ice age blues (hopefully without littering the system with too many dead mammoths or bronze age axe-bearers). If the host concerned has important duties then this lack of responsiveness can compromise key services. It also gives local users a way of carrying out denial of service attacks on the system.

If users always log out at the end of the day and log in again the day after then this is easy to address with cfengine. Here is some code to kill commonly hanging processes. Note that on BSD like systems process options "aux" are required to see the relevant processes:

     processes:
     
       linux|freebsd|sun4::
     
           SetOptionString "aux"
     
       any::
     
       "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec"
     
           signal=kill
     
           include=ftpd
           include=tcsh
           include=xterm
           include=netscape
           include=ftp
           include=pine
           include=perl
           include=irc
           include=java
           include=/bin/ls
           include=emacs
           include=passwd
     

This pattern works like this: as processes become more than a day old they name of the month appears in the date of the process start time. These are matched by the regular expression. The include lines then filter the list of the processes further picking out lines which include the specified strings. On some BSD-like systems the default ps option string is "-ax" and you might need to reset it to something which adds the start date in order to make this work.

Another job for process management is to clean up processes which have hung, gone amok or which are left over from old logins. Here is a regular expression which detects non-root processes which have clocked up more than 100 hours of CPU time. This is a depressingly common phenomenon when a program goes into an infinite loop. It can starve other processes of resources in a very efficient denial of service attack.

      any::
     
       #
       # Kill processes which have run on for too long e.g. 999:99 cpu time
       # Careful a pattern to match 99:99 will kill everything!
       #
     
       "[0-9][0-9][0-9][0-9]:[0-9][0-9]" signal=term exclude=root
            "[0-9][0-9][0-9]:[0-9][0-9]" signal=term exclude=root

Under NT this is not so simple, since the process table for the cygwin library applies only to processes which have been started by programs working under the Unix process emulation. Hopefully this short-coming can be worked around at some point in the future.

7.16 Anonymous FTP example

Configuring a service like anonymous FTP requires a certain amount of vigilance. It is a good idea to automate it and let cfengine make sure that things don't go astray. Note that we constantly ensure that the ls program used by the anonymous ftp server is a trusted program by checking it with an md5 signture of a trusted version of the program. If for some reason it should be replaced with a Trojan horse, cfagent would notice the incorrect checksum (md5) and move the bad program to ls.cf-saved and immediately replace it with the correct version without waiting for the adminstrator to act. The inform and syslog options ask for an explicit warning to be made about this copy. Here is a complete anonymous ftp setup and maintenance program for Solaris hosts.

     
     control:
     
        actionsequence = ( directories copy editfiles files )
     
        # Define variables
     
        ftp = ( /usr/local/ftp )
        uid = ( 99 )  # ftp user
        gid = ( 99 )  # ftp group
     
     directories:
     
      solaris::
     
        $(ftp)/pub      mode=644 owner=root group=other
        $(ftp)/etc      mode=111 owner=root group=other
        $(ftp)/dev      mode=555 owner=root group=other
        $(ftp)/usr      mode=555 owner=root group=other
        $(ftp)/usr/lib  mode=555 owner=root group=other
     
     files:
     
       solaris::
     
        $(ftp)/etc/passwd mode=644 o=root    action=fixplain
        $(ftp)/etc/shadow mode=400 o=root    action=fixplain
        $(ftp)/pub        mode=644 owner=ftp action=fixall  recurse=inf
     
     copy:
     
       solaris::
     
           # Make sure ls is a trusted program by copying
           # a secure location...
     
        /bin/ls dest=$(ftp)/usr/bin/ls
                mode=111
                owner=root
                type=checksum
                inform=true
                syslog=true
     
        /etc/netconfig dest=$(ftp)/etc/netconfig mode=444 o=root
     
        /devices/pseudo/mm@0:zero      dest=$(ftp)/dev/zero      mode=666 o=root
        /devices/pseudo/clone@0:tcp    dest=$(ftp)/dev/tcp       mode=444 o=root
        /devices/pseudo/clone@0:udp    dest=$(ftp)/dev/udp       mode=666 o=root
        /devices/pseudo/tl@0:ticotsord dest=$(ftp)/dev/ticotsord mode=666 o=root
     
        /usr/lib        dest=$(ftp)/usr/lib recurse=2
                        mode=444
                        owner=root
                        backup=false
                        include=ld.so*
                        include=libc.so*
                        include=libdl.so*
                        include=libmp.so*
                        include=libnsl.so*
                        include=libsocket.so*
                        include=nss_compat.so*
                        include=nss_dns.so*
                        include=nss_files.so*
                        include=nss_nis.so*
                        include=nss_nisplus.so*
                        include=nss_xfn.so*
                        include=straddr.so*
     
        /usr/share/lib/zoneinfo dest=$(ftp)/usr/share/lib/zoneinfo
                         mode=444 recurse=2 o=root type=binary
     
     editfiles:
     
        solaris::
     
         #
         # Make sure that umask is right for ftpd
         # or files can be left 666 after upload!
         #
     
       { /etc/rc2.d/S72inetsvc
     
       PrependIfNoSuchLine "umask 022"
       }
     
       { $(ftp)/etc/passwd
     
       AutoCreate
       EmptyEntireFilePlease
       AppendIfNoSuchLine "ftp:x:$(uid):$(gid):Anonymous FTP:$(ftp):/bin/sync"
       }
     
       { $(ftp)/etc/group
     
       AutoCreate
       EmptyEntireFilePlease
       AppendIfNoSuchLine "ftp::$(gid):"
       }
     
       {  $(ftp)/etc/shadow
     
       AutoCreate
       EmptyEntireFilePlease
       AppendIfNoSuchLine "ftp:NP:6445::::::"
       }
     
       # Finally...useful for chown
     
       { /etc/passwd
     
       AppendIfNoSuchLine "ftp:x:$(uid):$(gid):Anonymous FTP:$(ftp):/bin/sync"
       }
     
       { /etc/group
     
       AppendIfNoSuchLine "ftp::$(gid):"
       }
     
     
     

7.17 WWW security

The security of the web is a slightly paradoxical business. On the one hand, we make a system for distributing files to anyone without the need for passwords, and on the other hand we are interested in limited who gets what information and who can change what. If you want web privacy you have to exclude the possibility of running untrusted CGI scripts, i.e. CGI programs which you did not write yourself since CGI programs can circumvent any server security. This is because of a fundamental weakness in the way that a WWW server works. It makes user-CGI scripts incompatible with the idea of private WWW areas.

The problem with CGI is this: in order for the httpd daemon to be able to read information to publish it, that information must be readable by the UID with which httpd runs (e.g. the www special user (you should not run with uid nobody since that can be mixed up with NFS mappings)). But CGI programs automatically run with this www UID also. Since it is not possible to restrict the actions of CGI programs which you did not write yourself, any CGI program has automatically normal file permission access to any file which the server can see. A CGI program could choose to open a restricted file circumventing the security of the daemon. In short, privacy requires a separate UID (a separate daemon and port number) or a separate server host altogether.

Provided you acknowledge this weakness, you can still use cfengine to administrate the permissions and access files on say two WWW servers from your central location. Let us imagine having a public WWW server and a private WWW server and assume that they have a common user/UID database. We begin by defining a user-ID and group-ID for the public and private services. These need to have different ID's in order to prevent the CGI trick mentioned above.

     editfiles:
     
      wwwpublic::
     
       { $(publicdocroot)/.htaccess
     
       AutoCreate
       EmptyEntireFilePlease
       AppendLine "order deny,allow"
       AppendLine "deny from all"
       AppendLine "allow from all"
       }
     
      wwwprivate::
     
       { $(privatedocroot)/.htaccess
     
       AutoCreate
       EmptyEntireFilePlease
       AppendLine "order deny,allow"
       AppendLine "deny from all"
       AppendLine "allow .example.org"
       }
     

Your documnts should be owned by a user and group which is *not* the same as the UID/GID the daemon runs with, otherwise CGI programs and server-side emebellishments could write and destroy those files. You will also want to ensure that the files are readable by the www daemon, so a files command can be used to this end. You might want a group of people to have access to the files to modifiy their contents.

     
      files:
     
      wwwprivate::
     
        $(privatedocroot) mode=664 owner=priv-data group=priv-data act=fixall
     
      wwwpublic::
     
        $(publicdocroot) mode=664 owner=public-data group=public-data act=fixall
     
     

7.18 Miscellaneous security of cfengine itself

     
      control:
     
        SecureInput  = ( on )
     

If this is set cfengine will not read any files which are not owned by the uid running the program, or which are writable by groups or others.

7.19 Privacy (encryption)

Encryption (privacy) is not often a big deal in system administration. With the exception of the distribution of passwords and secret keys themselves, there is little or no reason to maintain any level of privacy when transferring system files (binaries for instance). If you find yourself using a tool like cfengine to transmit company secrets from one place to another you should probably book yourself into the nearest asylum for a checkup. Cfengine is not about super-secure communication, but it can be used to perform the simple job of file distribution through an encrypted link (e.g. as a NIS replacement or other password distributor). Cfengine uses the triple DES implemenation in the OpenSSL distribution (or equivalent) to provide `good enough' privacy during remote copying.

The most important issue in system security is authentication. Without the ability to guarantee the identity of a user or of trusted information it is impossible to speak of security at all. Although services like pidentd can go some way to confirming the identity of a user, the only non-spoofable way of confirming identity is to use a shared secret — i.e. a password. A password works by demanding that two parties who want to trust one another must both know a piece of information which untrusted parties do not.

Following the second world war, the now famous pair, Julius and Ethel Rosenberg were convicted and executed for spying on the U.S. bomb project for the Soviet Union in 1953. At one point they improvised a clever password system: a cardboard Jell-O box was torn in two and one half given to a contact whom they later would need to identify. The complex edge shape and colour matching made a complex key quite impossible to forge. Our bodies use a similar method of receptor identification of molecules for immune responses as well as for smell (with some subtleties). Without matching secrets it is impossible to prove someone's identity. To copy a file over an encrypted link, you write:

     
      copy:
     
         source dest=destination encrypt=true server=myserver
                                  trustkey=true
     

Bear in mind that the server must be a trusted host. Privacy won't help you if the data you are collecting are faulty. In order to use the encryption there must be a public/private key pair on each host. The public key must be known by both hosts. You can use the program cfkey to generate a new key file. This public key file must then be distributed. Cfagent/cfrun and cfservd can exchange keys securely over the network. This is fine, provided you trust the sources of the keys (how do you know the key is from the host/user who claims to have sent it?).

Under encrypted communications cfengine conceals the names and contents of files. Provided the private key files are private, this has the added side effect of authenticating both hosts for one another.

On the server side, you can choose whether root on a client host should have server-root's privileges to read protected files on the server. In the cfservd.conf file you make a list:

     control:
     
       TrustKeysFrom = ( ip-address/series )
     
     admit:
     
       /filetree *.domain.country root=myhost,yourhost
     
       /etc/shadow *.domain.country encrypt=true
     

In the second example, you can also restrict access to certain files to encrypted lines, i.e. demand that clients use a private connection to collect the file, in order to prevent wiretapping.

7.20 Trust and key races

Trust is the central issue in the security of any system. Public and private keys help you to trust other hosts, only after the genuine, legitimate public keys have been securely distributed to all relevant parties. Until that has happened, it is necessary to trust the identity of remote hosts. Cfengine provides trust policy options which decide whether keys should be exchanged on trust or not, when remote parties connect for the first time. If you do not want to blindly trust keys, you could arrange to exchange key files manually, e.g.

     scp /var/cfengine/ppkeys/localhost.pub remote:/var/cfengine/ppkeys/root-IP-number.pub

or you could arrange to connect at a specific time, so minimize the chances of spoofer racing you to the finishing line in transferring a key for a given user at a given host. Note that, even program like ssh which use "privileged ports" are no longer immune to spoofing. Privileged ports are ports which only the root user can bind to. The idea used to be, a connection on a privileged port must have come from a trusted user, because only someone with the root/Administrator password would be able to bind to a privileged port. Today, that idea is naive at best. Anyone can set up their own host, pull the plug on another and spoof an address or user identity – there are so many ways to attack a system that it is impossible to know with certainty to whom one is talking over the net. The only security one has is in being able to keep a secret key. However, if someone gets there before you, with a fake key, and claims to be you, the receiver cannot know better. This applies to any and all cryptographic software.

Cfengine secure copy is not based on SSL/TLS (although it shares some of the lower level libraries). SSL is not appropriate for a system administration tool, because it uses a trust model based on a third party, such as Verisign. Most adminisrators are not prepared to pay a fee to register every host on their network, with a trusted third party. Cfengine does not use the Secure Shell protocol either. The ssh protocol is not directly appropriate for a system management tool, because it provides only unilateral authentication of user to server. Cfengine authenticates these parties mutually, i.e. user to server, and server to user. Moreover, ssh requires a user to manually accept a key on trust, when the public keys are unknown to the parties, whereas cfengine works non-interactively. SSh uses the notion of binding to a trusted port, to confirm privileged user identity. Cfengine does not make this assumption.

7.21 Adaptive locks

Cfengine treats all of its operations as transactions which are locked. Locking prevents contention from competing processes and it also places reasonable limits on the execution of the program. The fact that operations are locked means that several cfengine programs can coexist without problems. Two locking parameters control the way in which operations can procure locks. The IfElapsed parameter tells operations that they can only be performed if a certain period of time has elapsed since the last time the action was performed. This is anti-spamming protection. The ExpireAfter parameter tells cfengine that no action should last more than a given length of time. This is protection against hanging sub-processes.

7.22 Spoofing

Spoofing refers to attempts to masquerade as another host when sending network transmissions. The cfservd program which can be used to transfer files or activate cfengine remotely attempts to unmask such attempts by performing double reverse lookups in the name service. This verifies by a trusted server that the socket address and the host name are really who they claim to be.


Next: , Previous: Spoofing, Up: Security and cfengine

7.23 Race conditions in file copying

When copying files from a source, it is possible that something might go wrong during the operation and leave a corrupt file in place. For example, the disk might become full while copying a file. This could lead to problems. Cfengine deals with this by always copying to a new file on the destination filesystem (prefix .cfnew) and then renaming it into place, only if the transfer was successful. This ensures that there is space on the filesystem and that nothing went wrong with the network connection or the disk during copying.

7.24 size= in copy

As a further check on copying, cfengine allows you to define acceptable limits on the size of files. After all, sometimes errors might occur quite independently of anything you are doing with cfengine. Perhaps the master password file got emptied somehow, or got replaced by a binary, through some silly mistake. By checking making an estimate of the expected size of the file and adding it to the copy command, you can avoid installing a corrupt file and making a localized problem into a global one.


Next: , Previous: size= in copy, Up: Security and cfengine

7.25 useshell= and owner= in shellcommands

There are dangers in starting scripts from programs which run with root privileges. Normally, shell commands are started by executing them with the help of a /bin/sh -c command. The trouble with this is that it leaves one open to a variety of attacks. One example is fooling the shell into starting foreign programs by manipulating the IFS variable to treat '/' as a separator. You can ask cfengine to start programs directly, without involving an intermediary shell, by setting the useshell variable to false. The disadvantage is that you will not be able to use shell directives such as | and > in your commands. The owner=uid directive executes shell commands as a special user, allowing you to safely run scripts without root privilege.

7.26 Firewalls

Cfengine is a useful tool for implementing, monitoring and maintaining firewalls. You can control what programs are supposed to be on the firewall and what programs are not supposed to be there. You can control file permissions, processes and a dozen other things which make up the configuration of a bastion host. By referencing important programs against a read only medium you can not only monitor host integrity but always be certain that you are never more than a cfengine execution away from correctness.


Next: , Previous: Security and cfengine, Up: Top

8 Summary

Cfengine is not a tool, it is an environment for managing host configuration and integrity. In this article it has only been possible to scratch the surface of what cfengine can do. To fully understand the syntax of the examples here you should read the documentation for cfengine.

The big advantage of cfengine over many other configuration schemes is that you can have *everything* in one file (or set of files). The global file is common to every host and yet it can be as general or as specific as you want it to be. You can use it as a front end for cron, and you can use its advanced features to make your hosts *converge* to a desired, correct state.


Next: , Previous: Summary, Up: Top

Variable Index


Next: , Previous: Variable Index, Up: Top

Concept Index


Previous: Concept Index, Up: Top

FAQ Index

Table of Contents


Footnotes

[1] On some systems, core dumps cannot be switched off!

[2] This unique naming scheme was suggested to me originally by Knut Borge at USIT of the University of Oslo.

[3] Note: if the filesystem was in the fstab but not actually mounted a warning is issued telling you that the filesystem was probably not exported correctly on host1.

[4] One possibility is that an NFS filesystem cannot be mounted because the host serving the filesystem is out of service. If this is the case then a subsequent re-run when the server resumes normal service will succeed.

[5] Recall the `spam' song from Monty Python's flying circus?

[6] Recall the `spam' song from Monty Python's flying circus?

[7] Recall the `spam' song ... get the idea?


cfengine-2.2.10/doc/stamp-10000644000175000001440000000014711170173455012247 00000000000000@set UPDATED 24 December 2008 @set UPDATED-MONTH December 2008 @set EDITION 2.2.10 @set VERSION 2.2.10 cfengine-2.2.10/doc/cfetoolcreate.80000644000175000001440000001655710261007177013763 00000000000000.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "CFETOOLCREATE 1" .TH CFETOOLCREATE 1 "2004-09-22" "perl v5.8.4" "User Contributed Perl Documentation" .SH "NAME" cfetool create \- Set up a new Database .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBcfetool\fR \fBcreate\fR \fIname\fR [\fB\-\-path\fR|\fB\-p\fR\ \fIdirectory\ name\fR] [\fB\-\-step\fR|\fB\-s\fR\ \fIstep\fR] [\fB\-\-daily\fR|\fB\-d\fR] [\fB\-\-weekly\fR|\fB\-w\fR] [\fB\-\-yearly\fR|\fB\-y\fR] [\fB\-\-cfenvd\fR|\fB\-c\fR] [\fB\-\-histograms\fR|\fB\-H\fR] [\fB\-\-verbose\fR|\fB\-v\fR] [\fB\-\-file\fR|\fB\-f\fR\ \fIfilename\fR] [\fB\-\-help\fR|\fB\-h\fR] .SH "DESCRIPTION" .IX Header "DESCRIPTION" Creates a new database and, optionally, histogram file in a new directory with the name given. If the \fB\-p\fR option is specified, it will be created as a subdirectory of the path given. Otherwise, it will be a subdirectory of the current working directory. .PP The \fB\-d\fR, \fB\-w\fR, and \fB\-y\fR options specify the period over which the data will span, and may be combined to create multiple databases. If they are all ommitted, the default is weekly. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-\-path\fR|\fB\-p\fR" 4 .IX Item "--path|-p" The directory in which to create the new database folder. If this argument is not provided, the current working directory will be used. .IP "\fB\-\-step\fR|\fB\-s\fR" 4 .IX Item "--step|-s" The interval, in minutes, with which the database will be updated. If this argument is not provided, cfetool assumes a default of 5 minutes. .IP "\fB\-\-daily\fR|\fB\-d\fR" 4 .IX Item "--daily|-d" Create a database for recording daily patterns. .IP "\fB\-\-weekly\fR|\fB\-w\fR" 4 .IX Item "--weekly|-w" Create a database for recording weekly patterns. .IP "\fB\-\-yearly\fR|\fB\-y\fR" 4 .IX Item "--yearly|-y" Create a database for recording yearly patterns. .IP "\fB\-\-cfenvd\fR|\fB\-c\fR" 4 .IX Item "--cfenvd|-c" Communicate with cfengine. If this option is specified, cfetool will set classes understandable by cfagent. For more information, see the \fBcfenvd\fR documentation. .IP "\fB\-\-histograms\fR|\fB\-H\fR" 4 .IX Item "--histograms|-H" Create a histogram file, to store information about the probability distribiution of fluctuations about the mean value over all times of day. Cfetool won't write anything to this file for the first four weeks, as it has to have reliable mean values in order to accurately calculate it. .IP "\fB\-\-verbose\fR|\fB\-v\fR" 4 .IX Item "--verbose|-v" Print details of the command's execution to the standard output stream. .IP "\fB\-\-file\fR|\fB\-f\fR" 4 .IX Item "--file|-f" Specifies a file which contains measurements to feed into the database in batch mode. Used for testing purposes. Each line in the file should be in either of these formats: .Sp \&\fImonth\fR/\fIday\fR/\fIyear\fR \fIhour\fR:\fImin\fR:\fIsec\fR \fIvalue\fR .Sp or .Sp \&\fIepoch\fR \fIvalue\fR .IP "\fB\-\-help\fR|\fB\-h\fR" 4 .IX Item "--help|-h" Prints a short help message and then exits. .SH "EXAMPLE" .IX Header "EXAMPLE" .Vb 1 \& % cfetool create temperature --path /my/path --histograms --step 10 .Ve .PP Creates an empty database and histogram file in \fB/my/path/temperature/\fR, ready to store values over ten minute intervals spanning a one-week period. .SH "AUTHORS" .IX Header "AUTHORS" The code and documentation were contributed by Stanford Linear Accelerator Center, a department of Stanford University. This documentation was written by .IP "Elizabeth Cassell and" 4 .IX Item "Elizabeth Cassell and" .PD 0 .IP "Alf Wachsmann " 4 .IX Item "Alf Wachsmann " .PD .SH "COPYRIGHT AND DISCLAIMER" .IX Header "COPYRIGHT AND DISCLAIMER" .Vb 3 \& Copyright 2004 Alf Wachsmann and \& Elizabeth Cassell \& All rights reserved. .Ve cfengine-2.2.10/doc/cfengine-Tutorial.info0000644000175000001440000103554211170173456015307 00000000000000This is cfengine-Tutorial.info, produced by makeinfo version 4.12 from cfengine-Tutorial.texinfo. INFO-DIR-SECTION System Utilities START-INFO-DIR-ENTRY * cfengine Tutorial: (cfengine-Tutorial.info). Cfengine is a language based tool specifically designed for configuring and maintaining BSD and System-5-like operating systems attached to a TCP/IP network. END-INFO-DIR-ENTRY  File: cfengine-Tutorial.info, Node: Top, Next: Overview, Prev: (dir), Up: (dir) Cfengine-Tutorial ***************** Copyright (C) 2008 Mark Burgess This manual corresponds to CFENGINE Edition 2.2.10 for version 2.2.10 as last updated 24 December 2008. * Menu: * Overview:: * Getting started:: * More advanced concepts:: * Global configurations:: * Using cfengine as a front-end for cron:: * Cfengine network services:: * Security and cfengine:: * Summary:: * Variable Index:: * Concept Index:: * FAQ Index::  File: cfengine-Tutorial.info, Node: Overview, Next: Getting started, Prev: Top, Up: Top 1 Overview ********** _In this manual the word "host" is used to refer to a single computer system - i.e. a single machine which has a name termed its "hostname"._ * Menu: * What is cfengine?:: * Site configuration:: the problem * Key concepts:: the solution * Functionality:: an advertisement  File: cfengine-Tutorial.info, Node: What is cfengine?, Next: Site configuration, Prev: Overview, Up: Overview 1.1 What is cfengine and who can use it? ======================================== Cfengine is a tool for setting up and maintaining computer systems. It consists of several components: cfagent An autonomous configuration agent (required). cfservd A file server and remote activation service (optional). cfexecd A scheduling and report service (recommended). cfenvd An anomaly detection service (strongly recommended). cfrun A way of activating cfagent remotely (use this as you need to). cfshow A way of examining the contents of helper databases (helper). cfenvgraph Ancillary tool for cfenvd (helper). cfkey Key generation tool (run once on every host). The agent `cfagent' can be used without the other programs, but not all of the capabilities of cfengine will be available unless the components are installed and used appropriately. Cfengine incorporates a declarative language--much higher level than Perl or shell: a single statement can result in many hundreds of operations being performed on multiple hosts. Cfengine is good at performing a lot of common system administration tasks, and allows you to build on its strengths with your own scripts. You can also use it as a netwide front-end for `cron'. Once you have set up cfengine, you'll be free to use your time doing other things instead of manual configuration. The main purpose of cfengine is to allow you to create a single system configuration which will allow you to define how every host on your network should be configured, and to do so in an intuitive way - either centralized or decentralized as you prefer. An interpreter runs on every host on your network and parses the master file (or file set). The configuration of each host is checked against this file; then, if you request it, any deviations from the defined configuration are fixed automatically. You do not have to mention every host specifically by name in order to configure them: instead you can refer to the properties which distinguish hosts from one another. Cfengine uses a flexible system of "classes" which helps you to single out a specific group of hosts with a single statement. Cfengine grew out of the need to control the accumulation of complex shell scripts used in the automation of key system maintenance at University College in Oslo. There were a lot of scripts, written in shell and in Perl, performing system administration tasks such as file tidying, find-database updates, process checking and several other tasks. In a mixed environment, shell scripts work very poorly: shell commands have differing syntax across different operating systems, and the locations and names of key files differ. In fact, the non-uniformity of Unix was a major headache. Scripts were filled with tests to determine what kind of operating system they were being run on, to the point where they became so complicated and unreadable that no one was quite sure what they did anymore. Other scripts were placed only on the systems where they were relevant, out of sight and out of mind. It quickly became clear that our dream solution would be to replace this proliferation of scripts by a single file containing everything to be checked on every host on the network. By defining a new language, this file could hide all of the tests by using classes (a generalized `switch/case' syntax) to label operations and improve the readability greatly. The gradual refinement of this idea resulted in the present day cfengine. As an inexperienced cfengine user, you will probably find yourself trying to do things as you would have tried to do them in shell or Perl. This is probably not the right way to think when using cfengine. You will need to think in a more `cfengine way'. When reading the manual, keep in mind that cfengine's way of working is to think about what the final result should be like, rather than on how to get there (with shell and Perl you specify what to do, rather than what you would like). The remainder of this manual assumes that you know a little about BSD and UNIX System V systems and have every day experience in using either the C shell (csh) or the Bourne shell (sh), or their derivatives. If you are experienced in system administration, you might like to skip the earlier chapters and turn straight to the example in the section _Example configuration file_ of the Reference manual. This is the probably quickest way to learn cfengine for the initiated. If you are not so familiar with system administration and would like a more gentle introduction, then we begin here...  File: cfengine-Tutorial.info, Node: Site configuration, Next: Key concepts, Prev: What is cfengine?, Up: Overview 1.2 Site configuration ====================== To the system administrator of a small network, with just a few workstations or perhaps even a single mainframe system, it might seem superfluous to create a big fuss about the administration of the system. After all, it's easy to `fix' things manually should any problems arise, making a link here, writing a script there and so on -- and its probably not even worth writing down what you did because you know that it will always be easy to fix next time around too... But networks have a tendency to expand and--before you know it--you have five different types of operating system and each type of system has to be configured in a special way, you have to make patches to each system and you can't remember whether you fixed that host on the other side of the building... Also, you discover fairly quickly that what you thought of as BSD or System V is not as standard as you thought and that none of your simple scripts that worked on one system work on the others without a considerable amount of hacking and testing. You try writing a script to help you automate the task, but end up with an enormous number of `if..then..else..' tests which make it hard to see what is really going on. To manage a network with many different flavours of operating system in a systematic way, what is needed is a more disciplined way of making changes which is robust against system re-installation. After all, it would be tragic to spend many hours setting up a system by hand only to lose everything in an unfortunate disk crash a week or even a year later when you have forgotten what you had to do. Upgrades of the operating system software might delete your carefully worked out configuration. What is needed is a separate record of all of the patches required on all of the systems on the network; a record which can be compared to the state of each host at any time and which a suitable engine can use to fix any deviations from that reference standard. The idea behind cfengine is to focus upon a few key areas of basic system administration and provide a language in which the transparency of a configuration program is optimal. It eliminates the need for lots of tests by allowing you to organize your network according to "classes". From a single configuration file (or set of files) you can specify how your network should be configured -- and cfengine will then parse your file and carry out the instructions, warning or fixing errors as it goes.  File: cfengine-Tutorial.info, Node: Key concepts, Next: Functionality, Prev: Site configuration, Up: Overview 1.3 Key Concepts ================ _Some of the important issues in system administration which cfengine can help with._ * Menu: * Control files:: textfiles which configure * Network interface:: ethernet parameters * Network File System (NFS):: sharing resources * Name servers (DNS):: setting up a name service * Monitoring important files:: permission and ownership * Making links:: aliases  File: cfengine-Tutorial.info, Node: Control files, Next: Network interface, Prev: Key concepts, Up: Key concepts 1.3.1 Configuration files and registries ---------------------------------------- One of the endearing characteristics of BSD and System V systems is that they are configured through human-readable text files. To add a new user to the system you edit `/etc/passwd', to add a new disk you must edit `/etc/fstab', etc. Many applications are also configured with the help of text files. When installing a new system for the first time, or when changing updating the setup of an old system, you are faced with having to edit lots of files. In some cases you will have to add precisely the same line to the same file on every system in your network as a change is made, so it is handy to have a way of automating this procedure so that you don't have to load every file into an editor by hand and make the changes yourself. This is one of the tasks which cfagent will automate for you. On Windows systems, configuration data are stored in a system registry. With the right tools, the Windows system registry can also be edited by cfengine, but this requires more care.  File: cfengine-Tutorial.info, Node: Network interface, Next: Network File System (NFS), Prev: Control files, Up: Key concepts 1.3.2 Network interface ----------------------- Each host which you connect to an Ethernet-based network running TCP/IP protocols must have a so-called `net interface'. This network interface must be configured before it will work. Normally, one does this with the help of the `ifconfig' command. This can also be checked and configured automatically by cfagent. Network configuration involves telling the interface hardware what the internet (IP) address of your system is, so that it knows which incoming `packets' of data to pay attention to. It involves telling the interface how to interpret the addresses it receives by setting the `netmask' for your network (see below). Finally, you must tell it which dummy address is to be used for messages which are broadcast to all hosts on your network simultaneously (see the Reference Manual). Cfagent's features are mainly meant for hosts which use static IP addresses; if you are using DHCP clients, then you will not need the net configuration features.  File: cfengine-Tutorial.info, Node: Network File System (NFS), Next: Name servers (DNS), Prev: Network interface, Up: Key concepts 1.3.3 Network File System (NFS) or file distribution? ----------------------------------------------------- Probably the first thing you are interested in doing with a network (after you've had your fill of the World-Wide Web) is to make your files available to some or all hosts on the network, no matter where in your corporate empire (or university dungeon) you might be sitting. In other words, if you have a disk which is physically connected to host A, you would like to make the contents of that disk available to hosts B, C, D ..., etc. NFS (the Network FileSystem) makes this possible. The process works by `filesystems'. A filesystem is one partition of a disk drive - or one unit of disk space which can be accessed by a single `logical device' `/dev/something'. To make a filesystem available to other hosts you have to do three things. * On the host the disk is physically connected to you must _export_ the filesystem by adding something to the file `/etc/exports'. This tells NFS who is allowed to access the disk and who isn't. * On the host which is to access the filesystem you must create a mount point. This is a name in the directory tree at which you want to add the files to your local filesystem. * On the host which is to access the files you must mount the filesystem onto the mount point. The mount operation is the jargon for telling the system to access the device on which the data are stored. Mounting is analogous to opening a file: files are opened, filesystems are mounted. Only after all three of these have been done will a filesystem become available across the network. Cfagent will help you with the last two in a very transparent way. You could also use the text-editing facility in cfagent to edit the `exports' file, but there are other ways to update the `exports' file using NIS and _netgroups_, which we shall not go into here. If you are in doubt, look up the manual page on exports(5). Some sites prefer to minimize the use of NFS filesystems to avoid one machine being dependent on another. They prefer to make a local copy of the files on a remote machine instead. Traditionally, programs like `rdist' have been used for this purpose. You may also use cfagent to copy files in this way, *Note Emulating rdist::.  File: cfengine-Tutorial.info, Node: Name servers (DNS), Next: Monitoring important files, Prev: Network File System (NFS), Up: Key concepts 1.3.4 Name servers (DNS) ------------------------ There are two ways to specify addresses on the internet (called IP addresses). One is to use the text address like `ftp.uu.net' and the other is to use the numerical form `192.48.96.9'. Alas, there is no direct one-to-one correspondence between the numerical addresses and the textual ones, thus a service (called DNS) is required to map one to the other. The service is performed by one or more special hosts on the network called _name servers_. Each host must know how to contact a name server or it will probably hang the first time you give it an IP address. You tell it how to contact a name server by editing the text-file `/etc/resolv.conf'. This file must contain the domain name for your domain and a list of possible name servers which can be contacted, in order of priority. Since this is a special file which every host must have, you don't have to use the general text file editing facilities in cfagent. You can just define the name servers for each host in the cfagent file and cfagent will do the editing to `/etc/resolv.conf' automatically. If you want to change the priority of name servers later, or even change the list then a simple change of one or two lines in the configuration file will enable you to reconfigure every host on your network automatically without having to do any editing yourself!  File: cfengine-Tutorial.info, Node: Monitoring important files, Next: Making links, Prev: Name servers (DNS), Up: Key concepts 1.3.5 Monitoring important files -------------------------------- Security is an important issue on any system. In the busy life of a system administrator, it is not always easy to remember to set the correct access rights on every file; this can result in either a security breach or problems in accessing files. A common scenario is that you, as administrator, fetch a new package using FTP, compile it and install it without thinking too carefully. Since the owner and permissions of the files in an FTP archive remains those of the program author, it often happens that the software is left lying around with the owner and permissions as set by the author of the program rather than any user name on _your_ system. The userid of the author might be anybody on your system -- or perhaps nobody at all! The files should clearly be owned by root and made readable but unwritable by normal users. Simple accidents and careless actions under stress could result in, for example, the password file being writable to ordinary users. If this were the case, the security of the entire system would be compromised. Cfagent therefore allows you to monitor the permissions, ownership, and general existence of files and directories and, if you wish, to either correct them or warn about them automatically.  File: cfengine-Tutorial.info, Node: Making links, Prev: Monitoring important files, Up: Key concepts 1.3.6 Making links ------------------ One of the difficulties with having so many different variations on the theme of BSD and System V based operating systems is that similar files are not always where you expect to find them. They have different names or lie in different directories. The usual solution to the problem is to make an alias for these files, or a pointer from one filename to another. The name for such an alias is a _symbolic link_. It is often very convenient to make symbolic links. For example, you might want the sendmail configuration file `/etc/sendmail.cf' to be a link to a global configuration file, say, `/usr/local/mail/etc/sendmail.cf' on every single host on your network so that there is only one file to edit. If you had to make all of these links yourself, it would take a lifetime. Cfagent will make such a link automatically and check it each time it is run. You can also ask it to tidy up old links which have been left around and no longer point to existing files. If you reinstall your operating system later, it doesn't matter because all your links are defined in your cfagent configuration file, recorded for all time. Cfengine won't forget it, and you won't forget it because the setup is defined in one central place. Cfagent will also allow you to make hard links to regular files, but not to other kinds of files. A hard link that points to a symbolic link is the same as a hard link to the file the symbolic link points to.  File: cfengine-Tutorial.info, Node: Functionality, Prev: Key concepts, Up: Overview 1.4 Functionality ================= The notes above give you a rough idea of what cfengine can be used for. Here is a quick summary of cfagent's capabilities. * Check and configure the network interface. * Edit textfiles for the system and for all users. * Make and maintain symbolic links, including multiple links, using a single command. * Check and set the permissions and ownership of files. * Tidy (i.e., delete) junk files which clutter the system. * Systematic and automated mounting of NFS filesystems. * Checking for the presence of important files and filesystems. * Controlled execution of user scripts and shell commands. * A class-based decision structure. * Process management. How do you run cfagent? You can run it as a cron job, or you can run it manually. You may run cfagent scripts/programs as often as you like. Each time you run a script, cfengine determines whether anything needs to be done -- if nothing needs to be done, nothing is done! If you use it to monitor and configure your entire network from a central file-base, then the natural thing is to run cfengine repeatedly with the help of `cron' and/or `cfexecd'.  File: cfengine-Tutorial.info, Node: Getting started, Next: More advanced concepts, Prev: Overview, Up: Top 2 Getting started ***************** * Menu: * What you must have:: a skeleton cfagent program * Program structure:: an overview * Building a distributed configuration :: * Options:: spices and conveniences * Invoking cfagent:: from the command line * Running cfengine permanently monitoring and restarting cfexecd:: * CFINPUTS environment variable:: the cfengine search path * What to aim for::  File: cfengine-Tutorial.info, Node: What you must have, Next: Program structure, Prev: Getting started, Up: Getting started 2.1 What you must have in a cfagent program =========================================== A cfagent configuration file for a large network can become long and complex so, before we get down to details, let's try to strip away the complexity and look only to the essentials. Each cfagent program or configuration file is a list of declarations of items to be checked and perhaps fixed. You begin by creating a file called `cfagent.conf'. The simplest meaningful file you can create is something like this: # Comment... control: actionsequence = ( links ) links: /bin -> /usr/bin The example above checks and makes (if necessary) a link from `/bin' to `/usr/bin'. Let's examine this example more closely. In a cfengine program: * Use of space is unrestricted. You can start new lines wherever you like. You should generally have a space before and after parentheses to avoid confusing the parser. * A comment is some text which is ignored by cfengine. The `#' symbol designates a comment and means: ignore the remaining text on this line. A comment symbol must have a space in front of it, or start a new line so that cfengine knows you don't mean the symbol as part of another word. * Words which end in a single colon define _sections_ in a program. Under a given section you group together all declarations of a given type. Section names must all be taken from a list defined by the language. You cannot define your own sections. * Words which end in two colons are so-called _class_ names. They are used for making decisions in cfengine. * Statements which are of the form `NAME=( LIST )' are used to assign the value on the right hand side to the name on the left hand side of the equals sign. In simple example above has three of the four types of object described above. The `control:' section of any program tells cfengine how to behave. In this example it adds the action LINKS to the action sequence. For LINKS you could replace some other action. The essential point is that, if you don't have an action sequence, your cfengine program will do absolutely nothing! The action sequence is a list which tells cfagent what do to and in which order. The `links:' section of the file tells cfagent that what follows is a number of links to be made. If you write this part of the file, but forget to add links to the action sequence, then nothing will be done! You can add any number of links in this part of the file and they will all be dealt with in order when--and only when--you write LINKS in the action sequence. To summarize, you _must_ have: * Some declarations which specify things to be done. * An action sequence which tells cfagent which sections to process, how many times and in which order they should be processed. Now let's think a bit about how useful this short example program is. On a SunOS (Solaris) system, where the directory `/bin' is in fact supposed to be a link, such a check could be useful, but on some other system where `/bin' is a not a link but a separate directory, this would result in an error message from cfagent, telling you that `/bin' exists and is not a link. The lesson is that, if we want to use cfagent to make _one single_ program which can be run on any host of any type, then we need some way of restricting the above link so that it only gets checked on SunOS systems. We can write the following: # Comment... control: actionsequence = ( links ) links: sun4:: /bin -> /usr/bin # other links osf:: # other links The names which have double colons after them are called _classes_ and they are used to restrict a particular action so that it only gets performed if the host running the program is a member of that class. If you are familiar with C++, this syntax should make you think of classes definitions in C++. Classes works like this: the names above `sun4', `sun3', `osf' etc. are all internally defined by cfagent. If a host running, say, the OSF operating system executes the file it automatically becomes a member of the class `osf'. Since it cannot be a member more than one of the above, this distinguishes between different types of operating system and creates a hidden `if'..`then'...`else' test. This is the way in which cfagent makes decisions. The key idea is that actions are only carried out if they are in the same class as the host running the program. Classes are dealt with in detail in the next chapter. Now let's see how to add another kind of action to the action sequence. # Comment... control: actionsequence = ( tidy links ) links: /bin -> /usr/bin tidy: /tmp pattern=* age=7 recurse=inf We have now added a new kind of declaration called `tidy:' which deletes files. In the example above, we are looking at files in the directory `/tmp' which match the pattern `*' and have not been accessed for more than seven days. The search for these files descends recursively down any number of subdirectories. To make any of this happen we must add the word TIDY to the action sequence. If we don't, the declaration will be ignored. Notice also that, regardless of the fact that `links:' comes before `tidy:', the order in the action sequence tells us that all `tidy' actions will be performed before `links:'. The above structure can be repeated to build up a configuration file or script.  File: cfengine-Tutorial.info, Node: Program structure, Next: Building a distributed configuration, Prev: What you must have, Up: Getting started 2.2 Program structure ===================== To summarize the previous section, here is a sketch of a typical cfagent configuration program showing a sensible structure. The various sections are listed in a sensible order which you would probably use in the action sequence. An individual section-declaration in the program looks something like this: ACTION-TYPE: CLASS1:: LIST OF THINGS TO DO... CLASS2:: LIST OF THINGS TO DO... `action-type' is one of the following reserved words: groups, control, copy, homeservers, binservers, mailserver, mountables, import, broadcast, resolve, defaultroute, directories, miscmounts, files, ignore, tidy, required, links, disable, shellcommands, strategies editfiles, processes The order in which declarations occur is not important to cfengine from a syntactical point of view, but some of the above actions define information which you will want to refer to later. All variables, classes, groups etc. must be defined before they are used. That means that it is smart to follow the order above for the sections in the first line of the above list. The order in which items are declared is not to be confused with the order in which they are executed. This is determined by the `actionsequence', (see the reference manual). Probably you will want to coordinate the two so that they match as far as possible. For completeness, here is a complete summary of the structure of a very general cfagent configuration program. The format is free and use of space is unrestricted, though it is always a good idea to put a space in front before and after parentheses when defining variables. ###################################################################### # # Example of structure # ###################################################################### groups: GROUP1 = ( HOST HOST ... ) GROUP2 = ( HOST HOST ... ) ... ###################################################################### control: CLASS:: site = ( MYSITE ) domain = ( MYDOMAIN ) ... actionsequence = ( ACTION NAME .... ) mountpattern = ( MOUNTPOINT ) homepattern = ( WILDCARDS MATCHING HOME DIRECTORIES ) addinstallable = ( FOO BAR ) addclasses = ( FOO BAR ) ###################################################################### homeservers: CLASS:: HOME SERVERS binservers: CLASS:: BINARY SERVERS mailserver: CLASS:: MAIL SERVER mountables: CLASS:: LIST OF RESOURCES ###################################################################### import: CLASS:: INCLUDE FILE CLASS:: INCLUDE FILE ###################################################################### broadcast: CLASS:: ONES # or zeros / zeroes defaultroute: CLASS:: MY-GW ###################################################################### resolve: any:: LIST OF NAMESERVERS ...  File: cfengine-Tutorial.info, Node: Building a distributed configuration, Next: Options, Prev: Program structure, Up: Getting started 2.3 Building a distributed configuration ======================================== If a configuration is to be specified at one central location, how does it get distributed to many hosts? The simple answer is to get cfengine to distribute the configuration to the hosts. To do that, a separate configuration file is used. Why? Imagine what would happen if you made a mistake in the configuration, i.e. a syntax error which got distributed to every host. Now all the hosts would be unable to run cfengine, and thereafter unable to download a corrected configuration file. The whole setup would be broken. To prevent this kind of accident, a separate configuration file is used to copy the files and binaries to each host. This configuration should be simple, and should almost never be edited: they key word here is _reliability_. * Menu: * Startup update.conf:: * Startup cfservd.conf:: * Where should I put the files?::  File: cfengine-Tutorial.info, Node: Startup update.conf, Next: Startup cfservd.conf, Prev: Building a distributed configuration, Up: Building a distributed configuration 2.3.1 Startup update.conf ------------------------- The file `update.conf' can have more or less the same form for all sites, looking something like this. ####### # # BEGIN update.conf # # This script distributes the configuration, a simple file so that, # if there are syntax errors in the main config, we can still # distribute a correct configuration to the machines afterwards, even # though the main config won't parse. It is read and run just before the # main configuration is parsed. # ####### control: actionsequence = ( copy tidy ) # Keep this simple and constant domain = ( iu.hio.no ) # Needed for remote copy # # Which host/dir is the master for configuration roll-outs? # policyhost = ( nexus.iu.hio.no ) master_cfinput = ( /masterfiles/inputs ) # # Some convenient variables # workdir = ( /var/cfengine ) cf_install_dir = ( /usr/local/sbin ) # Avoid server contention SplayTime = ( 5 ) ############################################################################ # # Make sure there is a local copy of the configuration and # the most important binaries in case we have no connectivity # e.g. for mobile stations or during DOS attacks # copy: $(master_cfinput) dest=$(workdir)/inputs r=inf mode=700 type=binary exclude=*.lst exclude=*~ exclude=#* server=$(policyhost) $(cf_install_dir)/cfagent dest=$(workdir)/bin/cfagent mode=755 backup=false type=checksum $(cf_install_dir)/cfservd dest=$(workdir)/bin/cfservd mode=755 backup=false type=checksum $(cf_install_dir)/cfexecd dest=$(workdir)/bin/cfexecd mode=755 backup=false type=checksum ##################################################################### tidy: # # Cfexecd stores output in this directory. # Make sure we don't build up files and choke on our own words! # $(workdir)/outputs pattern=* age=7 ####### # # END cf.update # #######  File: cfengine-Tutorial.info, Node: Startup cfservd.conf, Next: Where should I put the files?, Prev: Startup update.conf, Up: Building a distributed configuration 2.3.2 Startup cfservd.conf -------------------------- In order to set up remote distribution from a central server, you will need to start the cfservd service on the host from which the configuration is to be copied, and grant access to the hosts which need to download it. Here is a simple get-started file which does this: ######################################################### # # This is a cfservd config file - it is used for the server # part of cfengine, for remote file transfers and control # over cfengine using the cfrun program. # ######################################################### control: domain = ( iu.hio.no ) cfrunCommand = ( "/var/cfengine/bin/cfagent" ) any:: IfElapsed = ( 1 ) ExpireAfter = ( 15 ) MaxConnections = ( 50 ) MultipleConnections = ( true ) ######################################################### grant: # Grant access to all hosts at example.org. # Files should be world readable /masterfiles/inputs *.example.org # Make sure there is permission to execute by cfrun /var/cfengine/bin/cfagent *.example.org ######## # # END cfservd.conf # ########  File: cfengine-Tutorial.info, Node: Where should I put the files?, Prev: Startup cfservd.conf, Up: Building a distributed configuration 2.3.3 Where should I put the files? ----------------------------------- Where should the files be located? To organize your files, you should think of three potential locations, for different purposes: * A version controlled repository for authoring, testing and applying changes to the files. Once a version is approved for release, these master files should be moved on to a publishing area. e.g. `/usr/local/masterfiles/cfengine/inputs' on `masterhost'. * A centralized location, into which you publish your altered and tested configurations. This is the `buffer' location from which each client will download new and tested versions of the master configuration. e.g. `/usr/local/masterfiles/cfengine/inputs' on `masterhost'. It acts as a buffer between the testing ground and the production location. * The Work Directory. This is the production location. It is a location that is normally chosen to be the private directory where cfagent expects to find its configuration files, `/var/cfengine/inputs'. Your `update.conf' file has the job of copying from the master location (second bullet) above to this location. Modules and methods are normally kept in a separate directory than inputs files are kept in, because they require a directory with special authorizations whe executing. This is good practice As long as the `update.conf' places the master versions in the correct location (usually `/var/cfengine/modules') on the local host, all will be okay. You should not try to copy files directly from a version controlled repository, as you might end up sending out an incomplete or partially tested version of the files to all your hosts. # Example update.conf control: master_cfinput = ( /usr/local/masterfiles/cfengine/inputs ) workdir = ( /var/cfengine ) copy: # Copy from bullet 2 to bullet 3 $(master_cfinput) dest=$(workdir)/inputs r=inf mode=700 type=binary exclude=*.lst exclude=*~ exclude=#* server=$(policyhost) trustkey=true $(master_modules) dest=$(workdir)/modules r=inf mode=700 type=binary exclude=*.lst exclude=*~ exclude=#* server=$(policyhost) trustkey=true  File: cfengine-Tutorial.info, Node: Options, Next: Invoking cfagent, Prev: Building a distributed configuration, Up: Getting started 2.4 Optional features in cfagent ================================ Cfagent doesn't do anything unless you ask it to. When you run a cfagent program it generates no output unless it finds something it believes to be wrong. It does not carry out any actions unless they are declared in the action sequence. If you like, though, you can make cfagent positively chatty. Cfagent can be run with a number of command line options (see the reference manual). If you run the program with the `-v' or `--verbose' options, it will supply you cheerily with a resume of what it is doing. Certain warning messages also get printed in verbose mode, so it is a useful debugging tool. You can ask cfagent to check lots of things - the timezone for instance, or the domain name. In order for it to check these things, it needs some information from you. All of the switches and options which change the way in which cfagent behaves get specified either on the command line or in the `control:' section of the control file. Some special control variables are used for this purpose. Here is a short example: control: domain = ( example.org ) netmask = ( 255.255.255.0 ) timezone = ( MET CET ) mountpattern = ( /mydomain/mountpoint ) actionsequence = ( checktimezone # check time zone netconfig # includes check netmask resolve # includes domain mountinfo # look for mounted disks under mountpattern ) To get verbose output you must run cfagent with the appropriate command line option `--verbose' or `-v'. Notice that setting values has a special kind of syntax: a variable name, an equals sign and a value in parentheses. This tells you that the quantity of the left hand side assumes the value on the right hand side. There are lots of questions you might ask at this point. The answers to these will be covered as we go along and in the next chapter. Before leaving this brief advertisement for control parameters, it is worth noting the definition of `mountpattern' above. This declares a directory in which cfagent expects to find mounted disks. It will be explained in detail later, for now notice that this definition looks rather stupid and inflexible. It would be much better if we could use some kind of variables to define where to look for mounted filesystems. And of course you can... Having briefly scraped the surface of what cfagent can do, turn to the example and take a look at what a complete program can look like, (see the reference manual). If you understand it, you might like to skip through the rest of the manual until you find what you are looking for. If it looks mysterious, then the next chapter should answer some questions in more depth.  File: cfengine-Tutorial.info, Node: Invoking cfagent, Next: Running cfengine permanently monitoring and restarting cfexecd, Prev: Options, Up: Getting started 2.5 Invoking cfagent ==================== Cfagent may be invoked in a number of ways. Here are some examples: host% cfagent host% cfagent --file myfile host% cfagent -f myfile -v -n host% cfagent --help The first of these (the default command, with no arguments) causes cfagent to look for a file called `cfagent.conf' in the directory pointed to by the environment variables `CFINPUTS' or `/var/cfengine/inputs' by default, and execute it silently. The second command reads the file `myfile' and works silently. The third works in verbose mode and the `-n' option means that no actions should actually be carried out, only warnings should be printed. The final example causes cfagent to print out a list of its command line options. The complete list of options is listed in the summary at the beginning of this manual, or you can see it by giving the `-h' option, (see the reference manual). In addition to running cfagent with a filename, you can also treat cfagent files as scripts by starting your cfagent program with the standard shell line: #!/usr/local/sbin/cfagent -f # # My config script # Here we assume that you have installed cfengine under the directory `/usr/local/sbin'. By adding a header like this to the first line of your program and making the file executable with the `chmod' shell command, you can execute the program just by typing its name--i.e. without mentioning cfengine explicitly at all. As a novice to cfengine, it is advisable to check all programs with the `-n' option before trusting them to your system, at least until you are familiar with the behaviour of cfengine. This `safe' option allows you to see what cfengine wants to do, without actually committing yourself to doing it.  File: cfengine-Tutorial.info, Node: Running cfengine permanently monitoring and restarting cfexecd, Next: CFINPUTS environment variable, Prev: Invoking cfagent, Up: Getting started 2.6 Running cfengine permanently, monitoring and restarting cfexecd =================================================================== Once you are happy using cfengine, you will want it to run least once per hour on your systems. This is easily achieved by adding the following line to the root crontab file of each system: 0,30 * * * * /usr/local/sbin/cfexecd -F This is enough to ensure that cfengine will get run. Any output generated by this job, will be stored in `/var/cfengine/outputs'. In addition, if you add the following to the file `cfagent.conf', the system administrator will be emailed a summary of any output: control: smtpserver = ( mailhub.example.org ) # site MTA which can talk smtp sysadm = ( mark@example.org ) # mail address of sysadm Fill in suitable values for these variables. An alternative, or additional way to run cfengine, is to run the `cfexecd' program is daemon mode (without the `-F') option. In this mode, the daemon lives in the background and sleeps, activating only in accordance with a scheduling policy. The default policy is to run once every hour (equivalent to `Min00_05'). Here is how you would modify `cfagent.conf' in order to make the daemon execute cfagent every half-hour: control: # When should cfexecd in daemon mode wake up the agent? schedule = ( Min00_05 Min30_35 ) Note that the time specifications are the basic cfengine _time classes_, *Note Building flexible time classes::. Although one of these methods should suffice, no harm will arise from running both cron and the cfexecd side-by-side. Cfagents locking mechanisms ensure that no contention will occur. The other components of cfengine can be started by cfagent itself: processes: "cfenvd" restart "/usr/local/sbin/cfenvd" "cfservd" restart "/usr/local/sbin/cfservd" Note that, to start cfexecd by cfengine, one must do this processes: "bin/cfexecd$" restart "/usr/local/sbin/cfexecd" It's important to use as specific a regular expression as possible in match statements (the path to the program and the regular expression metacharacter `$' meaning "end of line", in this example) because bare strings can often match unexpected processes. For instance, using `cfexecd' by itself will also match a process spawned by `cfagent -F', which shows up as `/var/cfagent/bin/cfagent -Dfrom_cfexecd' in the process table!  File: cfengine-Tutorial.info, Node: CFINPUTS environment variable, Next: What to aim for, Prev: Running cfengine permanently monitoring and restarting cfexecd, Up: Getting started 2.7 CFINPUTS environment variable ================================= Whenever cfengine looks for a file it asks a question: is the filename an absolute name (that is a name which begins from `/' like `/usr/file'), is it a file in the directory in which you invoke cfengine or is it a file which should be searched for in a special place? If you use an absolute filename either on the command line using `-f' or in the `import' section of your program (a name which begins with a slash '/'), then cfengine trusts the name of the file you have given and treats it literally. If you specify the name of the file as simple `.' or `-' then cfengine reads its input from the standard input. If you run cfengine without arguments (so that the default filename is `cfagent.conf') or you specify a file without a leading slash in the `import' section, then the value of the environment variable `CFINPUTS' is prepended to the start of the file name. This allows you to keep your configuration in a standard place, pointed to by `CFINPUTS'. For example: host# setenv CFINPUTS /usr/local/masterfiles/cfengine/inputs host# cfagent -f myfile In this example, cfengine tries to open `myfile'. in the directory `/usr/local/masterfiles/cfengine/inputs'. If no value is set for `CFINPUTS', then the default location is the trusted cfengine directory `/var/cfengine/inputs'.  File: cfengine-Tutorial.info, Node: What to aim for, Prev: CFINPUTS environment variable, Up: Getting started 2.8 What to aim for =================== If you are a beginner to cfengine, you might not be certain exactly how you want to use it. Here are some hints from Dr. Daystrom about how to get things working quickly. * Run cfengine from cron every hour on all your systems. Be sure to label long tasks, or tasks which do not need to be performed often by a _time class_ which prevents it from being executed all the time, *Note Using cfengine as a front-end for cron::. _Running cfengine from cron means that it will be run in parallel on your systems. Cfengine on one host does not have to wait for cfengine on another host to complete._ * Set up `cfservd' on all your systems so that cfengine can be executed remotely, so that you can immediately "push" changes to all your hosts with `cfrun'. Think carefully about whom you wish to give permission to run cfengine from the net, *Note Configuring cfservd::. Set up you `cfservd.conf' file accordingly. You can also use this daemon to grant access rights for remote file copying. _Cfrun polls all your hosts serially and gives you a concatenated indexed list of problems on all hosts. The disadvantage with cfrun is that each host has to wait its turn._ * Don't forget to add `cfservd' to the system startup scripts, or to `inittab' so that it starts when you boot your system. * Add _all_ your hosts to the `cfrun.hosts' file. It does not matter that some may be master servers and others clients. The locking mechanisms will protect you from silliness, *Note Deadlocks and runaway loops::. Cfengine will work it out. Cfrun allows you to remotely execute cfengine on groups of hosts which satisfy a list of cfengine classes. When you have set up these components, you can sit back and edit the configuration files and watch things being done.  File: cfengine-Tutorial.info, Node: More advanced concepts, Next: Global configurations, Prev: Getting started, Up: Top 3 More advanced concepts ************************ * Menu: * Classes basics:: * Variable substitution:: * Undefined variables:: * Defining classes:: making decisions * The generic class any:: a wildcard * Debugging tips:: nullifying classes * Access control:: specifying user access to programs * Wildcards in directory names:: multiple searches * File sweeps:: * Security in File sweeps:: * Log files:: * Quoted strings:: * Regular expressions:: * Iterating over lists::  File: cfengine-Tutorial.info, Node: Classes basics, Next: Variable substitution, Prev: More advanced concepts, Up: More advanced concepts 3.1 Classes =========== The idea of classes is central to the operation of cfengine. Saying that cfengine is `class orientated' means that it doesn't make decisions using `if'...`then'...`else' constructions the way other languages do, but only carries out an action if the host running the program is in the same class as the action itself. To understand what this means, imagine sorting through a list of all the hosts at your site. Imagine also that you are looking for the _class_ of hosts which belong to the computing department, which run GNU/Linux operating system and which have yellow spots! To figure out whether a particular host satisfies all of these criteria you first delete all of the hosts which are not GNU/Linux, then you delete all of the remaining ones which don't belong to the computing department, then you delete all the remaining ones which don't have yellow spots. If you are on the remaining list, then you are in the class of all computer-science-Linux-yellow-spotted hosts and you can carry out the action. Cfengine works in this way, narrowing things down by asking if a host is in several classes at the same time. Although some information (like the kind of operating system you are running) can be obtained directly, clearly, to make this work we need to have lists of which hosts belong to the computer department and which ones have yellow spots. So how does this work in a cfengine program? A program or configuration script consists of a set of declarations for what we refer to as _actions_ which are to be carried out only for certain classes of host. Any host can execute a particular program, but only certain action are extracted -- namely those which refer to that particular host. This happens automatically because cfengine builds up a list of the classes to which it belongs as it goes along, so it avoids having to make many decisions over and over again. By defining classes which classify the hosts on your network in some easy to understand way, you can make a single action apply to many hosts in one go - i.e. just the hosts you need. You can make generic rules for specific type of operating system, you can group together clusters of workstations according to who will be using them and you can paint yellow spots on them - what ever works for you. A _cfengine action_ looks like this: ACTION-TYPE: COMPOUND-CLASS:: DECLARATION A single class can be one of several things: * The name of an operating system architecture e.g. `ultrix', `sun4' etc. This is referred to henceforth as a _hard class_. * The (unqualified) name of a particular host. If your system returns a fully qualified domain name for your host, cfagent truncates it so as to unqualify the name. * The name of a user-defined group of hosts. * A day of the week (in the form `Monday', `Tuesday', `Wednesday'...). * An hour of the day (in the form `Hr00', `Hr01', ... `Hr23'). * Minutes in the hour (in the form `Min00', `Min17', ... `Min45'). * A five minute interval in the hour (in the form `Min00_05', `Min05_10', ... `Min55_00') * A quart hour (in the form `Q1, Q2, Q3, Q4') * An abbreviated time with quarter hour specified (in the form `Hr00_Q1', `Hr23_Q4', etc.) * A day of the month (in the form `Day1 ... Day31'). * A month (in the form `January', `February', ... `December'). * A year (in the form `Yr1997', `Yr2001'). * An arbitrary user-defined string. (see the reference manual). * The ip-address octets of any active interface (in the form `ipv4_192_0_0_1', `ipv4_192_0_0', `ipv4_192_0,`ipv4_192''). A compound class is a sequence of simple classes connected by dots or `pipe' symbols (vertical bars). For example: myclass.sun4.Monday:: sun4|ultrix|osf:: A compound class evaluates to `true' if all of the individual classes are separately true, thus in the above example the actions which follow `compound_class::' are only carried out if the host concerned is in `myclass', is of type `sun4' and the day is Monday! In the second example, the host parsing the file must be either of type `sun4' _or_ `ultrix' _or_ `osf'. In other words, compound classes support two operators: AND and OR, written `.' and `|' respectively. From cfengine version 2.1.1, I bit the bullet and added `&' as a synonym for the AND operator. Cfengine doesn't care how many of these operators you use (since it skips over blank class names), so you could write either solaris|irix:: or solaris||irix:: depending on your taste. On the other hand, the order in which cfengine evaluates AND and OR operations _does_ matter, and the rule is that AND takes priority over OR, so that `.' binds classes together tightly and all AND operations are evaluated before ORing the final results together. This is the usual behaviour in programming languages. You can use round parentheses in cfengine classes to override these preferences. Cfengine allows you to define switch on and off dummy classes so that you can use them to select certain subsets of action. In particular, note that by defining your own classes, using them to make compound rules of this type, and then switching them on and off, you can also switch on and off the corresponding actions in a controlled way. The command line options `-D' and `-N' can be used for this purpose. See also `addclasses' in the Reference manual. A logical NOT operator has been added to allow you to exclude certain specific hosts in a more flexible way. The logical NOT operator is (as in C and C++) `!'. For instance, the following example would allow all hosts except for `myhost': ACTION: !myhost:: COMMAND and similarly, so allow all hosts in a user-defined group `mygroup', _except_ for `myhost', you would write ACTION: mygroup.!myhost:: COMMAND which reads `mygroup AND NOT myhost'. The NOT operator can also be combined with OR. For instance CLASS1|!CLASS2 would select hosts which were either in class 1, or those which were not in class 2. Finally, there is a number of reserved classes. The following are hard classes for various operating system architectures. They do not need to be defined because each host knows what operating system it is running. Thus the appropriate one of these will always be defined on each host. Similarly the day of the week is clearly not open to definition, unless you are running cfengine from outer space. The reserved classes are: ultrix, sun4, sun3, hpux, hpux10, aix, solaris, osf, irix4, irix, irix64 sco, freebsd, netbsd, openbsd, bsd4_3, newsos, solarisx86, aos, nextstep, bsdos, linux, debian, cray, unix_sv, GnU, NT If these classes are not sufficient to distinguish the hosts on your network, cfengine provides more specific classes which contain the name and release of the operating system. To find out what these look like for your systems you can run cfengine in `parse-only-verbose' mode: cfagent -p -v and these will be displayed. For example, Solaris 2.4 systems generate the additional classes `sunos_5_4' and `sunos_sun4m', `sunos_sun4m_5_4'. Cfengine uses both the unqualified and fully host names as classes. Some sites and operating systems use fully qualified names for their hosts. i.e. `uname -n' returns to full domain qualified hostname. This spoils the class matching algorithms for cfengine, so cfengine automatically truncates names which contain a dot `.' at the first `.' it encounters. If your hostnames contain dots (which do not refer to a domain name, then cfengine will be confused. The moral is: don't have dots in your host names! _NOTE: in order to ensure that the fully qualified name of the host becomes a class you must define the domain variable._ The dots in this string will be replaced by underscores. In summary, the operator ordering in cfengine classes is as follows: `()' Parentheses override everything. `!' The NOT operator binds tightest. `. &' The AND operator binds more tightly than OR. `|' OR is the weakest operator.  File: cfengine-Tutorial.info, Node: Variable substitution, Next: Undefined variables, Prev: Classes basics, Up: More advanced concepts 3.2 Variable substitution ========================= When you are building up a configuration file it is very useful to be able to use variables. If you can define your configuration in terms of some key variables, it can be changed more easily later, it is more transparent to the reader of the program and you can also choose to define the variables differently on different types of system. Another way of saying this is that cfengine variables also belong to classes. Cfengine makes use of variables in three ways. * Environment variables from the shell * Special variables used in cfengine features * General macro-string substitution. Environment variables are fetched directly from the shell on whatever system is running the program. An example of a special variable is the `domain' variable from the previous section. Straightforward macro substitution allows you to define a symbol name to be replaced by an arbitrary text string. All these definitions (apart from shell environment variables, of course) are made in the control part of the cfengine program: control: myvar = ( /usr/local/mydir/lib/very/long/path ) # define macro ... links: $(myvar) -> /another/directory Here we define a macro called `myvar', which is later used to define the creation of a link. As promised we can also define class-dependent variables: control: sun4:: myvar = ( sun ) hpux:: myvar = ( HP ) Cfagent gives you access to the shell environment variables and allows you to define variables of your own. It also keeps a few special variables which affect the way in which cfengine works. When cfengine expands a variable it looks first at the name in its list of special variables, then in the list of user-defined macros and finally in the shell environment for a match. If none of these are found it expands to the empty string. If you nest macros, control: myvar = ( "$(othervar)" ) then you must quote the right hand side and ensure that the value is already defined. You can also import values from the execution of a shell command by prefixing a command with the word `exec'. This method is deprecated in version 2 and replaced by a function. control: # old method listing = ( "exec /bin/ls -l" ) # new method listing = ( ExecResult(/bin/ls -l) ) This sets the variable `listing' to the output of the command in the quotes. Some other internal functions are `RandomInt(A,B)' Generate a random integer between a and b. `ExecResult(COMMAND)' Executes the named shell command and inserts the output into the variable. For example: control: variable2 = ( RandomInt(0,23) ) variable3 = ( ExecResult(/bin/ls -a /opt) ) Variables are referred to in either of two different ways, depending on your taste. You can use the forms `$(variable)' or `${variable}'. The variable in braces or parentheses can be the name of any user defined macro, environment variable or one of the following special internal variables. `AllClasses' A long string in the form `CFALLCLASSES=class1:class2...'. This variable is a summary of all the defined classes at any given time. It is always kept up to date so that scripts can make use of cfengine's class data. `arch' The current detailed architecture string--an amalgamation of the information from _uname_. Non-definable. `binserver' The default server for binary data. *Note NFS resources::. Non definable. `class' The currently defined system hard-class (e.g. `sun4', `hpux'). Non-definable. `date' The current date string. Note that if you use this in a shell command it might be interpreted as a list variable, since it contains the default separator `:'. `domain' The currently defined domain. `faculty' The faculty or site as defined in control (see site). `fqhost' The fully qualified (DNS/BIND) hostname of the system, which includes the domain name as well. `host' The hostname of the machine running the program. `ipaddress' The numerical form of the internet address of the host currently running cfengine. `MaxCfengines' The maximum number of cfengines which should be allowed to co-exist concurrently on the system. This can prevent excessive load due to unintentional spamming in situations where several cfagents are started independently. The default value is unlimited. `ostype' A short for of `$(arch)'. `OutputPrefix' This quoted string can be used to change the default `cfengine:' prefix on output lines to something else. You might wish to shorten the string, or have a different prefix for different hosts. The value in this variable is appended with the name of the host. The default is equivalent to, OutputPrefix = ( "cfengine:$(host):") `RepChar' The character value of the string used by the file repository in constructing unique filenames from path names. This is the character which replaces `/' (see the reference manual). `site' This variable is identical to `$(faculty)' and may be used interchangeably. `split' The character on which list variables are split (see the reference manual). `sysadm' The name or mail address of the system administrator. `timezone' The current timezone as defined in `control'. `UnderscoreClasses' If this is set to `on' cfengine uses hard-classes which begin with an underscore, so as to avoid name collisions. See also Runtime Options in the Reference manual. `year' The current year. These variables are kept special because they play a special role in setting up a system configuration. *Note Global configurations::. You are encouraged to use them to define fully generalized rules in your programs. Variables can be used to advantage in defining filenames, directory names and in passing arguments to shell commands. The judicious use of variables can reduce many definitions to a single one if you plan carefully. _NOTE: the above control variables are not case sensitive, unlike user macros, so you should not define your own macros with these names._ The following variables are also reserved and may be used to produce troublesome special characters in strings. `cr' Expands to the carriage-return character. `dblquote' Expands to a double quote `"' `dollar' Expands to `$'. `lf' Expands to a line-feed character (Unix end of line). `n' Expands to a newline character. `quote' Expands to a single quote `''. `spc' Expands simply to a single space. This can be used to place spaces in filenames etc. `tab' Expands to a single tab character. You can use variables in the following places: * In any directory name. The `$(binserver)' variable is not always appropriate in this context. For instance links: osf:: /$(site)/${host}/directory -> somefile * In any quoted string. (See `shellcommands' in the Reference manual). shellcommands: any:: "/bin/echo $(timezone) | /bin/mail $(sysadm)" '/bin/echo "double quotes!"' The latter possibility enables cfengine's variables to be passed on to user-defined scripts. * To define the values of options passed to various actions, in the form `OPTION=$(variable)'. Variables can be defined differently under different classes by preceding the definition with a class name. For example: control: sun4:: my_macro = ( User_string_1 ) irix:: my_macro = ( User_string_2 ) Here the value assigned to `$(my_macro)' depends on which of the classes evaluates to true. This feature can be used to good effect to define the mail address of a suitable system administrator for different groups of host. control: physics:: sysadm = ( mark,fred ) chemistry:: sysadm = ( localsys@domain ) Note, incidentally, that the `-a' option can be used to print out the mail address of the system administrator for any wrapper scripts.  File: cfengine-Tutorial.info, Node: Undefined variables, Next: Defining classes, Prev: Variable substitution, Up: More advanced concepts 3.3 Undefined variables ======================= Note that macro-variables which are undefined are not expanded as of version 1.6 of cfengine. In earlier versions, undefined variables would be replaced by an empty string, as in Perl. In versions 1.6.x and later, the variable string remains un-substituted, if the varaiable does not exist. For instance, control: actionsequence = ( shellcommands ) myvar = ( "test string " ) shellcommands: "/bin/echo $(myvar) $(myvar2)" results in: cfengine:host: Executing script /bin/echo test string $(myvar2) cfengine:host:/bin/echo test : sh: syntax error at line 1: `(' unexpected cfengine:host: Finished script /bin/echo test string $(myvar2) This allows variables to be defined on-the-fly by modules.  File: cfengine-Tutorial.info, Node: Defining classes, Next: The generic class any, Prev: Undefined variables, Up: More advanced concepts 3.4 Defining classes and making exceptions ========================================== Cfengine communicates with itself by passing messages in the form of classes. When a class becomes switched on or off, cfengine's program effectively becomes modified. There are several ways in which you can switch on and off classes. Learning these fully will take some time, and only then will you harness the full power of cfengine. * Classes may be defined manually from the command line. * Classes may be defined locally in the actionsequence in order to execute only some of the actions within a special category. * Classes may become defined if cfengine actually needs to carry out an action to repair the system's configuration. * Classes may be defined by user-defined plug-in modules. Because cfagent works at a very high level, doing very many things for very few lines of code it might seem that some flexibility is lost. When we restrict certain actions to special classes it is occasionally useful to be able to switch off classes temporarily so as to cancel the special actions. * Menu: * Command line classes:: * actionsequence classes:: * shellcommand classes:: * Feedback classes:: * Writing plugin modules::  File: cfengine-Tutorial.info, Node: Command line classes, Next: actionsequence classes, Prev: Defining classes, Up: Defining classes 3.4.1 Command line classes -------------------------- You can define classes of your own which can be switched on and off, either on the command line or from the action sequence. For example, suppose we define a class _include_. We use `addclasses' to do this. addclasses = ( include othersymbols ) The purpose of this would be to allow certain `excludable actions' to be defined. Actions defined by any.include:: ACTIONS will normally be carried out, because we have defined `include' to be true using `addclasses'. But if cfagent is run in a restricted mode, in which `include' is set to false, we can exclude these actions. So, by defining the symbol `include' to be false, you can exclude all of the actions which have `include' as a member. There are two ways in which this can be done, one is to negate a class globally using cfagent -N include This undefines the class `include' for the entire duration of the program.  File: cfengine-Tutorial.info, Node: actionsequence classes, Next: shellcommand classes, Prev: Command line classes, Up: Defining classes 3.4.2 actionsequence classes ---------------------------- Another way to specify actions is to use a class to select only a subset of all the actions defined in the actionsequence. You do this by adding a class name to one on the actions in action sequence by using a dot `.' to separate the words. In this case the symbol only evaluates to `true' for the duration of the action to which it attached. Here is an example: links.onlysome shellcommands.othersymbols.onlysome In the first case _`onlysome' is defined to be true_ while this instance of `links' is executed. That means that only actions labelled with the class `onlysome' will be executed as a result of that statement. In the latter case, both `onlysome' and `othersymbols' are defined to be true for the duration of `shellcommands'. This syntax would normally be used to omit certain time-consuming actions, such as tidying all home directories. Or perhaps to synchronize certain actions which have to happen in a certain order.  File: cfengine-Tutorial.info, Node: shellcommand classes, Next: Feedback classes, Prev: actionsequence classes, Up: Defining classes 3.4.3 shellcommand classes -------------------------- For more advanced uses of cfengine you might want to be able to define a class on the basis of the success or failure of a user-program, a shell command or user script. Consider the following example groups: have_cc = ( "/bin/test -f /usr/ucb/cc" "/bin/test -f /local/gnu/cc" ) Note that as of version 1.4.0 of cfengine, you may use the word `classes' as an alias for `groups'. Whenever cfagent meets an object in a class list or variable, which is surrounded by either single, double quotes or reversed quotes, it attempts to execute the string as a command passed to the Bourne shell. If the resulting command has return code zero (proper exit) then the class on the left hand side of the assignment (in this case `have_cc') will be true. If the command returns any other value (an error number) the result is false. Since groups are the logical OR of their members (it is sufficient that one of the members matches the current system), the class `have_cc' will be defined above if either `/usr/ucb/cc' or `/local/gnu/cc' exist, or both.  File: cfengine-Tutorial.info, Node: Feedback classes, Next: Writing plugin modules, Prev: shellcommand classes, Up: Defining classes 3.4.4 Feedback classes ---------------------- Classes may be defined as the result of actions being carried out by cfagent. For example, if a file gets copied, needs to be edited or if diskspace falls under a certain threshhold, cfagent can be made to respond by activating classes at runtime. This allows you to create dynamically responsive programs which react to the changing environment. These classes are defined as part of other statements with clauses of the form define=CLASSLIST Classes like these should generally be declared at the start of a program unless the `define' statements always precede the actions which use the defined classes, with `addinstallable'.  File: cfengine-Tutorial.info, Node: Writing plugin modules, Prev: Feedback classes, Up: Defining classes 3.4.5 Writing plugin modules ---------------------------- If the regular mechanisms for setting classes do not produce the results you require for your configuration, you can write your own routines to concoct the classes of your dreams. Plugin modules are added to cfagent programs from within the actionsequence, (see Reference manual). They allow you to write special code for answering questions which are too complex to answer using the other mechanisms above. This allows you to control classes which will be switched on and the moment at which your module attempts to evaluate the condition of the system. Modules must lie in a special directory defined by the variable `moduledirectory'. They must have a name of the form `module:MYMODULE' and they must follow a simple protocol. Cfagent will only execute a module which is owned either by root or the user who is running cfagent, if it lies in the special directory and has the special name. A plug-in module may be written in any language, it can return any output you like, but lines which begin with a `+' sign are treated as classes to be defined (like `-D'), while lines which begin with a `-' sign are treated as classes to be undefined (like `-N'). Lines starting with `=' are variables/macros to be defined. Any other lines of output are cited by cfagent, so you should normally make your module completely silent. Here is an example module written in perl. First we define the module in the cfagent program: control: moduledirectory = ( /local/cfagent/modules ) actionsequence = ( files module:myplugin "module:argplugin arg1 arg2" copy ) ... AddInstallables = ( specialclass ) Note that the class definitions for the module should also be defined in as `AddInstallables', if this is more convenient. NOTE: you _must_ declare the classes before using them in the cfagent configuration, or else those actions will be ignored. Next we write the plugin itself. #!/usr/bin/perl # # module:myplugin # # lots of computation.... if (SPECIAL-CONDITION) { print "+specialclass"; } Modules inherit the environment variables from cfagent and accept arguments, just as a regular shellcommand does. #!/bin/sh # # module:myplugin # /bin/echo $* Cfagent defines the classes as an environment variable so that programs have access to these. E.g. try the following module: #!/usr/bin/perl print "Decoding $ENV{CFALLCLASSES}\n"; @allclasses = split (":","$ENV{CFALLCLASSES}"); while ($c=shift(@allclasses)) { $classes{$c} = 1; print "$c is set\n"; } Modules can define macros in cfagent by outputting strings of the form =VARIABLENAME=VALUE When the `$(allclasses)' variable becomes too large to manipulate conveniently, you can access the complete list of currently defined classes in the file `/var/cfengine/state/allclasses'.  File: cfengine-Tutorial.info, Node: The generic class any, Next: Debugging tips, Prev: Defining classes, Up: More advanced concepts 3.5 The generic class `any' =========================== The generic wildcard `any' may be used to stand for any class. Thus instead of assigning actions for the class `sun4' only you might define actions for any architecture by specifying: any:: ACTIONS If you don't specify any class at all then cfengine assumes a default value of `any' for the class.  File: cfengine-Tutorial.info, Node: Debugging tips, Next: Access control, Prev: The generic class any, Up: More advanced concepts 3.6 Debugging tips ================== A useful trick when debugging is to eliminate unwanted actions by changing their class name. Since cfengine assumes that any class it does not understand is the name of some host, it will simply ignore entries it does not recognize. For example: myclass:: can be changed to Xmyclass:: Since `Xmyclass' no longer matches any defined classes, and is not the name of any host it will simply be ignored. The `-N' option can also be used to the same effect. (see Reference manual).  File: cfengine-Tutorial.info, Node: Access control, Next: Wildcards in directory names, Prev: Debugging tips, Up: More advanced concepts 3.7 Access control ================== It is sometimes convenient to be able to restrict the access of a program to a handful of users. This can be done by adding an access list to the `control:' section of your program. For example, control: ... access = ( mark root ) would cause cfengine to refuse to run the program for any other users except mark and root. Such a restriction would be useful, for instance, if you intended to make set-user-id scripts but only wished certain users to be able to run them. If the access list is absent, all users can execute the program. Note: if you are running cfagent via the `cfrun' program then cfagent is always started with the same user identity as the cfservd process on the remote host. Normally this is the root user identity. This means that the access keyword will have no effect on the use of the command `cfrun'.  File: cfengine-Tutorial.info, Node: Wildcards in directory names, Next: File sweeps, Prev: Access control, Up: More advanced concepts 3.8 Wildcards in directory names ================================ In the two actions `files' and `tidy' you define directory names at which file checking or tidying searches should start. One economical feature is that you can define a whole group of directories at which identical searches should start in one fell swoop by making use of _wildcards_. For example, the directory names /usr/*/* /bla/*/ab?/bla represent all of the _directories_ (and only directories) which match the above wildcard strings. Cfagent opens each matching directory and iterates the action over all directories which match. The symbol `?' matches any single character, whereas `*' matches any number of characters, in accordance with shell file-substitution wildcards. When this notation is used in directory names, it always defines the starting point for a search. It does not tell the command how to search, only where to begin. The `pattern' directive in `tidy' can be used to specify patterns when tidying files and under `files' all files are considered, (see Reference manual),  File: cfengine-Tutorial.info, Node: File sweeps, Next: Security in File sweeps, Prev: Wildcards in directory names, Up: More advanced concepts 3.9 Recursive file sweeps/directory traversals ============================================== File sweeps are searches through a directory tree in which many files are examined and considered for processing in some way. There are many instances where one uses cfagent to perform a file sweep. * As part of a `files' action, for checking access rights and ownership of files. * As part of a `tidy' action, for checking files for deletion. * As part of a `copy' action, while recursively checking whether to copy a file tree. * As part of an `editfiles' action, while recursively checking whether to edit the files in a tree of files. The problem with file sweeps is that they can be too sweeping! Often you are not interested in examining every single file in a file tree. You might wish to perform a search * excluding certain named directories and their subdirectories with `ignore'. * excluding certain files and directories matching a specific pattern. * including only a subset of files matching specific patterns. * filter out very specific file types. The tidy action is slightly different in this respect, since it already always expects to match a specific pattern. One is generally not interested in a search which deletes everything except for a named pattern: this would be too dangerous. For this reason, the syntax of `tidy' does not allow ignore, include and exclude. It is documented in the section on tidying, (see Reference manual). Items declared under the global `ignore' section affect files, copy, links and tidy. For file sweeps within files, copy and links, you may provide private ignore lists using `ignore='. The difference between exclude and ignore is that ignore can deal with absolute directories. It prunes directories, while exclude only looks at the files within directories. For file sweeps within `files' and `copy' you can specify specific search parameters using the keywords `include=' and `exclude=' and as of version 1.6.x `filter='. For example, files: /usr/local/bin m=0755 exclude=*.ps action=fixall In this example cfagent searches the entire file tree (omitting any directories listed in the ignore-list and omitting any files ending in the extension `.ps'), (see Reference manual). Specifying the `include=' keyword is slightly different since it automatically restricts the search to only named patterns (using `*' and `?' wildcards), whenever you have one or more instances of it. If you include patterns in this way, cfagent ignores any files which do not match the given patterns. It also ignores any patterns which you have specified in the global ignore-list as well as patterns excluded with `exclude=PATTERN'. In other words, exclusions always override inclusions. If you exclude a pattern or a directory and wish to treat it in some special way, you need to code an explicit check for that pattern as a separate entity. For example, to handle the exluded `.ps' files above, you would need to code something like this: files: /usr/local/bin m=0644 include=*.ps action=fixall Note: don't be tempted to enclose your wildcards in quotes. The quotes will be treated literally and the pattern might not match the way you would expect. For `editfiles' the syntax is somewhat different. Here one needs to add lines to the edit stanza: editfiles: { /tmp/testdir Include .* Exclude bla.* Ignore "." Ignore ".." Recurse 6 ReplaceAll "search" With "replace" }  File: cfengine-Tutorial.info, Node: Security in File sweeps, Next: Log files, Prev: File sweeps, Up: More advanced concepts 3.10 Security in Recursive file sweeps ====================================== Recursively descending into directories and performing a globally `destructive' change is an inherently risky thing to do, unless you are certain of the directory structure. Suppose, for instance, that a user with write access to the filesystem added a symbolic link to `/etc/passwd', and we were doing a recursive deletion. Suddenly, cfengine becomes a destructive weapon. The default behaviour is that cfengine does not follow symbolic links in recursive descents, for this reason. The option `travlinks' can be set to true, in order to change this. However, in general, you should never change this option, especially if untrusted users have access to parts of the filesystem, e.g. if you clear `/tmp' recursively. Cfagent checks for link race attacks, in which users try to swap a directory for a link, in between system calls, to trick cfagent into believing that a link is a directory, as of version 2.0.3 (and 1.6.4). Note that, even if `travlinks' is set to true, cfagent will not follow symbolic links that are not owned by the agent user ID; this is to minimize the possibilty of link race attacks, in which users with write access could divert the agent to another part of the filesystem.  File: cfengine-Tutorial.info, Node: Log files, Next: Quoted strings, Prev: Security in File sweeps, Up: More advanced concepts 3.11 Log files written by cfagent ================================= Cfagent keeps two kinds of log-file privately and it allows you to log its activity to syslog. Syslog logging may be switched on with the `Syslog' variable, (see Reference manual). The first log cfagent keeps is for every user (every subdirectory of a home directory filesystem). A file `~/.cfengine.rm' keeps a list of all the files which were deleted during the last pass of the `tidy' function. This is useful for users who want to know files have been removed without their blessing. This helps to identify what is happening on the system in case of accidents. Another file is built when cfagent searches through file trees in the `files' action. This is a list of all programs which are setuid root, or setgid root. Since such files are a potential security risk, cfagent always prints a warning when it encounters a new one (one which is not already in its list). This allows the system administrator to keep a watchful eye over new programs which appear and give users root access. The cfengine log is called `/var/cfengine/cfengine.log'. The file is not readable for general users.  File: cfengine-Tutorial.info, Node: Quoted strings, Next: Regular expressions, Prev: Log files, Up: More advanced concepts 3.12 Quoted strings =================== In several cfengine commands, you use quoted strings to define a quantity of text which may contain spaces. For example control: macro = ( "mycommand" ) editfiles: { $(HOME)/myfile AppendIfNoSuchLine 'This text contains space' } In each case you may use any one of the three types of quote marks in order to delimit strings, ' OR " OR ` If you choose, say `"', then you may not use this symbol within the string itself. The same goes for the other types of string delimiters. Unlike the shell, cfengine treats these three delimiters in precisely the same way. There is no difference between them. If you need to quote a quoted string, then you should choose a delimiter which does not conflict with the substring before version 2.0.7. From version 2.0.7, you can escape quotes. qstring = ( "One string\"with substring\" escaped" ) Note that you can use special variables for certain symbols in a string *Note Variable substitution::.  File: cfengine-Tutorial.info, Node: Regular expressions, Next: Iterating over lists, Prev: Quoted strings, Up: More advanced concepts 3.13 Regular expressions ======================== Regular expressions can be used in cfagent in connection with `editfiles' and `processes' to search for lines matching certain expressions. A regular expression is a generalized wildcard. In cfagent wildcards, you can use the characters '*' and '?' to match any character or number of characters. Regular expressions are more complicated than wildcards, but have far more flexibility. _NOTE: the special characters `*' and `?' used in wildcards do not have the same meanings as regular expressions!_. Some regular expressions match only a single string. For example, every string which contains no special characters is a regular expression which matches only a string identical to itself. Thus the regular expression `cfengine' would match only the string "cfengine", not "Cfengine" or "cfengin" etc. Other regular expressions could match more general strings. For instance, the regular expression `c*' matches any number of c's (including none). Thus this expression would match the empty string, "c", "cccc", "ccccccccc", but not "cccx". Here is a list of regular expression special characters and operators. `\' The backslash character normally has a special purpose: either to introduce a special command, or to tell the expression interpreter that the next character is not to be treated as a special character. The backslash character stands for itself only when protected by square brackets `[\]' or quoted with a backslash itself `\\'. `\b' Matches word boundary operator. `\B' Match within a word (operator). `\<' Match beginning of word. `\>' Match end of word. `\w' Match a character which can be part of a word. `\W' Match a character which cannot be part of a word. `ANY CHARACTER' Matches itself. `.' Matches any character `*' Match zero or more instances of the previous object. e.g. `c*'. If no object precedes it, it represents a literal asterisk. `+' Match one or more instances of the preceding object. `?' Match zero or one instance of the preceding object. `{ }' Number of matches operator. `{5}' would match exactly 5 instances of the previous object. `{6,}' would match at least 6 instances of the previous object. `{7,12}' would match at least 7 instances of, but no more than 12 instances of the preceding object. Clearly the first number must be less than the second to make a valid search expression. `|' The logical OR operator, OR's any two regular expressions. `[LIST]' Defines a list of characters which are to be considered as a single object (ORed). e.g. `[a-z]' matches any character in the range a to z, `abcd' matches either a, b, c or d. Most characters are ordinary inside a list, but there are some exceptions: `]' ends the list unless it is the first item, `\' quotes the next character, `[:' and `:]' define a character class operator (see below), and `-' represents a range of characters unless it is the first or last character in the list. `[^LIST]' Defines a list of characters which are NOT to be matched. i.e. match any character except those in the list. ``[:CLASS:]'' Defines a class of characters, using the ctype-library. `alnum' Alpha numeric character `alpha' An alphabetic character `blank' A space or a TAB `cntrl' A control character. `digit' 0-9 `graph' same as print, without space `lower' a lower case letter `print' printable characters (non control characters) `punct' neither control nor alphanumeric symbols `space' space, carriage return, line-feed, vertical tab and form-feed. `upper' upper case letter `xdigit' a hexadecimal digit 0-9, a-f ``( )'' Groups together any number of operators. `\DIGIT' Back-reference operator (refer to the GNU regex documentation). `^' Match start of a line. `$' Match the end of a line. Here is a few examples. Remember that some commands look for a regular expression match of part of a string, while others require a match of the entire string (see Reference manual). ^# match string beginning with the # symbol ^[^#] match string not beginning with the # symbol ^[A-Z].+ match a string beginning with an uppercase letter followed by at least one other character  File: cfengine-Tutorial.info, Node: Iterating over lists, Prev: Regular expressions, Up: More advanced concepts 3.14 Iterating over lists ========================= Shell list variables are normally defined by joining together a list of directories using a concatenation character such as `:'. A typical example of this is the PATH variable: PATH=/usr/bin:/usr/local/bin:/usr/sbin It is convenient to be able to use such variables to force cfagent to iterative over a list. This gives us a compact way of writing repeated operations and it allows a simple method of communication with the shell environment. For security reasons, iteration is supported only in the following contexts: * in the `to' field of a multiple link action, * in the `from' field of a copy action, * in the directory field of a tidy action, * in the directory field of the files action, * in the ignore action, * in a shell command. This typically allows communication with PATH-like environment variables in the shell. In these contexts, any variable which has the form of a list joined together by colons will be iterated over at compilation time. Note that you can change the value of the list separator using the `Split' variable in the control section of the program (see Reference manual). For example, to link all of the binary files in the PATH environment variable to a single directory, tidying dead links in the process, you would write control: actionsequence = ( links tidy ) links: /allbin +> $(PATH) tidy: # Hopefully no-match matches nothing /allbin pattern=no-match age=0 links=tidy NO-MATCH is not a reserved word in cfengine, this is just a string you do not expect to match any file. Alternatively, you might want to define an internal list using a space as a separator: control: Split = ( " " ) mylist = ( "mark ricky bad-dude" ) tidy: /mnt/home1/$(mylist) pattern=*.cfsaved age=1 This example iterates the tidy action over the directories `/mnt/home1/mark', `/mnt/home1/ricky' and `/mnt/home1/bad-dude'. The number of list variables in any path or filename should normally be restricted to one or two, since the haphazard combination of two lists will seldom lead to any meaningful pattern. The only obvious exception is perhaps to iterate over a common set of child-directories like `bin', `lib' etc in several different package directories.  File: cfengine-Tutorial.info, Node: Global configurations, Next: Using cfengine as a front-end for cron, Prev: More advanced concepts, Up: Top 4 Designing a global system configuration ***************************************** This chapter is about building strategies for putting together a site configuration for your entire network. * Menu: * General considerations:: * Using netgroups:: a common database for classes * Files and links:: * Copying files:: * Managing processes:: * NFS resources:: the cfengine model * Using the automounter:: * Editing files:: * Disabling and the file repository:: * Running user scripts:: * Compressing logs:: * ACLs::  File: cfengine-Tutorial.info, Node: General considerations, Next: Using netgroups, Prev: Global configurations, Up: Global configurations 4.1 General considerations ========================== In order to use any system administration tool successfully, you have to make peace with your system by deciding exactly what you expect and what you are willing to do to achieve the results. You need to decide what you will consider to be acceptable and what is to be considered completely untenable. You need to make these decisions because otherwise you will only be confused later when things don't go the way you expected. Experience shows that the most successful policies for automation involve keeping everything as simple as possible. The more uniform or alike your machines are, the easier they are to run and the happier users are. Sometimes people claim that they need such great flexibility that all their machines should be different. This belief tends to be inversely proportional to the number of machines they run and generally only applies to very special development environments! Usually you will only need one or two machines to be special and most can be made very similar. Site configuration is about sharing and controlling resources. The resources include disks (filespace), files, data, programs, passwords and physical machines. Before planning your sitewide configuration you should spend some time deciding how you would like things to work. In the remaining parts of this chapter, you will find some hints and tips about how to proceed, but remember that when push comes to shove, you must make your own choices.  File: cfengine-Tutorial.info, Node: Using netgroups, Next: Files and links, Prev: General considerations, Up: Global configurations 4.2 Using netgroups =================== If you use the network information service (NIS) on your local network then you may already have defined _netgroups_ consisting of lists of hosts which belong to specific owners at your site. If you have, then you can use these groups within cfengine. This means that you can use the same groups in the `/etc/exports' file as you use to define the mount groups and classes. A netgroup is a list of hostnames or user names which are registered in the network information service (NIS) database under a specific name. In our case we shall only be interested in lists of hostnames. To make a netgroup you need to define a list in the file `/etc/netgroup' on your NIS server. If you are not the NIS administrator, you will have to ask to have a netgroup installed. The form of a netgroup list of hosts is: mylist-name (host1,,) (host2,,) (host3,,) (host4,,) norway-sun4-host (saga,,) (tor,,) (odin,,) foes-linux-hosts (borg,,) Each list item has three entries, but only the first is relevant for a host list. See the manual pages on netgroups for a full explanation of the meaning of these fields. The usefulness of netgroups is that they can be used to stand for a list of hostnames in system files like `/etc/exports'. This compresses the amount of text in this file from a long list to a single name. It also means that if you use the same list of hosts from a netgroup inside cfengine when defining groups and classes, you can be sure that you are always using the same list. In particular it means that you don't have to update multiple copies of a list of hosts. The netgroups can now be used in cfengine programs by using the `+' or `@+' symbols in the `groups' section. (see Reference manual).  File: cfengine-Tutorial.info, Node: Files and links, Next: Copying files, Prev: Using netgroups, Up: Global configurations 4.3 Files and links =================== File and link management takes several forms. Actions are divided into three categories called `files', `tidy' and `links'. The first of these is used to check the existence of, the ownership and permissions of files. The second concerns the systematic deletion of garbage files. The third is a link manager which tests, makes and destroys links. The monitoring of file access bits and ownership can be set up for individual files and for directory trees, with controlled recursion. Files which do not meet the specified criteria can be `fixed' --i.e. automatically set to the correct permissions, or can simply be brought to the attention of the system administrator by a warning. The syntax of such a command is as follows: files: CLASS:: /PATH mode=MODE owner=OWNER group=GROUP recurse=NO-OF-LEVELS action=ACTION The directory or file name is the point at which cfagent begins looking for files. From this point the search for files proceeds recursively into subdirectories with a maximum limit set by the `recurse' directive, and various options for dealing with symbolic links and device boundaries. The mode-string defines the allowed file-mode (by analogy with `chmod') and the owner and group may specify lists of acceptable user-ids and group-ids. The action taken in response to a file which does not meet acceptable criteria is specified in the action directive. It includes warning about or directly fixing all files, or plain files or directories only. Safe defaults exist for these directives so that in practice they may be treated as options. For example, files: any:: /usr/*/bin mode=a+rx,o-w own=root r=inf act=fixall which (in abbreviated form) would check recursively all files and directories starting from directories matching the wildcard (e.g. `/usr/local/bin', `/usr/ucb/bin'). By default, `fixall' causes the permissions and ownership of the files to be fixed without further warning. One problem with symbolic links is that the files they point to can get deleted leaving a `hanging pointer'. Since cfagent can make many hundreds of links without any effort, there is the danger that, in time, the system could become full of links which don't point anywhere. To combat this problem, you can set the option `links=tidy' in the files section. If this is set, cfagent will remove any symbolic links which do not point to existing files (see Reference manual). The creation of symbolic links is illustrated in figure 1 and the checking algorithm was discussed in section 2. In addition to the creation of single links, one may also specify the creation of multiple links with a single command. The command links: binaryhost:: /local/elm/bin +> /local/bin links all of the files in `/local/elm/bin' to corresponding files in `/local/bin'. This provides, amongst other things, one simple way of installing software packages in regular `bin' directories without controlling users' PATH variable. A further facility makes use of cfagent's knowledge of available (mounted) binary resources to search for matches to specific links. Readers are referred to the full documentation concerning this feature. The need to tidy junk files has become increasingly evident during the history of cfengine. Files build up quickly in areas like `/tmp', `/var/tmp'. Many users use these areas for receiving large ftp-files so that their disk usage will not be noticed! To give another example, just in the last few months the arrival of netscape World Wide Web client, with its caching facilities, has flooded hard-disks at Oslo with hundreds of megabytes of WWW files. In addition the regular appearance of `core' files(1) and compilation by-products (`.o' files and `.log' files etc.) fills disks with large files which many users do not understand. The problem is easily remedied by a few lines in the cfagent configuration. Files can be deleted if they have not been accessed for n-days. Recursive searches are both possible and highly practical here. In following example: tidy: AllHomeServers:: home pattern=core r=inf age=0 home/.wastebasket pattern=* r=inf age=14 home/.netscape-cache pattern=cache????* r=inf age=2 home/.MCOM-cache pattern=cache????* r=inf age=2 home/.netscape pattern=cache????* r=inf age=2 all hosts in the group `AllHomeServers' are instructed to iterate over all users' home directories (using the wildcard `home') and look for files matching special patterns. Cfagent tests the _access time_ of files and deletes only files older than the specified limits. Hence all core files, in this example, are deleted immediately, whereas files in the subdirectory `.wastebasket' are deleted only after they have lain there untouched for 14 days, and so on. As a system administrator you should, of course, exercise great caution when making rules which can delete users' files. A single slip of the hand can result in a rule which will irretrievably delete files. When making a `tidy' strategy you should probably coordinate with your backup policy. You should not delete files until after you have taken a backup, so that -- if the worst should happen -- you are covered against possible accidents. Cfagent helps to some extent to keep track of what files it deletes. When tidying users' home directories it creates a log file of all files which were deleted on the last tidy operation. This log is called `~/.cfengine.rm'. You might consider tidying certain files only once a week, in which case a command such as tidy: AllHomeServers.Sunday:: FILES TO TIDY could be useful. Nonsense files, such as `core' files could be tidied every night. _NOTE! Be careful when telling cfagent to delete core files. If you write a wildcard like `core*', then you could risk deleting important system files such as `core.h'._ ---------- Footnotes ---------- (1) On some systems, core dumps cannot be switched off!  File: cfengine-Tutorial.info, Node: Copying files, Next: Managing processes, Prev: Files and links, Up: Global configurations 4.4 Copying files ================= The administration of a system often requires the copying of files. The reason for this is usually that we would like to distribute a copy of a particular file, from some master location and ensure that all of the copies are up to date. Another use for this is to install software from one directory (perhaps on a CD ROM) to another. Cfagent helps this process by allowing you to copy a single file or a file tree, from one directory to another, perhaps checking the permissions and owners of a file to adjust the copies in some special way. The files are checked by cfagent using one of two methods. * A date-stamp comparison with a master file, using last-change times, can be used to tell cfagent to recopy a file from the master if the master file is newer than the copy. * A checksum can be computed for each file and compared with one for the master file. If the contents of the copy file differs in any way from the master, the file will be re-copied. Cfengine allows you to do the following * Copy a single file to another file in a different location, perhaps with a new name, new permissions and a different owner. * Copy a single file to all users on the system, changing the owner of the file for each user automatically. (This could be used to distribute and update standard setup files.) * Recursively copy an entire file tree, omitting files which match a list of wildcard-patterns, or linking certain files instead of copying. You can find out more about copying in the reference section.  File: cfengine-Tutorial.info, Node: Managing processes, Next: NFS resources, Prev: Copying files, Up: Global configurations 4.5 Managing processes ====================== Cfagent allows you to check for the existence of processes on your system, send those processes signals (such as kill) and perhaps restart those processes. Typical applications for this are sending `cron' and `inetd' the HUP signal, after editing their configuration files, or killing unwanted processes (such as user programs which hog the system at peak usage times). You can read more about this in the reference section .  File: cfengine-Tutorial.info, Node: NFS resources, Next: Using the automounter, Prev: Managing processes, Up: Global configurations 4.6 Cfengine's model for NFS-mounted filesystems ================================================ Most of the filesystems that you will want to make available across the network are going to fall into one of two categories. In cfengine parlance these are called _home directories_ and _binary directories_. A home directory is a place where users' login directories are kept. This is traditionally a directory called `/home' or `/users' or some subdirectory of these. A binary directory is a place where compiled software is kept. Such files (which do not belong to the pure operating system release) are often placed in a directory called `/usr/local' or simply `/local'. In this chapter we shall consider a scheme for using cfengine to make NFS filesystem management quite painless. * Menu: * NFS filesystem resources:: a conceptual introduction * Unique filesystem mountpoints:: avoiding collisions * How does it work?:: * Special variables:: binserver etc. * Mount example:: example program  File: cfengine-Tutorial.info, Node: NFS filesystem resources, Next: Unique filesystem mountpoints, Prev: NFS resources, Up: NFS resources 4.6.1 NFS filesystem resources ------------------------------ Using the Network File System (NFS) in a large workstation environment requires a bit of planning. The idea of NFS is to share files on one host with other hosts. In most cases, filesystems to be shared across the network fall into two categories: _binary_ filesystems (those which contain compiled software) and _user_ or _home_ filesystems (which contain users' login areas). The most simple minded way to share resources would be to mount every resource (each available NFS filesystem) onto every host. To avoid collisions, each filesystem would have to have a unique name. This is one possibility, but not a very intelligent one. As experienced users will realize, cross-mounting too many NFS filesystems is a recipe for all kinds of trouble. Cfengine offers a simple model which can help you pick out only the resources you need from the list of NFS filesystems. It will then mount them automatically and edit the appropriate filesystem tables. It does this by defining classes of hosts. For instance -- you really don't need to mount a binary filesystem for an `ultrix' system onto an `HPUX' system. There would be no point -- binary resources are _architecture_ or _hard-class dependent_. But home directories are architecture independent. Cfengine lets you to define a list of allowed servers for various hosts so that only filesystems from the servers will be considered for mounting!  File: cfengine-Tutorial.info, Node: Unique filesystem mountpoints, Next: How does it work?, Prev: NFS filesystem resources, Up: NFS resources 4.6.2 Unique filesystem mountpoints ----------------------------------- The first step towards treating NFS filesystems as network resources is to invent a naming scheme so that every filesystem has a unique name on which it can be mounted. If we don't sort this out now, we could find two or more hosts with a filesystem called `/usr/local', both of which we might like to mount since they contain different software. A simple but extremely useful naming scheme is the following. (1) If you don't like this scheme you can invent your own, but the remainder of the text will encourage you to use this one. If you follow this scheme, exactly as described here, you will never have any problems with mount points. We shall describe the scheme in detail below. Here are some points to digest: * When mounting a remote filesystem on your local system, the local and remote directories should always have exactly the same name. * The name of every filesystem mountpoint should be unique and tell you something meaningful about where it is located and what its function is. * You can always make links from special unique names to more general names like `/usr/local'. If you this involves compiled software and you do this on one host, you should do it on others which are of the same type. * It doesn't matter whether software compiles in the path names of special directories into software as long as you follow the points above. Each filesystem is given a directory name composed of three parts: /site/host/contents The first directory (which only exists to create a suitable mountpoint) is the name of your local site. If you are a physics department at a university (with a separate setup) you could call this `physics'. It could be your company name or whatever. The second piece is the name of the host to which the disk space is physically attached. The final piece is the name of the filesystem. Here are some typical examples: /physics/einstein/local # /usr/local for einstein@physics /physics/newton/u1 # user partition 1 for newton@physics On the machines which are home to the `local' partition, it is better to make a link to `/usr/local' than call the filesystem `/usr/local' directly. This is because it makes the procedure of organizing the entire network much clearer. It is worth noting that, when you ask cfagent to mount such a resource, it will automatically make the mount directory and can easily be asked to make a link to `/usr/local', so this small amount of extra work is really no work at all. The whole naming convention is compactly summarized by defining a mount point variable, `mountpattern'. With the present scheme, this can be defined as mountpattern = ( /$(site)/$(host) ) so that it evaluates to the name of the host executing the file regardless of who that may be. This variable is used together with the `homepattern' pattern variable, which is used to distinguish between home directories and binary resources. (See `homepattern' in the reference section). You can think of this as being part of the naming convention. In this text, we use the convention `u1 u2 u3...' for home disks. You could equally well use `home1 home2...' etc. As long as the name is unique, it doesn't matter. The full list of named resources should now be listed in the `mountables' list, which is simply a list of all the resources available for mounting on the network. ---------- Footnotes ---------- (1) This unique naming scheme was suggested to me originally by Knut Borge at USIT of the University of Oslo.  File: cfengine-Tutorial.info, Node: How does it work?, Next: Special variables, Prev: Unique filesystem mountpoints, Up: NFS resources 4.6.3 How does it work? ----------------------- Once you have defined your unique names, how does cfagent know what to mount? The idea is now to define a list of servers for each class of hosts. Suppose we make a `binserver' declaration: binservers: mygroup.sun4:: einstein newton This would tell cfagent that it should mount all binary resources from hosts `einstein' or `newton' onto any host of type `sun4' in the group `mygroup'. Every filesystem which is listed in `mountables' and is not a home directory will be mounted. Home directories and binary resources are kept separate automatically by cfagent, because a home directory is one whose contents-name matches the `homepattern' pattern variable. *Note Unique filesystem mountpoints::. A `homeserver' declaration: homeservers: mygroup:: einstein newton schwinger feynman would correspondingly mean mount all the home directory resources on the hosts in the list on all hosts in the group `mygroup'. Clearly it is unnecessary to distinguish between the architecture platform types of the actual servers for user directories. In each case, cfagent will mount filesystems, make the appropriate directories for the mount point and edit the filesystem table.  File: cfengine-Tutorial.info, Node: Special variables, Next: Mount example, Prev: How does it work?, Up: NFS resources 4.6.4 Special variables ----------------------- Once you have mounted a resource on a unique directory, you have access to all of the relevant filesystems on your network -- but you really wanted the `local' filesystem to be mounted on `/usr/local'. All you need do now is to make a link: links: any:: /usr/local -> /$(site)/$(binserver)/local The meaning of this is that, on any host, the directory `/usr/local' should be a link to the `nearest' binary server's `local' resource. The `$(binserver)' variable can in principle expand to any binary server in the list. In practice, cfagent goes through the list in order and picks the first filesystem resource which matches. Could this lead to a collision? Suppose we are on the host `einstein' and we execute the above command. The host `einstein' has a filesystem `/physics/einstein/local' on its local disk -- it is in fact the binary server for the network, so it certainly doesn't need to mount any NFS filesystems. But this is no problem because cfagent automatically treats `$(host)' as the highest priority binary server for any host. That means that if you have a local filesystem, it will always have priority. In contrast, if the host `schwinger' ran the command above, it would find no local filesystem called `/physics/schwinger/local', so it would go along the list of defined binary servers, find `einstein' and try again. It will succeed in finding `einstein' _provided all the binary servers were mounted before the link command is executed_. This means that you should structure the `actionsequence' so that all filesystems are mounted before any links are made. With a little practice, the cfengine model can lead to an enormous simplification of the issue of NFS-mountable resources. NOTE: cfengine does not try to export filesystems, only mount already exported filesystems. If you want to automate this procedure also, you can use the `editfiles' facility to add entries to `/etc/exports' (see `editfiles' in the Reference manual). In practice this is very difficult to do and perhaps not desirable.  File: cfengine-Tutorial.info, Node: Mount example, Prev: Special variables, Up: NFS resources 4.6.5 Example programs for mounting resources --------------------------------------------- Let's write a very simple configuration for a network with only one server called hal, where all the hosts are of the same operating system type. In such an example we can avoid using classes altogether. control: site = ( univ ) domain = ( univ.edu ) actionsequence = ( mountall mountinfo addmounts mountall links ) mountpattern = ( /univ ) homepattern = ( home? ) binservers: hal homeservers: hal mailserver: hal:/var/spool/mail mountables: hal:/univ/home1 hal:/univ/home2 hal:/univ/local links: /usr/local -> /univ/local In this example, we have only one type of host so the configuration is the same for each of them: no class references are required. If we look through the action sequence we see that the program first mounts all the filesystems which are already defined on each host. It does this to be sure that everything which is already set up to be mounted is mounted. Let's assume that there are no problems with this. The next thing that happens is that `mountinfo' builds a list of the filesystems which each host has successfully mounted. Then by calling `addmounts' we ask cfagent to check whether the host is missing any filesystems. What happens is that cfagent first looks to see what servers are defined for each host. In this case all hosts on the network have only one server: hal. Hal is defined as a server for both binary data and `home' data -- i.e. users' home directories. The list `mountables' tells cfagent what filesystems are available over the network for the server hal. There are three filesystems which can be mounted, called `/univ/home1', `/univ/home2' and `/univ/local'. Cfagent checks to see whether each of these filesystems is mounted and, if not, it builds the necessary directories, edits the necessary files and mounts the filesystems. Finally we come to `links' in the action sequence. This tells cfagent to look at the defined links. There is one link defined: a link from `/usr/local' to the mounted filesystem `/univ/local'. Cfagent checks and tries to make the link if necessary. If all goes well, each host on the network should now have at least three filesystems mounted and a link from `/usr/local' to `/univ/local'. Here is another simple example program for checking and automatically mounting an NFS based `/usr/local' and all home directories onto all hosts on a small network. Here we have several servers and must therefore use some classes. # # Mounts # control: site = ( mysite ) domain = ( mysite.country ) sysadm = ( mark ) netmask = ( 255.255.255.0 ) actionsequence = ( mountall mountinfo addmounts mountall links ) mountpattern = ( /$(site)/$(host) ) homepattern = ( u? ) # u1 u2 u3 etc.. groups: MyGroup = ( host1 host2 binserver1 binserver2 ) ###################################################################### homeservers: MyGroup:: host1 binservers: MyGroup.sun4:: server1 MyGroup.ultrix:: server2 mailserver: host1:/usr/spool/mail mountables: host1:/mysite/host1/u1 host1:/mysite/host1/u2 server1:/mysite/server1/local server2:/mysite/server2/local ########################################################################## links: /usr/local -> /${site}/${binserver}/local Let's suppose we run this program on host2 which is an ultrix machine. This host belongs to the class `mygroup' and the hard-class `ultrix'. This tells us that its homeserver is host1, its binary server is server2 and its mailserver is host1. Moreover, since the homepattern matches any filesystem ending in u-something, it recognizes the two home directories in the mountables list -- and therefore the two binary directories also. The action sequence starts by mounting all of the filesystems currently in the filesystem table `/etc/fstab'. It then scans the list of mounted filesystems to find out what is actually mounted. Since the homeserver is host1, we know that our host has to mount all home-filesystems from this server, so it checks for `host1:/mysite/host1/u1' and `host1:/mysite/host1/u2'. If they are not present they are added to `/etc/fstab'(1). Next, we know that the binary server is server1, so we should check for `server1:/mysite/server1/local'. The mail server is also checked for and added if necessary. Cfagent then tries to mount all filesystems once again, so that the new filesystems should be added. Note that, in the process of adding the filesystems to `/etc/fstab', cfagent creates the directories up to and including the point at which the filesystems should be mounted. If something prevents this -- if we try to mount on top of a plain file for instance -- then this will result in an error. Finally, we reach the link section and we try to expand the variables. `$(site)' expands to `mysite'. `$(binserver)' expands first to the hostname (host2), but `/mysite/host2/local' does not exist, so it then goes to the binserver list, which substitutes server1 for the value of `$(binserver)'. Since `/mysite/server1/local' does exist and is now mounted, cfagent makes a link to this directory from `/usr/local'. The script is then completed. If the script is run again, everything should now be in place so nothing happens. If for some reason it failed the first time, it will fail again. At any rate it will either do the job once and for all or signal an error which must be corrected by human intervention(2). ---------- Footnotes ---------- (1) Note: if the filesystem was in the fstab but not actually mounted a warning is issued telling you that the filesystem was probably not exported correctly on host1. (2) One possibility is that an NFS filesystem cannot be mounted because the host serving the filesystem is out of service. If this is the case then a subsequent re-run when the server resumes normal service will succeed.  File: cfengine-Tutorial.info, Node: Using the automounter, Next: Editing files, Prev: NFS resources, Up: Global configurations 4.7 Using the automounter ========================= The automounter is a daemon based service which replaces static mounting of NFS filesystems with a dynamical model. When the automounter is running, filesystems are mounted only when a user tries to access a file which resides on one of those filesystem. After a given period (usually five minutes) any filesystem which has not been accessed is unmounted. The advantage of this scenario is that hanging servers do not affect the behaviour of hosts which mount their filesystems, unless a specific file is being accessed. In both cases, filesystems must be exported in order to be mountable. It is not the purpose of this section to explain the use of the automounter in detail, only to offer hints as to how cfengine can be used to simplify and rationalize automount configuration for the already initiated. Let us begin by comparing the behaviour of the automounter with the cfengine model for mounted filesystems. The automounter is designed to be used together with a global configuration file, distributed by NIS (the network information service). As such, all hosts read the same configuration file. This makes it appear as though all hosts end up mounting every filesystem in the automount configuration database, but this is not so in practice because filesystems are only mounted if required. Thus a system which does not require a filesystem will not attempt to mount it. Moreover, the existence of a global configuration file does not affect which hosts have the right to mount certain filesystems (which is specified by exports or share on the relevant server), thus a request to mount a non-exported filesystem will result in an access denial. The automounter is configured locally on each host in files named `/etc/auto_master', `auto_direct' etc. In the cfengine static mounting scheme, you define a list of binary and home servers. The filesystem table is modified on the basis of these decisions, and filesystems are only added if cfagent deems it appropriate to mount them on a given host. The idea here is to minimize the number of filesystems mounted to those which are known to be required. Again the issue of access permissions must be arranged separately. These filesystems are placed directly in `/etc/fstab', or the equivalent for your system. From cfengine, you can use the automounter instead of the static mount model by * omitting `addmounts', `mountinfo', `mountall' from the actionsequence, in the control part of your cfengine program, * using `editfiles' to edit the relevant configuration files such as `/etc/auto_master', or `auto_direct' etc, * using the `AutomountDirectResources' command in editfiles to dump the list of cfengine class-based list of mountables into a file of your choice in the correct format for autmount's direct maps, * using `processes' to restart the automounter (send the hangup signal `hup'), or perhaps stop and restart the daemon by sending the `term' signal (you should never send the `kill' signal). * using the multiple link facilities to link in indirect mounted filesystems as required, and `files' or `tidy' to clean up stale links afterwards, * perhaps using `copy' to distribute basic automount configuration files to multiple systems. The automounter was created to solve certain problems which cfengine now solves (in the author's opinion) better. For example, the use of the `hosts' map in the automounter mounts filesystems like `/usr/local' on different (uniquely named) mountpoints for each host in order to avoid name space collisions. Using cfengine and a unique naming scheme, you can achieve the same thing more cleanly, without all of the gratuitous linking and unlinking which the automounter performs by itself. Moreover, the idea of a unique name-space is better practice and more in keeping with new global filesystem ideas such as AFS and DFS. The only advantage of the automounter is that one avoids the annoying error messages from hung servers about "NFS server not responding". In that respect, it seems sensible to use only direct mounts and a unique name space. Some systems advocate grouping all users' login (home) directories under a common directory called `/home' or `users'. The automounter goes through all manner of contortions to achieve this task. If you use a unique naming scheme like the one advocated here, this is a trivial task. You simply arrange to mount or automount all user directories, such as /SITE/HOST/home1 /SITE/HOST/home2 ... and then link them as follows: /home +> /SITE/HOST/home1 /home +> /SITE/HOST/home2 ... Finally, you should be aware that the automounter does not like to be mixed with static mount and unmount operations. Automounted filesystems take priority over statically mounted filesystems, but the automounter can be confused by manually mounting or unmounting filesystems while it is running.  File: cfengine-Tutorial.info, Node: Editing files, Next: Disabling and the file repository, Prev: Using the automounter, Up: Global configurations 4.8 Editing Files ================= A very convenient characteristic of BSD and UNIX System V systems is that they are configured primarily by human-readable textfiles. This makes it easy for humans to configure the system and it also simplifies the automation of the procedure. Most configuration files are line-based text files, a fact which explains the popularity of, for example, the Perl programming language. Cfengine does not attempt to compete with Perl or its peers. Its internal editing functions operate at a higher level which are designed for transparency rather than flexibility. Fortunately most editing operations involve appending a few lines to a file, commenting out certain lines or deleting lines. For example, some administrators consider the finger service to be a threat to security and want to disable it. This could be done as follows. editfiles: { /etc/inetd.conf HashCommentLinesContaining "finger" } Commands containing the word `Comment' are used to `comment out' certain lines from a text-file--i.e. render a line impotent without actually deleting it. Three types of comment were supported originally: shell style (hash) `#', `%' as used in TeX and on AIX systems, and C++-style `//'. A more flexible way of commenting is also possible, using directives which first define strings which signify the start of a comment and the end of a comment. A single command can then be used to render a comment. The default values of the comment-start string is `# ' and the default comment-end string is the empty string. For instance, to define C style comments you could write: { FILE SetCommentStart "/* " SetCommentEnd " */" # Comment out all lines containing printf! CommentLinesMatching ".*printf.*" } Other applications for these editing commands include monitoring and controlling root-access to hosts by editing files such as `.rhosts' and setting up standard environment variables in global shell resource files-- for example, to set the timezone. You can use the editing feature to update and distribute the message of the day file, or to configure sendmail, (see FAQS and Tips in the Reference manual). An extremely powerful feature of cfagent is the ability to edit a similar file belonging to every user in the system. For example, as a system administrator, you sometimes need to ensure that users have a sensible login environment. Changes in the system might require all users to define a new environment variable, for instance. This is achieved with the `home' pseudo-wildcard. If one writes { home/.cshrc AppendIfNoSuchLine "# Sys admin/cfengine: put next line here" AppendIfNoSuchLine "setenv PRINTER newprinter" } then the users' files are checked one-by-one for the given lines of text, and edited if necessary. Files are loaded into cfagent and edited in memory. They are only saved again if modifications to the file are carried out, in which case the old file is preserved by adding a suffix to the filename. When files are edited, cfagent generates a warning for the administrator's inspection so that the reason for the change can be investigated. The behaviour of cfagent should not be confused with that of _sed_ or _perl_. Some functionality is reproduced for convenience, but the specific functions have been chosen on the basis of (i) their readability and (ii) the fact that they are `frequently-required-functions'. A typical file editing session involves the following points: * Load file into memory. * Is the size of the file within sensible user-definable limits? If not, file could be binary, refuse to edit. * Check each editing command and count the number of edits made. * If number of edits is greater than zero, rename the old file and save the edited version in its place. Inform about the edit. * If no edits are made, do nothing, say nothing. Equivalent one-line sed operations involve editing the same file perhaps many times to achieve the same results--without the safety checks in addition.  File: cfengine-Tutorial.info, Node: Disabling and the file repository, Next: Running user scripts, Prev: Editing files, Up: Global configurations 4.9 Disabling and the file repository ===================================== The existence of certain files can compromise the integrity of your system and you may wish to ensure that they do not exist. For example, some manufacturers sell their workstations with a `+' symbol in the file `/etc/hosts.equiv'. This means that anyone in your NIS domain has password free access to the system!! Since this is probably not a good idea, you will want to disable this file by renaming it, or simply deleting it. disable: /etc/hosts.equiv Other files compromise the system because they grow so large that they fill an entire disk partition. This is typically true of log files such as the System V files `/var/adm/wtmpx' and `/var/lp/logs/lpsched'. Other files like /VAR/ADM/MESSAGES get "rotated" by the system so that they do not grow so large as to fill the disk. You can make cfagent rotate these files too, by writing disable: Sunday:: /var/lp/logs/lpsched rotate=3 Now, when cfagent is run, it renamed the file `lpsched' to a file called `lpsched.1'. It also renames `lpsched.1' as `lpsched.2' and so on, until a maximum of 3 files are kept. After passing 3, the files `fall off the end' and are deleted permanently. This procedure prevents any log files from growing too large. If you are not interested in keeping back-logs, then you may write `rotate=empty' and cfagent will simply empty the log file. When ever cfagent disables a file (`disable' or `links' with the `!' operator), or saves a new file on top of an old one (`copy' or `editfiles'), it makes a backup of the original. Usually disabled files are renamed by appending the string `.cfdisabled' the filename; copied files are saved by appending the string `.cfsaved'. It is possible to switch off backup file generation in the copy feature by setting the variable `backup=false', but a better way of managing disabled and backed-up files is to use a directory in which you collect all such files for the whole system. This directory is called the file repository and is set in the control part of the program, as follows: In the `copy' directive, the option `backup=timestamp' can be used to allow multiple backups. This is useful when using cfengine to make disk backups for users, since it allows multiple versions to co-exist. control: repository = ( DIRECTORY-NAME ) If this variable is defined, cfagent collects all backup and disabled files (except for rotated files) in this directory, using a unique pathname. You can then inspect these files in the repository and arrange to tidy the repository for old files which are no longer interesting.  File: cfengine-Tutorial.info, Node: Running user scripts, Next: Compressing logs, Prev: Disabling and the file repository, Up: Global configurations 4.10 Running user scripts ========================= Above all, the aim of cfengine is to present a simple interface to system administrators. The actions which are built into the engine are aimed at solving the most pressing problems, not at solving every problem. In many cases administrators will still need to write scripts to carry out more specific tasks. These scripts can still be profitably run from cfengine. Variables and macros defined in cfengine can be passed to scripts so that scripts can make maximal advantage of the class based decisions. Also note that, since the days of the week are also classes in cfengine, it is straightforward to run weekly scripts from the cfengine environment (assuming that the configuration program is executed daily). An obvious use for this is to update databases, like the fast-find database one day of the week, or to run quota checks on disks. shellcommands: myhost.Sunday:: "/usr/bin/find/updatedb" Cfengine scripts can be passed variables using normal variable substitution: control: cfbin = ( /var/cfengine/bin ) backupdir = ( /iu/dax/backup ) shellcommands: "$(cfbin)/cfbackup -p -f $(backupdir) -s /iu/nexus/u1" If you need to write a particularly complex script to expand cfagent's capabilities, it might be useful to have full access to the defined classes. You can do this in one of two ways: * Pass the variable `$(allclasses)' to the script. This contains a list of all classes in the form of a string CFALLCLASSES=CLASS1:CLASS2:... This variable always contains an up to date list of the defined classes. * Use the command line option `-u' or `--use-env'. When this is defined, cfagent defines an internal environment variable called `CFALLCLASSES' which contains the same list as above. Unfortunately, System V boxes don't seem to like having to update an environment variable continuously and tend to dump core, so this is not the default behaviour!  File: cfengine-Tutorial.info, Node: Compressing logs, Next: ACLs, Prev: Running user scripts, Up: Global configurations 4.11 Compressing old log files ============================== In the previous two sections we have looked at how to rotate old log files and how to execute shell commands. If you keep a lot of old log files around on your system, you might want to compress them so that they don't take up so much space. You can do this with a shell command. The example below looks for files matching a shell wildcard. Names of the form `file.1', `file.2'...`file.10' will match this wildcard and the compression program sees that they get compressed. The output is dumped to avoid spurious messages. shellcommands: "$(gnu)/gzip /var/log/*.[0-9] /var/log/*.[0-9][0-9] > /dev/null 2>&1" Cfagent will also recognize rotated files if they have been compressed, with suffixes `.Z', `.gz', `.rbz' or `.rbz'.  File: cfengine-Tutorial.info, Node: ACLs, Prev: Compressing logs, Up: Global configurations 4.12 Managing ACLs ================== Access control lists are extended file permissions. They allow you to open or close a file to a named list of users (without having to create a special group for those users). They also allow you to open or close a file for a named list of groups. Several Unix-like operating systems have had access control lists for some time; but they do not seem to have caught on. There is a number of reasons for this dawdling in the past. The tools for setting ACLs are generally interactive and awkward to use. Because a named list of users would lead to excessive verbosity in an `ls -l' listing, one does not normally see them. There is therefore the danger that the hidden information would lead to undetected blunders in opening files to the wrong users. ACLs are also different on every vendor's filesystems and they don't work over intersystem NFS. In spite of these reservations, ACLs are a great idea. Here at Oslo College, it seems that users are continually asking how they can open a file just for the one or two persons they wish to collaborate with. They have grown used to Novell/PC networks which embraced the technology from Apollo/NCS much earlier. Previously the Unix answer to users has always been: go ask the system administrator to make a special group for you. Then do the `chmod' thing. And then they would say: so what's so great about this Unix then? Addressing this lack of standardization has been the job of a POSIX draft committee. Some vendors have made their implementations in the image of this draft. Solaris 2.6 has a good implementation. In spite of this, even these systems have only awkard tools for manipulating ACLs. Not the kind of thing you want to be around much, if you have better things to do. But the incompatibility argument applies only to multiple vendor headbutting. Some institutions who share data on a global basis opt for advanced solutions to network filesystems, such as AFS and DFS. Filesystems such as DCE's DFS make extensive use of file ACLs, and they are not operating system specific. Even so, DFS provides only interactive tools for examining and setting file permissions, and this is of little use to system administrators who would rather relegate that sort of thing to a script. The need for this kind of thing is clear. Systems which make use of ACLs for security can be brought to their knees by changing a few ACLs. Take the Apollo/Domain OS as an example. All one needs to do to kill the system is to change a few ACLs and forget what they were supposed to be. Suddenly the system is crippled, nothing works. The only solution, if you don't have a backup, is to remove all of the security. Unix has a simpler security philosophy when it comes to the operating system files, but ACLs would be a valuable addition to the security of our data. A cfagent bare-bones file-checking program looks like this: # # Free format cfagent program # control: ActionSequence - ( files ) files: classes:: /directory/file mode=644 owner=mark,ds group=users,adm acl=zap action=fixplain # ... more below This program simply checks the permissions and ownership of the named file. The regular file mode, owner and group are specified straightforwardly. The new feature here is the `acl' directive. It is a deceptively simply looking animal, but it hides a wealth of complexity. The `zap' is, of course, not an access control list. Rather, cfagent uses a system of aliases to refer to ACLs, so that the clutter of the complex ACL definitions does not impair the clarity of a file command. An ACL alias is defined in a separate part of the program which looks like this: # ...contd acl: { zap method:append fstype:solaris user:rmz:rwx user:len:r } As you can see, an ACL is a compound object--a bundle of information which specifies which users have which permissions. Because ACLs are _lists_ the alias objects must also know whether the items are to be appended to an existing list or whether they are to replace an existing list. Also, since the permission bits, general options and programming interfaces are all different for each type of filesystem, we have to tell cfagent what the filesystem type is. It is possible to associate several ACL aliases with a file. When cfagent checks a files with ACLs, it reads the existing ACL and compares it to the new one. Files are only modified if they do not conform to the specification in the cfengine program. Let's look at a complete example: files: $(HOME)/myfile acl=acl_alias1 action=fixall acl: { acl_alias1 method:append fstype:solaris user:len:rwx } ACLs are viewed in Solaris with the command `getfacl'. Suppose that, before running this program, our test-file had permissions user:*:rwx user:mark:rwx #effective:r-x group:*:r-x #effective:r-x mask:r-x other:r-x default_user:rw- default_group:r-- default_mask:-w- default_other:rwx After the cfagent run, the ACL would become: user:*:rwx user:mark:rwx #effective:r-x user:len:rwx #effective:r-x group:*:r-x #effective:r-x mask:r-x other:r-x default_user:rw- default_group:r-- default_mask:-w- default_other:rwx Suppose we wanted to to remove 'w' bit for user `jacobs', or make sure that it was never there. { acl_alias1 method:append fstype:solaris user:jacobs:-w } Note that the method used here is append. That means that, whatever other access permissions we might have granted on this file, the user `jacobs' (a known cracker) will have no write permissions on the file. Had we used the method `overwrite' above, we would have eliminated all other access permissions for every user and added the above. If we really wanted to burn `jacobs', we could remove all rights to the file like this user:jacobs:noaccess The keyword `noaccess' removes all bits. Note that this is not necessarily the same as doing a `-rwx', since some filesystems, like DFS, have more bits than this. Then, if we want to forgive and forget, the ACLs may be removed for `jacobs' with the syntax user:jacobs:default In Solaris, files inherit default ACLs from the directory they lie in; these are modified by the umask setting to generate their own default mask. DFS ACLs look a little different. They are examined with the `acl_edit' command or with dcecp -c acl show In order to effect changes to the DFS, you have to perform a DCE login to obtain authentication cookies. The user `cell_admin' is a special user account for administrating a local DFS cell. Suppose we have a file with the following DCE ACL: mask_obj:r-x--- user_obj:rwxcid user:cell_admin:r--c-- #effective:r----- group_obj:r-x--d #effective:r-x--- other_obj:r-x--- Now we want to add `wx' permissions for user `cell_admin', and add new entries with `rx' permissons for group `acct-admin' and user `root'. This is done with the following ACL alias: { acl_alias2 method:append fstype:dfs user:/.../iu.hioslo.no/cell_admin:wx group:/.../iu.hioslo.no/acct-admin:rx user:/.../iu.hioslo.no/root:rx user:*:-x } The local cell name `/.../iu.hioslo.no' is required here. Cfagent can not presently change ACLs in other cells remotely, but if your cfengine program covers all of the cell servers, then this is no limitation, since you can still centralize all your ACLs in one place. It is just that the execution and checking takes place at distributed locations. This is the beauty of cfengine. After running cfagent, with the above program snippet, the ACL then becomes: mask_obj:r-x--- user_obj:rwcid user:cell_admin:rwxc-- #effective:r-x--- user:root:r-x--- #effective:r-x--- group_obj:r-x--d #effective:r-x--- group:acct-admin:r-x--- other_bj:r-x--- For the sake of simplicity we have only used standard Unix bits `rwx' here, but more complicated examples may be found in DFS. For example, user:mark:+rwx,-cid which sets the read, write, execute flags, but removes the control, insert and delete flags. In the DFS, files inherit the inital object ACL of their parent directory, while new directories inherit the initial container object. The objects referred to in DFS as `user_obj', `group_obj' and so forth refer to the owner of a file. i.e. they are equivalent to the same commands acting on the user who owns the file concerned. To make the cfengine user-interface less cryptic and more in tune with the POSIX form, we have dropped the `_obj' suffices. A user field of `*' is a simple abbreviation for the owner of the file. A problem with any system of lists is that one can generate a sequence which does one thing, and then undoes it and redoes something else, all in the same contradictory list. To avoid this kind of accidental interaction, cfengine insists that each user has only one ACE (access control entry), i.e. that all the permissions for a given user be in one entry.  File: cfengine-Tutorial.info, Node: Using cfengine as a front-end for cron, Next: Cfengine network services, Prev: Global configurations, Up: Top 5 Using cfengine as a front end for cron **************************************** One of cfengine's strengths is its use of classes to identify systems from a single file or set of files. Many administrators think that it would be nice if the cron daemon also worked in this way. One possible way of setting up cron from a global configuration would be to use the cfengine `editfiles' facility to edit each cron file separately. A much better way is to use cfengine's time classes to work like a user interface for cron. This allows you to have a single, central cfengine file which contains all the cron jobs on your system without losing any of the fine control which cron affords you. All of the usual advantages apply: * It is easier to keep track of what cron jobs are running on the system when you have everything in one place. * You can use all of your carefully crafted groups and user-defined classes to identify which host should run which programs. The central idea behind this scheme is to set up a regular cron job on every system which executes cfagent at frequent intervals. Each time cfagent is started, it evaluates time classes and executes the shell commands defined in its configuration file. In this way we use cfagent as a wrapper for the cron scripts, so that we can use cfengine's classes to control jobs for mulitple hosts. Cfengine's time classes are at least as powerful as `cron''s time specification possibilities, so this does not restrict you in any way, *Note Building flexible time classes::. The only price is the overhead of parsing the cfengine configuration file. To be more concrete, imagine installing the following `crontab' file onto every host on your network: # # Global Cron file # 0,15,30,45 * * * * /usr/local/sbin/cfexecd -F * Menu: * Structuring cfagent.conf:: * Splaying host times:: * Building flexible time classes:: * Scheduling interval::  File: cfengine-Tutorial.info, Node: Structuring cfagent.conf, Next: Splaying host times, Prev: Using cfengine as a front-end for cron, Up: Using cfengine as a front-end for cron 5.1 Structuring cfagent.conf ============================ The structure of `cfagent.conf' needs to reflect your policy for running jobs on the system. You need to switch on relevant tasks and switch off unwanted tasks depending on the time of day. This can be done in three ways: * By placing individual actions under classes which restrict the times at which they are executed, ACTION: Hr00.Min10_15||Hr12.Min45_55:: COMMAND * By choosing a different `actionsequence' depending on the time of day. control: Hr00:: # Action-sequence for daily run at midnight actionsequence = ( SEQUENCE ) !Hr00:: # Action-sequence otherwise actionsequence = ( SEQUENCE ) * By importing modules based on time classes. import: Hr00:: cf.dailyjobs any:: cf.hourlyjobs The last of these is the most efficient of the three, since cfengine does not even have to spend time parsing the files for actions which you know you will not want.  File: cfengine-Tutorial.info, Node: Splaying host times, Next: Building flexible time classes, Prev: Structuring cfagent.conf, Up: Using cfengine as a front-end for cron 5.2 Splaying host times ======================= The trouble with starting every cfagent at the same time using a global cron file is that it might lead to contention or inefficiency. For instance, if a hundred cfagents all suddenly wanted to copy a file from a master source simultaneously this would lead to a big load on the server. We can prevent this from happening by introducing a time delay which is unique for each host and not longer than some given interval. Cfagent uses a hashing algorithm to generate a number between zero and a maximum value in minutes which you define, like this: # Put this in update.conf, so that the updates are also splayed control: SplayTime = ( 10 ) # minutes If this number is non-zero, cfagent goes to sleep after parsing its configuration file and reading the clock. Every machine will go to sleep for a different length of time, which is no longer than the time you specify in minutes. A hashing algorithm, based on the fully qualified name of the host, is used to compute a unique time for hosts. The shorter the interval, the more clustered the hosts will be. The longer the interval, the lighter the load on your servers. This `splaying' of the run times will lighten the load on servers, even if they come from domains not under your control but have a similar cron policy. Splaying can be switched off temporarily with the `-q' or `--no-splay' options.  File: cfengine-Tutorial.info, Node: Building flexible time classes, Next: Scheduling interval, Prev: Splaying host times, Up: Using cfengine as a front-end for cron 5.3 Building flexible time classes ================================== Each time cfagent is run, it reads the system clock and defines the following classes based on the time and date: `YrXX::' The current year, e.g. `Yr1997', `Yr2001'. This class is probably not useful very often, but it might help you to turn on the new-year lights, or shine up your systems for the new millenium! `MONTH::' The current month can be used for defining very long term variations in the system configuration, e.g. `January', `February'. These classes could be used to determine when students have their summer vacation, for instance, in order to perform extra tidying, or to specially maintain some administrative policy for the duration of a conference. `DAY::' The day of the week may be used as a class, e.g. `Monday', `Sunday'. `DayXX::' A day in the month (date) may be used to single out by date, e.g. the first day of each month defines `Day1', the 21st `Day21' etc. `HrXX::' An hour of the day, in 24-hour clock notation: `Hr00'...`Hr23'. `MinXX::' The precise minute at which cfagent was started: `Min0' ... `Min59'. This is probably not useful alone, but these values may be combined to define arbitrary intervals of time. `MinXX_XX::' The five-minute interval in the hour at which cfagent was executed, in the form `Min0_5', `Min5_10' .. `Min55_0'. Time classes based on the precise minute at which cfagent started are unlikely to be useful, since it is improbable that you will want to ask cron to run cfagent every single minute of every day: there would be no time for anything to complete before it was started again. Moreover, many things could conspire to delay the precise time at which cfagent were started. The real purpose in being able to detect the precise start time is to define composite classes which refer to arbitrary intervals of time. To do this, we use the `group' or `classes' action to create an alias for a group of time values. Here are some creative examples: classes: # synonym groups: LunchAndTeaBreaks = ( Hr12 Hr10 Hr15 ) NightShift = ( Hr22 Hr23 Hr00 Hr01 Hr02 Hr03 Hr04 Hr05 Hr06 ) ConferenceDays = ( Day26 Day27 Day29 Day30 ) QuarterHours = ( Min00 Min15 Min30 Min45 ) TimeSlices = ( Min01 Min02 Min03 Min33 Min34 Min35) In these examples, the left hand sides of the assignments are effectively the ORed result of the right hand side. This if any classes in the parentheses are defined, the left hand side class will become defined. This provides a flexible and readable way of specifying intervals of time within a program, without having to use `|' and `.' operators everywhere.  File: cfengine-Tutorial.info, Node: Scheduling interval, Prev: Building flexible time classes, Up: Using cfengine as a front-end for cron 5.4 Choosing a scheduling interval ================================== How often should you call your global cron script? There are several things to think about: * How much fine control do you need? Running cron jobs once each hour is usually enough for most tasks, but you might need to exercise finer control for a few special tasks. * Are you going to run the entire cfengine configuration file or a special light-weight file? * System latency. How long will it take to load, parse and run the cfengine script? Cfengine has an intelligent locking and timeout policy which should be sufficient to handle hanging shell commands from previous crons so that no overlap can take place, *Note Spamming and security::.  File: cfengine-Tutorial.info, Node: Cfengine network services, Next: Security and cfengine, Prev: Using cfengine as a front-end for cron, Up: Top 6 Cfengine and network services ******************************* This chapter describes how you can set up a cfengine network service to handle remote file distribution and remote execution of cfengine without having to open your hosts to possible attack using the `rsh' protocols. * Menu: * What services?:: * How it works:: * Configuring cfservd::  File: cfengine-Tutorial.info, Node: What services?, Next: How it works, Prev: Cfengine network services, Up: Cfengine network services 6.1 Cfengine network services ============================= By starting the daemon called `cfservd', you can set up a line of communication between hosts, allowing them to exchange files across the network or execute cfengine remotely on another system. Cfengine network services are built around the following components: `cfagent' The configuration engine, whose only contact with the network is via remote copy requests. This component does the hard work of configuring the system based on rules specified in the file `cfagent.conf'. It does not and cannot grant any access to a system from the network. `cfservd' A daemon which acts as both a file server and a remote-cfagent executor. This daemon authenticates requests from the network and processes them according to rules specified in `cfservd.conf'. It works as a file server and as a mechanism for starting cfagent on a local host and piping its output back to the network connection. `cfrun' This is a simple initiation program which can be used to run cfagent on a number of remote hosts. It cannot be used to tell cfagent what to do, it can only ask cfagent on the remote host to run the configuration file it already has. Anyone could be allowed to run this program, it does not require any special user privileges. A locking mechanism in cfengine prevents its abuse by spamming. `cfwatch' This program (which is not a part of the distribution: it is left for others to implement) should provide a graphical user interface for watching over the configuration of hosts running cfagent and logging their output. With these components you can emulate programs like `rdist' whose job it is to check and maintain copies of files on client machines. You may also decide who has permission to run cfagent and how often it may be run, without giving away any special user privileges.  File: cfengine-Tutorial.info, Node: How it works, Next: Configuring cfservd, Prev: What services?, Up: Cfengine network services 6.2 How it works ================ * Menu: * Emulating rdist:: * Remote execution of cfagent:: * Spamming and security:: * cfservd protocol:: * Deadlocks and runaway loops::  File: cfengine-Tutorial.info, Node: Emulating rdist, Next: Remote execution of cfagent, Prev: How it works, Up: How it works 6.2.1 Remote file distribution ------------------------------ This section describes how you can set up `cfservd' as a remote file server which can result in the distribution of files to client hosts in a more democratic way than with programs like rdist. An important difference between cfengine and other systems has to do with the way files are distributed. Cfengine uses a `pull' rather than a `push' model for distributing network files. The `rdist' command, for instance, works by forcing an image of the files on one server machine onto all clients. Files get changed when the server wishes it and the clients have no choice but to live with the consequences. Cfengine cannot force its will onto other hosts in this way, it can only signal them and ask them to collect files if they want to. In other words, cfengine simulates a `push' model by polling each client and running the local cfengine configuration script giving the host the chance to `pull' any updated files from the remote server, but leaving it up to the client machine to decide whether or not it wants to update. Also, in contrast to programs like `rdist' which distribute files over many hosts, cfengine does not require any general `root' access to a system using the `.rhosts' file or the `/etc/hosts.equiv' file. It is sufficient to run the daemon as root. You can not run it by adding it to the `/etc/inetd.conf' file on your system however. The restricted functionality of the daemon protects your system from attempts to execute general commands as the root user using `rsh'. To remotely access files on a server, you add the keyword `server=HOST' to a copy command. Consider the following example which illustrates how you might distribute a password file from a masterhost to some clients. copy: PasswdClients:: /etc/passwd dest=/etc/passwd owner=root group=0 server=SERVER-HOST Given that the `cfservd' daemon is running on SERVER-HOST, cfagent will make contact with the daemon and attempt to obtain information about the file. During this process, cfengine verifies that the system clocks of the two hosts are reasonably synchronized. If they are not, it will not permit remote copying. If cfagent determines that a file needs to be updated from a remote server it begins copying the remote file to a new file on the same filesystem as the destination-file. This file has the suffix `.cfnew'. Only when the file has been successfully collected will cfagent make a copy of the old file, (see `repository' in the Reference manual), and rename the new file into place. This behaviour is designed to avoid race-conditions which can occur during network connections and indeed any operations which take some time. If files were simply copied directly to their new destinations it is conceivable that a network error could interrupt the transfer leaving a corrupted file in place. Cfagent places a timeout of a few seconds on network connections to avoid hanging processes. Normally the daemon sleeps, waiting for connections from the network. Such a connection may be initiated by a request for remote files from a running cfengine program on another host, or it might be initiated by the program `cfrun' which simply asks the host running the daemon to run the cfengine program locally.  File: cfengine-Tutorial.info, Node: Remote execution of cfagent, Next: Spamming and security, Prev: Emulating rdist, Up: How it works 6.2.2 Remote execution of cfagent --------------------------------- It is a good idea to execute cfagent by getting `cron' to run it regularly. This ensures that cfagent will be run even if you are unable to log onto a host to run it yourself. Sometimes however you will want to run cfagent immediately in order to implement a change in configuration as quickly as possible. It would then be inconvenient to have to log onto every host in order to do this manually. A better way would be to issue a simple command which contacted a remote host and ran cfagent, printing the output on your own screen: myhost% cfrun REMOTE-HOST -v OUTPUT.... A simple user interface is provided to accomplish this. `cfrun' makes a connection to a remote cfservd-daemon and executes cfagent on that system with the privileges of the cfservd-daemon (usually `root'). This has a two advantages: * You avoid having to log in on a remote host in order to reconfigure it. * Users other than root can run cfagent to fix any problems with the system. A potential disadvantage with such a system is that malicious users might be able to run cfagent on remote hosts. The fact that non-root users can execute cfagent is not a problem in itself, after all the most malicious thing they would be able to do would be to check the system configuration and repair any problems. No one can tell cfagent what to do using the cfrun program, it is only possible to run an existing configuration. But a more serious concern is that malicious users might try to run cfagent repeatedly (so-called `spamming') so that a system became burdened with running cfagent constantly, *Note Spamming and security::.  File: cfengine-Tutorial.info, Node: Spamming and security, Next: cfservd protocol, Prev: Remote execution of cfagent, Up: How it works 6.2.3 Spamming and security --------------------------- The term `spamming' refers to the senseless repetition of something in a malicious way intended to drive someone crazy(1). In the computer world some malicious users, a bit like `flashers' in the park(2) like to run around the net a reveal themselves ad nauseum by sending multiple mail messages or making network connections repeatedly to try to overload systems and people(3). Whenever we open a system to the network, this problem becomes a concern. Cfengine is a tool for making peace with networked systems, not a tool to be manipulated into acts of senseless aggression. The cfservd daemon does make it possible for anyone to connect and run a cfengine process however, so clearly some protection is required from such attacks. Cfengine's solution to this problem is a locking mechanism. Rather than providing user-based control, cfengine uses a time based locking mechanism which prevents actions from being executed unless a certain minimum time has elapsed since the last time they were executed. By using a lock which is not based on user identity, we protect several interests in one go: * Restricting cfengine access to root would prevent regular users, in trouble, from being able to fix problems when the system administrator was unavailable. A time-based lock does not prevent this kind of freedom. * Accidents with cron or shell scripts could start cfagent more often than desirable. We also need to protect against such accidents. * We can prevent malicious attacks regardless of whom they may come from. Cfengine is controlled by a series of locks which prevent it from being run too often, and which prevent it from spending too long trying to do its job. The locks work in such a way that you can start several cfengine processes simultaneously without them crashing into each other. Coexisting cfengine processes are also prevented from trying to do the same thing at the same time (we call this `spamming'). You can control two things about each kind of action in the action sequence: * The minimum time which should have passed since the last time that action was executed. It will not be executed again until this amount of time has elapsed. (Default time is 1 minute.) * The maximum amount of time cfagent should wait for an old instantiation of cfagent to finish before killing it and starting again. (Default time is 120 minutes.) You can set these values either globally (for all actions) or for each action separately. If you set global and local values, the local values override the global ones. All times are written in units of _minutes_. actionsequence ( action.IfElapsedTIME-IN-MINS action.ExpireAfterTIME-IN-MINS ) or globally, control: IfElapsed = ( TIME-IN-MINS ) ExpireAfter = ( TIME-IN-MINS ) For example: control: actionsequence = ( files.IfElapsed240.ExpireAfter180 copy tidy ) IfElapsed = ( 30 ) In this example, we treat the files action differently to the others. For all the other actions, cfagent will only execute the files part of the program if 30 minutes have elapsed since it was last run. Since no value is set, the expiry time for actions is 60 minutes, which means that any cfagent process which is still trying to finish up after 60 minutes will be killed automatically by the next cfagent which gets started. As for the files action: this will only be run if 240 minutes (4 hours) have elapsed since the last run. Similarly, it will not be killed while processing `files' until after 180 minutes (3 hours) have passed. These locks do not prevent the whole of cfagent from running, only so-called `atoms'. Several different atoms can be run concurrently by different cfagents. Assuming that the time conditions set above allow you to start cfengine, the locks ensure that atoms will never be started by two cfagents at the same time, causing contention and wasting CPU cycles. Atoms are defined to maximize the security of your system and to be efficient. If cfengine were to lock each file it looked at seperately, it would use a large amount of time processing the locks, so it doesn't do that. Instead, it groups things together like this: `copy, editfiles, shellcommands' Each separate command has its own lock. This means that several such actions can be processed concurrently by several cfagent processes. Multiple or recursive copies and edits are treated as a single object. `netconfig, resolve, umount, mailcheck, addmounts, disable, processes' All commands of this action-type are locked simultaneously, since they can lead to contention. `mountall, mountinfo, required, checktimezone' These are not locked at all. Cfagent creates a directory `~/.cfengine' for writing lock files for ordinary users. The option `-K' or `--no-lock' can be used to switch off the locking checks, but note that when running cfagent remotely via `cfservd', this is not possible. ---------- Footnotes ---------- (1) Recall the `spam' song from Monty Python's flying circus? (2) Recall the `spam' song from Monty Python's flying circus? (3) Recall the `spam' song ... get the idea?  File: cfengine-Tutorial.info, Node: cfservd protocol, Next: Deadlocks and runaway loops, Prev: Spamming and security, Up: How it works 6.2.4 Some points on the cfservd protocol ----------------------------------------- Cfservd uses a form for host-based authorization. Each atomic operation, such as statting, getting files, reading directories etc, requires a new connection and each connection is verified by a double reverse lookup in the server's DNS records. Single stat structures are cached during the processing of a file. MD5 checksums are transferred from client to server to avoid loading the server. Even if a user could corrupt the MD5 checksum, he or she would have to get past IP address access control and the worst that could happen would be to get the right version of the file. Again this is in keeping with the idea that users can only harm themselves and not others with cfengine.  File: cfengine-Tutorial.info, Node: Deadlocks and runaway loops, Prev: cfservd protocol, Up: How it works 6.2.5 Deadlocks and runaway loops --------------------------------- Whenever we allow concurrent processes to share a resource, we open ourselves up the possibilty of deadlock. This is a situation where two or more processes are locked in a vicious stalemate from which none can escape. Another problem is that it might be possible to start an infinite loop: cfagent starts itself. Cfagent protects you from such loops to a large degree. It should not be possible to make such a loop by accident. The reason for this is the locking mechanism which prevents tasks being repeated too often. If you start a cfagent process which contains a shell-command to start cfagent again, this shell command will be locked, so it will not be possible to run it a second time. So while you might be able to start a second cfagent process, further processes will not be started and you will simply have wasted a little CPU time. When the first cfagent returns, the tasks which the second cfagent completed will not be repeated unless you have set the `IfElapsed' time or the `ExpireAfter' time to zero. In general, if you wish to avoid problems like this, you should not disable the locking mechanism by setting these two times to zero. The possibility of deadlock arises in network connection. Cfengine will not attempt to use the network to copy a file which can be copied internally from some machine to itself. It will always replace the `server=' directive in a copy with `localhost' to avoid unnecessary network connections. This prevents one kind of deadlock which could occur: namely cfrun executes cfagent on host A (cfservd on host A is then blocked until this completes), but the host A configuration file contains a remote copy from itself to itself. This remote copy would then have to wait for cfservd to unblock, but this would be impossible since cfservd cannot unblock until it has the file. By avoiding remote copies to localhost, this possibility is avoided.  File: cfengine-Tutorial.info, Node: Configuring cfservd, Prev: How it works, Up: Cfengine network services 6.3 Configuring cfservd ======================= * Menu: * Installation of cfservd:: * Configuration file cfservd.conf::  File: cfengine-Tutorial.info, Node: Installation of cfservd, Next: Configuration file cfservd.conf, Prev: Configuring cfservd, Up: Configuring cfservd 6.3.1 Installation of cfservd ----------------------------- To install the cfservd daemon component, you will need to register a port for cfengine by adding the following line to the system file `/etc/services file' cfengine 5308/tcp You could do this for all hosts by adding the following to your cfengine configuration editfiles: { /etc/services AppendIfNoSuchLine "cfengine 5308/tcp" } To start cfservd at boot time, you need to place a line of the following type in your system startup files: # Start cfengine server cfservd Note that `cfservd' will re-read its configuration file whenever it detects that it has been changed, so you should not have to restart the daemon, not send it the HUP signal as with other daemons.  File: cfengine-Tutorial.info, Node: Configuration file cfservd.conf, Prev: Installation of cfservd, Up: Configuring cfservd 6.3.2 Configuration file cfservd.conf ------------------------------------- The server daemon is controlled by a file called `cfservd.conf'. The syntax of this configuration file is deliberately modelled on cfengine's own configuration file, but despite the similarities, you cannot mix the contents of the two files. Though they are not compatible, `cfagent.conf' and `cfservd.conf' are similar in several ways: * Both files use classes to label entries, so that you may use the same configuration file to control all hosts on your network. This is a convenience which saves you the trouble of maintaining many different files. * Both files are searched for using the contents of the variable `CFINPUTS'. * You can use `groups' and `import' in both files to break up files into convenient modules and to import common resources, such as lists of groups. Note that the classes in the `cfservd.conf' file do not tell you the classes of host which have access to files and directories, but rather which classes of host pay attention to the access and deny commands when the file is parsed. Host name authentication is not by class or group but by hostname, like the `/etc/exports' file on most Unix systems. The syntax for the file is as follows: control: CLASSES:: domain = ( DNS-DOMAIN-NAME ) cfrunCommand = ( "SCRIPT/FILENAME" ) # Quoted MaxConnections = ( MAXIMUM NUMBER OF FORKED DAEMONS ) IfElapsed = ( TIME-IN-MINUTES ) DenyBadClocks = ( FALSE ) AllowConnectionsFrom = ( IP NUMBERS ) DenyConnectionsFrom = ( IP NUMBERS ) AllMultipleConnectionsFrom = ( IP NUMBERS ) LogAllConnections = ( FALSE/TRUE ) SkipVerify = ( IP NUMBERS ) groups: GROUP DEFINITIONS import: FILES TO IMPORT admit: | grant: CLASSES:: /FILE-OR-DIRECTORY WILDCARDS/HOSTNAMES deny: CLASSES:: /FILE-OR-DIRECTORY WILDCARDS/HOSTNAMES root=HOSTLIST encrypt=TRUE/ON See the reference manual for descriptions of these elements. The file consists of a control section and access information. You may use the control section to define any variables which you want to use, for convenience, in the remainder of your file. Following the control section, comes a list of files or directories and hosts which may access these. If permissions are granted to a directory then all subdirectories are automatically granted also. Note that plain-file symbolic links are not checked for, so you may need to specifically deny access to links if they are plain files, but cfservd does not follow directory symbolic links and give access to files in directories pointed to by these. Fully qualified hostnames should be used in this file. If host names are unqualified, the current domain is appended to them (do not forget to define the domain name). Authentication calls the Unix function `gethostbyname()' and so on to identify and verify connecting hosts, so the names in the file must reflect the type on names returned by this function. You may use wildcards in names to match, for instance, all hosts from a particular domain. Here is an example file ##################################################### # # This is a cfservd config file # ##################################################### groups: PasswdHost = ( nexus ) ##################################################### control: # # Assuming CFINPUTS is defined # cfrunCommand = ( "/var/cfengine/bin/cfagent" ) variable = ( /usr/local/publicfiles ) ##################################################### admit: # Can also call this grant: # Note that we must grant access to the # agent if we wan to start it remotely with cfrun /var/cfengine/bin/cfagent PasswdHost:: /etc/passwd *.iu.hioslo.no FtpHost:: # An alternative to ftp, grant anyone /local/ftp/pub * # These file paths must not contain symbolic # links. Access control does not follow symlinks. any:: $CFINPUTS/cfrun.sh *.iu.hioslo.no ##################################################### deny: /etc/services borg.iu.hioslo.no /local/ftp *.pain-in-the-ass.com _NOTE I: cfservd is not `rpc.mountd', access control is by filename, not by device name. Do not assume that files lying in subdirectories are not open for access simply because they lie on a different device. You should give the real path name to file and avoid symbolic links._ NOTE II: access control is per host and per user. User names are assumed to be common to both hosts. There is an implicit trust relationship here. There is no way to verify whether the user on the remote host is the same user as the user with the same name on the local host. NOTE III: Cfservd requires you to grant access to files without following any symbolic links. You must grant access to the real file or directory in order to access the file object. This is a security feature in case parties with login access to the server could grant access to additional files by having the permission to create symbolic links in a transitory directory, e.g. `/tmp'.  File: cfengine-Tutorial.info, Node: Security and cfengine, Next: Summary, Prev: Cfengine network services, Up: Top 7 Security and cfengine *********************** * Menu: * What is security?:: * A word of warning:: * Automation:: * Trust:: * Why trust cfengine?:: * Configuration:: * Disabling and replacing software:: * Process monitoring:: * Monitoring files:: * The setuid log:: * Suspicious filenames:: * Checksums and Tripwire functionality:: * FileExtensions:: * NonAlphaNumFiles:: * Defensive garbage collection:: * Anonymous FTP example:: * WWW security:: * Miscellaneous security of cfengine itself:: * Privacy (encryption):: * Trust and key races:: * Adaptive locks:: * Spoofing:: * Race conditions in file copying:: * size= in copy:: * useshell= and owner= in shellcommands:: * Firewalls:: Computer security is about protecting the data and availability of an association of hosts. Briefly, the key words are authentication, privacy, integrity and trust. To understand computer security we have to understand the interrelationships between all of the hosts and services on our networks as well as the ways in which those hosts can be accessed. Tools which allow this kind of management are complex and usually expensive.  File: cfengine-Tutorial.info, Node: What is security?, Next: A word of warning, Prev: Security and cfengine, Up: Security and cfengine 7.1 What is security? ===================== For a computer to be secure it must be *physically secure* -- if we can get our hands on a host then we are never more than a screwdriver away from all of its assets--but assuming that hosts are physically secure, we then wish to deal with the issues of software security which is a much more difficult topic. Software security is about access control and software reliability. No single tool can make computer systems secure. Major blunders have been made out of the belief that a single product (e.g. a `firewall') would solve the security problem. For instance, a few years ago a cracker deleted all the user directories from a dialup login server belonging to a major Norwegian telecommunications company, from the comfort of his web browser. This was possible, even through a firewall, because the web server on the host concerned was incorrectly configured. The bottom line is that there is no such thing as a secure operating system, firewall or none. What is required is a persistent mixture of vigilence and adaptability. For many, security is perceived as being synonymous with network privacy or network intrusion. Privacy is one aspect of security, but it is not the network which is our special enemy. Many breaches of security happen from within. There is little difference between the dangers of remote access from the network or direct access from a console: privacy is about access control, no matter where the potential intruder might be. If we focus exclusively on network connectivity we ignore a possible threat from internal employees (e.g. the janitor who is a computer expert and has an axe to grind, or the mischievous son of the director who was left waiting to play mom's office, or perhaps the unthinkable: a disgruntled employee who feels as though his/her talents go unappreciated). Software security is a vast subject, because modern computer systems are complex. It is only exacerbated by the connectivity of the internet which allows millions of people to have a go at breaking into networked systems. What this points to is the fact that a secure environment requires a tight control of access control on every host individually, not merely at specific points such as firewalls. This article is not a comprehensive guide to security. Rather it is an attempt to illustrate how cfengine can be used to help you automate a level of host integrity on all the hosts of your network. Cfengine is a network configuration tool with two facets. It is a language used to build an `expert system'. An expert system describes the way you would like your hosts and network to look and behave. CFengine is also a software robot which compares the model you have described with what the world really looks like and then sets to work correcting any deviations from that picture. In many ways it is like an immune system, neutralizing and repairing damaged parts. Unlike many shell-script packages for sysadmin, cfengine is a C program which means light on system resources. Also it works on a principle of `convergence'. Convergence means that each time you run cfengine the system should get closer to the model which you have described until eventually when the system is the model, cfengine becomes quiescent, just like an immune system. In the words of one user your hosts `never get worse'. This assumes of course that the model you have is what you really want. Using cfengine, model building becomes synonymous with formulating and formalizing a system policy. What makes cfengine a security tool is that security policy is a part of system policy: you cannot have one without the other. You will never have security unless you are in control of your network. Cfengine monitors and indeed repairs hosts with simple easily controllable actions. From an automation perspective, security is no different from the general day to day business of system maintenance, you just need to pay more attention to the details. We cannot speak of `have security' and `have not security'. There is always security, it is simply a matter of degree: weak or strong; effective or ineffective.  File: cfengine-Tutorial.info, Node: A word of warning, Next: Automation, Prev: What is security?, Up: Security and cfengine 7.2 A word of warning ===================== Before starting it is only proper to state the obvious. You should never trust anyone's advice about configuration or security without running it past your own grey matter first. The examples provided here are just that: examples. They might apply to you as written and they might need to be modified. You should never accept and use an example without thinking carefully and critically first! Also, in any book of recipies or guide to successful living you know that there are simplified answers to complex questions and you should treat them as such. There is no substitute for real understanding.  File: cfengine-Tutorial.info, Node: Automation, Next: Trust, Prev: A word of warning, Up: Security and cfengine 7.3 Automation ============== Even in the smallest local area network you will want to build a scheme for automating host configuration and maintenance, because networks have a way of growing from one host into many quite quickly. It is therefore important to build a model which scales. A major reason for using cfengine is precisely for scalability. Whether you have one host or a hundred makes little difference. Cfengine is instructed from a central location, but its operation is completely and evenly spread across the network. Each host is responsible for obtaining a copy of the network model from a trusted source and is then responsible for configuring itself without intervention from outside. Unlike some models, cfengine does not have to rely on network communication or remote object models. We also need integration, or the ability to manage the interrelationships between hosts. It is no good having complete control of one important host and thinking that you are secure. If an intruder can get into any host, he or she is almost certain to get into the ones that matter, especially if you are not looking at all of them. Using cfengine is a good way of forcing yourself to formulate a configuration/security policy and then stick to it. Why cfengine? There are three reasons: i) it forces a discipline of preparation which focuses you on the problems at the right level of detail, ii) it provides you with `secure' scalable automation and a common interface to all your hosts, and iii) it scales to any number of hosts without additional burdens. We'll need to qualify some of these points below. The first step in security management is to figure out a security policy. That way, you know what *you* mean by security and if that security is breached, you will know what to do. In many cases you can formulate a large part of your security policy as cfengine code. That makes it formal, accurate and it means that it will get done by the robot without requiring any more work on your part. As an immune system, cfengine will even work fine in a partially connected environment it makes each host responsible for its own state. It is not reliant on network connectivty for remote method invocations or CORBA-style object requests as is, say, Tivoli. All it needs is an authentic copy of the network configuration document stored locally on each host. If this is the case, a detached host will not be left unprotected, at worst it might lag behind in its version of the network configuration.  File: cfengine-Tutorial.info, Node: Trust, Next: Why trust cfengine?, Prev: Automation, Up: Security and cfengine 7.4 Trust ========= There are many implicit trust relationships in computer systems. It is crucial to understand them. If you do not understand where you are placing your trust, your trust can be exploited by attackers who have thought more carefully than you have. For example, any NFS server of users' home-directories trusts the root user on the hosts which mount those directories. Some bad accidents are prevented by mapping root to the user nobody on remote systems, but this is not security, only convenience. The root user can always use `su' to becomes any user in its password file and access/change any data within those filesystems. The .rlogin and hosts.equiv files on Unix machines grant root (or other user) privileges to other hosts without the need for authentication. If you are collecting software from remote servers, you should make sure that they come from a machine that you trust, particularly if they are files which could lead to privileged access to your system. Even checksums are no good unless they also are trustworthy. For example, it would be an extremely foolish idea to copy a binary program such as /bin/ps from a host you know nothing about. This program runs with root privileges. If someone were to replace that version of ps with a Trojan horse command, you would have effectively opened your system to attack. Most users trust anonymous FTP servers where they collect free software. In any remote copy you are setting up an implicit trust relationship. First of all you trust integrity of the host you are collecting files from. Secondly you trust that they have the same username database with regard to access control. The root user on the collecting host has the same rights to read files as the root user on the server. The same applies to any matched user name.  File: cfengine-Tutorial.info, Node: Why trust cfengine?, Next: Configuration, Prev: Trust, Up: Security and cfengine 7.5 Why trust cfengine? ======================= Cfengine has a very simple trust model. It trusts the integrity of its input file and any data which is explicitly chooses to download. Cfengine places the responsibility on root on the localhost not on any outsiders. *You* can make cfengine destroy your system, just as you can destroy it yourself, but no one else can, so as long as you are careful with the input file you are trusting essentially no-one. We shall qualify this below for remote file copying. Cfengine assumes that its input file is secure. Apart from that input file, no part of cfengine accepts or uses any configuration information from outside sources. The most one could do from an authenticated network connection is to ask cfengine to carry out (or not) certain parts of its model, thus in the worst case scanario an outside attacker could spoof cfengine into configuring the host correctly. In short, no one except root on the localhost can force cfengine to do anything (unless root access to your system has already been compromised by another route). This means that there is a single point of failure. The input file does not even have to be private as long as it is authentic. No one except you can tell cfengine what to do. There is a catch though. Cfengine can be used to perform remote file transfer. In remote file transfer one is also forced to trust the integrity of the data received, just as in any remote copy scheme. Although cfengine works hard to authenticate the identity of the host, once the host's identity is verified it cannot verify the accuracy of unknown data it has been asked to receive. Also, as with all remote file transfers, cfengine could be tricked by a DNS spoofing into connecting to an imposter host, so use the IP addresses of hosts, not their names if you don't trust your DNS service. In short, these faults are implicit in remote copying. They do not have to do with cfengine itself. This has nothing to do with encryption as users sometimes believe: encrypted connections do not change these trust relationships--they improve the privacy of the data being transmitted not their accuracy or trustworthiness. The point of cfengine is normally to have only one global configuration for every host. This needs to be distributed somehow which means that hosts must collect this file from a remote server. This in turn means that you must trust the host which has the master copy of the cfengine configuration file.  File: cfengine-Tutorial.info, Node: Configuration, Next: Disabling and replacing software, Prev: Why trust cfengine?, Up: Security and cfengine 7.6 Configuration ================= The beginning of security is correct host configuration. Even if you have a firewall shielding you from outside intrusion, an incorrectly configured host is a security risk. Host configuration is what cfengine is about, so we could easily write a book on this. Rather than reiterating the extensive documentation, let's just consider a few examples which address actual problems and get down to business without further ado. A cfengine configuration file is composed of objects with the following syntax (see the cfengine documentation): rule-type: classes-of-host-this-applies-to:: Actual rule 1 Actual rule 2 ... The rule-types include checking file permissions, editing textfiles, disabling (renaming and removing permissions to) files, controlled execution of scripts and a variety of other things relating to host configuration. Some of the `control' rules are simply flags which switch on complex (read `smart') behaviour. Every cfengine program needs an actionsequence which tells it the order in which bulk configuration operations should be evaluated. e.g. control: actionsequence = ( netconfig copy processes editfiles ) You should look at the cfengine manual to get started with your configuration. Let us step through some basic idioms which can repeated in different contexts. As representative examples we shall take Solaris and GNU/Linux as example operating systems. This is not to single them out as being particularly secure or insecure, it is merely due to their widespread use and for definiteness.  File: cfengine-Tutorial.info, Node: Disabling and replacing software, Next: Process monitoring, Prev: Configuration, Up: Security and cfengine 7.7 Disabling and replacing software ==================================== One of the simplest things which we are asked to do constantly is to disable dangerous programs as bugs are discovered. CERT security warnings frequently warn about programs with flaws which can compromise a system. In cfengine, disabling a file means renaming it to *.cfdisabled and setting its permission to 600. disable: # # CERT security patches # solaris:: /usr/openwin/bin/kcms_calibrate /usr/openwin/bin/kcms_configure /usr/bin/admintool /etc/rc2.d/S99dtlogin /usr/lib/expreserve linux:: /sbin/dip-3.3.7n /etc/sudoers /usr/bin/sudoers Although this is a trivial matter, the fact that it is automated means that cfengine is checking for this all the time. As long as a host is up and running (connected to the network or not) cfengine will be ensuring the named file is not present. Another issue is to replace standard vendor programs with drop-in replacements. For example, most admins would like to replace their vendor sendmail with the latest update from Eric Allman's site. One way to do this is to compile the new sendmail into a special directory, separate from vendor files and then to symbolically link the new program into place. links: solaris||linux:: /usr/lib/sendmail ->! /usr/local/lib/mail/bin/sendmail-8.9.3 /usr/sbin/sendmail ->! /usr/local/lib/mail/bin/sendmail-8.9.3 /etc/mail/sendmail.cf ->! /usr/local/lib/mail/etc/sendmail.cf The exclamation marks mean (by analogy with the csh) that existing file objects should be replaced by links to the named files. Again the integrity of these links is tested every time cfengine runs. If the object /usr/lib/sendmail is not a link to the named file, the old file is moved and a link is made. If the link is okay, nothing happens. After putting the new sendmail in place, you will need to make sure that the restricted shell configuration is in order. # # Sendmail, restricted shell needs these links # solaris:: # Most of these will only be run on the MailHost # but flist (procmail) is run during sending... /usr/adm/sm.bin/vacation -> /usr/ucb/vacation /usr/adm/sm.bin/flist -> /home/listmgr/.bin/flist linux:: /usr/adm/sm.bin/vacation -> /usr/bin/vacation Link management is a particularly useful feature of cfengine. By putting links (actually all system modifications) into the cfengine configuration and never doing anything by hand, you build up a system which is robust to reinstallation. If you lose your host, you just have to run cfengine once or twice to reconstruct it. Of course, the fundamental tenet of security is to be able to restrict privilege to resources. We therefore need to check the permissions on files. For instance, a recent CERT advisory warned of problems with some free unix mount commands which were setuid root. If we suppose there is a group of hosts called `securehosts' which we don't need to worry about, then we could remove the setuid bits on all other hosts as follows: files: !securehosts.linux:: /bin/mount mode=555 owner=root action=fixall /bin/umount mode=555 owner=root action=fixall securehosts.linux:: /bin/mount m=6555 o=root action=fixall /bin/umount m=6555 o=root action=fixall One area where cfengine excels over other tools is in its ascii file editing abilities. Editing textfiles in a non-destructive way is such an important operation that having used it you will wonder how you every managed without it! Here are some simple but real examples of how file editing can be used. editfiles: # sun4, who are they kidding? { /etc/hosts.equiv HashCommentLinesContaining "+" } # # CERT security patch for vold vulnerability # sunos_5_4:: { /etc/rmmount.conf HashCommentLinesContaining "action cdrom" HashCommentLinesContaining "action floppy" } TCP wrapper configuration can be managed easily by maintaining a pair of master files on a trusted host. Files of the form # /etc/hosts.allow (exceptions) # # Public services sendmail: ALL in.ftpd: ALL sshd: ALL # Private services in.fingerd: .example.org LOCAL in.cfingerd: .example.org LOCAL sshdfwd-X11: .example.org LOCAL # Portmapper has to use IP series portmap: 128.39.89. 128.39.74. 128.39.75. and # /etc/hosts.deny (default) ALL: ALL may be distributed to each host by cfengine copy: /masterfiles/hosts.deny dest=/etc/hosts.deny mode=644 server=trusted /masterfiles/hosts.allow dest=/etc/hosts.allow mode=644 server=trusted and installed as follows editfiles: { /etc/inet/inetd.conf # Make sure we're using tcp wrappers ReplaceAll "/usr/sbin/in.ftpd" With "/local/sbin/tcpd" ReplaceAll "/usr/sbin/in.telnetd" With "/local/sbin/tcpd" ReplaceAll "/usr/sbin/in.rshd" With "/local/sbin/tcpd" ReplaceAll "/usr/sbin/in.rlogind" With "/local/sbin/tcpd" processes: "inetd" signal=hup The services which we do not need should be removed altogether. There's no sense in tempting fate: editfiles: { /etc/inetd.conf # Eliminate unwanted services HashCommentLinesContaining "rwall" HashCommentLinesContaining "/usr/sbin/in.fingerd" HashCommentLinesContaining "comsat" HashCommentLinesContaining "exec" HashCommentLinesContaining "talk" HashCommentLinesContaining "echo" HashCommentLinesContaining "discard" HashCommentLinesContaining "charge" HashCommentLinesContaining "quotas" HashCommentLinesContaining "users" HashCommentLinesContaining "spray" HashCommentLinesContaining "sadmin" HashCommentLinesContaining "rstat" HashCommentLinesContaining "kcms" HashCommentLinesContaining "comsat" HashCommentLinesContaining "xaudio" HashCommentLinesContaining "uucp" }  File: cfengine-Tutorial.info, Node: Process monitoring, Next: Monitoring files, Prev: Disabling and replacing software, Up: Security and cfengine 7.8 Process monitoring ====================== When it comes to process management we are usually interested in three things: i) making sure certain processes are running, ii) making sure some processes are NOT running and iii) sending HUP signals to force configuration updates. To HUP a daemon and make sure that it is running, we write processes: linux:: "inetd" signal=hup restart "/usr/sbin/inetd" useshell=false "xntp" restart "/local/sbin/xntpd" useshell=false The useshell option tells cfengine that it should not use a shell to start the program. The idea here is to protect against IFS attacks. Unfortunately some programs require a shell in order to be started, but most do not. This is an extra precaution. When the cron daemon crashes, restarting it can be a problem since it does not close its filed descriptors properly when forking. The dumb-option helps here: "cron" matches=>1 restart "/etc/init.d/cron start" useshell=dumb To kill processes which should not be running, we write: processes: solaris:: # # Don't want CDE stuff or SNMP peepholes... # "ttdbserverd" signal=kill "snmpd" signal=kill "mibiisa" signal=kill A couple of years ago, a broken cracked account was revealed at Oslo College by the following test in the cfengine configuration: processes: # Ping attack ? "ping" signal=kill inform=true There are few legimate reasons to run the ping command more than a few times. The chances of cfengine detecting single pings is quite small. But coordinated ping attacks are another story. When it was revealed that a user had twenty ping processes attempting to send large ping packets to hosts in the United States it was obvious the the account had been compromised. Fortunately for the recipient, the ping command was incorrectly phrased and would probably not have been noticed. processes: "sshd" restart "/local/sbin/sshd" useshell=false "snmp" signal=kill "mibiisa" signal=kill "named" matches=>1 restart "/local/bind/bin/named" useshell=false # Do the network community a service and run this "identd" restart "/local/sbin/identd" inform=true Process management also includes the garbage collection which we shall return to briefly.  File: cfengine-Tutorial.info, Node: Monitoring files, Next: The setuid log, Prev: Process monitoring, Up: Security and cfengine 7.9 Monitoring files ==================== Almost all security programs available are for the monitoring of file integrity. Cfengine also incorporates tools for monitoring files. Here are some of the elements in the faily complex files command: files: classes:: /file-object mode=mode owner=uid-list group=gid-list action=fixall/warnall.. ignore=pattern include=pattern exclude=pattern checksum=md5 syslog=true/on/false/off In additions to these, there are extra flags for BSD filesystems and ways of managing file ACLs for systems like NT. Here are some examples of basic checks on file permissions: classes: # Define a class of hosts based on a test... have_shadow = ( `/bin/test -f /etc/shadow` ) NFSservers = ( server1 server2 ) files: any:: /etc/passwd mode=0644 o=root g=other action=fixplain have_shadow:: /etc/shadow mode=0400 o=root g=other action=fixplain # Takes a while so do this at midnight and only on servers NFSservers.Hr00:: /usr/local mode=-0002 Check no files are writable! recurse=inf owner=root,bin group=0,1,2,3,4,5,6,7,staff action=fixall In the last example we parse through a whole file system (recurse=inf) and as a result we get a number of checks for free. Any previously unknown setuid programs are reported as well as any suspicious filenames (see below).  File: cfengine-Tutorial.info, Node: The setuid log, Next: Suspicious filenames, Prev: Monitoring files, Up: Security and cfengine 7.10 The setuid log =================== Cfengine is always on the lookout for files which are setuid or setgid root. It doesn't go actively looking for them uninvited, but whenever you get cfagent to check a file or directory with the files feature, it will make a note of setuid programs it finds there. These are recorded in the file cfengine.host.log which is stored under /var/cfengine or /var/log/cfengine. When new setuid programs are discovered, a warning is printed, but only if you are root. If you ever want a complete list, delete the log file and cfengine will think that all of the setuid programs it finds are new. The log file is not readable by normal users.  File: cfengine-Tutorial.info, Node: Suspicious filenames, Next: Checksums and Tripwire functionality, Prev: The setuid log, Up: Security and cfengine 7.11 Suspicious filenames ========================= Whenever cfagent opens a directory and scans through files and directories (recursively) (files, tidy, copy), it is also on the lookout for for suspicious filenames, i.e. files like ".. ." containing only space and/or dots. Such files are seldom created by sensible sources, but are often used by crackers to try to hide dangerous programs. Cfagent warns about such files. Although not necessarily a security issue, cfagent will also warn about filenames which contain non-printable characters if desired, and directories which are made to look like plain files by giving them filename extensions. control: # # Security checks # NonAlphaNumFiles = ( on ) FileExtensions = ( o a c gif jpg html ) # etc SuspiciousNames = ( .mo lrk3 lkr3 ) The file extension list may be used to detect concealed directories during these searches, if users create directories which look like common files this will be warned about. Additional suspicious filenames can be checked for automatically as a matter if course. This is commented further below. The mail spool directory is a common place for users to try to hide dowloaded files. These options inform about files which do not have the name of a user or are not owned by a valid user: control: WarnNonOwnerMail = ( true ) WarnNonUserMail = ( true ) # Warn about mail which is not owned by a user Corresponding commands exist to delete these files without further ado. This can be a useful way of cleaning up after users whose accounts have been removed.  File: cfengine-Tutorial.info, Node: Checksums and Tripwire functionality, Next: FileExtensions, Prev: Suspicious filenames, Up: Security and cfengine 7.12 Checksums and Tripwire functionality ========================================= Cfagent can be used to check for changes in files which only something as exacting as an MD5 checksum/digest can detect. If you specify a checksum database and activate checksum verification, control: ChecksumUpdates = ( false ) files: /filename checksum=md5 .... /dirname checksum=md5 recurse=inf.... # If the database isn't secure, nothing is secure... /var/cfengine/cache.db mode=600 owner=root action=fixall then cfagent will build a database of file checksums and warn you when files' checksums change. This makes cfagent act like Tripwire (currently only with MD5 checksums). It can be used to show up Trojan horse versions of programs. It should be used sparingly though since database management and MD5 checksum computation are resource intensive operations and this could add significant time to a cfagent run. The ChecksumUpdates variable (normally false) can be set to true to update the checksum database when programs change for valid reasons. Warnings are all every fine and well, but the spirit of cfengine is not to bother us with warnings, it is to fix things automatically. Warning is a useful supplement, but in security breaches it is better to fix the problem, rather than leaving the host in a dangerous state. If you are worried about the integrity of the system then don't just warn about checksum mismatches here, make an md5 copy comparison against a read-only medium which has correct, trusted version of the file on it. That way if a binary is compromised you will not only warn about it but also repair the damage immediately! The control variable ChecksumUpdates may be switched to on in order to force cfagent to update its checksum database after warning of a change.  File: cfengine-Tutorial.info, Node: FileExtensions, Next: NonAlphaNumFiles, Prev: Checksums and Tripwire functionality, Up: Security and cfengine 7.13 FileExtensions =================== This list may be used to define a number of extensions which are regarded as being plain files by the system. As part of the general security checking cfagent will warn about any directories which have names using these extensions. They may be used to conceal directories. FileExtensions = ( c o gif jpg html )  File: cfengine-Tutorial.info, Node: NonAlphaNumFiles, Next: Defensive garbage collection, Prev: FileExtensions, Up: Security and cfengine 7.14 NonAlphaNumFiles ===================== If enabled, this option causes cfagent to detect and disable files which have purely non-alphanumeric filenames, i.e. files which might be accidental or deliberately concealed. The files are then marked with a suffix .cf-nonalpha and are rendered visible. NonAlphaNumFiles = ( on ) These files can then be tidied (deleted) or disabled by searching for the suffix pattern. Note that alphanumeric means ascii codes less than 32 and greater than 126.  File: cfengine-Tutorial.info, Node: Defensive garbage collection, Next: Anonymous FTP example, Prev: NonAlphaNumFiles, Up: Security and cfengine 7.15 Defensive garbage collection ================================= We tend to be worried about the fact that crackers will destroy our systems and make them unusable, but many operating systems are programmed to do this to themselves! There are few systems which can survive a full system disk and yet many logging agents go on filling up disks without ever checking to see how full they are getting. In short they choke themselves in a self-styled denial of service attack. Cfagent can help here by rotating logs frequently and by tidying temporary file directories: disable: Tuesday.Hr00:: # # Disabling these log files weekly prevents them from # growing so enormous that they fill the disk! # /local/iu/httpd/logs/access_log rotate=2 /local/iu/httpd/logs/agent_log rotate=2 /local/iu/httpd/logs/error_log rotate=2 /local/iu/httpd/logs/referer_log rotate=2 FTPserver.Sunday:: /local/iu/logs/xferlog rotate=3 tidy: /tmp pattern=* age=1 Process garbage collection is just as important. There are lot's of reasons why process tables fill up with unterminated processes. One example is faulty X terminal software which does not kill its children at logout. Another is that programs like netscape and pine tend to go into loops from which they never return, gradually loading the system with an ever increasing glacial burden. Just killing old processes can cause your system to spring back from its ice age blues (hopefully without littering the system with too many dead mammoths or bronze age axe-bearers). If the host concerned has important duties then this lack of responsiveness can compromise key services. It also gives local users a way of carrying out denial of service attacks on the system. If users always log out at the end of the day and log in again the day after then this is easy to address with cfengine. Here is some code to kill commonly hanging processes. Note that on BSD like systems process options "aux" are required to see the relevant processes: processes: linux|freebsd|sun4:: SetOptionString "aux" any:: "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec" signal=kill include=ftpd include=tcsh include=xterm include=netscape include=ftp include=pine include=perl include=irc include=java include=/bin/ls include=emacs include=passwd This pattern works like this: as processes become more than a day old they name of the month appears in the date of the process start time. These are matched by the regular expression. The include lines then filter the list of the processes further picking out lines which include the specified strings. On some BSD-like systems the default ps option string is "-ax" and you might need to reset it to something which adds the start date in order to make this work. Another job for process management is to clean up processes which have hung, gone amok or which are left over from old logins. Here is a regular expression which detects non-root processes which have clocked up more than 100 hours of CPU time. This is a depressingly common phenomenon when a program goes into an infinite loop. It can starve other processes of resources in a very efficient denial of service attack. any:: # # Kill processes which have run on for too long e.g. 999:99 cpu time # Careful a pattern to match 99:99 will kill everything! # "[0-9][0-9][0-9][0-9]:[0-9][0-9]" signal=term exclude=root "[0-9][0-9][0-9]:[0-9][0-9]" signal=term exclude=root Under NT this is not so simple, since the process table for the cygwin library applies only to processes which have been started by programs working under the Unix process emulation. Hopefully this short-coming can be worked around at some point in the future.  File: cfengine-Tutorial.info, Node: Anonymous FTP example, Next: WWW security, Prev: Defensive garbage collection, Up: Security and cfengine 7.16 Anonymous FTP example ========================== Configuring a service like anonymous FTP requires a certain amount of vigilance. It is a good idea to automate it and let cfengine make sure that things don't go astray. Note that we constantly ensure that the ls program used by the anonymous ftp server is a trusted program by checking it with an md5 signture of a trusted version of the program. If for some reason it should be replaced with a Trojan horse, cfagent would notice the incorrect checksum (md5) and move the bad program to ls.cf-saved and immediately replace it with the correct version without waiting for the adminstrator to act. The inform and syslog options ask for an explicit warning to be made about this copy. Here is a complete anonymous ftp setup and maintenance program for Solaris hosts. control: actionsequence = ( directories copy editfiles files ) # Define variables ftp = ( /usr/local/ftp ) uid = ( 99 ) # ftp user gid = ( 99 ) # ftp group directories: solaris:: $(ftp)/pub mode=644 owner=root group=other $(ftp)/etc mode=111 owner=root group=other $(ftp)/dev mode=555 owner=root group=other $(ftp)/usr mode=555 owner=root group=other $(ftp)/usr/lib mode=555 owner=root group=other files: solaris:: $(ftp)/etc/passwd mode=644 o=root action=fixplain $(ftp)/etc/shadow mode=400 o=root action=fixplain $(ftp)/pub mode=644 owner=ftp action=fixall recurse=inf copy: solaris:: # Make sure ls is a trusted program by copying # a secure location... /bin/ls dest=$(ftp)/usr/bin/ls mode=111 owner=root type=checksum inform=true syslog=true /etc/netconfig dest=$(ftp)/etc/netconfig mode=444 o=root /devices/pseudo/mm@0:zero dest=$(ftp)/dev/zero mode=666 o=root /devices/pseudo/clone@0:tcp dest=$(ftp)/dev/tcp mode=444 o=root /devices/pseudo/clone@0:udp dest=$(ftp)/dev/udp mode=666 o=root /devices/pseudo/tl@0:ticotsord dest=$(ftp)/dev/ticotsord mode=666 o=root /usr/lib dest=$(ftp)/usr/lib recurse=2 mode=444 owner=root backup=false include=ld.so* include=libc.so* include=libdl.so* include=libmp.so* include=libnsl.so* include=libsocket.so* include=nss_compat.so* include=nss_dns.so* include=nss_files.so* include=nss_nis.so* include=nss_nisplus.so* include=nss_xfn.so* include=straddr.so* /usr/share/lib/zoneinfo dest=$(ftp)/usr/share/lib/zoneinfo mode=444 recurse=2 o=root type=binary editfiles: solaris:: # # Make sure that umask is right for ftpd # or files can be left 666 after upload! # { /etc/rc2.d/S72inetsvc PrependIfNoSuchLine "umask 022" } { $(ftp)/etc/passwd AutoCreate EmptyEntireFilePlease AppendIfNoSuchLine "ftp:x:$(uid):$(gid):Anonymous FTP:$(ftp):/bin/sync" } { $(ftp)/etc/group AutoCreate EmptyEntireFilePlease AppendIfNoSuchLine "ftp::$(gid):" } { $(ftp)/etc/shadow AutoCreate EmptyEntireFilePlease AppendIfNoSuchLine "ftp:NP:6445::::::" } # Finally...useful for chown { /etc/passwd AppendIfNoSuchLine "ftp:x:$(uid):$(gid):Anonymous FTP:$(ftp):/bin/sync" } { /etc/group AppendIfNoSuchLine "ftp::$(gid):" }  File: cfengine-Tutorial.info, Node: WWW security, Next: Miscellaneous security of cfengine itself, Prev: Anonymous FTP example, Up: Security and cfengine 7.17 WWW security ================= The security of the web is a slightly paradoxical business. On the one hand, we make a system for distributing files to anyone without the need for passwords, and on the other hand we are interested in limited who gets what information and who can change what. If you want web privacy you have to exclude the possibility of running untrusted CGI scripts, i.e. CGI programs which you did not write yourself since CGI programs can circumvent any server security. This is because of a fundamental weakness in the way that a WWW server works. It makes user-CGI scripts incompatible with the idea of private WWW areas. The problem with CGI is this: in order for the httpd daemon to be able to read information to publish it, that information must be readable by the UID with which httpd runs (e.g. the www special user (you should not run with uid nobody since that can be mixed up with NFS mappings)). But CGI programs automatically run with this www UID also. Since it is not possible to restrict the actions of CGI programs which you did not write yourself, any CGI program has automatically normal file permission access to any file which the server can see. A CGI program could choose to open a restricted file circumventing the security of the daemon. In short, privacy requires a separate UID (a separate daemon and port number) or a separate server host altogether. Provided you acknowledge this weakness, you can still use cfengine to administrate the permissions and access files on say two WWW servers from your central location. Let us imagine having a public WWW server and a private WWW server and assume that they have a common user/UID database. We begin by defining a user-ID and group-ID for the public and private services. These need to have different ID's in order to prevent the CGI trick mentioned above. editfiles: wwwpublic:: { $(publicdocroot)/.htaccess AutoCreate EmptyEntireFilePlease AppendLine "order deny,allow" AppendLine "deny from all" AppendLine "allow from all" } wwwprivate:: { $(privatedocroot)/.htaccess AutoCreate EmptyEntireFilePlease AppendLine "order deny,allow" AppendLine "deny from all" AppendLine "allow .example.org" } Your documnts should be owned by a user and group which is *not* the same as the UID/GID the daemon runs with, otherwise CGI programs and server-side emebellishments could write and destroy those files. You will also want to ensure that the files are readable by the www daemon, so a files command can be used to this end. You might want a group of people to have access to the files to modifiy their contents. files: wwwprivate:: $(privatedocroot) mode=664 owner=priv-data group=priv-data act=fixall wwwpublic:: $(publicdocroot) mode=664 owner=public-data group=public-data act=fixall  File: cfengine-Tutorial.info, Node: Miscellaneous security of cfengine itself, Next: Privacy (encryption), Prev: WWW security, Up: Security and cfengine 7.18 Miscellaneous security of cfengine itself ============================================== control: SecureInput = ( on ) If this is set cfengine will not read any files which are not owned by the uid running the program, or which are writable by groups or others.  File: cfengine-Tutorial.info, Node: Privacy (encryption), Next: Trust and key races, Prev: Miscellaneous security of cfengine itself, Up: Security and cfengine 7.19 Privacy (encryption) ========================= Encryption (privacy) is not often a big deal in system administration. With the exception of the distribution of passwords and secret keys themselves, there is little or no reason to maintain any level of privacy when transferring system files (binaries for instance). If you find yourself using a tool like cfengine to transmit company secrets from one place to another you should probably book yourself into the nearest asylum for a checkup. Cfengine is not about super-secure communication, but it can be used to perform the simple job of file distribution through an encrypted link (e.g. as a NIS replacement or other password distributor). Cfengine uses the triple DES implemenation in the OpenSSL distribution (or equivalent) to provide `good enough' privacy during remote copying. The most important issue in system security is authentication. Without the ability to guarantee the identity of a user or of trusted information it is impossible to speak of security at all. Although services like pidentd can go some way to confirming the identity of a user, the only non-spoofable way of confirming identity is to use a shared secret -- i.e. a password. A password works by demanding that two parties who want to trust one another must both know a piece of information which untrusted parties do not. Following the second world war, the now famous pair, Julius and Ethel Rosenberg were convicted and executed for spying on the U.S. bomb project for the Soviet Union in 1953. At one point they improvised a clever password system: a cardboard Jell-O box was torn in two and one half given to a contact whom they later would need to identify. The complex edge shape and colour matching made a complex key quite impossible to forge. Our bodies use a similar method of receptor identification of molecules for immune responses as well as for smell (with some subtleties). Without matching secrets it is impossible to prove someone's identity. To copy a file over an encrypted link, you write: copy: source dest=destination encrypt=true server=myserver trustkey=true Bear in mind that the server must be a trusted host. Privacy won't help you if the data you are collecting are faulty. In order to use the encryption there must be a public/private key pair on each host. The public key must be known by both hosts. You can use the program cfkey to generate a new key file. This public key file must then be distributed. Cfagent/cfrun and cfservd can exchange keys securely over the network. This is fine, provided you trust the sources of the keys (how do you know the key is from the host/user who claims to have sent it?). Under encrypted communications cfengine conceals the names and contents of files. Provided the private key files are private, this has the added side effect of authenticating both hosts for one another. On the server side, you can choose whether root on a client host should have server-root's privileges to read protected files on the server. In the `cfservd.conf' file you make a list: control: TrustKeysFrom = ( IP-ADDRESS/SERIES ) admit: /filetree *.domain.country root=myhost,yourhost /etc/shadow *.domain.country encrypt=true In the second example, you can also restrict access to certain files to encrypted lines, i.e. demand that clients use a private connection to collect the file, in order to prevent wiretapping.  File: cfengine-Tutorial.info, Node: Trust and key races, Next: Adaptive locks, Prev: Privacy (encryption), Up: Security and cfengine 7.20 Trust and key races ======================== Trust is the central issue in the security of any system. Public and private keys help you to trust other hosts, only after the genuine, legitimate public keys have been securely distributed to all relevant parties. Until that has happened, it is necessary to trust the identity of remote hosts. Cfengine provides trust policy options which decide whether keys should be exchanged on trust or not, when remote parties connect for the first time. If you do not want to blindly trust keys, you could arrange to exchange key files manually, e.g. scp /var/cfengine/ppkeys/localhost.pub remote:/var/cfengine/ppkeys/root-IP-NUMBER.pub or you could arrange to connect at a specific time, so minimize the chances of spoofer racing you to the finishing line in transferring a key for a given user at a given host. Note that, even program like ssh which use "privileged ports" are no longer immune to spoofing. Privileged ports are ports which only the root user can bind to. The idea used to be, a connection on a privileged port must have come from a trusted user, because only someone with the root/Administrator password would be able to bind to a privileged port. Today, that idea is naive at best. Anyone can set up their own host, pull the plug on another and spoof an address or user identity - there are so many ways to attack a system that it is impossible to know with certainty to whom one is talking over the net. The only security one has is in being able to keep a secret key. However, if someone gets there before you, with a fake key, and claims to be you, the receiver cannot know better. This applies to any and all cryptographic software. Cfengine secure copy is not based on SSL/TLS (although it shares some of the lower level libraries). SSL is not appropriate for a system administration tool, because it uses a trust model based on a third party, such as Verisign. Most adminisrators are not prepared to pay a fee to register every host on their network, with a trusted third party. Cfengine does not use the Secure Shell protocol either. The ssh protocol is not directly appropriate for a system management tool, because it provides only unilateral authentication of user to server. Cfengine authenticates these parties mutually, i.e. user to server, and server to user. Moreover, ssh requires a user to manually accept a key on trust, when the public keys are unknown to the parties, whereas cfengine works non-interactively. SSh uses the notion of binding to a trusted port, to confirm privileged user identity. Cfengine does not make this assumption.  File: cfengine-Tutorial.info, Node: Adaptive locks, Next: Spoofing, Prev: Trust and key races, Up: Security and cfengine 7.21 Adaptive locks =================== Cfengine treats all of its operations as transactions which are locked. Locking prevents contention from competing processes and it also places reasonable limits on the execution of the program. The fact that operations are locked means that several cfengine programs can coexist without problems. Two locking parameters control the way in which operations can procure locks. The IfElapsed parameter tells operations that they can only be performed if a certain period of time has elapsed since the last time the action was performed. This is anti-spamming protection. The ExpireAfter parameter tells cfengine that no action should last more than a given length of time. This is protection against hanging sub-processes.  File: cfengine-Tutorial.info, Node: Spoofing, Next: Race conditions in file copying, Prev: Adaptive locks, Up: Security and cfengine 7.22 Spoofing ============= Spoofing refers to attempts to masquerade as another host when sending network transmissions. The cfservd program which can be used to transfer files or activate cfengine remotely attempts to unmask such attempts by performing double reverse lookups in the name service. This verifies by a trusted server that the socket address and the host name are really who they claim to be.  File: cfengine-Tutorial.info, Node: Race conditions in file copying, Next: size= in copy, Prev: Spoofing, Up: Security and cfengine 7.23 Race conditions in file copying ==================================== When copying files from a source, it is possible that something might go wrong during the operation and leave a corrupt file in place. For example, the disk might become full while copying a file. This could lead to problems. Cfengine deals with this by always copying to a new file on the destination filesystem (prefix .cfnew) and then renaming it into place, only if the transfer was successful. This ensures that there is space on the filesystem and that nothing went wrong with the network connection or the disk during copying.  File: cfengine-Tutorial.info, Node: size= in copy, Next: useshell= and owner= in shellcommands, Prev: Race conditions in file copying, Up: Security and cfengine 7.24 size= in copy ================== As a further check on copying, cfengine allows you to define acceptable limits on the size of files. After all, sometimes errors might occur quite independently of anything you are doing with cfengine. Perhaps the master password file got emptied somehow, or got replaced by a binary, through some silly mistake. By checking making an estimate of the expected size of the file and adding it to the copy command, you can avoid installing a corrupt file and making a localized problem into a global one.  File: cfengine-Tutorial.info, Node: useshell= and owner= in shellcommands, Next: Firewalls, Prev: size= in copy, Up: Security and cfengine 7.25 useshell= and owner= in shellcommands ========================================== There are dangers in starting scripts from programs which run with root privileges. Normally, shell commands are started by executing them with the help of a /bin/sh -c command. The trouble with this is that it leaves one open to a variety of attacks. One example is fooling the shell into starting foreign programs by manipulating the IFS variable to treat '/' as a separator. You can ask cfengine to start programs directly, without involving an intermediary shell, by setting the useshell variable to false. The disadvantage is that you will not be able to use shell directives such as | and > in your commands. The owner=uid directive executes shell commands as a special user, allowing you to safely run scripts without root privilege.  File: cfengine-Tutorial.info, Node: Firewalls, Prev: useshell= and owner= in shellcommands, Up: Security and cfengine 7.26 Firewalls ============== Cfengine is a useful tool for implementing, monitoring and maintaining firewalls. You can control what programs are supposed to be on the firewall and what programs are not supposed to be there. You can control file permissions, processes and a dozen other things which make up the configuration of a bastion host. By referencing important programs against a read only medium you can not only monitor host integrity but always be certain that you are never more than a cfengine execution away from correctness.  File: cfengine-Tutorial.info, Node: Summary, Next: Variable Index, Prev: Security and cfengine, Up: Top 8 Summary ********* Cfengine is not a tool, it is an environment for managing host configuration and integrity. In this article it has only been possible to scratch the surface of what cfengine can do. To fully understand the syntax of the examples here you should read the documentation for cfengine. The big advantage of cfengine over many other configuration schemes is that you can have *everything* in one file (or set of files). The global file is common to every host and yet it can be as general or as specific as you want it to be. You can use it as a front end for cron, and you can use its advanced features to make your hosts *converge* to a desired, correct state.  File: cfengine-Tutorial.info, Node: Variable Index, Next: Concept Index, Prev: Summary, Up: Top Variable Index ************** [index] * Menu: * !: Classes basics. (line 133) * ": Quoted strings. (line 30) * $(arch): Variable substitution. (line 114) * $(binserver): Variable substitution. (line 118) * $(class): Variable substitution. (line 122) * $(cr): Variable substitution. (line 206) * $(date): Variable substitution. (line 127) * $(dblquote): Variable substitution. (line 209) * $(dollar): Variable substitution. (line 212) * $(domain): Variable substitution. (line 130) * $(faculty): Variable substitution. (line 133) * $(fqhost): Variable substitution. (line 137) * $(host): Variable substitution. (line 140) * $(ipaddress): Variable substitution. (line 144) * $(lf): Variable substitution. (line 215) * $(n): Variable substitution. (line 218) * $(quote): Variable substitution. (line 221) * $(site): Variable substitution. (line 171) * $(spc): Variable substitution. (line 225) * $(sysadm): Variable substitution. (line 178) * $(tab): Variable substitution. (line 228) * $(timezone): Variable substitution. (line 181) * $(year): Variable substitution. (line 189) * ': Quoted strings. (line 30) * -a option: Variable substitution. (line 274) * -D option: Classes basics. (line 131) * -f option <1>: CFINPUTS environment variable. (line 10) * -f option: Invoking cfagent. (line 23) * -h option: Invoking cfagent. (line 27) * -N option <1>: Debugging tips. (line 19) * -N option: Classes basics. (line 131) * -n option: Invoking cfagent. (line 23) * -v option: Invoking cfagent. (line 23) * /etc/exports: Using netgroups. (line 6) * /var/cfengine/cfengine.log: Log files. (line 17) * /var/cfengine/output: Running cfengine permanently monitoring and restarting cfexecd. (line 12) * `: Quoted strings. (line 30) * acl: ACLs. (line 74) * any: The generic class any. (line 6) * binserver <1>: Special variables. (line 6) * binserver: Variable substitution. (line 6) * CFALLCLASSES: Variable substitution. (line 110) * domain: Variable substitution. (line 6) * exclude=: File sweeps. (line 50) * exec: Variable substitution. (line 68) * faculty: Variable substitution. (line 6) * filter=: File sweeps. (line 50) * host: Variable substitution. (line 6) * include=: File sweeps. (line 50) * MaxCfengines: Variable substitution. (line 150) * moduledirectory: Writing plugin modules. (line 16) * OutputPrefix: Variable substitution. (line 163) * repchar: Variable substitution. (line 167) * site: Variable substitution. (line 6) * smtpserver: Running cfengine permanently monitoring and restarting cfexecd. (line 22) * Split: Iterating over lists. (line 33) * split: Variable substitution. (line 175) * sysadm <1>: Variable substitution. (line 6) * sysadm: Running cfengine permanently monitoring and restarting cfexecd. (line 22) * timezone: Variable substitution. (line 6) * underscoreclasses: Variable substitution. (line 186)  File: cfengine-Tutorial.info, Node: Concept Index, Next: FAQ Index, Prev: Variable Index, Up: Top Concept Index ************* [index] * Menu: * !: Classes basics. (line 133) * -h option: Invoking cfagent. (line 27) * -N option: Debugging tips. (line 19) * .cfdisabled files: Disabling and the file repository. (line 45) * .cfengine.rm: Log files. (line 6) * .cfnew files: Emulating rdist. (line 49) * .cfsaved files: Disabling and the file repository. (line 45) * /etc/hosts.equiv: Disabling and the file repository. (line 9) * /etc/inetd.conf file and cfengine: Emulating rdist. (line 27) * /home: Using the automounter. (line 84) * /users: Using the automounter. (line 84) * /var/adm/wtmpx: Disabling and the file repository. (line 24) * /var/cfengine/cfengine.log: Log files. (line 6) * /var/cfengine/output: Running cfengine permanently monitoring and restarting cfexecd. (line 12) * /var/log/cfengine/cfengine.log: Log files. (line 6) * /var/lp/logs/lpsched: Disabling and the file repository. (line 24) * Access control: Access control. (line 18) * Access control and symlinks: Configuration file cfservd.conf. (line 193) * Access control by directory: Configuration file cfservd.conf. (line 193) * Access control in cfservd: Configuration file cfservd.conf. (line 193) * Access control lists: ACLs. (line 6) * ACL aliases: ACLs. (line 74) * ACLs: ACLs. (line 6) * ACLs, DFS: ACLs. (line 181) * ACLs, Solaris: ACLs. (line 178) * Actions, order of: Program structure. (line 42) * AFS: Using the automounter. (line 78) * Annulling entries when debugging: Debugging tips. (line 19) * Atomic operations in cfagent: Spamming and security. (line 106) * Atoms in cfagent: Spamming and security. (line 106) * auto_direct: Using the automounter. (line 34) * auto_master: Using the automounter. (line 34) * automount: Using the automounter. (line 6) * Backup policy: Files and links. (line 111) * Binary server: NFS filesystem resources. (line 20) * Binary server, matching: Special variables. (line 33) * Binary servers, declaring: How does it work?. (line 6) * binserver variable and actionsequence: Special variables. (line 33) * cfagent, starting: Invoking cfagent. (line 6) * cfagent.conf <1>: CFINPUTS environment variable. (line 18) * cfagent.conf: Invoking cfagent. (line 16) * cfagent.conf file: What services?. (line 16) * CFALLCLASSES: Variable substitution. (line 110) * cfengine model: NFS resources. (line 6) * cfengine model, how it works: How does it work?. (line 6) * cfexecd <1>: Running cfengine permanently monitoring and restarting cfexecd. (line 22) * cfexecd: Functionality. (line 37) * cfexecd restarting by processes: Running cfengine permanently monitoring and restarting cfexecd. (line 59) * CFINPUTS variable <1>: Configuration file cfservd.conf. (line 20) * CFINPUTS variable: CFINPUTS environment variable. (line 10) * cfrun: Access control. (line 20) * cfrun program <1>: Remote execution of cfagent. (line 21) * cfrun program <2>: Emulating rdist. (line 64) * cfrun program: What services?. (line 8) * cfservd and access keyword: Access control. (line 22) * cfservd daemon: What services?. (line 8) * cfservd dameon: Remote execution of cfagent. (line 21) * cfservd.conf file <1>: Configuration file cfservd.conf. (line 6) * cfservd.conf file: What services?. (line 23) * cfwatcher program: What services?. (line 8) * Class data and scripts: Variable substitution. (line 110) * Class, generic any: The generic class any. (line 6) * Classes: Classes basics. (line 6) * Classes based on shell commands: shellcommand classes. (line 25) * Classes, compound: Classes basics. (line 95) * Classes, defining and undefining: Classes basics. (line 131) * Clock synchronization during copying: Emulating rdist. (line 46) * Comments: Program structure. (line 6) * Compound classes: Classes basics. (line 95) * Config file, default name: Invoking cfagent. (line 16) * Configuration files and registries: Control files. (line 6) * Contention during copying under load: Splaying host times. (line 30) * copy, file sweeps: File sweeps. (line 16) * core files, caution!: Files and links. (line 137) * Cron jobs, controlling with cfengine: Using cfengine as a front-end for cron. (line 21) * Day of the week: Building flexible time classes. (line 24) * Deadlock protection: Deadlocks and runaway loops. (line 10) * Debugging, annulling entries: Debugging tips. (line 19) * Default file: Invoking cfagent. (line 16) * Defining variables using other variables: Variable substitution. (line 62) * Device boundaries and remote copy access: Configuration file cfservd.conf. (line 193) * DFS: Using the automounter. (line 78) * DHCP: Network interface. (line 22) * Directory Names, use of wildcards: Wildcards in directory names. (line 6) * Distributed configuration: Building a distributed configuration. (line 6) * DNS: Name servers (DNS). (line 6) * Dots in hostnames: Classes basics. (line 194) * editfiles, file sweeps: File sweeps. (line 19) * Environment variable, CFINPUTS: CFINPUTS environment variable. (line 10) * Environment variables: Variable substitution. (line 6) * Exceptions: Defining classes. (line 6) * exclude=: File sweeps. (line 50) * exclude=, problems: File sweeps. (line 79) * Excluding actions in a controlled way: Defining classes. (line 6) * ExpireAfter, caution setting to zero!: Deadlocks and runaway loops. (line 22) * Exporting filesystems <1>: Special variables. (line 44) * Exporting filesystems: Using netgroups. (line 6) * File search paths: CFINPUTS environment variable. (line 10) * Files, checking permissions: Monitoring important files. (line 6) * Files, configuration: Control files. (line 6) * Files, control: Control files. (line 6) * files, file sweeps: File sweeps. (line 11) * filter=: File sweeps. (line 50) * Format: Program structure. (line 47) * Free format: Program structure. (line 47) * Fully qualified names: Classes basics. (line 194) * Functions, in-built: Variable substitution. (line 80) * Grouping time values: Building flexible time classes. (line 51) * groups and time intervals: Building flexible time classes. (line 51) * Hard class name collision: Variable substitution. (line 186) * Hard links: Making links. (line 31) * Help: Invoking cfagent. (line 27) * Home directories and automount: Using the automounter. (line 84) * Home server: NFS filesystem resources. (line 20) * Home servers, declaring: How does it work?. (line 6) * Host name gets truncated: Classes basics. (line 194) * Hostname collision: Variable substitution. (line 186) * HUP and cfservd, don't need to: Installation of cfservd. (line 29) * ifconfig: Network interface. (line 6) * IfElapsed, caution setting to zero!: Deadlocks and runaway loops. (line 22) * ignore=: File sweeps. (line 46) * Ignoring, private lists in files, copy and links: File sweeps. (line 46) * Immune identity: Privacy (encryption). (line 37) * In-built functions: Variable substitution. (line 80) * include=: File sweeps. (line 50) * Infinite loops: Deadlocks and runaway loops. (line 10) * Invoking cfagent: Invoking cfagent. (line 6) * Iteration over lists: Iterating over lists. (line 33) * Linking to binservers: Special variables. (line 6) * Links: Making links. (line 6) * Links in access control: Configuration file cfservd.conf. (line 193) * Load balancing: Splaying host times. (line 30) * localhost and remote copying: Deadlocks and runaway loops. (line 30) * Lock files for ordinary users: Spamming and security. (line 129) * Log files: Log files. (line 6) * Log files, rotating: Disabling and the file repository. (line 39) * Logical NOT: Classes basics. (line 133) * Macros: Variable substitution. (line 6) * Mailing output: Running cfengine permanently monitoring and restarting cfexecd. (line 22) * moduledirectory: Writing plugin modules. (line 16) * Modules, user defined plug-ins: Defining classes. (line 20) * Monitoring important files: Monitoring important files. (line 6) * Months: Building flexible time classes. (line 20) * Mount points: Unique filesystem mountpoints. (line 6) * Multiple package configuration: Iterating over lists. (line 83) * Musts in cfengine: What you must have. (line 6) * Name collision: Variable substitution. (line 186) * Name server: Name servers (DNS). (line 6) * Naming convention: Unique filesystem mountpoints. (line 6) * Nested macros: Variable substitution. (line 62) * netgroups: Using netgroups. (line 6) * network configuration: Network interface. (line 6) * network interface: Network interface. (line 6) * NFS: Network File System (NFS). (line 6) * NFS mounted filesystems: NFS resources. (line 6) * NFS resources: NFS filesystem resources. (line 6) * NIS: Using netgroups. (line 6) * NOT operator: Classes basics. (line 133) * Operator ordering: Classes basics. (line 196) * Optional features in cfagent: Options. (line 6) * Order of actions: Program structure. (line 42) * Ordinary users, lock files: Spamming and security. (line 129) * Output logs: Running cfengine permanently monitoring and restarting cfexecd. (line 12) * Package configuration, multiple: Iterating over lists. (line 83) * Path to input files: CFINPUTS environment variable. (line 10) * Patterns: Wildcards in directory names. (line 20) * Permissions, extended: ACLs. (line 6) * Piping input into cfengine: CFINPUTS environment variable. (line 16) * Plug-in modules: Defining classes. (line 20) * Policy for running the system: General considerations. (line 12) * Privileged ports: Trust and key races. (line 34) * processes cannot start cfexecd: Running cfengine permanently monitoring and restarting cfexecd. (line 59) * Program format: Program structure. (line 47) * Program structure: Program structure. (line 6) * Quoting strings: Quoted strings. (line 30) * Race condition: Security in File sweeps. (line 21) * Race condition with public keys: Trust and key races. (line 19) * Random numbers: Variable substitution. (line 80) * rdist program: What services?. (line 41) * Remote distribution of files: What services?. (line 41) * Remote execution of cfagent <1>: Remote execution of cfagent. (line 6) * Remote execution of cfagent: What services?. (line 41) * Rereading cfservd.conf: Installation of cfservd. (line 29) * Restarting cfexecd: Running cfengine permanently monitoring and restarting cfexecd. (line 59) * Restarting cfservd: Installation of cfservd. (line 29) * Restricting access: Access control. (line 18) * Rotating files: Disabling and the file repository. (line 39) * Running cfagent remotely: Remote execution of cfagent. (line 21) * Scripts, passing classes to: Variable substitution. (line 110) * Sections, order of: Program structure. (line 42) * Security, link races and travlinks: Security in File sweeps. (line 26) * server=: Emulating rdist. (line 32) * server= when copying to localhost: Deadlocks and runaway loops. (line 30) * setgid root log: Log files. (line 24) * setuid root log: Log files. (line 24) * Setuid scripts: Access control. (line 18) * Shell commands which define classes: shellcommand classes. (line 25) * Special variables: Special variables. (line 6) * Splaying host times: Splaying host times. (line 30) * Split: Iterating over lists. (line 33) * Starting cfagent: Invoking cfagent. (line 6) * STDIN, reading from: CFINPUTS environment variable. (line 16) * Strings: Quoted strings. (line 30) * Structure of a program: Program structure. (line 6) * Symbolic links in admit: Configuration file cfservd.conf. (line 193) * System administrator, name: Variable substitution. (line 274) * System policy: General considerations. (line 12) * tidy, file sweeps: File sweeps. (line 13) * Tidying files: Files and links. (line 111) * Time classes: Building flexible time classes. (line 6) * Timestamp backups: Disabling and the file repository. (line 53) * travlinks: Security in File sweeps. (line 23) * Trusted Third Party: Trust and key races. (line 38) * underscoreclasses: Variable substitution. (line 186) * User programs which define classes: shellcommand classes. (line 25) * Variable substitution: Variable substitution. (line 6) * Variables and Macros: Variable substitution. (line 6) * Variables, cfengine: Variable substitution. (line 6) * Variables, cfengine model: Special variables. (line 6) * Variables, environment: Variable substitution. (line 6) * Variables, setting to result of a shell command: Variable substitution. (line 68) * Variables, using: Variable substitution. (line 251) * Verifying with -n option: Invoking cfagent. (line 37) * Wildcard, any class: The generic class any. (line 6) * Wildcards: Wildcards in directory names. (line 20) * Wildcards, in directory names: Wildcards in directory names. (line 6) * Work Directory: Where should I put the files?. (line 27) * Years: Building flexible time classes. (line 12)  File: cfengine-Tutorial.info, Node: FAQ Index, Prev: Concept Index, Up: Top FAQ Index ********* [index] * Menu: * Brackets (parentheses) in classes.: Classes basics. (line 196) * Configure multiple packages: Iterating over lists. (line 83) * Define classes based on result of user program: shellcommand classes. (line 25) * How can I make complex time intervals using time classes?: Building flexible time classes. (line 6) * How can I use cfengine to make a global cron file?: Using cfengine as a front-end for cron. (line 31) * How do I quote quotes?: Quoted strings. (line 30) * How to keep all users in /home: Using the automounter. (line 89) * Iterating over lists: Iterating over lists. (line 33) * Parentheses in classes.: Classes basics. (line 196) * Split, using a space: Iterating over lists. (line 63) * Time classes, picking out complex time intervals: Building flexible time classes. (line 6) * Why do I get network access denied to files I have granted access to?: Configuration file cfservd.conf. (line 193) * Why does cfservd give access to files on a different filesystem?: Configuration file cfservd.conf. (line 193)  Tag Table: Node: Top475 Node: Overview1001 Node: What is cfengine?1433 Node: Site configuration6172 Node: Key concepts8807 Node: Control files9371 Node: Network interface10567 Node: Network File System (NFS)11723 Node: Name servers (DNS)14199 Node: Monitoring important files15733 Node: Making links17180 Node: Functionality18785 Node: Getting started20075 Node: What you must have20638 Node: Program structure26361 Node: Building a distributed configuration29834 Node: Startup update.conf30904 Node: Startup cfservd.conf33896 Node: Where should I put the files?35347 Node: Options38394 Node: Invoking cfagent41359 Node: Running cfengine permanently monitoring and restarting cfexecd43319 Node: CFINPUTS environment variable45955 Node: What to aim for47530 Node: More advanced concepts49562 Node: Classes basics50207 Node: Variable substitution58594 Node: Undefined variables67012 Node: Defining classes67962 Node: Command line classes69356 Node: actionsequence classes70478 Node: shellcommand classes71645 Node: Feedback classes72924 Node: Writing plugin modules73755 Node: The generic class any76985 Node: Debugging tips77507 Node: Access control78187 Node: Wildcards in directory names79233 Node: File sweeps80479 Node: Security in File sweeps84237 Node: Log files85665 Node: Quoted strings86978 Node: Regular expressions88158 Node: Iterating over lists92881 Node: Global configurations95382 Node: General considerations96075 Node: Using netgroups97735 Node: Files and links99665 Ref: Files and links-Footnote-1105905 Node: Copying files105965 Node: Managing processes107716 Node: NFS resources108325 Node: NFS filesystem resources109498 Node: Unique filesystem mountpoints111123 Ref: Unique filesystem mountpoints-Footnote-1114829 Node: How does it work?114943 Node: Special variables116413 Node: Mount example118665 Ref: Mount example-Footnote-1124859 Ref: Mount example-Footnote-2125031 Node: Using the automounter125257 Node: Editing files130436 Node: Disabling and the file repository134748 Node: Running user scripts137602 Node: Compressing logs139816 Node: ACLs140752 Node: Using cfengine as a front-end for cron150403 Node: Structuring cfagent.conf152508 Node: Splaying host times153842 Node: Building flexible time classes155454 Node: Scheduling interval158424 Node: Cfengine network services159322 Node: What services?159828 Node: How it works161930 Node: Emulating rdist162242 Node: Remote execution of cfagent165702 Node: Spamming and security167552 Ref: Spamming and security-Footnote-1172924 Ref: Spamming and security-Footnote-2172990 Ref: Spamming and security-Footnote-3173056 Node: cfservd protocol173105 Node: Deadlocks and runaway loops174023 Node: Configuring cfservd176113 Node: Installation of cfservd176349 Node: Configuration file cfservd.conf177310 Node: Security and cfengine182998 Node: What is security?184246 Node: A word of warning188557 Node: Automation189335 Node: Trust191982 Node: Why trust cfengine?193930 Node: Configuration196551 Node: Disabling and replacing software198342 Node: Process monitoring205095 Node: Monitoring files207769 Node: The setuid log209713 Node: Suspicious filenames210529 Node: Checksums and Tripwire functionality212324 Node: FileExtensions214340 Node: NonAlphaNumFiles214855 Node: Defensive garbage collection215505 Node: Anonymous FTP example219697 Node: WWW security223852 Node: Miscellaneous security of cfengine itself226976 Node: Privacy (encryption)227422 Node: Trust and key races231113 Node: Adaptive locks233894 Node: Spoofing234788 Node: Race conditions in file copying235338 Node: size= in copy236087 Node: useshell= and owner= in shellcommands236797 Node: Firewalls237772 Node: Summary238440 Node: Variable Index239237 Node: Concept Index246729 Node: FAQ Index271589  End Tag Table cfengine-2.2.10/doc/cfengine-Reference.pdf0000644000175000001440000345003211170173461015211 00000000000000%PDF-1.4 %ÐÔÅØ 3 0 obj << /Length 311 /Filter /FlateDecode >> stream xÚ}P±jÃ0Üýe¨==É–Ö”d(´¥àN¥CpdcâÚTNRú÷•,§„ІwHwïND„Ä R"r« ©?2±Ü2XBæÍ'ßü#fa;+å¬_WÙj[J"/´Ñ¤j¢·.€—ÆjOÞhݸ¡í—3,5=Ë4½kœwCíò÷ê!ÛTÙçïþ¸@Yn\üc¤(ì÷Ž4ÙK²Õ@@p+,D[,lÄD£áR%ë;;vã©ä’ƒH¸}Šžsi¨óÓ_V5ÿ GUÈhÀd™˜ ¶ lòxÜùCúÒúä[7MQ23СÂÄÙæVÑ]}ê9ýNô±Is3·ã|7´wéæyêÇ„^‡î%1áµö~ì{׺…ÿ4ú¯%Ý%Æ­BA ÀëB[‹—BŠpƒ” endstream endobj 2 0 obj << /Type /Page /Contents 3 0 R /Resources 1 0 R /MediaBox [0 0 612 792] /Parent 6 0 R >> endobj 1 0 obj << /Font << /F72 4 0 R /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 9 0 obj << /Length 302 /Filter /FlateDecode >> stream xÚmPMoƒ0 ½ó+r ‡¤v¾€k+˜Vi=qÛv@@[Ôª“úï—&µÒ”Cžíç÷l#÷d@)y¦RRß"X³—W¤¤pÿ¿%¦… ì©{[F›B#AàdHÊ£—GT¤lÈ'Ý ÷X¤ôa»ÓÙƒ)þ.÷D+.I€K‘^íó›ÂÀ³“¤ó}â}ê@}õEŵ2nÌ…%Ò˜I)éGe/)ºí©ÇÅŸÍ“4% G¹J—çntT£é­êý¬su q3¤ƒ‘Úvôø3‘СoÖ†ið¿¡»"?¼½òÍ›nê\ÓЇªà‚#„ÚÑÉ-àÇ;µvìK¿°ªUÿZ-¶Sˆæ`ßTSÛ,ë€[Drt ÛcØ}ÿ·†}„¸³dÜwDyýûH{ endstream endobj 8 0 obj << /Type /Page /Contents 9 0 R /Resources 7 0 R /MediaBox [0 0 612 792] /Parent 6 0 R >> endobj 7 0 obj << /Font << /F51 5 0 R /F60 10 0 R >> /ProcSet [ /PDF /Text ] >> endobj 15 0 obj << /Length 2582 /Filter /FlateDecode >> stream xÚYmã¶þ¾¿Âß*gÚ’¨·ûÖKàŠCÓv7‚¤@e‰¶‰“%‡”Ö·ùõá eÉÖ¦@±À™/#r8oÏC^¸ÚÁ_¸*v«,ŽE!óUu~Úñè×§[ØL$>½‡F­Ý…1*îOQ¯3Ÿ½Åqwˤdà“ ð‰”Átj˜xÃUº:'§Ú+þÃÓ{wë+Zðb:Ø_Vš÷¡QÝÞ´œž‹Ž58‡Ä9i¿^›Ø-&:ÀÜU7hü8 ÚŽFš®=Rä÷ÂH«T=_L…¡ïŒ.8´L2ŽŸåG>ÉÖ‡ò)8 {©c§C"ÀëøQZ®ý£²4wÕý [Q Jš¤q¯|˜uXlPBÀ¹+œ¹+*‚Ÿ×¹d'EÞ@ ÅΡN¹o ¸`…2; èžWo6z Ö2<Ù.ñb4Å79S9ñUàåY Sœ„#¸îÔª/ucIbâc ømÐFÍ«–>_5É«ºw9¦Ä¢ÁKi.wé¢+0’«XŒ¤€ Œ|•ÈDG\‹ÄXl_6[ïê"Œ¸º@ñƒéL>òÓ‡4­DIDGEx;-ÎÙS745µñ8ÆöÔQ­Ð nÕSÉ£.|±q€bÓ¹Z¡Û# ](’¾®“$(]¤á·¥Q3•TÍ&Iâ…£¥œ•?\(|Úçç/K–H2‘Â7sY²¼íS±ûžU…!<€ã ;þ™+ ©Šßõìº/% gk‡Žæí‚~Kù㿾|¼‡­0ô)2€/À¥t?)CFlÔÛ_>-y* E г¯~Ý%;ª1Æ25ìÌ™ÊÖ† PDXm¤Ø¡…¦ÿ¢'—‹›«[Íu©âSö'e¿Áxn8ê²/÷¥å °o¶Wg±ËžLÅL"³\$qø®'Ij3[ôä|±OBáh”PÛöª:µ]Óß¶€lHNìvGcoêýV·µú&Ný¹y L2i”Í5ö>ÿmÃ:$d4ƄϣóVF­Oÿœ,^ïñl÷Q&…ˆ}3¨a5DT3T¯ô5é%àBÇØ×ˆòFÉÁÚ}‚vÀÄ•”ÈE‘¦ŽÝçÊeÆ[÷¥AxJ‚ß¿¨á«àæ›À?ÇßÇØ ™Ò—U½$?d¯‰-`ÀA±N.LŸË¯ï»-|•^H› )…š(½5‰ñPËìÐôÜqˆ“ì‚=4ivÎÂÎff°LãðX‡'ŸÃïX‹Y°FP°ÉÙ»¬Ù6]U6[»×‹•'Øôü ÙMÏš™lŽô§Ð¬gÛõ4ЪJY 'hÞ(ñ£¼˜§}Éõ‚§rL˜ÑÞ':¥6×DQP6,xêlo?Pˆ±<ïáÊ< €W=…ÿ,©.ÔkBüöUw!£ÃœäÞ‡>ØÉû§Û…š3¡`é¨ã‡1t­f J—”.5Ì`G*äÊaE™X™ xær´?¤"±§"Q‘ŸÖEÌëÀ¥ç¶Î°’|ÂJŠbd%Ðt¬~ñœ@äµò4ÓMž¸Q+«]‰ÀŽEÆ¥›'z…&Ù¥Ž.âüW*­ÿ²;ÕóÍ I”y]S ¸ÝéØãë:IÀ˜ÉRî¨NʨrñúãÀ b™Ö™\ØŠˆ™WÐ5«zû4r·ËÉP|ƒÃÈ¿ ÀPYŸu«mT’¶Á r¼ g):x}˻ߎÑèYhá¢páwŒtˆCÎ4¯£4SväÝíQºÀ?ÝÃQiqˆnx Ztõj8äàZ^8; à͸@Dv€ ¨& D­GvÐcãm!]Nèv"Å@â‡Ý[È`(àúDfÎó$бL`ûÑ®{=iŠMžU‡’*ìm™üY`úŒòµ4Ûñ˜ É’I!9ÖGZYh¯-ÞÑÀ8‹DœË¹Õ€:}§„Y¾C$¡Hd2*€,ëã¢n¢Dd¦›(…,Þ9Ý=´Í¶ûÉõí]!Ý^0ô#ÏÅàçå Œ“')ƒåŒzäé=¥È³z܆M¢ âôÿ?VÀÒs00…97SÒø V ?¢´ÝMüÍ_Éà°bµ‚Ô$¨?%#\r¾—-mJð¬ó· ‘<ˆ¿ñ–Ž? _°®Ò=˜QŠ—œ–“éWü2(@_A¢MÀY⫉˜½†ˆyÃq¢è€W…”s?S¾`‰¬#)幌oçÁNÅન‹ø,%WqpñGM48¡A°ÆþÙ½¼XžméºKñp¸Ö¹ÔTôà—¶u/¤Ë‰…–³6+D @ÌsË…ûÈŠ±ÓIÙ {pÄñbD3v Í?T;â¢%¢Øy@‡põ·£K]M{ªÄÓ÷+h6k=4Ê`$ȽåĽeÍ‹v­‹r<˜îì× -‹©šq°x³þŒx¬ÕÒïp¡_·‰À ëØÆ8µãÛ½C&'®¥UÂiPŒ‹æˆh _Ì¢4sщS7n†=äfhÍ0c6ŽƒÜá—ØÄµ]£qa»tºÑšs@йG ¶½)Ä~s~•CxløƒKSâS“só NŸ<=,äW x0}À*bAF»Ç¹¥à !¼FîÿÝ÷Ÿÿþ_ž—¢S" Çè´=¿’¼=ˆÍ2¬¥9\;å½-\Td‘G_êÌè ÆY9Þ‡sœ…XÖÜLìþÌÙ Ý5)ƒò²·þ?¢‡ø½RJ@«òW"hs¤fžëAÃ;¸E»{ ÓvžL^¥1"®Q$çg¡9¬GNÆ×,”cN&ˆ%þ™$,?sUGøzÔÀu–kÎ.™Qj¸`t ¼É.>ßD¢(¦†{¸È‡õ/¥±¤s|C"¸ýÃúùܹf@õ\-]†\PpÆUQ×z<W)ü¥=1KOÛ(='2ióeÀ%¿fâ½fN÷®ãÿÏË•âË Å,>®ü Aº endstream endobj 14 0 obj << /Type /Page /Contents 15 0 R /Resources 13 0 R /MediaBox [0 0 612 792] /Parent 6 0 R /Annots [ 11 0 R 12 0 R ] >> endobj 11 0 obj << /Type /Annot /Border [0 0 0] /Rect [177.297 521.561 303.296 531.561] /Subtype /Link /A << /S /URI /URI (http://www.openssl.org) >> >> endobj 12 0 obj << /Type /Annot /Border [0 0 0] /Rect [176.085 476.106 542.627 486.106] /Subtype /Link /A << /S /URI /URI (http://www.oracle.com/technology/products/berkeley-db/index.html) >> >> endobj 16 0 obj << /D [14 0 R /XYZ 90 720 null] >> endobj 17 0 obj << /D [14 0 R /XYZ 90 720 null] >> endobj 18 0 obj << /D [14 0 R /XYZ 90 589.249 null] >> endobj 22 0 obj << /D [14 0 R /XYZ 90 347.468 null] >> endobj 13 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F53 19 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 25 0 obj << /Length 2464 /Filter /FlateDecode >> stream xÚµY[ã¶~ß_1@VV²xÑ-À>lÓ.š t‚"h‹)G¢ÇÂÈ’KIžŸsxHYòj.™mᑇäṓüÌ®bø±«"¾Ê„ˆ ™_•‡w±£Þ¿c®„p6ãÏ×ï¶ŸvÅ⨈ vu½›³¸®®þðMÈ  ßït{W·z !ƒǯŒÞi£ÛRoþ}ý㻿^O[%œ¿ ÎxY˜4—’„9‚0yÐ5uùÛ3Ô=~e0á +5èhJ‘×{Á^¹9GSŸ6IÀ$"”ê{íFU[Ñ|˜“ÊÔê¶Ñ½ãöÃŽÆÚŽ&ŸftŒüV=ôY0Pg×´ ¨Äç*‰\D H1iôýç~þå×ë¿»© íeå,÷3?à”«Pò<*²«!öº%o@‹ÜSé› ý¦³–+ÕPwn®z¾f0#,è­ º¢ÁrætTµÑåЙGêþgM?žÇ uá¥Þž”Ùz.Ûº=ŽC¿¦+c2J¤ôËÞG¤­n¸…,DšÑൕ8fOD̳éÆá© eÅ“”ï‰ß\?èZ Å1zgÁuÁÄÎTÔîvôí1<³ sAªÝ°ÛÐhºf ˜¨EïôPÆ5ªž– ûî5ÙL‰@žg$¸ªu[÷ƒQ öXÀ!’QlÎ!Þõ©îƾyÜä"pƒ”v°Tœ·V.í¨Ý±¶ûCÛî_Õv ‚_‘Óa¿†—)“`ìTëœí9Ö­çhŠ/TimZàsÚ8ÀH·†lßkEäÆ ¼-#!SŽn&\¸Ð`‘Ø„Iº¨VY5À@hWÔñi¿(R1îjß'¢¯Û»Æ%‰]ìrC¹L:›&t>YlTàjí‚P)¬å0ÝöÀ¶ÿŽÄHã¹á2YÆü¿b–­æ Ò$ñqL™!XЪƒmÅN ô }; R û­ì}póL‰âîëRa4ŽŸŽî¢Õdƒ%“)mÇf0õ—59¸,‹ZvÉ+ÒsèÇV®ñá›g>$ÝPbRIéË>èM_F”¤z‘È–geó£Ü¾r!ÿ¢c<%PIîbb­Æ¤PªS¿(ZsuX€%8žˆ?ìl™ÄÁØþwTM «$¦’ÈÿØBÿãWÑç¨ÌP—c Øþ¾ë°]VH{È!é3®ÝØ6"¢í wcÆ6Q p/ÈJŽWT8—5>D¥=)-é#ÏîŒ=íƒËººs•ÇZPT¡æhç²Ú‘Õ°8ÓZRšÞ‚U7¬ûÀÙõ­>Xjãó^Ñg„ÒViéT•ÁéÆã²J ²ý+¤“D:W¿*…}\n8™èµ¾÷Kâúò6:¬e,ø5Êå”?um¥?ÐâëQ÷¾'ƒèª=÷Eà‹ù…ôi2¿€,lÝ$àQ ·Æ7xìSë Nq&¿¶Ú+'{É5ƒˆg ’FŸÊÄßL;…¡Éˆaº;«òÆüuVà‹ ž½Å ?Õ6›ÆsAâ¶þ`ÒKÍ£B¾Â)ÜÙø|«É Ðé–fšLÖ¯„3}… åqú ‚Ùy²y@ýÃdwWnqî'îâ?Q_6Ø+ÒˆóÑ¥Ánâäl³8¹añ×fK’›8^Õ‚cn¹UÃI舜½)^SZÙmÿœQ ðžÌ¦bHQÌÙšüÃ…A€&ØzÁ³È_GyÅYþ æxYágÒ&΢4žÂýGÕŽÊøzùYßš©;WZ—úp«Í+£à©üaQ"ø7ä½2heÞ v‘Eñt/üͰ¢ÈœÎ¿Ç«—À,°õ¢b,Ï¢,K¿å˜P涆׎ò®æðú‚›ôÿåf‘!öð }UUoì¸W× OØá·Àk>]vIy~Ma*c;U:’÷¶¿åS¾<‹X>÷õñ$oXÁo Zݬ¦>Ysöì­?”÷—Wò9ç5¾i'CöÒk"M¿–t[’Ažð¹e—Ü^Ælž Mˆû<þŸß9›óÑ„—eïi ëˆ ozÁJ{þá rõåÕÙË3‰h”“¬ÕÃM;Þèa¿äIágöí-=ƃ˜Eç_Ðz¡ÞÊ•Þô3E}Žº“©ÝÉåâ´xikHnÁðž¦Ò:@D¹Mc¥™“ýi&¯µ‚ÏàgËJº Ø…,+à:V\âvq;|b]ë «#,G5ì_ÙÍÖÃuÎj‹ß_ÛúKØÔ÷î0DRGˆì„!À»ÒΣán…)°ñT»æ 1¶ë5”„b§‰ÓR‹„*„ŒíD°á~-(ßo‹†ÚG(pƒC³?)DðÉÖ¿|ö¯KO} aåbŠ5l[d6sȬ›wÀÄ-’ón Cê¶ïzð@ÍíÝ» ÉÏ`±,JÛ¹Óÿöï™÷ËÝ~,õâÎrƒ>¥.ÎSô)»Ã±Ñô÷LBp:ÈWZ@iB˜aÄ–ø>ìë5r\æð=tÏb¾ºµà{|Þä ªþ¢pßïV ?Äh†±j ¿ ±­ÊíràáŒqÁ‹7u£co¶MWªf{P=žÀ‘ý¶ªû[«g´ËìLp§¼¯ÑŠò±±‡9öÚ¸&a_ypPÝ=‘{ÝÚ¿°˜wD²QCM"åt fç¸AÖà[p8mæ .þÊ(GªL¾ W‚â뿞$jÑú#~ ”†W5¤ßÞtãÝÞ¡wn×Z÷ÓÄÿ-› Lˆ !”Á}ÝVýò]JZº+ÎÑ~Úá®8 uõhƒã î' OÈÁwœ;ïáôÝâMÇ>dþñ±´U)p7øSÓ`ÝïõG(ôþÿÒß/%x« endstream endobj 24 0 obj << /Type /Page /Contents 25 0 R /Resources 23 0 R /MediaBox [0 0 612 792] /Parent 6 0 R >> endobj 26 0 obj << /D [24 0 R /XYZ 90 720 null] >> endobj 27 0 obj << /D [24 0 R /XYZ 90 616.019 null] >> endobj 29 0 obj << /D [24 0 R /XYZ 90 228.828 null] >> endobj 23 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F72 4 0 R /F60 10 0 R /F54 28 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 32 0 obj << /Length 1328 /Filter /FlateDecode >> stream xÚ…VMoã6½çW½DÖ²I}çÖn¿ÒCQt³è¡[`‰¶ˆÈ¢+RÙÍ¿ï gh+HÒ…“’£Ç7o†«üĪ٭ª,K›¼^µÇ«[®÷6°`³XñÃÝÕöçB¬Ä.mvXÝí—.îºÕßÉû^¼žÖ›,Ëq³Þäy‘ÜŽkY'~²ë ´ÝÜzcGZâ-µ“ÞëI­ÆažUØ2«a½MQŠ$[ÿs÷ÛÕOwgp…”ß@+¾ ¿,«´i ‚ÿ+€xd•رÈ2ib•Eòe2^S÷3¢gò™³&Í3 ß®Z;i^õì“RB·Ž«®Ù531k‘øÞΞ¾«hê¤|ÏîºU³cl ²HŒ#Àø3Ȳ·-!JŸÈúi'ò÷Ú=Ù|¯ ÝÛê¨:bäó³ ”ï©oHŒú) Éä{í¸ë´:ŵ¿Xmq’4,a¼´¶ñ“FìuS‰†?Û‘¾}Þ¿/Ïâ’Xä’V¯éTÖiý\¥P6QpØ¿hî…`w]”¤ƒœœüg†J‰ñ«w±¯1d¤¬ÈMßÓ¬âEªÅ]nP.Î`Ö†ŽsóQw´3¨áâ•:™¤y,Ñ.È B=>Ñ‚Pgç/{«€(n4/Å@§Q\8£¢© ÚŸ¯VËmgç{ˆ%Wa®­U‘•ÄÒ›å¥D!l²J릤oŠ´€JWfÉ <}?T˪‚™Ãž3¨²¯FUФBòCàõÜAUuBEÜ:gîƒ+–(Ò;O#YºËwq®ÂÓìiÊŽl›xŒM¼[Ñpš9èhk÷êÀµµijÖÏм,öóðš”éî„,ð¦#RízÊSË—N†««–I¼˜k¾û íaŸóÉá©=²k™ ªgW p.6LöHVE†ÅÑža'èƒšÇ ï^w$v4ûªÛîåeÌÉô=œ°)/DJÀ¿nO4œø9×Bé¡õô~;u«Yº<§¨ùpûËÇ |1°3ÐÀ!Ý Ô7,ch¸¤0{·ô]¶÷Šïj*¸0¡þ§¸š(þL‘ôª#{Ó#Ùñ ÀÛ‡p„Žæ8 `|—\o:yM³ö u‰â4VÒàüÄ ïØqVËŽ"*.„£mÞ0 ¼ 3lá÷¿ ?º#t"F,§øðΙ¬Xé±³¤†f<yxS0¿ÛøŽá7d†7Tx“âg£ŠÑk´í½f$ÿÎ&îæÂuϵ‚ê>úÿ&dM endstream endobj 31 0 obj << /Type /Page /Contents 32 0 R /Resources 30 0 R /MediaBox [0 0 612 792] /Parent 6 0 R >> endobj 33 0 obj << /D [31 0 R /XYZ 90 720 null] >> endobj 35 0 obj << /D [31 0 R /XYZ 90 483.587 null] >> endobj 30 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F31 21 0 R /F67 34 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 38 0 obj << /Length 118 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h M]#K ˆ†sZj^zf^ª¦®±±‰F™ˆ6Ö(JMK-JÍKNÕŒ ñâr [ejd„Ý--%1 endstream endobj 37 0 obj << /Type /Page /Contents 38 0 R /Resources 36 0 R /MediaBox [0 0 612 792] /Parent 6 0 R >> endobj 39 0 obj << /D [37 0 R /XYZ 90 720 null] >> endobj 36 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 42 0 obj << /Length 915 /Filter /FlateDecode >> stream xÚU]ë4}ß_ÁŽDLü‘/Þà Ðå]¡¾q‘ðMœ&jkWN²Kÿ=3·Û^ÐJ{<Ÿ9sf*²þDÖ•Y£ït›õ§§2YO"­ p(î<¾ß=}óc%2Qò®ìD¶ïCì†ì7ön2çÕ†¼PJ1ùm^h]±wã!—-³2;Ú`]oóB6²­Y•ÿ¾ûùé‡ÝíáJÊA†ƒÖÈL4\ŠJ'hu«¹Pš É¼¨j `òB°C®$jª;@€ãó Ùò²KQv“¥KÏ1¥B|,…ËJ›ušÝ—š]rÙ0¿Ñf™üvÈgðôõ޾ö1Þä)˜f󒂦 vYͧã¼L´5ô9o`ë‹s˜ŸóªffM(_‰G'3Ž9bRBq™RRy«˜§ê é I,_ã2&ÑR`wÖÉÃÓqØÜõŠ¥Å9ø}0'¢S‰¬å]]Ç¢•m|[ëŽÞ¶Ï4¦û%ÔGV¬€÷BénÍEªr§±Ž¯Üáƒñ¼ht ÕBúÐx…7˜C²cé䨲aC]¢%7øë|`;áÿOÑÍ$GW /ô•5䂥؆>‹ßÂ5¨ß⟞rvY8vŒfß{ÄÔ°„ mc ¶x%Y°ý…¢PRFxyv ”㑌el>¸øY½$û#ñ-ïù–µæ•Ö€5bìG랇· £4WõÍï+ yã}H0hÿëedôi\¬hG>’TÈ„S¶‰+ ?cÍ5$?ÐãÑ:2{>z r‰Mˆ&„¾Ÿ¥ÄÂÕ-[ætWüCþeËe[ýüã›þx´ýºÐî¦%X£Zf£¤Ö%y™æ SÊ.¤¬ŒKThÉkh™ÙØ?{ ¯P$êÅ«ÖOd¿èÐdü——‡ª¨ºØÞèð¨ô¤Eël0ëì¡aöjêG•zù=¾Ø4÷S¯‹q’Ä XZÛâëp~²QÒ‹Ù[2|„‘ýá×_~¢óéúMk‡/p&µ-›“õd[ÈsL2‚ô7˜Èu?¿’ƒY 9ƒ%ro©Üq;ú-¶Œî¢ä”U†!’¦Øc`:!rCC–,†n”Âú:ƒaÆb{w%{ïRB ×úh±˜]%ÓH·•Ùh^wò?*SÝw&„¤²¿Bí -Ûf¡ÝɇkJn žTÙñ²ª‰ZC’“Ù›™´?åÞŠ{ endstream endobj 41 0 obj << /Type /Page /Contents 42 0 R /Resources 40 0 R /MediaBox [0 0 612 792] /Parent 45 0 R >> endobj 43 0 obj << /D [41 0 R /XYZ 90 720 null] >> endobj 44 0 obj << /D [41 0 R /XYZ 90 720 null] >> endobj 40 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 48 0 obj << /Length 118 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h 3M]#K ˆ†sZj^zf^ª¦®±±‰F™ˆ6Ö(JMK-JÍKNÕŒ ñâr [ejd„Ý-Ï%3 endstream endobj 47 0 obj << /Type /Page /Contents 48 0 R /Resources 46 0 R /MediaBox [0 0 612 792] /Parent 45 0 R >> endobj 49 0 obj << /D [47 0 R /XYZ 90 720 null] >> endobj 46 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 53 0 obj << /Length 2253 /Filter /FlateDecode >> stream xÚÅYKܸ¾ûW4’ê³W¤Þ{sŒl’E$ðܼ–ØÓ¨¥^JÏüûÔƒTK=òÚ^ ¸KÅ"Y¬ÇWEŽÜEðOîÊh—DZ(“bW_EŽûðJ:*p!ñç»W?ü”ÊŒD•rww\.qWïÞoOú2»ã8â÷a’¤ÁÛãpê÷ª>2ßš£±¦«Ì>TY&“ ߸ûùÕ_îæS¥>£J¼Ð-W;™ %ÓÄé–‰qºÅû0Íh³e€ÅŠ4ÊÓ…F ÈíÁ*Hã*w'/¤–BJ‰÷ÚFZ³ib2­žÌk&ßs[ÊT5*/vI®D”*° -ª™ ¯RÅöf)R✉·‡b‰œé÷o¦½ ø<H=\ÀÝHEAÝêg‰È‹x¡çFÕõB¿­çÍR¤'†w’xXwR ¦¾4HÂ"\ˆ°<á±1)ÜkŽ•^¢*+—tˆ'Šœs˱ïëÈEÛÁ‡ûÇf<ñèÓ¹}ͼi`ß9nWyØÚ‹9ŒÃð„›l–y/ƒØ·Õ/ÈõBOŸXG •Ïyæ@Ó%jŒƒeîr5ùÒ\­|®V'S= Óyk_ô\ߤ+Xuàš©!N”ÜRÍÐÞ‚(â@…ù't_–ÍÅÚ qlê-pÂ8; ´)•q@*85,&Ó–  hHcjSs0¢°Óžª#¶’5QþÌó±ð…¯¸Àêa{ëìô-¯6Ö×tkîÍ‹gùªaƒ0•Å5pf±›‡‰RåmÝ!“µ»ßAÿï[ $RîÒžbç ýì¶MõÌ ¾8ò4ôÁx˜¥rûœ2/)‘ç÷øÅ»æÖU¬¹º^ÅØy¸á v¢k+kMש(ž_âz|6 ¡Þõ< ,¥ëòWA, ŸF¶DÃs oŒ"èô™.aQŽŸZm™äí‹'ÏŠàŸýhXΫ´X…o[!€Ž)g¼øÃf£æX¼`Ì xaæ `°üÍ¥€„ô"ÍàÁ÷¿n)§ endstream endobj 52 0 obj << /Type /Page /Contents 53 0 R /Resources 51 0 R /MediaBox [0 0 612 792] /Parent 45 0 R /Annots [ 50 0 R ] >> endobj 50 0 obj << /Type /Annot /Border [0 0 0] /Rect [203.978 469.663 364.783 480.572] /Subtype /Link /A << /S /GoTo /D (Auditing) >> >> endobj 54 0 obj << /D [52 0 R /XYZ 90 720 null] >> endobj 55 0 obj << /D [52 0 R /XYZ 90 720 null] >> endobj 51 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 59 0 obj << /Length 833 /Filter /FlateDecode >> stream xÚÍ–ÝoÔ8Àß÷¯ÈÛe…âø+_•@'ݺ}@‚“p“Ù&"q‚ã,å¿g{·Û^¡½ éPìŒÇž™ßسˆâÇ¢ŠF…¤’eT¤Ÿ7,ôTHÎ4^í6éÛŒEŒ’ŠV,ÚíÏ—Ø5ч¸Ü&¼BIüzúªÓ°M„ñ»VÄö`@×°ýg÷׿Íîd*ãü_œÆÎ0Y<ÊKI˜Þ=Z´œç±Zì8(ÛÕªï¿yþÖ[^Æ-4AG‡ŽmÁwfPuЏõÿÝìÛK5'úΜºWsP³pÌïÍ8ÜèaðTÂa™÷ó#e²²M¤”ñ® ØÆÅN‹õèVÓØúˆpÐ@¯ìêJíèÛ¯mçcò:«/f*–­ƒIpjvec 844du.ÉÉ„U„ñÙOn‰ósâ‚P‘¬ I0“$˜ýhò|7MeE2™§ýá Iª" L˜ú»“_gï¶m·,!Øn€ÀE{É õ¨›ù¸Ï¾,¹ ㇩&ÖãÔЬ™w«´Ð÷^×P/¶õL|‚E%©ò\º xIÊÕ[yÊ`F)¡t‹;5‹‡NãÒ eñn/{ —¾ÃDh« šá<æ_|{³Ê³4¹+B°¾ózœ¾9›ýˆ[ºg{‘.³ABé*IçËN§õ^]¶~Æ ß¤epÀÏôLkõ$œË/§ƒWFJR‰—ã7PÈþ ¤ò"£O…ô³ïl:4k¨ËÔ(ëîí&˜INÕ™‡›>™Ì¢aR¶Ÿ§4:²9iþ?I¿Ïšam§ãQ6ØÃIDE |tä·ÓÞÀ!ÕKßߟæ\âoš,Çèªý¯gW&9lq~,Î×C_QÆÕ ^Üå¤`yü'h0Êž½F0ò%¼?|á±[pí¬ÐÜȤÌÜé+/½t%<¼2æÚt“ ålMŽX¾’ñœB endstream endobj 58 0 obj << /Type /Page /Contents 59 0 R /Resources 57 0 R /MediaBox [0 0 612 792] /Parent 45 0 R >> endobj 60 0 obj << /D [58 0 R /XYZ 90 720 null] >> endobj 57 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 63 0 obj << /Length 2104 /Filter /FlateDecode >> stream xÚ­]ã¶ñ}…>T*E”¨¯úÐ^›ôò°h‘ÍS \‰¶‰•EŸ(eoÿ}çK¶¼çl.ÅÁ"‡ÃùžáŒÕ&…ŸÚ4é¦Êó¤Ñõ¦=Þ¥}ºS²Š!^aüýáî›o µQiÒ¤Ú<ìÖ$ºÍOÑûƒ9MvÜÆyžGúÝ6ÖºˆÞïÌÞÛ¬Ž&>íÎŽvhí6Îʼ©£fûËÃ÷wÿ|8³.²ìwdCŒÏ„«²ª’LZ„+k¨\³pzeâlc‘HyF"UÅJ$„ é$×e†„À y‘èF”’oPr°QÑ4z¦tm/ ¤šDe‹¹®,S—‘ üEô¼ÍªÈO‡­‚O@~râwŒÚîì°wƒM¶q™ªèÃB‰ÉÚñ4ÚI¨š¡“;þxš'˜’0+£Á¶63¾ð6L£™ìÞ¨B²ç‰…HöG7w<õö(j¸aÏÐÖ(ú¯µãJKøÍ"Ý`Àä †I}øÔÒ“bf$¡ðt"Ï[Â}âý9U%Z§uªÙÖ:ú F\ ŒUDZfMt1ùZ+Vj?úù„fÉTÜÑõfäi'ç9™üÞ‚ÑF<˜²ºH®Ø;ˆz°ÁÞ áä»÷(ŠXɶcð#^äz&^µ¦ïDôÝ ç/ûq¶d`D€n´<e%)6×zdŽºj€A°,W( áµ Q<|v}Ï—!}k GܘÇ^Vè4übõv²|Í,·F#..Äs'’þ¤…àɹ‚VEäEëø¬ÓºÇ’ó_dgÊ&+ÖÆÐH51ΚRÄý„› £JïgÈ$¶àNŒ‹ÞC´ƒ;† Òmð=3`é(;(ۀтùòyvöĶ:ÐÁq¢‚ çÉA Ž&%ééˆ?‹Ùð͆EAå¯ëL=‘!ìIC¢·xúÄ7ѱPu¦o¹Òˆ p‰d¼{0Ó­<˜Kdf™ YkÞžx;B!9R8Œ+”Vâ ßéà)hi&^Ýþ°(—ÂD!‰'ƒµB€J|ÏAбêŠeýœéÞ±œ"Ù…SðÇ·ò b T`oUè-ø¿äj•QoèQ¤³y‚H³r•<–“¢(ðX•éèÃîLb´¼tq oY‚{t=¦¤oVŠøˆcD÷F c0Î(â 1”T}ed8óÄ®mgʬ`r0Î ŠRÁBöt¼æÔÅCr¨›öUšÊ¡Þ~ÈÇÙqdBÀßðÃuºA-æì‚ÅÊ)@ÿ…èëKXzבê—{yÃ%ÂP¢ÃŽ9<ì'ÑL2l7S!F0˜Aܧ!áî=_;Ç mFáñ* oèEî|vÔ!5EtXªW}]½2LøI ‹^=p´mQ£ƒe3†y¨n9_»ˆp\]§/!ö£5Ý KZÙ·¯‹hyçÜ€Áo);ëÆúÃn>õPäP®ä7ú±¬L´^úº$ã~ì]CñUéë7•BèÉäþ,àÜ1Q¥²M“4eV.­YžÔ¸A¢d éJ?žÛΦHšªÞè¬Iò²À¾ó§_ÒMg U­ìæ™0€fx¯ßüp÷îO¯9YäUIÔTyá›Þà›&ªi6Y^&e^¿Å°ë2©×\sµ©iÉMq¤M±É›2)riCÁ$ЯöïØ,eµF§^!Π…ÍÄ]mIÍ=á+ÚØ× ˆ@xïÞÉ]€vB"“÷ÍS M|ý•?˜š7øCFUµZHþãþ‡˜ïƃ9Ú"Te’C÷Ÿ.Æ,Ô"€ç®ÄM¾Pï÷ˆýÍwØ!²ÈݹÁqö|.I¼&! ¡Uöãô…ü¾…j˜¦~ùþ2ûß¡§E®Oö>.ŒÃ¢*þÏ躎i˜¹²<aÔ9œ³ßL#Ä,ÕWÊ¢×lխʽ cs)–’¿5Î\9ÜQª‰?­|þæ|wï'zÇŠ¥¥€Õw÷?ò¢÷üî^ÒÆŒrE p/>Ì!Ô^#øÙQ_¦–¹ á…ë½ù$2ek™²:MR}Ή8FÆÌò– eT`YÁ¦ö¹–çJhL@ ã\Ãꪱ`- –SkUqk['ßÇslj‡SHÎC•”•˜ï¿·ÔÉ“4?ëbni T¢‹bÁù3vrô,æšž® bÔë„—`ºã-ººHjU]ÕÒåߣ»ü»oëÐË;Æ‚+>ܽ:v•||¡ ÐØíÇ3žX :¡)‘b–‚‘J±Uõ¥¶úÛ×·$·¨æQeþÊRÐÕ¾74ãç«® sàiV˼FqûÁí^ÈwôeúaLK‚ó¨­—?B¶ô‰¢Éjž ‚uZff– 3ìO8ˆë¤LËëÎDÆâÙàx‘O >”Zº f‡‡xº1Ê+êÍhƇïà'Æ8¶ƒx/ÛN¨üHãM*OŠw@3ðFÒ” õ/ÿmÜè£Z3Óæü¯î䀂Y¹³†uï©?¦îð)4%ä¹Èÿs䦀¡á¶#w…Cø `²›§y!ÞI›ÚûÓòÏÄn1ûG#÷ñëG.HÝÚx°SÜúÓË-ú‚ǰ¸Žá †ß{hqyþε²3ž¡wÛ)ð‘™ ±OËŽ»áz­“ŒjÝþÈpÀ³uG6¼”5¶-k?ÿêpldhÑp ôØ^ý%†@Oþ²UÏcÈ@ÛGÃîrþYÁnMS880n î˜òX™4‰¾š¨ŸÎAþÙÀ‡ÿvv½6 endstream endobj 62 0 obj << /Type /Page /Contents 63 0 R /Resources 61 0 R /MediaBox [0 0 612 792] /Parent 45 0 R >> endobj 64 0 obj << /D [62 0 R /XYZ 90 720 null] >> endobj 65 0 obj << /D [62 0 R /XYZ 90 720 null] >> endobj 66 0 obj << /D [62 0 R /XYZ 90 661.229 null] >> endobj 67 0 obj << /D [62 0 R /XYZ 90 456.811 null] >> endobj 69 0 obj << /D [62 0 R /XYZ 90 214.178 null] >> endobj 61 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 72 0 obj << /Length 2665 /Filter /FlateDecode >> stream xÚµZYã¸~Ÿ_ÑÙ—•‘FÔíמd&Çf€íd„–h›±G¢º×ÿ>U¬¢,{5GOw£‹g‘¬ã«*²ÅMâfÞäq¬“â¦l^…Üzx%¸äÃ6â§»Woþ˜Šëp-nî¶swÕÍ¿<®ühű÷v«ÚnÕÊãÄ»ð{½Úª^µ¥ZýûîϯÞÝMk¥Qô•Íàˆ¯ìF$yÝdEˆ8¡ ™=î`]x­2«¨ðð§ëÔh:üæ^#«(÷Õ¦9ewÄá§U{ÁÊÏâÜ»Ûë:»£Ñ]K3¶]_*n/ÏGZÝ)[Ýî΋/àŒ¾ˆ‘Ò¶¯và8m2?m’yQÀD;㟫0¼ªiá ]£V©ð:»h0{݆©lK¹§¹eÔv¬ÿÀ«\ðÔaİŽ/ÖAe´Úxh4aì¶ã—KÄ„’4uc~„ų<ñ>…i¸D¤ ››(úmç—{Uü­®Û ô×"Èâ‰>РŽyêÝvôm;ƒ…Ä+QÜû•@‘ ¬Þ†| ER+5œ£š:@ÆTè¬dZÕ{}¤¦7ô±5Oõ òUxèÇ@””)­ ‹i$ù£ÙùöÙÙtck–ù S²è’ŸIyoarð@U$€L1TE6€Újj°1&öao LÑÀ×¶tvU„Âû°¥^ÒMœàì [õÀÌ AÀaʦ"h[­§J²SLí '‹È«@̺‡ ƒH ìjVê |Øk+ÿ=®¹˺hQÃ'À•ùa¡ïò°?P£ì•¤P¢&Zñ ÷ë6Ú]Ø¿;”BÃ1lOÁò=VÜHÏíÖtá+[¤x2¨Ì*0nÚ#.‚£,PÁ4Àñ$.¼Ÿ»¾‘u}rD0a^_ƒ ô¨æN:`u¼¨’y°^OÃæJÞ/šž•aGžçpû€QE@L|ü¨  âêLÐã,Ë“¥bņ_Âqì• ±€*ç ž`ÁΖRïýÇ_ÿAsªŽ´Šiºí_‰i§nY{iµà’ÝXWTÝÐÑyLßk# )dÈn0,®µ ªÜZÒ,yÂ]׎Âß@1Å¥BĬäqÂr‡†™©bõÒTS  ÆÕóƒq¥6ãn‰láúãhí½kåÆ*?”íÜ1 ªÝhŽ£A+O¢¹•C׉DF•XWs{äÄ-h±"ƒï ÚŠ[#f}¤i°Pü½Ô·É:óh wòˆe“ÇÞº^SÛPöúh¨\vM#í‚PA—c%UšÍ 5 Áöä“Þµö¼8Cöç¥_ŒÃ¯"¤œÏ)EE:Q¥WÖR@U5â Ž—%9),Ÿùœñ«p¢³’A«5›~=ð¼Û³,‰&\° Í Áº ""¤0ºupd}n옅†Ñì­ ü‘ €7ÆÑ.Z­¯adËÝR6vŠEh¥õa<²AõÆ-¾UÒŒ½Zäñ³ÊJ©k6ânK¬[hÅ–lÀNÒÎÐ@ÞA¶;Î+$$ÍåA(ž'X÷íKX÷3‚%óNƒBäWö g¸Uh@.}’|ú®a–-c^YËgcÎȶA‰nl,ÚÕ×lf! ò.ùù(Šƒl=m]Öǽ 6˜J€Ô‚ë\:¤\I>ŠÌüDÀáâDz_½H¤«*½₆Dyô{üêÝ“3Ž“3šA’uñ<œNˆô±§|÷ü§T­MCÁ¿c¦·$¤ŠÅÕQÁ³ÿ©î6 6ç`ÐÒ¡"ƒ®›qĬ\<¤„`w 4\„ à[KÍa'²‘ÔÅÝØMØdW8px¿-\\À†¬|…œBý™"¥È¼_lÀ‹ûÄÂ,¹¼!J(¿Å6IŸÞQûôXõØDYŠN±°N‡ì-ÚÜs€d)wôµ(0þ±Ä[®3÷è xæþ5PVÊ!Vå ƒu¾6ÆcgëÖU«áMÛQý£êß8ˆ)1­òâ®üzÍ·-cK…YÈgã#=<·Ï¯º˜Ð/Q!°Èâ+Ísï£{›@•¬³¥(êrk,7óÜù( ŠSÚádë?¨ÀY޵¡ÊŒ•P«IfÝiCÅæ s^S@jš]xéLJU‹é”-ºƒ¹Eƒ’îl9œå¦ÓÝ^zâ•cß«y´[aÎ ù.':|ùqòèˇýóK¢¿ã7KNóÇÛƒÚ¬Áz9Œ Œ^!Çl´›z·zÔ™…÷dYÝÔ¡íȶ,Í™ ACý0‚C®%Žkë,ˆÂG›Éûñc{ÙW¾uúêolð‚% ½=‡šÁâåG6¿¬L²µ·í»†Ú)¯¥ü {¦ø +›™^ßÞ@!Ÿ¿¡aËNSÊ'‘Ý,²·²½@5ªØVS BrQ na¬¥™„y{އ€O@4ý"¢Ò[®·z1«Ë!^J¯ÔÔ¢fê® ¸ß%Ð^»«aNÏð$‹(ºÙ8|I'wA£±¡WSRÄ˪{Ÿ52ùìÒ0À¥Ïn7ìÅJœÌ’œ!x‚V^æÊ¸;žãh¤IºÈtt(JmC/!ot#wꜾå³É©S|ý]Ïy‘Ã×]yxÌá?ìZÒØ4szy8pÊö`/©9TkçIÅwº~þC›^ÞƒÿüBV±ôæ’ÄëÙÍÖfŽj³ËU¬ZÝÀÂy œŠðzÑ6 '‹û|oRë’ši;¶h™HްÀ>­ÌL ‚ ü?Ûñ‰dq”ˆv6a¶Æ»£f2ie¯c’Ä=÷a}<ûs„í2¥™õØ+þÝlø¯/qQ+£üÁÈú R"•N®U:ònít*×гbÍR°Jçœá_¿”P§áA6±c ŒÎéâàêi¨~ómA^ä—¶:` €à(oß¹àc&Þל*Í·ÓcÍX™n䇛Šb©ï–dó"€dŸî¾õZ#ÿd ðJ`@Ã9ÀHéš¿³‹s¬No¢0ñü& öI¾x%Âl$Âsœ …g'ƒ×O»<ùÛ ñ²?ó®œv{_Ä÷†ðhp¦Âje/‰)|[NG‡0ÍÖ=zûüG£èÚ¯>=¼þêÖüª?ùxåðUùYZâLì¿ã`üc¯—Õ{I ä¹?wøM˜å˜ú@”ûw{!ŽÍHϽÝè~¥¡|=Åw%,›Žz]BBâÊà ˮòšŠÞè¬G0ûnd‹ø¢)> endobj 73 0 obj << /D [71 0 R /XYZ 90 720 null] >> endobj 70 0 obj << /Font << /F51 5 0 R /F54 28 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 76 0 obj << /Length 2355 /Filter /FlateDecode >> stream xÚµYmoã¸þ¾¿" œ DŒ(Qo÷m/ÝZ,îÉ][ôŠ;F¢ÝÊ’W”œ¸¿¾3œ‘l'Ú&QÃáˆÎ<óbyÀŸ¼Èƒ‹4ŠD®²‹bý.`ê§w’G>0øßݾ»ú>–2yË‹Û塈ÛòâßÞõ½Þô¦[øQyêÛ…¯Tì]/õÊ4‹0ózšèÌÒt¦)ÌÂã,Ï<)ÿ¹ýû»·Ó·ã0|asÈñòî’L )ÚÝø` ™"D Ñ1ø?0Ç‘)…Šã‘ç8C’*ï· æä©TDq6Iô³Ò½™“«b‘Étä¼üÒæä^ÖДfY5³ÒâT„i8òÂî$lT¦ÞµE×4Öô°¦§A»Ägâµ¶nCzö(aàµq ÍBz¥ù- >ëHxðIÂvÇž®žë»åÝ©ÃÝ…Q*Òl:ìR×vöa(‚ ;:p]øQ jõeOšÕdME»Þ€!e^ êaž‡ŠŽ¤þÞÐ`Ùvë¹J¥D’O;Ôõæ^‹»E,=Ók±Ò뵞Û0Ø—Ú«]ÐnÃ,i’à Ižj}›×·¾î¬ñÛ¦ÞÍÉN2‘†É±Í(™{?¡³âJzÅÛ¯y¬QÇ8…60[±}» ? ¤÷‹5<½D ÂA±SïÞ(òSÕ¬¦Õ4°;BýHïx_î;¤É49*Ò]»¤}nºvÕéµ@tQÞ¿YWO—[¶tëMËPs¯Qúÿšê[š¹s6ÃFa2!Ó v„¯že `Ó}ÃŒ–TYµ›¾j¾sð¿„/\žzá?½Ü´>è§0àÏvÖ^Á2ù&à,}ª9óhŠ¡7GÞ£P÷ ¨ÔÃ8°*tq  ©À‹Cu®ù~mØM­w'&åæ¡êÉhù–Áü#¶¦Ö²vÜá7`µFÖ3lœpèX³ ÊU"s!¸ÎTÉϯ¯’σéúÙpˆ ®ŽŸÇ®3b( ~âPÿK ˜¼Ö4g `D@†æºUH‹ ë*}WóêF¯H‘GѹžeßĖܱšrVx ŽÎu,[tÕ¦ÕÈÈcïM]¦]ž”%"Ì“s­éæõ•b«Ú4ýËÙÍ{ኂᤃü‚,§Z³FПtÇmÀ…öfðzöû7±‚¾*çEŠXÅ'X€ÀhA‘ÕÝúÎ ¦P.[Og‡àeÙ¹‡^ÿð}ÓlO=¼”2ƒüsÀPD/ÅÒ4+L`éC¬@}`$ø¬T6l«®mÖS áfŽPƒp æq†øÇ‹9õõ÷ï?~¼þøþææÃÍËê+˽‡ûÊ¥3 òÀ+p»H¿s¡Ñµ3ºÉÀ»£1­«jž¢pšy¯ÝBA(€ø‰”Þ-e0ÿüä©iœ'IEËyUÕຠwérAªæ= lËÍ9¼YBp C×±ÆëÍe@É®h…÷ĪÀpH/«Š¯†xÐÇ1i‹: î=8Þ5eTÈ®@­‹‡ Ò:x>v¶7k¢þÊ“ŽÄœ.kƒçÞ¢p•&âws}è:¶ƒ.°X³r&EŒv›8ÜÞXµ u'È¢N€ lëôÚB¯j°¶ Ån o '8ÅJ©ª)Ì!yÙµkb¤lH{ÿ@òÝPÕ½_54GðÞ1í0s¦ýD›AS‚«å›«©™”0Š&w ~ådÖ8˜2e|Ù (æÐ–ŸðP‡q~m\ùT¼ |²-ƒÞdÇø‡«Ãh>ïàhóOÒ‚<ñVà,°‘K¯=e¢-½Õº[1Ÿ+=¢<öÀN€Ÿ·_–”£CëJY` ÏÍ1—±-‘tA©­£Ò ÌÚô¼†³œ±‘¿!Ôß» `|Åán˜²L¨p‚Ы­î®F{¸²`”æj—³Ø8É=Xqø€º\dJž>~yƒðÑ”¦³EÛÿkÇ B‰: %ˆ2bÓ GÓQ6!R‰–cãÒµ–ü yuY2‡æû¡6smŠ#Kt†–%ä¥8`‹Á³)¤!’0Aõ »’H–! Ç“5 ê­g®>-\ܘQaæ"Ú+ãw;4j¶o’‰dïó½$Hã‰ã÷ºj†Ç9IQ*T6ñ™¾@å‡9¡n›ø8Ùdç)6âŽCÏQCFÅà˜ÐŒGG‚îãÐ\R„ƒýU”py*‹=[¹<'A«–‡ÓJ]cˆÝñœ>ò |ö¹g>,Ü–\è ñêkÔ;Ü£‹o@éŒ|§±sTxm f·GT4Æâ1ûnŠv‰#ÂÜÛw!ÚŠ§ È!@r_i ´ÆUÑÏFÅ £t(!¬"Þ ôâô…¡ç CóçPVEÕº ‡–zfh\¤BŠ&—³@˜R R Ä‘_Ršp°Î™6ޏÑ&=׌ ¼aq7w„äËw…Þ˜k¬±MUâÿÑMÙ¾>bmMw×Îw*ç^•‡”dʃeäÎjº¦<¯Ä(Ç[WQ°4_ÈÔj×<ËŸf9\%‹zb v‹åI6÷ã ˜ÕæÇs¥ž~}¥ZN°N-¡&uq¡ÜÔ»'‡±Å'½nì×UØŒn¸ ÑwS‹Fmbjaâôç™ûÙ‚ëdû{|£nžxXžÚ¾=£—7{"ÄpæIh±_ÙÀq ívj3f>ÕÔjèØ’÷ïØ'Ï#¡Tz®MþóM ñ“=§Qø²šgõŠ8ôûÅFááG­)ö*güûÇÔ'•Ƒȓè\•>¼‰Jtw‚›_¾¸;üӜӴ|v5›C™šL¾Û¯ˆw y¿^íq"âàì®Ëß ÇVÜ›r¨Í9¶ù0'˜D=è`S;‚¤¿Ž=A‰ïØw¶9³q?ŸpÆ€Ž¾D±åa»;PÊPž‚ÊŽþ[3A5d»!P—#8óóî®3ÛjBå-Î;6}Šæó0öñhE=X ‹Èãò==þ>Q–¦ü–4É‹ |$Qîj"‘AZ LP$%\7C}Buè~·îéÅ÷õÖånø™b[oÍeÑnvS¶gHä×ü9XSð)Õµ}[Ìøƒøÿ÷áâí endstream endobj 75 0 obj << /Type /Page /Contents 76 0 R /Resources 74 0 R /MediaBox [0 0 612 792] /Parent 78 0 R >> endobj 77 0 obj << /D [75 0 R /XYZ 90 720 null] >> endobj 74 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F54 28 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 81 0 obj << /Length 1971 /Filter /FlateDecode >> stream xÚ¥XëÔ6ÿÎ_±º"5+݆Äv^TýP•ŠÔ‡Ê¢¾Ä{‘Çá$ÇPÿ÷ÎÃÉ&KŽ¢VûÁÎx<Ïã7ã 7üÂMl)ýL¥›¼~8êû¡›í€a7ãxrñàÑQ¸ ? ²ps±Ÿ‹¸(6¯½Plw"RzO÷¦¹*³ÝI©¼£ô¬ÙkšÜlß^<ðìb:+â_”AŽÏ´IÄ&T¾T±pÚÄ©òC©Xå«í.Š…÷r›IOÛR_V¨PyæöZ7]Ù6ü©›‚'9P¤ðzsÛw¨ãé…Á"aæ‡ÂÝ÷å6wÛ …W68J/Ÿ €TÁDmÝwaÞ¡jLÁtÞ$¼|» =PA¤¬‚¿ÝÅ©˜³ =¼B蜦ùóª¼Á½fÔá(Š dfí[&õrÝLúaÄ+JÐO¢¯Hx5’ÞõŽ×·‘ðÚ=æÖäCOöDΑ<á1œ(ïªj/uukqê ×0¦^¡{Ût⠞׺l|T0ñ~r2¢à1÷ˆT‘/ƒô'ÅÏÖ¼ù xÌq䃮µ*ÄÉ/ŠK}u”v4ñ9Ùq'3é§aêÌ2ÛÍ6Šg‚9qи‘ýÅÙ7¤¥}kk>X†pZÇ Ï©ÏbÓ1ß¾ ¢àÆÉ…yñ."ïá§‘ö÷šþ$"ŠaŒýH:QœaÊ1*ÃŒs¤0ŽlJPÏò ¥ ЮµíÊæŠ?Z·¨{·a ô£ 0ˆÕÜÀÚFæ\7Mëæ—s%0.@2/ä{¦ÔÒºÖ`¼À†( ø”*󊶪´eZ×[P³Iœ$-2à‘‰gª£õŠi˜ $å‘£—KHpÊG餠ž­£±/a27"´Š  Ö(ðn‘}îBGŒ iÉ$-Ljî¾>B˜3Nfœ™¯B5 bº×ç¥ð³(ùüe¨…^ǺÉÃO+Ç'Rüçsî ߪ@ –ñûKK8Í!‚÷CUÝñ'û‰&HÆ/k> ¥% ƒ/eÃFcˆ×ðŠ8^Z4mÛ3çóäfJ£kCádÞMU¾GÉf%€YwŠÝX¹ ‰¥G;)RU0;Ç%厙§”þc¼ÀB[—}o 8>’±wYë¤RœCÓòxùÜmurz ׄLæ¨Zç˜:–¨Ä=eZAñ÷[Öò¤.)W—äñ<˜wÇ­ÂÛZõK#?Üu:?ƒ›ýnº¡ê×îóû-QP¸7ºðW’u‡5E„Ë|Å϶%÷R f;ò…3Ñ7ü@i«‚'d¨bŒ*âÌYqÕd¶ïy ^–fgä,š>º,›GUÇ»êlb b— 4æãÿSàhR¤èp|‰Ý[2” à%ìgYv?º.0\ý¢¶ñ¹Ä'8ÿ«9%¿¿ fE¯úëÁÔ1Ä&‰ügÃØIHþbÁAu÷ ¥ÖÕ8î‡ôCYõ»QÖ/]Õ_×c¡É ‹|.ž.ó%ôU4µ(® \¼øÏׄ ÇÔ½Z“ž™5L«~ Äø„ ?k®nÎwzluÖË9™Ã•s×£p;dïð…z¾¶⑵ˆZ@ÕÉ’Sƒ,»ºˆ¡ËWå@B‹S£œü÷¦âˆ…¤â¨nkˆ¡¡±_«ï;!Áu‰$ØŒÇVë^Ìp‰ˆÈßQ©¿')RžœŸ•.©sÇÉei‹³c6ßÓ>@䳯HZ)ýˆ´ƒØ´–@ /ÿŶ&t ôë“çÏž^> endobj 82 0 obj << /D [80 0 R /XYZ 90 720 null] >> endobj 83 0 obj << /D [80 0 R /XYZ 90 720 null] >> endobj 84 0 obj << /D [80 0 R /XYZ 90 394.82 null] >> endobj 79 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R /F67 34 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 88 0 obj << /Length 1722 /Filter /FlateDecode >> stream xÚíYÝÛ6 ¿¿"ÀöàgÕò§\àÚC;Ü€í¡»·¶G¹çØ,ßÇ?R”;õõò0lV8SEQä•òEÿø¢ŒE’°2‹jw9îýwTáHâýíÅ›_ðˆ•QÉ·›±ŠÛõâsp½•{£ô2L’$Hß.Ã4Í‚ë¼Sí2¡ ­6J«¶RË0ÎD)ž,¿Þþzñáö°wǯ‡ßX—ð…`ež§h/#†R¹HOR²0Íòr ‹³à-}dßwÕŸRkùüùý׫º'ö¦ÓD¬j½Fë`×NžæNOžD/깞ÑSIƒjN=¦1+ñ(qÎ"0ß*×vfëݨžänߨ·´zrÂX0VÅL8ÿW]kt×XÙEÊŠ¨Å‘ÝÀίêvÛõ†,º¢Ï—(s'y‡dS·ÃÓåNVÛºU8|4ÙwÔuï§ãã´¥p×pfÛªÛ?k“;ìO¤àL—•3Íé§?ñ¤µp’s5Å'šÜq¼®±Uo”©ÞôÝ +·v­zse¹ZUêÁq{¥”¾úãœûÙªNùê=‘'‘/9ãÖ‚¥™ÛöÓª>©~hŒ ‹]–ãe9à¥,Á\çÙÝN¶ë9ý)gI–xÁ‘'øËY Cž0>¶b0ªG–@ ´r§ÖÄóûÚÁcm¶Ý`HH¯ßª¦ µÜï!ËE@h†i¿¨nÁwæt P³Ì!¸h™TSéPYLò±àÁÃ2ˈ¡\5ŠA¹‰‹à÷Î(/%Í%e Ô/ªÅó+wzü¤¶‡"–Óâ¶¡X*³„¿8§T;ZøJ ’çúPÉõ;ìÎóá¦nfälîgLpq¾/Q×!cf3Ù÷um°Î*ã,K³ó•a…Sí¬]iÄ:[Õoò‰BÓ»•c·!Þê ÞÌ.ÐÒ.](JkÆÄÕÔ¢éºJy`¢€.˜û¹#,æéäpñåƒl†Yd†> endobj 89 0 obj << /D [87 0 R /XYZ 90 720 null] >> endobj 86 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 92 0 obj << /Length 1919 /Filter /FlateDecode >> stream xÚÍX[5~ß_B%&Uâ{î•x(«‹€âªÊ™q“¹Ï$Ùâ¿sŽ';ÙNʪºãËññçsùŽ>ñáŸdþ$ –…é$¯®|7º½â®µÅ@â‹åÕõ—ŸpŸe~Æ'ËõPŲ˜üêñp¶™ïf­ê÷ºV³E„ÞAà7ðŒZ+£ê\ÍÞ.¿¹zµ<í ñ`PâÐ?bb§!ãAH€J€ÐÂÞiêɺ FÞT•ªg"õ:7õ›ù]CmÕ‹5kú¢ àØK½Äv&OÝãFªÀÃA<`<"l¾RFç²,ïg‹0ˆ½¶“¦Óõ{ìEÞÚ4sú Jœè6Š*y§+RDN+þ]3`oCº~´ô7Ÿ‡¥bgÈ8A{iµ ¤$ëmˆÍn#;l¥^ÑÐHÝtÔÈ2©´û€ícgŒQ¹‡hn\;qOí¤¸×˜v _.÷­¢²Û`Œ­÷uÞi@Aà }×R—4ÔÝ5î;êWrkíŒR²?/Nȶçö!bí‘&†‘¶ˆ¤”~L:u×mÁÛ$}—VØ'±[Œ*žlñÂcoݘ ­Š£4–xíŽl“kt’*æc ¸Y’%½æ•,^#Ç!D½Xg´r»Xq©2;£:"«‚  µ¥C,­K<Éìþgž)uÛ‘Mmþ€9û< }gAx>IYÇ! R& MP³8nãò9üóƒ,÷ŠŸâÂgaÌO2Ê„$#ÆL±8)X"2Z¸$w¶Ã,Š ‡µ\•.ÂŽ;,³"…QêBÍÅñ#†sê¬Í`Õ3Ë1¨ô×­e„{þ¶o‰·È/ãÆ9rÚY¤¡£¿3£FZ'g¾æ, Oþ^ëRÕ²RcÚÈ¥<í%ç£ÊÀFÉP— ×mæ"O×F<<ª*ô¶ž¬ê;yGæ®÷Õ MÞGÛê¾SíhùKý“Kòc#¢”qž:z}+|o¿Ã¼È(Ÿ /ésFÍ80Ê}¸Ð"•e¡N9½Äþ½FۙƃÁzae¬;:UÄ)]aJ@}X0Y!Þã>Þ¡˜…aä}©ûÐ'í}(õbÌŒ¾ ÏdXrŸBƒ±ßÓ`ì?Ð ´iŒ B Í1Û,ö©W@ã)BúÑ1WÆð„@_aò˜Tã`/ö{š´ˆ!qHLmé4œ2fY$>°9œ*L¬×ñ«éî B`™š†Z*€ŠzÖ¢èàÞåÆ ’ß€ä¨ ¸ö¦Æ0°*[úJRû°çC¸ŒTÕÕ :–±°½‚õVûiWêQãbH9jÞÀ‘r¨2l„ðYÄ|– 2H5Gt›¦ÅØ‹Dä}NKy¶5$Áëƒ4×¹»p^ëz·ïÚëBvùjn­7ÿtÎ}ß§{œÓÄG 7dºHY'1´¼ys‰nÏI1_ß¾¹HjOç´]c:GgÿlO¸Zº×B·épïÑc3ýß°nœ°0I.°n@¬+„#¸€XW¼FhT;pý¶µ¶°ü€Ë6TÂ3ѱˆ£‡Ca‡…­Ñ ¬>"i{¦üž†5[šœ̾® 4LY–ƒÁÒ‚‡Ë|‰YƒØ÷¾PÒдvb•® ·ÝÇagÜËK|̱“yêNåûŽÎÌiW8;ð 8zÁ±£.K„kAû\õ¶R4¯@؇ŒU·¦iIÝBc^­úí|¯Pµ–åHØ‡ŽŸ¸‡Ž5 /KkÈíMoA|cùýK $Ü鲉톮¥87˜Àj€hòÎÕJ;Ö9mÒmî(£v¦¯r­{÷ÈNìõtÔà _™Eï6¼3ÌRp¬¡Ü·Šîdµ+{­c—|àØÒ<`aænáM­Þ¡ÎwM]Þ¿°k&ðƲX`!HìS¢ðŸzE_n—_SëæåÏËÛ×ßS瓹]ë£ ÕñxüHYq\_6.0ç©?ÿì«WK’€`TwlÓUåg—KÊ£GÀ"{øŠ×ÎPhG÷ -Ý ™Â ìN¯³¥9—M—Í8|)ÁS¼3MyÑ~9dêOæLìŸO[µU·û76Ñ|:ƒˆðCƒœ^i]ÀAÅGõƒèïqLïÙF7¬nÐÓ“/®Zóƒ»#|½\¾¹æÌiyögýþŸâMqþõÇÃOP ‡B¥*å¶ »Ÿ¡B–¥hnÁ³‰Q“õÕôÓÓ™ð¢Nx,XšºX&j[Õ’…3âûaˆú;e ¦ÍK¿¿©vØŸ²çoî» rN,á&¥V2ß²çÓùôÙŸ½IÿšŽX1ÜÝùX–PqžÎE Çßà†j¦?ª\érnyæŽÁÁ¨¤bë¨VÔÀ€VfÚ»áo GÓ endstream endobj 91 0 obj << /Type /Page /Contents 92 0 R /Resources 90 0 R /MediaBox [0 0 612 792] /Parent 78 0 R >> endobj 93 0 obj << /D [91 0 R /XYZ 90 720 null] >> endobj 90 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 96 0 obj << /Length 1601 /Filter /FlateDecode >> stream xÚÕXÝoÛ6Ï_a¤}‰%ê+@¶¢2 E׿m݃,Ñ1YÒD:‰÷×ïŽGù#‘Û`X ~à‘<y¼ßýŽ2Ÿ…ðã³"œeqÌ ‘ϪÍEèFï/¸“PŽ4~¾½X\'|ÆCV„ŸÝ®ŽMÜֳ߽÷ë²7r˜q{âj‘xïWålçQîšäJ²­ä<ˆ’¼È=žÌÿ¸ýåâÃí~ï$оs8ÔxyºèÙéÒ\0 :ÝÙÈÊ|*£ŒêÚRÝ­—ÝvÐ_Ã$Ä,®ÓìØ9ÈlhׯT#Ûr#Iõt/‘°œç£¦?e-aY´·Uu›lͤ©¡ôjSŸºFU»)K±`q¿ÞÒÝÐm{Š‘VMú™¤L1.€‹ãNëA”', Å,à1ã )ß®•D©·Ú¶F€z4šy«n ­–nÆiÀ™=RºyÓÑÎ`xpÏMmºV™nPíõ˾‡Ë)q3ÍæAžÝ7Õ4‚òQ£à•ÓaU[«UoËîCpoÝi£QŒìöتڡZ­vnf-7Z68*v©É@°£‘nåfhb¼tik¾†\ÌѨhxàËÄ™o׃w|¿Ø¤Ù­¦NIM£´!éaž$^9¨rÙHŸ†jÙ¨2²¦îr·¼#ÙŒ[ h ®•‡í*ô~ C0rN—F#ç8Þ£2kúá2Œ ó¤_š å˜%‰Aœ³0ÊÇjÍÐ5Wv‚ Ø ˆ„À v"ÜãeÍ,ï56×­ôM:X<”âZÉöNµr¡Ú~k4ô‡mËÖsî!ü7þë6¾°y0šç#™ýy ³"d©€6 YRŒŒ&X‘£/fƒœ­.~#;qœçœqðzÞï꽨KS.¬èHµÔæÝ¢úAöÆôØÍj9<ÈáÝ[tz¼°£´>Iþ€‡p~$Þ8dQ’MÒ꯲¬åp–R£„EñjJ;Ë^ùk)õ?dÔü0j±¨HŸgüÿR'5Ë÷Œ ¢eÔ¬ðd–%Õl$Uœ|Nª0fI8R…Kª8CÍxï8b‰”µÅé‰Zc±z†L•¥Ìì„M3`Ó²¶dFŒ|2$!m7’d{ ˜ÜD„;cÄ}™wó‰Ú²®©5Þ·Ô>-éZg×’äÂå7ÀIþÔ¡‘ á-›²½'µmJÆ#\®Øêõ|ªYS_×’zGêö‚4A-±·|² rFü‘e–—à€ ãýFÑQµ‚N¯l5¹wÝ’ŠÉ+$c'Sq:FDcm=Ý€ƒsδ%!RÔÏŒP…l¶°“œºtŠt<ÖFq ÷þ­R6ºüšBv ào1WÁàŒ¯.bÀ@q‘ÏâŠYœþ£*–…Ù­bÍèÿ4‘ÂË4Ér[Â’Â…ðcg0viA,ïi¾¢¦ ½îMMÝu‰À$R¢‘¶£uº/+ }Mý%¥®±Ähõ-Ôí^n)‚ø@2h‹ÐR‰(ªŸé£‡È•@Éx{‡ˆÓÇ6d±ËïµÔŠ˜X72$£CÖ‚î)ÇZ][ œòv€Tjké,QsGòãZ™Q }Ç<‡”¿žç±7>õäS¹éy5‘QÎ ‘€¨É ,^.Zî¹ɇÏÐ7­Á¡Ðâ—ÈÆ>FÛh2>còÓ¬>K½m¬ÍÅRµ‹Æ½+ƒ’ÚE×›ïo´ÙɧJ=ƒ¥‰ÃCl¯×8r¹¦Z ¶U%õ¥Eá7vp·ƒ/spçÜÝ€ùŸ†¡ÜY?̦_”Øó±ˆÝˉ¿7—>¼ô^nõ"—xÎxPX”:*»iŸÑaSšýU©é+ãhþP5aþ€IxJ`ât÷®«îç#q±ÒS`‚ È“Ôfçî@HuoÉ‘M78Â8¸¾§ô‰ñ} Øÿbè̓ÚXõl»tËñ0µÐÉz¿R“•cÕ±â Rú€µvGêP—¥Ã¾Ô잨¨Ï|ecêð”å¡ó•ªœýÁêRY†$2µ_˜j|ÖÄ®ˆ ‹¢^`˜àøª˜x¹FaƲäðþ¶ÿó¸ÿx‚žìu> endobj 97 0 obj << /D [95 0 R /XYZ 90 720 null] >> endobj 94 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F67 34 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 101 0 obj << /Length 2209 /Filter /FlateDecode >> stream xÚ­]Û6ò=¿Â"1+Rßòîm€éÝÃîpHƒ W¢×BdÑ¥$oŒ»þ÷ÎpHYr´°¨áp8ßZ¾ ᯊp•E+â|Uî_„úùw« l&?Ý¿øñ]ÂWOã>!­¨:ûì²Ú )›Úvˆ§—ŽÊújÈ|–A;%KÀ.0E€–íædÐðX› ÚÂèsIÌ r§Ês^ƒ)#dœ÷n¬ŽòàÒÔ%!hâ²Kò …·8ÿñEò€´‡—RŠ8dTÔ(N¡;äÏŒSk3A[ò’ØØ?Ʊ¯ðXNj`ˆ ¦¯Iê`¨ÛâPâz*ÑÑ(œ`œ ñL®LƒK±òÏVÖîúP±Wõc­¶€OºµÞb÷ S M´Mzh%†^#¼„Nätnà$òT]öT¹¯ªÁè.4§…¶$8Áð²'~°KSmðÛ‚ NŠ-'&Á ‹Ä_Ü m¼ÄX çG‡õjqÔai: °; _¾MG åÂ$ì¤þÿ®KQ1Í:pÛ©]e ‘N­A×çÁŠª‘À˜oÁ™oû¡ÞÒódGÙ^¨Ï©KµxÂÆ@$½v;e_¼]C[ls$’ëi_?îžK¯~&ó±‡hÊŒê}Ï,½oÓ¿3¸7“Þ݇JßoìníZY[¨„VÆ·¹nȲI`lT0Ð`~”½oO'˜ÚY’j½h–‰l2s,™9x¹°³öŸ¾;î@"ßHÍCh^ø·€Ü¼;÷°×ö{ Ï9sU•Q³™m‡)õî´K#îtf‡/ÔŸû”±ÓCãÖòàÆ\é,㓤65 ?Œ|‡|¿Ê/ïaL¹2Cÿª­¿¥9x^kG·ÔÍæøzhim™‚§—–N¾4·Î ðÏG;hšD®`<¯†Òš €fhç7Lz Ü$αd,}ïiGÃÛî)÷®m{ž‚º£" xbuiq]šCgè´îˆ·jGÍfîIkV@Ó×<à$û‹{–+žäÜçC‰[è3@³)3ã,Êfi¥u²—_ê=†È°ŸWJ…%´üvIŒ&Žs¯¯ŽÍÛÍ3á]÷çp˜úü,/vç„îJ¥¶Ÿ–hÜ0u¥?ì‰<‡L4ªª°¬#;ÊXqž§yuZý.êTó¢Èæñµ•%¸Üéj5þ¤³ñ¹·«{5OÿymìA§“×N§ÔrO½ÇÞñ]õÿb‚,b–|æ'Ûßw˜/®–û´ßñ»L (¥/}HË}‰¿2EþãRìÚªksßw16½9¾¼ʾ«¸¢D˜·ZúÊ7E;ýh$qˆcÀŸ”,•ð endstream endobj 100 0 obj << /Type /Page /Contents 101 0 R /Resources 99 0 R /MediaBox [0 0 612 792] /Parent 78 0 R /Annots [ 98 0 R 104 0 R ] >> endobj 98 0 obj << /Type /Annot /Border [0 0 0] /Rect [350.749 356.824 522 367.734] /Subtype /Link /A << /S /GoTo /D (ChecksumDatabase in cfagent) >> >> endobj 104 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 343.674 240.328 354.583] /Subtype /Link /A << /S /GoTo /D (ChecksumDatabase in cfagent) >> >> endobj 102 0 obj << /D [100 0 R /XYZ 90 720 null] >> endobj 103 0 obj << /D [100 0 R /XYZ 90 642.092 null] >> endobj 99 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R /F52 20 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 109 0 obj << /Length 2165 /Filter /FlateDecode >> stream xÚXëÛÆÿî¿B ˜,†oRú¡u[ÀÚñ5@àð¹’X“\yIžO ò¿w^Ë£t<ŸZpÜÇhvvæ7¯ Wü…«m°ÊãØß&Ūl_²úùE(£ lf¹yñýßÓpþ6؆«›ÝœÅMµúà½=¨ã ízDZ—¼Yo’$õÞîÔ^wë¨ðÞ°z§­îJ½ÞDi±-¼0_¼ùÇ‹¿ÝLg§QôŒpHñXºèBº¬Hü0NXºú¨ªÊê¾ÇÓ.¯’æ~¶Ú„±¦L}sùÒ$óHô±Õ¶.UÃK;c[™GýŽoªm§^q‡.ÓL/tåh­è©9ñ’»®îö(/Üš¥ Y¼r§»}ÝiVéÎŒ]ÅÃÛu”{'+§ð;\Ô¶òÆ€ê Ï|¼Pwüýë¿Þû¢3UnX=Q0©§>Þ%˜4Ëç¤Qágqâ2YªØ)°õ×4ò‹ p¤—̲‰b¿H’ó»“i’(öÞýx—ðhR2NPÉø˜.ò:ÕÂ(ô*žÂmA(Ø:ôT‰;B¨„C¥a·õV<ßYÓÊAü9ZsK:Ô—G®‘ÙÜ`N‚ TFï¯7YÁEj80. ïnRl­n´Q‘{¾1ݾç2ÐÊ4Þ7æQ‰û¥‘3î^P„  ".ƒ‘ÍG\õÎv¦´Û¯D‰¾W-êìb4ºÇá¶]® ›e‰¡û%~ ¯—¿³¸>çÐêàãÓ™Ÿd‹tz8Ý#T™Ј? å§ÿT÷oÅ3žsó9˜¢4òZu_·ìë¼ ŽÿÅ–7ÐØø-§“`z_u‰À:𔃦2cSñ&ÈàD9Åâ?-hü‚ç˦ƒÀ\(6äÌdЊaÀƒ­×Ÿú0ßÖ’xÂДJˆ–üP†)HÞ¾˜ö5oðRcTÅÌ«Q–Lð;‡oþÔ¦#TÂVTm{Ä&Ÿ  Ñ×èð7è}IŠ„ü [š%°Èf:Ç©šerW`Pw•>²®a4ÅÔ"ö@y¾•”•Þ©±–TÊ.ÙÐUcàÙ3úÇ®©ÛŽº2PB|?õ“X”à÷gfÞŒø<È1¼h[8(+pè~þò× ”-ð —ÎJGB¾,z˜e²ÿ0ÇqøÂG}­7¡ž’ õ¾Œ†í q,Eúpð?a2öŽ!EthµƒêöBÁÁÎd4ùäððæåÒâ»õï‹Wðó(w˜Œ)W,°JR?½åOñšÒÙ+ÂÔ&ÎC?ÎÏ•t´ú× LîÑARq]( @ÙàãÀÓ†AŽìe™×›‚!ÇaXÖM¯É¹ ïĶy½­÷ <ýZ÷‡ >ˆ2ÝÉ"EŒÐéõbt(…‹‰³ £ªáB±v1ŠgפÅ~ƒ5Y}’œ]`²4•(âúËQ)×oΪÊÁ¼^HBqáG!—ÛlÔPG¦ÞŸøƒ>Ä£ïP…‹(:Ö›ïfîuî;ÛÔ/ðœ™óü¤PÛç<_BQäqîPV•TBã’ÜQADRgÀ{,L®‹âDI43ÒÈCc4ò3Kñ1‡è„ῆcO¼Ça™RpËቂþ—QpÀ¼Ñwz _T1 Ôpàmû¯%Í ;8³‹ç;Eà§ÖÂ;0Hß`Å›Ÿ=?Ù‚¿NZþþYßµ“ŠÔ$>³,ä+ý¼Yݽ؈Si7»q]‰pgÁ(^’Z˜yø&PB ¾qz*àgÁƒE,nQ{ŒŠVÕ¢EC.>¥Tª¿¸7š]¸å_™ÇûcSW932¿pfª[”º©ûaÊÔˆQyCÂâéÏJ*Ú„ÚOUíÕ²ÎtnJœ&§¾jÑ$Td¶"jUÜÅ*ˆ$Wêt¨[ý›éôõj•yÊ–¶w‰ãQ7ô’Så H¹3 Ú Ö4OOß®¢,‡ÝîßP{Ú¾4V¿mTß_Û¼C-§XÊSœ€‘ûöø¤@[†¿ŸL÷ŠG³ç˜½–Ÿ+¡h2kUpzK¹@ï©Äíz%+ãt—…:Þù£B–T¯›º:ǘɺÇ"ÿ5é½Ö—Ï>Q‘ûIX¬Âmäç½ë€²hsöôã¨63²…Ç©Kf$ê{]b£!/T~Ì¢|xôFõÓ(ŒsŽÔ ||í’Ú^îµ}ôvlýáñ ÝÒû•P=s‰Kf߀` Çy(€Œ:ÿÿìüIš±^T˜Låǃ÷ÅçÞ—LoKSÔ(ùõ©ÒWF‰“¾²ŠZ¼À‰DV’fܳì!÷à»Xç—Ûfn0aï3ñ9<ë¹|ÒeMi<½×”jdnôÆwâ=¨V$íË‹âEæAø‘èƒðøË;X×øæBC%Û—žM‡FØ–kj{lj°¼“Ö9‚¹4@·wÅ#u`\NNd;ß 'óênl)6Á‹°W¯sÌìȪL"©+C´ž£]’ûhÍÞª«Ä4‹¼Ÿ±¯!ƒÐ[Öª²<’GŒ> endobj 106 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.418 190.04 509.752 200.949] /Subtype /Link /A << /S /GoTo /D (Cfagent Runtime Options) >> >> endobj 110 0 obj << /D [108 0 R /XYZ 90 720 null] >> endobj 107 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F67 34 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 114 0 obj << /Length 1640 /Filter /FlateDecode >> stream xÚ­XYÛF ~ß_!,TbEsé0З >´(â¶I€ÎÊãXˆ,9:v“_r8²¤µÜu¼A€hÌáòã1˼þ1/ ½Xˆ •‰—íoBGý|ÃÜj ËÇ/ë›WoóX¤aʼõv,b½ñÞû,Y,yÊ…ðÝšòS^šÅRéßsü ¿6[S›23‹ëßn^¯ºçOƒ'Ö0ƽ4H#õÖ0ı k>„Lôо%¥*HãÄr¦À ¢Þ ½ ìýæ…HïÁrî=É£@rÖËPïã´]J.) ¡X(Ðm¹×.S[Eµà‰ÿ—Ÿˆt¿P‘? IºvìºÀÈâª/×÷xÒlÜ^é{äoôã>‰ïŽbOëÄj\Äþ¦ËO[Wj®öŽÐHD–ëâ,˜2T¹ÓµÎZS7T‰ò’*QÓÖp9¸‡Ýe¥Ö?$¦žó¡Šƒ8-Ç미hC’ñ¨ °g ×™®ÁwŸL_Û®vv€ñÑÆYk–VZ„)OUEU>ß(+Ånÿ;§ØV™TöòV³ ƒ˜Ç=ÇO_‰Å ²é­6wÅ—®jÍUÓôscqBë±°éÅ­Ç‹Ý:%MB>² RA_ÿYŸF,`6‘í¹ç\š]zÆ\R¦S[‹ísnÇüìÎà ð&HB1Ý„<£æ Ÿº%*Xhq£ó²¡=Må"C½Ûž«hsÈ2e1„L 0¤,V`ƒ4‡DÜ8¸ù\×=KC;.Äsáxn„¯úæ¾íAa4e‹> endobj 115 0 obj << /D [113 0 R /XYZ 90 720 null] >> endobj 116 0 obj << /D [113 0 R /XYZ 90 443.731 null] >> endobj 112 0 obj << /Font << /F51 5 0 R /F112 68 0 R /F54 28 0 R /F52 20 0 R /F72 4 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 119 0 obj << /Length 1301 /Filter /FlateDecode >> stream xÚÍXMoÜ6½ûW,‚Ö-R¤>öÖ-Š äÐ0-qWª%qKRIüï;)YZ+‰¸FàÃJÃáÌ›7ÃáÈxÁÞäÑ&c”ÓlS´g‘—Þaÿ‚B8Óøåúìò7†78By”ãÍõ~nâºÜü\Uüh„Ú†qt· )eÁÕžD·%Y`Ü‚{¡DWˆmHX–gη_ÿ~öëõä›òpVãºo2”' µà0ÎP¶I2ŠpL¾b/ºC݉Ýîò¶î.EQÉ-Xb©”€—$ã‹“c †4M¾ÑYÁßh%~+ôYVö²Wîi4õ y5_2D^ Rüb–šN«=Ä1ÊX¿)””ù]µì꺆ÒçF*m_iÀGy'}áó¦‘ö|Ü’4å…“šjÜß›Z”nwSk£ý¶ÑQ‚›QûU]ð†+½sˆ—'Àã%bðxy#”qÚŠÒ(…eN“[n;ñ©×»Ç žÎ7¥§ï§÷‹,J øDF¬ìÍ*‰$F$]r(Ð} ~zšMçqD#Ad>Ê«ûY•îÈ.Þ=!ÌÙ;ä°þ`Ó$ÑâÓ‘w[ß8¨eç“åé/z¥|wkîÝ%´Quá3i“>9I´ðÏPžçK&ÞG8]Ê JƒÒv »EåР¬•( òî¬PÑxïr¢Ì˶6—¥íwh¡> Eé{7/ ¡}„ªo„¾XÀà q‚’8û®nöJ¶ç_ÀÏ^!3ܼ0‘'€K¿ œ£'›è™¤§Ç ˆôé³×+²Öü¶ÏäðÚU¨ºWMò‘O¨¿Ö¦¶oL}ùkêînžjh?™JüÛƒ~y i¿{ JùÔeóÐI‡ ²E?5 ©ËûW=\úÖßúbœ†Í½‘GW®wnàJ¹íÐË¦Ó cçÐ,5zátþÁÛñÖglšUT‹òÒ‰ýÙßL•hšB¶-Pãc¿…xÓÀG}¿Íâý_…ü誤Á‘›j‘¬ÓäŒewÕþ!bJ6˜¢˜&Ä CÙ'Gqî'³«vi†0ÆË¹·`ÐŽ†ë$… F)[sPÁC×ÝÁÞ“ °Im |˜&µ“ÖÚi˜9üÖ¾âL=t/夦âÆé·v/÷5i— Ùi˜ºÝª­>oíAƒ7ÇÊ  Ápê÷YAafô"'orß…ÓgUŒ0›øPº€`»cÁ?½u3¹$ÐPÓ莃rÛÁ¶S&èâ$(¹±×NçˆáííŸn—%\`Έ-/V\É!Pt¾=‚ø·üm¼©kØíÀ§·° Ý[wßMs7¾ÊȼÊâ*ž’±zÑZ%2”Â÷•×8w.øÏ%ÐúòxÜ~ÎæÔ7ÎÝ÷žµ i„ˆáò²D‡4"(Í—e'ÑÊCJ]_§Ó©æá¨º–É}ë½ÚŒWXvV-|[åÍxÅ‚=×zìÿ‘þ1Ç endstream endobj 118 0 obj << /Type /Page /Contents 119 0 R /Resources 117 0 R /MediaBox [0 0 612 792] /Parent 111 0 R >> endobj 120 0 obj << /D [118 0 R /XYZ 90 720 null] >> endobj 121 0 obj << /D [118 0 R /XYZ 90 234.882 null] >> endobj 117 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F60 10 0 R /F72 4 0 R /F54 28 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 124 0 obj << /Length 2515 /Filter /FlateDecode >> stream xÚ­ÛnÛÊñ=_á¾4m¹7^ü–6 zpNšÀ@´…CK+‹ˆD:KÒ>òñÙ™¥D›Ž/)ô°Ëápvvî3’')üäI™žäZ‹Ò'«ý«”¡__IÞ-ay„ñ׳Wyoå‰LE™–òälsLâl}òïD¥‹¥*•ÖÉß6®¹¬·Xjm’k…«N¼Û8ïš•[ü÷ì×W?ϲJ= bÜã&K'ÜðÒžd…Râè?©Ìñ°»œK%2ktÀ:ÛFeÒTû°K“vCª¡µ½‚«å‰óU_7—ën»ÞíϯªH¶uïVýà™ž—‚WÇÇ+c…±&ž?ìz_ÿ1ǧ6Bg:â½™£•‰ÌŒ”º¡1st”ÂíqׯÄbiŒÔÝ›VIªònÄN–:-…ÎO–R i‰Fß’N«Žt\ñ±f¾…,â±ÛÊ/¬LÖð-’Õ®êº9^M&Ê<‹±ü¦ª^– ?SCxÀóumlš Í·¡ÚÕð•k©w¨~\+Z®*ß׫aÏÛ¶ëAtyi’_óvæÑŒM÷ÞA4Ý„àfØíniûmX€ùŒŒ ¼Ó‰¤×í¾ª’v4P“lZO [´»p0>!gocµ©.]ƒo{z×û¡YU½cÕ ®âkò‚4¾ë kÝöó*`±¾TÓÛ»i.Cçürí‘•ƒ(—¾®èuÄÆËvOàN?‡»·D{]¡Bo§Ž"ºÁ—Î}³iÔ£íçüUZ) 3úâom³®nßÐÇgƒëâ“IþåÖÍáY'BÌrŸYaÍ#€9/po‘šü%{ÛD“™ûAy$/3'ýd"Wc”ø‡OS¾0l%pw)=Ëoª@ æq)¨\ŠRå/±ŒßêàMÃÁƒÀsÚŽ·ÜŽ®x‚y‚²Tu|Ô(ØwS1ÌØYŽe ÂÌž ‡R‰"Í~ÂCÐ;¯Q lðûQ<ôó¤wþza3ˆp#ôq=Á”Ê …NvžÚƒÌR{.Óûb³öê™­r(¥ÒâÑÛ*iD¡_f&xš¿¸ðij&@_‡°»›ºßÒ.ÈÄyz`“€]‡eXØjÌÓ…ĶLëAC)3‘Ùqx9¥…áä|^@%dàTÅϰVzØ$R éú'LâÇÙfß’+mä'`GØbËßU·2&AHËY+yJ$1…Hóò'"Éã÷û¤¹ÈÒ‘Í_«,)fÌ÷îÂGqà[¹ý˜ÛÓâÀCT «ÕOh=ÔŒ®ò/¸v™‹ttþÏ^–eÎwþìUšÎ»<è©|ü^²ÈEžÛ»<–qþ¢î=þár®ƒ–§¹üo¡´Ìu‘üòOZ«õÚ;è3ÂC‚ɪw}lp-±Ë£â%|²êë˜×ðyÌc›jÅ ¨*Ü÷ñȇT¥U.d1 ¾¾º6ç²Tç®Îg®HÅ¡išíù âäЖÜ'Èû”çèf”ùcÍd–ÝçtŽšÍÁMÔ£Ôò»Ôf[¾IŸ8š&\|Œª”BF£÷”:Yµ{ÊíÐ,¨­Dhh+ö浢¥s߆0|O!È"´Þ_íL%«ÅR&ø½ëâ ’v_Qþ´‹«aíã†~ Ö/W5'­×„Òá×·{´¨ âw4;¾ %”­=¢u‘b×I…“oqÊБp k·ÉûEÁÇ‚¹?*¼È)‰WË“B”YfB½—`+êì”G5ûÛ (A=Èéil>hFÉÃDá; (¾·ÝæôtNËxe*7£šŒÉ&jZ3ˆt„[ÇÅá@})‚p²€ëèWQ†¸¯7´V»mZï ͺ¾®×Cµ;:#’¬|zC_÷½cÖ¾Ì Û }pÙi=Nñ¯g‘,R¬³©MÎ¥ªËïO:Ü ­Ø®Å bä(ÈW¶L)_ùvOØ«Ã_ðÄù®ƒ8I%¤]ÎX t&–…Šžìžw;ÇðŠ|KaÕçx;=c„-GïÿóSo†Ý¸ÒÒÝ6-UŽûMKh…ìTÀ4©Í¢gÑ `Ó²¼‚ ” %ýukªY]×¼î ² !wÛÿ†öc oÆ#»€]ܱG‚ñì˜p‡Žébýa‡þ¦¹3ŒŽCãîk}ÅS°£$ȵÈÅ®j¾òšË1žö†ò…•®%”+®aÇ:wAÊ.m”¶`»vWùºû^C¼yF¹Ò>JßLé?÷€µcmC¥bzq­=χøí«®5'šDn’ Ã:G.„mÁèQ v"T« ¿&Œœ&n€yTx øÈÿrªÃì¡Ó«f*#r2\}ÂÕq’c7åKs<õ³¶Àël   "9LB÷DE74y<Û²$€ ?ìxªýð*ü¡r3U_ƒy2&V_·`^±7÷¬Ð(2ë`¨‘2Uí²„œežHŸ°!F^@1ÛÑvÌ:øÐ·—.æt“ôõe(R{,ìð5‡?MU2nHØ%LtÄä(Àæ¸g\I@ìbœŸ¸¡áD¹¦ÖÐâÇŽòdýàývä=ô.Åø#ëMÛÃ$kè¢`²¶¡ÚºµÕ<,¶ãùÊ·—¾Úïù_Y ý[s9T—® 'åÉçÐ% ôrU5ñ7gÜžó=Ähøß3Œ¡‘Yp9ŽJB‡åPÿF…a××k7w:Þ^‰ÓÿXø§øÿ¥üØJ endstream endobj 123 0 obj << /Type /Page /Contents 124 0 R /Resources 122 0 R /MediaBox [0 0 612 792] /Parent 111 0 R >> endobj 125 0 obj << /D [123 0 R /XYZ 90 720 null] >> endobj 122 0 obj << /Font << /F51 5 0 R /F60 10 0 R /F52 20 0 R /F54 28 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 128 0 obj << /Length 2595 /Filter /FlateDecode >> stream xÚµÙnÜÈñÝ_!?-«aØ/¿m¼q°yðkå) lŠìÑâ–ìǧ®&9c*N€z˜êêbu]]GKÝDð§nòè&5&ÌmvSžÞD‚}|£ÚÁ~EñÇ»7ø«…y”«›»ÃšÅ]uó·àý±8®ßí1}·Û[ïŃkw: FÞèÝÁõ®-Ýn¯ã,Ï­vÿ¸ûË›?ÝÍgÇZG8¤øŽt*²°ko’̆ÊXñàÚ‡ºÅ³ó4(š¦CÉž^¿à¢›p‘cÇÈÊý=RÖ2<Õc‰dG^w-Sm% 6òåNÓé´ÓÈ™¨Ê¦à,¸ƒ2‹qC†²h; κšëf¯X½½2¡ŠY;ÙF&\ãÊ‘áÒõcQ·²1ÝnxÑð×E9Ö † ÂÝ>‰mð‹Ÿ‹~¬Ë©)ú[@h M7:þŠ%Fº{”ø…a1VÝ>ðZ´éåD2¶°'[¸á–´‰DÅŠLq0:g…ê0€¢àT<"ÇØ²;Á4x ºQýÔ }Dñ›ñ²×ƒ,H`þÊÝ2®ðÃy-C‹«¯…úNˆæïÈïÂÌûpC3ò(Y½¼·øœCЬä)5!8¤Øêbþ²ë{7 ƒ•Ü;sà…w{á¿á{ØwMã*Æ=!¦`f†C î–cN'”c­ +ÒÐ-2¨è™¸ƒz}ã,LM_Ò'ûŸ…æòžÆadbO#‡]3Ò NgF_e”x24ŠwÏ~æÜ#ñסë5).:O½„ÒàBÌ^:øä$ÌÈ]‚©Ì„™™%+ªJâzKÂ$ ³ØxÚºõˆp¿9L ˆTzà½+)kðÍ7± “8¹ ,pzq*š¨æô‡Y¢™æ'8'Ê‚¦{¨Ë¢ÁE|üõޱ\ˆ¾É4€:‰ éf´$3H—2ò©4…x¢åœÅøþ¹l¦ÊñbÎKH>ÈÙe飔ӻaºosž(ÁmlœºÞ1,b÷\ß7²þ6Äm&!ŽÛ‹5¬·×ÖT nüqTL:Àï{þá„@ëp1JA¸(?þ¸È*´±õ4p–bŽ_6P…Q<_±·[üâ0Õs„þ ú@[̪µÃX@IÆüG‘i6 £ôâÞ:_49+BEwÏÅéLÖ6’Pº©©xo.±¼ KÆ{çâçÚÏsŒŸ¥OÀ º• ¬³4÷êœ^Ó–ÖÆ†&™/Û;&IÒ›,Ì“Ä"Å^#V¬_*—DÊ!‘ƒ§r‡:Ó … ã"RÃÁZ8¼e¡Þm©²0Ó¹Ðûš°$Ùk%öI±]^c) õ©†òÜP\c‘VyÀUE­ o#͆G¼q\—¹±ßûnGNxè»é¼é†Ô„iª7¬)/TÀÊ爿»&IÃ8Ÿ7d‰]Ìq°íUµûJŒ¨4´ö¿±ßºvƒ €“¹J8WþÔ×£Ûð4Ä)zx¯“ÐXû¿Š-1tøÿޱ§cíÛ\chÚ‹Š®k|9Q*eæ§?3gOÀ0 HéÜÉé¶„&á ›.ÖH»‹DÜ!´ToÜïˆñ}Mñ‰ÛÐ:·Ú¬_ Ù;Kšƒ…OsÿÎ[&LŒ›a%WßõÖïo7øå¡UsSCŒô¦í3&ÊÛ~;Àx`àŽþ*u²—Rö’áÕAŸW±hA:ï9ýR­2ÆÏ!ª[Þò6½û.w´ÝèzÅÓúõäCÝB*ò Ë脤s r#SI‡nhh~º—Xa:êê:`×%±*ÆøækOÓŒµ>ðà#(\` éR¤£‡£øìzþšÕ3öë.†)¯¯»ix½Yu |BªƒáeijH¡ö2PŒàÍ Ä!ãDƒ¾×{᪎ÙÊðeëHE@²µÜŒtž»<ì•͈qÅìJXQF$è±õðÆ-zâ®ïµbˆ#ÅPæ¯k¡E/ÚXÃÖ Š=€–iž£–Ô‚ó62@_œÏ}wîëbD×:&¡ 5¦d辶BcE[5vÂSÂdc\YH+ßÄ,œå4›…Â& >Í¥•v¤GWAUÈ8O\W»O2˜‚3Ã!­!¨œç¦Ä«€õfmO®´Ÿ¢±XÐ-1ÁÔÂL»é¤¥ÕÆvË_O6¾4håüêAUßäÎOã2lp®9%Ï>Ö§l{}ÍŒY]ìéz÷n+IBºì¬¦fìëgP(†û4L­]@#àñ<=¯@É¢X¾ëÀ-õ «n8Tk»‚= Â*±>#)ê÷¢Ðúl;”Ðzçî‡JV­—Ewví²È~63ÝÓÐ —Ò=g‰¼“&¾:ºuÏ#Ü¡óÂvfãõl‰ÊÝ×E+‹²/^œÚúùóðUVnÿ*ÐÇ»ÍR“BW\¤ã_€¹¿a:ßâ‚â (d Ü:U!DêØëùy8uüeU˜*&ywQô`Æ'1 e ié-ËW¯Eˆp‹Èþñ±Ù*–‘2n­+7lÜz !3|;aÆúò9ë®÷ñÁ$ `NÝá8#w6Ûâ$|˜ñ J”qc~^3>Ï!ðMqˆ}qÀ* øÝ.ƒ;É”ª­ûŽ—šÊD²³NâÙ{€l:~Áxä¦~ÜQF¤3¤ZV,Äp±Åðû#`!0°2?ìׂýr.úÁí»¶yÙs¢èïýKÊLrê(7W›¹Âd¡Vöªû¢‡ã‘Cz–߯›¡=½¶6«)I§sõÐPí¸zèt©´€X=7òB@Y3 ¶KóˆldÊÅ07}â‹Î[:´Ìh±$,@zôµ›¥`tQU”Ø‹†7.ß‹.æ˜Ë`†4Ù ŸãÏvsÆC•©ï¿¢i5÷­Ìóðió±Ê\Ïl¼’0I’ V¯ ˜ÅúB™p`R‹ôU‹¸¼Ñ[±‰r‘…b—uã‘—Ü? EûÏ©hè^ÓØ (ž1â'l6‰ž{DâÍ„Px‹Àïÿîä?@§6,<ÿãÆÏFgJ6Ê)krºa/l]j/c$/•H×=ã(yâc-Pºpû­)“%&&IXP¾÷íæ žAÍïD½ƒµø ªWˆ‡NË. Qu'þoCn¯”JR€à9XëŽ^^qC²sW7‚`çæ±Oш;ëçxÜ,š‡¦ïãI(ØRø,…Ñ`UÞ¨ ëBÓ4‚ä#¾6ôÏHÜôÊbäRh¼G\• \úwuRœ˜ñOE58} ! Z­îÈ;œ @ëôÃ5Y-d®-»‰y»~·ªpÐx]:C“¼ñµ€%Â—Ì u,ÍøË%?·ü;¹ºÇ¬¡½Mäp6«‘–ÿ¡è•#x%é ?¼È?þþÇ{`ë endstream endobj 127 0 obj << /Type /Page /Contents 128 0 R /Resources 126 0 R /MediaBox [0 0 612 792] /Parent 111 0 R >> endobj 129 0 obj << /D [127 0 R /XYZ 90 720 null] >> endobj 126 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F67 34 0 R /F31 21 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 132 0 obj << /Length 1994 /Filter /FlateDecode >> stream xÚ­X[¯ÛÆ~÷¯P^j*ˆ6\î./úà¤vêµ ÷(Ðèr%±¦H…Ûúã;³3¤(*: Ç«½Îå›ùvV®Bø'WY¸J”™NWùáEȽ_Hnm`Âf6ãLJß¿1r%C‘…™\=lç[<«Q´ÞDY¤TðÓÖÕ»²vëR:øáW­ÛºÖÕ¹[ÿëá//^?Lg™(º# θ/Mœj!•&iò¦Þ+Äz£#<ìAš(‰ƒCÓÚŠše÷ JMý²§¾½]Gið ÿð‚¢é;ž_ã×§u”Ͱ–AË‹šŽ—×öàºoPAOÏå‹ÒDdÊ€>^¼wï^Ãé*4~[ê i×F…k©»oèëênð#ަõ{Ûã«Í¸åF*! íÛ£žZÆÁv-aUu¢ß¿ ¶*Aä_C©?ˆúQbj5[úN[ZØz\›(ð«rüÓ€’4`é“W¶ãžÆõ0Œ« ‡‡Öîjû¢9XÔÛŸl[ÚÇÊ 6Ý…kCÖP’ŠÞ•(ò BÌ›zú}ÙQ«ëÛ²ÞÑè粪¨÷¼äKx³ÛžÖ© ¾¥`ä7GDEàZÛ7-wµ°5K¦&¹óYÀ(oÍõFceF¥,«»mªªAy?‚=&3‘dŠü7Û2šÛR‰Pü54!ü—K6—Rh3¡õ%œ':ø"ßBãá æ$aÃQƒÊ¶eÁŠ8Š£ö~©wbU§Æ‹jùLQ¿Y’ш$Jg"j™e#:4FËv$¯O^g—uÁ’÷ånr÷ka`õžMEbÒ¯”SЦX4©Øš™TiyFó«w𡿦¼¿Ü•äÕiÄe<½ÿ0;2’_©ÄŸmì÷8þº ä«à³‡‚ýèýyà‰#8ÒΆSðÑæ‘Ê0Œµ0BB*‹£àïÞA}OñxôyÇcÒòç²ßS«ƒƒ¸3/1ÕcÏv¨ó¾lêîV~ID<2ÇŒ½´ Ž-a@çhŸópÀÇÀpÀ¿œVZÀ<ŠóÌ·U¿ñQ®ã™~Þ¶á&ƶBF±¬œŽGå0©h8Ãv>Uá¼fÕŠÅìÁÊœ¬Â Bø¥ój­)`±i@68«dÙ°c&N-ùûÛPæ¨áG&DOy´—­©•ÛªšAnï é.-g’Pî%ŸD aÊ?£t^I’PÌøãʃ# +© sÁsƒþ|º'À‚œ%Ç–mwÃ3Z7OË vîÛ¦nªfWæ–YÄçðEü†O¡t_¡íò0„y½øÑm1ŽýJ®R‘ű¦k‚Àœ#…‘¼É+\5-ÁœMËâd¶, E "Œæ’ ;gXyœñÝÂZ$a2m-lþÑàÍ3},RÇF†d“ì’. ÛóC¹¥ïa°¶œRG:1eå¯s_ër4(»íiœï]&üåÝÛ°×:g ®ÒÐH§×ÎTèL¸ßÂ-QõÎ;å¸ëK6,äU·]°dtוúž+Óÿ+Á*bWªkWâ=¯ÜÒw49¶åËŽ¶‡{ØãÐ;þM¼Ðò4Š/oÞ«æe5߯¦5vÖA0ÀÀ!Àˆ=œ—®ä‰Fy&\ÞšÎé2ÿ=\,„·fDTˆˆ®û«íó5PÏþY¡ýfx\²¿#E2ù±u;÷帴q&¢TÞõeÚÊäVTê0&W†ã=L ý7½÷ tÂñCe[AàrÜ•HE8x@½Ñ™ÞÑ0¡©yO_U@ï ´6´í,nql,ø$&>Hö `ð¶_p'xï0HýHlØòU“ÑS®‡®ÉÊ”= Ûž§ïy’« jxö†EmKTŠ?þlLÃ3 endstream endobj 131 0 obj << /Type /Page /Contents 132 0 R /Resources 130 0 R /MediaBox [0 0 612 792] /Parent 111 0 R >> endobj 133 0 obj << /D [131 0 R /XYZ 90 720 null] >> endobj 134 0 obj << /D [131 0 R /XYZ 90 551.215 null] >> endobj 135 0 obj << /D [131 0 R /XYZ 90 482.927 null] >> endobj 136 0 obj << /D [131 0 R /XYZ 90 429.873 null] >> endobj 137 0 obj << /D [131 0 R /XYZ 90 364.274 null] >> endobj 138 0 obj << /D [131 0 R /XYZ 90 252.691 null] >> endobj 139 0 obj << /D [131 0 R /XYZ 90 198.264 null] >> endobj 140 0 obj << /D [131 0 R /XYZ 90 146.422 null] >> endobj 130 0 obj << /Font << /F51 5 0 R /F54 28 0 R /F52 20 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 143 0 obj << /Length 1481 /Filter /FlateDecode >> stream xÚ­XKÛ6¾ï¯ð¡ˆ‘¢(©Ç¦ ¢ ©ƒmz`dÚ&¢‡KIûHÐÿÞáKÒz¥¬Ò>pH ‡Ãï‡Æ›~x“G›4ŽQN³MQ]EnôÃvR áDã‡ÝÕó— ÞàåQŽ7»ÃÔÄn¿ù+xqâçN¨mÇq@¿ß†”&Á‹?ŠzK² ³”8%êBlC’dyxû÷î竟vÃÚ !O8§5y—’ ŽQî9ïXFŽ©õŽ¢eÛ0a$xÕþ(ÞE˜Öb¯—~þ2Æ› åŒQ=‘d(Û„b~¦V?HP~%‘ÀÒÉš¢Öެö W’¿/E(çŒ'e8÷º`[¥‡È†6’Ò„Qf•wÛ Ðë·8Jy°mwr5¯`;F¼Ù&IàÜpÚ­m÷~ß؉YðºéœÆ­¦H”¥¦-&Aߊ ûꟈIP7[¨3+eAÑXÒ÷­Þ&l‡cÚaز!êNÜ…‡lŸ9DÈŠQ–¸=`_Â1‹ΰŸõÌ®Àk SLƒz‹ð{nµ‘4ž]í»O°Þ¿K æ)ŠyLïÃÐ cˆå °PŒÇ͇•jehJµ– Lè°‰Ã\0BŒ%OÆ"€‘Ît(âG±¨9;ØÖÆ «ƒ¬tžWû‰Ûî^*QtºŸÅLJÉ%<8òøü"ëëÒš Åå þz„àP'@ß¡ö¾Ò'ç=¤É,hJYØárØøZ̰Æ,^A´·×%—õ:ÜŒêp)bIö €_“|)Ëý?ÜÎf‹FtÊO¢E&h‘ Z¯Åí6ÆP»_‰L±ê È% Ñ,Ã3V œŒ9kæ¾Ai4š 3&cš'áÏœ®€DÄ™û‚;è«¢n©ÅÞ*á¯üÂ]å½ýÖ¼ÓGœb¿`½}ýêgÉÌ••XL¨‹Át^oC¼á ÕGñY6Çæõª«Îßï•hÛPñy㌀cñ×Þûs'¢è•zP`š¶ó¹B8‚newò§ÂÍ„ s6¹EÚªk;e²“µ`S öµç_]û¾\µ¢µ—Î FévÕ,Û%àÙÚ³ÃÕQ'G¢ëš#AÍ%²ÂÓÄÁÁƘ,‡#K´~Œ‡‚ ÆÌùÉ,Zf@èX½“: iÉU0lK svÀˆ½ü¬;Qô+îÒ`w æMʄټmûÁ‰®±ƒ‡¦,O·Ë5›ÝD‚¶Ÿ¸ÚÛÞY5GÅ«JÖG=å +ÕnÆ¡QV˜xÕZmÍ}+œÞï=ÙI]¦9sç²?š0ž™Îÿ¥ë¡°¼ÔdJ=ë½uþm]Ê[Ô¬¼èdS·âŸÞ>Ktùê3š¶nj\sn|Q|±¶¶¡Ü'aëä²ç/ÇeKè›ìMmÛ3W-@5­Å§ÞXûÚx8óïì@{júÒà1$ϸ%ïäÇ@'äæ"9ð¾;ŠÇl~±äXÁe4@s‰"šI‰Moı¨Îk®T«¹ª€Sâ(îÎ_ŸÚN™Ö‰A«nK©“ª–Z´YrM×*ÏÜÁ”LŸÌ„0”’/«½‡z°â]¡‰> endobj 144 0 obj << /D [142 0 R /XYZ 90 720 null] >> endobj 145 0 obj << /D [142 0 R /XYZ 90 720 null] >> endobj 146 0 obj << /D [142 0 R /XYZ 90 627.875 null] >> endobj 147 0 obj << /D [142 0 R /XYZ 90 573.155 null] >> endobj 148 0 obj << /D [142 0 R /XYZ 90 517.829 null] >> endobj 149 0 obj << /D [142 0 R /XYZ 90 462.503 null] >> endobj 150 0 obj << /D [142 0 R /XYZ 90 406.571 null] >> endobj 151 0 obj << /D [142 0 R /XYZ 90 351.851 null] >> endobj 152 0 obj << /D [142 0 R /XYZ 90 257.074 null] >> endobj 153 0 obj << /D [142 0 R /XYZ 90 201.748 null] >> endobj 154 0 obj << /D [142 0 R /XYZ 90 133.271 null] >> endobj 141 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 158 0 obj << /Length 1280 /Filter /FlateDecode >> stream xÚÍWKoÛ8¾çWA2É$õ°‡6ë¶Yt‹ q/û@ H´-¬%zI:MÐíßáC²dK‰o»RÃá7ÙÃ1ž øÃ“Mbß÷Ò ™äղҿΰ¹ àv4Þ/ÎfB<ÁÈKQŠ'‹ebQL~wH0uIJ|ß¹^ÒzUÖtêú~à<5ú§KÊiÓ韋_Îæ‹ÖVHÈÎ(#ob2Á¾‡ÀëM”öãMà…N¦nç^ò¼Ú*³³>ž$^EÚD/™¸‰‡£Ôì2š í(îhûÄKCå“Vx0õ4—£¤… á $ ¸bíôƒïÆØó N½”„Fy1M Ì;jâ].Í(×6Bò²^!x¯GúœåróbªLæS’8k*¬–u°jˆ`â’Ø‹Ò¨ïTÅÛw¾N±#(Ÿ?O]씾¤x-ú±øª÷”BŠ‘„Ø‹Ûàí@»Î*:ì'Ú/«øÏHâ©,†òç‰ÞL&À¹4Í MPdó“Ös½Ìø^jfàŽÙ(Ì7§+ ÜÂ|³Ú¬·€â–+3W¡“ëfkÁàNƵŸ5“ÖDµÕI×(™Ü;gÜçrŽá¼m¸ )ò¬6tÙ0K¦²6£> ,¬3ËŸÌ kVY %§¹düEÔ":¦A†V7ŠV9Í ‹5xqÂ…¾én¡UB>Éÿä^cx¾Oú„º£rÇkÔ0u¤aV„ ³”dmOÓ0r²M³Î캾ìJß"¬LHŒP®u>O!$‚øÎ&i»Y^ªitìŒ)7bœRëL›'õª§ø©æ»Šò2Ï6FÔú"”¤95¢š³j›ñR¨ûARs”| ˜àKÆ+ZX~òo¥ F×¢6%òNõ/-Åá^'wˆü™ q:‹íS*ãÌàÁA!X±Güè¿7ü…™¦Œ’hÊM¼°!È™]×ü%ØÄÔ6T=,¢Áƒhï¡ð02ÜpXo1&þ¡C¸å°þXƒ! lÜP¶OlŽ=í5Lú,|…£åª]ØZÉX¬`:,VºµaqN1N­ƒÚZ9¾/ò ™Ù¥sÎjÉÙæJ£`X&ð`tjZÚŠ’Õ‚þ½Ó-ÔÐùÉ šÃz¶,7êi²BÜF«~O£YDzªû Ñ{Çzß­ãþYòM&WMȺžmäxÿÎ^|Ï~\^|ü¡-õm6á뺼‡=xÐ^Cv3³¡\ÚÃØ`õtue`Î/~¶Çý<¿¿7³Å§w_ÌLë<*ó!F­ÆÑ>ÞÍß-æwo5ŸÐÜ<Ð|bŠëü9ƒæFw<1ô¼TJÓôÆa“Ç¡ª…tÁŠš_TÇxÛ#+Ä«Ó.F—+¦Í<¸9ÐâA²è…FrlËåo”3%œ=–õ,/ÌÚ¬z¹F½d®½~‰ã ×@ž-ÞS¨&TÛ 2ŸmÁõoÅC•©nó²#zÅ\ûn7™îí݈[µ¬-Éj;ƒþ“qylÍ•££°·wjY 0¤ÂO½$õ0rqø6ôõÍφ{èdÜ N üNÒ‡šMi;‚ÿÄ„l äÛ{‰0¼0cž®P¸”cA¸åtû++v 'dÆånK.Ï3¾²®ÂŒœ{®~ƒÿ Œ«w endstream endobj 157 0 obj << /Type /Page /Contents 158 0 R /Resources 156 0 R /MediaBox [0 0 612 792] /Parent 155 0 R >> endobj 159 0 obj << /D [157 0 R /XYZ 90 720 null] >> endobj 160 0 obj << /D [157 0 R /XYZ 90 720 null] >> endobj 161 0 obj << /D [157 0 R /XYZ 90 641.166 null] >> endobj 162 0 obj << /D [157 0 R /XYZ 90 571.619 null] >> endobj 163 0 obj << /D [157 0 R /XYZ 90 492.254 null] >> endobj 164 0 obj << /D [157 0 R /XYZ 90 231.631 null] >> endobj 156 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 169 0 obj << /Length 2410 /Filter /FlateDecode >> stream xÚÕËnãFòî¯Ð-µÉf7“C0ëÌYöm2X´É–Å>´$5¶°Ùߪ®jŠ’èxäF¿ŠUÕõîR´ á/Zåá*c‘«lU47!ï~¹‰x¶€Í âo7·u´ŠB‘‡y´zØÎQ<”«OÁÝÎìGÛ¯7qêÝz£”î¶æÉ¶k™#ôvk{Ûv½‘:˳@êõç‡o>n6¦®Ì@8èìŒ SŒU×.pÉ„áþ{-K»Nõæ¹ÁÈ´ŽD¦ä¤?ùªÙh-E¨¢?Én.éF$ŽsÝ( £R¡Rv…»­mŸªÖ~Ê ;q\j¯Œ÷w?-!mÄp%ÚZ3zôè<ªFCCÑ5 芎(Ø~k †Þv=MÓ`ê‰Vp!UÛá8Œ¶at~Ãàñ²¾«i£®†‘M&—ûÚ€ú"í%¤Ã÷øÁÝOÌ#á ¢Ñ{à,C‡0ç—˜s‡™À*1-öe´miKZÓ¹‡­4°}S Ø*“û;ã1uÝ!gÆwÄEw ÅØPÇ8˜E°Wwƒu÷ ù†Þ+à<“8GT2‹üQkÇ+LéN8ë¶4Ö \”°íú eö\»îÀ ;ƒ|~%-MèePô`LÒзO}wØÓ©ÁwÈ9€ êá;ºÔP5Umúú¸ÎTð-îÉ o9]©“èâ(&ÑÁæ\t¸ìé˜Dç¶ íL*ƒ­­ã3V;~¿¥w©Áé2 îíW$m{SŸíÍè$„{dÁ}ŽâKúŠ)‘ÙͯÉavnƒ*LɺA0!‚GÔnZS ÔW˜`a~ÜWˆèH;¢nbh(+Ll˜‘Æ2‰–yaضühÔÍ.¼·PþŽ•S5,逫º"^×YŒÊŽ£Üÿ M£âÝÈò=ÒÊÙÞó—gäÅô%m’Â5rÅjyØUííMψHš›Ç?ÚQ£<Po]K›`û¯¯,cw‹Nç–mN%³#•7´ûHWv'û¾#O*éÒRè¤é0ŽâÌ™€7—¶šQÈX øÙ…ðìø<ÕLUõÚà@é¿¡±`‰¶5®ˆ'á çÈA‘ì±¶¿Úôç΄R4!ápCå+HÚQ.’ŒËC µ¨ – -37•¨ILxZM¾®cñvë² ÃûKšŠñên¤ jÃ!kA0Ó1˜Jª³àg\“¯ÄÙ)àÂYYw¨K®cü}N,ê"‰ñ>)k9q)Îf)µ¦¡H’|Êšd¸¥äK¡ó)¹¢œA;è'iQÇ^–Ë2I\*‡Ÿ`}èÜá¬döP›ØBQ‰Ì±po v ¸…9Í>q–þ̼íÁè$¿ªéã<¡Vs&êzõ“—ȓ̄3þ×C%É“d÷ÇÅâ&Yýßò‡"0ÎKýŠèñ)5ƒX~Jy€ ë.a¦òàpìÜÃI\+/qJ¢+³®¡ç¼-HÜC½Áà%2Ç%FÜœ‹`ᙨ.iùHÙT)Ý£84è4 Ñ]3ñ·œK ã7¥‰‹­€ñۘ¹5ûjÌ7š‡irK—w£y^I2¯_\äÜ‘ü²XOYÂY¤ÎŽOO>¾H rë’œ="b¦Œ½«1žU»s,V@Ù—‰«7B¶{#AüÅBìÉ‚DzZaÍF3C\q_ÛZpYSå‡ã‘qq&•R>£"ºE¿T[šAN*=74‚{;øÄµ<U˜Ï»®æéã¡-ýÜ…nO)\ô("zо‹ÿa¾ìø< ”ÎÞ½±ó)BC,Y™åo|ÖË‹ MR å ¢¨Ï¯jÚ…+s%1\Š(ÊÎ…È¥3ºEB¢ÇѹLˆÎÈs4ÛÒÕ¥ÀÁ#z~mY¯ Ik%ÛõÕö.5g0¼VOŒ$hikŒ×¯»`ܬ°}K†ï>'ŸNSèÏ_t˜|¾9+Q¦÷Ö º \¦ôÖùéF\ Ü(‘:„³ÞDŽØ•ÜNÑñœ¼¹žÒ €‰žûj´ ŒÄ©2ö_Üšý^›K|@a¥ê¼ù±ÆãÞ.õuÎÙwCõr;t`CÕp[n‡[ÿ»ýáå¶%¯Ýð=˜úŸH`IΙHòdê-p€r›œ‹Ù[z/^ãRX|ô®Én÷' àîQ"”ç’ùK°~©â¥‹A嶷ëÞ×U?È»B¾oKÑ(Ö®=À_é3EG¯8Ä9…í¦I~…‹f€ù‘¼“¦J|x땜(_ö´;+ê](pŸÕ{|Uþí«‚ÝØô¦]ë‚h”4ÁÞ–¶ß°9¤"ºè <¹ðQŸf!ç:l\ûñy‡5ÎNÜ®°"ÁÙ[ 8q_]‡û|‹LNa|󾲞fKãïRvbŠ¿v±Å åR:õøŽÔ?m]4=Õ'¸ÚQ…¡:î¶ø‡$äì‘vüÁŒQlëK ;*ôðÔÐpŠÇ¸:½}q5é—‘o´-ô<¶õq±õSþë0Œ¶üž0•ûÛ,®ßÀóyë{DÛ¾kh6oiÐk7¹“Sw>‹pƪN€8ø¶Ñâ÷ ·¥­ù;î$©I ß.]çÔôKAµ¸8¸ž\жNÅ vJ¤ÙL‡©b³Äý/Ú:Î\'Æ‹æ)baùœNi†8ðç®à“:¸;ôþ‚ø8¦3š©àžÅr rñwnøxO‹ÙóVÆu7`‚%²m\ýƆW¾Þ:øùÞ!y(…¶4΄—Ó['dg–¿2ÍfWͯ Ú5$»|n¯)¿.pò6†¹5÷ Ì ¯ðϳÿXè endstream endobj 168 0 obj << /Type /Page /Contents 169 0 R /Resources 167 0 R /MediaBox [0 0 612 792] /Parent 155 0 R /Annots [ 165 0 R 166 0 R ] >> endobj 165 0 obj << /Type /Annot /Border [0 0 0] /Rect [266.122 396.748 396.054 407.658] /Subtype /Link /A << /S /GoTo /D (files) >> >> endobj 166 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 383.598 222.875 394.507] /Subtype /Link /A << /S /GoTo /D (copy) >> >> endobj 170 0 obj << /D [168 0 R /XYZ 90 720 null] >> endobj 171 0 obj << /D [168 0 R /XYZ 90 720 null] >> endobj 172 0 obj << /D [168 0 R /XYZ 90 79.203 null] >> endobj 167 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R /F53 19 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 177 0 obj << /Length 2462 /Filter /FlateDecode >> stream xÚ¥YÝsÜ6Ï_á·Ê©W©RžéC®M¦éä­¾§ëM+ki[VòIÚ8{ýድ–“ÌÜd&&A,‚ø¤.ø§.Êä¤i\fö¢>¼J„úé•’ÑvÇ?n^½yŸ« •ÄeRª‹›»PÄÍþâ_‘..wºÔiý|çºû¦s—»4Í¢Ïÿ¦ÑàîÜàºÚ]þûæ·Wïnæ½r­¿¡ r<ÓÆè •Æ ¨#Ú6‹Uš±6Y\Äêr—:z{¹SQ]»ñRE#èbò¨î»ËTEÓзLp2o€ Ô;?+C™¸HSþ¶ƒ_•*ªPêÈc© ˆ€]Hj©£¶á-A235Â|{lÚ=û;‘?·Ñ‰'4>ðÿ[°ªÜ°ænº}ó¹Ù«öM¬?œh†‡#ÂIž¼EžŸß0V1ž™™Æ NN‡¼yp|qoñ×Àɳ‡JÓƒ\ð]ß¶=J{jº{^»wH7˜Œ'Þ¿úrͶ-Ì…Ë¢ÈдØU—°uÃ;Wuûçtzt̪€;µqQ *1nÊ‹Mb<ÃqtÛû¡?>nÈÊl¬”únYn84ãØôݦ‹ÀÒØæä(Y^žÙakõƒ˜ˆ´¢!y,ýÁMÍÁAÀ n/æî™É›¿%²P ­ËØšÒ«üɶTUy <_þN§I¬ Ëú¼ôþÒ¦¤°ÎÈAá¯ŽÜ—Ç¶êª Á è“ø—ýä#O&òæGvÞ‘Yu{Y|pÍÀ40ÌŒò’ËD<+òPbÚž¤ÕèW8?TäWG?¬î]|¹ËTýÊþˆÿ¹ÏÈä†+>&¸Y™eâé|Ê®Ÿð–tzU¨ZOLrUR„eÑ©@$sRDÂÒ‰ÊZ7žÆÉ®D2ˆäjöÚ SÕt"\•VŸ0cÔ¸‹ìH9à8ŠZîKÃÃ$ò2*ù+Öß åxCÆx{ò„TÒ :8¸M ]"3±sO<_n&wCàõ±ª‰Mƒ÷gíZø¢61‹ÔÍ݉×Á4#]–./ƒ÷¥:<¶ä¶¤C"õ÷¾­†fÜ:ç±hÀœNhI œ¶ƒÙC…Sö¦¬Í¼u޽ޗ"Ζ¨¢XÞ+­ah=×Õ–¤".íÌ䥵 Tǹž·Ã¨Ù¥„é,«G_ÛT fZ,±¾ËUý³ÛS:‚#ÿòþ÷ ËuŽÒN^€GVÓÂÉ™¢(ã$±«‚ lшY>'¦•¶ðvé*-ÿÙßþ½¥p–ÇV™oXѪreÅ—„åéZTÌ0f¶t,âbI÷dÑåª8ÏòEIj¼øœC3ã|Δºg`±Ú³ÌãrÞòPŸ¾jÜcqõA6ª=à¢ûI h§òu˜Ð#lñÆ ™pòðݦ³)|2’U\¿¾ÞÔ3‰qôµë3±Q++¿ *‡É~3 tœd+ ~M±àÆ2]Ò[Šß;Hg ­=Ón9É#²1Ѽ0%Ò,)—\‡´†Éã‚meøêQ’ 6̱YÎïþÅÜå)§õyÕõӥÍHS«ƒ a/?‡‡‹?§6‹© )~‡ÁíÖÉ—¶—»¾c×nDòjz;“N³È0ýJÜÓ Pu÷‚AôŸ ù¡]àDX¤àm ¢Eùáih&YG:8ÀµCŒºFOUCxïˆ/;<ç¡V8ö#O‚ÜoùÕ  ϪDJœþ³×O˜r]ß5À·‡~½b{V6e±]¡Ÿ.3ÓºÌÁïªc;a€CAróÀ y4ºéœU^>¦BÐìa¸Fja΂' G9Ty¬ÌêëW,  dÆ@`¹Üf»¸ñ3s?5­Ter[È\ýä:qŽQÀäÚ‚ƒíbûë$Î| ^A¡UšøËÚ NóXïì~†`#, 8÷l2¿ØBs猃Pž™™¨ËMY½ögÆ O¶çñR8QªL¿%Nˆ¾BÚÈ· 9°5â o=Æ ØŸíeØ{­ï…µ¾••³}Ø‚¥XÐxÄ?id·Nd-8Ö.ÈïÄÓ;¾Hë74Ñ}Ã^ÙmAÎ3ÛQ>â<”…§"`€%ó¤¦8ÁŽÀ¢ÁWâ#Hsn/…š¸}–ðô«Š|Þiv<¤´®§V64¢Û*°|µM¶Üê«Íµÿ&÷?ð!#\ endstream endobj 176 0 obj << /Type /Page /Contents 177 0 R /Resources 175 0 R /MediaBox [0 0 612 792] /Parent 155 0 R >> endobj 178 0 obj << /D [176 0 R /XYZ 90 720 null] >> endobj 179 0 obj << /D [176 0 R /XYZ 90 109.054 null] >> endobj 175 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F67 34 0 R /F31 21 0 R /F54 28 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 182 0 obj << /Length 1966 /Filter /FlateDecode >> stream xÚ½XÛŽÛ6}߯ð[åb͈"uÛ·4I‹EÚb] E[l¹m+‘%W’ãìßw†CÊ’WÚM/(ü`RÎ 9Ã3‡ä ~|‘ú‹X–Êd‘í¯|ûõ÷­¬_­¯^|ò÷Yê§|±Þ U¬óůޫ:tºY®„ž¼Y®¤ ½WµÕÕ2H¼Ž½Ñ®2½\a’&^/_{õfÝÛƒàçPâ‘w‚/–F‘Dçx1&‹(‘Œ I[pŒ’,DFôyÛÔÇÃè;§½j?L}¯»Ý…";ë:–ÝÝŒ!7œŠn‡-$m6›¡ýÃ÷·Ä ¯RûsoDÌYóËÔ¸¹™Œg<$ ¸åÒ÷ˆÊÀjà,}\†¡§ÊÁ•À¤é„ÝÊZÍÞ|9iSs;—lg,Ã3·¡µr¯‚&$”Œ|‘QaÈ¢PŽw±íTóBµp—) ‚˜Ê„éTèÖÕ?Õ]T®—¸á®ªC/,(¢f’Ûw(|¦ÆUî®DupPW‘l—®ZÞcéöÞë¬#ʵ/•r ùT×g)ž%ˆPë=0ˆÖd[oxÀÓg".8 yÁ"Ÿ ‰Lœõy:ÈÓ€ù˜ÌA ‹J­ú E% ž KY]uM]^’¥kú€±Àÿ}Æ6RóŸ•3¼-ŽÊr3éØçðTî‡þ?'ªã îÿBTG&ÿQ›4ª†T¨˜°w à²ó‹ @¡û,{¤j|—ž\a”¤OXÌu©çW8¦fxÇ…ëãèœÞêË›”õýé5¥=q¥=±…Ëqc‹¦˜¹EµÁ{ÞYFÏ®=<íçP#( ²\^>ø¢H Ø_ySäôµ…,…*Eë$—q‹í&ß8üǯ)’ðÞ­‘âË¿ó¸a¦ôüíÍåƒÖÐÎv\C{ùJÑN¾Qp‡|üFäâ®{8èÌ׿Fts8³´•áæ£„{ ü èÁùg endstream endobj 181 0 obj << /Type /Page /Contents 182 0 R /Resources 180 0 R /MediaBox [0 0 612 792] /Parent 155 0 R >> endobj 183 0 obj << /D [181 0 R /XYZ 90 720 null] >> endobj 184 0 obj << /D [181 0 R /XYZ 90 522.092 null] >> endobj 185 0 obj << /D [181 0 R /XYZ 90 124.355 null] >> endobj 180 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F53 19 0 R /F67 34 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 188 0 obj << /Length 2157 /Filter /FlateDecode >> stream xÚ­YßÛ¸~Ï_á‡'£±V¤~P ‡»kФh·EáâZôŠ×¢×ldÉ'Éë5ÎP–líí>Ab’‡Ãá7ß0bÁ±(¢…Šã°HòÅfÿ.âѯï·V °I|·~w÷ÇT,DQ!ëíXź\ü;ùr% ÇÁ÷[S?ÚÚ,WqœOã 5[Óšzc–ÿYÿéݧõ°V*å+Æ Ä+Öˆ(¯É"Ë“PÄ ™´Þ¡ "ô¦?ê ÛE°YÊ<ØéúÑp¿©;ÛõI6[úíwüÙ<÷­¦±#‘˜ª¦¡¢^ÛÚÖW“ôfc:ÖØ£ØùÎÉ.WIßÒ§®×íîzÓÚî+ºe±´•ˆC‘Ò.l ÒÒk—ÅÈÝ6-Τc(f²÷9Çδwms<°ìÄwik¥^ö„ö6G¯¿nÚ½®ª3-m÷j¢9ºŸ–ö¤ ¾ÿ3uôáPYÓ±HCóÑW9Õ¦åîöòü U¨rïA¦áÆ+CáÔ<,WiüÏlzçÔ$øÜàòÎ|óäþmI´ßÙŽbq{¬7½…“®lòg’!‰8Ð,é ¹;¸R»S¤±ºéIèìVéY¸Æì E…)C·á8³0Î ÚÅ—š&ܯߓr Œ|‹sÿptˆðUÚhžú@ÑÄžð7m°ÙëÛ6UEކý@G‹EY–àÉgi˜Å™sr–_BÅ™1’d4übð¬°EEÂß5ýŽMq.æM°k[óóѶÆÛªÙgŠ;’é†}‹`c·p^ç+_ÕzµmM?n䘖øƒÛB8ìmt"÷k’àKÚîm×A”°½º…åý 4û\VSò [oÕEäÁöK?±¿äØ_2ŠC%•¿míé¹<4sŽ00ñrß¼'§€èÜQ®d”†I4=Lp@*Ó`E?7º¤ìáÉVæŽäö¨O“I?´¶7¿9‹/çódÚ§g³9¾mb9™øS™·Í;Læýí"ëúxqñwÃPïÆv^ñøŒq a*±]s‹6oZ´×_YOƒ×í,‹3»Î͵Š%œbz‹RAz)Kë`ÌõD)Üšñ ;¨Ø{°µö’„²nÆÎt†š­ï1qGdŽQhËÙðMØã£²n8ÓÍì ÉÃ|’ÔD™¡nBi¶úXõ³ª ıt(èl÷(ˆ#ÜÀá””Ab¥Â(SÓ ‚ð[€¬~¨ sã=Æ.¦Xü%@ãК'ÛYº3.k`žäŽh£àbÃ'‹€çD›=«€ä^—º-Ñ»J¢ÆÒ`½F› 4]r?1ÚZ@›ny¼©]>Æ!˜®ƒ#.òQ( ´C.ås4J “bdh.‘c®ÏÖn¬c¬Z?8˜v‰—R.ÛR—“Íxï;«%éÒÒ“-&™°ñÛæÂ%çcø=ᦪ\®Á¿–yBÉBú´(ôSƒiÆÔmó&g|üdúž˜ÛxÂÕ¡ð×f.z¯6×"ºÎ¯”ØôÁû~NSfÙp°æ2‚ ‹¢xåJÅã¬ÄmN‘P¡È…búD¡F l†ÑøØ%\£‰KSÏ]¾™•ó8‰NiUx÷ëÙ†¥Äù2UŒÜº©@·}žæ1Î{AÈ­s¢è••Q4œOÂvãaØåà ¹dýtDº®DŒn·$UaŽÓB»¶aå" ¾º;uö€Ì„Ä €L0ìgMXH·Ê_Ä cL]Îaµ„Bvòª«ômS9Y$噃òËŠv™°3?Ýs·£˜éçÇ(.…7 ŠYØoöÚÖ/Ì·Çpg›®jº¹R³ò6Ip¯”œ’p½Mþ*þü׿|B%w}ÏüXoªð÷¿º²ºà nïãÖ>ë!¶f„y3ËñÖ~!“GºyÿN í €Dù¡y2íɽBÍøhÛõçƒùP÷þ~€³] endstream endobj 187 0 obj << /Type /Page /Contents 188 0 R /Resources 186 0 R /MediaBox [0 0 612 792] /Parent 155 0 R >> endobj 189 0 obj << /D [187 0 R /XYZ 90 720 null] >> endobj 190 0 obj << /D [187 0 R /XYZ 90 240.529 null] >> endobj 186 0 obj << /Font << /F51 5 0 R /F55 85 0 R /F31 21 0 R /F52 20 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 193 0 obj << /Length 730 /Filter /FlateDecode >> stream xÚ¥V]o›0}ϯàa° ‚Í·¥> endobj 194 0 obj << /D [192 0 R /XYZ 90 720 null] >> endobj 195 0 obj << /D [192 0 R /XYZ 90 556.364 null] >> endobj 191 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 199 0 obj << /Length 1585 /Filter /FlateDecode >> stream xÚ¥X[oÛ6~ϯ0²•‡š©{€=lEƒmÖ.ñžÖ!e%Úâ"‰.%9ñÃþûÎ)År˜eÝ$âåÜÏÇÃÃÐ…?t‘ù‹$H¦‹¼>óíêݵ£¬Ž(¾_Ÿ]\EtA}’ù]¬7Ç"ÖÅâw/ð—+–± ðÞlD³•X®‚ ôö ¿§ÅFhÑäbùÇú§³·ëIWÄØ Æ ÅkºHIÇ!C£˜„QºˆÓÐ 4©®úò›Ëû©Q)[al¶kÞÞÁ®~¸ŸmR³Û·À{A¹=)¥j+Eu‘‹ªºåE-›K»ø¶Zõ;#ÏóneïrY|R­Tv:|ø ×.®¶ ! ˜a0V± ¤ƒÄ~f(C’,WQÌ<^ ݵ†ožQÊ,Çw†p„¾Ç5f3¤^£tÍ«ê`–ÿìÛÎŒj”ÔkùVX–®äÝ óNËfÉR¯…Ù¹/Ec¶òŠ·íÈú ”z"Wµ°òNî—Qäñ‰UZF¥‹%õ*Lr@hdœèÔr‚°Ák3T˜A{h;QÛ}ÌŒl;Í;¥-em3p”«¦TÍ(4s+µä­•¤e+²\%,›b8póf´¥µ¢ÑÑÄ3»-Ú ‚ä•9@›¾ÉQyûÚÌ+y·¹!•ì8•ÔH”Ä tvSªû›‚÷Á|ø¥®ôjâ`b±é=[Ñ‹=ÎcÐpGõÝ®ïÈ`þŠF a1 ŽÂ7e'Šô¿Q(@h3\©fk0ØH4$@8]‹I‚ÑLÞ\¾€ l°D°dB$¿ÇÀ©ÒWFï‘“0ㆠ@€6k­j³,öCÜõÁLKÕN1ÈB’Fñ ?6è«2ñS"oBqÖˆÄ=þQú©Á•lÍ$W=ÚˆÄZ´}Õ™±´RÍ©hí*¯UoN˜åV³ñ¶æ²"ºØ[—£l ¿’£M{©zm¨¤âÀ¦ÉL6Jç¢xík©&/ÆàX~µƒçæÚÓÊ;ðz[+Ôˆ4¼’x¼ãAÄ=ƒ 0`b~Ðsxe¦h•­ašªÂŸ†0n†ÂªY¬TŒëF¦Âlaj[b6»oXJ°¾FÄ Äé—Ct S÷@2¢ÁöËK#+NŽï.¤f–Úž›Ï½*]Ä¢ …O­ÈH(›©‘Qñ]+ŠošÂ„øG§“µKèÊRÍ.&ÞCás‰„@°0œDê^\l ¾9 ‰£lîè¬2½hòŽk^‹Nh‡ø0 ¡?Y29ìdH˜$swníÏjûŒÊ€‘,¢“J-•–ÝÁ¡Ñú3‡õ$ñ“‘àùUE¼SŽ+Ãùµ€–¬€†Ø”Á–Ì „\™¡Ø·ð° q?7ÃÇû.Éͦ-nes[Êmy[ˆ=;1ÀZwþ쉿\ÝX#„•f ½ÀëǦuÀv¿3߯1‹x“ q–ö¼êÅÑî0¿µv=’ñý LàrÒPAžîê#¶+À†c¢óñÉõyzSÅ‘OB)H¡ëËÆ‡W…“Êh¶Ðb±9ûÕõØÂ¢O‘×'4¡ŽB.èÝe³%`Ä#ÔMQ™Åø+c÷õ»wk3zýîÍÍ@~LÍÆfOÁããpk®åkx½×*oŸ$Ò¡è|¤¶‘5’,t¦<3ó™Rˆ½Â¥_j;´éÙ$š dó”Ô•Æ™DW"cHB.(à€…ÿ-‘~ OëØ‘È¹?®šÁ2U Û ­K盄1²ðQ:ûZ¶žãÿDqÚŒ7•1´Ìûâ±qäCX«†ŒÿÞHp– endstream endobj 198 0 obj << /Type /Page /Contents 199 0 R /Resources 197 0 R /MediaBox [0 0 612 792] /Parent 196 0 R >> endobj 200 0 obj << /D [198 0 R /XYZ 90 720 null] >> endobj 201 0 obj << /D [198 0 R /XYZ 90 617.415 null] >> endobj 197 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R /F52 20 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 205 0 obj << /Length 2116 /Filter /FlateDecode >> stream xÚ•X[Û¶~ß_aìéƒ ¬uDÝ iô À¦Ÿ§žb¡Ø´-D]’Úûë;Ãʲ«m7ðƒxr.üæãÐbÁO,ªhQ$IX¥åbÓÝD<úõFpk«‰ÄOë›ÈÄBDaUb±ÞM·Xo¿ïõÑJ½\%I¤o–«4Í‚w»z/ûe\–&´ÜI-û\®â¬¬Ê ËßÖÿ½y¿ugqüÆ¡Ä_¬KÄ¢ «Ôóg[[ùÿ(‹š~£º¦ß‡vs4§†œ°ý \Ló™%j°{…KLgY þNÉóóó«Œ*^»à¨ÕƼÆx­”žµÃ¤~½ø`¤%¯a²IXf9|‹0¼|½,“@"Ú¦k i°Óò÷Pr¢qµ£oÝJmÍÉœUj ™MÝSÃHKÓ-l”ú 1e M'Ͳó0e˜å X™†IÌVþk HË‚‡ûû5µ>=Ü¿û쑆ET,V1ø XtÒu¯ºº==”±&|€€Â>šýáq+Ÿâ7o^Zzë¥I ïD\N­˜>°5TOßð P«;7ôT·ƒœÌºþã%HÕÓDª~’Òå–"¸=vQc·`Ç厷>‘35Ï#HÀr‘%YX¤Â§sV%?ÕBËÅîæ—¹NbˆÐÈÃRÄÿjÀgÍN¶õÑÈí""{å·c£e½nú1Žf!aUé­Ã &öèŠc Q4ôÅ¡KÒ0€¬ußËVnih :7¥-¯2'Óª=8NÇÁ!úäÐÜliH~³ºî¥¼ª7ªem|E` •¡¥²¼Ušº”ƒXvuÓ†3ˆO0þ  KÞ“ù¨öÛ÷ÿy|ÿðpw»–ÆR ÉxjC¡þÛ³>NÂø*¢÷=:–A}<¾ÚfSÛAŒc;¥y²…9ç¡Fmøëb–Á±6!µ…ËU‘&ÁGsgc8Óº;¶?ÍÀìáHz”‘´º¦9(mWmãáw;’¦ü­ŠCV7û=X|±Ó¦uAró‡ÚŽ4>‡†d±EeE/,Oª˜t3h`f N`J€k¹ˆƒµ£jDkг58ÄŠ±Ù!{ñ ì‰YS¸¬ꃞbu×~OM:gtvªr‡þó( 뇣uÏ8»¹¨E¢$hzúî†2•2F#̸¡ÝRÓ:\*Fþ‚‰\”ñÓ*w· œÔ/æÐbÔ¼äCå7Žý©Ñœ³ßíOÐdÝèî d¦~±[8wŽƒ¾ôúo1`©ƒr1r®ã[èšd6‰Þ°5;p¿³€åiùmÓ[žFrįò‰Ãic.­§B €ÔOË,Çd§¥;Þ®gÇU‹1Õ°j`ù´¼ÎKpVd#ÐEêSе7H"¨;#òpA —×–ÆíA«oXìÔô¢³Ž:FÜSs7ôôŽÕa^¾Žn[Š»ÓÌ#þHë}í83áâÅr‘§›3ÔvLcFçÑ0¯Nï.î0tßsrï¿[Œ™2sµOrGš«ÇÄùÚ‘-wÖGâ¹±‡¹gDŽU}yéÖÿz3q¬;9]/ú0î0qbM²ñTÜEµ }Ð œêÌÜÎHG±—öD†‰]¸ÃÆ/—¢ÈÌMKÅá«©°õÄBta°àõûÄ¡SÞ QmcŽ­Ûø4jq®!Ù‚CTÄŒ ¶t*¼ž N.lõJCED%ÖÞȽÞ8©és.ý°ËÏBÕ²€‚ªÝGúx°^—[²ƒÖ“j«põ–gâwvÍZ¬ÆÁ'/8ó2èˆçrçZÝ2Œ×MƒÙïS¦w¨”I“7sÏäí4RöÎo*Ih\]zxk’¸XM²ŽÐGw¹«gœûCj·T UØ9ÞqQaá`¨U£ª(èjªV@bÕÊZ;BÃy`yvÕúêF¹F$­¦bÆ3®ÑtÜrp»Ôi¡…TiV@¼\sc;ãµþÿЫAÛPF¹¶‹Q‘9"‡.[ LjEד$OîÁI¹š6„œ¡§LòAòZ^nÈš¹u£;4T=VÎÔ†T¾À`Ã1ÌÄd‘éêB¸­h@ó‹šô¿‹ð(…G NðÄý]#øœtãcލò<Uå¹çcmìg)û÷îeþ_æs„…T&~Q­Y¼÷>¹]$EæquyŒ5ó¸9ÂÞÐ\AÊë¿E^-Š*Œ£ÿš€¾ŸüÓˆ«³ÄÌß “-øc6qƒ†ø§YFúÞ·üžü#ñÛ_LŽÝ’êÚȤ!<&†Îü%ê…þÞØ«­œÁ¡×÷'‰ÚŠ endstream endobj 204 0 obj << /Type /Page /Contents 205 0 R /Resources 203 0 R /MediaBox [0 0 612 792] /Parent 196 0 R /Annots [ 202 0 R ] >> endobj 202 0 obj << /Type /Annot /Border [0 0 0] /Rect [169 76.476 381.303 87.385] /Subtype /Link /A << /S /GoTo /D (lastseenexpireafter) >> >> endobj 206 0 obj << /D [204 0 R /XYZ 90 720 null] >> endobj 203 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 212 0 obj << /Length 2037 /Filter /FlateDecode >> stream xÚ]Û6콿"æk}X¶û¶ +Ðaè†Ý ÐîÁç(‰pŽHvÛÛ¯)JŽó­ÃQ¢Hñ›4ÛdðÇ6U¶)„H+Ynšó«,ì>¾baµ„Ý ãÇûWoÞålò´Ê*¶¹?ÌIÜï7Á·;^q!’Ÿº;šNowBÈä3Ç_‘X}ÐVwÞþ}ÿË«Ÿï'^9çßx b|ã5,“p*7ª”)’žtòÌ—Ïq9böH¿[Ó ïLQds•ªBFÔÃØ5ƒé»íNYÒÔañ‚—‰&`tzO«¡§ß½q—¶Þò"y¢ wêí@KýµÑö28‚¶?‡»úkÀø”1Ùj—nwežG‰À>yš‹|³c"e9½®¶Çñ¬»-¼ ¢îk«IùÃ),ˆ\WŸƒuênO5ýœë¯æŒ$Æ3!t€ÿANK˜ý~[°t`‡ãÖ¤. _ÿ&½OIÅXC¦B*Ž*GãEZVФi¹ÝåŠ'¦sÚ~Þ ,Ýšqà&«RÆËÿ¶6K+-ˆ¾@Pe©Ì&kïuÓÖ¶&ƒó²H:¦ÅUßµO´šDE€l+s ß'”¼ ðÖà%¨Ó™îH{Mˆ•ïÁçÞÜoeIKÛ‡ÞÆó‘´¹#?(y*¸ ~Àèី¨xòáÝ.¢ÕÝ“ô]Iqê2ŽN‚â=Ó¿s8=ÁSz‡oñ^ÇÞòðûådtëSØ'³´<õn×#Mò@Øè¢hÊñÅ+È>zi²…?_¼&zç´CZÙ¸%“¦'uÔ¦#±Íõ‡+m Àü”åÙƒæ]mŸâ–§'Œn’D¥—À¦5!ž?Š…ê‘²ëé·ïÐ+ª2ù`”WàpSæÂíßøyöP§ ²ÀÖo<˜à™\äÕåRA÷¥L|leÅ×èEAÑ ­ÊôÍp¦=×'0àŠ$œ,¸*Ù/ä¤@ª§åܺB^~tô˜:²ºœ<+g@mxi= jÈ`7~ú=\ah¢Î„*¡2€Ï¢T…"ÿ‡ÓšŽ¼Oê¶¥ÍÞëÎüƒY;½ˆ‰@ašÀÛ&Þ¼¦XÓ"ô]Ìrn}%b2¿Ýæ,iNfÐ~1Œ~Ãë J(A®9Q% kO¹ôË7·d*ÍY¾4÷ŸÞÿª@[˜TB¡ðZ¾DS²ä5aù4‡ HÓCMîk“LîÆî·;Ú!ïAî¯c£ƒ?Ý‚ÉîÿxTÿºE䍿Iïý¾”udWF=ÄDa¢"~4Ág'BÞg¥X_÷sI§c1 ñзmïMêÞ’B!Ë´RJúi™+ hHØm…zßÄ8ô@ÌÀÎå„êR7vòí[4/ ÆpÊ'Ÿ|rY¨nê†ïñ«'Ù1ñÐËæßIîß°ãÐ]k.t}erÖ5%`°@àïpÂ|ëX–SØ0.bWm%ŸKEò:<‡ìrï‚üäE +R€òT¡¢Ã¢ºÖäqX^F¬Y–@&T´½„‹&ˆ2üNÈ ëMö2/B̓ÅÑöãeí…Š4š-¬²öF .RNôý¾Üa–ñeÍw@Ï’ç á^6 †BU]•H²ÀX'KÊÈa¨›M—™J»_Œû{r‰0púàR±ÂB×]8¹F @T`qêýT÷Æêfè¯8&Ü|!hD^¥E)ÿ_Ðøx(øM£„Ú}/ž¦©¦†ñ+f^Æ ¶|ë!öäRn…źm;ºu4T;:{ oÍ‚´lŠä ý B½€¢“γ¹_æ. ¶E™ò’á`äüálöX»ÚÊüKÌ?áN‡q¥„:š¥B¿Rê,F>ÎÄû;4$—úB@ªÛ÷³ ¬Ì‹P9´ ì…ok7C[û~qClR¡êgºãK¾+zãßæÉoùMúBÑeÊ9‰îsm¢Üså°¬|fÝ,óýàk'b}ã¥·Äæ)‚ã§oÊkŽøÐ¾jC§yª\‰DDZ…%|ò‰ÎiÐÁµ#¾ÙD0¦HÜrÓ­ÐþÑ6 åxupº= V2æ›Ê9gš_mä·d`”qVõyh"äEúÓ«Ó~1ɵ“9ž4Mm ?º@R ‰Æ[D1Ž~ë–FcšuhÏ?¯6£µ8õI …*òÓa˜lý¦îÜhõt·ÓbÛûž¾¡i°¸-.ž¹ÕkÃñ후(Ã÷\QE¹xúŠèaúâT„/°1UªxóöÓ‡ÌËøéCPŠ÷Ã%p,oÁSò<4RÜŸº$+21•HAI±ÓÿZ†-¡ºv¨ßÑGŠÐkxíåÙR…ZTJŒ¼˜g˜S endstream endobj 211 0 obj << /Type /Page /Contents 212 0 R /Resources 210 0 R /MediaBox [0 0 612 792] /Parent 196 0 R /Annots [ 208 0 R 215 0 R 209 0 R ] >> endobj 208 0 obj << /Type /Annot /Border [0 0 0] /Rect [451.171 375.857 522 385.857] /Subtype /Link /A << /S /GoTo /D (homepattern) >> >> endobj 215 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 362.404 199.727 373.313] /Subtype /Link /A << /S /GoTo /D (homepattern) >> >> endobj 209 0 obj << /Type /Annot /Border [0 0 0] /Rect [227 362.404 400.515 373.313] /Subtype /Link /A << /S /GoTo /D (homeservers) >> >> endobj 213 0 obj << /D [211 0 R /XYZ 90 720 null] >> endobj 214 0 obj << /D [211 0 R /XYZ 90 656.907 null] >> endobj 210 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F72 4 0 R /F54 28 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 221 0 obj << /Length 1201 /Filter /FlateDecode >> stream xÚ…VKoãF ¾çWèEâ©f4zåØ` l½¬/Åvcy kI® ¼¿¾|ÉÒÚF‹ñˆ¤8ɤtÁŸŠ(ÈâX6Êæ)é÷'-§-lW¿íž~ý=ÑŽT:Ø×.v‡àkøZ¹óèûÍ6Žãоl¶Ö&áëѽùvcòpdEï¾÷mé7[“äEÆñæÛî§O»ë݉1ÿ-îÐe&ÐVÅ65‚.Í­Ò±etV›m’špßwîPºaÄkoc‚ u¡´‘vU=0ìº=v}ãÆºkE@ Nƒ?°dìXRvíß‘¶¾M½gÙXy6jýˆÉøØ˜,ìúï³sJï®;¸ßô®DeÅâªF…À1ÔÂZ€›BŒÃýôަ¾¿@î“$<À¢ÒXäzïðdW@r‚êÊ ¬uü ¡ žÝ2HJšB4:x@ÞÔmݾ±æ£ªg̨¿F‡W²÷á÷ƒ\‰Äx¶×€b¥¡($œp>à°”{ÿÏä‡|éPAuþ ¦:lPâ0§ š¦Pª"’_×Êãlïz>cí….fM—86ÊÀBëœSûý^•e©L’<âW^¨,çè§[kŒ2Yüs*ÖΣG®3« ³kÈE%@`Œ ÏÂC œŒçÎCɘ‘…È‚ŒYà}Ë ë F+ް31𑲘§Pnoô,t§(ìLî«!ŸãüîrW_Ðsȉ‹l iÀÔàÿ=ñ™n…£þ‚C×úAN¢úõ÷}ÇQв÷D”3 ˱~Çè=0$·˜2kuø×&/¿@wN3lëö ÷L"\±©e²û–A]-0„ÖM!;«Z_(ᓌR‡Ñí‘ËõP5$XÏT×Î#ÈSúq}ûV·2M¦š“lY`rë°<¹ÆŽŠ–UT9tV-³¨yaÊÅ:ÈU‘¦gr•p+»ö&Y…²Jj€£ffq{yy™ç—Æ)NZ#ý@U4©IÂ_ —᫉¿? ’Ãó½ÌZÔ*ŽSpžª”]Æà`ú73…ÀÝ@´¡ä›J'¦5Xr"@›Ì÷Pm¶~ú×h­`\§B{y„QgJçf6zFŸEe*åRn$¸‡Ê¿‚BÓà];ëdVÁypÍ|šö8r©¿ +‰³ŸyV¹eºùµ¦†¿; *:DâEËRÈV Ç“¥áç#-–W°w`ÊE(9‰OK]s†„bIP0xÙe´¹@° 0&þºm8WöõG=VÂô›Iý8†áJ|YòZÓÓì’› —øíÎg®,íÕt½†3O¬aØò~yË÷ÉëÒ°âkÎÓHü,ìR^8»rœ0'hõ¾ÝäN“¨ˆ)ÅܸpXïJx\Ö\ai$à'Ê|ƒèr˜G%Ž ¿±…ì<Ÿ»5¯0ï:Ü 5no /Þß~«´È›ä°5ñ;:ˆt«OÁÙh»X=øV½qEX¿à˜?ç`E*ÑŒð« ûöÌÊ3|Ãò)‰nA»ùà{u6úo7®dË}ÿ +ö) endstream endobj 220 0 obj << /Type /Page /Contents 221 0 R /Resources 219 0 R /MediaBox [0 0 612 792] /Parent 196 0 R /Annots [ 218 0 R ] >> endobj 218 0 obj << /Type /Annot /Border [0 0 0] /Rect [223.697 456.052 387.697 466.961] /Subtype /Link /A << /S /GoTo /D (netmask) >> >> endobj 222 0 obj << /D [220 0 R /XYZ 90 720 null] >> endobj 223 0 obj << /D [220 0 R /XYZ 90 720 null] >> endobj 219 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 227 0 obj << /Length 1827 /Filter /FlateDecode >> stream xÚ­Ùnã6ð=_¡î“ ÄŒxè P Øv ¤E»ÍÛv™Ž…èðŠTï×w†‡"Çr‚Å"+r8œ›s˜F ü£Q™D9ç¤ETµ‰‡>\P¿ZÂz†ññöâê×”F4!eRÒèv;'q»‰¾Ä\¬Ö¬dœÇ?oUw_wjµæ\Ä ¿<ÔV ª«ÔêëíoŸn'^)cïƒ'Òä,¢‚p‘1/MVB¹pÒÀ2Y­ÓŒÅUß­8ÍÐ7Èùµ '- e^‹Ûˆ-xoÇn#[Õ­XÙ8à¾V•?ï·î+-ÆÁmªIsÜéÕšÆÕPïWÀÞßð›¡P'TÀÁý8HSƒŒö¿^k÷5A¤ éõN"ÔÆ1Q^'¨›U†š:]nPÄ„pp£ݦokãVfg9Àj/ £N+€H÷™é;º˜KØÐ2Tžê¦q«®÷D6½'âL|ºûVë,M¼yç•=¸ÓÃm@°¹:Ôé3jµXBÑ{ü'…³‘†4Õ`dݹ£ÇU Îjy×(}‰°x˜po+ÇÆ¸k€™Å²•v{Ùm–¨[7à¢6jpŽaWW¨Î. ‚cÕDÝÊö§ñ¢ZÒ*ÌYÁ_|…›ÄÝ#þ§$ˆ´q[g|\Ýá'`Urê€Ó†€UYT•zœÉµ¸«={ØTĸœóÆØu‡.Âá‚JìîGy¯¬ÝË`:ñb:îM'ŽMÇ_Œgr¿wjÉ£Kü…`x/İCdÙ†#Â;x³Zƒ šƒ;Ј)ÄÛ+bNºÓwd¹B›‹ ‰ îÜ”[¨ge)úÚ(\m`…æ©‹}ÄÒŸUž!|tŸ¬î |­õµË^”²¨$eÆ2Ÿ½J"„Oz ÙõÛ”>Ë””y¥eB’ÄæÏ/_“hg (áe=YÌ6,#‚á½&úëâO—g¦¬ <Ï¢´(I‘”ßdoBhYF)e„§o±…BBIÎéœ+ì `š dJÌX”f9ÉsL!ƒ`öðfÉò9>d, Ò<ó! ¦ÕZi‡}DëJQ‚ïz‰ –ˆ Ž¢àÑg—’‚‘ð@òG(D s{š, [‚Mì›Z‡ŽÏ ¿˜š { Š5É%ÉSŽ4IIÆó@æ /Aòd‘Ãý’9¼ª/„è$>=u2ÆCš§ÿÑËDZ5ÔÏöô¦3â—ÙiI:¥¨žaØ›sÎÿ¬äæW°B>\)S]i5<ÖÐ'~¸d,AºöIàa6Õå$É}*ü3.t®ì60Q×âb€0ªìÉq÷´SvàKâV>XS[d÷q`‚ÖÐAvÛ~h§1ÑÍø MX1°yþ¯û(ÉË»s‰¦à¤ S~ãÅÕã6µýëA~;º[Õ|.ųéeá÷ëwOžl·h£…‹x& ½÷?‹[z endstream endobj 226 0 obj << /Type /Page /Contents 227 0 R /Resources 225 0 R /MediaBox [0 0 612 792] /Parent 196 0 R >> endobj 228 0 obj << /D [226 0 R /XYZ 90 720 null] >> endobj 229 0 obj << /D [226 0 R /XYZ 90 720 null] >> endobj 225 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F60 10 0 R /F52 20 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 233 0 obj << /Length 1822 /Filter /FlateDecode >> stream xÚ¥XKÜ8¾çW²R,K²]æ0l°»À^&}Ë µ­ê6Ú?ú±¿~H‘rÙÕÎHÙE‘ÔÇtË] ÿäîï2¥ÄQ绢y³ôáä§(ÿ¼yóþ“‘;‹c|”»›ÓÒÄM¹û}¼·çÑõûƒR*Òö­Môñdï\»Oòh¤…Þ\ïÚÂí‰Éy¤Ìþ›ÿ¾ù×Í|¶I’8‡¯¼Kã•w9,š]šk!•&e†‡A$ÉRW&"5L{­ßœ-?UµcÍUÌÚˆ\æAó÷ØÄ¬eVZ"ÑÉEIêÚµ¶Ù4¨ŽBuÐ}·eM‰XÉ ñ?û y<Æä4‹¦3{ ©Ì#ŸyXèNø+A Â—Ñ [ÇÊ|LŽ‹@$íú•Œ4ö¹ò¶á/oùå'Žó¯Õ@Ë=$“$§½Œú®AovyLE&5<(! 91Þ;‚æ 7)ÍÉ#±mKz8×¶ UË‹ôó¸7&²}eoá´Ú :-…ëMñPë§}®¢ŽÁÚt=ŸqšÚb¬ºvxGæ?ƒXÂÿ®@š$R$Y¶KÇ$EB†ýâ¨Aë°PÛ(¥kcÞÅÏλÂõ$ÇäÓ—Ïn«önŽ8¥ˆkŸ{PxªÆû«pþxÇ©ƒj¤'™\G¤s#Ò,YF´QzAë]óñu¨<Y’Ã…¤€Hk7áög[ŽNº@èløº_K1磌6„ï¡¢Ò E_1Z:üVwhíIPi€›Ã\GÏRs4%rvrcúMš`… ÚJ~Ƶ†í•™HÕ"À îS”™ à×ÛïÛÌ”HŽ*h×Õ¬ªåÑǬeŽe€¯a!÷©BI6Y·  &^®°È\ÏÆ{Ë6Ÿªº&Y'µAÏ‘ÀRNÁoÖå¡#… Í*Pg\í’œ/¦¾¿t†£‰ŠU«AÕ#`a´\ÇÚ°hYâúÞ—1ˆ7 „o´Ö‘)[1š@F ›<{Ñ×b©ƒl(×–¸ }¯¼Æ<2n€•¡É¤©ö,­„‰3BMf6nš–‰~¡ß8ü“k\Q/ôÚvuwWµ_Ý3Üà0+Ë-,d.LªàÈ~M@B!1@áŽJ28‰'®ªFàgÑÓ@ï]ëHwìHÐØÜÃÒ¾«k, ”¹çÂ=¥°É‘-`þ¼àr‡(¯Ý£·X „D†¼«=ï’1ÛœC£]eRž{ÊVBK. p]ùà¯E‹ÌgÒ³€_·DuîωƋÍ|÷®®‹®i ›\å¯ÚÛ“?}{¥mï\ÿ+åkßÝ`¨+£‡ OWNP5ïô…^€C†y‘‚¿š ޳øÌs®ë«ÂÖ$BñIAçt×-ÓÛá½4ŠÕUyÙ‡f Í'~ýœ<·økêúr«Ù”v´·vpÈZ¯gVæÎóæüSc{& ;A7µÌ% ýj“þ ÍâMp#¢¸¦º Ÿ}Nc³GUøÇqT; wÚºÑCaƒ‹ëá“€îHù;¢%ô~õÕalÎ{ñëIO†[5”Ÿc:8+åø Ç>ü9]†.ôIá×KÍM_Ó@)‚‚‚Jù+Ç‘U—984Cc†£¹i_Žf[L  iû¾"2€™gQ&‰þ Ÿâ+àQa‚¶Ì7¡O{á«ÁЍ‰4OS ¦zæ-šÖutö × Cu[ÕÕX¹á‡à5ßëìè7Ìêÿà[âú£üºS6ÝÔŽž93Т0ôQJ'øæ^†Ñ5\'÷òŒ¡·ß4Yµ'Àk¦€«ØæPØvaÓ~mÃXq±jÜÿýXf’‹A¿D³Â†…Öp9§êníÎb7h„Ðt'’ÉÛ–6É$”mW?‚V®ã-ƒ¼ÞsànœÎ[žM-çyifzâi_~*Kg[<Àˆ9¬oÑ)Ôõûé ݬtï{×tÛ¼cÃÚëipönî÷óÔRÅÚ¯“åÊjôî¯óâEl[~زô¹¸Ú âpoOßÀ(r¥÷Ð ·l—UÑAùÖT]òþ»JþR—ÿ:ðsQ:R endstream endobj 232 0 obj << /Type /Page /Contents 233 0 R /Resources 231 0 R /MediaBox [0 0 612 792] /Parent 238 0 R /Annots [ 230 0 R ] >> endobj 230 0 obj << /Type /Annot /Border [0 0 0] /Rect [221.277 649.199 485.672 660.108] /Subtype /Link /A << /S /GoTo /D (Setting variables with functions) >> >> endobj 234 0 obj << /D [232 0 R /XYZ 90 720 null] >> endobj 235 0 obj << /D [232 0 R /XYZ 90 624.804 null] >> endobj 236 0 obj << /D [232 0 R /XYZ 90 390.688 null] >> endobj 237 0 obj << /D [232 0 R /XYZ 90 261.754 null] >> endobj 231 0 obj << /Font << /F51 5 0 R /F60 10 0 R /F52 20 0 R /F55 85 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 243 0 obj << /Length 2106 /Filter /FlateDecode >> stream xÚÍYKä6¾Ï¯(dq±Çzø•c‚›²‡ô-ÙƒÚVu åG­eOOç×/)ʯ*w§w‘Á`P2EIõ}©f‡þ±C2!¢B懲ù{éåó­•Æ7>~Ÿ°‹£".Øáá´žâ¡:üˆôò‚ |{Òí“iõ1BŸ8þŠ ×'Ýë¶ÔÇ?üøá»‡y­„óß15î¬ìGEšJ4†É,Š¥8¤¹Œ˜dQmÚ‹=†…LâàG˜% ʳ./ÔTmEF™v€ÿôåaó×8‰­iŸj}3¢<›º‚^†[Cp‹LiQ˜­ö«dbwaÔ°ºÿ¤ûÍpæÇw#XS×0<Ï’i8š¢žÀÈ»Uý°^ÿg4½®¶ÃV«. øu2µ¶/vÐÝ›m0Õ 8®Xf"É`kžZUSûãÝ–A;ˆéª±Ö_·ª£R±8OÖå8l70rÂJŸ€^|Ýð=K'¬Ü27Lˆ,!O£Xxå9‰¨Æq}6ÝÔQvÍ1dÁõÈ< ¾£Ò¶ìÍu€ƒ!º‡³V-0é®×úþË‘ç~yÆŸ®¯läíæk»q{YTd°ª*Ç»·EØa Ú"bÉ5º3ãy”s€ây ý®¶ç¼ŽšÏgS¢MgRùéûŸIþkÌä קz?ÆA÷ŠÒS³¢Øù­3öqÖa>54”ìö€Ùõq¥"[|üªyRDÏîý;_¨+óÀ¿äÃ=§±$×òc,˜Ý—C2_!Ú†sVæ¸ ´€Z–òY¼Û]Žt5%¦Ð\R8š½½Yüµ,•-i*†hÎ!ÃÃ!© ¨‚á)•Uø;L]Þ&Ù+Yâí¡îµ1 ƒùþîbÁ)´Ëü{@ÈY$—‹k[pßÝ[qÄÒ[0P*%Y”2¾Ý8!$Ÿ².&P<ã%”iì²³•òâÕ,H@é>¶()*]ë܉"eoÖœv䪦ž:ñ‰à6q_—¢`ërFqpvƒœ&†ÆõìRjkJ¬eQb·ø!áê¼p¸µ.®Øtm7œ)‚.ãW¨:̃”¥Á¿`µþÙØÝc&Þmf))³\'ÂÝ S|°>gU79¬/ŽnÒ6¤ 8K-#ƒwæ¢KÍýVìûi®«N¾ôàV¦†úÂU0æÎ“AÚ] }{uœ3¦ñe×b¡×µ[ÎÔ¦!Ÿ,S&pîÀ5xÍ]BÓø4 'ó4óƒSgOßP¹ bÀi¤Ü!¶SDWë[çrd²>N|[+z6AåFÍ;O—2{ì³|ž^í€ÙEj8)wÌ9eöð ¡r¬j;Š¢ q™–¾WLÍNôèà;\P©ë›ÉÔà$uR¤ÁÅk¸ ²Ó”ûu3ø$ÑŸÍú¼eLfÊx† o_‘§u4T¨œUklCcc±á]¦[ú4SúΑµKWyÆ)QÁ‡ Kµ5 ˜¤Å„ bÂŽé_W‚?»4 ]Œ#}8€Èxa É Ž&NN‰X<ÍÐ{©›¼¥F]LnN¯ÐûD1ö˱9•$içgÂôÀËïAã Qç¤<Ý`c®ÖYÐo¦JBª+Aºß\©÷B÷¡úLÌß¼@‹<â óFå9Û¼ì5/tÍ{»8D î5¾¸Q¡§¾þ‰Í-N­(úb÷)o^6‰’Ì×ìï®±îƟ½’`]b¶°>(Ô\ߘ¨–þÞ|R`(²á«R¡èÊ}þ¹žr)ˆ³Ód›‡Ñùü¢á¼¾û`)X”//z(#AC´ÅwÌ5bç(#>zcßÒ+L:=¹zÉvÿN€Z£{„éúI'<[‘"=áTj Ö`ðëÒv³goËÐMøø/3a¸‘ endstream endobj 242 0 obj << /Type /Page /Contents 243 0 R /Resources 241 0 R /MediaBox [0 0 612 792] /Parent 238 0 R >> endobj 244 0 obj << /D [242 0 R /XYZ 90 720 null] >> endobj 241 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 247 0 obj << /Length 2751 /Filter /FlateDecode >> stream xÚ•YKsÛ8¾çWèªÊbH|Ížf=;µÙÃTjãª9dRµ0 Y,K¤ÂG<þ÷Û/ð!S±S>h4F?¾†ÃMá&6iù¹Î6Åé] ÔÇw¡ŒvÀ°›qüóî݇ßãp~äáæn?qWn¾x·sîm»ÝEQäé_¶;­cïvol½U™×óBk÷¶µua·;gyæEéöëÝÞýënÜ;VêåãíBúÉ&É´Fš<ÔãôÐÚ3}z¥^_55“ú†Ûáh;>ª™<:+¬ËÃØ+ަë&~+ÂΦíªúá0‹௄Ãý–M-äCÀÔüpaä‡1kÿkY~¬»Þæþh…qä,ðà mDüþv—%±÷q‘Fži†“œ¸s$‹ÔNP2€48!N@³•`”›í.òiééÐED×·rŠÍNô`åCÖæ„¦:pJÝÃOêYž|šwW‰öŽÕ#2ÊŠabw°ÇcÑœN¦.áTZ…Þgk/½Œêët“Ä©ŸEz‡ÖfŽ#L»ùNÌ y!ŠpX³¸ö•VÎàC]Ú¿‚P×pâ] Õ‰$ãíTkâR?T‰ãøòç6ƒp©z´+Ùá|ªšÇ³[é¾Þ°ÝU úäùÒðgˆ¿5uTì'yä6»zºègN·8Üün”BKæ› ›dêJT;®ÝŒm%²/…9oÃÀûó`Á;1ű×ÈoÝôüÿ?s"/*sdJYµ¶è›öy›iïij-Yë8ðuoâ\ùAv%Y;¦Ýĵ’.DÑi>Û•õÀ9‡h(? .r䗙ώøzÀ…(cšüE^Kµ©l§™Ÿ«üZ^®ÝŒm-¯]“¼¶â»0‰!°æ±»ï¡Fx°vÙ1‚¡`⣤Ѥ’`€éó&—Ð{îz{"–Ä›R?1¢àoàHÄñ¡éœ@ä!$@²@ð'P¹î !µ0'2Ø¡¶OküÇïŸ1ņ,ÓÅ}çtCheÊõB¦)\Z,„š¡ã14à²V·j«ØÒ‘³.×ä©|nŠ4S‹ƒ-_G3'„HÃ\Â3ÏÆë±¥ïêzîƒw/-Ãf„’ð¨Ž%Ïms¶~æÙ˜ppRÀ¶œ/4pã4eÓîÁÆMkWÏD~¬â¹AÝ7«‡ÿ F¤ l@^‘­c_¥o¼ž…hÛb¥|àÊ2ƒE,‚ZLd pxu²ÍÐ3 8üžÑ±LÇ'O>Ê*t¸)R÷[#™W^3˜,¿S¯DÀÁ`Yy`¾ÿ~ºe*íÑ`ýª-û í}­S/A)ˆz œh ,.“£0㎹$DÖÓeÎÉ[.“Ù'»ÞÕ±D»¤” H‡¶¦@¨•'g& ö/¶;Ìgاót!B©3ÁÁ¹ÄÆ;P|iyl úZ-ýièAµnÇT§Š26GP§o§êœ€« Eê˜ ñÍÁÈ'­ý6@](wºâWs¤„B¸©RWôÚƒú˜Fã|€*èA€ (B€É"ì2pŸ_yAü‡£?êè˜x>šÂÊxÄÈY¸.™V›$ÂHuôj­’É«qB^­UŒ ´¶%i…=G£çâ„<?X\!®8ÏÅñè¹»T)l_W/—N“°dv U@¤66ðöCëªCÕdfXùnaÆ×8\W•¶%UaÞÚcE 8³ÕåÄ¿¢(8ÔÉ´ù.¢MSÓð«q)wPC~kê}õðJ\Êv숖ž,±<èˆAi²N¦{¼Á’£¡!MCïã'f‚Ô !×É„ò6 îÛÆ`¿C9ËP’¼„•ÖÓ~xÎòbï—N&ÁˆýÉ2Ê]EÐËM‹PŒ'ß·Ðg™ã@-̹Nñ˜vŒ‚\Nˆb™Àpt€‚4Ç/F͉©• ¹ëJµ¯_+…,€.×à;mÓ"¾Qš›\,íÞ Ç¾¿ Í»éå¦J‘ó`ªš”Ëå­ëÁ# &¢.ÈÁÈ”k :P”¤|ø­±X%‰S‹‰N9Ú¿+@pØGëXÐ’K†Æ¶sRäKè-É«A"•A ýöïÛO<* aŒ‰(:MfYr-J¬<.^“ŠQ4ªˆËCß`a)-e‘÷Ö0rùû5hÌÍ!žUåŒUžˆKE¡:&ÏP1.â I;}°Šc?›Ô´Ò¹ÄcwÖ¹~÷Áƒ…Vú0ÒÌ ]ßFèï²4]ú£Ø”ß4-Ýæ ¤Qã€ý®ÁÜwüP‹T܉Չ{>(Afz×Á¬fh Û½ýrºæøÝ¾v7—¹ :9ß‘ËB–„y¿ýñ™˜¼2AÄU3•Zc‰ Ù§MK·‰4:º°w¶¥’hÛŽ‰Ôˇ+®=a²h½µWŸL/g ß`ƒø˜ø×Œ’‡~_¼¿Ò!&¹Ÿiµ´ôÙÐÍvoƒÀƒVr|yòJ‚¹ï#ø~ç×|?Ì? µÛâGª€ï§SË4ú> §«H\ÊG¬ƒ¾oN˜¶-PÚb÷ Ôâ‹Gè§ŠZÝ,÷¾ ¶}æ!EðÀ³žèÝ ( $EÕžz‡‚“H¿¦“øYh!FàDQ¡…6,DÅ( Ób s˜Y~Í{VdÁ™"Z¹á'0Ê  3½"œ4ÝÂú“{ %¢üRRg”ØÐÁ€ñâìS©HܬEBÐë4g¼-ngq^ñÿ,PO­¼á ·UZamù·µ§fÄš²æ4ÁöÌpÌÏ4êàpeˆUƒøZ»[¼Q_Zó⤋25Œ%õÿdx[æšÿc¢{B›B íÍO/ØôOgówà’(Ó×£L©ÌWA6ÆÎk ¦¹¯ã—¡¦%Ôœjòt§Iâ ›ºø{›Åúª|þ‰ìƒ5M„FÊR43a1åõŠS,¸”$mµgI§·™+º©ÄHô2ÍŠâ¨ÛÍoi¦–÷PSïýFA`NFѱlŒ`{2 þsq–õd A竦Èñ?^Á«:éÊJòÒ šŒáTnn $‘…ˇ„;†0ñÚÓ#.hu‘‡Þ»l—ÿ¿h]Ã4Óñ¼—ù,¥ðÿsטÓ@žÅL­¨ÓdÖá“ðZÖ®di6×ìÜ/ÞŠ"Áþà*r‘œcð-ùÿÝ‚/] endstream endobj 246 0 obj << /Type /Page /Contents 247 0 R /Resources 245 0 R /MediaBox [0 0 612 792] /Parent 238 0 R /Annots [ 239 0 R 249 0 R 240 0 R 250 0 R ] >> endobj 239 0 obj << /Type /Annot /Border [0 0 0] /Rect [344.47 655.106 522 666.015] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Writing plugin modules) >> >> endobj 249 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 641.955 227.839 652.864] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Writing plugin modules) >> >> endobj 240 0 obj << /Type /Annot /Border [0 0 0] /Rect [450.409 589.959 522 599.655] /Subtype /Link /A << /S /GoTo /D (moduledirectory) >> >> endobj 250 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 576.202 274.328 587.111] /Subtype /Link /A << /S /GoTo /D (moduledirectory) >> >> endobj 248 0 obj << /D [246 0 R /XYZ 90 720 null] >> endobj 245 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F60 10 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 257 0 obj << /Length 2644 /Filter /FlateDecode >> stream xÚµYKܸ¾ûW4C4€›¢$9$»Y`ƒ`7'‡Àk šnö´`µ4ÖÃãòãSÅ*JTz æÐd±T,ëñGîRø“»2ÝåZ‹Ò»ÃåMÊÔOo$öÀ°8þxÿæw?dr'SQ¦¥ÜÝŸb÷Ç݇Dw{U*­“ïN®}¬[w·×Ú$_þê¤w'×»öàî>ÞÿùÍŸîç½2¥¾¡ r¼ÖF]ic #¤6¤ÍSßÜ0¸w»V=Ë…Ýí¥2#n÷Õ¦˜½Æ‡îr©Úã@zÝ/©4­;Òtj®§áxv,}¥Š=l™ƒêÿ&™… ¬ƒ;Œu×’ôîDÚà.ž‚ûê"PÎn¯ %2Á@ ©$ ø;)gR•´]©ëäP÷‡é2ŒX åñ\óèÐUýàˆ±ëáûº}¤•ÀáÚnz<ÇØm˜ê‘F—niíiêŸÀò¤ÃÓîe"îö6“É-©, \ Y~è.xº,K•ÿ‡/wªHº‰&—¶†ùHÓgWmD»·0°i2TH}¹+t”®m^ˆ õ*ןÀ*H1ɹjN,àÌ*4uû‰»À_á}°ZDÌé&R-†'Lùl|è7^†Ñ]Д&Í8¸i Z›_é²bЖÙI@ï.U· ¶Ím–ü?C[áâ ãÙø–aôKš¥¼9Xª¾ÔMÕÑ þërë ¤ÛÞd*™rL±>p·õÑUDBÅ_Ž—™•vVŒœõÒ¡©00à(Eš&ïݫԠó\d6ßY#%Æ>„_ŒÒCàÚGl>EØ4޵kaþ|ç­¨4B™9(gµ!xÞµTcEje`®·Ä•Bæ3LJï·ðñ-‰6¹H\EÉSõè¶öV™0Y$ÿ?Ž_†ÌÓ]VæBYy#O#Ç>bÙ¨±¿ §3›‰4äœ c¹¢Ü‡Ì7¼@œåÉX}%µµÜ¢´Öx‰Zø%Ciþ²òytpŸ'_p €dÉïýFƒ0[îÑì§Y:û~DÇ|0ˆSÝãÜ‘¨ÛC3ÝŠ•!ÄmÕ»öˆ¶xBà]jo”(½¦‘E.®òÙHcÖª0j›¢r›ù¤Ó#M溶U¦ÀäÒÎeÊ뺥ˆVB•&°=×ã9(àxrà­=òBU„ogKÞ¨„*=“Ɔ<¨uJϺD÷ŒfåÊZäfÞ8xýd¡ã3KÅf—Íã@üK5b}UÆ$Xþ”ùu©°6û¶…¥ÐËѽ…·Î~žTˆœê•1KQêWÇ?B¢5Ò× ãkêïkhB€*¸vqã¹óUïHK˜ãñ·:}þò–ë[•™È ½®!ˆ<’ª,•S=œ Ú\¨”Â)è«5«@Î: ýç é¨ðö]C’êv…‘‚†PNÊüSðhÄ=µTT×»i¤ˆ,y{ÖReRŸˆ¾ ˜ÌE"°Ä!yI°´Ðtã@+K ÖòËÞ0(Ÿ)¦aeµÙæÊòáÛ hÅf`”YÃ(Ȩ#B‘îÀQ ŸˆÂß($„dÈÑÊf:)!_{ì»éiÛ× ¡äì™A©5ÈöºÙŸÜ5Íš îñÂÇ8wSÃß<hÏÒl L@‹`ÀN¹Ô7pö<ÇvϼþïgÀ^d ”Z‰#›|ðç¿“‰GÁ–UqÏ)S{­œÒ¥Èó,Öp£À®o¨y-Œ³ÚÞÊú+EÈÅÇ/*[³úQ¦\­È¬0?vüa–Tô>NK€V‰Â°Û³°w²ÚQ*mêqlp3¥’ç¾ÆÄ þx"êâ¿0ñî7­$.䑃…kE? ^™µ r9<õpAÝCõà•UØ14xìYññ•b°LãºÝÌsî꣈Ó!ˆg¤/(8r…ø%…‹Ã{KÅ”$   ðg«0mAí:~éýj»Þ˜L”AG-C¾£¨# 8Èázæ+—Âj»Ô,„È ð·c}ª]¿*d&Štþþ&º¨&L^®sóývC­”sj‰Î³!×BÅÍõ\øêô‹Ï"p ’zZü…jw¤‘Ï¥rî[ÀºÌZÑ™G>‡KFìÌ3Ž}ýÀORr Hn<óÔ÷nÎÝ@8C¿Ìpp‘ækÿùÉ÷ío¹J%cÓÐq•иöGQ-ALjeQœÎ½[ü9µ£Dô±€ÄŽýä~KD$VôóˆöƒÄÚòö^ý}¡tòãH¤zXƒK4Ù¾­!x0ÁN Úp)w×4 të娮š¸Š2(A–¹:gÏ-KÁP§aÃõÞ5ôÕÁõcU3÷ ˜7ŒM°ÓóoùЭA¸ 5I3 BRC`iËá€î¾zØz¤%ÅÅ E²èÃÄ’¡Æõ ç½sÉ?,Ì»À¹¨|ŸS ˆ¬zXÔÛìóg ÁØ]Ë£šÏâ1‘OaŒåžñ:)Ñf«ä*(@gv*‡PØu7pí#¶­ªv%쪃R>ajÒøÃºôE"aéìZ[“B×±¶58p}CÛkaqg¡ÊBò ˜Þû—œõ›#Í*ö'JD1 žÃ–)õÄè9¤Š;ì£Ý0€MØKYÄòïíö¡D^¼®)ÔZ/%ÅØÅiâø Ô OÌx£*€]®ß¼ãF$Øp}ž #eMš%¯CZ, & M†ÉægµKÕFé£ÒCÕz­WKm$JÜÁ_ðn†2F ‰Mê[9ÛbyK=ør`ãgtkCÚ¿~')!I)ùú}ð†Ml¾<¾ð.¾BÀë „ðDñ¥>©x>òü©wbp8Û^ÀU…ÄSß]ˆÊF/®Áú>Rý1û¾¦×M´U!t¹n; XrÈüþA#s*zœQCX¬ºú%ˆ ¹]¥^å 6uøòùì84£äë«,¹tŸî–:Z2ÎËRª] ¡¦¬/‡”+á—§D©CMû¼<Û*ÌÜ€ññ©4X®>|LwGX„,*vÏžõ²ÓH­w‡f÷þÍߨ¬­wÍ`[[/Í–fÞ8ÝØ¢¼„Е)½®ýÊÆ©ÏmÞѾW¡‹M@ ìÞîŠþ†»š¥{ųÿi]‡^é†ÇÈ #ý/u[ÛZìJ á±Ü„º}ÀYäÿ£{¸ÚõÆS²&æUíú á¿ʶ~² endstream endobj 256 0 obj << /Type /Page /Contents 257 0 R /Resources 255 0 R /MediaBox [0 0 612 792] /Parent 238 0 R /Annots [ 252 0 R 259 0 R 253 0 R 254 0 R ] >> endobj 252 0 obj << /Type /Annot /Border [0 0 0] /Rect [377.567 607.684 522 618.593] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Defining classes) >> >> endobj 259 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 594.533 170 605.443] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Defining classes) >> >> endobj 253 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 411.986 239.775 422.895] /Subtype /Link /A << /S /GoTo /D (groups) >> >> endobj 254 0 obj << /Type /Annot /Border [0 0 0] /Rect [214.303 277.059 403.758 287.968] /Subtype /Link /A << /S /GoTo /D (actionsequence) >> >> endobj 258 0 obj << /D [256 0 R /XYZ 90 720 null] >> endobj 260 0 obj << /D [256 0 R /XYZ 90 375.996 null] >> endobj 255 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F60 10 0 R /F31 21 0 R /F54 28 0 R /F72 4 0 R /F67 34 0 R /F112 68 0 R >> /ProcSet [ /PDF /Text ] >> endobj 264 0 obj << /Length 2094 /Filter /FlateDecode >> stream xÚ­ˎܸñ>_! ‡¨7-’"%˜ƒ³Hïaƒ¬ç¶»@ä{Z°^+©=6O«¨‘z4Y#‘Åb½_l%ð'£"‰2­E‘æÑ©½KúùNòêÇÆ_îÞþÍÈH&¢H =œ×$ªè—ø‡K9Ìn<µÖqúîpLSÿp.]wPy<ÓÁèÎntÝÉŽÊäEëâðÛÃw}Xx¥þ@8Äx!”**Da•Eé¤ÌEeR‹,Ó$௉Ô×ï 1©R@ɵ6i:0­zݧˆj)Dþ>½e,‘ñmVSMØG „-»âáâ&‡ `âSß¶`ʸì2®&Úx¼v|ºXwOõ|¡Õ|q„Ù•­«·)§ÉM,Eº–BY)RP"!ö×®r p t 0Ý“;MEž›pA@ö‚¯.åL¼¼È®ì¦ N8(O3":êÄ Ud »Òpð4å'Èõö-H™J½µß S — d xú+b¤ƒç\ÅÝ0öcÙÒæ©nºµøÁ7©€ Oˆ{Bk‡ÀAÀÓ¥>!× mû®ùny2'”øµØXÅ–*@§¿ŠJ æÕÅÕuòIå±vª‘Ù<µrgÐú~·Šh¡òÅ{ý@15QÂ$¬…|0£PÈNfÜ<¡%(9'†ù°ñ²öô\PÝ@ël%[d©H@ƒMºÒR£[ ðÇx¦eëÜŒö6 ©¶,»ŠAcí½aHM^È/èÇ¡<9BZüi´éË 8z3{òK€Ú¹ º „®}Ûz y­U§Ú}A¾TpR?m¶â6‡¢ÁÓ‚0À ˆózÚFu)ûPñxïà]“è5ó>•‘n\Yñµ~ËDoºÆ¾JTæ!ÔÛlRѺ>Ó—êã’¨|8Ñw(Çå »››Cã]¦%X úÃí1.}xàj‚¾E> ôûî .²2èä6ê6«~ÅÏ‹˜Ô6¸íŽñÁC²¸‡ÑÁÿ7˜7é‡øÐ½‹kB^Ñx…څͪù$G9ÄÑΜ -Lgf™Úúñ‚.ÏÐr] ÿN åPhÂÏþpºÐ™È³eºXº8F} *¡% æ eÖƒ—`ª(5rôPšâªî„ÂOûŽácRÇf¾ÛS0F×Ó÷RŽLeîw˜¬¦+Кäß(¢¦ÀQ“~=]䩟¡Ò$þû‚æETIìu‚½ûZ¶CÇOÏäB£ñ›ÎQ¬$¥,VRJŠ$ø,ƒ¶!ëËëÄx~.A"—+ç½ð2f=®É3g+ZFðp±6õƒ&Nä›ñáÔwóØ7ïh ƒcU„‚Rß9øUûSÁ’kûš s<×›Þ…PxÃ)½#Œæb³½ÿvn‡·³ “FÛWîÞ¦)?l¼î÷çú+L2(-Œ¶[&§~øF 6§kç¾'’°º¿aÊ=5h½7²%´'laRgÂÀU ê  ¼5º¶çµÀBáÆ5ÅO‰j½ÁG¸wtÇt–ÕsÁ;Ü#Uˆ \`Ê7n"|Õ@Ïd‚õL(ÓçzàkJ}hf!4wÊ¿ÇËmü¹óJ<áõÜàœp¡!ÎxŠê¯3’Hù2¸ãò_»ƒŒ)à™,—r÷ºµÓÆã€÷ç³]rxá;nàVï9“þ´9÷MÃÒ£A ³hU³:3•¤ž M9;Áñ]Ber“?»ê sZô ¬â÷ ²qÝDnœý´ g禯õCV¶²æÛ¥óç<ɺ¶ÄB‹«Ç_tq?õôå€3O6t¯ÚwrGæFp½Ž*_xn†BD𥎠­½éÆå=Ø…„ “¨»M1Ó¬ -Ìw¾‰ìêM„Ö0¤ýìXs¯ö?Î{±”Ðo:%Z?õc µ_ >ø×?€4ýK¶ëXÇý¸aÈH¾bÃ÷˧c…•–^ kt5l°=Ú"Œl_<¦+þ¼°ã2ê>ùê +sê>9ŽhsùÙ—?ìÏC‹dïùbÔ׸]?“»RÝ_G”ä'6LVܱrÿË­¨™åÏG 7XjÄ裞âOû[f8ò]õLãe NX~l¨ê©(XXñõVˆ¿ûéN˜lû·T~¾Sxѱ©Ü4ÀdÛXÞCú„î"ðZçÑ ¯ =ìåÅõOM¹½Œ?¸ýl6·÷ endstream endobj 263 0 obj << /Type /Page /Contents 264 0 R /Resources 262 0 R /MediaBox [0 0 612 792] /Parent 238 0 R >> endobj 265 0 obj << /D [263 0 R /XYZ 90 720 null] >> endobj 266 0 obj << /D [263 0 R /XYZ 90 588.69 null] >> endobj 267 0 obj << /D [263 0 R /XYZ 90 212.456 null] >> endobj 262 0 obj << /Font << /F51 5 0 R /F112 68 0 R /F52 20 0 R /F54 28 0 R /F72 4 0 R /F67 34 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 270 0 obj << /Length 1853 /Filter /FlateDecode >> stream xÚXKÛ8¾çWø¶ò¢­EQ9ä±dÅ  Ìa2˜¡%Ú&"K^ŠêNÿû­bÝV¢L>,¾ª>ÖWU²Ødð›&ÛTR¦MQoÚ󫌥Ÿ_ îí`ÁîfÅ»‡W÷?)±YÚdØ<nxè6¿%E¶ÝåM.eòþ`†£Ìv'e‘<æØÊÄ™ƒqfhÍö÷‡¿ú×Ãõ.•ç?PW|£›:mʲ@e„¨ÓzSV2-«‚ôiÎ\¶°W%o¨ù”©Œzû~¼ŠêsÿS•o„L3°ÏÛåxÞN)Èɼl¯`W™'o·;‘Ìõv8Òî%4€(@YÖäã¨óÄŸìD½Ç­*í¬Þ÷†$qf2žܺÙÄíf ^û0ŽÆ¡›[Ϙ/Þ “}Üæu tT5ŒFÖÆÆºõv¶"™–7k4-Ø’¥E)È–N{½×ž\Ô‰¨Õ¨ó„׎î3:ëLëG÷¼­e’nwEÝ$¿’0ëæÞLÔÕŽ÷ëË¥·¦»ƒ‘B‹A+ƒ`[Góøny•´UŽ›‡Ž:ðÚx{oÛgnBóVl¡[á%@ËÑuQU¢ûi$9µè¡=I¬'Ix.ó•Ódé%AäyÓdX`¾Âý3IŸN¶E­N|óLÛ*BNó± ëìé@(*Q$ý ²'(LÓÓ4ŸÃn ëbz$è,U„%âÆ`§fé>Øhzhž^“Ã/ØGdÉ‹4W “o¼û°xÓ¤…(`’瑜v¸Ì~úã1ê±ÊS‘æ©X2õëG|{uî›iVˆ¹ËešWДÀNVõ!°Reâ+V¢DZ©, ` $€ˆ‚c?îuOÂÎôÜ{샇š“F¸í8;> ŸwžÑ¡Ãì3 `ZPfÇu¶C² øêø}ÿï '•ùÂJ>;hB±¯#Lo—û8ø*:pr˜vxïì~öfº#?÷sÓÁ?™@4„*]  |ØÂ+B ­oc¨?˜O™(ó]·’MšgrÅ­ÀJ‘‹¥_æËÓóÔÇîõ‹ó)^yד…ºêv÷Æ·÷tLÚþóëLñ•KÉ*•M¾ô©ÿb®sr ލŠ‚¶ŽF ( ƒ‹ h| q7Ò†ŸÏà@wkÏ*ÍD}}·ëVÔ-P§Œk-ߣé–ÞNž”$еéY‡ x„quÖÌ᤼f'cd)Øäu–<Ù¾§^8Œ‚EØ™ ,ß¡@&wXCd‰=LÓÚA‡p†Ý¨öQ{lÛñbã ãâ#"¾EH\çK»sHß›ð„oUÊ—åtÕŠƒ ± Ñén8ºê¡ j¸«7SA1÷ÝÁÁ•ÑÈŽ4 Nâ?×thdZר¶ ø8V£¡HK©âŽÐÙÁg ]Ž˜P«´©Ê¥ƒÄ¤«ô!Ûóz´ÌVâdCqò´{þe+ ]÷þõÝ\§UÁ±wÞìZvŸ„,²9еVhb™‚ëÝ&N)›$x+„•> q‰ EÁóa •EÚAÎ ¤€©y¢Z¤!~Á¢‹fÁä1¼NË#æÁüoƤŒÂjä@êÔŸàjJ\ýÒ@†Â—-©Iã<Ë…äÅG§Ï´¬ ÁŒþÛ./Ð !¤¼LìÐ=l¸b`V¨n,ÐèJÑ×´í´!þ{_cpùæk¬ÀD õ }{…©‘ZMÍ7Á…á5]çÌÄ': X¿XtzùNJF`<1¼g¡òhÊi%QYQjœýq ŠbPb0á[oǬ ½þ<ÐÌÀ)1ïa¬GÆP£]á˜Ó8y>šAÃ|Ðã|·ðxÄ –ŒÔ‚>ÀÑÖÓ4úôšÿ9 À”˜àJf9´ššÏ}r 4\@† L‰äíÍ\EN‚U{ОfB®C]£kþÀAX¾|o'8–ôØâC†qÄ™/ -~3¹¿b×þ%ÞÅÁ8]ËX*ÖWB«LFû9–ÝQ8Œ1»P6Æ@b{þ37EÎŽ=Ë¡æ?@ùª¢i½|Z}ËQA}‚pÄü ßš^þø>-ñ/ŸÿöÇÔ endstream endobj 269 0 obj << /Type /Page /Contents 270 0 R /Resources 268 0 R /MediaBox [0 0 612 792] /Parent 238 0 R >> endobj 271 0 obj << /D [269 0 R /XYZ 90 720 null] >> endobj 56 0 obj << /D [269 0 R /XYZ 90 653.898 null] >> endobj 272 0 obj << /D [269 0 R /XYZ 90 485.45 null] >> endobj 273 0 obj << /D [269 0 R /XYZ 90 300.594 null] >> endobj 274 0 obj << /D [269 0 R /XYZ 90 204.803 null] >> endobj 105 0 obj << /D [269 0 R /XYZ 90 106.97 null] >> endobj 268 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 278 0 obj << /Length 1693 /Filter /FlateDecode >> stream xÚ­XKoÜ6¾ûWì-ZÀK‹õ Cš¦@{( ØAi€ÐwW° ’²ëýïµÖn6HP>,ÅÎ{>-W1üÉU¯Š4•*Wu‡Ý‡+V`Ø,8~¸»ºù)“+‹*®äên»q׬>Fïöúà]oÒ4ÔëõF©,z·Õ;3¬“2òL°fk¬j³Þ$YY•‘’ëOw¿\½¿;êÎ’äÆ!ÇÖ¥rUŠ*Ï'e)ÊU^*!S5Ûgê7õ?j¯ïµ²$‹ÞðÏqóêæQÛ›zk†];X4÷G²ô< ™Š2ËW›¤²ÌY×Ï[p¯‘ß·W1—ª3ƒî Sx_FAÊ`škø.ÓhÖÌÔ§¶ëøüäæƒ>ˆ™àüh©7ÎA¸ƒàvgœZнVII@‡}>øqgõaßÖè8¡ –Šœ‘à9QcÚ h뤈0pŽB@Y·üË^9üPÑv Éw¦ž,Ø ÇŸyç0ÙúθkÞ»5æ<óiœ‹RBÞT"ŠªÀÔB¬‰¸Èþ̵Y°]¨ÏsaäÓ­©};¡H…¬ØôÁ‘OÁ¶…WUvn¤J3‘B•-´_(Ñ™ëFž ##¯C%KÎ\äy²95¡–ß\ªÈLŠ rX'8-K‘C‹ld!Š$”é•'%ô0‡EEO˜89XSko&¶k¾DH‘$‚M(ÀØTÄ`7E¨§$ª Ú Ü± ´Sž`7®7j,M¨¸~›ìਓFN°7I%ªò´ùÀåFO¾¿g‹e0’*×YiÛêûÎðNc¶zÏ;X¨ûà÷ó•“®7E½Âîo¨÷äŒ_òf‘·“Áúб˰ˆ<¡ÑaÕQ_GãjχõLƒx¿7L±f×:^Ìæžü²¯ÙÏÓ(@pÑ¿ô€™NÔ¢ýËèiO{§ìñ¼gNçÉzÜ4‚-%)'ŠØ2^#ÿvã°›%Òa‡ea‚üµž T¥ ^ýˆæ<"$¿èb| Z[;ö\¹¬êtá_:û‡‹eµÛ¡v¼?·DëÜdnŸc—ͳ¸¦Ô¾îV HÄÌ}âÒŒ °l BÑýäÑO°Dm}[O¶áLÛ›pf‚ªzœº ² ÇÜØCŠÈüìÚ4€øÝF¯/ôر°YC78o¡éw­á+%Џh¢$„úon2ô†dG¿ŽOo‡æÜ}ͼò˜²X¨<Èyß9ó;óȬÈ"Up1Ó?\ÏK3‚’z¼»¯š¹0‚y*¡¤:•ñß@å óÂQéFå  \b^Š˜—’–ï>À}˜J¬MnÕï…½>ò¿Ÿ*°¯²ìøp‡€PO!îQ¯$Ô+˘šI„zKÞ€z™ÌNQyõKO~ì5T<àÜ3oyh@ƒÐ½ù*®+x‚áR:kþáî${’¨ ´Ö3/Ýk$Ì@P‚‹¦uèp¡ŽQ+`ìÒƒ›uôŽB¸s‚7´A¸€d÷ä;*–e#^…ˆV5Ñ«Hßó­p‚ßè'ÞWä |?ᤇñáƒ{ý£¼ÃTô'Q•V WxÖƒ }г`ãs„/ÖÑô@šÚó[ÎZ³¹äçòþJeΓT ã7lÔ£…ÄóÇBÝ·å<Äí8Ä`­á52Òäã‰d÷ÔzN7«åÖ!õ[~ÄÀ–æ÷ æõ¼ž067æúÄ‘póŒÕ1\°ÎkÈ NôUE÷-n¶1ƒ' Ò(>\߸á÷`pXÏ×Vn˜n^'Jvb)x9–ðŽÞéÙfŠ!ðÍDï0z17Pïà¸R<ñ«4ê¡ùª„MÍ?gó>péÎX ÞvÐz›Sµ[*ºàUAˆüÏH‚l±T|Ïàë¸yy@ª4´’¹@`LÖúñ„”Ö]òÊMp"¯Û ÷:L¶á…Zëð> endobj 275 0 obj << /Type /Annot /Border [0 0 0] /Rect [306.818 640.07 435.364 650.979] /Subtype /Link /A << /S /GoTo /D (files) >> >> endobj 279 0 obj << /D [277 0 R /XYZ 90 720 null] >> endobj 280 0 obj << /D [277 0 R /XYZ 90 612.397 null] >> endobj 281 0 obj << /D [277 0 R /XYZ 90 314.881 null] >> endobj 282 0 obj << /D [277 0 R /XYZ 90 150.192 null] >> endobj 276 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 288 0 obj << /Length 2328 /Filter /FlateDecode >> stream xÚ­XK“Û6¾Ï¯Ð‘JYâAtUq×&ådxö°åø@Q†;|($åYýût£›©áÄS»©©`£»Ñ¯«þä* W±Ö"5É*¯nB^}¸‘<ÚÁfBñæîæö]$W2i˜ÊÕÝ~Êân·úµÞ¨Ti|¿wõ¡¨Ýz£µ ¾(üÕAëö®uuîÖŸï~ºùán”)õeâ‰6±ZI-BP‡µ±‰RÖF€ª2Zo"«‚ïï‹r÷~½‘A±ý°Ö*Èú{ÔâúHpf «5ñøèúŽtÏø(ëÈYyr´ºoZZÿv8Ó£Ò2Q"íÊZ+b¡ÚŸ>‡«|üi ¯=eµÒBÅFåêãͯK––I,B©<«(”¤ÜûßüöÝoëDÿ~*\éXÄpe¤H¤ž ÿ€r¿['&¸û™ ¨É&ùZ%š›¦Ç¶¨H‚Üuë^³ÑÕTÀF‚ÍUbW=B*KräQÛ#º  ¾¥ŸßÃ(¤Ñí©koË&ÏÊ[ |ÍÃêÜýáFr¹äêLE”è¹Ð_š\k´ @¨„(&~5BÿGAÖÙ¶t--¹^éTh°± aóÿY_ ,•2éK\ŸBèÿMÂÓDÈkás×£y 6Ewô®vy‘•b½‰#ÜÝÁ!mÖži9—é³ jçvn‡§„$vé-#ޏâÈÈ$hO5Rެ˜" S»#‚Œ!c Dðã`‡65{þÈ…j†aðÏ=PõžK £W@d `br?ìÎÀNØÓº×–»>k{PÞ/îÛ¦bmÃR1dï J ÆGgCF:‰/Œtbƒ-ê¦qQ=2*ê‚B­£-ÃÖºa§¢Ï¶p†’ F»ã„ìŽÉd=3ÌjÚÝ»²Ì›ª‚æüX”%öYQÙcÑÏÏÁNêú6«(YÙÀµmÓ"ÈBP C£9õô­nx°õ>tE} 9fÐḵl²­t÷YëxÜ`zGÁ\ÞwÝ¥­û úA@ ‡#6¡¢¤- ':un* ËÑ#:ñL Móš¶EH8`aáT B yÅIJÉiÁ²\°šãZËàü¾¨º¿ªT\í(Ï4ì,‹®§­h<ÂŽV¼Iáwç~¥ñõfýÊf›•s&|DX©³Ê±_ôàlÙ»¶æUŠoÈ8fÚº¹L ^Ì›c1(ÕfÎK¶ïï3.*%˜íî÷€»s…Sª²Ü/ÏI>¢àއâìþ›UÇÒ‘µ\%"µÖx|KDâEª„3ìÎ6_.9߈¼©÷ÅákµE‹$‚‚&#h¢ÁEˆ"qt`Jí³¼(‹ž# Wr<18/xǬè74¸ˆ—1²øYQïŠ/Å46%Ûù/ ³‹ Ë9u>j‘an¡5a3~ð^N9û‹>Ô à¾}Uv‡ªëqš|rÝv0Q€/bø­t,02¸ó6Îå…R"­a<ú ¹Z´§–"–É$x §d²Á¨'^GBÛ1ü«çA`õ¨Ï"'+”³8¿wùCwª–xH¾ûé^õ6ϵ-jìK—Îo@{=ÐyÓCÙ±è 07)Ò±aPzKöAh¹;Ý3Ý Ù媕¹Ê ‰ÆðkDhô4a’' óááðó¡}A†\V(.) õüÅŒ}ö3ŠÔ1 ýˆ‰‡jY $K/>ê¡‚mOýä-gÉýJÄIrÁÛü ê"™T˜hÔ¢è]Õ-úKE)Üè±e°P fîbû-;«=VÿC×ùƃoLæÅk!^ù´NÆ;Š=jÐ }‰ù–¦ñ¶8l«\Vó=ÇŽ÷P=Þµ4úš¯¥þÂï[Ô/êÀbà’ ã–(;WB«æv¯Š·¼dܧí´á…ššG5ý>'¡…T/qf ÀÐ M$2÷7S×ÓìÒšïσ: $|ä]Þ1À’<+2^ÂÁ¾÷ è×›”ŒY‘&É ¦Ù7êrSÀ Ùű,cò-Ž™¶8p5¬±Èð5@CY£_5¤£š:Î)å6jV^ÑÒB‡oÀ¨Æâk(v<ñ3þ@µ™-tÏ×Ìæ>jÀ©HÑOW!‡Í¾7¦Vƒ¬Ih9(u µ~rKÑøš@ù¢GÕåÀ@µ™-ÝR®˜1Ä/A¯a†O{•t€Þ:Š_~›ú_–Ýö]QºîoÛ?î1n¢¡ÜÇfÚ¬à‡a¹Cö®§Ißð®ö„N‡&x|J£„HºóÊÑ*]H:&_Âüt‡7ú˜ÆÁ½eù²& Á•Œ˜ÖþîŒ 3x@hfo÷õ˜¸zêytPìÄ‹ÞØÚhéÁÌËHÆ™CµëÁ˜e/~<6Mù¶ÀG£†®QËÜ_²ö¶CÚ[|LôÿúlÛÍ™c¨þ tfkf endstream endobj 287 0 obj << /Type /Page /Contents 288 0 R /Resources 286 0 R /MediaBox [0 0 612 792] /Parent 283 0 R /Annots [ 284 0 R 285 0 R 294 0 R ] >> endobj 284 0 obj << /Type /Annot /Border [0 0 0] /Rect [142.572 456.142 279.065 467.051] /Subtype /Link /A << /S /GoTo /D (links) >> >> endobj 285 0 obj << /Type /Annot /Border [0 0 0] /Rect [410.461 178.199 522 189.108] /Subtype /Link /A << /S /GoTo /D (packages) >> >> endobj 294 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 165.655 131.818 174.806] /Subtype /Link /A << /S /GoTo /D (packages) >> >> endobj 289 0 obj << /D [287 0 R /XYZ 90 720 null] >> endobj 290 0 obj << /D [287 0 R /XYZ 90 720 null] >> endobj 291 0 obj << /D [287 0 R /XYZ 90 544.888 null] >> endobj 292 0 obj << /D [287 0 R /XYZ 90 368.803 null] >> endobj 293 0 obj << /D [287 0 R /XYZ 90 282.351 null] >> endobj 295 0 obj << /D [287 0 R /XYZ 90 157.017 null] >> endobj 286 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R /F67 34 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 300 0 obj << /Length 2009 /Filter /FlateDecode >> stream xÚÝXÝÜ4ï_±ª@d%6'Î/Z•ŠÁò€(¾¬w7º|l¤Çò×3ãg“»=xtkÏŒíùúÇ«þÄ*Viù¹ÌVEý,`êí3Á£ l&ßìžm_Æb%?r±Ú¦[ìö«ß¼'uîµYo¢(òäWë”±÷â ŽºY‡™×Ãèƒ6º)ôzÆYžy2Zÿ¾ûþÙw»ñì8 ?¡J|B;HàÊU’I_D’TÜÊÔHBÏýª†~AImTUþ©ú²µ4áµâ}«+Ýë·móK§Íª¬ÜÒ= ju‹j·uO¿Fï‡f¯Èx½‰£`ä¹ã­©UU]Ы •7"òELë?t1ôzOÎS¸,’ž¢éYöªUýIá=ØÜ—ûËs^X Y>³}™†+8!O¡£ ÎaìG1Þ ü0u¯–¯7àŒæÝ¸èeYv›¹¿a‘ú‰óôkTH P¹^GÐWÕšr¦Ö Aîuºgá–Í ¿Ä¡ôŠƒnŽe£Iò5Á «Š$÷VA¿„¬4ïicÄÂQûhdX»SÛñŽ (ÄÔ=ŸÞ´½ GÀdQÑ£»3¤m»s@¬Æè_rÿmÓâAw Q‡Žà ½tV5jo ÞÍÀ¡«Ëãićônà€ÔÓ4áÝ\øopz™¥ÀìDiOä(Gb•ùy’HŒN˜ù™Í¯,çI= +à*ö¾¦Ÿ÷AУ1Ò„sM¡Ù5?ŸÛ¶ú¶4ºè[S>ºÑö£2Ûe·…iû¯W7Ý|óû‰…AÈâĦWœÍ ($Øç€„’X€Ò/äkðD,%)bÉ–l$`9e ߦ%®` ¥ÉHÀ¸+-‚@tDPk®méKIFXböKÀ¼;•N$³ç“ÑI¡,í0ËcÄ¡KrD˜®ZT÷8…Ùß%='ÃÞÇkGŽù!­B(ž¢^$ÚÕ°ç3«Öj ¹%AöÀÓKføXÉü'QþTÌÿfÁ|BŒ#Šñ¾'5ÓpS B1ÝàaÀ9ÏÒj¢]ž¤ÓåIèçyg?Xhñ±p`’ûy6®x¼†Æ™æÙR•@Ɖ§L©n*LLŽF³€í+,ÝêDhE40ĸ¬! ía3ÄéÊ^™x¿®³yV°F÷]ORîâ•L=A‹a—"uå P©G»¤ îÙ˜;Aäu—®×5)YR›,0%ø×4 YÙw4˜š‡ó»“nhä쳃vZƈ7,èD°.A)jÆ`€&šŽOîËý"#¬Rz©HN•ãØ+ðn !Bì ¢‚?ö4®ÙŠÅÇ€Äyh‘ß 7þ0`W~ÞÓRTpl{tc«/n˜Eòg˜¶¤&!2o‡ =Yó?a‹ ²™–y”ƒÛ# 9(v¡1'^ÆìB8OŠÐajN[}ÔK0tâˆ19áÛ¹ÜðX§”ªºv®(\Ÿ«²({×µ‡qäÇA4·Û¹SBú·`„¡¡­hªohäÉú¦zˆÜ7›Àˆ‘„ ×úÉâªÚÓtXH‚Á¨>Œ1#ðW+S]¦¤Ô;ÛrÙv]I’[5¢h©–7xèq0ÜVá:º>h­uÐÜ1½›÷}[²þgÓÂÑu‡OcÏ]º(íKˆT:Œ*¥ì‡äÚ<Ør?1\ÔÕµ;“¥à4 y I¾¡wâ_ À{ÙŸˆ[—††‡ôþ‡ZK´›àõëºøzDá®´Ï\¤!¾gw‚¥¤øK›e€³pdÞ² š›àBñuv{ZwÑŽ5'.uöÜßxùµe˜tÔc«DXöaìHwïºËy|€ºt´;),yO½d%7R?¾YGÂ{õºézHŒm]cŸþ7Tįm£™²22 lØŽÑ–ÀhNÉ$ü-ébŸ·‚X]zÜNõÄoôý壛‘Í{9x;XüÛ-(qpŒšWK±½§€{40~êûîÇ7÷]·ü*{¾:³½)›íùöX Q?ïžÿ‹gÙ7ØkÅx«ÔPõعáýAÍx|¿Ï@ qBN6 @kËËj­zÄ‚}#z†ñA…TB±¶·Æ×cp‰[U {þí»ŠÉ p`ïID‘gs%CM\ j ‘Ø‘KÞÄø$‰áÚxÛö¼YZlåÂ8÷¥ÌÜõô|É뱟†©“ø¢£ý”ÁÓÛbóöV(Šà?ôfð7vŸˆb 1Óñ=–ľHã¹;Œ>Wªpý4;vú¡éúp{ð j1‰ëÒèÞ§W‰˜«„¹ ¶šTDÐô ˆ/vå9¥„(üh7~] N:F£m¶h""ÀcÉ(U1ZвL†âÓ-z ¡† °5óϾsÀ³ît€rRÌ"‡Ã £XÀë|¤‹žf WpRQå‡Q{F´tK/🟈ъÍfo.ã¼~/IVÉø&iÍÒ~6ÇÆžm³¸¾„ _Û5eÞk¶©×Uʼnå°znö¹nv§¹‹«mª‹û¦Ã/S÷ õŽ* f#¿,'}—û’à@0ÞwP`j[¬‘¿Zàç#ß}Úþ ™‰ endstream endobj 299 0 obj << /Type /Page /Contents 300 0 R /Resources 298 0 R /MediaBox [0 0 612 792] /Parent 283 0 R >> endobj 301 0 obj << /D [299 0 R /XYZ 90 720 null] >> endobj 302 0 obj << /D [299 0 R /XYZ 90 658.452 null] >> endobj 303 0 obj << /D [299 0 R /XYZ 90 548.912 null] >> endobj 304 0 obj << /D [299 0 R /XYZ 90 492.773 null] >> endobj 305 0 obj << /D [299 0 R /XYZ 90 436.634 null] >> endobj 306 0 obj << /D [299 0 R /XYZ 90 288.439 null] >> endobj 307 0 obj << /D [299 0 R /XYZ 90 173.52 null] >> endobj 298 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F52 20 0 R /F67 34 0 R /F53 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 311 0 obj << /Length 2241 /Filter /FlateDecode >> stream xÚ­X_Û8ï§X¬sh\Kòß÷ÐöZàîá¶ó¶]`5Ž21ƱÙ™6û°ŸýH‘òÈ™L§w¸ 0’)‰")’?Jb•ÁO¬šlU)•6y½j¯2¦Þ¿ÜÛÀ„M4ãýÍ«7Ÿ ±YÚdXÝìb7ÛÕoIž¯7²‘J%vf¸ë³Þ(•'[•8³3Î ­Yÿ~ó¯Woæ½ )_g<‘¦¬VuÚ”eŽÂ©Ò"«Ve¥Ò²ÊI¢¶×ãhFÜïÍ'%¢éȪn€¹Ÿ÷ö-NYmdžU-( ;ú±¸ó¯§a "Éß©ù’õì0SíRÉ•Pi6Âm6¹N ì'…`;¥`DYÂÊR&`#‘l»é¶ôZ$îŒß_2‘÷ ·Hº? ñ-dlú¼ñ­(R) bû¸¼.îü©ëÍg\¹ éBjÏ ñªJóB[ŒÏl)›´nf‹=*¼ô‰hêTeQ´¢hhvä"O¾v}O=ðˆÓè©E2Y¢Pƒzš2MúºïÚµ¬“= u#µ½vwÆ1Ÿ½ˆ:íyÇuQ&º?1»»¦Ÿ‚cï >wÞ5#£,ÕU| B¥¢àóípÿºHnQÒóçGš®7e–%7{/3ŒR[’Þð}tæ˜ÿO4x„ˆª;zøÃ­·Œè¶í¶<—9îœ=Ð °zÛžœCîüîv74ukvúÔOôæ)‚yuÔ™PVŒ‹Œõ#õÈš®Ó$K^’*y‘ˆŒþèëRý¼Î’îhìŒcöDË·vøe"zßÝ{Ð×DÆ‚);£§“3¯ñ«=û3ÍÍDS¦=¨ÊÅž³‰½D›Gæš²9„]¬(¤w+Ê]ÞЧÃNãÖŸ‰w7HnÞX0Áï­ºÍnQgØÁëŒ3ö!FÒÝëä?³¯‰ÔFùS…x)ÝÝ`«‰ŸSz-é€R¦Ug›j™mþç³ûïRK†Rý¿2K™§™,)³”4™ÂI6ŠØ»;9¦l(?à $™-õÈ)©ÿheü2³'øÏ©;ð¦#dÆçÞÚƒ‰2˜ÖŒ£ž—Xæ´¥% } ²6ºƒÉç0¢ôˆ°-_òØÅ³ՎǾ3ÞU ¾ïþг&P&óm¢2+ôþ¨Ç×45kÌÌ*„:tgü#ÕÑ€uK®ˆ¢þ„¹ØÁÙ<÷… ^3\‚ÑÂà+e ¾0èåŠÊŠ‚ÿ8ׄÃqËÃqZƒg5£í>Øa÷ÃH KãeOÁØ÷&‡ª.ï'—õ«H3U-sÕ¿­Ãl~F¼*"säPrlɇApp°ѧnËóOGj-&Zâq]HL#Ñ10q¢?ìüqµ8¨D*ç`~c¦öóЧí£Á–×R‘–ª+~!Þ3WP?Þ„Âv£ª*­E³h¯Ð[¡SW`®|QNÕE‘NO<î‘Ú/Båvø #N4>âêsÀ“i …‚¨“Ÿ^#hKð5‘žpÐîž7Bo~ï˜?”@Ã/~wx Ä J½ëÌ}ðð‹ËŠ1z„”KæÞ’q·'ÇG¡.P”Nи‰ª'ðàôŽAƒ’0ž¿…Bðñt Uí½cúB(‡öc¬úõ(¶»ÝK Ì÷ÒT¶t„ÓÖ|°GŸs~ØTµd728 ÔØ£»\* :éÀ°¡‰x×C]Ù/™*¤`Ò }%íIŽÚ£ž&ãF1ºíû2Ã3õgíÝç2ïD  ‹5ñÒZP?2ÜÝBñÎÌß×>­ëp­ƒ£ÿ¦ÚÌõ$|oÚ™ÖÕãa’Ïϼýí/n¦¶õòÝ -jpµÌÐ\34ɨÜÃÄ¡ÛðLУ3W^OÈw­/»ò&6XøŒÄh;<=2^J ¨õüÚ_@xy|è¶':Ôöî©·´%ÑN#Et1óí¯ÞþTU.Þ]Ȇ×Á RûåcKœ¬?›'O‹"W) ­DQ¥ÌØ`ˆ£çÅ0kM»òàyÉÌ ðÙ´@ØIrœß‚«ýÎwú£o ¥¸”RVEšE,å•GÐ0ë)/™y)S®J«,-„¸Äû %+szCÑ}ˆ• b”<]Aâ}K“OÃÖWd¥¿ô"e|êZ@õ/²Ì?¼d”ó“Hdzø~‹Ìxro½'E¸LLD!žÏÞ@¨€$¾çÝ0NšŸ¦/^–UJ‘S —Mô°|%)øäüòYn/ùÅ«òwSÅSàH•¨_Î’×’R–MùòS UYQ.Ýà+]üý82ÙG'¦é]*JÏø‰ë5;¼P,Ö/2¡)^›K0³ ¢G¾ðîÒ?eÏž-‡Ö´E£ endstream endobj 310 0 obj << /Type /Page /Contents 311 0 R /Resources 309 0 R /MediaBox [0 0 612 792] /Parent 283 0 R /Annots [ 308 0 R ] >> endobj 308 0 obj << /Type /Annot /Border [0 0 0] /Rect [143.333 154.536 275.455 165.445] /Subtype /Link /A << /S /GoTo /D (copy) >> >> endobj 312 0 obj << /D [310 0 R /XYZ 90 720 null] >> endobj 313 0 obj << /D [310 0 R /XYZ 90 634.485 null] >> endobj 314 0 obj << /D [310 0 R /XYZ 90 539.378 null] >> endobj 315 0 obj << /D [310 0 R /XYZ 90 378.229 null] >> endobj 316 0 obj << /D [310 0 R /XYZ 90 311.544 null] >> endobj 317 0 obj << /D [310 0 R /XYZ 90 243.662 null] >> endobj 309 0 obj << /Font << /F51 5 0 R /F67 34 0 R /F31 21 0 R /F72 4 0 R /F52 20 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 322 0 obj << /Length 2352 /Filter /FlateDecode >> stream xÚ­YKoÛH¾çWK-¢ûÅG€’lÌ`1ƒ}˳´Ø²K¤BRq|Ùß¾U]ÕtSf’ÁbàƒšÅfu=¿ªjËU rU¦«\kQšbµ=>K™z÷Lòj6ÑŽ·×Ï^~°r%SQ¦¥\]ïb×õêcòn_Fׯ7ZëļZoŒ±É»]uëÚµ*’‘^ônçz×nÝz£lQ‰±ëO׿<{=m•úp¸ã‰t¹ZI-R¥Ë #¤6$,S¡åzc3•¼_odòu{8×îßM{‡\jêË\dZÓç×ûfŒLÍ€ª˜4 ”óàjZýÖîTšÖÑ¾Šˆ·‡î¦:̙ȤÛѦ¶::æ×õô{ªF°g;Іû}³]«<Ù3ÓÞÍϼƒ éH9k×wGÔÑ+¥…M½RнioÉ1݉ôÕØtí Ð&ù°.4 [Ü×êx:82—–«B”YfÐZà ›æÀÝ ›ó÷‘}Áa6yM?¤6¥Õ?ÿË¿ÏéwÛ¡N¼G.9e# a3íU<ãu.“,H«ÝZ&Õ}ܬÑÖ#ÚíßɶjiSd¯"p3 OܶAç‘í€y£Lp„öôÔ´À¹n¾4õ™|ZzkÒªcNdJ¢²4,GøtÏV´*ÖOçšüäUc/.ZB—RÀ’üIÛ»®ºrî2­¤Ñ^­²4:Ç´šeVØ´yܵú¬üéWnûx¼÷àÊ$Ñ,çD?ÐJJu) *¤Py,àBê‡Mßð‚•Pø€¬’*g1ôk7¢X™IÆ=ÆÎHÕ]›iŒ™ŠõOS †$¯ió¹­=øÁ›Š(ÃÓ€êöP óïá0>øËÚfp`ûºöðÀÌxó¡óñQÆ= ª™'©gÍ<Ï=PéHbAà Ém8¹ Dô0VˆË>Ú²<În°”4³ìžN¼e`‹ üê eEn,ø¤ä_€‡§"äÀ;|—€¨Y9%зq$—"µÙ,îÑ¿ÝùPÏEÖ©BüÒÁþ!Fd|Äï+65ûOÏë?r,·µ³ˆ5 Œ¬‚ä‘}/";©š\ð¬ÿf^ 7*5u ‘ê¸ ª¸ žšÞ½Ùa ÿNAäzú3Ô-U€Uo5z „¬ZLr|÷¼#X0™»]x àêTõßp4EªÀlOöä\ßP:1‹Ö/,óÒá,Œ i ¯úa¤g·¾Ã$p> \wô pkÓ/UËm×"ëÛóë`øaÛ7§‘ eJ½¸8yÉòQAzf'Ý7xùq1õ °Žì†¾Yˆ÷¾|6?S\—KuÀd¹0Ö¬ =Òß(a×&Úæ6K㨸dæµÞ/Å”£CÜ"Xô¤d¿à*ÒLNA¾˜ÂFå"·Å¬~¼:UÇ#Z =R[Óbð¾=#Þr7à+’´PôïoÝ’Ò”lÄø{´š)5«~%´³…] …½Ðß*¼km[ª̸ÂWù“é<&SŠÉü1&Ógir¬¾6G Øó Ðu6G~Õ´„ñ*eÉâœ_ø¯FêmfrE•Ò¨d»símCý2C#kê±–â¿»G ©7SÜújè¼¾à;‡ æ:yƒýßè]ÞóFîÞu9ap vMëX •ÐàöXƒûÆ÷ˆaT¼îè÷Žß2*!)â]ÎÍ€(çÜqˆYh@Q<›ôb Îp˜oØJá o°(¡¶G æq.Jï ¬÷ã…4db1Ól†XšM¬ÆöEãÐq~¤ˆ+ã5ö·óøbªr}¨œŒ” X==¸¥:Tý14ü²?ŸÆøxí§+®jÐ3®J(õˆ®¾ A~J½Ô!¥>OùRZQætZ¨"Ãdùø)]Õðôº,V÷~çqe 4…ßVWÏ~§¤šhUÍdæ¹¥E>›.œ› Y–0å"•ß;6] ˜2>uÖД”q»Ò6œ-Cï¡þ_ì&àÁ Ø4íRÓ§åÓ dhN.z¨¹‚h ›ÛÿSù]aT×:yÀ)0©ú¶+agY¨¿Ë•ç.w‹FÓî,aÌ-ç7óҳ䱊ÆÍê0tOæM˜UÝHïÃÐMäGä+|Kâ§Å0߯/© }>Óü€³ ”7\ð<{ƒéôÀßø¶æ´ ðÉw®»Íb·Ãc dàÀ7T´ù¼jÁÐÅ)ï/HˆÂhs¦DY–q.ö·Ð—æS¼t • ¡»‘À êö¬Ó%à îó™î/#¶ÝéADHûƒ«ˆpå‘”‡¡Üêm&ÙkZÁ ,˜HÅGËYÈh¾ÃÍx(>ÏË&èÂó%\T(pp2зÝñõ€í@8¹qßy÷×Dà†zÁãšçØ ´¾ÔÂsçÇ¢<㢔Úz·­Æ°cÕg*[؃F$oæ±£_~;P4A ˜Æ°rÅã<ᥨÚpØ4ŒÁlܧU,X±ùÇù¶aƒõ¦šKWÅenSÂ8·£_v«A‡—2BAJÀlþxƒƒUa@½–éR¯…|Œ÷¥ñMëLX?@cPËx~Ó4¿}X—xµêÞ^ýëgLÃáë÷ãI6-X;XÀ˜»gRG¿ÿ9ÝÝ>Åd u.Ó l®Efž”“O˜¬ýuÌ ‘/®”J#²¬ð¬LÊãSU×ÿ óㆠ–˜¯^'AùbÎ_çðöÈ'º½»óÃø­›ö7(°jÝ%£iÚôç‘Qúë¡û–”䎣ÏÃyC,€”Uà·lîÍ‹Î[†ªŸ^ž‡þåpÓ´/Á+‚‘ˆ¾ánàùðÓ°+‡‚©»H€·$¯®wÕùàû80à Ðé£oª›ƒ# ½QIÛDôãÏŽ®j©ÖXŒ «ª ˆeeä<ÔûÆGnö¨ýš-ÞÂê›×\¿þvýxQP„‹‚Éu~üQ|×7»ø|î<Òâºê»s[Ï6Ød{P‡¯&ªøõ`§2U°ç‹·8ƒÆÆ·8Ê÷ê§CµuÌžLáo0‚ øOÒ&/a/§­'(uõD¤b£#¼E•¬ÄYþ?®™ú endstream endobj 321 0 obj << /Type /Page /Contents 322 0 R /Resources 320 0 R /MediaBox [0 0 612 792] /Parent 283 0 R /Annots [ 318 0 R 319 0 R 326 0 R ] >> endobj 318 0 obj << /Type /Annot /Border [0 0 0] /Rect [143.333 603.642 281.273 614.552] /Subtype /Link /A << /S /GoTo /D (links) >> >> endobj 319 0 obj << /Type /Annot /Border [0 0 0] /Rect [467.454 442.406 522 453.315] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Spamming and security) >> >> endobj 326 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 429.255 293.985 440.164] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Spamming and security) >> >> endobj 323 0 obj << /D [321 0 R /XYZ 90 720 null] >> endobj 324 0 obj << /D [321 0 R /XYZ 90 720 null] >> endobj 325 0 obj << /D [321 0 R /XYZ 90 507 null] >> endobj 327 0 obj << /D [321 0 R /XYZ 90 203.56 null] >> endobj 320 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F52 20 0 R /F67 34 0 R /F55 85 0 R /F60 10 0 R /F112 68 0 R >> /ProcSet [ /PDF /Text ] >> endobj 334 0 obj << /Length 2793 /Filter /FlateDecode >> stream xÚ­YYãÆ~ß_A1B+ûàÑŒëxaˆádÆÈÃz‘p¨ÖˆŠ”yÌzþ}ªºª)RCílèAÍîbwu_A ?˜8È”ŠŒÎƒòø&æÙÇ7‚G[ ØÎ(Þݽ¹yŸˆ@Ä‘‰îöó-îvÁ‡P§›­4R©ðÛ½mªÆn¶JéðIâ¿ ;»·mJ»ùx÷ã›ï)_a)^p“É@¨(v˜›4בP𹉀U¥7Û$•áûÁóí»Û¿üÝÛ’áÓF‰Ð~ÛE³CŽ.¯÷Y”*EûÝÚ¡Ç{ˆp8XœŠá€£8Zšù×éñÁßî·‰}aD”Ê$HÓ4ÊT‚øð1v°øcG: >9Êc "™)ÕÁ훿­É\˜$JSé¶JbA¬ílmûGbáÓ¡*72ôX1ÓcowÌ~KO>ù–¶^1b)R(ÝT ´„:õš{ªíŒlE —›±ç”, àÓP˜þÀ®÷‘y;qÖ¬B“¼Ð:D®<3s&×´ÎT¯0y¹ èòÈDD‰N^‘‹§zíÈ‹ÍÖ䢼\†j÷üR(Bg—,ê¤mô+RñT¯°x¹ûŠý¹jI/âÂkŸF¹Ñ‹j,ÉØ{2(0ÊFýQ4s®DZ~Çû=ºbñ&Tª»²è˜àŸ˜ÑK5X“33§M"ÂëœcÈ—¹r6ÞA=Þ©m†§N*&Á¿±üZ„Eœ×Œ¢ûÉè|oé,,M ±€_£‚ÎóÝh±+Ì?\ߢ«Z –¥R®¹½2³^*!¢,É®™7Smgdkæ}±Ù…ygÞ1]éÃòNß²Ðb>iŠdü"…|aürÎJv‰ÙLœ]1~Oµ‘­5ë.6ó@« +biOŒt¶v¢Å±»[l 5Ájjìè©È)×Ür„•‚·¨ª 1})ލ(—É0=×—¾#BÎ]üyŸeQÙUÜZØÑš³)áó¤˜ò›ÌÊ Y³0æ†yîõ:˜)h?_F‚ƒ]«Ð]c3, Zµ¿ÇSMM*-FZ:bˆÀG.ÚhÁuæFN˜ñúmkn2ƒ¥ *ðëgzªöôÊâ<ç8ë jœ{î˜IÔ.õ€Vnzµb‡õ[ÒD×ùYÎN‡S¾×öàRh7Éœtô´JL#èÛuW×ÒiÀW•N)Êgø ºfàtéhUóòÄ•3RðÈ|¶qµóÉ9…X‹J(“-Üv”×:rfÊD ر1ÐRÔÃ} êÔ;à¦,•…ï?Mzv%z¨y#ŸS®q‰½x£¾¸@I¾—˜û‹¡D8·=WÎxÇ#.ÞSã¦ëÿ´Ò#ßJGyФ‰rù’—õ"|üó+ýoÐ@>wÌÙ7</ Ž{èìDGWaåçž1®Ì:gøH·sGÏY­øÑ'‰þÙÛ)2{œ¯Ô JLÕ€C³<ó-R®Ð(¢ç.àw4ª[¬÷8Ââg¹°ºó–®aÖíx:¾9åÉØƒ7=P¿Ëƒ‘’üñVJjœ°D°•eì£1,,|'ÆÏ9º>›Úº¯%øBäQ¬õÜ£äu¤åœ‹Çéã‘û‘ uÉ)öz}ƒ· × £˜@Î ï ãnÖõDw½;Xî$ÏœS-S{¿à¦¸=RçÕù»×§®ìš×(éhF -Vš%«>ƒ2»;ì÷‹g仌Ÿÿœäœ¬æ—ä2Œ  ׎ͦ–iÊõaæÛ·08AåÌBòÔÞæú R¬/í˜åf{†]·ÔpÜíR5euªÉÞDÈËz?>Ùü"<ö–9Œý7‡—-[Êß½*Vßp`ÓF3‡±³…5Ôò?ø»¢šù öü 룸KczŸ†’ËìæŸ¼ÂuX0¾ØóWÍÙ×”~úÐ2L$ŠÉHëš@­ÿBƒù+úÔç-æÆ9_FèœÎ=Ú~ ¼FANº°+'ó8ÒéíÌ^×MÓßæìY endstream endobj 333 0 obj << /Type /Page /Contents 334 0 R /Resources 332 0 R /MediaBox [0 0 612 792] /Parent 283 0 R /Annots [ 328 0 R 329 0 R 330 0 R 331 0 R 338 0 R ] >> endobj 328 0 obj << /Type /Annot /Border [0 0 0] /Rect [109.672 352.931 329.974 363.84] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (NFS resources) >> >> endobj 329 0 obj << /Type /Annot /Border [0 0 0] /Rect [216.333 339.78 344.879 350.69] /Subtype /Link /A << /S /GoTo /D (files) >> >> endobj 330 0 obj << /Type /Annot /Border [0 0 0] /Rect [351.545 339.78 486.394 350.69] /Subtype /Link /A << /S /GoTo /D (tidy) >> >> endobj 331 0 obj << /Type /Annot /Border [0 0 0] /Rect [396.099 309.03 522 319.939] /Subtype /Link /A << /S /GoTo /D (mountables) >> >> endobj 338 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 296.485 131.559 306.182] /Subtype /Link /A << /S /GoTo /D (mountables) >> >> endobj 335 0 obj << /D [333 0 R /XYZ 90 720 null] >> endobj 336 0 obj << /D [333 0 R /XYZ 90 720 null] >> endobj 337 0 obj << /D [333 0 R /XYZ 90 561.069 null] >> endobj 216 0 obj << /D [333 0 R /XYZ 90 408.809 null] >> endobj 332 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F52 20 0 R /F112 68 0 R /F67 34 0 R /F60 10 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 344 0 obj << /Length 2229 /Filter /FlateDecode >> stream xÚ­ÙŽã6ò½¿ÂÈKä`¬Hð‹;ð>1x~àáÏHGzM\LVF+>›±*ÐÙ¢­áÖ9¶£RÖz*‡3Ï&=ãõŒã\Ï"•pÒ…r'Tå.V.ÔÒN:[·sýS‚CC§øj1v@B¤Á3oíMו¶ãíc×Ö<3<\ðþ ˆVi*‡2 rLÄX'ŽÊÏW˜WnfÄì“S¬`DžzwŠÿQC͉Œd3I„±rvô;±'3 ~fÐ93ô8`˜îܹŒ†>FìEl\l€=uzêpËã䈸ทQˆÀ¿Å‰¹Å‰4 …Ô`ûÄlqìÆ&dW\±ÏD„yž{äo™îÓ¹$%ŸyY£ÖF C3–È(¤†Äf 7c6!W‘J©@ö¦/!b5Åó6Ss¿e‰–®Çù&ã|ƒÉ!~®ÌsEFH0ÿc¢Q×D#ræ‚O=ò¢ÀÅÙ4'ËkŠŸ8á—©F·l~Ÿ¼fÓA€€¼‘äÀðþÜŽÕç{zpO‚<#׎–ôwirL¯ë^£±ŸÁFú‰átbÃލƒ™4ÝZ0í#éÓØ™¡Äx…oÓ]y^¶qŽQJ$W q™"5r¬®­ €[§ªÝ£¯"³7)·PØ.$&|ÑãÖ½*…}@›kS©§FIì‘ËÕ´Ò†©Î–/õöábêšÂ‚‚œB¥*k ¢åÞ‘j2PÕÉ®]ƒG&‰ð·ÿ5Â,d™¿†ÈóPDÙFé(Œ2õB½é±v3´•Šø–] %K*âÉõÒ5ÛczµGím âVÙ”5n޵Û)k·Dä8šÅ-ŽzF=¡æQO(u­3Ø‘b½á"2§\€šÆûn–Æž€ë& ûatõ¼Ò>T©ôDÀ‚)ÅáÁeU1dÊÄÓ'JAÅ8Ü@¾&=™²qá7ŽÅ&‡òG$.Jæ¡RNé`Ò?õ‡ésæëÄ -s|Ä·ï¢Íöà¢PæÙæ‰0ë m¨ž«6wÿäÇ^^¨EýDBÔ$Pó÷F+÷Fa 9J&P¢eáÞh£ òùµ‹*/Ï áh(öâ0v\F˜bÐm‰ÇþÎ$ ƒhò.4¨]ÙìÀÒF,µ>/+!CŽôø¾J\ʇªÐ©þ\ê7 I=’ɤRñâS"¦‹ŽÁSÞÞ»^+ÉØ˜•e¾H7 ØÜ½%„¹Ú¸Ò¦ê[ƺÖE°à‚c"C;{/êÆÑÍfONóaô\“'–÷}yIç.î_¾![ŽóÞŽ‡v·š‚+Ó÷œx (C}¤]nMuÛÕ*½ÎQãP+=·Â5U ¬Í¦<„½„ˆ7ÛL­ûÌ€}¤àójÅrwà+I~ÓýHj{˜bÖjOT´—çpâ?Ö_é¤ uä[¤k IeOæË£loó”E&ðÌ^½e¼×à™ǹGj"Ì5–4ߟЪ®!óR«,}¯†”\¯–R¯Wâ}©}–iÊÅïšâ¯ÛŠ&‰ûÒƒ½@gqæ6…r wVp"ø±w4Ž<ºÝžM"ŒÃKÑ,»V¸Ä…iüeœìyÅþûéRvÏk°ªÑZ¸vTdï°ôÞ¶scèÞ@©ÿŠç¦çí­Æ9ñ.]Ý‹»ð"õj#!“)v–Gg?ÀÛ®u2Y˜Šäjí+=ÆN ‹µN#çNãÍ*rhO›Ãý©$ü‡=ÙO/u\6‘õÖKU:¡;{+ã Ô‹ýõT~SHýx¡ †’oÒíÔ飣õ„Oiº†»EoU› G°E½^ÈßmxZûØ¡äÜÄéÁ¹ ü†®g±×½ûEñë4Š^‡ßýïŠé_|sëæ7º÷wJÈ÷i:Ó½Š\—G Üs'g»£)¾¬þYSGêWÊ7f8›Ô¯ÔRý„Öòx°•ÜQ£qZ6h“®[Âó†=º¥¯O„@=3Ùû«Û®h™~®Yñ.~ÙéËdμáØ[4©Ü¹]În*^7Ów<ì{ÆõßêÆ&‚¦©ËÃ>–Ý0šŠá5J˱î8{17À¥;Ít5”ÃxØâ§ÇvìW>®-UòU£KæFwß,Þû»ûX‡ßÝ5ÿ ìöª endstream endobj 343 0 obj << /Type /Page /Contents 344 0 R /Resources 342 0 R /MediaBox [0 0 612 792] /Parent 351 0 R /Annots [ 341 0 R 348 0 R ] >> endobj 341 0 obj << /Type /Annot /Border [0 0 0] /Rect [467.454 460.508 522 471.417] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Spamming and security) >> >> endobj 348 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 447.357 299.208 458.266] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Spamming and security) >> >> endobj 345 0 obj << /D [343 0 R /XYZ 90 720 null] >> endobj 346 0 obj << /D [343 0 R /XYZ 90 720 null] >> endobj 347 0 obj << /D [343 0 R /XYZ 90 522.987 null] >> endobj 349 0 obj << /D [343 0 R /XYZ 90 243.271 null] >> endobj 350 0 obj << /D [343 0 R /XYZ 90 172.459 null] >> endobj 342 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F52 20 0 R /F60 10 0 R /F112 68 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 355 0 obj << /Length 1851 /Filter /FlateDecode >> stream xÚ¥XKoã6¾çWøVX+¢Þ ÐC[l€í¢Àæ¶»À22m«‘)ƒ”“ì¿ï¼äÐ^í(|Ðp8$‡3ß^)¡V ° $~¿¿º¾-ÔB%q“4jq¿ ·¸_/>Dy½\¥MšeÑc·5ËU–åÑSŠß,rfcœ±­Y~ºÿóêíýé¬"M  J|¥M•.T' ŽhSÖy¬²\´‰AÕ\-WE™Fwv³\©hp{<ûú6S‹:nÊ2Ç•Y§*_¬²&.”âÕ°…áà"ú•?“"áÕe¬.T\Õ %-ì5‹Y ¢ŠX•'‘‰Êf´Pyœ§j’‚Ôìtfó•Jò¸„…«´ŠÓB,¿ëür•«2zZe¤]§zÃÿÜí2­¢ÝRE­@¢èÊãN$‡ãx8ŽL÷æi™Ö‘éyø¼Ï= ç 3Ú“‡qäÌ\_ƒ}GÑ£EÙ¶[#ŒN6ÞëGÚØãíà:9¸lŽT…Ø~}tÝfjiþ¸£Á u½·è¾ÿÂüÁNÔÑmÅkŽ<Þï5NrŽ¿mo4‘idœœLkg˜8ÀɨÞhÖrÞ{3ލ û" }‘5¸¢š\&™sÚ$É×dñq˜Û`ÅÎm6«ª|’y5è*KŠÀ1Y’‡Ža:¿`B!Ú±¬çFÞżú®íF².L´¶ïÍš‡©,gùϾë [î9è€û‚ó¬ˆî—5pØã€Ûª9w¸7#gˆ‘pŒ9cÂ"r,âp˜òʳëFãofbE‘€¹Ó<.J‰‘¶×Þ3ì.ãÒJÝLö¼¹=amUÀ Ùç»Y(4­p$tÏÔ*Oa'ˆÜ¬ˆ“´³T:e©e¦{n£[óNïÍœ÷!-+D“¤¹» ÆUq‰n> M ðpÄVãimyf@õênĬ”¼ðËi<­Ñ+-f2(RÚ ÝŽBä]$È…´<ô³Øá2)Ò€¥é ö»n™nÃßSèààɾ."{½–)tY ÛDŸçJ$èSýk7®^š"9IýÂ;cÂè1ee¥ý«Nâ=†©T0¨R¶š°)MÝè$µ ÄfúãËÍH‘÷† .«!Áć1¿òe°HÈ¡œñÃѵ’Áø2ŸÞpf:@·Ã|U–—÷RM½H—yù%VÈÌ}ÂMHx¶Ì©¤–$X…5.ãw Â[¼ìËh¬§ÖãÇEŽûÛ¬¬£¾£j¯¥ÅÁ‡ :ÖLQÅ(“h++óš?Ô-÷¸‹,w_çì@çø'K<:@Êl™l¥EäÏ+ÿ¶LìÆ}ÿƒîñôJÅî± #+çÈú £JC ñ#d6ûóa¥2éÖ‘N£‰7º£aÎJäJz§Æ¾¢î¹\A”ôh°„_¹¼·cÖF÷Þ0«™upØÚC+Ç…Ü37x€,Tëi‹S–¤Á¸§µl톹 Œ=©µyB—ÆðjìwHî Æ©ø†‚&†¨¹ Ö5sH™«®¥gu{j p5×YÙ@[j¸ÐpX{¨sFþTˤgÕLX=¸ßx؉” •^ʱgB2ô:¤Ø¨^;ê«`žº!ÈBOyff ür7UÖÁ“]Âð„ÂÄRÔÁìÝ?O¥¬öh‰èœé»§1‚Ê$òÚÝ#ÿQ—pö<ž¼¼¡«È“o‡6@Ƀ£¶0‚6“ó€§ÒFÑ?x1à­¦Ç#!X¬ÄvOµò?^£à| endstream endobj 354 0 obj << /Type /Page /Contents 355 0 R /Resources 353 0 R /MediaBox [0 0 612 792] /Parent 351 0 R /Annots [ 352 0 R 359 0 R ] >> endobj 352 0 obj << /Type /Annot /Border [0 0 0] /Rect [445.365 302.07 522 312.979] /Subtype /Link /A << /S /GoTo /D (cfrc resource file) >> >> endobj 359 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 288.919 198 299.828] /Subtype /Link /A << /S /GoTo /D (cfrc resource file) >> >> endobj 356 0 obj << /D [354 0 R /XYZ 90 720 null] >> endobj 357 0 obj << /D [354 0 R /XYZ 90 720 null] >> endobj 358 0 obj << /D [354 0 R /XYZ 90 512.339 null] >> endobj 360 0 obj << /D [354 0 R /XYZ 90 279.295 null] >> endobj 361 0 obj << /D [354 0 R /XYZ 90 165.34 null] >> endobj 353 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R /F53 19 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 369 0 obj << /Length 2020 /Filter /FlateDecode >> stream xÚXmÛ¸þž_aN."®ø¢·ýÐæ²¸¹¶@è‡ä€ãZ´­‹,¹’¼Éþû›á2eËÙô°Ì—Ñp83Ïð™å«þøªLV¹”¬TÅjsx•¸Õϯ¸Å xuwŸòOX™”|õ° Uަ_ÇRÊH½YÇJ¥ÑÛ­Þ™v-Šh¤ÞlMoÚYÇ"-Ê"Råú—‡¾z÷0 ñ‚q(qeä«‚•Y¦Ð8. &¸Ze¹dY®ÈÂ÷z?0¤Ñ_éçS’&4ê¶Ûi‰£Qw÷¹Xqɸ2*%)…‹0©rRªøD¥ðe&¢÷ë˜GzÍ#:èÝWœëÞüm‹®±:ç^7óœeÒ™ø°¯p—ÑÓ:M#Ýœ MÑ̺¥q¥×"žk§]Ìè>÷öõÁ}ª·Xü²¯7Œ=íœÚÁºÇÛ¾6mEbûnðútï´OýθýmßfÇÉèל‹´7’Œ§t!<à }¥Gý¨ó§*Ò-?Õæ Úd•Ãú#NžiÕ“ÓDè4žLB :ãÞšþaÔãiXòq.@Zzéí©ÝŒu×¾¦# N— (‹”y±Ê’’¥Jb†>»$¡—б˜\*³6|0Ö‡–ÓÍ?êÆôãð‹³ìС‘L®0³K—pâ¤^0ñR™5‘‘'g¨‚; DZ”ÅV゙3}aâã+ ðU·ŸßvÇÚ ß“œãIEM=` âiäWNƒÏç±£Ê|J¸j‚4ýìšîQ7$à•((ôÛêƒh³s ;ê\Ð!är‚œòx:Ÿù…0Œ×ß~ž°BÃó§(SD]SÇ3„qºãF7ÃK¯1=eÓ¸×.Á6è­ŠaEVÑýºd*옯úplÌB¨¡~BÞpÁJéa¾nšSeÐÄáF|ÿÂvõÖ;î.Ã=^¢H3øMY&r0t…*£AÜh õToläaÔÔ£­~¸WÀÝ["ZlÙ%ÇnjŒ©u(ê²7‡ÑS!„TVUõS]l¨aɆŽ:§ œK˜…µÓP·;Žðér™’y†þô…‚i•.¹B–œÁp×îx® UŠ+@ ä¹*&ÊòF•òRq ¶P.•-U).\™‚|²5úºPeüÒJ‘§ð:¦¡• …ÊK½`奲s¡BÔ',å|žMÿêF´,C4`4Àà@b¾ðˆèI_[⯠ŸÚÊB v4­ ש«x§¿‡ÃÜÁðŽgp`í¤ºÖb•9ᦳ™¬rGZ!t?lGÍ3¤vOèd1#ÖWã r{5.›wY€Ü×ÛæÓ‘—A±4ŸžÜ7oȪ”å Â& FÀÉè98×ç«*qmD-ã^««œ §ƒ¥Y9!évEÉ2x9ÊyXvÑšjî,ÇB| ÓÉv–lœâ÷ž­¸øÉy`íGÆ æ¬àdáMÜ{‘ÛKÄtÃ…È.=˜"ƒJ(ÔB°¢HÃ3^Ìn÷#$$<Λ±ëŸ¿Ÿ†‚ô ï\‡^øâ­:‚.=:³VSn^ÿp¤Š¼©·à°´ô!ñ.ø ] ÅôiM%«É:;µuôš£-·¸°ÙšvW·æ‡´6Û@z ùÏy™8ûíªÙêS3º<º7Áôëb gÉDïžtןÚ;oÂ’#Ë<䚎ùz(.T*9CÀò­r%ð|À"Mãi p¢/Ò¥Å{È‚ÀÉKï÷üð?ÊÕŠYæ=ÔÕóOÝÁÜ×–‘Mz€Ò+>™:ÿì»¶‹z¾…|Œ[…c«ÿ@â– l™pÀ‰ˆÁÂ'.Uh“ë8/¢?áÛéÕº]›f(n ]Y*;À'ñÊ=Í·`ºSc[7zV÷4Üw–àä|ÊýÚ‰ŸUR{…Æ‘6šœ»¸›ÉL4;¨ºª—:+åź’¸‚’…a-)¬tàêԘꢢÌÒZ¥¬,è9æ©ËC7ÿ,æËÅ"¤&ð¸ˆ|* Õ<‡©PÀàØœvµkíéœa±uÌ )ñ%‘;KnŠÁEù_V‰¼ÄÇ w;g8áìKÔGMG¤þ3Mí=ðS¼GŒÁÕ Ñm¹ðhmIÚ`þw«¼¾K’s(>~á¶ðnÝàN*Ä–8ä…²9‡TEF‰$qœC³;³¹d*”ã’( Ó«¾<' žÒÀŒ.é¥^°öR™ã’q™¨è?ØgP:¡%> °J°‹Ú¡ /6u¸C}%.ciÁ_¼*ý?g4Á½‘a#‡ÜÀêO¹ï0T*¾‰Í ®èfåbܰ8/‹¥ØY.áÎ)Ku#¶^*Ĭ·²äšyŸ•Y{÷KÈQ ‡rgO¦ Ú3­* Ÿ¾zñ=e:-Ä f4 ”Q ‡ó4Ý£ý¾ËP+pƒíª‚ÿt}ãž"¤õ5s(prU ¨LêFV{¡ø,µÁ™ª)§wÅK•¥#®}­C+g’„3›µð»ÈV°QÌÉÊݼêòëÎZ„ØZ†ƒc­wC=ÄÕÂ’€Ô;›t[MÆ€ aÿ7…ûóOÿþùÖü;ö]fË|F¶èéÜz:×vm|ÄV­7;ÿÌZ³™òïTMÂ* endstream endobj 368 0 obj << /Type /Page /Contents 369 0 R /Resources 367 0 R /MediaBox [0 0 612 792] /Parent 351 0 R /Annots [ 363 0 R 364 0 R 365 0 R 366 0 R 374 0 R ] >> endobj 363 0 obj << /Type /Annot /Border [0 0 0] /Rect [385.878 606.816 516.878 617.725] /Subtype /Link /A << /S /GoTo /D (alerts) >> >> endobj 364 0 obj << /Type /Annot /Border [0 0 0] /Rect [143.333 477.572 275.455 488.481] /Subtype /Link /A << /S /GoTo /D (copy) >> >> endobj 365 0 obj << /Type /Annot /Border [0 0 0] /Rect [111.063 115.928 307.612 126.837] /Subtype /Link /A << /S /GoTo /D (actionsequence) >> >> endobj 366 0 obj << /Type /Annot /Border [0 0 0] /Rect [275.459 102.777 522 113.686] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Writing plugin modules) >> >> endobj 374 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 89.627 117.273 100.536] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Writing plugin modules) >> >> endobj 370 0 obj << /D [368 0 R /XYZ 90 720 null] >> endobj 207 0 obj << /D [368 0 R /XYZ 90 655.271 null] >> endobj 371 0 obj << /D [368 0 R /XYZ 90 567.742 null] >> endobj 372 0 obj << /D [368 0 R /XYZ 90 391.972 null] >> endobj 373 0 obj << /D [368 0 R /XYZ 90 278 null] >> endobj 251 0 obj << /D [368 0 R /XYZ 90 175.413 null] >> endobj 367 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R /F52 20 0 R /F67 34 0 R /F55 85 0 R /F60 10 0 R >> /ProcSet [ /PDF /Text ] >> endobj 381 0 obj << /Length 3130 /Filter /FlateDecode >> stream xÚµˎܸñC€Õn-%R/A° lÀ9$ûæ5M‹=­ŒImcòõ©%J­ñ8‡…a7Y,VÉzËÑ‚?Ñ]¡î2­ÃÂäwÇöèÓ›HF@8xýüæ×It©°PEt÷ù䓸\Ý} uˆ‹Xëào'Û=Ö½?hm‚o1þê`°';Øîhï¿~þû›÷Ÿg^I¿" bÜH“Åw‘ˆ#Ò¤¹ #mXªEJÒ8hûkw¯£`º”Ód‡%€ãÄþqL9ðBšpP"‚ûæ=‡H%*ø3PŒ“àw3•4ó©D E©—ý‡K_wÓË´–32ŒkuχXÁa¢DËB¸Æþ|¶{$ã8LòtÅ}æé °cã°›zœà©LÔ#ÿ^G[ñèá>΂gOg˃ãòÎ0k{xÿ<¨lÃóS?¸¸}X™êî‘!ÝIü®"ÓØñyœl;†÷“Á'{£!ø¸F…QQàëþÑVƒô#UmutØóÞ}˜06±»ŽkWY”¯ƒ;à—^4i¨ÒÈ!×{äÒ°ˆç·øòŸà‚L †0ö×áhǯoêàR>Ú=¨LYœ8 „Èþ-k•„‰Ñ;–È87w½–iMˆ˜áÛFIðqâ+@Ãß²{±ªÑZÇ¿¤f8°ßî“P¯åT÷´˜ýiƒtíµêñH`0 –%Ì(³¡.š]³Q =[â¹oíÞ]ƒq‹q¿e·¶£®QVbg¡2/é¬Ã:xh;—¹%F¼?Ù#ßJÞ¡`WûEìé«ÈFŠE£"¹}í<4‰ñ…Ü}oÆzEÈ-1¹ -Kx—(Ž^¹‡õË ±½{Ñî^¦ºzþzñ›ï^"“m¥4.<{å^é7¤ÄHG5Ä;§.A‹Ì#óÈ2g™úG º>ðì{=ƒõ@ÎFà–—ÀDv4=ÊðÍ}UÿA€HÁcDs€˜zæÕ°§?–“°*;³®¬¸úÓ³ˆz.'FZùz1ÔX婘ªÝrÀ·)ô¦á9²×… Jž>Öß•íxzî)zá:Jƒ ïçúˆ(gž a³$+ˆ=ΘÚÀ(ã`©³¿ã?ýð~,…ðÿá>7Å7”ëLñvIeÕA[>Y:¯Zù¤Ñv#2I¬HýŠI,€ŒŸãi .y:ÔuÅcß-'é0d‹5À‡ãÔ–@U8"/Š÷TöíÈ` /Ê÷šõá仲%â1bñ+ØÖò¼ù·²ãq¨è•IÑFÞ?• ÍΤqÒ:õê;·¡äýÞb¬‰ãàã‰æËÅÉ©ošž”æ3›ÁûÈW:_:ú à à™Dt 4â7Z-±7¼; Jc¼\ÐÎ\ÁoGqí ä] Q„ÓåLûèÐ5P>â „‹‹1Ï; [´Ü;wMõx;k§J+U@«¶ B³D€ø:-——kJïtüFèk«nNˆ8㹿6Õ†mFû✊hĈðŒ&G–¥ÐGŒèhwŽâB¿8]¸{©ñÙ–Ör"ËÅ‹‹t°PwÎêëL´X߉å/W *÷vö")LŽnˈT)Û9\Ðè ·Í¥ßýAf )Å0î®\†þßð¢ãÖÖ×u¶Øz ¶JüR;âR»£[ŸÚ.}|úÙB¢l[úÍvJì4‡¢(s9IY–áÃÃCx<êªöq˜ù«evxiß–Ùð&É"¡xèd.'âꮑ±'·mvH=œ;÷PÆëCçÂ@YUPŽŽ «ó*:kÃ)Iæ¥$”KE&,ŒY›ÃG|M¦Ë-Ok/RW ž,-,qeÉ‚2L{Èß"VYAX-JðèÙ@¼v¼Ö² „Ý‹cp=ù2,ªß<óC# sp‰ÓöA7F'IèþªÝ6‡¡âDÍ¥hšixY’ R, ¸dζB2ò)¼ Ç+y_\ ÿ+›7``-¾e8•GÙPïöšâòj5«$N§úqOø$ “l„ß):ê«Ò;§aþbqå°ÚNá²%披뚉„Š!Wõ¨ µT^%goà ÈCìíŽö¶>Õ7õiœê0…âIgøûRæ°ÚÎy¶ÄüJ,JÀ¡$z¿¼—j•2sÅŽ(–f±hB¦—G'#&dÌoi‰Ì{ÒÙé2Ä{GËI5;c΀+tiB…s\ÇúQz<ת®¶C9pþPC¶Ô¸ ~-x_Ή…VÛú†PkŽ<*E%ͺ†ÌC¸Q§“Uß–.I9%Ú3ÁˆìÕ9m¬Ð<ÅG„°•X#Ô¥Ñi├…ODN“·J))!¡Ä6ÑÆïáskwÂIçÚ—¹Š½Ö§º;Z‡ê|“û½ŽWºÄ™"4kË9‘ó¸AªP5ÎÙvüKY{PS$ØØš• Ýä• ‹ÝúcûLZ‡-…µV‹¿¤IU«+ν l»0P4µç‡Qò,ŽsJ¯=:ƒ(b)W+½/ §:ÈÛ7ÏRkíœH¨å$ëÈÎf¾¹R–è·€cWœ¦N윘zDdGÉ?p˜ÊzpåšrWKL³VvžéJ¿q´†ùò¼¾8·õwd4XÀÉ~ç)!::Sp«`9‡ÁC’Ü$ËnïyòX‚ÂYEúúhy^³keâ•—n=ÖÏ“k¼§®uŸú ævêÎIšºÍv0­m»›kå«FªKšöúÖ*ÄÑÖŒ1.Û2~¶¥—jpô’å%—îæ„ÝóÃ’LÁå ”’E%ãžJN;ƹ†çÔší»½“²„šx až›Ûì³mÛݼÒå»þ>>¨á¦Øà>»xV%ßIp|mñ_QÙaä}ÿÚííÁãÅñ&3~ýòa’Ü[¾ïd.:1”¼€É–Uvû¤ Ùr Á"”ûD°kWÎXCõÎéÏ.o+(gP‚`È÷Uu¼ðýk¼QŠ˜P(JkMÓ(W«%åÆ1Ç"ÍãæZI!QY¥~_Ñöû«qž…y”üŒ(¡fS™lÓˆÔXÍÏ‚ŒÒ’ûÇ:ul~%ÞÁT6;aHÛŒ¯"é[DîìxàœF¶"³,q.‰jÅósÙœxÔH¿üá¼ÂGÐvi*ÐvçÊ‘ß܉’Ä»u±>´Ô.hóÎ¥j=÷l)a•¡§ÁÓ±°mNâý…Ï)•—’ÄE$uM\@öÒ·-u&ê)N¹eUHÅ€Ù¥á„ü°ºo0Ž¢Y3þÏòæ—S&ú–à±rbGÁÙ6—Óµùzb²õ$)UQ@9Ÿ­.Ÿ¾·eî8™òŽ“)nÚâªÚ‘‡n*5dýÄ“ÊÑ"%Ôœ£ËÈf³€¿t¨m¤vMá§p)Ø¿-ÄÍ_Èႃj!âä‹4ȸ&<¹sµCšw CÇI˜-á@Œâ'Þp#ž’#á3I_N>Hé4 ßdªô¡F{!€ŽŸðG\w‚ƒz¨¤e´§ÔˆC— ¿ûAòŒT'Þ!÷ž)Ê—¾Âÿ¶¶ìF'O9mDÄëî[êcöØ­…ZJ˜Pé é« ~1êy'©”žØZ‹Ö}ðóxµñ¶E22”×Ì_MLìAKî Éj,ÆŠ ¾ù÷!0œþºF+nšË £çÿ¿³èfùhÈPòÞÆ’›Ðzݤ3ë8Ã2z_m–8ãzésü”‡nÙ endstream endobj 380 0 obj << /Type /Page /Contents 381 0 R /Resources 379 0 R /MediaBox [0 0 612 792] /Parent 351 0 R /Annots [ 375 0 R 376 0 R 377 0 R 378 0 R 384 0 R ] >> endobj 375 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 637.472 305.5 648.381] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (NFS resources) >> >> endobj 376 0 obj << /Type /Annot /Border [0 0 0] /Rect [179.909 624.321 308.454 635.23] /Subtype /Link /A << /S /GoTo /D (files) >> >> endobj 377 0 obj << /Type /Annot /Border [0 0 0] /Rect [315.121 624.321 449.97 635.23] /Subtype /Link /A << /S /GoTo /D (tidy) >> >> endobj 378 0 obj << /Type /Annot /Border [0 0 0] /Rect [502.606 384.425 522 394.425] /Subtype /Link /A << /S /GoTo /D (actionsequence) >> >> endobj 384 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 370.971 263.697 381.881] /Subtype /Link /A << /S /GoTo /D (actionsequence) >> >> endobj 382 0 obj << /D [380 0 R /XYZ 90 720 null] >> endobj 383 0 obj << /D [380 0 R /XYZ 90 720 null] >> endobj 224 0 obj << /D [380 0 R /XYZ 90 456.887 null] >> endobj 379 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F67 34 0 R /F60 10 0 R /F31 21 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 388 0 obj << /Length 3032 /Filter /FlateDecode >> stream xÚˎܸñî¯häb à–EQÏrpœ5àœƒða½Àj$ö43j©¡‡Ç³Èǧ^”¨±fc‘Åb±XU¬W«CÿÔ¡Œ¹Öa™‡úò*èÃ+%£# =Œܾzû!U…eTªÃíÉ'qÛ~ ÞŸ«ëd†›£Ö:H~¹9&I¼?U÷¦»‰‹`â…ÁœÌ`ºÚÜã´(‹ U7¿ßþëÕ¯·ËÙiÿ„9Äø w*J`59dE*0‹OÀ•΂élxðí&Í‚ªez®ÜwE`€sšþ, ñæ¥Ã$O#¢§i¸þ%²cÃS‘°p^¿âY Ìܨ@èÌtçÁ# ¬ȳ¹ÝòÆ“Æ~ƒÝ¶1²8_ùkYæ=Ïb椖¹.—8ÊÃ<) ôd†ÔÏI˜dåáè¡¥ˆv8&q¦Iz8‚TÊKã|7áb:VÁhIÍZåÁ×H%§‰ä©\æÄ_wuöûŠpg§‘wVƒ¬÷ ñ6ep{Ð`.•ílwϨ°‰á­©ðößð?32Ìtý|–}pjORì/ 9õÝ*’ë(¾Ï„Xü€W¨ jšÁŒ#…i„Ÿ(¨º†ç 8L‹,øwg@Œéܲ²è˜Y”Ý'dk%$¾âTƒM)g9wÃMŠ7H‘¡š>#ÈkG{i 7Ù7¹[´-³\±¶JÍo=ŒF¬«Ž•­£,Tj+œÅuƒä[OsÕò•ÛÃm½} ÷_†#}ÙöˆÖΦMâêÚ'^ØA`{D¥”˜ ‹>Ü·¬i¾Úf£¾¡ù^]®-¾4•’*•u?£Á·«Sq$ECd<äî„0Ç‹ãê£K§Õå±Ã˜¹“ý(¦j|à2¸`WO¬ ¢R°:€Î#¹ÜÔ3dªÆìYµ¼Rܱ0ã"g[`Ø*D\X„˜ðÃ<¿‰S” nÜ÷“%ørÇO&a´g³9 ƒù;/É”=CÁ)XpÏo“ÎWqÁðÆ‚§Ñ`$ä¬ْ㬀¸Pn%ÂúÁð$ž2‹|Žtæqî8úEz—ï°ÈËõ–Ù%U„yQx”v%ÀC‡¥Ð ŠàïüI•bNE_8ìññé$0U×>‡|U²Nñ¦e¨I¹)4=+ØÖƒV×€u¯'&±¾;¦|èÈ?þ#b[Àfa%â2`И©²íÈòyZ¯« ü ™6Nðí£-%Yðyeeµ`YIÈIÁ|$þäNª&‡&ŠTßý÷êY¥Žøá¸3ÃÅò=`Îþ#Ò@œŒJfF^,Üq MÏïÇwŽÈ]}ü̺"Ÿ€gœÐy¤œx>‰GÛ¶˜îýª‰¦*—ÐVvaHÅÞµ&[Ïm50X8%³ÀÜ€SÄwƒmòñ0ÚXó¼+õnz€?ŒJ--´èu!ÖÑCÛéD<'FÜ}6µ¨8€ØÌƒß–ëÿþ†!W0Òú9—:ƒê®,|.wz%ë'\>'¶Í$x¿êXÇÔuìËÙ×1"œ$óÎ…ßm»´Å×»N8´ËS%ËG®ôýÔrs”–Ô3YÉŠ}„œäP—h¸äÖpãY £"cV’¤‘ÆýâàÜwïÚë¹ú4_>ØÖìæhsy˜múKðÝUw­ãók,)PeA‘}eõ#v]ÍÔQ ñ"jÄ¢R.R”ÁÖÃÈ® hG8E0±ÁÒ:"œ¨Pf‡Óså+„\çÁ`¥;»¾;î¾¼;ù‹ùb Håsº 2”7’a†DÓ•*Vpzxãu7ùlU£Ûe×D½Ô¤ôÓZAWJL#˜*“ª5XèíÙì8á CÙ8:aª–ŒN¼2°âÏHÊ÷ݪ6ÃöW¶¤—õé’$¡í‡q¨×dT|“ÇT¬ D3³£ÕŠÙju€š5Ë$tŒ£(ÌÊdk¼ŸžÛê1S,ñƒÑšGhqÙmöcB¡{ŒË0Ï…4ˆ[Wq™¬òÄ Åå˜Gƒ­Ø6ïà Kq<šj`Ë çŒ îAÀ‹¯³&²§Ø©à‚“À¹ÄъЋ©º½Ñ™õX[댈ømŒ®­q®f:Wb":‡ä4v?˜jér¯x*Îþ'£ÙÉt'roXPßÀŸ®XfÏÚ’jì¿)jÇ­î4NOW󣪹ïûû³Âï`ÀÎ#mÝ9 ;†‘×ëxÁPॹÚ”®Ã–K:XvPq+¶«Û™“,lIïpM½<8ÍÓ<È&óý ÊG‰ c”‘Eä5 ¤¦çoG  *÷ÏÕKÓŠ™zó²…X×VyVJ7æTA­4nÛ_•N@ž{¹Ì~'~/ƒ|åŠ]ßάþgýuuu£€HB$=ìöéÃg º]VŸq:´ýù€‘ðÕ2ñIú±›.’«¤PÁz}ÝË’Y™MU we1À9ikS$g.è¸À1p1™‹lCAâ—:  SJç¡^~ÄúMˆ‘cR { 42Ä’ŒÈœÁû¦êˆ´û"v›–9øAí^Á[3Õoáµ½;âÆë¯:»ôÊ>½úlê‡J„ÝÞEªBy=Ð4³˜êË:Ü@ð„5Nšä àÒÏÎÄpê ddæI´•üòÕ¹mÂ^ì™Oùèì!Õa¡ò­A\xΖ[ä™Wœà„#>·À3Í6Y9¾BÉMFkTü©{lºs¬Çù=]Üäô‹dxt¤»8E„lï¾W‘®©Ñðcî¸1cÊâ¨Ùí¤8Gó¬÷s”»´g#ï×®«ºüºGÍÒ~/ErZ‘¥YÒ䱿˜é¼¤Å¦ÍÏý¶ñùw‹ 3{1 ¢ß7ð¾P޲ü`R›aâ_6`b»q²Ó,m„Pú‚ƒÁ\Ûª–mâ ˆÿð?8û,Ù÷®ƒBìñeãëM?)¥øLÊ"ø'-™(—‡¸ÎäÜ`nA\ôÛHY’mÍr½ÒÕÃßìÐw1/qˆ%7…x[h)2âÆ¿H8ÝSÓq’©ZŠq06ß)öÉ [Iœ­}x÷ü¥C7xÞ»Æéuè'vÁuß2¨’%8’ãŸ/A\·0v?'°AÍ7øºžÄ^)0˜g%XÂúô3uÐ…Tkw£f/¿-Ðï Í6xÎîŸÈòZR±‹óå]@õ.Ÿw¥"ÞU*ãÿì‰q. endstream endobj 387 0 obj << /Type /Page /Contents 388 0 R /Resources 386 0 R /MediaBox [0 0 612 792] /Parent 351 0 R /Annots [ 385 0 R ] >> endobj 385 0 obj << /Type /Annot /Border [0 0 0] /Rect [211.955 432.366 362.898 443.275] /Subtype /Link /A << /S /GoTo /D (broadcast) >> >> endobj 389 0 obj << /D [387 0 R /XYZ 90 720 null] >> endobj 391 0 obj << /D [387 0 R /XYZ 90 407.68 null] >> endobj 392 0 obj << /D [387 0 R /XYZ 90 266.646 null] >> endobj 386 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F4 390 0 R /F54 28 0 R /F60 10 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 396 0 obj << /Length 1902 /Filter /FlateDecode >> stream xÚå]oÛ6ð½¿Â(PTbF¢H}èKÛu@» Í[W¬ŠEÛZdÉ‘äù÷»ãeÉVtØ€ ƒ|<÷}G3~Á,õgqŠT%³åö™ÏØ›gC X (Þ\=;¯ƒYà‹ÔOƒÙÕjÈâ*Ÿ}ö´œ/d*ÃÐ{»2Õº¨Ì|†Êû&ñ?ô³2©–fþåê—g?\õgi))N¤‰å,…â°4Q¢D*’@_h5_èHzó0ðê¦ËÖæçªí²²|[o·Y•£(ÇzâA,¢0$FŸLׂJyÝÆ°Ëº £júÿj¶¦Y›—´º›/o3¼b9—±Ç´³Ù·&ï.H&Ç6%ÞÍ\käíÏÎ:‚*s¼ýìžxfÄËÑì«Ü4¨¥U+èjÕúÑTx ò€¿š\tâÖ HަB-Y( f‰H£H¡ÀÚg ©„·µ©ººm½5¯^Ùã‚D$2…3}¡">óYeû²»¸YX7੽×ô÷›¯}‚vä¦ôÂ##âs1éÊi~ÏÏ÷ms~]Tçä"Â.U½¬Ëš¥xÑ>?:páä—}C-k„Æ© q†ÁiÉþ65ƒ¿ªgY\Ÿ3ë ­Æ¯«ƒÎÑ¿¥ˆ E"Ö$Ç›{x9)v†«BÒF4à¿Ía™5Ev]ÂÐéUuGˆÖ¸m[“UEµ&4‡5@™ G>h"{WØ´CâeWÔÕëCÞØ¯‘ëÔ 5÷¿^aˆûƒdÅ0Yp¹¡3<„1(ÔÆÜî‹Æäb¾P*ô>Ös¢ÚÀípLa&Õû*§e‡%ÁÜv áŒödGä9t‹’XÍ"ˆ«Î‹vÒwŽŠT'RËï®Ì–¤ªr¶ùƒ¿ÖD=ÞÚ[” ǸHû£¢A%ZS‰¾Äjcvo7Y3©¿iXߪ”÷_2ùIBØýQ<Ü%"–±3ß¶A ™É£t"4t&u¹ybëèd𠙤D}…“±M 0U¹ç%ZTÆs<ÜÒbœ6ˆÉ È´…ÎÙÒ¶nìùÐüñnSšH FS{AÌ5gb—}K¶´cAÉxš7¤E@\«âvoa & Ti0\ZúˆìðCOM„„¸³R·EW7÷ó$„¦¾J!{š-Ä  ”‡™¥^Ñ1Ëýì -1ƒ2B|€ø:åÁP%Z}²ü>å?=Œ‡—Ä”ò¸šÌYöÁ3t$B¨Ìàü©G€©¬­Uêq‘²öSRò€¡dÀI‰8 !üwUagg„ÑDøÏ¡R­1 š ?Lª!}_H•~—©™5roÁ©t…•=ÑéA¾O¾Wèû8ð½ŸY›{”¶ÞÓ¾ù²“ôÁNq4¶S^€â!“v„ËJœ"N2„|B ÙA( ¦„îml÷]—¾ëDÒ•òcŽŒÊ*mDrÍÏ æÂ )pN ¸…$+Íh#UpÁbš×{jžPCo÷Ø6¸‹(Ê. ©›Ü4ãÒ Ót½Ýe-—øê´Ûeºå“Kp4*Á°?è=öôRìvÀ£ýÇÊqÀ€Ý'h-uùÐqO-ÇI $N¥ÃrüŽý¥Ü•á_ f¢Žµ,²’0,ÝFo)™äš[à~Ç0øc_ÝDÙØ}æ8ÀÐUsšüÔ{_œÒ€‹ueòëp†I¡û*¬¬i]¦5µ{ÛÀe‘sv`®(Ó–3S÷F{«¦Þ"  ÓÞT7ôŽ¬Ã¬‰!š¯6óËl".»v(S;ußh3dýmNY³$„YC·âö3áö4>Hk›ä„ã•¡íèΦ8ÅBÆaßùëÝý)|:Ÿ²¨n&g0ŸcÝ ~¸bŽ«.„ÿA;“ݪ`»_-¢¨'ýdNnÏ0S qb>®ÇÀÀ~Ü Õb@foÑ‘?’þˆ™=t3iwhÒ‰…·LÊ4VwÌUEPpG\L±KDõÆýüÎú›n 1çF •æØ¥¥K(µlA„ÛQçùræÙµ™’0Á­½:ÿ„ÂC—I[ÿ‡>Ô¬ø7G´8PM<±²çMÖ}°óÃò¯ÓaýõÿâÃòñ§5œvSå.†´ ±–Fß”.øß9âK;Ÿ¦¡÷SÆ;.°*d¶zÝØÍk&9nhá䲋éa&ìPå†2¼7»í¤7µH‚d0ÔØ°»#Ð_ip‘•Ðþ Ÿ»ªŽ:…‰Ž£®ª«Üª> endobj 393 0 obj << /Type /Annot /Border [0 0 0] /Rect [356.515 311.694 522 322.603] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Disabling and the file repository) >> >> endobj 401 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 298.543 227.697 309.452] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Disabling and the file repository) >> >> endobj 397 0 obj << /D [395 0 R /XYZ 90 720 null] >> endobj 398 0 obj << /D [395 0 R /XYZ 90 720 null] >> endobj 399 0 obj << /D [395 0 R /XYZ 90 491.777 null] >> endobj 400 0 obj << /D [395 0 R /XYZ 90 384.33 null] >> endobj 402 0 obj << /D [395 0 R /XYZ 90 289.427 null] >> endobj 403 0 obj << /D [395 0 R /XYZ 90 194.72 null] >> endobj 394 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F52 20 0 R /F67 34 0 R /F60 10 0 R >> /ProcSet [ /PDF /Text ] >> endobj 406 0 obj << /Length 1941 /Filter /FlateDecode >> stream xÚµXKoÜ6¾çWlSÕYY¢ÞriÚ.4H ôÐ)-qׂõØ’R÷×w^Òjk9q…É™á<¾™u¸ à/ÜÁ&‹"¿ˆóMÙ> „{û,jv‹?\=»ø9 7aàAn®öKWÕæwïõ>ÆnwQyñËí.Žïõ^L·U¹7ð†5{cMWšíN%y‘{I´ýóê—g?]ͺ¥¾`žx`]nr¿HÓ Uî«0Þ¤yì‡QÌþhözl†··‡7°3Q‰÷Š?IÀ”=¶3+DË@ã^§,ãÝÛ7—tÓ¼îÛVwÕ#rž_ŒÎ^\×ÝÅý(wrVNìÌùòž¿5KçÅwîùCkÄ@æ|ËÛW7µcê®ÑcMÛ%³ÄÊMWAjãN6óàµá$ÿ¡ D'xâiøŸ±4ÿëýÐÖ‡›ÉkÒ'›•Õn¨KûY‰°pŽñÓ^†¯šfzÆn×õàe÷˜å»RTÙÔå-TŠ{ù™Ç § ×S8—N:í‹´éÈAÛêôø~Ï߯ººï|ÒXø1TË™\ßšðºnÍÙ•WÁËÀ'”íñÕ¤I—îŠM öâçLmÂÈ3°*wWå.Nü4+Xx#ð“D¤Ê{_n£Ð»1ÕØˆ„D-A.9ø„f…+å<$iœÇ‰8oê.> oÀ* >D ‹O³¥ø0¹Kêéåe£Á+¥±¯R5]˜‚ü_¬Ü)À!U@ž…)<@ 鷀ƙ‘‚Ç“Ìro>™²ZcòÎÖbôcy£3R1` s* !ºíysÀˆÐ©Wr†ÁQd =íØuuwàEO°‚µ»éG+r&ùÃá4/”'ª0‘œ’óØjßøþgC¼ðÔW†øÑ0D¡DS2–͘¡²Ü+ñY*˼kr‘a®ù4 bV¼…ŽAn«o·§3øh"Ý—à>¾ÖöVNô{磯RPmD*%n»#ë.ë?‚0†z¹VNB6t‡º33”q,>–tÁL5¼œÄÊ#ôŠ‹‚$AàÝÙz x¡k6ÚØÛ$…f!l‚ øJe5<Õ ­GÙG æ:s:ëà}`t6ö{·35”EZXãúfDðÀ\RœÉð=ŽÝ‘y½3Í=󚺭JpXPšÂ}õQâë–4F$IDK=:9ÂÖ£‹Æ¡ß•½µ¦Ñ'øÉH¡â8ôèfèÙÇ0Ú’´Û_Hc¡õÞËÒMR¤ ŸŠ؈Ûà°4ÅþEfcôbœ†syÙ±¥·Ó5-Ûì6= dâ’-ÓÍ®ÎìžÌþ{¬-¥vžp® ÁÙ L"vghÎý¿S&‚­ªˆ½;3¾Un!d\°"±–­ ˆ& ʈT‘©ÈGS‰˜ ä2¶KwkÞ× ½¹cb}ðk–f\hqE3¬ 9MBÖ„x†Íþۤ¹w=Ê©ò.¢%µšÔÞË Þw”9ÈÀñã÷£E÷= б×ôºbÖµn4ŒkQ\R”p¦¡–Ñ×÷Û<ö¸‘ψ°@Ï_Ù”(K%ŒH NÈs‰kЉáF‚T-Û”H`Œó©O§©Ý€Ðž§ìä;ÍtQ ojg´àAFŽ"‘d>Ä6qëÇ´øUAMÍÊ—U4w+ä†{ÏË%XÐeL—lJŒ·Üã/ˆ¥Ò­˜©…©ù³·9LI$¦w>v°œc£)N˜yäùk“N|ÐÌ“l1¥ÌD„;lPCä%ê;ŽÃS¤÷˜)æ’®¬²XOoœ’V—Q:ÍQ³·€ãÌÀÄÜ­h[¢J#Q·ðVœÆˆœ»›šóŒ—ÔÃPÐ|½ÇÝ»Ž“"bpý±Urx¬ewže;)kiv´=¯•Ie*I°Ïà&µHMU_S)ÀÁÙŒ“ î\Aƒ{z„Ë<èQƒ®×=T Ë_‘›.+“ÔÚ<ä~fó(J7×&V˜çUúÅ)8Ì~±¯_IáÁì1®Ù‘È™vˆºf¸#šÛü»cÍ®0…Q:šGé¹ß­ÍÒÉò¥4 ÞåÀ*ƒyÙ±‡PZ¥ä7–£aÆáž¹Ç$èG^”=¸¾2r ¦J=¥"?9kȧÁsÙ† ê–¤•IxE,¹aÏ{ó\EËæ«ùó×ä…ï¥']½p‚wçTÚ¸wzÀz5á´kÎdžd0×up,ºÕ¡‰í ®q†Y2w†D ÎÜ2 Ç>ü:#§ë½|¥‰˜OÐÍ“,ÀæßIgšÎI;3œtõÜUtÝ9æàP!æ‹ë#ˆ4¦@’¸e YIË~eΩæ¤,—Åu–™YFÿçš‹‹BûBZ«¹CiÛQ*"©PZÌö04šÊçQäŠí §Ÿ{³Ñélt(Cˆ &dŸŸ5Õ&‹üŒ ˜Ãü,Õg±-_b›ZŶ÷õ?ækaî<ÕШÙÿèR…ŸŸ~…O˜†ÿ¨ü†ô|  endstream endobj 405 0 obj << /Type /Page /Contents 406 0 R /Resources 404 0 R /MediaBox [0 0 612 792] /Parent 412 0 R >> endobj 407 0 obj << /D [405 0 R /XYZ 90 720 null] >> endobj 408 0 obj << /D [405 0 R /XYZ 90 496.488 null] >> endobj 409 0 obj << /D [405 0 R /XYZ 90 282.661 null] >> endobj 410 0 obj << /D [405 0 R /XYZ 90 213.969 null] >> endobj 411 0 obj << /D [405 0 R /XYZ 90 107.945 null] >> endobj 404 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R /F52 20 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 415 0 obj << /Length 1884 /Filter /FlateDecode >> stream xÚX_oÛF ϧ0ú¹¨•;$KòÐ+Ð=l °‡mè.Ò9*Kštjš|úñŸd;“Ñnȃ)äñÈyÑ+z•«ÕÖ˜0³Uq¸RÂý|¥…Ú€ÀæD⇻«›‰^iæ*׫»Ý©Š»rõ{ÄëM”GÆïw®y¨·Þ_"ü5Aïv®wMáÖÞýtõãÝl+‰¢o8ƒßðF«VãUšÅ¡61»t·¯0›àË:IÛWö¾vÌá•8×:R®ä…ûu”OLû½c)[øªmÐs0NóP§è*™ìÝßcÕƒ.=ó1NÂLg“d¸ÞÄÛ$øèÙTéþP:nœ8¼k{¶\ƒ ìǽù't³E¨m†ªt=Z]m¢(á"VmB°5ß‚¤Nàt؇Út*Çî¡jª*¼2TϲĎËò÷_Ó ¯ù½®ÆäÁÇ3ÎÁÆÒµíEeí‚È‹#v8ó®j˜O¶@ ̽AN~ žTÉ5Ÿñ±ªkÊ@ íïülƒÏÌò c«`pŽyÕNÖöÂàÃ0í¾Vƒà`©ÖÁ/"Y´c?8ð%VfyÛÁNù3é`ò~œˆùPàÐy–ÏL j‡ö…Wt çmÁ©8A$&?âTQ~#ÏÖ¨©ó  ¥ˆ<تA?YÙ´“ÊÛÅ=„!‹"ºße‹@Oû†ƒ­kÈErÃïAÃù¨E¸ñzGá e¥Î²wpßPºS$^VÖ6 Mj¦Ê² 8è¹í¸xN(#ªzƒÕ?Œ®Ä¬€ ÇÜÒíìX{þ`ȨGÉRØÌ¥`ŒÄè(4ãŠ1³­”âm (ÞA.‘ë[8¨ øŽ®oÄ÷M‡Qšó ÃT˜šõ&I£à×}»6:x|G4,E %Ï(5èȶ¬¶Í[6Z%*¸}Vl¢XIº=ôíi/ ]Æ€²"šôÒu€i˜ÜF§aœggh ˜WØqp}Ä7ø"˜‚ß®o©Lʱ•Òy[ÕÒðÕŽ¾ƒ‹¡šÂÏÿ <%€Môdö ]Ⱦ¯N4ÊÎQTsC9MÃÎöX%Š â/'µB‡ ¿¿òWÕ@®,»€ŒrìÉ,íß1«°¨R(Ž m›~Lïš’J÷4õS”„lºêe•übÔ¡Ž][‹(¹¯ 8;‹еœ·MÉh$ëýþX'—BtOEsacN€ewü[WÞ×¢m:fï±O×+{îE¶Y®µT-±T Ä èà}Û­MA! F¯²0OÓDY˜aŸ U"Õ2ж¢íž¸HNk…¨Îúý'ˆÏ§dac„*gÉ µ`Â,IÁZæ‰xL8j ÕB[ZES8¶ =Õ¤TMùé!š ë¦dŠòy°(™ÍÍ}hOýêKEieg6ü‚EJ©·¤fËÚ€}ÀÜÚe…J'ÔaH7–*·Ìx¨¾P£i¸¤ò]œ ¾…9ŒšÌ÷{»9 ŸžÂÛ=]4sã|qÓÙaxüÆB¹%Ýg%ƒKþ©s·÷ÀêŸæ4RaœêU}‹CsÖPµ ó.z¾=Ùû š4h ¡Ê3râgÕøj±UE&Œ¶çêçÖÓ-¦ø sFjÐI¡§F}|¾É\ ¼³~ìeç~zÞ N°ÄÖÌ€1ïê‰ûõ*Êd¸ñàd/># ìz&KǘŽs’ü_áÅØ6:y¨²ÓFåÁƒkÐì¸(øMdËvÀ¶¢ç‚Iå¹ øñÓ“fé—²_,³Çò[Kwµ-dûcÕ ¢ò<ÒèkøMª¦—•ìÂçó€Õ<èQ‡œ_tQ®4Ž¿Ô¦ þÛ…&-fúŠ‚ª‚ÇéŇ+ ˜Èè„t%¼v( uXyP GúždÞ‰,]ôV.šÁGúBÿi9÷gj|H˩Å^ä‡ðò(w2þߺ¿¯í¿‹”+gçjÛ ®¼¦^ýš$ß endstream endobj 414 0 obj << /Type /Page /Contents 415 0 R /Resources 413 0 R /MediaBox [0 0 612 792] /Parent 412 0 R >> endobj 416 0 obj << /D [414 0 R /XYZ 90 720 null] >> endobj 417 0 obj << /D [414 0 R /XYZ 90 620.086 null] >> endobj 418 0 obj << /D [414 0 R /XYZ 90 538.731 null] >> endobj 413 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F72 4 0 R /F67 34 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 423 0 obj << /Length 2400 /Filter /FlateDecode >> stream xÚµYKo举ϯèC€¨iZõ\`›Ù âlä2»@h‰rÖ££ÇÌ4öϧŠU”ÔÝ2ì=,²H‹õøªÈv>ü»ÜߥRŠ<ÊvEóÁgêˇ€[˜pXÍøÛㇻ¿ÇÁ.ðEîçÁî±Z³x,w_½ÏGuu¿?H)½è§ý!Šbïs¥žu»3o¤^Wº×m¡÷‡0ÎòÌ‹ãýïÿüðëã¼w†o‡3n¤“Á.y’D(\Jûé.É"Ȉ$¼Ócq÷ÜwÓiüØ÷J=ŒŸîÆæt÷T«=°½ñ|ÒŸžL«ú3L¥kutù)@A¯µp2'rws‘ŬŠûN—‡^×—¨0¼±#’B]|Ã)‰¤œjS˜‘&Ö8FO¦}þ:ó}¯¨tûlZ͆ajôÀljtŒíç7?ˆjMƒG5ñɲԺ%z̵ÛÜÊ¢Y`SÑŒ¶Ã³Âá"Pq_)‚˜Î¦ŠqR5NÁ@ )r8edé_¨{ªUÁÂüA#´×GÂùpàö™¦8Š¢îrXÆçU§“êÙ¡jÞ͹¨¬ªFý›ù¬<óD«ÜŽ!u¿íãØS5˜Ïíó‰:r1Q†!m—Ù]ˆ Ú’ã‘)§¾kÌ ï@W¦k‰†'¡fí`À-4/*»Öj$ò½ûÊñq“¿[ãôÌ¶íÆ« 5àQ%:îQ·ËèÆ)ª®ß~ß *\¹“s žÝ¬›ê’ºÃhêššì?Ô1-}kë‘Øªºžú‡.&>2tI1ÐXxcŸÙá/ö­¤öø½ŒYŽÇ}à]NWp©ûØDgº@¢àÇŠßazô'œ:h2í›VˆBáYAqŸ†;ØÏ‡ÀǸ‡ÝÃT G< Œ/’ # ½ÁŒú®B©H[Lõ¸?3|„køˆ|Æ`óÂå°‘ÿ‰0è7+Z¤ëÕI&Ò0Yæu­jôÖ>q(2ž üð0±¼ŒðJ¡È J^ùšI.ò,¿âQ“Høa\Èœ•òhc"ÊÕ4kÔâC”AY·8h@»Õ (ZQ7W·fö³âÚ–udlœÑ-º‰{dfƒŽ\¼j4 a&ÁÙVÖíc>ÒL;ŒÊf_$<"ýL1IäBµD-5žÖÆ-ôubVØÂt’¢è+M¯‹±ÃDŠT„gü:0±¦¿HÚa&24¿HÁU)cÿõÞB½c7Œ¶Ww$¢-bF+÷ùnÆc7¡`ï#%a«nì£døLžléGn  °•²‡IÑg8±ú~¢‚‰ /¸F Mv[h¹¯r2´å™·ASÃ÷…ºóì·X·¸Tì pÃàÆÆäRŒÒ(Où~¤½Ž4F––äE©ExäÓœl·ëG›¥ˆ5+jeà%Àµã>ÐÉÛp^ëò&B.F„ÕÌ4̱²™Ã¡ Gr ;f¸k8·íç†è…ÝõžY(â4Y£çÖVaˆM7ËfêÌʪZÒTG„UÑØàg©5+áJϱå:õ@p“qTû¬ÛÎûLz›ÙÇbd'[I(Á$$½‡sº/è$T¦z;ûpȹuvÍM  ¹ŸôLÛÆð0ÚdÎtàašxîkã E½ 2ö±@¢aˆ!ÜæÉ]ßë=´-m[nÝ×A÷\lñÚP‡„d2ýEÿ†@«6]0NEFYùèãž0êºêe.ÜB®*ʹ ŠŸêºÈÏ ˆŸK|jFSKÓ4V—-\°o¡&ôúÙ #•–ØG<°lÌë—®Q–í/Êíðz2óF+ÿòå +¶0þ¡kôhrnW‰J¾•œ„œ BxQƒ„ëÕ2…Á®'½V/LëÚÖÉŒsÔ„×5aJWÁd0|¤6Ü h9€Õ× C¦Z`±×–›BcQyÈÀõ÷J9°û"þ\–àx<óc³‡[Ï'’ D C€¿¿xL)nëÅñdZºwéØÐ*tùwToY ÍÙßÁ7jÔç«õcö'K·‹ÀG}péÆu›M ùÓÁ!{•Ä :Béh°¤ÛÊ0¿¢ÐÌꢘZeˆ6¸˜”¯ )gž[ƒd ¤p‰E=?ší²vEa-x—|dÓ.†×Á´‡Æ´Ó¨‡­-s0Gþs䈔oUÒø®æHVæðéš_ÎL>]èñ;è‘ GžÛ¨¦A-O Øãb«CCÌØ‹”uÝqñ¢a颉»UïDY–ºS, XÿÕW çù€ýG"ŠOW8¸ d*Q­g}œÔ³ÞÚ1Hä\Qý?N°¶`ƒˆÁv+ån<ó¹Y76¸”ëš'ä­`—¾ãxí9ÝÝA“f#ÀÊ,¸„[šLo‰o]”¡ŒÌç2²?WŸ ìqWòøíàŽ±~½)²0§.¶ë‰»˜Ž£$ç§¥e‚ ~¤Ø˜CÁ[À÷övÍãn·Ú ·áâACV£½Ã¤\‚yü¼ ABŠ€] üÛèæªCÿpy‚n$î.®ß¦ìUJ+ž‘Û'>ü¢pƒ-Ü!mÓû‘¥—ºRø6c;+}a×–/ö h†õ„,Ü_ô2÷uYWÓk_æýg³¾L¥È’ùÆñÓfY¹¾Øü•¥þìà’*Ê4q./‹<¸½aF7º#÷ü1BõÇ·ÞØ¹ŽÒ¥ƒ=Ò*²º£&Ý’ãå c;}÷âq>ŽÚõøô‡¸UõdìuüÃEéBçðÂ,Ílƒ3þ8±š±ýã„›@‘ª‹¥L‹D$$ã×{+ß<Ô-¯D=Ͱ¸€OÛ ²k©ÃÜ) ÃJ° Ls³ÞÿšÙ‚iø‹C,²ù²|Ydù1]IÏ'S@Y{&’r/¿<¥èš0ámÕîü0‚ï$Ôú¸?ã¿ÇjóÂ70¢»Ú7Ówm³¼·ÂÀÕÓïf˜7W1dy¸ §¿ÿ¬êµÇ endstream endobj 422 0 obj << /Type /Page /Contents 423 0 R /Resources 421 0 R /MediaBox [0 0 612 792] /Parent 412 0 R /Annots [ 419 0 R 420 0 R ] >> endobj 419 0 obj << /Type /Annot /Border [0 0 0] /Rect [153.152 206.429 397.515 217.338] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Splaying host times) >> >> endobj 420 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 109.024 290.788 119.933] /Subtype /Link /A << /S /GoTo /D (Iteration over lists) >> >> endobj 424 0 obj << /D [422 0 R /XYZ 90 720 null] >> endobj 425 0 obj << /D [422 0 R /XYZ 90 587.328 null] >> endobj 426 0 obj << /D [422 0 R /XYZ 90 420.968 null] >> endobj 427 0 obj << /D [422 0 R /XYZ 90 323.866 null] >> endobj 428 0 obj << /D [422 0 R /XYZ 90 265.914 null] >> endobj 429 0 obj << /D [422 0 R /XYZ 90 194.204 null] >> endobj 421 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R /F52 20 0 R /F67 34 0 R /F60 10 0 R >> /ProcSet [ /PDF /Text ] >> endobj 432 0 obj << /Length 1894 /Filter /FlateDecode >> stream xÚXÝoÛ6ï_a(&µ¢ï{غèÒ‡¤ØÃ6`ŒLÛZ$Ñ%©dþïwÇ;*²£¤C€ˆ<Çãý~<:^Eð¯êhU¦iXgÕªéßD,½sk ›™ÆÏ·o®>åñ*ŽÂ:ªãÕínnâv»ú#È‹õ&©“4 >îä°o¹Þ¤i<$øM-wRË¡‘ë¿n{óëí´Vž$ßq5žyS&«8 #p‡½)ª,ŒÓŒ¼f–Ñz“Ips’@Áÿ8PÝ/­–Uº•}¹Üì<.Ã"MÉÒO0«Š‚®5[``G±Ý¶¶UƒèHn`•¤ÂU’V!áv¶–›µSšFš§(Ø*’yv qÚÄA¨òàó@£ö ô†×1Ä•œ}蹎yãuüÅY'ÑÓ&Ý®Ò0†­º]™ƒ»-žL4Jké½X肯ü6Þ{êFjCM†}¢¥±mNÆÊœÎ²4øý ‡g³:eÐKË‹d«©)šFÃ\°n ÎrëgaðvqìF§Q %l”A/ÚŽD³ó¨è<@èÏãDÚmÇwNMR§A?>epm¹¥:=˜HáåŪ<¤T‚)èžx=y„…õc. < n$/':£>p*&—©ˆÛ¥Ýþ";iåµ¾ÀZúSÛ-çoUa—0ÙÍz¿d¸‹bÒ˜ì~5¯š´UµŸ.™àTa×Ð(Â,­Iõæ¨ÎA€Îƒéóg”GÔºzúÊ îU£ÕàþYqg–G…ýGù1°“;礰ɢ0ɳÕ&ÉÂ$ªçÌ33|½Ætü )<+ºî£ê{x…˜an¤5Ö’r Ov8i×*”PÒÒÔ9 —d÷ë<Ä^N¦„¥Iƒtp¾01eéÌžô °‹­›¥y–wÌmsaÕ%LÁ`Dóù¦ñª ë¢È0 $–S.=éƒáÏç[>Û·W£ÑWwípu¼ß÷{MÒwæí垇תò‚Ó‰×ü¡•ãVwbì,’E^x²ùúB·â®“$¡‘$”%‘~Z/Å@ì–Ç}l‰Ác:Ï ¥-0)7x ü8/B £»‰3¸¶²ó_¹%b›±N4?O×݉.ÂC©å·`µe½VVN¼Jo#ÈX[hÈàØío[ AxÏL|¡±€ó,‰Â<+<¼[$Œ×:Û:ùŽåÀ± í5óÁ9»žxuÑ Ý4³¡Ë,¦QEÚwîå©SHÃ%~ˆ–˜!AfH{ͱmZ5šé}&8ävJ˜˜¦]»iˈ{ENß§ßAA’©žƒiš¼‚š÷‰ßîÕ8 @‡KX(`ÃjÉwJYÏL³|`…½„{F¸¤5AÂG ½ÐŒšÉL6/hÐh#ó2fu‘«qªà–ü†Ò¦o÷WP÷ #U̬êj!®˜¶pw5¬zð‰ÀzT“°é©øRPˆŠÎëµÚkÑ{W>º«ì,–NÌ ®}$ÜîD^lYŒ¥Ø@Í‹ê/‡à;#¬ZW[H:/ ŽœhÙ¸;Ȇ Í\`D°ϾÎÀHõ ‰ÅMpýòž±ÓnOŒ5M’F‰«4øÿØIŸ°srÅ(4Ķ_DNÖU|Ž8*Ô~7ê•y“zò¡‚u¡ ‡:v§eWþÄW/_7E–yzµÛ×è\ZRéïV:{œ0`jÔÔ£´óê};KÊûú»š_ЙXÓLüðè`ò¯¢ xA¼Œ3ëJÓµ—TĈü®MŠàóŽk—)]ia¼6N}pó§B(Ϫut ºý$+Ã*ñÑ߈Åò2¡&~*Z!$õtG9@9¿,}MÛy®¦Ñè%8Â5”­÷ÌoƒJ‚n”!E*Éë0)/BÅ!†ä§oæÀÝ ëDÍÐç¨ùrÙ­™P Ý‹{~$Aú7º=ZCkM‡r™QIŸ'†!er–a§å/¾¨õ¨[kñ‰å†ééÄCÖ/@O xrÐ3EÚSczÂ8c‡Ö“v§lx1±w“` ¢šŸEQEg%&úÉh|EŠ=±³RÓä Ègt7 îUQÔ™êí5_òÐãÒtÄÀß Ÿ0L[+giV¢=ãÆ9¡¸<ØÑáB8O>&> endobj 433 0 obj << /D [431 0 R /XYZ 90 720 null] >> endobj 434 0 obj << /D [431 0 R /XYZ 90 720 null] >> endobj 435 0 obj << /D [431 0 R /XYZ 90 598.921 null] >> endobj 436 0 obj << /D [431 0 R /XYZ 90 487.742 null] >> endobj 437 0 obj << /D [431 0 R /XYZ 90 393.296 null] >> endobj 438 0 obj << /D [431 0 R /XYZ 90 269.261 null] >> endobj 439 0 obj << /D [431 0 R /XYZ 90 109.091 null] >> endobj 430 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R /F67 34 0 R /F53 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 444 0 obj << /Length 1810 /Filter /FlateDecode >> stream xÚYÓFø_¡Ju$b<öøBêÃv»TTÀJ%åP;ëL ©–mËïwMâ,æPÆó]óÍwOÔ"€ŸZäÁ""?×Ù¢¨}ÿ@É× VŠŸ×?ÕB~äj±ÞNE¬7‹7ÞåÞÛ-WQyúÉr¥uì]nÍÎ6Ë0óFtvk;Ûv¹ ã,ϼ8]¾[ÿöàj}<;Ão(‡Ÿi©EæçI¢Q9f~¨ô"I#?I5køê®¯ÚÝSS”U9Ü-ALìýÄËÛ PÇO“t"&Ë}åp(ño'ž§#_‘#iЉÎM¶Rqâ+ʇ‰/f[ïËžMóaÇžéJsSY†˜ *ØaO@íõt ŠFhß;ÆVöîl壴gý?£o˜úyš‚ÚWAþ}桯ç׿þùüúòâ¹:bæ¯z<áxÓ×Ë ¯TnärÝn¬%6z²3ºªÈÏ⌮Ԣ+ªñÇ««ß‘¬¾‚“urBýrqõâúåR°¤ðU¬ú*6ü*6ú‚R„Ô|Á4Äk9Ú•‘È" Ýâ§ Ø8 ½¡¬Á÷Êû§mÄ>q8µµŽý<ƒ´PÚ×î@ä!ú/FùD@ Œ±vÑ­Š½éLAÉŒlGY3g«Pùq¤¿ù!ÄCÆ dâGÑ1ö-Fi0Ñw牀L\ /UÙüÕny-–aê´FP?te³ÆÛ}Y`¤íy»±o¥ÝywˆiGâS^ÕBiJ½ÂT'Ýœõ)•ÈйÖ‘*½l»ÚTäN"a“äÞmYU n"Xcí†a†—”¥ëÒ™ãØ?ÐÞÍ80¼oYÄ÷Bº‡r*‚:aë@G× $žéËÅæDõm‹U;‹Q\v%ó6¼=9wTPVqž{/®ÖÂÖ`JgÚ»˜ÕRä¼§ûn„bgʆ:(ídOâ‰dmm³+²6 t½^øZ‚sM3ký®­ÁEœ¥ƒKü`k°V’(ïÙ–±†—ºìk3p¼3„’Ö,˜}¿9c¹EbÓ-•×𠔜JH¼˜‰Üb7r8_ 9Eµ fØj6š­6è Y:}Ñ6èÓÝHÈs±m~Šw<2PZ" ¶Ö Bžñ5Úî}Ï[ OA¾ '6„}Þø!±†Í¼[cи (¸+œ~ÇßvS6!GTH¹YY2pî`‡N §ÝË6-»_ÔÉŒC !=ëšÛrØól0I1s^q5˜Ž*…ÎCÃÐM æBr2::ªÕ„lf¸½/Œ$H¯²mdÂõUʺ¼A ¡EÀ¥_ÿî(Åð zù=}£5ÕwfÔuTßÐ÷¾0ÒWºU¨2_éTZo>i½‘J°ÙB€V£l©xªÄ¥ÊývŸ)?€Y,¸—83_ç~˜'br6ʽáòÁSP†¨îJÆØ£VÇY ýxÓå0ŠRÒêJ4Æ~Än‡Ÿ·(˰@˜:1¢Ü{6¸þ“rÓä±ÁnØnÙµ2tG“f›’ð¥Ãi‚ÀŽ'³C7MyÓ1¶ßÛª*ںƣŸrQèç`ÉU¦ Å‘m±oyûá_gôO ø—Ú”•£€:`6õ§‡³£f¢üåGÚÓé°™ò°¹Æ†#®Çaæ ?« šBȳj-Ôó|ë¡ù!¿Òü,83è6vkÆjà ^¼e#3K‰ž?®90ZMÃÉÚ3 ”µÁµ·@²Á$ "×p&t·¹V¨÷m'çRðe“<; v '…5Œ.'3ê^4e‹„æcé0D8CººŽ2(Çm‡æ!Çw/SpæÂ9”âF°‘1.r"ÐÁx{(W"ÃͼɀñóÎÂRÂ<õ’€×“5Dü *ˆ+¼ÿa ¥«àÖe9~;¡8¹þQødéºñ ¢° ”Í9ýh‹‘éoPÁŸk#â`hÜ ÚÃThz61¤ÓÀ×ÕÇCÙÙ‹í@#D”dœæH3™ú`kxaShòoÇä´Îþ=‚L!"o"öü¦„šŸP`¼-?¸w>Õ³™ÔΟóœÕgõëeALÝ`uôÚÞ~gj¿¤þŽ¿JâÄ×Yæê}Û<–d¦/ù®tü;¥…¢ͽ÷á5ªû/JlÿzÕ̤ endstream endobj 443 0 obj << /Type /Page /Contents 444 0 R /Resources 442 0 R /MediaBox [0 0 612 792] /Parent 412 0 R /Annots [ 440 0 R ] >> endobj 440 0 obj << /Type /Annot /Border [0 0 0] /Rect [176.364 356.725 323.091 367.634] /Subtype /Link /A << /S /GoTo /D (editfiles) >> >> endobj 445 0 obj << /D [443 0 R /XYZ 90 720 null] >> endobj 446 0 obj << /D [443 0 R /XYZ 90 509.512 null] >> endobj 447 0 obj << /D [443 0 R /XYZ 90 275.766 null] >> endobj 448 0 obj << /D [443 0 R /XYZ 90 131.079 null] >> endobj 442 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F67 34 0 R /F72 4 0 R /F52 20 0 R /F53 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 453 0 obj << /Length 1736 /Filter /FlateDecode >> stream xÚÅXKoÛF¾ûWèH!Í}ñ —65Mq›C’-­,"×]RÜ_ß™!MJt Þåìp8;ûÍ7³«þĪLW¹RI©‹Õæp•²ôÛ•àY ñDãÇÛ«ë#V"MÊ´«ÛÝÔÄívõ92Å:–¥T*úigÛûºµëX)=JUäíÎzÛnìúëí/W?ߎß2R¾â j¼âH5¬êU–™$Ï ¹t»¯;øxžGk“E•¯«»Æ’¤;Õýf-‹hoYǵ4ö{VqÇþáØã<‹û¸–ydz<ía/w(y"ÁæyÏ𦷌"r¾gãøzYÿÔïëöžduOãv-"ôÁÎ*´™X¨DÀ>Ãf¶GOo¦*ªhðÇ–&5÷ÞV=M·¶¯ê&YÇÎàƒó‡ªižhɵÃìèïm‹ŽñKŒ…ˆºê>u=›ÆV<µÞ;ÏË•·4yç‚!»}ƒ’2úh/N “©2Ñ™ÆS„ó ò3ÔM4–Q7(„¨|´›¾''U¤ÐÔ‚>¿ow°í¯èŽÌ¢Økç~Im’2ϧÎ- pÐzÅÃscÁM<-@‚îáÙm’é¨j®ëIfÿ<ÖÚO(XÞ;Eûèë›,Ÿù!u¢ó|Äñ£õw®cݹϱ* pÆÌçvKvA£(ÔhöqÉžÈ0Æ*w8Tí6nBzè,çÍw”Bg”Ap‰³mý%Šé"H0F8ö{8κ§®·šSˆkïÚÃh\˜$"Æ+$—‚­*5ßj°R¡[€-1Ãk¢xL ú>ŒœÌæál‚¨òx:lhx³u=Mº½C §öŸeEt».TäÈDgY©ßï ,„ó†i¤á¥6ì(å½ÐV:Û@N {Ⱥ{@TGD숑Utòuo»·ãáI™!Pw+ X“Âe–Í¡Ù4U×1]ß(1×.‹r8æ·o)¼;“’$ÀA²?zÀä&ú†/©Ii†yÀ±ˆN™SâÉ")›¼ QóCmiªqËç¹ô4õ¡ÅÇ7ô°@N²P‰Ê (G@#¢|¡­x¢¶DgÆÎ¸JM¹ %®‚2p@úýÊN2e©%ÊÒÀ.y&§Þ.PÖ õŠ·çÆ˜²ÂQä3>U" ÍDH3l%/á3}Z—XZH€Ẻ„÷b-’´`Ä~Ô/àq‰ÐL$¢©Åµ× 5Ñ&Ù¨‚L²à”X-Å õ"ôè¥:cìMÛ }ÑVè‹¶Bs[¡‡¶'HÖÇc^ƒhš×ð8tv(xî.ôEw’Öµñ®ê«æåöá„æ8ÐXr5T#ÍHUÇpÕ¡¾@sÕè©§º£÷IZF-‘< ˆéà Žht¡”(œOjIܺø>.„‰ÑãÁc†hƒù¿TùÒDf#âÓb…Pïô 3„™˜·Êå¢Ô‰„¾sʱÄÎϬBsÄ€ˆÆ“ Ëœí”qõ’˜Õ@Ìú æ—Sïf>£-ƒ­XeI–Š éœ>¸öw@ýMÝ ÏÏkXždŠ)åý#’YSlo=- âP0ƒ¦ãÑmàÏbړénž! f᩺£d:²!à Ý„ö?Óòg8ãà?dtCÂmíѯíIÏÖݬÊéBÊ Eظk(Mã§ôüS„¿d™°ŠÎŽýãƒsÍ»i"-Ñõcå¯;Ô½Þ@“þõÕ]7§' Z`7ùÌns-[GÎx¥Å[™·ß›>ÿŒh‘ÂD>­LZ¥ v뫦þËrõ ª‹5æ¸ %ÆÚm·äŽ02b¶ìϯ€ÏïMg 17¢XHgy‘ÎÈ/}k)™å˜ÌržÌ|³Â‘’Yr2Ëç §.pËY˳,–”­4{®’“PòUD~/ y]p^ÏïŽøøßÖ‡Tñ}u dF(©À)ô£Ó”ZðפMsÜw(ªy¡‰ûFë“d¸“ü öKè endstream endobj 452 0 obj << /Type /Page /Contents 453 0 R /Resources 451 0 R /MediaBox [0 0 612 792] /Parent 412 0 R /Annots [ 441 0 R 450 0 R ] >> endobj 441 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 636.736 245.977 647.645] /Subtype /Link /A << /S /GoTo /D (Inform) >> >> endobj 450 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.368 521.392 439.762 532.301] /Subtype /Link /A << /S /GoTo /D (Inform) >> >> endobj 454 0 obj << /D [452 0 R /XYZ 90 720 null] >> endobj 455 0 obj << /D [452 0 R /XYZ 90 510.195 null] >> endobj 456 0 obj << /D [452 0 R /XYZ 90 333.043 null] >> endobj 457 0 obj << /D [452 0 R /XYZ 90 257.749 null] >> endobj 458 0 obj << /D [452 0 R /XYZ 90 122.81 null] >> endobj 451 0 obj << /Font << /F51 5 0 R /F67 34 0 R /F31 21 0 R /F72 4 0 R /F53 19 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 461 0 obj << /Length 376 /Filter /FlateDecode >> stream xÚ…RMO„0½ï¯àØ& ¶´|yt£‰&ê…ăzèBYÈB») ñß;ÐbP¦‡ÎWç½7Sê8Ôˈ—0d<õŠnG\ô¼£Îò¡ÀßTÜ仫»ˆz”ɨ—WÛyé½¢C-.ƒ4ØgŒ!~}Î#t¨ÄI*¦h° #+i¤*$öÃ(ÍReø=ØÝæßØQþCn®øÃ. =Êô»8åeܲ“)Ã~‡èg £ž´zž”4¢ig¿% hÄŒÙ÷hˆb4ÔMo­‹0¢“V5¸k¸—ƒ«Ôî6˜¢4S´‡HLQQIuj”´ù©i[gͳjÖGSŠôèú½Ê¡S+vuè¥ùÀa‚¤qɩֽë¯à‘èfxx Be,  wQVj»¥—5qThcdô@J\•°×Yé™ì¤lvì×å+˜ÉÞšÇÑ5ìšS½ùV—´ŽžiÃÊ5©Ï ÿ Ũ`ý6_.Ö±‰ endstream endobj 460 0 obj << /Type /Page /Contents 461 0 R /Resources 459 0 R /MediaBox [0 0 612 792] /Parent 464 0 R >> endobj 462 0 obj << /D [460 0 R /XYZ 90 720 null] >> endobj 463 0 obj << /D [460 0 R /XYZ 90 720 null] >> endobj 459 0 obj << /Font << /F51 5 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 467 0 obj << /Length 258 /Filter /FlateDecode >> stream xÚ…‘=OÄ0 †÷þŠŒéÛéGV ÌÙCÕKîª;Z”ÿžôšž œ@l9ü¾¶©ô€Å"itËú—Båê±€œ‰ˆ qk‹›‡ (i”fý¶…ݱ'^«R A"~çݸFW "ÍßqŽÄƒó.¸±wå³},îíE«BüÇÌLürÓ -IטÝÔ­–@zq“R(EU#ïO]Œ.Ϊ?GH3‚‘€y{p™Â-…(5꟡?Úi’ 6+x,±åîócSØ-ËⲌnÌñ4tqùòS¸¦)oÚvíºÓÛëUuº0]™|¾ÀÙIˆÃ”UAj©¾3}¾™\¯óY^ª endstream endobj 466 0 obj << /Type /Page /Contents 467 0 R /Resources 465 0 R /MediaBox [0 0 612 792] /Parent 464 0 R >> endobj 468 0 obj << /D [466 0 R /XYZ 90 720 null] >> endobj 469 0 obj << /D [466 0 R /XYZ 90 720 null] >> endobj 465 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 472 0 obj << /Length 1003 /Filter /FlateDecode >> stream xÚ…VËŽë6 ÝÏWdW»–åç]ö¢]t][ Š­ÄêØ–+É™;ýú’¢œäNŒ)ñqHê?äðÇ]~h„Ⱥ²=ôóKoß^x”R0H,~:¾üøKÅ<Ϻ¼ã‡ãù1Äq8üƾŽrõÊ&©‚•_’´,+öõ,/jIŠ–yRXuVV-½JÒ¢j»–Õ<ùãøëËÏÇvUÿ“Zü'»¦8ð2e]Äìê¶Ì¸();‹$­ê‚õfMgû¹&(šw`¹—tVËE/«hZtÔ gpâÌáUÃ~Ïy9)Gú”Ô0åøÿŽ%+¨èr65F Ÿ‚ArΫ9bÈe ‡«–tãǘт`-ûF—gkf²³ê¢]Šu†ÂDÆ+ª ž)€ÖsÊ^1ae]ý© v ÑA…‚Àt’ÓÅXíÇ;gU׬G&Vö*íÍ2h¯Í/ßGÝ#ÀƒÊ…„Ø~³t¶ë !|.î± NuÄÖäÌ…†‘ÿ$=ðKÓ«äð*±÷Šôr¡ l¹uþ{`y×Á»M*úÂË©÷'q§n¹STMVÔ%är;kð$Šß™(îVY^Ôû3* àò=Úlbó"r6ÝhEŠÈ¡ÐŽ×вTÀTT¢yÒ¹R0–œÈS<À`Ê94'¨FíPâìï ß°eoÈ]Tib®¡Ó:ÁÃ{Ñ{ÐGê™´æü9œæò27›§ËÕÆRÔ°Ya¢={ýG Bù°YûM"ùÑù§0œ€UC]aÐVõžôvéw`7ÈÄ P`Þh,éC%YÇØ± ÊÚm¥1嬇ÀYIÄk{…*x L’8׈p‹¼JûtHuÜuróa›ÔÕ=PΗš/­’™žðƒdå[2¸÷Ú9æ¾,—˜HÀ›WïÈw‡Y­¢…qÃ¥Hšôòæž½Sp†Õ¿˜%¥Î‹9‰òqÆ8KÍ 7û ,Ü+ùœ6O–N)º¡G¡G¹{xð`W0jhçâ*Îâx•ãCÑ•å!-Ê<+º.î{¹ÅX5 Žf›’O ,FE²úm¬8ëµSø&:ºõxgÖ¸cjA5Æ„ÂR#\Šc´år‰¡C\¹"›A Ç¿Gvúœ²vü1ÌÒ ŽvªÀ>âi ÁßK|äNlÍoB™†Ú‘«mÍô™”¡Û( x´ ;:À¬Ò¾¸ •ã2€mt§êï” ‘c*k(Z]ÕâwHý”F;”¨Zj”šÇÆUÍ­‘ÌOvéÓÇ>îDr òÄËoñ¼Í³$† õ/ûï“:Ce endstream endobj 471 0 obj << /Type /Page /Contents 472 0 R /Resources 470 0 R /MediaBox [0 0 612 792] /Parent 464 0 R >> endobj 473 0 obj << /D [471 0 R /XYZ 90 720 null] >> endobj 174 0 obj << /D [471 0 R /XYZ 90 720 null] >> endobj 470 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F67 34 0 R /F52 20 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 476 0 obj << /Length 1431 /Filter /FlateDecode >> stream xÚÍXMœ6¾ï¯àÐ#u þÀ@¤\Z5‡HmUe•690`v¬<5Ìn¦¿¾¯1̬'6[E« <~Þ×ï7Æ^ØKC/¦¥,ñòú&ž>Üàán €íñÓíMð.ÂQ¦Ø»-§·…wçs²Ù’”Pêÿ\Šæ^6b³¥”ùÄ\©¯E)´hr±ùtûþæ—Û³¬ˆe â…6/E)'|ÔSÇÔjó1Ätô×™)P'=2$PÝ} ½Þ½÷BDÓÄ{ꑵÇGŒ˜u•÷áæ—Ȉ$ˆÆü…ÜÐ!7D8M=ÌâQò%¹¡qŠhOåRì% –³~§ö5O0ÂŒ[©¹:œÞ±Á;O°˜!llGÀmpµØ*k[‹ñ†¢˜=ê‹n îgÑȇ-²ÎÚNèm)+á`MŠáA¿’+ Ñvoô„¢ˆÆ£%›¬“ª¹F¾VÌöW«B,³Ô—{}-T=5B;DØÙb=ÌIia3Üku<,sö°µœYnlå"¥¥IŸ2Ý-X´é‚R~vÑ fô»,8ëÑ«ô> W(r…gPPfU+‚NÖàå¬vî‘¥6ئJhqP­ì”>¹öaÙNõÝ@ñˆüBj‘›U.9vÕÔãÐYÕí¦Œ!ƒÓé^Õ.£Ä}ª@»]5V¥KâQÏ·šïEþ •r¦ ‹Q%g¥éJ5úd½°øÙE­Ëõ3‹´h…~ÜÄÁC‡%‹bÚS]ÉæaÙ䇬ƒrÓ8£ÖgÕI6yut„¯æê+>¿¯¼o”ËIü%ZGòBíÜElNkqY%³v‘Ú®ø\ˆÇår;D¨ƒÓtõäl-WCP†ñÊæÁ2oúGÝ®pUs¬wB²)ƒÍcî‡k½Ö•s#ä&—\¦ÂˆÓçÒXXЧ{¬ó¿;u"ØA7Ô§ kœUŒEóy3 uM3Få|”™íZUA¤¡ÉÛŒr‰¯*™;ÔaðˆŸÕÕ¢‚&ý(‚}¦‹ Q èãˆKGŒ§Ýub»~³N5]uÎE@È’‹(šWLˆ¢Ër\–Î*1DÒË‘¥„v9úáj[ɶs0³a|†~ £ðÇ7.Ø`A.F!¿¨¾ô¼.{V}ÿ‹è4E Lõ³ÊY*‹ååËlÓÿEQ3BkoWwÈW×2‰PÌS‡šòðȾo5[ù÷Š¹Ù ìLUÉZvíÊÚÌkúÅm÷ÊÅîÖ–ÉJ]!ŸW¹>C„Så8ëàŒ¶{§eâç‘wÆŠ!«xüu>[ú­éiâí]!`èʳNŸúLgV‡¯m}:tW;_òM6,o`èÊÓ€ÇdyZŽˆW¶m#æ¹jª*®ÇëË„}Eí ÕrÏëòá¨ï×Öe×H2ûÌ¿n‚œÌ¢=µ•º_粯¨b/Út¼ªM¶™MÏ Ûú{Ö0;²[齫οþgíZ6…Гqïú¤ðk–ÿþáO[Åí2{o¿<»2Ç\Qýëëçt˜&ˆQ|>/#WÏé ’«cºK±xHŽÙ¡æ–Q‹Þ¨ðû›êÌQ&a~·Ï:s¦Úo°?ø&"SRR2šú3ju{ÙŽ³Ö¥@F'Ï3Ä$ Þ]&›v)¬Ä&«-TyñêüÑ­í‹#ÌŒh³e û· Ú‚7÷3-³]5ðÔÙ†ÄþÉþ°¿x&°w²±"˜a3›R„£!D{ñ ˆWGpì}Ööfrz7 :-›ûÖþÃC¥ûà3·®¦ÏFà.V‰Áðûi/†B™?5•Ê à·K­ês;4G•{¬:yèm@©ú`_Á™ý°y`ž·µb ¶©¬(ãI4†ì?°„ÂÞ endstream endobj 475 0 obj << /Type /Page /Contents 476 0 R /Resources 474 0 R /MediaBox [0 0 612 792] /Parent 464 0 R >> endobj 477 0 obj << /D [475 0 R /XYZ 90 720 null] >> endobj 478 0 obj << /D [475 0 R /XYZ 90 79.203 null] >> endobj 474 0 obj << /Font << /F51 5 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F53 19 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 483 0 obj << /Length 2771 /Filter /FlateDecode >> stream xÚ•ÙnÜ8ò=_aä%j¬[EêšÁ ²¯—“ÃÊ•ü© *ƽ8m®GDëñ‹I(Y$—B:iቇDrHôò¦V‡#?Ô®²õ%ÒY{rh‘¥ÐVH¼ø¾¡1dÞìÎ<…ÉÃÄL>ÞçÔnÍUfñ„ØE5û ZÒ»¿OðÂ%CéÑá;) á°F˜ß^Ü£ }„Õáįë5¦Âkà·EÆø?•…I‘23I‹•Wwui-Ѭ°èµ_1ãðe+ˆæýû®oxôyMfqÁáÆËb_Õ‰¾ Cü”°ûám?ô»51*£Ê•ßû•,"—Ñò5 :KΟ’L® )P—ÉEŸ@3Ð>¬`>¡X»“ “6ócTí½ßàxл¡;õ;™áxD²–§“ qo'Ô[þþûÃÍš´t…&Iüÿ±*•(Œ¢I¹äG »Su.Žá üjƒNlùûßüªà<ýÝÞŸlºŸEEðQpè¶8°wGa¢°çÓê™ú Àß±ÄÁ’q­šhÃã<÷$¢JÝ|ýÅfxÆoL•Õ5¯ìö®½¯ZdzǪ®yo~j*ï £ù…ÞY§è0Á·õüΨƃßêÖœEiG˶'o¿°ÆÉhç ÉÍs—¹ D³PÇùU^Eå1&'ðÌ´¸È_<Öv¶’a]#6?¡Üþ¼fvŽ]1§i|ÉŠÖI˜gzÉÊJ*å±¾ÃÊ%1bE’ÊsðHZ}€4Uר%o1çP—2á˜%÷¦1y:.¹k”ƒ4¢Ø®p´ý8ÈÅ;ɯZ^:ψÂË7$êpíÙnYR`Ê›¨ø÷®ià #xµHY–ô&8ûÏÓ‡ª"o×ka&i$€–Ú–zàï™±¡Álœ²ènå©׶㙓—„ŒË¨<8HÖF±žó8Éþ悃ÞnGÉ9°’Qï¦ôOO±íN´ºÊÃ"M ùû<„˜  x]Q‰H<‰“Ióx‹¢ Ûò·á,aeÛó¬lIžÎeâ²ÍÓÐ@¸ŠÃȈÏoºÒIðé[×_óïû´ã¥úú¹f M9ŒvRDR%ô –-š3.Ókãà=E3Ê[´Ï[4š;D°Ù×Ë ¡dWá©N¨YB“ †èP¡±–™$ÌÒ³„wX»îÖ#že@§v7 kYCT@i!R=™—²ÁÚ.ÐÖ²† bÄÂ[p`BUð³}U¿Ì'tP$Ïó ói¶dr5Ÿ`¬ï0yIlÎ'žé`l„"©¡fTË×ù¡†NárÇýTtfY4Öç0íƒO 2 Ãþ²ÏaëÓôÖñy!S¥Êa¶_e؆¡Çº^£”†* ¢‹©Õ^•†t0ͧ´_e*3ÏzúuµØÈ(‰‹¼Ø!}O¼°ÀÉúj#½=Õ#ƒEä$¡j] QqñS‡_K‘“)Ѓ3«á®DÇe’”›EQkPù®p’ƒªø»/œxª+úÜR`G†Çps,¨¾°èZŽky2Ѩ N!ßèÒ¤9gÜ ‘)¶p" —«øÜ]JO;7'vcàûáPj½$zœÿˆR塉ò31ÀA÷§g˜æè<òÑJsq–M97šü#e¾‘‰“÷ %m›;†´¹øæÀEš—7Ÿr·‹*lº¸î,8Ü,Ķûž£ þ‰Ê À£TÊi>ýÉQ‹"ޏÀ%06Ä—àtgOƒ“¥…|”¤*]JGe %€Iïîm_Ât`ÔNxy<8¸pÏ“j5µç¾“&µ œD:N î§äS¿˜‹Þ©ÃÍÕ N(ÌâÀhd ‡ò­H _RžAáW£¥ÄI±§êe“œqèJEÑãÌb¥sHípWÛõ ZO \]éç Þ|.D)£tA™(Õ‰mµóÍ2í«nΓxêãÃY¤3:_ö0É‚Ùñ¬~3@[xÀý…"@e¢ÜžaâpåÁ‡®™òLK °¢$Œµ— Åw$Aí0îuí¹‚ Vÿ”‚”U?ü¸‚˜L˜1·A0™RÂ!‚}Q½!|²BêA:ÜZäå8½«9ƒ$ØÃ8-Dº=¹¨!Eäè·³V-ÏýVddVžznuZºÃ•/]MqV0˺p±¨ ­YÔ¼%ƒìP•ŽQQÆ` OX‚zŽß1Òtk·¢Ñm×n‡ÓÊŸh³MµØD;b(eüNþ\ð~Ä#‘^ð×Í6óý\ò™ú’bÓÍ•Rhu/7á±Ym%›84ñ”X‡»ý¶é¾Å5eSab¦6ê›uVˆ•ç:|gwߨO–QÀÄß(â"̳)ã{™*„³(/žýT`¤ãg°­é!ÃÂJ›½­÷­Ù˜e e ´°8j0i¥Ÿìpfyx"  óEà1Êëü6Ͱè\û¥Mê2üS¦¢Æ ¢ˆ–¿øe…–J·ç„7NÙ3OÙ%EtQt¯e3ûÑh>þeE«Æ £mޝ¿ù·Înà”Es¿cc[ý}§‰”(Aj òÝå‹2Þ}ë£<ÿ9gñÎ`ÏL×f]}ùôgôþü endstream endobj 482 0 obj << /Type /Page /Contents 483 0 R /Resources 481 0 R /MediaBox [0 0 612 792] /Parent 464 0 R /Annots [ 479 0 R 480 0 R ] >> endobj 479 0 obj << /Type /Annot /Border [0 0 0] /Rect [267.328 545.455 335.873 556.364] /Subtype /Link /A << /S /GoTo /D (dest) >> >> endobj 480 0 obj << /Type /Annot /Border [0 0 0] /Rect [209.721 357.646 338.267 368.555] /Subtype /Link /A << /S /GoTo /D (files) >> >> endobj 484 0 obj << /D [482 0 R /XYZ 90 720 null] >> endobj 485 0 obj << /D [482 0 R /XYZ 90 357.646 null] >> endobj 486 0 obj << /D [482 0 R /XYZ 90 296.758 null] >> endobj 487 0 obj << /D [482 0 R /XYZ 90 261.565 null] >> endobj 488 0 obj << /D [482 0 R /XYZ 90 200.071 null] >> endobj 489 0 obj << /D [482 0 R /XYZ 90 127.547 null] >> endobj 490 0 obj << /D [482 0 R /XYZ 90 77.082 null] >> endobj 481 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 495 0 obj << /Length 2701 /Filter /FlateDecode >> stream xÚÝYKoä8¾÷¯æÒòZ²ü:îôλÇíÌif€8eUʈÛÕéüûåK²ªâtç¼I-Q$õ‘T©›þÔM•ÜiW¦¼Ù÷Ÿ¡>RÒÛÃ.àøõþÓ?~ÏÔJâ*©ÔÍý!\â¾¹ù3ÊÍíNW:M£/;<µƒ½Ý¥©‰¾ilÓh²;Ùaooÿ¾ÿϧßîý^™Ö?9ÞJ£¯¤ÉK«Ô°4“=s»ŒÓ+nw-{VÄùÍN¥±Ê˜ýþØÎ·;£Ó¨îºñV—Ñ‹cc" îtíëŽÉÀSDßÑNSÛX¡¸]ŽV¶½R*.ËE›þ÷‡2æÈ[:Þo·YÕS[?vö61y4"¡´íb{î=¢\¯–¿Ùiâ¢0rnÅë>Ös;Ǹ ‰þ}`‹Íva“-#þµŽ%*½ÝEô lj™prû Û…§÷5˜º›e¡£å#Ÿe8¸­ù›§n|D³»œ@ãeä4Tš(¦s€cªoéöW ç¤c¦.dÏäi¦#gqr‡}ºKŽä¯gÔ̺Ðá%,1‰5[°f5àxc…—ƒ;Dj Fñ÷ç÷Ý€«¼nIï¯àšsü-(“œqÌ™ <òyAk?Nd£ÙC}îPÅ¥–|õÆ^9Äß$uwÿPw³Ý„ˆ2ÎSw”Šbp §ìP }I!Hêò*¸ÊÔQx$žL};£aÝú‡•ð¡„K«ËCO#›Žm5Ð'‚ì=¥@MhÇd÷gpgEþˆŽÛ¬è”ƒ ).ÃÛa™Î”Àéð Èadf–vÙBnÎJŽkÆÃSJ6\¥[þt?u }ÒKÝŸæ¥ÍqÃ[F¸V⢖8—FáUýÌ4Ê"çó6{úŒÊIJ×´•¤‹•vsióÂ|88Aa¸Óþ5[WËg%•qkš5µãkÂ…wì_Âa®sCœsm×>û¸lòpúÌØ?¬\æ„еòz©§-íÛÅI÷cÓ|9ØÉíÏ2 ¯rñö-ꈣ{ÉÎ`¹ß؆JìÒé • Äq½À„xà‰@Lx9ެÃ6Ø-“å]ŠàÂ=è¤>Ø™²#lFØÑÀ¿ ˜Ö®H‚·Fý„c:Ð8RÌ•é‰çÇInòQîÿ3ÉðJ!cœšÍʯÊãÊ©­[šUE¬Jå“^Ä2¨¥ Z¦q&œD9û­ÝÛðãyhvRì)'°Ú…  ~$…Lmß øxCˆ ÞNQXxÙD؃»±—´Æ×F ârœÆóÓ1\N&Ðzh¤TG÷˜0ÁÁé›DS_^®ÊŒYÜØ°`\ðŽyx•…'úú{Û‹a‰ÐYþ² õNúQàœ_û®žvc  ó¿(V_ĉ5!. _Ûš „ó5ÏÕ®Ý'èEéq³BHWjqå"Na‰ä$;ðœxÂÝV,Ô†L²Ù×S#¨æ™*{Y‡ú ¯X¯]¬Ð*Ì ƒsŽ]»ç̧Hé®\¨0ËÄêMãa |M›ë*ú'rfëËô»–Ü Ë‚·§zòœ¢,¦õõÀÈ{FîÒâ½Ä“,QFy/¶‚ýk¦=²á Ùƒì™}D?MãÓT÷ìÔ_í›Ç4­¡ .*ȽҸÈ+|-g¤ÉàAÍqí¶'¾ëÅô½´ މÝä,Ο` €~‚CN‚þ¾©é-‚>¨®%N«*.MJ¼ñè¸~"ñõb¥›¥"+†¯}°TøØ-6Y$˜ÿLÃ<ê0 âpÀól78ôeêsî¸@z [M³{jð¼>§ Ááæcýßjp“¨Ài¸¢2À 7ô¾ÁJŽ”Û ¥RN»É7ÜPÞWp*¦@¯®¸‡B lJ‰x¼ƒ¾ÊàêLâS¦¤´ø4•B³êó2‰\ôÀYqΙ$ñ˜^ÁMyAàèÜçÀ É,Sg,éAhC¹Î—è3;𲔠Ƥ:80Jù‹è„ÖA¼ÁÅ:Åì­Ê…AÃé6Ûúyp¢•ï8QÅ•‚ȳ!÷"ûxp©×eäÙ|„§:0ÉÞ«\ Œ$¥¤=§§Í‹–ª¸Ê3Çæ/¬K—.qri’sTM²°hÀXê\¸ x_•C¢­ Ÿ¿ ù)\ü*Ý’çXÏë$> endobj 491 0 obj << /Type /Annot /Border [0 0 0] /Rect [229.479 281.042 399.843 291.951] /Subtype /Link /A << /S /GoTo /D (linkcopies) >> >> endobj 492 0 obj << /Type /Annot /Border [0 0 0] /Rect [310.206 76.476 492.085 87.385] /Subtype /Link /A << /S /GoTo /D (excludelinks) >> >> endobj 496 0 obj << /D [494 0 R /XYZ 90 720 null] >> endobj 497 0 obj << /D [494 0 R /XYZ 90 613.337 null] >> endobj 498 0 obj << /D [494 0 R /XYZ 90 515.438 null] >> endobj 499 0 obj << /D [494 0 R /XYZ 90 456.991 null] >> endobj 500 0 obj << /D [494 0 R /XYZ 90 400.664 null] >> endobj 501 0 obj << /D [494 0 R /XYZ 90 340.096 null] >> endobj 502 0 obj << /D [494 0 R /XYZ 90 281.042 null] >> endobj 503 0 obj << /D [494 0 R /XYZ 90 236.351 null] >> endobj 504 0 obj << /D [494 0 R /XYZ 90 135.226 null] >> endobj 505 0 obj << /D [494 0 R /XYZ 90 76.476 null] >> endobj 493 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 508 0 obj << /Length 2906 /Filter /FlateDecode >> stream xÚÙrܸñÝ_¡}§¢axûæ={+»b=¸*I•!£aÄcB`,Íß§/œm©æ@£Ñ@7úžð*€_xUWyûeR\UÝ›@ oBma»ÀøåöÍ_ߥáUøeP†W·»%‰Ûúê_Þ¯{u°zÜlã8ö’Ÿ7Û$I½_wê^÷›¨ð,/Œz§GÝWz³Ò¢,¼,Ýüçö7¿ßNg§QôÂåãùí¢‹ÛeEâ‡q·{ªõ7<è’‹4÷3 J8ŸFÀ«Ê… ܸ ½j§ûû¦ß„žfÀn:^­M¥ûºéïyÞðÆgÿ¤Õ<6'cugxb÷ÊòH²Þz>ÄÂy{9ШNãÝážÛ0öÔ¯ 5(G«BÒq¤0Â%à.ƒˆ}ØñWÖxSdžŽøAÙ½/ò9“ã–´ K?ŽK>מú%Qþc;Õ¶' žæN„xtšyG£ Ãù6ª6[`¹ž; ´VVoUÝAðé¶°À’uDþÖ´¯›NyÜk ?òš:_Èwtï¡üµ® C¢‡ ; f`5]£RG lFXîodóÐ#Ïá mv #~qÐ)C¦B‹Æ]áqåƒIIú³]t Ô¯Ó3lK‚„ŽJ‚tÒOû£fÍЦ¿¶ ÑO±þf›¥…÷aÇ0Ë›a@[Nt†aºF ~¿®iP”¤~:Ũöºz0ÇnM± ‡yÍ4™±ô{´ý,(ÝŽï s?,‰ì >b„ ö|+˜AäƒÎLÌh0T¨ ôþü-åA…Ïl `ˆ‚¢Pð Ú]óˆ¾KÅ ƒ…b"Î^¨›á8V2V}ívÛôÊ¢™~WÉò3q%0hjñ_M¥ZxÕ$èUqmUˆaùq9ÝìªyG¯ƒ‡ñ„#¸k˜Ot“ñ´F9Nü8‹/(7—Õ«dW×7Â.îH;­^ÎÖVª¡;¨±1"ÈmXD~ž‡çò¤#³Üxcð=5H/MBïmÏðU&‹ÐOƒIxmºué~gK³ty+˜glšà O9(žU6?/¢ ¬©ªŽS„ÍЗœǽvÈ÷ÃWüóW ã✑4èª1 ræFbù4uì:jzŠŠôÒH\.âO5ðPsŽ¥ka §B7 qîµh×ôµ‡–VüYÓù¡» vp(XOZm9q “9h‡Ï\_"[,Áhzþªž—ß¿û¼jAáÇ“ üËÚ¥K¼mp˜2'<ä”?UÅ€Ÿùû…?Sêþ¨FŸ9Ï—ž?ñ»M“ÑFYî‘ПpEÝÃô7Ȥ ÏÑ&{˜Þ4NĵÅìÃÀô“­¡u0·¸|ÇÞ'Ãg=…ZuÎoa_5s’«c+¹#cBcQ¼zæC¼æ»SÐ(2!Vdóõ p;­º§ÜdðÚº7œZÒ®4ØQœ€mú ²¹V¯I@øŸŒoáŠ/†!|AtSe)Olv|ä'–sóK.Ð}ˆ$±ŸGŽðÒðód~ý¦}B”ላpÐ~8¶5#v³¯ÆN.F†O— µgç¥|^ÎŽ¦SÒÆ82Z¤RxܦÐcc÷kV³ªŠÓ[­jÀ»†Ó‹"K€4Lc:d8Z^›ˆ.«n/¹ð%—E~œŸ=g;!"5gêõXUÓˆ²(¥fZ–™—9GûÉoæ!Rî|À u úêz@?CMÞ{}ú F)äUª—pyÆ’ÒÀNæüÚgœ»ïG4°…¥yÆaèL;ä¾ ~¿¶ìp¡$FK»¾áŒyј‚mÂ: Kn5ÊýaMñBË È0xò`EâÍtÿhÐ`ŸG*5UI½Ó,ÊË$2‰Ù¾äœ¥·¹SM;¼Ö;—œw–‹< Œ™œ<1Ì áa} îjÆüìð¥g¿á ˜É´Êpw&`Zò´×Çnîû©Ó7……rÊta$ÎêãµÆ§‰ñ{ß°ØT ïóGÎöbæ`˜=Í(MÏ£´Kæ`yÓšˆ¿RúC[¿—w§7È'”LGÄO^.Õ2+]¿4œ]x&¯ZÑì¡å5#Ê[-ªt^á,é莑†[2 l׌ìîš¶±‹ò‚RLÎÕèš"i3õ”#÷8(^Ý\!²<èÓKºÌa7*!zœg†4Yï°È‘îä¦Þu?\ î(Ô/ä]’8Ç*ýÌåF÷$A$î›z¼ÆÊŠ#UUú PÅŸT›ÅWÄÉÁ{ÄE) Ž Õj³3CØ#8,ÍC!Kã3B$ D€$PnÙÊÒ±@køØ3ŒUFºt¼û“+ÿ² N!àkøk|HÚ“%“üqìÒXÏ L¸+Š#êg©äæî_ cGu`Ç$޹N?ÉÎQõfG)ØLžÔò‘d¡åèà¿â7>ÒßNØUüÁŒÚÓI¤8¡²rQOCzm×-±ÔŽL ,i,¯>’ÃD½åÝÚdmÔ‡VU$¼ÍÑBˆ¦~-¼7«ÿMY--'"4/¹´¸µ9}Vÿ`.={Ä•¦Áҽך©î«ñt°/Yé{ê )G ü«|R¬©T¨tNrÛ»f… »VzÊ¡$ ¼ì¿G/ƒÔ9"Z™J‰`ª®‚D Mq/H. îš§Ý”ûëê,sH%š¤Tªò²È‡/šºL:ÅfªÞR˜ÐGk EEQ×·á;nPmjƨ•UþzU—bšAøÿ;6£–Ù??¿åX•€ùÏ›|ÙKËAàŠµ-7Òø·‡º8­ uçÄ%&gõ,IÒ/™wÙÔ“03²r6T'àƒÀ% (†{ž‚‘ìç?6Äå”î̲˜DN 1œ•Æ¥¤_„2­Q)pL¯žˆ¸w𱟴®ä) ô°à‚è!¢No°ãUöù÷‹ä#xŠ´¸Ópr±¹¨.nR¼'Œ žß¡3Aˆó~[R¤ ¼¿é^ð.@æÄÈ®ÀUÄ)n“ÊÿRÿ?Íü=ü endstream endobj 507 0 obj << /Type /Page /Contents 508 0 R /Resources 506 0 R /MediaBox [0 0 612 792] /Parent 517 0 R >> endobj 509 0 obj << /D [507 0 R /XYZ 90 720 null] >> endobj 510 0 obj << /D [507 0 R /XYZ 90 668.863 null] >> endobj 511 0 obj << /D [507 0 R /XYZ 90 570.619 null] >> endobj 512 0 obj << /D [507 0 R /XYZ 90 399.461 null] >> endobj 513 0 obj << /D [507 0 R /XYZ 90 301.218 null] >> endobj 514 0 obj << /D [507 0 R /XYZ 90 266.606 null] >> endobj 515 0 obj << /D [507 0 R /XYZ 90 220.966 null] >> endobj 516 0 obj << /D [507 0 R /XYZ 90 149.024 null] >> endobj 506 0 obj << /Font << /F51 5 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 520 0 obj << /Length 2686 /Filter /FlateDecode >> stream xÚµËnä6ò>_a`QnÞA6‡d'@Hö°rH-±Û„%±CIöô~ýÖ‹jõŒ;}P±X,‹õdÇ7üâ›:º)Ó4¬³ê¦éßE‚}| ´‚ýŠâÛ»wï¿Ïã›8 먎oîkwíÍ/AQìöI¤iðÝAG3èÝ>M³à)Áo8}ÐNÞýçîŸï>Þ-{åIòŠ0HñŠ4qV†ÅMQeaœf,º3ˆTåA£FÍøûü`š]R<œÌÈÐašÉX!ëÕ#Ri™õ°0¯NN #Йá(ε¸ú™Ç'5ŽÏ»¤ ¬kQp´}œ†qÎÒþÅY§Çp·Ï³:ø84î|šˆYZT  @öá‘=ðw<“î¾7ƒrEÆÑê8ìÌ4u Ã.F4m]?ÙI0Îh×µ¤1‹ªE8ÔRZdÁ#žJŸG9ýûlœnqz±Œ=ê‰rN`sg{4‡Q»'Y§œæ…ÓƒµP[çq‚™G-¨yhÜvuÓh—MÀ$ñÉ4ça`UÃà×(ëzÕ¡ùàgÀ{›`*q°¾dm}û­oס8ÓvæpÒ+C%ʈ©~8 ËÄÁ)VИŒ«Nà²g}‹` r«£nb5ÁŸ&OiNÕ…Sš"–ÎLtåGj72“ íÉîí¤Å÷ÅøÅø6ô|Vh¸#$.Ådô3 «²æ#Î ãšÖ-X_–Á݃Ÿ™V¾‡CÓ³.¢`4E«þþøœÆö§yRâÂDÑn‰KGQâêxí=ªcöÎ01ÒËÀ£S§ý¶ûÍõk·ÿ³™Ð(«XÂBÖ»U•ÀÝÀÖvæ‰F Œ'VtCwÌ«ÕÄ+#¼ž^S0D"òHÀÈ… {{2䲸äàùj^1ÚÙ5›‘à²SôZO㕤B4ÎLüí€1nðn9pcç®e¢+À³Ûµ¼Èfɾ­‘)1v]X¤d7ëÜ|štû‡"§ ¹:Ÿ2%GŒˆG& ø _R>Ð`ŒƒÓ „½±W‘0¼É-/æ°•Š¸`ºFöY–ÿ¼†#‘ñ÷ÏzžxÞ72G«jî¦[6ÒûYl·W‹ˆi ºÑÊü¢eü>Û‰ô QΈ#<šÎ^m|`©êj*…{’Àé£2àËø= (oª°.Š  ©ÀEöI&YÉâsÏ!åý÷i¼&­Ã¤Š½·ÜÓž_2Ü Ù¼,+â?ÅóñÿÁ´_1½vþ}^…rMаN &ÿW)uêcuJÖãFŠó°(y)±J»‘ 8\Ó ªG€lœîÈc²&¤Íq0È#¦´“œÓ2!ðý{ÅFƒÅLpð î;AöÙp§)qXÒØunm,e-NLƒÑ,Ä6ÃEýëj.MÂ$N¼JãìñÛ-…& ‚žêv‹S€¸ðÙb—a|¹¿7±Ayéš N—(¯§F|ýã'ÕŸ:ïSpA6liŸDu˜æâ"Å%›üýë,Š ú@È þQ4É1bÂ߃ÁІÇ^šùû5ˆ ‹üt¥+;§Ýx³¼ÌÿÚfPªŽAŒßbãoþâ1¿yi—/ruE!uÐP䕨’Èãt>½š´¥>©‹%U#Üj®¬°°¢a¨t©KïØ& p°Óŵ qå’ög g>"·ü¥¾ô+Û„ rÂJ #E N§Îø­Ac[Å ”­Š»Œq$ ØòØ) wL¥ÆÀX_0 ,±¢Qó(|ÍÄ_Ò…š8†iÙ@ñ焬˜ñ¨'ÏËg¹Ïï rd•£¿ˆñÜ“¤÷•E!BBH.»ŒÃ´¼ÖÃ/Q%…â ”Ô~¢š_æ}Mª„ú›F¨A¤¿ç¡ƒfƒHP¶¥¤.O»®§›}IûÛÖ1°¶ªZìÍéréÓ¦]fyXÅ•§üŠ™b®F¹¶™Ça•-+Ôýh»yzï/u(ÙÎ'´(WµEÁvŒ¹B×$€ƒ<Ö2)Y1#¯X@íÀدêG­¸P*TIå8£¸./e,à¤Ñ¸gØJ`,R^/"Èͦ`­ºA9=šV3Ìp$¥ FÕ $ÛccŽNÐ3VɰÀ¸+Â[–ÛB›‰Y›qKj¨8çžãî¾C/ãAo©r¨–ó òÙt#/yý2˜$…ƒ¹ëgVÒ÷l"îV«Ú?–ÛÅ y£ٙ‘Òn:2T¿ÙÅ?)¼oUKžîêàÖm±Šôb­ƒô[ÊHûo%ª`ÿM“‹1ÈÊCèb“ Ú`매ØJ5Ê~“E #²Ò¤kIêÕ[cÏ,‡+-»¸^&ɵëMV ‹Ÿ¨Yç\Iõð5;Ç*‹/B·žÈ×fK·¹ÔkбŒ„.¾}­Ó|6´Ù<èæñÅÜyuƒßY>—³8Ã3:Ú0yÊ´@â Íå9=¨ë¸äÙ?.:ÌEÃä—BýY,'_µB³ô“Kê~ö€™ôpW¤>{U¬<ª lúó`ó ^1>›UFäæü½…Rn_µsÖë^|iÁ¹Ë¤ýÕŸÌ8-Ío«q .ïÙqVºhŒ¯ñ¤÷I¨2 ±Yq­>3$Å©pÝdcVNËFÜ;Á/ ©ò”MeCòÔ;3ÝhÌÕg×XQæŽqlÏñ:šp$€9²8˜W‡¸ª…;G&aã)Éx`¨üVd> endobj 521 0 obj << /D [519 0 R /XYZ 90 720 null] >> endobj 522 0 obj << /D [519 0 R /XYZ 90 641.955 null] >> endobj 523 0 obj << /D [519 0 R /XYZ 90 596.459 null] >> endobj 524 0 obj << /D [519 0 R /XYZ 90 395.118 null] >> endobj 525 0 obj << /D [519 0 R /XYZ 90 281.142 null] >> endobj 526 0 obj << /D [519 0 R /XYZ 90 208.738 null] >> endobj 527 0 obj << /D [519 0 R /XYZ 90 135.729 null] >> endobj 518 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F67 34 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 530 0 obj << /Length 2574 /Filter /FlateDecode >> stream xÚ¥Y_œ8ϧ˜·ÐRš€m Dš—[%Ú½‡}Ù‘N«Û“Îîinhhazgû>ýÕ?hH˜M²§~ (›r¹\õ«*wz—À/½+“»\ë¸4Å]uz“÷ùM*Ô&ì3þöðæý§,½K“¸LÊôîá°ñPßý3úáèΣv{­ud>ìöÆdÑ÷ä»*¢‘ðƒï*¿Û«¬(‹Èæ»=üýÍLJyíL©¯(‡3¾¢]jòØÞÙÂÄ©6¬ pѼˆ\z¤ò¨ï˜3e(øáwÔÖ1l@Ùè§®j/µ¯yþoIjZDÌ$¯ëG>_†'_Ë—ÇF&ž¼ë´“¹¡?Éç“P0loŸê8ÍXãß’, — :‚ù2¹ÀÏp £?!Fá r@åªAIOxÁúá™ßd —ò7•ëxä‘¿åÿÇ´Yœsúó«þÜxYù¥»4ê/#¿ƒéN+ÕSÖ]7Ý6jơߩ<º’ÙL*ú¹Ñv¶ PhÇùC²"0ë&¸¶íñã–ÀüæÀϪg?s•H!MI„cÆàOób·ƒÞRþàš6 ‚:—sÔi2#’¬«NÓ¨%Wƒ¶ü>»N{iÚ–)ò¤éž_&£“Qxò#›‰hÇÚwYý¿Æ=4•—yã~ÃÀ(ø9Æ1ˆ³Œ•Ç…ÒðMýu‡qiÆDáØ_ÚšiVÝèèÃD Å@œXÍKAÎV1$ªÌRêÙé”À0Ï A¹Ó¹Ýܺ(Hš’ýGž)§¡Ó»".­5{E\¬„E®4Ç”Q XÉÎß·= û{?Vï!N]@ ÉÀx¸»û/Ù§{k “ýýУ¯ ýt³0êšÄÆ®xtÕóå¼Aùo ˆ·¢]”è¦øÓзnhÂÖ~5ãKí» 'VÇRåáó=¬7 Œ•mò8ÏÄr?A$Fq$†Ag€X £#ʩϕ¶DôÀ‰Omÿˆ 'Ìö× ¶pR#<*@j¦¹,Y-zr*Od†fô+A°ûï­€—œsáÆ‘o"ºñôÍ[I =?7×P&ÎÕ×_“o ˜Ïòþt‚42ÊÝÒ¦TD¿ŽS^*Iˆ3A4&ÊÕ«I†ëÚ‹2vµ²Œ3¬•Õ¨Hβù„Tf U $ ·é•e0@e°7í‚§–iö Á‚k.$Pûн™éÿhÂÈ wá=Önü6ÝŒŠ•.þ?W +@“2_¥Ntè¬,£Î¿`‡Ç…¯PNvLmª”—±IÌwYËκ@ÒOÓ(Ty-ÏDðê`›$‹µÖ¾f—"Öù,wV:V¨[zzË âæq1ǯ=×5œu2çùg>7õMG>Ÿ™rŽöÌPÑÞøt;7N˜Kpœ=$\!…”‡ûLÔ+1jÓ8™cTjìMC›,.ÒU|¾*4Íbkgxù“Ã3ÉÒ¾]äÙ~×[µ‰õmÞÛ8ޱ ”@‡:5¶‰]ý£›ZNƒMäŸÔöy¦g ãKÓñs[Ë$Ó›‘¾ÓkH<-“/ñ…ÔøIÑOÑMœ®öß©Ëdù2š¶tQ Éeå ðÛ¨qÝ«(5¯ãÅ$£±3k(2fýƬóÕœ›Ødfa,²æŽ ʯFʳgª·Î#s±Ó:3I=VfnôLQlàÐ/\J0wÝzYòX_©Rß’ÁVð€ÕÊùxDZeÛ|bÞ6ã€Ôˆ°|aåz¢ÈÅxAÝHÍãt ÇÚs¹Ñ`KI@€õ-"Žˆy96ó- ‰"òÖ"_ÚuäCÙI]9ñÉÄìýXÙ°M ~4åºÙFã–„UpIjLQ§\†`dÌm™UåtÑl~š²B-Bø˜€¨!Á Íã…kœÞ.à…[ Øüyþâµ;›e¦üÞÊ™jÏt]JîdÀ>4 Ùû¸ ÇaU࢓Ìl* ûÚß'(6«PÈÎ%­³¨BÅ`¤f6ÏÙw 6 I¹ß£A9W. rA·ÛÍÞ;ìñM4ø'7Ôðxtš%r ‰d(ιâ3ÄŸË´åúr_²9ë›tµ=´É²—ë‡M”ÓûfÕrÞÏ+™Æfixëe { Ò÷1,4a³<ÉãR—ë¥^íC­…&ÍþÝ›™,3æ¦üV‡©T³¹Ï5‹&Sq“ù#ƵÃJ¹æ>³mºçÀ$AHžÍ(žé×ÛÏÁ}øÄE”É-_#¯—hðyºö@—¹žð1¯oͪ…òM¾t}MÞɾ•QŽå¾áÊâÊÔŸ 'R7J3—¾¯#€–­;¼Ý@la«Xw¢" I&|*'lƒòÒ<±|D9èÊȱÛÁöæ)t¥ - óö¥`yà§ã¡#Yh¹¯‹%ìH“^Të·@ojÜs̽ь&JËE¹‚¶ËÕ5s€h0ˆ±yÅw1’·4³uÛš@ú,æžçv·çäbñŠ7ÓýF¶"ÕÆ:›#•ÿ´ÐÓ•ó;ìiRqRtqþˆÿ\‚P\4ÍÎþ?wíb†O»ÂH|bäèØšÏn_E xÛ]SQiDÌSuXýŽ;­I+;ie'­, åÙ „§øÖt|¡^“CªÌ~ùmöÙØE+A¯óŸL[ª`¨R|Eaþ$/D¯ èîéî?þAW8D÷óäðÂÖƒ”Ö'æ8~ÜÊÜ‹gM½‰’Ç(ÒW›s+‹ß¢PCÉ+LHü8âÅpØòß©¤;žÿÔË8=…Pžio.S±7= >ÞØjýÑþÿÿ¤û©ÅG endstream endobj 529 0 obj << /Type /Page /Contents 530 0 R /Resources 528 0 R /MediaBox [0 0 612 792] /Parent 517 0 R >> endobj 531 0 obj << /D [529 0 R /XYZ 90 720 null] >> endobj 532 0 obj << /D [529 0 R /XYZ 90 553.538 null] >> endobj 533 0 obj << /D [529 0 R /XYZ 90 177.534 null] >> endobj 528 0 obj << /Font << /F51 5 0 R /F54 28 0 R /F52 20 0 R /F72 4 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 536 0 obj << /Length 1819 /Filter /FlateDecode >> stream xÚXKÛ6¾ï¯ðQbGÔËÖ± ` ´'ßÚ‰¶Ù•D‡’6u}çEIÎ*H`É!ÇÃyϧ¨M ÿÔ¦Œ7‡4Ý—ÙqSµO±œ¾<)Ùí€a·àøpzzÿ)Wï˸T›Óy)âToþŒŠãv—”IšFϦ»ØÎlwišE¯ ®iäÍÙxÓUfû÷é·§_OÓ[y’ü@äø6*Îà6ÛÇl¯ÒŒUú`*=ö¢‡æåª}Í»Æv/¼ûgì9s`Ä1r/}àyÙDt¼:_ÛNû;SÅ*kLØç±Y•î:'ûÏ$V˜jÛ<4öW#ºœ½ky7\ÉA›bƒv*Ý«œíqÞ‚_uóX ¬[E2ó"úŠjjüƒZå9™ çý½ÅC~ß5¶â[±v %(­˜€Ç½á­íY€f²ÖÝÅøÀ¥y¤[¼X¹Û69 2ÙëÁºŽÏ¾Ú¦Yðâ/ÑÔXŒTlå€7dã !êÝ㶈¹DѦ׭ì( ì$u/œßÊíÍMƒzÂ*Y#¬î,|G¸ÙowYRF'¾/ ¤pžJ~Ÿ ¯¢³V¬¬P‘+z•Kt4.hìŽÂƒÞ«ù0¤îoÞÝôEÔ.ÅePµd½ÃZk1žZ0:³ýåÂâR,ž´X>¨½ üí­1ƒiÃÆöØ®6rØQ^`’%©ôy0¼–—eôÜñ”¥ò8^ÏÚ×óØ4w¦½sAê!ªGô,žiJ"Ø «$#–2¦{6}‘‚/ªÐ•V‚ÑSK¾“”ü™uË= Í+Eƒ*È©âs[R…*ŽR¯äý{?˜VŠ©«ySa,®†’àE*øjÐS“´; ¹RQ¿†.4¿$I¹bí¸‹ÕfGq-€‚p8dº˜¡Y–IJŒMd:·*$°ãáj:7úÖò7ëä¯F×àâì ¢Þ17v@Z…Ú Ô®3òþsnѵ¨ðm‘°!W} )…ÑI¸ªp•»j6@qÕ˜[`ózrqÂeMkGù•H÷ÀÄŠ‰¯Ûа¹ZŽ“¼=<ê û©FI”ãU³nÏÎ˱Y+Óƒk©3ÃBgÜAµµ/"‡36­æW{9géàaÃÁƹ5Ãâ©4Q‰Áˆœ)I¸QBðÄv(@ÛïØ>èo«!Û›a¿fÉ3 q,œ´Ì%p3p eRfytqL;ìŸhk^Ê,ƒ.âaJÊ ñ ¦¹|¸²á ‘YÅ%&oM#\~Þ‚7B}e‹pç˜}sœlíåÊíëmF.æx:÷vÅ4°‹½rÚSê¶%¸l„xzûeFœ-ooàaã_ChñhÑÞ¬Gp}a2L[°RrV'eÁùk·ˆ0”ÈÎãÕ¨Âdfš¿0¼ÅVÒnêé šœÑž'NÂôýáøâ³ÜH%4=R•CâÖ†(EU œà´–±•ª2Ôç‚•ëTqëõ„ÖÔ„bÏóIÇÍ÷{¿lÌÚä"§“êÓà…³ñFöÅÉЄ;¬šP/L ãeD¸Ài?ý 'Mj8×7Š´³5!ºj(_‘qBÊᩎ¹$†©Ô.¤„ЃþŒd¥é9Uü^L€¬@>6”‹’Éx%x½¤:•Pš>âØy2!Œd'Ž x§a–-Å\*ª±–⳩}Ë©çžù¤;“‰ï?’ ØôGä'ðe úOö)àŒ"˜•T}©¢¿ÌÁn Ô), LÇdè ôÆã×zõ°/Âw˜ ਣ;õè{;é,àIji11>¿£InDp£é+ê¾XÙ53@¸Ã8TYP5¾(H¤é™¦,‡µ¶Þ ðy0=xç¡.ªhQøËh9Ç›UäíÇNŠg–Ut˜b½½Ás=‡À`¼Z?%‡hØ“fz€ŽJ¸—MÈÙ> Ø>…î šoKÆ2p)á:}:Á¾ÂšFÚØsà#UV%¥)p3… ® åå–B…‚Â+27©±­¹äGöÃLà·^K[Î?¹º^d±3ŽìŒ4|WÁ/B}®}p°à±8÷„Æ ¡¾x•:@dyôi{̸½¯Ц¡1IÛ or…óýG¦É£¼³ˆÒ$ÒÛDQ½¥jsÜ—E‘a¹%Çýñ¡ªÅy’?f ¨8ÉÖjv'RŠ}‹˜ßÉYR̈ˆ« ß$'¸}˜à6ÞÂØú2ÒçVFÏŸ5´-ù%¡;ÜpÄqw#¨¢[,jøVò3ì(/cLéQך]ìê˜`°¦R)$™Še?.Bþ-n1Â!"úò¥³×-~‡4£á»~œ  â‹ # ˆ~™h…”¬ŒçðÉ‘¹5ܳø1o1çx‘¾i¨¥7«‰:c ÃÈ ÿ³èÛäž endstream endobj 535 0 obj << /Type /Page /Contents 536 0 R /Resources 534 0 R /MediaBox [0 0 612 792] /Parent 517 0 R >> endobj 537 0 obj << /D [535 0 R /XYZ 90 720 null] >> endobj 538 0 obj << /D [535 0 R /XYZ 90 485.949 null] >> endobj 534 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 541 0 obj << /Length 885 /Filter /FlateDecode >> stream xÚUKœ8¾Ï¯àh¤à`cžãf“H{îËjw5rÓ¦Aá1³“–öÇoÙUt`2ÉJ+×ë«Ïe¥ðˆH§Q™e\«*ª‡‡”v¿<Z%àì<~9=¼ÿ”‹H¤\§ZD§fŸât‰þ`Zóìì'Y–1õ'JåìCc®vŒeÅfÛØÙŽµ™Wºb…Žÿ:ýöðñt¯Kùà¼ÇwèJ Å3UHBWTŠ‹L!:¿Œ“¼ì¥kÌÚ»yZõå_÷Í Í…¤Ö~½fèjÓCSyÅ|X7^ñ£[ü[³qr¸QO㟩P×u6çÞ’ÓH¶ÆŽ×n´ïàS§ì¼RL3͸LíÉjÁ‡ò¾t®EÛâŒëê#ÀÀf\äˆÕùª+uÎ:çß*`ôßëb›µÇ=7áÖ³áõ·\k® ú^l  ÷´CÞo-ÛË1û3¼*6u›ö6×Z\ŒÖÌv!ëÕ8ûËjCÈíСÀ'Y@2sTÚÉgó»Ë ‹™¯þ[±&¥[9x™vØI» ¦nxîo¨‹LD×E¡¼,dÅ«(‘ ;BBÄ P”»¤ X Ò͆˜º7ËòVrÅó2‡^ƒ×cH}§\åÙ1Ãp{ ,™Û[ÚMò’§Ê‡¼À€Oq•ÝY³_ ôgÿ_‘æJ¨Wp¦ÅÜЯ$3åRs©R.%ÔÓÞ‹’xü$É2˜¾º¾ü8Á8=Ú'„ûD è{%ϲ L)æ3ʲò²,ÙÍ 85#ˆë‚kT#ÖeÀ7ühƒ”ÿöwè<Øy´Ž2].@é"—{> endobj 542 0 obj << /D [540 0 R /XYZ 90 720 null] >> endobj 543 0 obj << /D [540 0 R /XYZ 90 720 null] >> endobj 539 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 548 0 obj << /Length 2307 /Filter /FlateDecode >> stream xÚ­X_oëº ï§ð€K€FµdI¶°‡mØÎ íËpîæ&rcÔ±{-»½Ù§ÿÈŽãºë½ÃP ‘%ФHŠü‰2ŠáOFy¥I"rEûÓMfŸodí€`7£øóÃÍÝW##‹<ÎeôPÎY<¢ï›4ÞîT®’dó—Ò5OUã¶»$Ñ›W…¿É¦s¥ë\³wÛ»ùëÃ$Ë(õ‰2HñN›TER‹D[´±™2Ѭ õvg¬Ú*ÿìQæòpB™ ©‚þÇʃ¦RnÆß‚ü¹i›­Ê6ç†'ʶ üÔœŸŒ¡’ø¿Îýjÿ#(÷R<9^’:^ª©e&¬k¹âÄ@ô‰’ V¤£Øît’ÎTÌtîïý•_¢]¢X”L„4Ì£?†pt¿T¾§0¤Ï¶äß‚~Š¥®iÉl€ÛlΟaÛ UÑvó­gl‡úÀdþé&°Ýow f½•ä&7¦({¸u̓¿½/ÇóÔ±À¸{ÅA© Å5tÒ8œQò!Oí@Ú»)j6ÿÜfpƹˆÛ™¯ãà&Ëøà ‚öUQóÒëÖØMÑUÅcíÖ"^Ź0ÚŽqüûŸb?VwÝ«ëàC®Å~ªDb“qÏr‚`2)U”‹Ü*‹d ŠÄ=Š„ÖáVƒ‰’1ø~žB+7"O³È* ¤¸úþ#ްIžEoDxŠ´²B+ÜVG÷7ÿàø»k t’Ô3eå$6^ ™çp—Saùorâ9gre ÖjÎJd±ŠLn…se®/äh8™Ô`0#äBZ½c«ÙtÆF‹4ÎFÓ–ÕMLy%Ѐ͕ ¢KªƒSh€Šú À­€¢¦r’Îå~Ž*u]tPª§J …gê@èTQ¯À-,¿UTÆq„g(º ¤*™G–ðÞ£Y޼ˆFœòºÀ±i{”P̈¾’˜¡P1Û}æQÝÒqÚç5P¨Aü<þ<è…ò‹¿PéGÁ»IÉ©†Ì`gàä@–nñÖ€z^, H/a"w°_qùÛ· úÿöÄdK\ì6¦@K¦%M;€ ÉÝÀ3%¯­@Δù;gÂÔÛÑ!WüÈ‚…aöWß·Ýy5¶›ä—xý<¶õèâo9l[Ê& ö„ú ¾gÙP¿¥ºUرçwj_„’†Å6‡˜—W™Ãû 1Û<1· ì+Àø+)"êYÖË$¾<(ß(#ðÄüÉÀØõ½Õ`œO6ÊF\ùÁs!»Ø¸h«I7{Árq¹¾)</ 0hŽ—éièÂ[ SŒ†Ë\ÈÅË“”•——£ éÚÊe2°¡µ£Š<;ÒCCÀe1q%œ€˜K—•!Šæ)ìã0 @ÚÅP÷<Ë.¨òr/'jèÄL^ZKˆ³ç…ݤ\¡p ã8Æ‘%oДâïÎMoȾ_­Pè09d'âªá_Ô~Õ— ÈåqÐ6}×ÖtQâT]¼N]0`&õZ3Eã\›HÎÒð°\o¦ŒT»ÙjŸâšÙu3§… fúN÷Œ £­ÜŽÁ$Í ú,p)½<€Ô—„U™Ê|Ô,©v3²•,™…N g „Œ×ᑉ)ÚÍ,Ú 'eœó'¨)”’`jc³zû¥‚Ÿÿ†Ûo¦:ÓÞ.Œ.Èå ó”T1§BpWa«L ãÛsLœÇ{§s;;fHŸ±PÙ2\jæ¬Mº™ÀœÉFò‹F6´“Ì"IÓLéÞµðçG¦S ¼ ²ì·d¹Äf——3墠 Ø¢aiUP5TT¢t´Z>ÞRW`›EWÍQ±‚h¥T05Ò’ O5¦ -­ÊûÛSïŸrð`É¥ •'ï P”¨šÓëq|B7ç/³UµèP;ÊW½ÃÔs÷¾9õq­Ì!â<ÇÎ*xu¹*QlŒÞ!ò]´ŸY%òD½k³¬ 5ZÄÙ”ö®Zo,¡e‘NYž?Éþ£Fk÷x2›®Rè\Þê °’ÌzÓÊ$›} yi„Å(†ÜèYöÌ×~Œ•LHJ!sÊ1—J²ޏ9Ïslš,!xž 5xåΠålㆊslkìvˆÕ?5cƒY; ùÆí¨½ä–æ°Xïù%KㆯW×-Ö±L²s¬b¾/š=`¦M,LN0°v)Çð14Uöð#ÏUÝ>2 £+©eÂÀϸ@µ>°g›Ò‘àƒªkŠÚ2Ì<Òjï‚Ê1¸Ë=ŒõÛµ"ïÄ“kÌ­·}¤ endstream endobj 547 0 obj << /Type /Page /Contents 548 0 R /Resources 546 0 R /MediaBox [0 0 612 792] /Parent 517 0 R /Annots [ 544 0 R 545 0 R 551 0 R ] >> endobj 544 0 obj << /Type /Annot /Border [0 0 0] /Rect [264.677 662.279 418.66 673.188] /Subtype /Link /A << /S /GoTo /D (required) >> >> endobj 545 0 obj << /Type /Annot /Border [0 0 0] /Rect [415.945 292.682 522 303.591] /Subtype /Link /A << /S /GoTo /D (control) >> >> endobj 551 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 280.137 126.364 289.289] /Subtype /Link /A << /S /GoTo /D (control) >> >> endobj 549 0 obj << /D [547 0 R /XYZ 90 720 null] >> endobj 550 0 obj << /D [547 0 R /XYZ 90 720 null] >> endobj 546 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 556 0 obj << /Length 1902 /Filter /FlateDecode >> stream xÚÍXKoÜ6¾ûWèR@ tiñ¡—\’6@{PÄ·4Fâî Öc#Jqüï;á´ÒFŽƒ¶‡À€ER£™áÌ7¯åA<È£ •’å* Šæ&ò§7ܯö@°_P¼¾¿¹}ó€G,rÜ–,îËàCøæ¤Ïƒéw{)e¨îv{¥âðÍAM»Y8ЋÞLoÚÂìö"Îò,LùîãýŸ7¿ßϲc!^P)¾ÑNò cy’(TŽóŒeA’)Æ¥"ýzóy¬zSÞ¡¼ gŠ«`/à>‚Á­­s{êìÿÃw '½1ö¬ ó*ŽšOtVšCÕšWe7Tå“cÖÓ¨d›•¸fÅ£_žátmå½Ì˜pš¦LäÄ}8I÷Jð°8˜ö h÷XÕ5®¢ðq'ÒP÷­ßÍôð%-þޏª}²ƒi<«œÒ·¦¤íI[Z•>Öžápªü™nºqr/î»=ñª³a$ã±7Œ»>ƒ»+¾~H$I¨Ë²j¸ŽCím VHK™J`åXɶl¦’1Ÿè}ü˜¦*|B»‘$x k«¡À7'Úw­W¡Eã=ÑÆÝmlð|ÿÀ‘ú@Ï¢ÖÖKÔ•?$ûà ÄľËBÓZæ æˆY&Òµ]îÝ"ñuÝ¡ÐG¿Ÿ•™ ‡ÎCõeƒíC'Ö‹)*]moÀAv쥓C×qitíLާ`†“çJÄÆßOq”§j2ÒMW-½.u{ó,½N—s¶‚ØÿäUìò7ƺ&»pÑ 8ç Ë$}÷~§$¡V*vç¡7m@$‘îkïz¸(ÙЛ0I8‹ø ç)2ZS"^ i]¢ _PT¡ø³î­?\Æg`¾ìœŸi×ùç»·ïéã9P Â<r–åù+¾' lô®ë@ RäiX øÌ²#kZ:n;Þè§í,àÎ/v€²@0ŸŒó佺º£ÞaðdøžZÇåH³†Ìse ¶ûÀÉ_+ Šíqe"p2ß›‚.寯sÊÓ¼Ÿ>úT}†üG«<¾ÖJÀ«d©Úư2Q½ ß53§äÔ2Ž’H¬*ÃýÉÌŤ!ݧ>KÓcô¾ÚqªhwäÎad‰›4¦ò“2 óÕZ9ÝúóÅ1ËÓ,i Ó•Äû|ø%¼Ð3™gÁ££l%ã¬ëàýÍ_tïµØ’„„îuHj–mÈÀMyÀcÞrñ=¹Q "('07-ä®ÄH° L ­ƒJîG‹K({%éò€ NžË¡qJ»Žz%ÇÓ,Ÿ ~wç] 6K< oäÛ QŠ¥Ñ\©'µž6¤¤ƒ¡s5|6]i^mð’År£jƒßÞS­8v­é7YB´«9ÚǪÜäHDÄ‘(Ð œ_fxü†^Åþ+XÉn±”‚å‹©†‚Ûi†øŽ¿^tÊR6p:¶4L9KTºv³õ_ÔÐ!ªÆ¶ÁØ“.mi@çyÇœA¨þk¢\ª{Ý6£.5¬ZL?³†z,«áe¨ÿW³R0I ůXu0µ>„¶tT)‹.ÕzÈ­D·÷T«k›¯gÈZú0l'ŽêÂe™¯Ó=V†&‚›ï×uê?¡ëH.ý˜x¶´!¥MÿŸÒv-—oþЧ$QRßð¾Ýe2œ¦EóU7çz+k üµ¦èø•²Ÿ?]rØâ­À j]ÇÐhÿã\”_ endstream endobj 555 0 obj << /Type /Page /Contents 556 0 R /Resources 554 0 R /MediaBox [0 0 612 792] /Parent 559 0 R /Annots [ 553 0 R ] >> endobj 553 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 396.359 218.546 407.268] /Subtype /Link /A << /S /GoTo /D (files) >> >> endobj 557 0 obj << /D [555 0 R /XYZ 90 720 null] >> endobj 558 0 obj << /D [555 0 R /XYZ 90 458.335 null] >> endobj 554 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F72 4 0 R /F112 68 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 563 0 obj << /Length 1152 /Filter /FlateDecode >> stream xÚVÛnã6}ÏWEÒÀš/º¥ÈC[´ÀE_jôew2 ‘Å€’“íßw†C)²£E 5ÍõÌ!E’ÂO$UšJñJ—I}ºI£ôñFÄÕ¶ Ÿ÷7»ß2‘ˆ”Wi%’ýaibß$ŸX!7[YI¥Ø/Û?´½Ýl•ÒìYâS1oÖÛ¾¶›/ûßo~ÝϾ2)ß 5ÞD£DRò*Ï5#´äJåI^j.”¦ˆvçÁï:W›nwßö›­H³”\cïŠ,Û€ÕŒ¹—Þú;ïÜHïÞŸî^ŽÖvæuΠÜleÎsr²?BžR§ìàü W‚¹IFÚ¬v§“é’¶ ‡öÔvÆGU7}bÆÙ —H‘qQUP–àüÐvvX T .³YíþA6#}N…†¨¿|À÷Š=™K;Uv¤,O‹rä ÏLZïym,‰X/%ÛͰãF„™Rº`@<ЕÑúƒ©cx´•ÇqÃp-jÔŸñÏö-Òe0¬ØÇñòãaôm=‚0‘¢Œ‘/{jx ¨‹ÇoUˆ %˜pñO,á´8÷¡Ò0«#Fð/ižÀýà-Ò> endobj 560 0 obj << /Type /Annot /Border [0 0 0] /Rect [141.943 628.506 271.078 639.415] /Subtype /Link /A << /S /GoTo /D (files) >> >> endobj 564 0 obj << /D [562 0 R /XYZ 90 720 null] >> endobj 561 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 568 0 obj << /Length 1909 /Filter /FlateDecode >> stream xÚÍXKÜ6¾Ï¯PNV#n¶HQ¯rؼìÁÀbææG¢¦…¨%E”<î`üV±(u«MgŒÅLóQ,Ö“õ•xÁŠ(Èâ˜2ÊÓ]äVÿ¸ãn´‚ýÅ÷w‡ŸðˆQÁƒÇúšÅc¼8ªaÒãnÇq(ïw{)“ð‡Z=ën'òp¢Q×zÔ]©w{‘äEfñîÃã?ï~z\ïN„xE8¤øLºL\²X¦ÂI—æ’ñX’t0Lwû$aÕõÔj¼õV%ЙŒ §Ñ–²éžAÖ"þÈð·ˆËVÓÒI«ÎÐ2(¥N+m3Ѫéi>•[¡8|‚Ÿ<ÔeÒŽÃqÇC5žZœóÐ0°`ÌÃÇccèD­Õ4Ú±q‹³ÑõܺµšÖÎhï~F ­J1ã iô‚;jñ‡Œ@°ž~‡QÄetV¶l–zœTÓá즺g=ö³¡=2ƒ›Ôc¢‘SËç NtÕ[˜ˆ(|šãEB;©úî[ÿ²|•nõ¤7*qÒi:êÓ¿)¸þHG[ÑÚâ.—ªëú‰ˆPÐ,Ô4ÑŸÐwË‘VA£ù¥ ÑèGiÎ$úD´àHœ‹ `E*RHƒã$!ˆ°ùŸk +²À£ó‡ýgþî +·söØOµ¾KbÁŠ„/—èÓ0Ó8w%кù¤Ç¦Tíþ£jg¯Bîüµ•Ló×Wèó¼}šTº†T|]:mc¦W…vŒÍÙ´ýóëŒÁ8úÐw¶Xqòb¡s‘—Ä_Œ<Õà´¤ÿ­Œg©Ì¶26]ݧÿoÕ\5þ$É™ò+EÌoDü,óëÚ'`špÙ¶¤‚zÓLýxö ™p–­¬1Ý›NM È ¨"×kÔ%õÝEG·¶(ñìw+oýµÛ—.c‘¯cõ׋;¯$Ks±5DSëV FW>;H¸7‹¶Pý¼O£Úè¬? `%UC‘ôªUžÝ2Þ!¬WI–ü×Uh[ýëÅÄÐ,…O|±Þ"%À™ÿQÁ½½—û`%à8¢ÞóŒ¥P|-õ¯ˆÖ´ Z®BQ¬ÀÅ–K`¬›Á!Ç)4b+‘¶qHÛ‚7a‘6ž5t@’;ÝÏcé8ÚÚXšžHíF$wÉËÀ»„‘L½1 F9(Œò'ÑKà§Ê(–] ÏfÒ' wi¹1Dja.¨¶íp½ fº¦Y­Ú)ºž~+ÂÍS-v”În¸ÿÜ|´¡0dˆ¾uWŽÍä¤—ß r8‰À_Ãb5Èy—k6rE–±\dŸuŠ76qôìà¸ì;hs©÷˨ßÄå•Ö=Íèæï~} ʹs¯ÁhÜš§Ç' SrñX¹ÀèÚâ…oðKDþ¢¦hyüUï)r!zïC9xvÝÒÒj\·_Èâ›~É/ö ¼·$]`¹é6ÛNžÃlFèNž^¸“jZV—®A“Œ‹›ÍÌt Üf{aöQ3ô}{€òÐÔÄðÍñÒàˆUPŸ;ÿKCºÇªÀ7ýºÌôòf¢Ñšè8qf24Sôƒ©'ÊŽÜfLGx} ™–3e©ÛøëOÛXÂ8^BM>ÝàµÊV¸8OMÛLxùy—Ç!<Ìy… ܼ&lÎAnz¦Á,)šå:hÊþtRû¢QÒ;óÙwº¿”WˆdG½Ö²Ë{|ùŠ"æ}KZß~¿‹…°ÙÍíð4.T¯yËÌ ùÖÛ—B[ ‘!Àþ„—Ï æ~‘ð?C"e¯ endstream endobj 567 0 obj << /Type /Page /Contents 568 0 R /Resources 566 0 R /MediaBox [0 0 612 792] /Parent 559 0 R /Annots [ 565 0 R ] >> endobj 565 0 obj << /Type /Annot /Border [0 0 0] /Rect [322.727 114.456 451.273 125.365] /Subtype /Link /A << /S /GoTo /D (files) >> >> endobj 569 0 obj << /D [567 0 R /XYZ 90 720 null] >> endobj 570 0 obj << /D [567 0 R /XYZ 90 720 null] >> endobj 566 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F53 19 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 573 0 obj << /Length 2404 /Filter /FlateDecode >> stream xÚ•YIoãȾ÷¯Ð­)À¢ÈbqkÀ—$3Àä09´>$Aš&KÇ\4,ÒjùñyÉ4<jå«Woý^Éßxðó7©·‰ƒÀMu²ÉëOžÌ¾|ò¥·ƒ »ÅŽ¿<}ÚÿúßsS/õ7O‡%‰§bóO'ÖÛJU8=˜æX6f» í¼*l§3Ó™&7Û?ýýÓOOÓY¡R0ƒ;Þpø›ÄM£H#3~ ÜTù›(Ñ®hæÈ¶µùòÛø0D”GÛhyÿšu{{nÛjŸwm³Ïz7«ªö²…óBçÑ‹´æî¯Ü´—Æt]Ûö<>víp~¼œŒ©x¢o‡ü„ÇÝ‹jÆ®§8>róñ—S™oUâœ@<¡v.Øo‡ªàaÞ™¬7ÜÏnM}îqו‡ÖäCW.gþåùº’¾ #jɈò"7Ô Tâ`ºð Ë:t?w~vá†^ä|5#K•m¹we¾;áéj{Ss¿¾amÈ*Ÿ³£±¤ •„ñf箊>mÇ–ÒŸÌóAèê$œ™_cÛ]ìÉž¼­‰‚©–¶Ga˜'‹¶ùÜswh ÓÙ~Ú9mUL’%–J˽\t”žÁàcGÌ|°æ0T.ßX07`'IDß+mö\•Í‘édüLl}ç……©Loì,Ù;šPÖ¡óË—×ã)íéÍtà€"|8H ïhÍñöÜ—mC*‚i{%•õÙî¹Iò7 åR]ʈ“%n¢Rq2%NV”Éû¶»î›¬6â(׳y<”•Yu»‘Y8Kßbpñ{†6qL^®ØKá&` ´–q3:.¶ ¢0r~äû«›êʳÏL”H›oUðµB-¿—óÎU:\Š <çé421‰÷€ŠkÃR^3rïÖ'HRkR |7!§áÅ ¹—-_…F'é¼nA Y5°ÿÝŸ™nN¾Î÷Y9R%`ÔѸíaRäê`"ôž‚•Âî‡t¦“ÀE^VéD®šÙ†à±BdéÅ7”ìÇW#Fìi ¼–2D¿ö0‰ÕŠ`)*@;Û%Ú€)`ÚWN>fB‰z d¡T4,š£`rŒ5/HLù¢6¥ŽíçÑ:qì±õâ”ø •oÆÉöC±}œ Èä;ÙSʉë¬g~(Öø`ÂÓÈÈâEÆs˜Á#[n T–bÎ3ôXû÷q¤™RU )ävŒ/—Uöc”ã—|LA‹t4.4-^ë-í0ÂyE;eƒá=7î R­ocô¯ÿxú ®î‡V°‡bÃöŠ÷Ç+ã 3Ç¡Ê:TE<ȸ¹Ð~´ÌõL"õަ·¼¢$¥ü‚Æ[cq o:w-圅l¬}`Ú®2ÛUÏÑG¬<šƒ£B/=!ñ\åùK¦°½âZ„’ÉgòÃtÒŠƒEàóéäóŸ™KYUÜ›0 Z¼ú+…±î§Gaá‚ÉÈMN<êËZ>˜¼lya+»Nâ|~’ºð{cŒ“¥Ä©Xaⱑyv(˜Ï[Û½-/SPà¯d¢+ʨHµ“¯«Öö<5_ƒÈÃ5]%eŒ5ܤn4ë¤k{D†k9!qCOMºËò²šá!°@3ÄŒ¼àV“ ¢F¿ùm°ý[ÄR<˜þºöWÜ*b²” £¥ŸD>¸&œ5t²B,"ÃSÀ-€W žFG§}rn×V²p’½¶ü¯ÐB•`;‚QìWí‘·±ÊÁsvQ9vý×FÙÜø“ˆfOCv FyS9‘õ¾Ç¡î›¢)vƒ(Xø£2A…z p‡¡›Ãã‡Õ소ÆÀ0ôòT îZ€¤¡`0ƒžr‹EëÜÍh {õ`i&zLê7ðq§|HØ~ú>€¤X´À›ËšM­¤úìÙ¿ó’G½Š0ÓÐõÀ¤¤Á"šà¨£ãðú)ˆ ’ I+]ÔZ)9Cnº††SÆ‚~v–ôݬd˜ûîúŸ¹G"L%×áîFHd|Hc. \í%7µ_Üœ^Úµ<;¹²ŠÏ6ÒbÔÂŽäYc¦kñ€Ól°Ö±GáK_‹D‚ïÕÕ¥µ`ŸÍJi½°Þ˜=÷$RÇþìÿÄŒðb~4«|è9wÜßDÄ¥S6ChY)H†Ð~w•lc)ê1tCg×{DÆ3’ùãŒPwX\ I97T)3w°@w’` d/8D|ÔŸfÞ–—•'‹ŒS}°&Þ(Y¾­à¦9 #gÃx¬åU”Œ:z2ͤ#qUù²åR–÷lY;8às&ëʼnŒ›:ûQÖTß×<QwEy~˜P™•2öiÊ$Sl)ë Õ-®›‚“¤…Ř×r¢ÚJƒX!þ}d÷ q‹úX¥˜2ê3×€$G)Ìh•kÎ`éz8dõ·xg[9(ã†òŽš<C¥G>…hÏ+é¡â"ù.>ÌÛót¨–ð´¼À{ÀKAÈöX믥¬ÔM¢ð.Lâ¯k¡2VnûÖXI¬î(öÝÐä藍$\€~´ó3BBÀûˆÔQ\©ÏÖÓ\Û’‰Ÿ=‘bK8&h½ãÙoL¼*¤ó•úwÏOßÊBlv›g1KÓ½’ ˆÁBí—•ô%¤€Ëtõm“™ûùuhŠìú¿o¦hŒ…Þ—ù%¸{El·¯Ú<«ö§¾?{äbŸå9@ÿ‰ù^è}¨M9Péû÷àlôÀÑÕíM±Šl¦W+:‹^œ¯—“óe9Hº²E;_!¨à…¯jSáÇg1ˆXÅ“ñŒ'×^7•«ÓéuñàúÓ‰‚´?Ù« +ˆÉ¥I@ÛsšÂI.}.}µ·(}aÀÉjƒ¬ë®ü1ù5}ÈÍL ǰžÍ§J%«T¡ë±–€aZ2Ù(uãäÆÑÙÒ£±>‰o2R"O°1׎;³†à„ç˜ßùYg[nÙ÷bçHÀ¡›?ᡸÞ:âù­CfUÌQ^à|…®)åOÌ¢… ÆFý¸þÌÖ°’8 sȆªð?è¬oì‡_¡çôÀƒß‡VŠ-*Û.«vy6>}ŠG׿˜Ý,Ý ò)5è\ ´5¨ÊÎO¸Vþ i†úÙtkq"uU2EÔg:ó-Ál¿vuô§H¾ü1šþŸ"ZODñŸ›ÿwÀ} endstream endobj 572 0 obj << /Type /Page /Contents 573 0 R /Resources 571 0 R /MediaBox [0 0 612 792] /Parent 559 0 R >> endobj 574 0 obj << /D [572 0 R /XYZ 90 720 null] >> endobj 571 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 577 0 obj << /Length 1060 /Filter /FlateDecode >> stream xÚVKÛ6¾ï¯0’ DŒ(Šz¤I  ½(|kzàJ´ÍZ·¤v“í¯ï ‡ÒÚ…ƒ ‚–Ãáhß|Zl ø›®Ø4Rò®j7ýé¦HÚãHRù™Å‡íÍëÏJlDÁ»¢›íîÜÅvØüÉ>ôÝl|–K)Yõ&Ë«J±;½7SV¶l¦ovÆ›©7Y^ª¶kY£²¿¶¿Ý|Ú®±UY>“Z<Ÿ]ÝV\ÈŠ²û}!Lä`HøRˆÊÌ«ìX9´×=ÔÈÀíÖ/‚!³0{;íÓ¹öÉS°ûÉ¢»^S­¯°Ø‚·:HÁOÏÉÙ-`аäù«·ó PE³ƒC³¯øÏ$ \pXkf¾Í^“ ®ß`±‚”ñÁÒ0‰€ç¢\©:]Ø„û ¢O¤çÓ€Mг 8KÌïíFT0æ*tÓ¬£ï…ž”-›–µ_¸éÝ餧6¯€`÷xæ€:hè”>î)i”1p$ØžÌf}¤²XÐàŠ!vfÚÛÉÀ˜+»*b‚jê#Š»Ñb}QŸ²íG³ ‰ŒùZÚ4)¨ÂDðë sµÑ&3g3PK\2‹”‰Rõ(h;€©DEr‚¬9¥yfe+x+Ú…>ƒÙAÙï®Í¯ªà(%C,5D®PR5\ÊudÚ”¶óƒñ)oGøHÒ%ü xöûå=N.‚‘8æAx±µáûÚÌÕrKÞ¶ëöæÎ;;ÿxu .›'` b¯‰P²©™GzÃBÚã¢Ø˜ÒE’ Ú==\ÞÛÁ$íŽÖùz–¢ëx£ÖçäOó!SŠ·x[ðnF +$1a^\–òs ,AdÅz P>Óê`§ï&ê‚™IÀqŒëø1âàfË,oö‚”Î?Nn2/×´÷{3†ä(þrÊïÓÖ¥ˆš–=¼œ_¡…ð ²Ã[>\üHuŽF?5$=ž)ª\¦Ì@;QcšYv"Ýjô) Ö›>††À—ŸzÿÁ¤¨E endstream endobj 576 0 obj << /Type /Page /Contents 577 0 R /Resources 575 0 R /MediaBox [0 0 612 792] /Parent 559 0 R >> endobj 578 0 obj << /D [576 0 R /XYZ 90 720 null] >> endobj 575 0 obj << /Font << /F51 5 0 R /F67 34 0 R /F31 21 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 581 0 obj << /Length 1631 /Filter /FlateDecode >> stream xÚÍWÝoÜ6 Ï_adõµj}ø+o[×bŠ­[ò2´êغœPŸ}µ|ù@Ñÿ}¤(;狳"ÆàbJ¢È)’¢xÊ8Ȥd…ʃj{ûÙÏ'ÜS0D?]œ¼xð€Ç¬ˆ \¬E\ÔÁû0KW‘(„”á˵n¯L«W‘”*¼ø•a¯×º×m¥W/~=yu1éJ„øäx€&WLªTx4i®—ŠÐ™­¢$!Ààam†1W¶¨ýذ•Œ oÉ»•ÈCݯ»~k{‡¥­ŒRá‡8‰0.º,­®aĉEƒ ³âa{Eã®%þAßѨ›VzZiÌÖ º¦ÉKÓÂæ²¿;æDc·¦I/…­"UˆðÍzÎ v9C$ã ÙQCò`³ZSÑþSWx^{8¸Þ"…¹tï^›ÆSç®h½³46-}}¢©pØÃ©ÁvS6X6Áà€®`E*R„%…ÃqŒË—ãñeºŠ<I^0 ¼ÞŒƒÖ ¥˜,òàÆqn%R1Ü×ç'Ðí1W›€?e–:i"–“ÞxAoÌxQ2M˜(ä?éÁù9ã¹8Ô+yG—¦Ê]Z’É<ƒÄJY’%G)xFþI³ƒ páq¼ !k á“¥jJëóu&\(ªÆS=;£È¿ªd” híë‚&ð*D–ߌx¢¡‹.u„ðtM²ˆg¦¬7ßC4xyçÅ(ðtA£bY<åÖ—}j"¸ c ³”É$™Ióxâ꙳3õ ¾uöIFuæîåG@–üy³ïñ^IDžšv}êÈ8ü¦@T_ºËGÝ5ÜŽr… ‰© »ûáÀH¸¹9¤ixºv£²1¥=]âká`•ÝôÕœqV¼ThF–¥Í¸X«[•;½tšG;ÿ¿q1Ïn,˜Šÿ6½çešR -NÓ©¢ˆG+rŠ4ù*Ù±^¾Tôáº#îHµ¸ѽ/éÔÕAé¶ÝÖOéÛr»»¯NóŠ“3¼Ès–ªb©˜Qùâó<´ûV,U·¯º/ôP½€xÛ–ö³]JçŸu£ýsû²k‡Ò´î’wa/ s¡Ÿbñb`ÿ¸Ûé¶~³þ­;ßW›·îíâ¶rtgá#þ^Nr,ç°ÐD3;<¾w°Ã¹î!Ó푹‡@ÍÝtv°¬ÙÕ3{¿‡*ÖÓLìêG²ýÑ—]µ¸ãÛb%‹• "É™`¹~VIz ôv ¶´ø…†Áúõï~¨ÂvZ¹ß×xúÓRÛÃ!³lêi„Ï1ÈLÁµ8]–Ï< Ö£pÝ$çûö÷s"}ìôÖbç˜(xÆ@Rs‰ÛZzÐPŸ }œbÞçâ;MËbhÙ÷¸8GæAå ðþ„'îQ@;ê‚€c£7Z[O’JÚ‹mãe6î<šîHÝä]Â-<-ïqæÜAEåòÄñ˜5}ÛΩ.}k¬;Øß½.ë»U.CxòäyæCجµg;v­{ åR…øM»ôª¢&äR·d~œtNǼtÍkoŸÑšó&ò—uíÙ'm¹u Ý+Ì­õÚ¯:(g)ð‚\ÄÈ€'k玤v=ñ¡x|Nƒ˜þІî¹_Ò•ŽGáÒ2rä endstream endobj 580 0 obj << /Type /Page /Contents 581 0 R /Resources 579 0 R /MediaBox [0 0 612 792] /Parent 559 0 R >> endobj 582 0 obj << /D [580 0 R /XYZ 90 720 null] >> endobj 449 0 obj << /D [580 0 R /XYZ 90 720 null] >> endobj 579 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 585 0 obj << /Length 2408 /Filter /FlateDecode >> stream xÚ¥koä¶ñûý Ãia-â•Eê}E?\ ê"¹g+p´Äõª§•¶¢äŠþ÷Îp†zøäKÂvHކ3Ãy[œð'Nòà$ C?²“âð&àÝ/oC[@ØÎ0þvûæâ‡XœˆÀσ\œÜîæ$nË“_½Ë½:öºÛlÃ0ô¢·›mÅÞåNÝëf#3¯§ƒNït§›Bo¶2ÎòÌKÓÍ?oÿñæýíxw,åo0‡¿Í]’E¾#âî3ÞHrŽúA-Â…î‹‹}kzã×Ç’±$³À™pøg Ošzûª@ñö´4G+ótQ} D¤ íö{…â§ @ú™öT§¨ë) "–< bÏTÍ}Í»mG¿e;ܹ½ð‘!܃bîðàŽ4J‹Á †•;`Kukø¾^ßmHrÏÄP&<+vº¹¯ío¶IœzW;:~Æ«Úa$?ʃJ$ã=LŸç¨oé>îèÈô]‹ ”!µ†<£Õœ² N&É'Š«¦$ŸqKZF™P$+œöã0ñ~†'ê+Ã4þÄ–,`ÖK)H{M‰n0§GùÄ(.š¶'Œbè:vÜú™·æBà†a'±Bàf]}±Ÿ¸³Ã§·°JÇoKú–uHf%"ððhi[ïØÛY¨³ÄÊ™¶ô?!ÐF¼éqà`40kã‹ÇSm Å~\ÎBõÕh"3ÞˆO{N×âˆ~h$)PÎýLd+²f,+ü.e… áCC[Ì­!§ÖÃLz…bŒÁZHæ\€ÕH( ¸Eaì˜Ú·½Æº”ÎC ,«BT匷*¾]—UO†ÃZ7ê@¾üÂâ®¶Vˆç£Z^[RŠ™/³laÆDRB°#’hsiƆ»Ö]XQÏ´:è õ&]Å ólz}8ÇÇÎ!œÚ@üP•Ö ï™õSezð½H&Þ›Œb¨Ã±Ö–Df£’ݹÔ6®Ïy93kA¦nï²dçdp“jàè‘5[õcWõüR¡8Éü<D[Å ð )0é‚ÿ@ä±}Û ¿0û®°lD~¤€ ¯,™•wÇ£nʫ݇öf(ö?BФOOîuó@‹ëWnߤE©wj¨û-f$ÈF§£€`VÉï JÐQõ{‚þJ?Ÿ‚8 èOÓÙE£/ÈèZT+# ºtËòÌoþïš-oG%~–±ÇaVóÀÆSø!ËA¨„°ÚRL0´cC%*Zc´á#ò5Ä{Ç—ã¢7=_æ"Âú×`˜”ùRGªŸ˜À¤%"ïÑÐ%¸šñµb^E§ÃÕ|}kù„w°Þ±Ã%Ð0’}ं ºu‹6Nþ ‡ "@Ûðfæ i¨¤å˜ÁÑèz·ÕOÇZ5ʾø;úU’y—íṃ‰ÌÂ2Ü #š`ŸèJZ@†S×mQ­•ÙZ ~?ϰi§Üg…î8)ÀB•}ùLxnKÑÏøw ó2Âö±Ôµî_ !F)þz:ñ…ËÍ¿+³_ȉGcÜ® Uš“œâÄ·×uM;KYጒèXï`k´hŒ¤_Ç•­„4•$V„4dóùŽ|¨÷k²Àûû/rÛMýŠD ·Lå·$z!ÆT Œb\®æ8Ôh6RþþûÕäû1NoˮޮéCğ€ Þp¤½¸ø#¹Ö]1a/¸Š@Û2ýÿtò;drK¦, ÷M^“dGÁ²8YÊòS‹.—C'íŸîTM‹—¸±`ÊÐÞXœábŒ¸(5úZƒ>œ§1WbDg¯_+ÉTU¬¸Ý_’ 7½êV¥ÉbÇÎWŸ.ªyºˆEå÷Íjó˜fþT8©gAX HH£}2=Ì“æ'Õû©ì|QNF¢o²œøI’®¶zx•p6oxwCC1ÞU¬Œ2~Q°b/g]0><îÜwíp$ Çô!m°w¡WÿÞ)C}¤Ê ~©ràú盫_ü¨ï‡Zu´xÿtì W²ýù—M{ê^3ócg1‹Ä©MI©jF IÇ ”zŽ´¡S[íÅØv«ÎMp]ÛԎЛ2~>íö{PÇ=#÷ú©'î›R®(tEív6xÞUíÀW;í}gï´ãLÓ1GãˆÀŠINQŸ²(”8¾u7EØ\úê[ .RÛå %¡…ÚK€©S¾Æö²8œËEF?eþ®šWÒ"N¨î°>ŠÐL”áíñ||!<׳ÇÇÃÞ7Ðרõõî•$XʪÓD…Êž8õ¦)ÎTïØÀú —›ùÑ¡*K÷µCæFûÓ&Š`K.MÁ²„´Æ89hÒj*s -«Z@¬š¢íXû¢A†Ñ–ŽçrÂrj6gj­ql­Ü×i`mÚ;,úÓöuÿ)ê¡Ä¾"V„£‹Ð›B ø x:ÏÜTöíÕ¥µÁFSv¦n®ÈpìŽ× 1Ô<|q»açþö»¦¶ß9-#ŽâÅxc­V¤VÐ|Cºù†ÅƒBgÂËýHŒÝÑ®ªW{šù„iýØB Ð.±ÙÒ‹fkwQ2ç¬=;ϯë}ß_¹4~%.Dûi.‡W ´îX°]·v¶.Cñ{JóüÇÉÿr ·U endstream endobj 584 0 obj << /Type /Page /Contents 585 0 R /Resources 583 0 R /MediaBox [0 0 612 792] /Parent 587 0 R >> endobj 586 0 obj << /D [584 0 R /XYZ 90 720 null] >> endobj 583 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 591 0 obj << /Length 2555 /Filter /FlateDecode >> stream xÚµYYoÜ8~÷¯hÌ>D½HË")êØ7gÆx9ãì Zbwk­–::&öÃþ÷©ƒRKmy²»ØE€4Y*²Š¬ë+Z¬ø'Vi°Š•òÓ0Ye‡‹ÀQï/„m€a3áxu{qùZ‹•ü4HÅêv;Ýâ6_½÷âd½‘©TÊûzk«]QÙõF©Ðû]â¯ò»µ­2»þpûÝÅõí(KKùeã‰6J¬?¢•*ö#™®¢XùQ²F¯,hñmS÷Ç›íõ÷¦ËökØK{_ý…³QQœmøG^~gªËT…z®R?ájç#ÁÛÞTYc¶ê~ª‹ª³Ûs#xEpÎÝÚ¦{3Jùdi§Ë²ÎLyyWT—mgšnóæ+yá7v ‹nø*ÜÚ«<·ù¯ß|Ïü›…c^W9/ †ÐƒdÎð/ürî›Pú©›ÉÈBÉœo 4û&Êëö4Þo›¶cjAG³9*éˆH?€ÍÖ2ñö¶=[~ll^d¦sŒuÅä¶¿kí§ÞVk{ÓàŽÊö%ŒÁ »µðönÍŽ¯¶Ÿ nÇ T¾Ð‹²/•8м;^ÊäÌ4MÛà—ºïæÌú(8õþ±ˆHG@¶A~ì Y>q™Æq5}õGé°P{ÝÅËéÅ+)ÁD!hNö]²Q¨ýD$ç –“•¦u²‡ÓòA=v%>EâôfLÖ¿¯uä2ü¶n8âûÖòà­ñÈcÃ?¥¡ÈAþ#ؼ—'õ–¿óaaÐfMqì|RA„ÐMµ¯§À-™SÞ¶G­qTäW0ÂÝð|¥+ªOL¶Þ¯+@l]¡_iá-ÛÁaЪOˉŸ™V¸o¦<îcèÀðºÉmFSíýPwN¹noœJm}p÷9žfrY}8˜*Gm¤ä”ÉîÆ_Ì¢»¾4Žh Ú¶àc–ò€¤¸g{HïEYÀå“ÂÈÚ5p5í žýè ðÑkcf©œåNŒ³ðpѱ/8J/Hø.ƒÔ«ð‚;þtÒ&'íA¨‰Q”z_'à# ,-Ì]iy5FuWt½³YLâ¹nÐí„w@ÛR<Ã'fMÀT%ÜY¬Wv)Ö Ûþ£¤‹cëá<ð ›½.éÚè—á=íyfœ1ÃT@~ t:Ÿ¿ŸÚe<†'f®0|f7(‰J¬ýòf37ÅGÐE¡êɶ36ªi ÆmãEÞO®9ú¡˜ù!»vûa¨Ï.–¤&šœ~î ¸oÑd}öL¦ î)‚‘iȲ8„â¶ WFfs¿¦ ÅÔ½=ðÈy8: —#€|Ò&'­qŠÍ²—oû r…šŠ† ƒŸ~|{ó+íCg«œò`4ÆŸÆ+¥txoí$¤¢Àµ ãØ—€oê€-éã \› !¢(˜„³ÍèûÅzàËpt¢€µ¹‚cï|×Êz$æbi»Ä—28ÞÿòÌ-|x骊„ª¢ÎªÊÑìì’t©ýPëaïÿÇa¦æq,¡<‡K‘asâXÉ“-¦ñ.„d™FpOˆ™Ækó4ÐX º|¥¥ÚOãŠ7œP¡¸÷‚UŸÀQ}•&«ÏÄxX…½ *a\®Þ^üÌjÍ%j¸tG´¸È 5Xø"MW*ëÄúÏÄ+­}¹f"U«Ùe <1°«ØÁL(Íh¢’Â)$Õc”-&Æ N2&³›ŽW`!P1TÖ~·³-Ã(uI?©ìÝ”Z(¡Ž(J¦paŠ -$Ðü;fŠ]ä]·r}$Þ¢`3•„½}Èè¶ZÝ\lF^×Uþã–žî#–¾/¾°±>ïéÛº«ß˜¶{nGè0'hÛ8´gÜaÂÆ)ç:Ê‘u9¦J-v,»âHù X{,M†Ï5ô"Ð2•­ƒÖš†w¶øD À@ë©t@VúQªg‰p†u¸±¹oyhøÇµ€>LƒÍ“އLÃ¥ˆ€0ðMŽ…<§'!úXp? ~eM누{á:RqïäÒ…<òdÛ7àr؃B—޳käàgʫеO$Å–ém`f¡êôœÀ¹ÔÊãÏÂs ÷Úô^S8æôÆÝÆ+„º‡ Ã/»“Ÿ¥<Þ7ë öÙP˜Shì®™øõÕ/ׯ߽ቫâIè”BÚÖš®oìß8Æjz¥B:/zC»àEw¿4nìÁU;òºÍè݃ۅúÉ‹rzõHG:> endobj 588 0 obj << /Type /Annot /Border [0 0 0] /Rect [360.003 474.503 522 485.412] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Regular expressions) >> >> endobj 593 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 461.353 170 472.262] /Subtype /Link /A << /F (cfengine-Tutorial.pdf) /S /GoToR /D (Regular expressions) >> >> endobj 592 0 obj << /D [590 0 R /XYZ 90 720 null] >> endobj 594 0 obj << /D [590 0 R /XYZ 90 373.37 null] >> endobj 595 0 obj << /D [590 0 R /XYZ 90 215.233 null] >> endobj 596 0 obj << /D [590 0 R /XYZ 90 117.121 null] >> endobj 589 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F60 10 0 R /F112 68 0 R /F53 19 0 R /F72 4 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 599 0 obj << /Length 1632 /Filter /FlateDecode >> stream xÚ­XKoÛF¾ûW¹˜Bšûà’Ì-5b EšC£[[ +r%¡H…¸nÑÿÞ™]Š´å:- ´Ùyì|óíÐlÃ[åñ*"Êe¶*ŽW±[ýrÅÜ(p&ñÃæêæ.a+Gyœ³Õf7W±)W¿·}L·…|³¥L‚ÛÞ›fͳ` ÎìLgšÂ¬Cždy¤ùú·ÍWï6“í„óœC‰¼c±„]¹R*ž‹oÁh&‚ÆÜã@ßÐ1ÓõUÛÐN»£ßá`H¢­K ý|¡Ÿ«(‘ü!ͧ“iÊ÷»í§±8|¨ã=rJE,cþÐý¡*Ѓ{0Ê‚žfš~:³kÝÑÄü~êLïÝ•AÕôƒÑ%šZ…\¦‘RÙ*d"b.`ŒGH…Êð§® Aº¦IƆnÍ@Í>‚t Æ-d ’!±™“8Ý›¡w:O'ô"€¸MIKÇ5O!Œf[ÚvÖŒ[…¾UíØ×4{0é†Eª"!RYŸÌðܵÊ8Šs/ç"y¿»¤3”LE’§î’ùüys¨zÔ~}}IÊ£œKo Âø³$ØWŸ†¦Ú-[èHŽîö㱟ÃkXÊS¿—ÅØuç²€…oën´ݾÍ)sê]B@ïvü5f¬{ot߃µ2",8QbŒTƒº®[tëÞÍ‹pÔÅÀrK»ÖòQbº}ÕPö¸&°/kã$‹V)í. ËUÖ¼ö¥!ÜâÂCèâƒ[ÝWýºwÁVY”+%ñÚyeëH8†1e5ì*°l¥W2JcÈ$‡DqãŸkà†$¸ާ›m­­XìD8‰ÜµÝ;M%ú¾!ñWV¾j^Yy&#†üŠ=.o<÷“Š¢–N{ðÐñpqžŽ¿kÊm{òîÌ5ÿE§S(#LÚŒMÈ(“NÔ¦‘›Š#‘±ëO°àÌ;k˜Í¸gq™"‹8Dp´¨þ™´T:;˜å‘Su}ÛÁ”!Àå\µ‹Z ã—,¥„@†J$ˆDZ$Òƒ9I<\]5öBq—ªdŒÆÎ" ´tx„(h`ëf®‚ JâÕó›2([b«¾¹heæÚ”X|QEEºR³.f0÷…Ö=?¬¢KyŽð¶ N¾+ÁýÝ:—A×ï þs¶û»…†EÚ™`QO¤‡e×裹œò$TËEÊï0h$ÇÑòÍft?2Ƈ‡~í-â–5‘—4¥yJ–Љ¿µ/O:¿| 0$`ÏqÊê²ìÏfÝâ#Ô½]%úñæ·'XÂF€k“$Fàö&x)Y%¼œ‡¬¢–c±³|é©KŸ7Åc +ñÃñ¢;øßÁ«.‚wƒXµÄ‰ÙnÁ'Ø@ŸúKÐuÔg¡›Î¡»Yè˜_—spêß´9´ ½*_<–±r<ê¦t³ºµÈk¿¸9½“0Ð ýú«„áž ß9ÁÔ&šÇîÖaa¢7OôÆ©*‚KD „t)cìsì ?‹coIÎ,I°`‹Öšv Á /$Sr_£Î8–¤äAåŽy=ú\˜ØŠ„ð>ûR´÷aŸ~R;5‡¸¯óÎÞ'îCÝúÒŒ—Á¸›è*ê@\mùDØòü^À¦3ÀŽ%†#RI HÛoø^ç z޵Jž‚Z.'2…^ËÜìtÝ_¦S©€yÓ›~ Ê.lﮀMQÙþ½‚®Ìv`…¦;mÇ„î’ÖÑæ@€†‘¡8BA7hZ½¯j§ûܶ£N Èæ2áyð³ù:Vég{„Z8F ǧãÏ‚Ñ7ŒûºÝ¥?,Né…%Ÿ×ƒÆÇƒ:J—i§Â`'lÔâ»SžÍS>´·@rÃÅ< ì€Ò„¤Ã¶ÐâÌû#Ç 4ñ‹Óãcm‘úy茓j¼·0Ñ7ŠÛü¬?pøÎ4{beØpyBóäùRŸ~ΪŸÒ¾}Càö*÷IþèÙ°ï­!¨q|l»ã9M3gP|tøï€)']翼¡éñÞ‰Ù£æÖpš,Mn¼v_ ã0)½@ gÔø_øàtGñË¥*´XhwÅÂ=¼sïÈ¥k{«©§SÌ•¶¿ˆÊiq:[zlMRux§[Ä9œø;ëœ~Êeéÿò7G • endstream endobj 598 0 obj << /Type /Page /Contents 599 0 R /Resources 597 0 R /MediaBox [0 0 612 792] /Parent 587 0 R >> endobj 600 0 obj << /D [598 0 R /XYZ 90 720 null] >> endobj 601 0 obj << /D [598 0 R /XYZ 90 510.571 null] >> endobj 602 0 obj << /D [598 0 R /XYZ 90 421.903 null] >> endobj 603 0 obj << /D [598 0 R /XYZ 90 322.206 null] >> endobj 604 0 obj << /D [598 0 R /XYZ 90 224.629 null] >> endobj 605 0 obj << /D [598 0 R /XYZ 90 135.961 null] >> endobj 597 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F31 21 0 R /F72 4 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 610 0 obj << /Length 2132 /Filter /FlateDecode >> stream xÚ•XÉrÜ8½û+*|1ÑE ·™“=¶&<Æš“»cL±@‰aYÍÅjý}竊²äP„ˆ%‘H/Jm"øS›<ڤƄ¹Í6åþU$­ß_))mÁ`»°xóêíu¬6* ó(W››jéâf·ùdÑÕVçÚ˜à_•kïêÖ]m±Á_ô®r½kKwõÇÍ^}¼™çе~&´x>š$³¡2–£y¨Ç{˜WÙ`ßA\Y°s\M¬åÂïQ NZ‹fè¸ô¿}1|‡>õÖ3»Ø‰MYºaàrÕõ\p?®À¹ëñÓµÞ]+cúztçÃã ºR÷0Þ‹Aé· öÖ½U&T1¯fX[m(ê¶ë÷EÓ8IƒLdB¢‘N°¥»í0öu{Çæ§„ª068a&V&¼-…ÓTPvû=Ã*¾qç†ú®uÔ KBTp±†zÙH  ¥Â¯6vDD°ãö÷HÙ»©/ƺk¹‘ñ DÎàý ÷Ö-œÖÝ? “ÉVàà¢Äyî¹ÖUg‘Ì‹*niêg rírLÛ Vrè‹» Rå¡1É&¶qh•F¦„Fê\©·Ú.ÌVõÜ™LZ Æ`64—¾ž¬køƒv6Åc¥Óó`ušCvŸ»ÂüÞê™`ÏQ°Eq80QòA¡®øÛv#*`Cøî‚? #Qχ;÷ìˆ;¤i™’Q™„¼<­}q@Vœi€hÖ¦°•N›º—PEŽE¨Bp ñ.²{”©ˆµ°•îëyÏÕªkšý< â¹h¹ày™*…; ABd·Êºzä–‚ây\É´£mY$ÁÃäíô©­ÝQƒOÒÀ…wÂý±>ð§É­'Üoß¶m7LõîÍ›5º®C>pÜ0aºÁ0ŽçÃa惼A)1Lñ†9ÝpdŸ ’ùJåcÍ3 ïäXùžEuÃ÷,ê‘)Úü·Øíˆâ±³óæ2î”›Œn’„I(0Tã þ,ÛbO ‘!ßÖö˜%L³ÌoÝ[7–oÂÿL¯lt®Âh@F¼Y½¶·s¡ÕvåöV_ßï ¾O“ÆÌsðu»z”kcåÉGééžÐËåm4Ì­^~aÃÑÆÊžÞ×_H Å’™±&©Â-3üV€u% Ó8ÓïhuX‘Yú1ˆIî»-(Mi#°Î)Ô5uù(þ½6ñAög >¸ª˜ “-0ê5Ä O^ì;?ÔD±h„!õƒÉÝT:é©÷6°ØcŒ¸;n¾å;V (›Àƒœã?YãJ@ûžu¡Œöôƒ=¥¿Õw\'ÿÛ w{YÍ<æ86r”½•ä R^;…þšÛpSuf¨ÛQG€ÛOÐa½°%œõàN<°w9à4 ^ÿ†¯ÌPî=n×qðûÄóAæè*žƒh0 phÚފ¡a0«è”Iª4Y.`í%×¼jص†“3RñK‹i}+èLÅgÐò¸®Å#à.™£)†‘; ŽA]’ ëêÌÖÓÓ16‘âFàíDª¼¡ð±ôÄÑú;ˆ¨íлu7  ÅðÅN„gÅ#Æ60Ïù„*ÓOk( ²T¼Il¨£ä) %VÛ…Ùš†:sF“~-»-æLµ&Xbb.ô’Y‘%ËÀÖô’X=ع3 ,\!àmž„:‰é0l~ÊÀð,ƒ×V«×0²Vk·‚’[añÌüà.-Kúg_r§#«zwr%ä0›á ea©ó7œAä}˜hð²Ð+,ð&Z“n7TÛˆðO)úa\Õ=Išlòc»£e­ÅgA’çÞ°èÅ7“¦+'bla…ëU ÄÁ+çÆ2X–ÀOžøW¶^´Ž6 T~Â9wôPlÞax"mHï‹Ü<Ò;J `qú’—¾Ò—¨…õB`ØK`Ðà§°g­2òà€i”6+à°qLï…‹GdàîÔ(†ïH)$ßú±È‚X„ÿ iÚØ¾ 1Ê;s‚tîft`~‚{ó=–=@°_B¦òEýÉÈ€”V™:AÆ=ð¨±3R,!/ó«ûŸ…2ø°˜K°à/Uÿ¢M`ÞñYI¹‚öîáIÌd¿‚™$ÌŒ'½$Po‚CªïŒMâŒÙD4$}ý¸Ÿ²IF$ù26I’3:çG°`¨d9÷L%³.å‡õû†äŸ=ƒñíEQóC”Ø + ÉFð+¿aZx*\×ó»—¤C´|âb•"Ʊô:ÂþVË¿¬`ÿ-ýNÃe‘$`2µ-=±Â’(‘~˜Å–ÙgÅ Iñ]Ôü.”Çš·owkrå0õ¢ë7ø'\»¥ý!ÿÐú­3Å÷ + JEuð7ß~h endstream endobj 609 0 obj << /Type /Page /Contents 610 0 R /Resources 608 0 R /MediaBox [0 0 612 792] /Parent 587 0 R /Annots [ 606 0 R 607 0 R ] >> endobj 606 0 obj << /Type /Annot /Border [0 0 0] /Rect [109.336 542.685 279.176 553.594] /Subtype /Link /A << /S /GoTo /D (mountables) >> >> endobj 607 0 obj << /Type /Annot /Border [0 0 0] /Rect [124.338 361.478 229.186 372.388] /Subtype /Link /A << /S /GoTo /D (copybackup) >> >> endobj 611 0 obj << /D [609 0 R /XYZ 90 720 null] >> endobj 612 0 obj << /D [609 0 R /XYZ 90 648.824 null] >> endobj 613 0 obj << /D [609 0 R /XYZ 90 495.913 null] >> endobj 614 0 obj << /D [609 0 R /XYZ 90 339.712 null] >> endobj 615 0 obj << /D [609 0 R /XYZ 90 253.463 null] >> endobj 616 0 obj << /D [609 0 R /XYZ 90 167.343 null] >> endobj 608 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 619 0 obj << /Length 1000 /Filter /FlateDecode >> stream xÚí˜MÛ6†ïû+t”€šÉá‡zÌb·H‘äRßÚT›¶…z%W’‘ôßwø!Y²d¯½h€ ö°9œÍK˜F)þÑ(K#Å9É@G«—‡4Œþù@ÃÓ ‹÷ˇwÏ‚F4%YšÑh¹ºX®£_ãÇ]~hM,8ç1ü˜,Dü¸É·¦L˜Ž[?Q›©M¹2É‚ éXÓä÷åÏOË>¶`ì•ä¬Å$;Å"ÊIŠé…ì¤B9øìðQ ÉBH¿7Û¢ü©®Ž‡›çbo>4ŸÍ—„ÓÓÇdÞ=si’I ÖÆ©ŠŒŠ%pîf=t«¥¬¦”‘L LÜ-üëXµf½hÚº(·Þ|\Öå”®1ž Z ¿l¹³S*Þ¥i죎7Õ~_ÙÒ~AW?à˜ÖññàçÚÊ›·ÝºßR uÓ†ˆl‘JF$æ2|*×ncsÉ& ³ÌëàÜ|5«#nËÇ.6g±ýžý¤ÍcoÊü%Ìa3%nÅ—÷Î$!l5°è>\»ËK‘óÌ9xo ž›ýÃ!6¶²Îά L,Š?á‹7ÛâöpÑ¡ñ¯/¹ü·_\øWj;®cÆR›'ž SÄ>â™=V¥¬Í‹²?øe KcSÆ‚‹Ñò1fLa^òÌ_0”Ç ˜q f\Š f\1‡™5³˜¹ÿ~p‚¥½HZFؤeDelDš t"ÍF³¤ ÂCOš}{w†ùÁ}±Éë&Ƥ)€…¯º|åeO„/….fñ3g|qÇ×MpÝ–œë“%4Çš·+ Øî­t}ÊÛÕî[^jvÆVm¶æë lˆƒ-S´˜ôhY3×Á œ­5¾ÚÁR¨¼±ƒæãC®l(×ÁN±O\ÙIÜ÷qŸ×ݺCmš¦À¯;ô-N$œaõ‚¥µ»Ü™Å€/>á«Ãfù‚_ü"_p7_jÊ—eÂAõš*Î0åxš EYqz;K)',ƒï,]b©‡eu¬ëÑUˇøkØ\oò쨥7é);Ÿ«¶3uÒÇn“¾™ë:zUü¸$‚Ò;ÄO¤„K5sÇâ@{ñƒt*~À½øáœ?4÷'€W©R„Ÿôìå||DzQʇ¡œò c÷ʇƒ½òáøºòçÚø©²j;ý£D«1[^%µUɱàýWôP™Ë®1ç;{›zâ® âìeëJݵÄÿ·‰ù C&íÁWm×loS(73Ô%î\ýËx#¡üæÍŽ¥sà_ÃÞÝ%ÅÌ0,ˆ;SãÍ–~WLzm—tN:úÍïøŒÎ¡õËÑ#e›R÷[É?‡ìŸ÷ endstream endobj 618 0 obj << /Type /Page /Contents 619 0 R /Resources 617 0 R /MediaBox [0 0 612 792] /Parent 587 0 R >> endobj 620 0 obj << /D [618 0 R /XYZ 90 720 null] >> endobj 621 0 obj << /D [618 0 R /XYZ 90 720 null] >> endobj 622 0 obj << /D [618 0 R /XYZ 90 612.351 null] >> endobj 623 0 obj << /D [618 0 R /XYZ 90 527.746 null] >> endobj 624 0 obj << /D [618 0 R /XYZ 90 443.14 null] >> endobj 625 0 obj << /D [618 0 R /XYZ 90 358.534 null] >> endobj 626 0 obj << /D [618 0 R /XYZ 90 273.928 null] >> endobj 627 0 obj << /D [618 0 R /XYZ 90 189.323 null] >> endobj 628 0 obj << /D [618 0 R /XYZ 90 104.717 null] >> endobj 617 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 631 0 obj << /Length 1747 /Filter /FlateDecode >> stream xÚåXKsÛ6¾ûWèHÍDñà«·ÄuZwROZ;‡NÓCA‘Tøˆíß],@ )Óé©£ƒ`w±‹]ðE?¾ÈÂE"%ËTº(ª‹ÐÎ~ºàök« Å뻋—o"¾à!ËÂŒ/î6SwëÅŸA*–+‘ )ƒË®ïËZ/WRªà‹À´z£[]zù×Ý/Wwã^‘'”AН´‘|‘²,Ž*Ã…dQ˜,âT1.iôZƒ?µÍ°¿ÞÜ4·C±}‹ZÁö/ßÄÉ”;L™ˆSØÌð}š^¯W]ß–õ=‘û¦¯¸ˆY €ÁL¥±ÝmÁb%x°ƒ]:úÜ4»]³Ið¢^Àœ’Á°§µ¾±ÿŽïCÈUÛõvG1Ý‘'’%qæ4¼ª×Æ®9å¢).eÞZáúQ˜…#”KÐ>ÇíÉlgB¯Û|Gƒƒ#À`™1°\ ‡Í&k°D¤‘®›ž>ª¼/Ðø- óz TO‹h0b¤¬‰Âè‚èŠfè°(¸Z—Và=Ý9á(ú‰I»¿îÀFÎIÀ’…àt B—d6d–„ h‹àu«óO×à N~E奶`–‘äN¤,'d,‰E±;Ö‘ÍCZ;ªèh­¾×ó8`†á1Ζ© t[•uÞœ%"Ø -ø®Å¬¿0`f¥ÙÐ$…>Š¡×ÃID÷õDDî¦õrCsSCµ4ø&š1ÀN‘É‚É`†+8¸Ê‡ Ø<ìò–¦÷­îº²©Ïš¤ ]š(ñ`û ÑjÚ~Γ ˜b—QQœyÑöÒàa[hçÖ®ªP¤75‘mòÑ;àÑÂñ‡0 »Áãìæ1äF©ØEÿmS@G¼<“kxˆŽp<°§-ÊÝŽ¶ÿ{¨ö4‡Åüo5y^ÊŒ>:­.ͬbÑ®»>Ǥ #eÀ‚³ý¶ìh¦ÊÛOhbËÑë|í“Mµßé^ïžh~tx‰hfk¢ÖÆù8S~µíõô°4섟ÐWŸrM¨4962ÉC ’ãüaÐm¹ï!‘$< þX¦ ô@+…£/ ˆMìphó!Èy,ôÞ¢ƒÚé,ßG›Í<&Lø`õ˜óIµ“JS­<{Èœ*¯×ÝspQœ¥é˜È/›ªÒuóÖ\.3@IS‘rä/æ$’ŽåÝ5'(B&~RðHñ£F,<¯hœ²DÄg+JâÎÐÒLtÈ­³r!‹P?çÝö|o(àLÏwÆu]´E¿kÊîÔ9™‡CúmÅ#ƒÚÿ"qœtó;Ý æùŽˆC&cáÉǪîóX¶Å¨@-TÿñXÛÁeBÊPN«›‹ßlu)ŽªK¥“Êé÷¡¾5Gùzƒéö¦ÁLxRÇHôìÔïë“§,àsŒÿìuµ€‘(‘s·–²·nƒ9¡Æ £7»ýên²Ñ˜‡Õud>0· M|~Éj*û%Çû¯ºÔVQ*ü¢W¾,£8Èwƒ%Ä«é,ƒ¹#*a­we…efG”¶ Cw§ª<ÈÇcp«Zoû|þÚÏÔõ‡Z¸^Ï'È¥ý¬p~5²ùù6/¼y±’qVšÊ 'šÁ~ئ«ÝÊ]8æ~ðêÞûò 2ëÚõL³U’_4›vóP$%ˆé†Ñó04¾< ÁøkúŒ§!ø­öjŠÁÿ!ÿsv.Vfá¡ì·G8t½ éÔ\/ˆ µï[< ¶iŠ=/ÑM9¦MÇp, ɼ{@š»Éîy3{ûÐ-`IFïC³Ö6~qçï#,ãud/h0 ²cYY휄­‹óÞ&n€G3Ý…:35&ºbšù¨½“ÐÍí©Œ/‰E·Œ"‰=²t-%ÒézM3fG×â„k,qk|œƒ>™ÒŸ,äŽ}éÍ €ê|Æíî_%³oû]±ðP¢9¿ã>­ÕjmJÊ5zN}N“¦çÈÛúðÔ‘>¢Ä;“hƒâÐstÝ`(ñ„áì¡ó€AÑÛJsˆ™A?$êUœ…öµé¼ö& E6áÐ4ðܵFðä„ãÄ4‘rô?tæ9y›¹Nj NÀg”«Ü;”‚®^÷[DS¬i¨“jŸ³\÷«õlÃË¡n•ò;²¥_^a‡­ìòjӛ穞ÍÞ( ɉ0s‡Ö7äÐpßâc@SNógíóåSuH‰öXà;ÖÆ²NV'®9äÍú™kyöA#ÁÃ%]"Âc{·ÌàHyoQßYΕñ3/ŸÉsÕ!ôÿáJÃR endstream endobj 630 0 obj << /Type /Page /Contents 631 0 R /Resources 629 0 R /MediaBox [0 0 612 792] /Parent 587 0 R >> endobj 632 0 obj << /D [630 0 R /XYZ 90 720 null] >> endobj 633 0 obj << /D [630 0 R /XYZ 90 627.518 null] >> endobj 634 0 obj << /D [630 0 R /XYZ 90 538.551 null] >> endobj 635 0 obj << /D [630 0 R /XYZ 90 428.062 null] >> endobj 636 0 obj << /D [630 0 R /XYZ 90 339.398 null] >> endobj 637 0 obj << /D [630 0 R /XYZ 90 250.432 null] >> endobj 639 0 obj << /D [630 0 R /XYZ 90 122.013 null] >> endobj 629 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R /F72 4 0 R /F59 638 0 R >> /ProcSet [ /PDF /Text ] >> endobj 642 0 obj << /Length 1800 /Filter /FlateDecode >> stream xÚÕX_Û6 ¿O{p€Fgý³ì¾]¯íС+0Üí©-×–ã;µ^þûHQvâœ{m×{ò™")’ú‘¢Ä!üø" FJ–¨x‘mÏBO½9ã~´†ÕÇóë³óWš/xÈ’0á‹ëâXÅu¾x\nÒ]oÛåJJ¨gË•R:¸,Òµ­—"zšhma[[gv¹:Nâ –Ë׿½¼×ÖB|Ã8äø†uäªòâ´ü8…kÑh›öjÝøÂî“Ýä+÷Ö;3dëò3Únësë}•zdÚ/»Öv™ßΩ‚Oû¦·£ˆ¬d! c© `ËbIË ð v9Á ‹Ôö²J»"ãÄ%_Ä,‰"…Ò"f1Ø™°Py/lQ$Í:xB‚‘94!‹À¿5²ó9ý #¶g3Š3¡™èßÖÃ{2˜W†AL–ïÒEÖ—”:=f6äµÛ MU5¸y·¸yŽ”5US?…¸‡ÚA-%rÓÒÞô«ÎîÒ”åH2…®÷L…×1„?JOÄÔ ®ºº#Éaj´ÇΡˆS‘˜ ¨ìÂNæD¹-û ŽDЀ­gÌĬy8_æ~½²¸ó²›´§9p»/3ªa8ƒžt4…âXaoœáÊ»*Í,Ø®dHgŸH±bXC"eIÜaÝlöôq‹ö¤C9GŠ[ þs¯ƒ¾RúC·–+tôIÙŽ©úÔ S>š:w§CZy®šþýùÓÞÍyæN HÒ”Š÷s».w @ÅþC/ëõùcEÑrgÉ £åÕ2V3Pd¿¤Û]eŸ~=g# Ÿ³¸ EYÙÎ%Ø‚ƒH€%d*òvþM©|nûìPÑç ü-{ÂàÀžrÜx]¼m®öÙæ;]5øå}¨Ãí]gÛÏef9|ñ'£"=Ut±ÛY,… ®¤a‘޽è×ëÐAö¯4ÏmNÒ¡ät]h2Æ’çª$Ôˆ!Z?àœø¯Î‰ŸpNüs«™íûg¶6BiŒ,¦¹™h(UE£CNá—7jè?ͯ93"‚.’ÃÊÛßwÂE“r¦ÌâÖqn’ ƒ]µ¸:ûc®G¡fúJT%„oã]Èwš>lL9ÉãG1&1ÞjΘ{ËBKÈT(cY)_&'ËÖT­ï/¦ó( Î"y|ª¸X÷î(òîƒ[Òñcß':@äÂg§â<ø¸ï  "¦&u8}±ÅþHr¸kLð9¼ f D3Éo3‰rªBc¦xSœ³\šäæ(21ÉFaP•7ÈboKwY¢®°Ÿº)b€”z7Uü±žq“ùÊk¦÷%a¶ƒv·¡áVuÚ-¹ šï–*C·„×´–þO»%¡‡n ™ ¯cì–ðVæ‰ö‹ÍöÃeMÃÕ)ÍŽûõ> 휹‚spÃzÇ£z¦HFœI3òâé=§P3©ÆÞ÷¸ßß8vÆKmg3tŠÏðÌ`Ô¨±IËš¢j0â.£ ]€ZÐ"h£‚×QÇîÈ3×7#=öt3íš|Ì4˜Ïw0;w³†Öãô&éf±,ë¡×™ ŠRßæÐÙñ0ã³ÊwFYiuå§dë!RhxÖï}Á‘ò3¼ aØgïY+ÅL=sÿ–áÑu«²½}ƒYï'xpã:w> endobj 643 0 obj << /D [641 0 R /XYZ 90 720 null] >> endobj 644 0 obj << /D [641 0 R /XYZ 90 643.372 null] >> endobj 645 0 obj << /D [641 0 R /XYZ 90 556.043 null] >> endobj 646 0 obj << /D [641 0 R /XYZ 90 227.499 null] >> endobj 647 0 obj << /D [641 0 R /XYZ 90 151.503 null] >> endobj 640 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 651 0 obj << /Length 1275 /Filter /FlateDecode >> stream xÚµXÉrã6½û+t¤ª†06‚ä1ñŒ«œŠ}Ý29Ð"$³B‘—±ý÷éFƒ)S–Äå è~|¯ÐbÁáO,R¾ˆ•b©NëÝ÷«]? aC8Úñëêâò: ÁYÊS±XmÆ&Vùâ ÑËP¦R©àjc«mQÙe¨”~JUÐØmlµ¶Ë?W¿]|[í}ERžƒ;^¡‰åB(ÆŽGc̈́҄¦1Sà:22øjKÛÙß—¡V»Á-Î3˜të¥ÁCQm/ý.ÜqWw·Ùá"¾¼Vb‘°Ôþ´d©hR(C>GðôᤉG'S€'8ù»¯;›‡ÝÚç7¡ßñÚˆW~<ЮO˜4Éi_SEC¡ “:‚·Š7éØi˜•%‰Z:ÝÚñªî`´°éËò…¦;G3)"Ò­vÞ\WØœì´!P¶}™5ôÃ>?6¶m‹ºby*{(4ð¯±f*K¯NIÿ½ËšîµÞÃò9­ãWLOž×ºíšy?ïû _ób}ŠÚ÷õI`!ß«½ÀOE÷@'a/ö9[w´Á£"éa‡ÃúAõ)ïp^wWuµT2è²]¥½éì®á]&,9©î³4oeʿጃÏÿ¶VÙÎÎSC-㊨_3¿'\ÃK%Í.tiz3Ïh^ÓÚУ5¼>ƒÀ dîÁ m«7GOÛþžÔyÛÿŊΈEÕVº"ñ–TÐ" ìTÙ•Ã7¥Š83J½O*“2‘šÏ”j7TÈ¡âÀ—Ò#¡tÐPf‰`ÛÃÌL=*˜>cPé' 9# &øájÓ;SͼUßþ?õ4ÓIú™êµyZ÷>–cƒDú?æX<–ÈÉâXý€ w£Ê€Ðïo-qÄx4C:¾/7Aÿˆctµ?ŽOhKé¾ÝÍ9>dºï«ƒˆ`yÓÔ;oÛq Kë¾k§«…´@ä~B’zÔ‹æ—µkp묃”¢%§'Œ~OŒ.0ø­ËWïA!t×Õ#P ú-‘ïêÎh].Û°ehRÜ€e-¼eœØ*§I}üdˆNœ-ÍÖáÁúSÙp¼„’0€Øœa]Ængh‡d:„§Ýùi<’ÜÉœ¹ZÅpÁv‹Oø’YC÷×1#“ˆAÈN©)Ú¶wÜí¢÷Yfód–·ÓöF ö¶M>“& ¦‰ ¾bùD°«%_c䟹òŸÊšÕþð©?ŒÔûoáB²˜Ï×,©ãwœR¼Jíã—&Ꭰ>ÔÚh•F»Äg]M§͸àªNŠj]ö¹S 7d×4ÛMnõÎÖ€ÀÝß]èHNå¡`9‘éuM ÔÔ)@)£`²ÿ€9ÕÈJ—!¸XÕ4"œ"þ¡/¶G6·ÅODl½¯ŒµHá;âú$Z84ñ ®à³߈år3¤q>-ç䮹÷øÚ¾£‚’Ûiˆ®Ûë¾3¸Är6w;XÎ:[ú¦’ÝCr×Õ‰kó\à§øßÀú-²' qDe'÷E•5/4§Œ›­ïH@ =ØkßøþÖZŸ¬ï‘Þ\¢‚/'{+tMw›À;ŒÿIá?Æ@l6´jï°ú.í{u64è*üåûÕ3v3í«¡ÖQðÝzyÑ®û!Ÿ4PùaxbÃÿ+þô©…Ú endstream endobj 650 0 obj << /Type /Page /Contents 651 0 R /Resources 649 0 R /MediaBox [0 0 612 792] /Parent 648 0 R >> endobj 652 0 obj << /D [650 0 R /XYZ 90 720 null] >> endobj 653 0 obj << /D [650 0 R /XYZ 90 720 null] >> endobj 654 0 obj << /D [650 0 R /XYZ 90 612.494 null] >> endobj 655 0 obj << /D [650 0 R /XYZ 90 528.637 null] >> endobj 656 0 obj << /D [650 0 R /XYZ 90 455.847 null] >> endobj 657 0 obj << /D [650 0 R /XYZ 90 382.451 null] >> endobj 658 0 obj << /D [650 0 R /XYZ 90 309.055 null] >> endobj 659 0 obj << /D [650 0 R /XYZ 90 209.357 null] >> endobj 660 0 obj << /D [650 0 R /XYZ 90 109.66 null] >> endobj 649 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R /F59 638 0 R >> /ProcSet [ /PDF /Text ] >> endobj 663 0 obj << /Length 1176 /Filter /FlateDecode >> stream xÚ¥VKoã6¾çWxs’€#’zX9¥Iœb‹íˆÑKÛ#Ñ6Y(*Ù èïCùI·0`Óä<¿ù8C:‹áCgE<Ë9'E2Ÿ•Û³Øï>žQ¿Š@ :¸^ž]Ü¥tFcRÄ-W‡&–Õìàf#:#uq΃ä2Œ’$ nVb-›ÍƒZ®¤–M)È¥óbÌÓð¯åOg‹åÎwÊØ;ÁY‰WÑq:›“"Ë匌βœ“,O0ÂE¥ÌÏm®S–çתúåܺ¿¸Ëè’³êQ‚êÏ /8ª'„æ$‰A;cÁ"Œhöî»Z4q àâ?ðýgL“Zö€L xh)Œ_ת—ÂýA§ÕS˜f0¢(u§¥FµMÿNXôÊÁé„àÜ¡‘Öª<Ù/[—Oe;Ô•ß•¢B ÓâÎÐD6)—'RsY€ïJ•F<ÔàgqðeÌiÁØ„4!ü{Rí`iZ¡˜‘ß ®0)­¬‰·DYªÊ“DÔõ î–­ßÄÑÆÆû´9ગ€|[MlI“`9ŠŒÊº­§Òh;‡VV 85O3wroØEçÅ(‘­[m³,ØØr`XÓↄÂsYüg‹cOåžÄ^á«e*«’4 Ki¥·âÑb+½i5þ­Mïå²àÙæÝêG—v”e$NRŸ<ëà„‹xäÞ¥xtÆ À2Rp¾ç0B‚èóù6@Rä9ü$ƒ‹êT¯%z- 5ÔöOøø¦`YçNÛf5ôO ¢ÛÏÊl¼ x¢jtž“y^•í×f*¸„“œå£`iÁÚ…J¸7S(D îpžz|.¹•Ü.È Éc›-8³ýº0Ûîâ¡tä “¡Ó`~:ß15&Iæ¥~è:ÙT_V¿´÷C¹ùªš±y‰ºÛúézÔ<µùö™³ÏŽ5§Í_}‡y~eÍóIͦ0;Á•ɰw\6ò™^Á{Ûß«1í µÅ}=¨öº‡–-o±×È›Zô=¸}?è{9} )ïÖ­\©£'àzù‰¹°©~„u;tˆjΡ«é-Lõ=¢øc§ÌÀµj"àÆ®×T®¿ zoôPšAÿ “]œ_m£0Xþ_ uë"m;‚ϧ·†À¶ƒú®Õ \ÿÒLCíŽÚ9æ¼gì(©~‹d?¡?öé‚B;b€’õv%Çí•lÖîò‚a¯‡]=4¸0(ðzãOÉ­’Ÿà–è9ÝÙ´íjTó‘ý¸)\uaÓMÅjÜ´–^ð@˲]7ªwO˜Ã§Á¾·ï 2K Õ¬}"nt‰’öçøÖÁÀ¼/¡½œçÒgç™jNÒèK £)`žl/P=¥†V¦d´À*L> endobj 664 0 obj << /D [662 0 R /XYZ 90 720 null] >> endobj 665 0 obj << /D [662 0 R /XYZ 90 651.225 null] >> endobj 666 0 obj << /D [662 0 R /XYZ 90 316.347 null] >> endobj 667 0 obj << /D [662 0 R /XYZ 90 271.781 null] >> endobj 668 0 obj << /D [662 0 R /XYZ 90 227.215 null] >> endobj 669 0 obj << /D [662 0 R /XYZ 90 180.527 null] >> endobj 670 0 obj << /D [662 0 R /XYZ 90 135.961 null] >> endobj 661 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 673 0 obj << /Length 1275 /Filter /FlateDecode >> stream xÚÕWKoÜ6¾ûW,ÐC´@ň¤žÇÔ°›IzÈöÔ¨*Q^ÁZq#Jñî¿Ï ‡Ú•l­mè!0`‘ÔhßÌ|Ãå«þø* V‰”, ÓU±» Üéýw+ü‰Ä/›«··_ñ€eAÆW›jªbS®þôÒxí‹LHé]Wª½«[µö¥ ½oŸÒëT¥:Õjý÷æ·«›ÍÉV$Ä Î Äo±â’àŽó&NCÆeHÞÀ2a!¸Å»YûÜ;ìëN½«zÕ?I䩲îÿ xØ(ƒ½½•|•²,ŽCÔ'R–®|!ç i¼™(°òq2‘b¦ ¸kewuë”νôÓˆ óeÈâdêiBžÞÖÍIÿnÈÈÅRÒWŸó"\s‚C¡Øà¬Òn±ï†¶nïhCÑ’¸QyW¬Eêm•a—ã™àdpêÙ,r)Xñ1òÊŠåM/s–€ôSÒ€&ë¦-¯>b =…Kõf 1‰8ó¾ºW%®SÏô϶5…JÛJ7Íš{z-ïÁø.ÇÝ‘6ÿÂ#õœRU÷[„_üã¼So„L 9Pj³ä38ÌS1 ½!ÝúY½œÅPîî‹?ZfA/T(B;×ÛkÒ‹ ?¸# ÂjKg¼¢gc;_Hy—.ÓPP°A Ý9ä)t‹‚ßðŸj·¾ÖPï¾ÌbkZf Ú˜ãÌEKs4½ÚAÑù±Œ yµû²Ð»]ŽÎY¡­·Æt$žûZT1Ø,ã®ÉMO+ŒµäMóóÚ¹ôLí¸ÆÖ ºï*¹8ÓSí³ßSºÛÒÐI«hÈØ³Ð{€* C $.Î0$†ô ƒtîL¤ VõÊÎ.'×ÒsR¢¸­G³x–›ÑànßÔúBLåÐÚ‰VÚ…ÖåÖ5¶Ô‘u9nÎ͘¹f\£‹ÝM^¬¥ð¶ØZRÂŽZx@ZÀÇ:¤Nô‰pZ¤ª§ ãs¨Ý¾™±ì­5735c›8‚zìéL¬ÌÄO2`䲘¥Y6R†E8‰¡N»{·¤\ÁÂõ?ÔˆãN˜6¡ð.§¬ßh+‡ ãÑ4…°íT^:Åf( eLMCgcm¡®NïfÊ1”’–„ £fä! ÀpžxK~4^ÍÐôDî68‰|?š„ÓÁ`4 Lù˜&ï‹ê/1o(Y"NSî4etÁv´Ú:Ÿê–ž„¬Rކ¡÷Yjdxa±„.ÞÚçSÑjWËc)ïê¾Z,eŸÃâ…‚Ž*è_u¯?g¼r²|Òg¢sŽõ#Þça:ú¦kbÂ!Qá9z9²†{¢bè:  …4Aú¦ö^ݧˆß£`îm¯`¨$ÐÆo®5mòº=Æsp¼+ËÙ•cqlILÁé:ðÓ’ÚhZDo\üú¾¦Ï»‘Æ*Wãã*³DœØ8 LGƒMãµ€´"O.]x|É¢$œ#ù>7µb3´fÌÄEIQ“»‡,V+p™ä w¡H¼˜»O8^a·ý¡3§pÕhŽ$sº1œÙ©'¾x_ëmO”#ÝÝ M>òÏaß!Áêv1³)ܹùó™E<·òŠ@¦GØW‡ $Ä᪗-¤U¾˜Ö/ÝR3F`…ܵiJ‚³n´w¡Žºö¿¦nŽÙ+R÷\K^Ì]H¹ûPÙ_'M¾ÇüÑ]ìùåˆ?¿Ÿáû endstream endobj 672 0 obj << /Type /Page /Contents 673 0 R /Resources 671 0 R /MediaBox [0 0 612 792] /Parent 648 0 R >> endobj 674 0 obj << /D [672 0 R /XYZ 90 720 null] >> endobj 675 0 obj << /D [672 0 R /XYZ 90 720 null] >> endobj 676 0 obj << /D [672 0 R /XYZ 90 642.291 null] >> endobj 677 0 obj << /D [672 0 R /XYZ 90 565.778 null] >> endobj 678 0 obj << /D [672 0 R /XYZ 90 482.362 null] >> endobj 680 0 obj << /D [672 0 R /XYZ 90 395.986 null] >> endobj 681 0 obj << /D [672 0 R /XYZ 90 354.143 null] >> endobj 682 0 obj << /D [672 0 R /XYZ 90 279.751 null] >> endobj 683 0 obj << /D [672 0 R /XYZ 90 203.238 null] >> endobj 684 0 obj << /D [672 0 R /XYZ 90 126.725 null] >> endobj 671 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R /F101 679 0 R >> /ProcSet [ /PDF /Text ] >> endobj 687 0 obj << /Length 2024 /Filter /FlateDecode >> stream xÚÍXKÜ8¾çWÔ-. åXò{o»ÉÈ H{Ø,UY®öŽmõXö$ýï—Ée»I tI"ERù‘²8Dð'etÈã8,“âpé^Dnõ÷ÂNÀpZpüëîÅëw©8ˆ(,£Rîꥈ»êðŸàͽzõp<Åq$ÿ8ž’$ ÞÔêªû£,‚‘ ƒ®õ û‹>ždZ”EPäÇÿÞýúâ—»Yw*åOŒCŽ'Öåò â0óœuY‘„"NØ:æašOi&ƒ÷ýeÐØ‹`ü„ÿMð¬yýND¥‰ˆ¥‰< £T‚vöÇdF]`‹ ¦ÿŸát2ð»cq(Â2ËÜ{q¦Iz8IæÞ[Þ„ñ¨žÕfùbc:e²Õ9ugϽ¾SY„i‘ƒš,”ÙF Ý€Å;CÞküyLÓ@µ“›~‰ÒÜ@ã¶éµ…ÁSSo¶~‰DÒºñ\eAD%¸zÆÙãf°äè1 i—çö H/-ËÕ—•éŠWA œœšÀå'èÜP¤|VÖ ç*G‡¦¿ò:PY+þ©Ž"€]`™`øÈ«t43'3s0}OY“ðêF_Ý=Èå=HY’iîÞ¾~M^¾Ü»/Y„Yœy¶—NäG}Ucó'àN·”Ñ-yËGÐL#Î)†ë£aA~A@8 VSéE‡Ž™úJ º%…Û'ÊpÄÕ¯ç©{°/™×Ïlv.å>2MõÓÀvÕô–'°cЯ0å! CbhFnp9ÔÈûí¨†‘—à€Ë³ðQ|!4ÂÎ$Фjþe¦ƒh s MÆ¡Lò%ÊeåjŒl3t &¹U3²(»S€¦i”oAªÆÝO¡)–a™Š 4¹TÛƒ&ÈT$khú¬Ñ1‘tñºM£X„É-‹ÆaÒ»IÁjÇe†=Iè.™zžZµVÿ<_íIʸœ9L¿'p)¿Šçdêzל(„kðÇ7ì*Ë>‹]ÌÂJÃWDãV3n´ÌSS@¡ƒï)Iaä#é”@œ½ÕµšZw ÝÅ2‘†‰È~b*Äœ(æ3;é!&‡“8´VX­FH $…øD›¿1H»¬¤_Bs$!]ùjBÌ.]jÝ_¡b0ã O“%”D’¡d®4i‰œ­ÖjœC­b6¿«7N2)5Ãï¼…Ý:<.hºmÃ=lz«GÕ´Úep§­…ÓÐò ¡7H¦;q¼iÕ¹%`ÁìïÛGÏA vê:¦’àÛ½v¨3#ÈBöxÏõ ÇK¨¹ Î{Õ_uõ—°’-a%÷°bõ0¾kZýlYoX! C^<H ‹“xÛã |ôoêZ8•PÐ;º…ôÖ¬àXÕ\RéYEp™†áV˜€ÒRL!ÉÛŒ ä;-5ýFÓ-© ½ã\ƒe{o¦öˆ-M]¿Ã{!N«YÚÓ~ÆÅÒÅôÿ›ú‹S]–%p¡ÔÖ(^pB!NT5»ÀÓb5u@1CEg‡%Ê2’ãÃÛ4n?”ívª¸7(KßUE7/Â"MÎAe¹þYÏŒÈðCìáKÅ`(w_yì šÉ.V)$òxÑú£a/ú!2/Ç&rQ§•élñ12ʽ…ÌÜ#·q9E{ZuÙ¤§;‰G|áÏ!¸v¤VeÆl‘fCÒ·Os†)åG^p¯Až §ÅÒNv‰„‘~׸ ŒÛ+ €§¢¢¢Z^Ø@ùÎAFxs¹”£~ðÖ;xøF’wN<‹d(ß$*öü»Ärü@ƒèüÜ|,9?Ð;ÏH87ª@A}YW ŸSåÊ'†iÈíögåÊ<Üv_ŠEOÞù øo8ßûú£yI›G ÄoÏoXkX ãŽ)­&ž@ƒÁƒ«vd¿WÖ6—Æ­.<ŒýFÉé… Ó 8‰?ÎD2åæëŒ¯þóVN‡”^´ÏÌÑ,â¥Ïœz¸¸¯žoLç?€¢§ìÃE=Ï~ÒÆE(é¿HÛO$Ò‰›EÁ¨ßÏ`‘Rþ°Üâ‡àÿIÚ× endstream endobj 686 0 obj << /Type /Page /Contents 687 0 R /Resources 685 0 R /MediaBox [0 0 612 792] /Parent 648 0 R >> endobj 688 0 obj << /D [686 0 R /XYZ 90 720 null] >> endobj 689 0 obj << /D [686 0 R /XYZ 90 720 null] >> endobj 690 0 obj << /D [686 0 R /XYZ 90 574.213 null] >> endobj 691 0 obj << /D [686 0 R /XYZ 90 473.528 null] >> endobj 692 0 obj << /D [686 0 R /XYZ 90 350.785 null] >> endobj 693 0 obj << /D [686 0 R /XYZ 90 236.949 null] >> endobj 694 0 obj << /D [686 0 R /XYZ 90 127.356 null] >> endobj 685 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F101 679 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 697 0 obj << /Length 1226 /Filter /FlateDecode >> stream xÚÕWK£F¾Ï¯ð%Z8ÀР9ÑFI4ÊXÊ!‰m›,yüûTuucCpìÜùî®®×÷UUÃ6üØ&‹6©a&Õ¦xº‹ìê—;fßÎ$>lïî?Ålâ0‹2¶ÙîÎUlËÍÏžR~À3.„÷q§›}Õh?BzÏŸÂëôNwº)´ÿëöÛ»¯·“­˜ó+ΠÄoX$aWn%C&$¹ô¾,ÉvN®ü†¦á$??)’0JД9ò•™)Ô§Nâ©ZÒ94-ôCÞ ôÚîh/o|®¼7Z¬mF„W´°žzC^5>óªf¿ÐôçØºtZ;É«an¡WAœ„©€Ìpf± ï ú4L˜›Ü{ðótWè_†íÓ“}ýœé¿Ï‡ÿÐc@° ³$‘&1*äLõ*‹IýƒÑf5´œ4$é™&X¨"é2GqÞë×µ4,ŽÃ(E“IÈóÿ2ˆú5/†údž0“ u°` §QBЀ±ÃSBìÇ:ïnTžÊoô½_S‚JÎ,˜ò"˜s +`Æ 0‰ŸÐÌÂTñÿš½‹Û½TÃaã¢&ý2°ÞXš3$…CttúѦ\«?ÆQº€ ŽLÒ3xèŽÕí耇Üb z—ãÃåßLËR¦e™,¡É nºÜࢵhÖ™ Å×#C{Üû%b²Ö!¤… îmUoÏÚ±¶Ê‡ £<3@€^ÔðH;ƒØLc~$I ]Ÿ ÿclŠ¡jÚ lñ͘F™RU? @c1ŒîרÉcèŠ"qyþ aÐ}Óµãñóî‡KhÞC ’ÎÔR›$„&¹ Íêtþåón²0y·˜‚ÈA§šVf…šršç‘ýøà*T«d]Ï̼·0p&oÀZ%–ìEv(¯Ñ/ôòŒCVw„,. çði€7 u©»5Œþ„;Îy‹³š}Æ "wˆˆ†f€•=½åøÈÜ 5ýz®¼¬š~ÐyI$ç±Ó$™³œzÙÔBëjÐ]^Ïï ”ªÈ!W•(q4Ðb5¥ëhXl³©ÕNQÛ:ö'RÏ+"‹ 6ìG=\ÊŒ®’Sˆ.«3¦~ð°`&bHy2zù#¯À9ãdfeò/Æ8)Y²6î¸4Xñ;*Ì M–MåØt÷,F«cBåÚ…¼›u°føq¾G½•«ù¦<ÛŒ½´bѠѾyçã˜[ºz¹ûNÃÒÜ9“òZXùæ+±Ž}´zB ÿ¨‹±ëMæn›“t@_“eµ¯†ûªÙÝ<#?amç¾iÐLõì›±d. _ÈÞÒ0g¶¶^ð߈è²Î/þ/‡¶¶IšÀÀbì´6W }Ü"ð÷¤¥.iÇ:/4Òû'ìE·fnåÔ,ƒi –Þ^™•š'ÑÁ.m¤È,Wp)[æNÓW-P kûŠ&; SÃÅM:†çõ«Õ„÷Ù–»´à"]è:ÂzgšØÞ‰‚’‹¬·žT¶ž˜ñµÒÀGSUNäôÁ׺®ëúo=}5ç»IÕTVÆ/óf¯o¯!5£Ãûº¾wÀâWø_i´ endstream endobj 696 0 obj << /Type /Page /Contents 697 0 R /Resources 695 0 R /MediaBox [0 0 612 792] /Parent 648 0 R >> endobj 698 0 obj << /D [696 0 R /XYZ 90 720 null] >> endobj 699 0 obj << /D [696 0 R /XYZ 90 674.003 null] >> endobj 700 0 obj << /D [696 0 R /XYZ 90 602.033 null] >> endobj 701 0 obj << /D [696 0 R /XYZ 90 530.063 null] >> endobj 702 0 obj << /D [696 0 R /XYZ 90 433.913 null] >> endobj 703 0 obj << /D [696 0 R /XYZ 90 346.671 null] >> endobj 704 0 obj << /D [696 0 R /XYZ 90 261.55 null] >> endobj 705 0 obj << /D [696 0 R /XYZ 90 189.58 null] >> endobj 706 0 obj << /D [696 0 R /XYZ 90 104.459 null] >> endobj 695 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 711 0 obj << /Length 2475 /Filter /FlateDecode >> stream xÚ•YYÛ8~ϯhìK䡮û0¤YÌ$À¤Å  ²DÛBdÉ+ÉéäßO«(Kn9ÝÄ£X¬*Öñ‘–7!üäMÞ$Z‹Ì¤7ÅáYÈ£_žIn­`=¡øõîÙËÛHÞÈPda&oî¶SwåÍÇàõ>?¶[­µÖyµZ¯·ùÎ6+•Mtvk;ÛvµVQš¥Aš­>Ýý÷Ù›»qïH©G„CŠÒiy“Š,Ž '•Q˜ÜÄ©R’ðO{¬óÂþR׸åËÛ8™¬ˆ¤HR`ï(ÿj[®;»³ßˆvÆ=VBií‰ÿW û†(Ž/8öCW5;¢ž›s-£XH Š© ¾ÙLd°‘A‚»FÕôC6챫‚vKÃļ§Î! ´û÷s#ÃÞ=¨uªóŽFí·cgû¾jÏ{F-ƒ¿Ciº~ ŽSƒ·½g½At'aà«…­œä´>L`ƒ¼ÀÕaÌÒ°ÛÆFºÞmSú6¯pªÁíû:RÁ’®=íöíi¸`Qœºîìm0ƒ²×V€/ê8x,ˆnØçLPlm³«ëôYR`4 Ó7Jg!øæô©ív ÖÐÒ·«v{¿9t7y_9‘cM¶‚Q/,LŸí q3æ˜!CAާ°%† óêy»jKß︰=u,îT!>’ÙQ‡†7MXCì·Zù™nªÝ©=õõwŒ‚Š'+ONv7U€ ¤ž…s]¼ßW£~#‡(èVà€«µ ŽÐ G—A mwdQp»JuÐv´é°^ÒëX;ÓD›Dz“P§c:Ÿ9öÔ,•)‡j±ÿ^ŠP¥°é©ž?°W8kˆ •ø5¯oß¼ûíí»7KÜM$R™^pÏ]@DaP a¶ÞZ 4œ×:"°r{"¯·]Ï éSD‹ÒÉ(*4~Ó½­ë–Òô,.€¤Z9‹Ž)Á#ªÀÙDÚ%ð;“a Ï[÷¦4“©`^“¢v8Ì'Vz"41-+‘‘H¹ Ä̤bv–¸‘ýŠÑp–“ ·Ñº÷8ÛÒÀщÛB0mj6’ÊRCÞž¹æ9%'YpÀ³›: Q¥á$'Ãè9P!"÷ Q9P´ÐêhlŸ£;”Ôq0å;‹y˜p‘ãM;ÐFzâ"}1¶ ü]Úä£Ü˜ ¢ŒOˆsTv%ª¤È’äUOvâé#ë w‰ó¡ÿD`±6äÈ2êÔŸê7§R—Ô½óª8åI“G¼p1”~BxA4 l­ÁÁƒ90ÑZÅÂh¢Ô“ˆ8ï‚Á âܤ‚4ýò Xf¨FdZËL¤Y2÷¸nãÄRÈ,úÔ¤ž‚š’Ÿ@Mq$"Ȱ3Ô4– £!žspØ£Œˆ-„F§tþ80C8@èÆÄú\EÜ0åžÛcñÃ%á`{ŽÀpdðkÆhwº]_‡R½¸®j¼ÌT .öOG|FQÈ6‹f®ªB‘DÙõS››Î8;Ÿ10•ÄžÓòÔ‚gíS¨O_Qyû@rÛÃ=·£æçªUR"›YØ\SÏeÔ“(6BŸmÚAÊ•!HþÇìøÀÇ\îŒ`¤lч°E[ˆ‘fÄ€žÍè‹8‹†ÐJ”€ÃÑ­ £Ñϰ³œù4DÝT|þü×_”iþÃ)&ËD¢Ò¹}üøª¬vÕðêÓ§Ióùó%›Héiu”>^‘ ’Š–„‚ B³¼ yêÇ­ìÁƢᆧ@=Ñcÿ‘¤3”¾.“¦îæ4°åb Ò\”ðÖ £Õ†Vë —5ŠS(rZÌ€˜Ë ¬®ø"LÐÇm?­'Љ¹Âø²‚ff½£Ÿt ÖÅ3ÂëºHAðOpÒRù[ qýQÙ¤%! üéâÛ)ö;œfçö‡ÇBZ¹»­,Èö°h(Ðp±$9F£«gÕDf×éeªkN‡í–Ë ¸±2ѼœÜ9¼ ø.(ÚÃÁ9§ÊT<•7 °SW bã§0÷á×å>\9«48C•†&éÌçôh¬°¤e -óÅ IÝ…‡6+—P–4‰Ñ.Þìðû8DžAŠƒn9Ä„ŠÇ»m»7y±G¾o›EÔm ±Œ÷ „b*&̪üuµó×Ì;뵋hVd9„W*r¦ó÷¢º¤Œ@ãQhÅ/’ãk,>æ}Oà®+i„lOuÍí4^Hó.\$»¿,è‚-Ö)x¼Læfû€r¿_4†Ñ¦ÏøØÕزàG4ãTxþ s¢1g \K»Íª¢Ì/ˆ”.Š”høׂ³ô|OiJ‚ê0ŽêB°ôÔã+ (K/‚ï2©HRuWÄQê£Àq†+Diñz %š3D`ISt³Ã©1RpØ<¥ïƽ0ϯQ“iå!Ñu°%îêv“×D9=JæÛví™Ò®«ðjú6¡ã`g‡žZe…¸’§-Ù=`̵{O¢Äô¾ßœ>x€ù‚„Ÿ¾LEÐs¾Îi¼˜ä¼ò³§Ã—Ï? ú¥;[oÎuëïˆ=^xǨøÌû 0Èwò›7˜X¹Ÿy‘ 8Ku•ŸñÉŒÛl(0¹‹—”p©<ÈYyÀÇ=¸RWCÛ¡tIز&z>¥4øõOzàE?¸]Àå"ÖñR5ÐRã{¬³ß½ïãÇÐQ'|Ô0¼àÉ8º¥ï•d"Š˜ó}òR³ ÈŠ8uûºŠÀíº cʽ˜òÓ¥Ä4A›Vƒ=PkL+óQ|º„Ãß² Xb(9h²Æü¹—o»KmZ83€VIü‹½Â'4˜lÀExØC¡ß²ëÞ»'0P#ŸÎ^æL¦ÉÎð9烵ؽuW 4Ô _Áý)£q -óÐ^þõ \t ÖïÜS`Š&'?xªõ„lá’Kf„ËöèL¾¡ké—Óñçðc¾cÕc})˜BLã©` ÿ‹xªG»dæTfŒ¢ß0Úâ©Ûû‚ŸD1Ð þu„©A†d“¿ŽfbŸaªIjxh¿4¼ÔÁĤ¢Çìç©Ñá’Ûo'ÌñaòSÓ䇨lÞ"–ÁÓŸgz^µô–‚¦Nâ-%‰Dx}?¸b¨R~&ÃÆ¼®ý3hELJÓ‡áT¬jn5è×^0bô -ÇíD‘„ xYÕ\¬ñyÛ¤ ú­ºúF(á~4ÂÓ7ïo/9àn©š\Øhç²*òñB§Zd:[ú‹ ±)çjœñežÝñ‚Ògæ endstream endobj 710 0 obj << /Type /Page /Contents 711 0 R /Resources 709 0 R /MediaBox [0 0 612 792] /Parent 717 0 R /Annots [ 707 0 R 708 0 R ] >> endobj 707 0 obj << /Type /Annot /Border [0 0 0] /Rect [124.338 165.072 229.186 175.981] /Subtype /Link /A << /S /GoTo /D (copybackup) >> >> endobj 708 0 obj << /Type /Annot /Border [0 0 0] /Rect [256.459 165.072 469.096 175.981] /Subtype /Link /A << /S /GoTo /D (Backup in editfiles) >> >> endobj 712 0 obj << /D [710 0 R /XYZ 90 720 null] >> endobj 713 0 obj << /D [710 0 R /XYZ 90 538.324 null] >> endobj 714 0 obj << /D [710 0 R /XYZ 90 408.155 null] >> endobj 715 0 obj << /D [710 0 R /XYZ 90 261.448 null] >> endobj 716 0 obj << /D [710 0 R /XYZ 90 153.587 null] >> endobj 709 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R /F72 4 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 720 0 obj << /Length 1589 /Filter /FlateDecode >> stream xÚíXKÛ6¾ï¯pÑCå æŠ"õÊ-Y$@Š6²î©-P®DÙÂÊ’«G³ûï;áhÉV½Å+r8/ÎÌ7$ÍW>üñUê¯b!X*“Uv¸ñ-õñ†ÛÑ6Ž7Û›Ûw!_qŸ¥~ÊWÛbªb›¯~óR½ Ò@ï®Ðõ®¬õz#„ôþð+¼VºÕu¦×l¼y»u¶Â ø‚3ÈqáM¬¸`>¸c½‰ɸä c‹õ&Œïãzý¡¾ÏÚòØ£ùÛw‚¯–F‘Dá aÉj,ެøÇ9wO¸eÌ|0îç_CÓë|ÓõmYïˆ{§MãõG,’zû¤³¡×„&M½~±J¯V­#ó†œ5‡ƒªs¶ÞD’{otÑ´V@=hy®è$zª^‰÷L—}G<Š”€)… ã?°[Xm¸„XKø ÆCr¹oÖ¥^^vàIúÞë¢×-QeŒ–e”x{Õ‘ÜÔùKȇ/¼ÌrµºjTÞéùÝç²²°_"º­à¤Zà¶+°¯5÷z›H¹ÎÉ÷æµ »kU_6uî§~äm­$>ùœ$`7ô?íË íiù F«°þšbOÓää°Ñ&ÕCeàPÛìZuœheG¼êh=ªsL8’>•½µ×£ÒOk0Ó,mFµ»á å¾{""°‰÷SSA4j úº¥1¢8¦ƸCœbì°*¸?îJʧ‚15écøó3Ýs×ë÷ªµËY¥ºn4úšíº¡ "«åËÙÖhgC(z¢v¡ûŒÙ¸É6T2 g:Ì3ž ͵`²ËŒ=W×!‹SÏ»×Ê_·ïùð [ŸÔ'ÎëÆ$¤£iÝô{c+H}O=˜46CO‹Æ6º!ËtgE°|‘»Pe5´–·„_[CN)*Q= ”VAÞÔz˜vùÐ^n^ãÞŸ`ïf€ñijZc9tž‹@!:0äÛ=ZÇåB«Þ¸ÁK†Øpb Öœ–q3—Р¥ˆZ‡Fp–ÕwÔ@ç­j$,àbÚÙåBg®Hø r÷³ê³5 cïÚòµ-ÿ}1ÊŸdgçKãðú€CëOÀügŽ€`ì{Á¤‘;LÝaä$#ÁÔRs9:u¯ûé6w(”LÆñÈjOÒÞÔÕ3/‹3ϲ¡mmÛ!ÂØPÌbC+ª¬;ªÔ@¤p‡g½‹2^¹ÛÁÓ„­ö²‚)®ÄÖêÝP)[®ú騶  ¿EPÓú›sˆ`Ž@þÐ|”à (Ÿ4|Ì (’ô ÌPoúiË0,C‹e~q|Œ?Ý„ï®v@&,œKXŽ;áóß¡BɈ (£ò² Ë΀‘àn¸8°¡Ô²,˜Í€<"XXǘHÛÎVÓ%ˆÅÄòk ŽÄP­wP…Pgx-½ïU»ôâ‚·\èÇsÔ:É©Ô «qȯ?wS(ܳ‡×½ÝZVpÎ…±ð&—ý0–žUGã}ƒ—Õ*§©‹*ŠQT‘l^'HêÐm'¬è“Q0t$èXLf²MØí–ÂRqÙX]¶·y8ˆrßÝ °;,€<$‘{ÓNTß{ZRíCç=å…𬴯ªÐËu¡àFi>¡}ßÁÞ†{ZêžØ?èáÑT´üçr_Œ™ŒF{ß/öCΣ™Nˆô¬MU5öež½ãK0 ˆ„Ùªèm¦G•iv5(â%P¼sðp2s@ø,òÓë‘À• ¼ž]sDD<š"§#"Ìpˆxx‚.pdà€xÛ:9EŸH̱˜Ê™®ÿJ$`²¾Î™þg D<% ˆ48'¦…çôáØ»hm«âÝ:xF¹s8£YÐOêp¬ôK|lÇ 4àt“)ÔãÚž0»£OGV+=²»ÔtDy@mÏ–Y÷ö N¬Ô© Õœ=ð]D®}æ ×ÛË b2”'ðuö7‡™ƒ*æµ k{Ù £P~Æ‚5ôâö g!ŠÉ@.?qÀÇâòüë›h endstream endobj 719 0 obj << /Type /Page /Contents 720 0 R /Resources 718 0 R /MediaBox [0 0 612 792] /Parent 717 0 R >> endobj 721 0 obj << /D [719 0 R /XYZ 90 720 null] >> endobj 722 0 obj << /D [719 0 R /XYZ 90 720 null] >> endobj 723 0 obj << /D [719 0 R /XYZ 90 543.184 null] >> endobj 724 0 obj << /D [719 0 R /XYZ 90 428.863 null] >> endobj 725 0 obj << /D [719 0 R /XYZ 90 314.541 null] >> endobj 726 0 obj << /D [719 0 R /XYZ 90 216.011 null] >> endobj 727 0 obj << /D [719 0 R /XYZ 90 105.542 null] >> endobj 718 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 730 0 obj << /Length 1272 /Filter /FlateDecode >> stream xÚÕWIoÜ6¾ûWÌ- ¢ÅMKn©)Ú¨§§¶@Y‰ãQ£‘‰JìßÇM#Í0¶‹ôÌaDŠ|Ë÷½Mx“ÀoŠd“QŠ –oÊãUâv?\a÷ÃxqâûÝÕõ-Çœ ")ðf·_ŠØU›ß£›ƒè•¶1¥4b¯·1c<ºÙ‹{ÙnI)ûb{9ȶ”Û˜ð¼È£oÿÜýxõv7ëæ„qaÅ›iÊ´q˜PÄ“l“æ aʬ…wRýT·R뻾M³Åqš¡”ç Üœû8uJVñ¨†º½·§×®Çj“HØ¿r†…ïIÔhåæéÓ–óH4“[~>Ô¥>wpEkþòÈ}Ë,’m%+»5'ÉÒ@’ÄÙìЛ¾‡[ïöï;íÿÏB•‡/x†IxQø‹³‚MÌ’ éC1¦sç³ð¤ÞO0Ô³H>ôƒǺk‘Õiî&…ÖqE8"°i$=ÊŠ-@JÂmŒ#uW[Õ½²÷WÄRËkL0Jø‰W¸2Ÿ_1ËÀꌾœÙ”£”¦ŽY²f–Fê ­“­8J»Õíí¿°/¦Qñ8õ}S[–h4ZÛÌó¾ó(U5ø¨´fí$Óó¨aÑ f œ5Ø!1ƒL``óDK£»F€„ñpÓ œ‚f ãMg¢ng@Öpçˆ`vw#¼¤YÊJŠL1˜Á^Îæ(ck ÞTÕ æ¿BQOS”¤Økº¾8FŒÏÖ¼r´vg$ŒJ jÉ/‹„áäÑnúLºAHJã?@|A§õ×KÕN‡)„„e¼Qˆ]nœP?ñ§SY¯_ÁÞº¬¹#ÑâŒ:HvùfŽAò¤ßqòA”ªy´gŽG]€]>.2ýã´‚ã:ûª‹rGŸ+wOKž öNûñ¤®ï?OêSùø-±:z¿Í¡Ïµ:¬è<ËGÓmL¯ùïiI{PèÕ/ZPûÒnen´ÿ÷âŒÛjÝ«›Jêα —…a v϶R5Ò¾±‘/È3¾ÁÖr ¿ÚÉ0ÄÀú4—Àfm›• ,´°k­ÚÙTvo”=(S¦Â;ÛaZ¢r5ÔL¾«-Ó Kiáé…§²k¦c;"à„cÀ@›–jöbj”=ãg.ÛJõŽÕ Ê‚Oþ?Ð"ºà™'èuˆŽ22ŸxõH˳ô\ •Ûi½Φ^Œãg h7¸#¢u÷C7õ‚Ñ6ˆ €À2½Ón3ju2âuêÖî@ëúgjK¥Ë¾0xüƆŠA¼W¿Ê¾¥\5ÛZÓJpÎ1íl{‘­¡„S(i‹|Lµ¦í”Ý…¨3NSIh¶Á‡=xæ“Ü8{‘ø!— ‰Í½]o!ôL^)åàÁ\ÇVÙò…qŒçnˆ¼¨ÌUG†#„bÓéZ•qý>ºFÀØ ÷ÓŧÌY­&?ºÆ´ÍhP†·†áÅ»4Qw±sÅÐK¬[È‹£+¬¦í}Ò.Ëf5Á.Ѷfkn‹~˜sŽºàÓúµ>($Gù§»ÇQc¨Ž’?QÏK7Fœ)¤$¥K¸ŠøbüÒ¨ÛF#Ü$<:v• ÷Ê䋯fgb½ÉÉ(7øÌ Z(Ýh9Há’Ó4¼Àç„|å¤üì¡?¢ÿ–˜ ” endstream endobj 729 0 obj << /Type /Page /Contents 730 0 R /Resources 728 0 R /MediaBox [0 0 612 792] /Parent 717 0 R >> endobj 731 0 obj << /D [729 0 R /XYZ 90 720 null] >> endobj 732 0 obj << /D [729 0 R /XYZ 90 630.573 null] >> endobj 733 0 obj << /D [729 0 R /XYZ 90 556.285 null] >> endobj 734 0 obj << /D [729 0 R /XYZ 90 481.997 null] >> endobj 735 0 obj << /D [729 0 R /XYZ 90 407.709 null] >> endobj 736 0 obj << /D [729 0 R /XYZ 90 333.421 null] >> endobj 737 0 obj << /D [729 0 R /XYZ 90 219.377 null] >> endobj 738 0 obj << /D [729 0 R /XYZ 90 143.163 null] >> endobj 728 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 741 0 obj << /Length 1461 /Filter /FlateDecode >> stream xÚÝX_oã6 ï§îeÎá¢Z’ÿ>vŰ¡ëKÓ§Û€¹‰RçØ$·×o?R”;ur½=jš")’ú‘¢Ã!üñE.R)Ye‹Íþ"ôÜoÜS+X$~]_\~‰ù‚‡,s¾XïÆ&ÖÛÅ× ˕ȅ”ÁõN5U£–+)£àYàSZí”VÍF-ÿZÿ~ñy=ì ñgPâ7©XpÉBpÇ{“dã2"o€LY–,Wq"‚ûæºÝïU³”<°7à™¹n饨šªyD.¿H¾ÈXž$ÚƒÍâ0]¬ àH¤d³73˜˜¨'éH Ád–ƒûN󟮵j»2VâÓd®x/1„)2ÆEÖo¸!¿EXÈbE½äAMtn UCÏ?CÕŠè Ä(RŒTœŸNË–~œ"Ú{æèÂÛ,HÞt´Ê0™i°.ûß $Œ(‚§dÂs!lU]í+«´!Úâ0¦Û»ík[z>„²ÀKØünAGFY":CÞ‚Ô²×Gîl¡½LÑxã½"©ÏÍ–Ñ)LA˜1‹d6ÆPz Cvƒoå<‚à 3°²,Ëæðƒêå ôpÁò4>BVêû@6XO;Žf0E¸Ë(Mà>q P ·…ã<ÆMªÀUßÕ†˜;h‰[ä#\‘«;Ï0]=YorÛÑG‘³°­üH‘¥8ÛVfáúokº5Á–H<𑨚RéÊø! ]w´@%ö\é¶9\Ô¸ð¼Œ!<]5YãT^¸öTØòÞÝqðRV„?ÙZW}Ò¼ÑÒ{a{C#¯ÆCz8¹GŒ‚&:40u*óÑ­ƒ³uyè3fÆIÛu§èS;héŠHw°Å0 ºà0epXÑX‘ØÞFÒv–V\(ÑlŠ'-Àzœëø(#jŸ endstream endobj 740 0 obj << /Type /Page /Contents 741 0 R /Resources 739 0 R /MediaBox [0 0 612 792] /Parent 717 0 R >> endobj 742 0 obj << /D [740 0 R /XYZ 90 720 null] >> endobj 743 0 obj << /D [740 0 R /XYZ 90 720 null] >> endobj 744 0 obj << /D [740 0 R /XYZ 90 619.813 null] >> endobj 745 0 obj << /D [740 0 R /XYZ 90 532.208 null] >> endobj 746 0 obj << /D [740 0 R /XYZ 90 317.061 null] >> endobj 747 0 obj << /D [740 0 R /XYZ 90 228.082 null] >> endobj 748 0 obj << /D [740 0 R /XYZ 90 151.233 null] >> endobj 739 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 751 0 obj << /Length 856 /Filter /FlateDecode >> stream xÚå—Ks›0Çïùa¦¨èˆ›ifÒiz‰grh{ ¶l3u Üäãwå]žÆNœÇ©ãb¥]VÿŸvÁÜ àÇ$pb)Y¢´3¿; ÈúûŒÓȇ~oÅçÙÙÇ‹;<`Ipg¶ì‡˜-œîù:½¯MéùRJW}ò|¥B÷|™®Lî íÖ8Qš¥)M>7ž/Bh7‘Þ¯Ù׳/³öÙ¡O$gWìe ‡K@z”]¤ãRav0ŒY"p¶¦d2Ê»4+ó8u|΋a ¾ˆXô6‡¶Ý¤eSo÷¥:(ˆÙÝ6D[70 ¹"är ¹"äòò= ù¨,‘D8EâºNËú%†ŽOS蟞÷ÇЯIT=îTou¬ì^W„Pǃý (}&јÉ÷âP{&›6ÀáêæxGú@’³Pê÷”ßSó_ä°ƒf}£øˆOW1jŸÏÞëóÔŠ‰§é¼¸{uîë#}W6` —ø‡:çBN øŽ\ì©o‰€aG®( Z"0î:Ü :Üï¾(4~QÀ-’ D×ÑÐŽtì€âXÙбiä]°¹ŽPá!8B,˜($=êH{ õaHGÚÛÒ«Ú›ˆv¬D8ª0ìXÁ<²CË Œ»§AëYáí®€` bCóù¶´Æ+ʼnڦ¶‚žQäÔÆì¸Ä9"–†œM*ï’z+rÉ>¹ë-Ö—q9pì9 _J „zö§A"™ÖÿGyÙDÿ_õ‹m endstream endobj 750 0 obj << /Type /Page /Contents 751 0 R /Resources 749 0 R /MediaBox [0 0 612 792] /Parent 717 0 R >> endobj 752 0 obj << /D [750 0 R /XYZ 90 720 null] >> endobj 753 0 obj << /D [750 0 R /XYZ 90 720 null] >> endobj 754 0 obj << /D [750 0 R /XYZ 90 623.163 null] >> endobj 755 0 obj << /D [750 0 R /XYZ 90 547.248 null] >> endobj 756 0 obj << /D [750 0 R /XYZ 90 472.2 null] >> endobj 757 0 obj << /D [750 0 R /XYZ 90 399.274 null] >> endobj 758 0 obj << /D [750 0 R /XYZ 90 326.347 null] >> endobj 759 0 obj << /D [750 0 R /XYZ 90 242.391 null] >> endobj 760 0 obj << /D [750 0 R /XYZ 90 156.314 null] >> endobj 749 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 763 0 obj << /Length 1415 /Filter /FlateDecode >> stream xÚ¥WKÜ6 ¾ï¯˜£Øq,É/“E¤§ ] (’¼¶<#ÔcOmyýõåCöØ»nжðAEQ¤H~¤Å.‚Oìt´Ë” uœïÊóMä©¿ß?;ÃaÁñáþæÝ§DìDêH‹Ý}½q_í¾:Þ¤–Jwµi¶5ûƒRqð(qTAojÓ›¶4ûßîºùx?ß•HùÊ Çm2¹q¨âTzmÒ<…ŠY˜æûC’Êàãþ ‚ʺ3€2Yt-ŽIðÁ¶EÿÂóO·A¹×–ÂS é }ì" {¶ÎT¼h÷2Æó^fÁž2ðÓ$üïoµE³Ý+’• Ñ8?×üúþŰ’·Ï†ª…c"X9ò’L@ò©ëÁÒ[ª©uëÝKQùW—ì\¢Ci-‡ËVˆIÄÐU:ãEIØ[VxØ8¨4l«‹±q`R¢r_iL €¥ÌóJ8‘¨ªãµ–]Û#2Ú½Þ¨…H¹§Z‡:ÕS2¶aîàâm°Ðü«Ù)ÒkóÿfAU̓/hÄübòˆT¨pàî ixÅFS Õ®º±©ølcŠŠ7¨š,›}?^œå¢/}G¡(Á¼_çåª4¾AÕ€(Nÿ ¨~Ýc˜õíçú®ã .l;üBQ¿…Ž"ÊCƒÖ¾ûH¦2LôŒ¦¿ZÓTTÓ$Ù¥¿(Ào t[ó%f€@*ç#o mFK$šçc”È¢0ÏÒu$’z¸KèJYž.š]äÁzÜ”­ˆΜ/nà­‚‡H.DúÏÁ vupòÑ„ò¨ÛÛ^n–ºí~ïÒeú?ÞǶyË÷: ó«ë¹Qi‹ófg«‚÷ß#ŽghœÖ~:ù=òàŠ“Ò«D}O½ˆî5+jQ±\V‹Éæ¬yññ©.t¶Ž‡¥»4´ßEžÖ¾Fë©Fëd–‹Ä§“]ž" ×32’E¸ÆÌT„)€vb#$Åsþ¿‚ã@ðWvLYµå@ç¶\_ X®Ø˜…†Ø?•ˆóýæ áÐR:¯ “*¦U¶7ôrÜ…¶ØPz©éÑaR®~ /=^€uËÿ“ÇøÇ0N¬=¢"…ƒÿŸsþßñ/®·Ô” endstream endobj 762 0 obj << /Type /Page /Contents 763 0 R /Resources 761 0 R /MediaBox [0 0 612 792] /Parent 717 0 R >> endobj 764 0 obj << /D [762 0 R /XYZ 90 720 null] >> endobj 765 0 obj << /D [762 0 R /XYZ 90 720 null] >> endobj 761 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F60 10 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 769 0 obj << /Length 1572 /Filter /FlateDecode >> stream xÚÍXKÛ6¾ï¯ÐQ"š¤H=ì!IÛC-Š] ‡$®DÛìÊ’#Êûø÷j(Ûr¸ëí (|Ão†óâŒYDáÇ¢’Fyš’RQµ½¢~õþŠùQÉ ÅÇÛ«åO’EŒ’’–,º]BÜÖÑçøÓFíÝ/’4Mcñ~‘!ãO+µÖí‚ñ€½^é^·•^$\e—rñõöç«o¼%ç„sßI—óˆ ’ŠŒ{é²B– ”†å"‘¿P&`Ïbë8Ÿ_ îÍJ¸¿ÕíF{*~JÅ9áe Ä#ÑÊ4:–rÂ;©Ê4fpÚxmp«¦é<-ΟÝ^·ÇÉй/‡ï¾rë\þB%­z­ #öÎ-Š ôø¹Çc«®÷8p…q ŸŒœîý¡ÎQ?¶ÚÓ©¶Æ“;°Më~klân D€&–&ñ2Öt­E›v+÷^³ö®¢Hª]kÜ6 ÇŽCNpP ÚHˆ—€%«‡½ñÛ}7ï¼KíúnÝ«­%hç)¡`oΔ’œçG7 áæÙ9A»HAÅêé%_ÈI6ùÐðižM×Lì6ØjAwÛ•jq°QδnKãŠÕ‹Q³ªÁ…n7¸ë“E’ó4þ}Q¤HšQîPUks˜£û8"ý¤¶¦5í·FC»hm‹Î4Ó–³$ÛopŒO;6£R­Þ×]R¡ªkýõÃJRf<óú)‰^= —tŠåo‡`-%)ó"’#ÌÅêç¯4ªad!iYD#Ý6)‰àîTÝ\ý†1=g'yAÒ<,g"vàJ\)ºŒ8SŠ×ØÒ(͘8=e›²¨®™p\夠<’² ùä cÄ{dù)5x˜ËND„ïH\5ÊÚ)A̰] +Ê)?¼Ñ.Z(bøk.¼Éi~šƒ’îî] F 1Ê]S"2¹íj}€å)‘i6á:ª`â©fˆK&AÈ‚pp œ4Š‚°H‰°H¾î»ýî2êú­¨^XU¹Ø áBÖ.å1k›'HÓËB¨O|Àx€Ÿ³â Œ7—L_2×£‹9Õ·˜ …às‰ÓÞÛëò\+ÕX½´C· Ý HË£˜C¯t䫞¢Çå`êç> endobj 770 0 obj << /D [768 0 R /XYZ 90 720 null] >> endobj 173 0 obj << /D [768 0 R /XYZ 90 720 null] >> endobj 771 0 obj << /D [768 0 R /XYZ 90 633.952 null] >> endobj 767 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F53 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 776 0 obj << /Length 2923 /Filter /FlateDecode >> stream xÚ]oã6ò}…ߪ`mE$õY íÝè=v÷žö œ"ѶYô‰ò&é¯ï g(ɃÝ;ˆÉáp8ηÄ&?±©’M¡T\¥å¦9}HúôAðh»ÆÏŸ?Üÿ’‰Hâ*©Äæó~Mâs»ùUùÝNVR©èo{=ºAßí”J£¯U4ê½õÐè»ß?ÿóÃ?>ÏgeR~ƒÄxÃM^Üp“—i,TJÜÜï»^ïÌ㺙ðÀ[î³"Î7;¡b‘цÏÇΣYÑoMGM3ô¯i ­õ¼ªƒ6 ã´ÌüÆBq1‹E9›7œ|ª‡6QÝI©b™c-Aâ¬z'ÓêB¿Ðà7r•ÏÐì4¢4CÞ£Œ«üÆÌ>];|‹Î½‚@TO4ò’Áqí4ÔÍÙdKÀ3…ƒñÔY‹:ŽÆ."¦³Ç Šï5‰Îˆ*€C(B–HᑇÖz<+õ²êlìˆ'Š›-’ª(éUI±¶AþÌ8.æˆn%¡vè_ï² ®yá)føûžäiœBŧ„$$xYQRxúîéŽ31•³ çd 5‡óE:ìì|‚¾§Ìâà³»ø`&.Å$bk†šñíö¹DÂÉeÜm°¨Ô|‡vÎÌ຀Ë|\àš:䟗_ñ¥0ýà ÉŸ±:˜VˆóØ9û(“$ †*à/)F†‘ĉ½zš3.NØôtè‘åJF†å@zcd^Ziš®ëA&lÝ» ¬kˆáÜ!,ºC»ú¬oŇ˜aWð]‚ Ë†j*“W"Ù¾§¬¹Œ”(¹\ß åþhl—y~›q:oß 5¥J&d…Ò Òº¼(M8Z0¿”€ DüOÁ‰aJÍ#=Y>Õ ½ArÅ+õ£5=y!˜A>”»|hË΃ ³%?Yöž½W!ÕbŽXnêÁžÞTÖ”’Ï.Òò9“á,ÝÊ*Ä)0γ¹U…I¶¤Sö=xÜ`– ÅઔùùÓ߉¶Û¼*¤ðª¸¾½i† —7e)qµŒ®ª§º— /:Ôç“a'Ó¯vÒ'ÂX¢LÖž¦{Ú,]7Üÿ2Ã9´­8ä¦~Ã#]˜dœ.ï7Jä2¢9¾+¨*9gÜôj ‘ù{3AY“£åZ­cvÅ-Iàq„ÛÒiJl°èªÇ¥7ðä™Â<'?úýt:ß;þâµ€8NÙH’ƒ‡Üe2‹ Æñž¸øúà|ç¦H ¯Ç  Á\¬•èRŸÏC»½4ÇÃörúái;˜ör:o͹þ/Ø“%‹Ö!Ì¢_#ïõ0 TbQÈeÁ¹*¸fÆMZêé…ëÅ4‹K1áp9=êñ¾ö¡Ç".JhçÊJ:…tß3ª¦ƒìù¨)¤â’á_ZÝ6C¿Ì9M:—Žø¥¹ˆ¯¿ê’(jÇ:ZT¬ÝjñìÊÐi¤T*úSf‹„3îG#êA ®¡†¦Þûà˜*[µîÏàÔÓ­W¹pÕL®—Ê”ËÝýu½¹Ú,˜£n"f]-¸“ñ,ƒ’ tŒ®|c0þkA¯¿ºZ¡gøž{7=ÖW&ä’Ià-t3]Y={ Ÿ`Y"‰\7xÄŽ['¶ñ<:[uÿÛ¢Ðr-œv6¤ôà¸Óʼ£»L3›ã57ß䢕õ w/ËQ°ï -Ø|ÆγËÅkâ>Nø€ð@55À\ŸÙ…4,uõND»±£vçPýâ@ÛV2–I¾T²…|§më±v+´P§ó†ØuÛ™qm[Iúå7ÿÁ€z²±qCVEUù¦¿¬ 8']3èÈz¬o0zKléɾq‹*õWáÜø·Ã»Ã£õØùîøî•¾c“¨ÙöºÙÙìjߊõ4ΣeÁú€wéZ&øè?mÁ8ÐXá&¹Õçz¬'¯JëM®öw5ašÍa3àX|™m*⬜ k4fÚÊ­ÚB6R·§¬ ð¨–2/¦ï>¿bÿKVœX×ú’•ÿø%]Ë‚›Û¯íã.…¾9(ZÊ ƒœ[Ø"Êcwæ°¯qÓ®/“9AŠÅnï>ìaa!|«$Yñ8M๰¿‰½ÇžÖ—¼V¹8¡‰ûØLÊUDéh'‚‚O1‡îOútöæ÷}kÙ+XÜÒþýÚß¹ûž=8rÉÊÖ±òy­äz6õÁÁ«¥Zü;ú&¹(ßâÜ—^9rö½Ù5%Nß6?ßÀø¿Ì/Ũɿ5ý°ô0ÀïyáÊü8¾ã»p:Z`&ÉÜ GÞ˜p¶ÀÌ}˜-7•~“·ÀÀ3Îilº¤±!Ùb×yéœÙèþ&XA½¨²• `þh‚x›`ª0IóAÝ}Ç„ÅÙSþ"¢'Þ¶|Üå åÌà…AÇ9nýéçXJ endstream endobj 775 0 obj << /Type /Page /Contents 776 0 R /Resources 774 0 R /MediaBox [0 0 612 792] /Parent 772 0 R /Annots [ 766 0 R 778 0 R 773 0 R ] >> endobj 766 0 obj << /Type /Annot /Border [0 0 0] /Rect [421.314 615.654 522 626.563] /Subtype /Link /A << /S /GoTo /D (home directive) >> >> endobj 778 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 602.503 234.297 613.412] /Subtype /Link /A << /S /GoTo /D (home directive) >> >> endobj 773 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.206 191.445 437.904 202.354] /Subtype /Link /A << /S /GoTo /D (Recursion) >> >> endobj 777 0 obj << /D [775 0 R /XYZ 90 720 null] >> endobj 774 0 obj << /Font << /F51 5 0 R /F67 34 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 784 0 obj << /Length 2898 /Filter /FlateDecode >> stream xڵɎì¶ñþ¾bnVÓ‰¤¶98F$œÃ›Û€9-v·ðÔRCË›7ùúÔF-=j}æÐ¬b±X,ÖÆÒÄüÅEôi&8\>E‚ýò)–Ñö Š¿<zú[?ÄQXDEüð|\²x.~ ~8ÛëàºÝ^k˜?íöÆ$ÁG{rÍNåÁÀ;ºÎ5·Û«$/ò Èv¿<ÿãÓ_Ÿ§½¥>)>.6Y˜>¤¹ cmXÀÅxm\ן«+HcòÀŽC{±Cu°uý¶Ëuðø$†³c‚S׎BûZÕ5^@ö,ŠÞ <ZùõkŽbÓõ2Û¹C{jªÿºòãªA ÀÉö±ã„…e. °º"ÚÕ‘1¶)yÐ6 4x HDËUÏ¿M+kÛFصÂDø› ±'üNU)ë@¤5J¢˜ gµÔó>A=ïã<ŒÒ˜E·‡¡j›?3uš-©MFœtA'L×——…€`uÓg¯YÅÇí½"V§3³öŽm]ó½W͉Q_vxyo¯ˆm»²—céø!‹45(€ÊÃöWa§¼ÿ«í‹¨„€²êúºÖV®Ñ„Y”ÁÚ(4²ôX}›VÂx^À¼n¿\(‡ÚñpfÚºj¾ÎU]‚ó0æÐ9;8·—kçzákk× [zÝ˹’0Ò…^M¬‚ñ æ*A61Ú]³‹Çðë¡gJ6;D£™ †t Z÷<#.BJ'ʾ]îöi®æ=ù.×KNUƒ|V.!êø=êÛwpY\;8óÀãÃÑ5°Î1DŽ¿DC@ÀiGC}ʉÃKí.=C¯ÕpnGaøBªhÁŒ:¶›ÌÇŒ½ë —ý÷ÓàQ2QúEðxÅ65]M5üûuGê—½{api .(Ïè\&z¹¯CekÆÁ F¸*†ÈIâDäÄp®ºrK¯5©ÎèHbœQ…h@ÐìdSÅ# ¦wWÛùqÔÑ ß“ÝÑ|ä=ëê l+z(U„Y–øˆ°¿‚º7-Wa4‘‘Ùçá, c¼ìF„o¸@|d¿R)½JÖGÆ@ib`ÑU§“ëz†ÚF°d QÌãà›L€‘™÷­¬=WŒ.gž;[øZ™€â1ÄØlXšìò‘uï¾ê±$UãN݆­Ñ¶dËhFƒY¥S’5ÓŽ5ìÌ/”áš®0f!Ú“Cƒß¾'ˆyî/àXáÞ›÷dBjO‡ÙÎCÎÑ–ê%É~ë–q H†¯O¹:êÛLà3 $î±¶Rr ¨ì·++¶ÿ½ÉªjH×ÛÙ* óx:4øFy°]ùtµœ~;qÅa–«ÕMý¤Ññœ d[¾;µWIn0îÝWÊT»7U't¤>¤™bÀñ탚<0R$–Ål¥9Z©Ž1n»­ À[˜…µ b—â_‰0D¶³–`õ/òœz£t; ÝØ¾>WîûEâ PBÅÁÒ^nNÀÅO!Ô,ÇrÀX™©eÇf¥ÀÁ‘ùd0ð„s%±– øƒíe4ë ðªãXóøØv<€È áRÞ$Å–Ô³¥të|)#Ÿ@ySQ3<>‰_ ápn%ÇÛŠñ¡Úú2O”ø¡Ï°„rÿ—‰o|Ƥâ3&ÍÙø ®¡ Ìnƒ$ÞmKn“‹Û†ï Þ²r4m"•`Áf8a–Þƒä³÷ xð“0¿qèN{]$ì@ÅÒ9‡vœ:B #Äg!X¹PªrØaŠêXŸMâ 1ºªt2k©¼yc`áð*^Õð®të²çÆ…¯Í:>®¯Î¡IŒ¿ìûO„8Ê {››ÀK)o‹-\äËS:=¼$¥^ÿB x.œ¾âRžçåÙ§­Û ™0–Mh u·çó DÔ Õ{0€´ç˜ïr}±^§@¹HP•²ÚòŠ+^°M3¸íúª§´ŸsÕ€áå²P}2šEk»Š ‰ŒŸx83yæ>-²àßM=ÙÌYË]ÌÒL9YXࡽ€rë·2r ï !cQSs²í“ÏË íйß=ð!ÓoÆŽuíÐíõièìW¨ÎÜÓP•o[¶¢t¨t¶>ÊSµ£òtq„JŽx)EÞõ‡JW9ªu'% Nõã‹ÄÛŽËMð~W8¿H§’ÿã€CI+Ì\ÉXÏõ…ª•ÍðvÙMUZ[W”Ã5ëMÒêߌ[äG ÁV*?‚8}SÖହ9°˜*%Ã÷ÿ%Ñü ÄØs~‰õ½XSðZâý¾ÞŒð&̳ØÓHqÎT|¡ÖÅÖsDk×A®˜á7T€Ù9 DZ@O•^T„¥iŒ¡˜|ëÑÝ+u#5½5†nÜ RJápYèê\Jõw£0VÙÌMz3 ®²ç`JmŽ×»ù£CQ{‡“×H ¥” 6—ª›ò 1Ì€×]OEpºZ…0žqÀ1ñŽžãB…‰š$;Úz[':M1t[1°š_'9>¾2t%C°œÛÞ?ÀtB~—$E˜ÄùÚl9‡¨,¡«2©‹±ˆA€†DrêìED4«ƒè,ÌŠÉølýjßÐ’#(áÀj8Ýo-‡ûL'›ö @¾¡ KöDÞñì„™6:¶1ÅvìÔˆ[>rs†âOº¬öÓD^J)ik€\ÃÀ\µ0uR*M¼ó#µHDÀíæj¯ ¯î¥HŒ(ãã+Þì¢ÌÂPDS PJ¨Ž–¡:â'úªø$¶í]f«‡Väkʳ劤»­LâÛ£¥ðAÐpŸw¾~œ{%«ÇÑ"¸êÛ=nZ³v©Kݸ¹'ö®¿h’ߺ‰#Í•$–÷R~ª òMeÂpÆ×ÆV®½ä¤úa¢â$øu3œè4ÌÓIœý?ï¼[L2yêwÌnÒ n-m5@/,Žzæ¦G•›£^&nVFR”b'˜9å°x˜g‹§ VŒü@Ï‚¹£Ë\Ü…G¥FßO\8cGÏPt„’ò³ä¹êKÊ 3[D² ;J©(E‹šoKM-²ù¹ê‹$±°V¾L`«Ù¿ïÁ-h§öÛráü}«UWƒù—›Æ‰Îi”Ø4^Q4‹í„n^ ˆ¢¢Zjá’8Ô¥S\<Ñ }^H5"ÖæøH >¿PúŽ!~ÅÔpæbG„’Òp‡‘½_ºS÷¨=7  ‰55  wdŸ;ñ2ñxÕºxpýàbé?WЈáŽ&ð¢¶o´Ü°Ÿ£ÉþN/ó`埥S-×€æ­è–2iƘ,ó}Ä­®¨çiªÀq’{›ˆ]fËçâÏœäÞ”ŸTN=Δ] £¯.Wn´roê§2S³ÇËOkj1ê©n –&`üßàí8[¼2 ‹€› 0àA%S|Wæ£GþêCÓvõ•äÙMŠÙ¾GC‰&ccðbùeCÀ£ÀMÈõé-”Eä3"8›½¢O/¾6‰‚×®âð£èû +PɧÐFù­G§H½4²'ûôòtx 7ËnüðÏM«žrø¦Ÿ’‰9e•R_¢¶½L±ÙÛjü8$Ÿ$’ˆûH1ÅnâT÷-f !šõSùw&›uÉ“³\wît/çXÝì²µ°•LÓ0ÕS·eåMÒ~üì…q·ßéU|´~ÈŠPE¿Ãkš[|ª÷Dû™jãký +æ³›¾ôêÀÀ‰XžŸÞ¿ÃyôMŠ“´+²øVXc"(Vó…°ÿWà‰~[ØVüš –=ÿJ¢? endstream endobj 783 0 obj << /Type /Page /Contents 784 0 R /Resources 782 0 R /MediaBox [0 0 612 792] /Parent 772 0 R /Annots [ 781 0 R ] >> endobj 781 0 obj << /Type /Annot /Border [0 0 0] /Rect [280.933 76.476 440.448 87.385] /Subtype /Link /A << /S /GoTo /D (directories) >> >> endobj 785 0 obj << /D [783 0 R /XYZ 90 720 null] >> endobj 782 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F67 34 0 R /F31 21 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 790 0 obj << /Length 2984 /Filter /FlateDecode >> stream xÚ­ËŽä¶ñ¾_17k·V"©×aÎ&‰áÃÛ€9ÝìiaôhˆÒÎîß§^Ô£G›¹}Y,’ÅzWuz—À/½«’»Bë¸2åݱ}—ôù]*£ V}x÷þÇ,½K“¸Jªôîá¼>âát÷[T•÷U)­£g×=Õ»?hm¢Ï ¿:ÜÙ ®;ºû?þùîïó]™Roƒ¯©Q7Ô䥉Sm˜š“;ð®÷?æÅÕ$qRÁÁ„wl¬÷MíGÆÜ>1-bR§£ÿã É«Èòç÷$5ãq…÷—‘ìX÷Ãç§fô<©h Â#ï¥4zP‘D£}¾G˜`ŒýrÕ—Ë¿Ç]e4^„Œcßô}ÛZ|¼–_‘ò3ú²4:õ#¼»Z ÜpšDÄZèÏü%>9Ï¡Ž“Cj:wŠï¦*¢_ïKÙ¡«»§€Ñó· W">ßgy×2ß°C¬\‹„6b?dEœßTk¥ýâŽÏ~jweŸ¥qf² üö”½÷ûþÑíË?“,Ûƒ `´†8Ð@tíÔ_Y®8>Ú‰¸EãÙ¿g¨=d X÷ªˆ. €—⬌ð¼xFá€ÄŒƒÎ¶„(‡E$œpÃ3Ov´Ö;”“I¢Û=‘U _Ö¥´Š@ìA%HÇÅ3ÜòÔ»ã4Ô#"}ÝÎt×ÞOHtQ¨èYnÒÓú©AN ú5´¶i¾2BßñH“ÎÈ\œ€pNŒ@ÌHÛwõH\àcÝÙAö1gå¾—KM½ðZßí*ì ¢E©fÇû".â(º¾|&J‚çýyt<î¥ãÕ«­^ « qcmÝxé餓g|6 Ü0ôÞ6ÛÈñ‹Y#.½Ί ëd¼'Éß“,y 'Õæ ™șL NntC[³eør2ÂU\Aìæ©û¼´žç~º²Üûa ÉÀÚ¼é?A5>}ú×µ5+(”=’‚|å¨ÅUââ̵n$à³zú§Á¶ðàtáDº˜=õŽŠÁPDtç£ÄŠ_®à€e+˸*ó²•äþ¿ÇtG‹æ0L<šA‚ËCwÙ=! óÞ’ËE ’È¿œlø&œ1AJVÅZ—[ÚL‘‹#€ÁÊgãE²Y@–ý¼,ˆ¬gè‹ÂÉýÍ {Ù½Š<ÏQ‚Òkgn§±o!M:²£V%Äž˜B’Te<öÅ"EŸë~¦ ¼Äb€ Q·uc8ö dˆÐÜ8Õ'l½ \ñPR$ž£-{ºŠóªÌDŸÜ«$6­T\ªÉU\å³TÒâ*‘ X‡ÚNj}{ÝÿÉ…¼4Èt“8ÅÌÚTÑoÉäv~šÌ%É‹üAô‚©Ø''ûÒ[Âueb“UkÂw2ð€õ᷇ᔚè_BÏÿL†™äoð/`½AÆíaßâŸfÃÒ‰Š ¥Ô¶ç&3vÅmÇ£s? ¼Ú¸Ïs7­ávuI×›Ȉ_‹*àKÙmoQ0·rç ³G ÒÛ³ƒÑ§£üOIç ¾×mÅvŒ‡€E¤ŒY#5±7t<Ö'Ç ð1÷˜à7É ‚¼³Ch?ã\²xؼÕMíçq'yeÏRBi³ôSw²d”ð£¡zkñF¹ ©’ÅÕJµ¡ò†»(ܧ™s¸9®nÿ‚QWË¢z3®&‹>ÍqN­åÚ.”xØ/œ›€·AžVÆU±*5‡Ê¿­ [°Vk þ‘SÊÂ_¹u– Rãy²ÎóW†p_ Wnl­ÜBù?Xþ¼\úF6ÌUž28*)v¼9×_Ÿ½ ß[*BøF(Õ"ø%»ØóTb=ÓvÀF`"õ|·%㲂‘®uí½è#¾P–ùï UÏÿp‰'¦-1‚%mkžp*™ež­+;ÜÉ•݇ÛêÝ7q/4g“†²lÛŠ¤V(5åÙÜÈ”û”ïhrÊl rqDÅ#VÚLJs[u/Û‡¹:š n…‚[oºZÿÚÊ]ç§ð'ƒ¸þcãØƒ“§ôØÜ‘.,-%?Lf `3=ÀÌ.Ã9¯]þ§ØÆXIçÌp½Yš¯¹& 9¶û·Æ§þ¦rdi¼ýx+wÞ endstream endobj 789 0 obj << /Type /Page /Contents 790 0 R /Resources 788 0 R /MediaBox [0 0 612 792] /Parent 772 0 R /Annots [ 786 0 R 787 0 R 792 0 R ] >> endobj 786 0 obj << /Type /Annot /Border [0 0 0] /Rect [192.851 460.237 394.459 471.146] /Subtype /Link /A << /S /GoTo /D (ChecksumPurge) >> >> endobj 787 0 obj << /Type /Annot /Border [0 0 0] /Rect [450.306 460.237 522 471.146] /Subtype /Link /A << /S /GoTo /D (ChecksumUpdates) >> >> endobj 792 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 447.086 284.691 457.995] /Subtype /Link /A << /S /GoTo /D (ChecksumUpdates) >> >> endobj 791 0 obj << /D [789 0 R /XYZ 90 720 null] >> endobj 780 0 obj << /D [789 0 R /XYZ 90 286.027 null] >> endobj 793 0 obj << /D [789 0 R /XYZ 90 161.656 null] >> endobj 788 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F67 34 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 796 0 obj << /Length 2062 /Filter /FlateDecode >> stream xÚ•XMoã6¾ï¯ð¡Q¢¾ä°]´@‹=4ïémQ0m +‰%'ëßÎP’í¶…æ—†óùÌ Å.‚ŸØ•Ñ.O’°”Å®ê?D¼úùƒàÑV'~xúpÿS*v" ˨»§ãšÄS½ûð©QçIÛý!I’@>ìR¦Á§£:éaÁDVµÕC¥÷‡8-Ê"(ËýŸO¿|øñi¾;ã`O¼ã.»",³L"sBa±Ë ŠDǶÓã^¶+C)äîƒ0± ÝþZujè~—|"¦÷u ‰(‚ÞÔúQ}o_÷ÀJØÇv8ÒðØ~Q]‡4Þªëæa$ Y„B–Dó5c.] ÚY0ê‰Hà Îjþ Ðd2ôßãÔš¦™”L`¨ßPîu5Û¾%‘§éŒ2Lâû[>cµªï_m;1ý£±4Ð/ȹ¶W'À ÖÀeDŠ”d3YœEÀá,B’Hb‘\Â_r¯¿èê‚—áã^ÆÒøÝ}nÕ_±’-$ÝçñX‰@ù¨{`,NC™²ÖÁ)ÀÀ`Y ^ ´DPí“8ø<^zd.O™9À†5œ4Í{5€G÷àÓ°>mµ‡™w»ŸÉûõ ÄÑè¤x!Œíþ>ã¥àVÊjÚT4?‘qÙÄ´æí ú•–‰¶b샅ז"”ðÁ‰°R‰+OK¶CŸÒ ƒêÅÁ8½9Óñ¶q`.!ù||ÎK2&ÇIŽ9NܨƒZbÀ™S LûvìÕ4 –ø¿¾öhºÎ w¯l¶t‘ñ;›%•=PfÑmÀ—2e“2DÆæ›ð‡Y:ÇýGòNwC 6"V$û6ÔSl©¤¨¹"'0—‰æ,O²VÓ¾ù ²°ÉâY)J0eÄa4T´ãŠi«[pË0Z¨úÜð—ê´…PÜ`£Œ tóçÙêe¼ò5¸¯Ö˜Î]CM#£¾n+Å‘Xƾ&“ŠnÕXî;ó­Ü™"®ˆ\5¥†C¡ ˜ÇZ]cÁQHÀXg£¼$ŒÂ ƒ“…;øü2:³Á²sPX™l{:¹¾ &§¼^Ît’’â8ߢùÖ1|Öò¿¢_ùí8)ÆÎ Ôò¶+öX›x‘*?díõäy€0¾Îþ–KÉÿâR?éªO«äý?B]@'ß3øp’ãÛ°ÏÛ‹¾ó¢°ûrÁæMM%Ño@ËM¬vàøæS øÎeÞ™¡r£ÍÏ ³VƒË,%V§å,{cúMz‰‹TúSÔä´/ØxèÍÊ(ÏÜùÛöô—ˆœ"hBéÑ'Õ¸$gÄ›¼OKNt, (|`˜.õ—˱=ÜŽ|Och­Që|ËDZÆÍΜ\‹Ô ô o®¯.jkž3NwàL="Šš¦Tçáà2º'‰1‚sð‚ºR¶¦Ù¬Ü¯Ö‚©p¯ ïLö¦öJ]çS˜Ú\BÂ+œÆ–û}Ïz¥)Vã˜êD£[šœÄ|:gm“=hLÁÙ8Gûgo›4m}/‹9,gÃŽÂIæ–n^ páܸ<¶é×u ¾nPÖf"‚ãä꺒¡ëÛ—€ Üm•a€¨ÌÅŽëVŒÆjN†Ïs™€(¡,uF­+ùYÁ£Úê52.öRx”¦K­ðÍžˆËµïþˆÒ¨7—a:« =À\Ü»U”tµ¸ÝÑÁUý׆è Ù §Xu8ÿÓvOG5ré‰Í0Y³Ù~IhAÄÜ‚œ•ˆ0•ÙÂ/ÔØÐ¥ö,ÆOû‚_`KQý¹Ó7íðY)ŒÓäÖê\’sI–@­íŸ|6Pô÷â K_…C¼/wûÒVü¥Œ$hOƒ±jý6é+üWÿJÌ]®®ËfzÛ"“ïãc¡{F4‡÷¯ˆÍËK"¾þ ?8–\ endstream endobj 795 0 obj << /Type /Page /Contents 796 0 R /Resources 794 0 R /MediaBox [0 0 612 792] /Parent 772 0 R >> endobj 797 0 obj << /D [795 0 R /XYZ 90 720 null] >> endobj 798 0 obj << /D [795 0 R /XYZ 90 587.749 null] >> endobj 779 0 obj << /D [795 0 R /XYZ 90 262.251 null] >> endobj 794 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R /F52 20 0 R /F60 10 0 R /F102 799 0 R >> /ProcSet [ /PDF /Text ] >> endobj 803 0 obj << /Length 1711 /Filter /FlateDecode >> stream xÚ¥WKoã8 ¾÷Wä6¶qmY~ Ãî` Ìb=Ln³sPm¹ÖÖ¶Ûiš¿¤(ÙNÆó*Šb(Šüøp¸ à/ÜäÁ&"?çÙ¦hïË}¹ -µÝBâÃÝÃcnÂÀσ<ܪ¥ŠC¹ùì…A°Ý± xÞ‡JvϪ“Û]qï•áy½¬d/»Bn¿þºûó0]3ökPâÇæ$÷È“9G¸5É<Ù §^¸É=qu+FUˆ¦¹ÐùX +Ùi:mCäCOötP‹ˆƒ7N×¹VÅ–Á)¢#â ½àI+Ô+Ð6ŽõYQ;A»œkw›èŸÔØ‹þ‚n‚çïÂÈczÔiýà›ƒƒ38œ&~hŸüû@Žä÷B÷ºiP‘áškq­ÕpO´@Ÿˆß gœ€Ý£$þ [ ¿éžiÛ¨—­yñð…›ÌÏ“„cXä³t³ƒC‚‰îòþ½37Ä 2ˆ¬æ´Íçóy ñ½V—r/~ëiW©7ˆ]rh8ö£(U‰Ÿ"|KRo8’ï U]ˆ#nDc9'ŠS©zYŒº·òº¢U¾šG:¶ñû;¢Ñj¤ð·ÛÞ„–TdÜó·;Î"ïPÑHnÅ([Ù¡Ê‘”œÉóMI[(–O/+q· ÅØ‚SL„ÐR §Ó N8U1áHÓ=ÞiB¬J¹8Oć€éÓ£”Û KÙÞ¦v/E)ž@¤±ŒJ÷$7;^¦;éS(S¶gK e`ÁbÑÉýâŸ0ï¼óÜ™¤H9 ­Ncï¹×§#‘gÕ”…èËa %è¿ÔO¦j€Þbñ)!6¥¦µÓè\yœpqBÎoÓDÊ·c£ 5šÂ¿2QµR&ÀÓøSk5ð3€íŒf6lp$hKA#Öœp0g#œ ª=ºku«ÆùÖ¯¡âî‚P,®­BöqTºü• Ž2ŸA5¹ŠÊÉ%éBŽûiÂÅF RÜé§ÿ VTÆ©³Äɶûø”âý^uÕj†g±Ñ2Ã5&G`½ p†Ä 8V«L8Õ=N…ÄGw¦j¡ ª¬HgÝÊ—ƒ§®Dq—RHt¢•%‘‹:Ò#ÐA¢6ñzÅ«)*»©@cl¬/mê[5 ×Eù°(¸•‹›ÍõhQö¿•A‹J)H”Fu/ÛòÿÕ5Ð…"gµ-ò1[J1æ§€PÔ]|GgÊü$Ž&¨ˆB5€_×øS#qM«‡ÑòJ[+±O‹zf0uküúÍj)åPô +zJÕ «EœÛ ®="‹|ž/±ZEXî˜Àë#n¹÷I~5ÁÀðå)ä' Á°o¦©Y`}z±çæ¦O€5ƒrˆ*äADôç¿1–†ü`½þåž yÏ’NÂ0¾5AJq€ÌlÄʔ儾oê*ç™$K bŒºÃr…T‰}-2a™ZK·E8îÌÅjÓR2y+Eš(§ÕÕ±¡VG›d¹5yQ©W@ÚÜd›í`”v|nœ}ê®®± òºßF¶£âÓ¤+£V½ÀPaßçÜ{Üf®îN¥êýJ`eÆhnn/E#†a­&C~g™Ã §àá~–¤vžr•ºÑ0zz­(;Wíƒ4 ˆÖ{œ]zÞ·Û*p+Šqÿu*_×lÌ]»ˆûQº,9•œQŸ¨ÄüBq SS^¢ÂUeQèIº^UŒ_Ô†Ën-<aÊ>·g5ÖDD 1‹(‹-¹G*/ 8í=¾B'ä$ã4{tíc ØÁ˲äº3Ã| ´À%L¡±ÃL9@¬ÊÉÐ*ßÔ0Ò¼;jr8ð3F fP<ËRQAS\a=ÑÝ¥˜=™5ªÖR0÷´G×~ Ôù*¨³Pcü˜2âŠÈú4“äóèßAÂù„xpÀ~±´gPtY¼‚öÑŽsÅLà'žü)ЛO(n½þšºÎ… ?ð¹Â•“o…<ޤœJ(R –±4KÐxgM¡#EFçêMõ^ ”ò³ä fó†b Ý"çé5ØiàŽØâ[ÊF‹whs]9%J©ŠV[±Ù<5=Ϡ¼o°µøã÷~†^=ÐÖZdúf?ÞB3ÿß_}hÁÈaÜ8îç¶o0×7°®~ÆÙÞñºÍIÚ¾s[pî¯øùÓÝþ¾”•85ãº2]­m±%ÓÜfamâaHÎ#þœZ ˜ endstream endobj 802 0 obj << /Type /Page /Contents 803 0 R /Resources 801 0 R /MediaBox [0 0 612 792] /Parent 772 0 R /Annots [ 800 0 R ] >> endobj 800 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 394.483 285.409 405.392] /Subtype /Link /A << /S /GoTo /D (Link Children) >> >> endobj 804 0 obj << /D [802 0 R /XYZ 90 720 null] >> endobj 805 0 obj << /D [802 0 R /XYZ 90 559.174 null] >> endobj 806 0 obj << /D [802 0 R /XYZ 90 440.212 null] >> endobj 807 0 obj << /D [802 0 R /XYZ 90 330.262 null] >> endobj 808 0 obj << /D [802 0 R /XYZ 90 230.735 null] >> endobj 801 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 812 0 obj << /Length 1436 /Filter /FlateDecode >> stream xÚW]¯›F}¿¿Ârû€£kÌ. †(‰”FIšªi¥ÄoM0,ö&À¢®íÖùïÙ]¸pC>T]é²³3gΜY0YxðG±·Øú¾³h‘–7ž]ýtCìh ë‘Å/»›Í«€,ˆçÆ^L»|ìb—-þr^“ºåjµö}ßaWkÆçEžxµ¢‘Óš Ås®x•òÕš~9Ä#«¿w¿Ý¼Ü ÁJ¿ƒ-¾€·¥ Â\Ÿ…Ô #æŸxÌ¥Þj„ÔùàV´€8jEœÃ?L²'±K¨Íí9€¼þ¤23јg;§ÝÂR½˜u™›#ñ‚§­¨fIZµê*³“¬SÃØúlx¢Rô{´.ÑýþëAhHÜ"ÑnáX­$Ð9)oÞ¸PŠ˜9ï…f}’d®Sõ]˜LU§½Qæ9©ìŠ ‡ÄI꺪.fÖJcÐp %)̆ÜÃóRmn±À±“æ¼:ˆŠ[?E¡S8ÙœÈnê6ãˆÏsŽ6©¬2"Z!«Æúlz4u¢¨ë8)b²ÒÀBç#Õu|FŽŸ{Í7ÌVð 'Ì•YÌ ñQ»#5¬NËÏ-ÐŒA1c=tã86Ñ_ +š˜N(2+iR™Á=˜t#`JÇ%Ìw#ŸB¢:D*ëËœŽ)…aÔ[ÝÎyÚº, z ž‰6(gqü¸³¯:¢‘úá;jE6ŸÝÖ%ë­ÆŒ'JÜ( ½´†éŠï'}RÏycËSʦÕ%^ûp¯Dlª°4it‚b@ÄH‰9'%Ú>–O‘‡!³Dàî+ÏÞ1.Ä h€¬Zž>ÏÌ()DÒ<ÙˆgsˆC„S½õ’mo:Y+ ¢×RY–À^Œ9»Þ”ŸS^cw¢™¥”†.‹þŸh´ÛÓÉ´ }§¹˜ÎJζñîïæ skµ¾e–=›ó¿CÛ{ 2P:³Ú·#’½q¼œËÃç.ÅËsRÖ<“GoN™» ãQÇhã¬z[Ø…ð²Ó»›¶¬'iµ£Ì^’bùž&W­YQOE•ÏCŽÜ ô! ´[0¹­ôåÊÑe‚A)gfª%†ûæ1ܽv¦!èþÙNýåúƒû÷z©¬Ûé‹ëÛZ¹6í8\¹£vÏŒåÖó–}*Y¾hE‰–º 3ÐÎ/ð¨çy·þ<üƒ²„¨Ä󜟬¸÷,:βñë~b'{ï$Ø‚ûJž¾ŠãíG[Šªk‰@oýyŠI+î,ŽerKË=¸4#:íí´&%ă#Ö9ÇvÀJŸx`®ˆÿù$Ž·žÒ1‘³`ž æ+D½ÿhC+ T`m×g€ ê´|4`jF¢%ÞÁ÷álpëR .Ëýlð—gž¾ã~î³ÜtÚìEµÉ‡ˆ?cÖíQ`íˆYÂ÷QÒ¤B¸4ç;ÞtEû°\K}÷Ú*Ú—ãç»K}/ðL¨k!*h…uÄÆê8èå+î72ýÄÛk.ryͤT×ô˜¨ë¿§ag.ÄIÉ' »\ÈéfÁ8?›a™´éQÿv°íoY©’º±Œ¾iÞ_ÊßàNœfünSuEQÂè^‹;Õõ¥ÌºýÇ<0c«Wiõ»ÇïÜ1 |&oS˜AÈôÒnHz\»ÓQ¤G+¸#þVÙóž™¶Søž˜Iýsÿcó?ª]Þ¨ endstream endobj 811 0 obj << /Type /Page /Contents 812 0 R /Resources 810 0 R /MediaBox [0 0 612 792] /Parent 815 0 R >> endobj 813 0 obj << /D [811 0 R /XYZ 90 720 null] >> endobj 814 0 obj << /D [811 0 R /XYZ 90 720 null] >> endobj 810 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 818 0 obj << /Length 1888 /Filter /FlateDecode >> stream xÚµXÝÛ¸ß¿ÂØ+°4`+"õ íáRä€Üµ¿õ D–h[]YtE*^£îÿÞ)Ë» ’‡6"’3óÉå‹~|Q„‹,Š‚"ÎÕñ!t«ÏÜÖÀ°žpüyóðîCÂ< аà‹Ín*bS/þÎx(–k‘Ãûq'»}ÓÉå:ŠböEà7b½ÜÉ^v•\þcóóÃO›ñ°DˆohƒoÔ‰ø"Š4Q.¢ ³EšÇbRé‡ïý‡-â kWœü{ G'ÌHmvMkd_¶M©…e« ÖŸ^dõ×^íûòøžv=¾Û6Ý»VÓ쿇Ih†/DÒ,a?mÓ’FÍÎxp 'I“^š¡ïœ@›‚©ì%gN¼“¥_ɪ†~í±ÿ× ý”"Oi¢(¼â È`Á‹E/»‡¿Í¡Îó _¤òÈA6tœÚþSVÆbU1kðž8u|ÿ±„õtñµZ4gµ_Ïì½½Žeÿüè¹ÞèúÚÿ×àqNDâbàƒ=pÁÊ^â€3ùe™$¬l‡ÒÈš–Úæy)2檶԰ 85X4+ ö±#»²2+æœÌˆk¿‡<ÆcšnOÛÏ(JõÏš¦Û¥ÈÙ…x'G7à´CÜdÑÉÖ,£‘¢€'îâ¥1}³I áê)¦eYá)Z¶3¢œQ ÂRŒ°È 'BôÞA*î õ›…"°êÔD3H² S‘¦ ‚ý¥WɆUÙÑ`Ðx|±•Ž€]U¶Dkê'M#{7øvåQj=DTçô‰ Óù³?îT'Ÿžfu ƒ°µÜù3@£þÕ±{TÜÙBäQåѽ1·æz îu)vèj‰Ðvè_ˆsÓÑ×9ôEy¤ÅØü\¿Û;¤^#2Bìàÿ¤0«³ZÚ(IYy‚cOmc]"‹™êÚ Œ¢/ sÔ-ìJ&tí$MÙGC$}€qBô¥C6å ÍÏÁ[ft9 iÇ#®GUË?ÎÁ‰ ã#›64îL€Èb‰"HRqµ Œ¦I¥ŽG Sð+Îj¸OÆlsh,9¶ ‡ÇDc³;Ž0»Û/}Û·÷|‘hß í‹4—>"¦OÖ²jPÊ @Öc¦šèýYÔТ¤!$»'œiižh٠ƥbƺüç¶×ÊÖ&P)æeèSŠÎhhÉš¨w:uÊÕ+7½„³i9Ð{i¬-˜Í6ãº\ü'ÓåûÕôùd?_Í"÷Yït²>Þ%äÝð½;zãÝqœƒ7H‹pZT ÇW0˜ž3'ª/»=eÔ„}Xæ1ëÕ‘f:HÞ,óˆ)'óã멈Ītxr"ðfs0šòxBZWؼà{\˜1¬Z Ñ0(­ÛUôj¬"nî:8l:¸U2ÚTôMr‚Å)³8À¸t|ÍËœ+C°‘È­6o;øb ge|j¾kHö#XF’ÐÕl.²ìWGՙê./+pG˜6Öµ•–•êjj›f«vêüx×¶ò›Ÿ¦z K; bÝô©õp¶tz<–{õHÃMB8‚Cçuût§€Œw„gß(\¢lëïŸ1.5½I×Eäî4ao.'ùí>ïä{™ì5;Ó ïW.‘{—(ITÛhãì^ M0za·ËlN,Å]vkÌœ@_2&Ž—€K Rô¿·Y{csšz5R¨#cùL'¢`¢å©ì)Á ߘZSŸßç×ßœËO¥ «–ˆŸç›Û4(àÑç¿ÎZ$ÈÄØþ>­\×àÛÞ¯o²kRfuÖ®éEƯj±Ê–Œ1ùRµƒg.€ 3llévZ7[ÿàðyØ¿`FãT¶”õV%.8æ{ <)åµ—ûkÛtÏ׺é¯ZUÏÒ\wÍN]k¥úk­íuÛÂòw–”_”‘¾a/ÍœU’p|CàcjF¬Hƒ$N¦ï¡9ãB¼qá™à³’BÎ|”Ô;Õ IW¶M¿Õ çÛ0ž¥Ï’ûÀÆ?ü&÷òå;û¯[ˆ¸3ÞÀÔa[e ½mÀí˦ó„‘W æ4¸EÉ#q¦í‰¨¿à¾Ùaº§Ñ/ðPüßÜ Ÿœ_Ñô–|"ÿ,ò¹ ßû¡-{'¨µJhàÿÊó_†Ó7 endstream endobj 817 0 obj << /Type /Page /Contents 818 0 R /Resources 816 0 R /MediaBox [0 0 612 792] /Parent 815 0 R >> endobj 819 0 obj << /D [817 0 R /XYZ 90 720 null] >> endobj 816 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 822 0 obj << /Length 1356 /Filter /FlateDecode >> stream xÚ­XmoÛ6þž_aû@±*êÅ’ó-KÒÁC“±ÚaX÷‘h›«$zziâýï;’ÇÄrÙnƒµDÏ=Ïñx*xðGco;“AVžx8úé„âÓ †¿¦'¯ßDt@=wìé oºHóÁ_äbÉV-¯a$nùþtÊâ{xþ¼Qº4 ¼I3[—oEõ)•gjÃíp¢Ø †4pid°Õª¼8‚ˆÈªX«§¹_BÛF’ŸæÄÂùí‡HYÔ²[íâçÇÕ¹‰/|/¸XD¾ÁM‰ý…¿ BðYÔmÇ ,n¼”õúÅ€ ³ªz³¿øh³][†GÇ~aÊüÞ=/®1ñ$žÎ‹w××ç7—O5‚yó< êä<À!:‚ åæM-ËשT«ÒT”üÀ«=u@ÚZµxÁlÁFH-ø2qèÊ #éäúªÌS,,Ë:ÝDA«Ónz8‚ç­`fGYQ·æêí!ŸËzw•ƒšÙ¨Bbgš›ó[' &<Á44- %;âN~&î4ýsonÁåRŠÊŠÕ*¦×€;íã¯dõB§mZ MÆú°†}z;逛É3éÒǤH=Wº¬9Ë÷—›·¥”ü1ÝcnQÎ>܆/S%ìŒ ¹™ÕR÷(±êQX+ÔŠ_¦Óv·=ºŠa¯½yãÞm´ƒ¶)9à ÚÝç\=0hŠy£¿$ÃÞâxÕ6êÜñ¼×¾ê–Twwœc,4Ñ x‡~ñ=ÏÃæ´ÊmêêÕØŠt¸ãÑ(T úëǺ™Š}L¸¯ðUàGd.Tœ¬Ð"c» ªŒáU[©š‚ÅD›¿Êá¨*>Ôþ§”žÒäÔSŠŽW ;è:Âl“v9bX_Éû¾öm—ðC‹;vC{P΋âû²d9ÝìÁdɶ•ßYs¶È-ù¡˜G^¾‡ŽeW÷¾*r¡Ri 9õ¿2!ê—‘‚>I‘Z.AòJcQ’hNén5ìÍ%­ ŸzϹð½ÿõñÍþ—Ç:Yq² endstream endobj 821 0 obj << /Type /Page /Contents 822 0 R /Resources 820 0 R /MediaBox [0 0 612 792] /Parent 815 0 R >> endobj 823 0 obj << /D [821 0 R /XYZ 90 720 null] >> endobj 820 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 826 0 obj << /Length 995 /Filter /FlateDecode >> stream xÚÕVKo7¾ûWêeeX4Éå>d@‡Æµ[E ¤ê¡hz W”Mh.—Jd4ýïápÕU¢Ø-ÐK @;œÇ7ä|Ã?1YðI‘¦l¡ÊIÕœñ¨Ýž‰(ÍÁ`>²xµ:»¼ÍÄDp¶à 1YmÆ!VëÉo‰àj6—%è’ëiïmkfó4UÉ{‰Ï4qfcœi+3û}õúìfuH–Iù´ø N!'"eðD8y©˜HÁQLr&fó,—Éu×<Ö€F$1*yÇ…ª½q¸Ê³×hÐ#°OË„}ËÓ”Âþ%€µ=>E¢[ZÇ ´Åß‘¶7ÚU3Y&´ÞtŽ]×düLOÚvl­)³HŒõ&z®­3•º˜³¶í¶¿@y‘Ò´î Ë u¥L@±¡®­m×tL݆ž…ްC¿­‰&w3Y@˜ 7Úm/H´-=ï]·{$Ç*v£­MŤd‹Sæ æ!ØÕ4º]³Ù\¥er­wØcH]QB>y½E²Ó0„Ë’ñB M<¯»PÐÜÛÆÄ§Ç®§a¡Ü˜Y8}ûÊÙÆ¶Ú›úiVªäë™ òŸ _ñP¸f~kîÍþŠ\¦—w¶½ =xØuv½ÏΉ¡Ï±;8D<52ž% È˜*åøn–R…»YÊ4Ü͸¦»™Ú×£›5,QÖ®^x¢z¸.ƒòÑuøy“T¦ïéu³¤Æ.Ç×xÅŸ¸4½&eïµóƒ¥˜Þ„Kõ} [ƒÿw!>ŽÛÏYì+³Ê•Àzù/äà”…=Ï ñBÉ£:Ñ=ãyz Cîç Œáðaþ$9çB\púµÎøéo‘'ÜÓ/úG«Õ¯CjvþèÙùI«ãÒN‡×¿!uõÐ endstream endobj 825 0 obj << /Type /Page /Contents 826 0 R /Resources 824 0 R /MediaBox [0 0 612 792] /Parent 815 0 R >> endobj 827 0 obj << /D [825 0 R /XYZ 90 720 null] >> endobj 828 0 obj << /D [825 0 R /XYZ 90 720 null] >> endobj 824 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 831 0 obj << /Length 225 /Filter /FlateDecode >> stream xÚ…1OÃ0…÷üŠS'{°ñÙçĮԅ foˆÁ D”´r"1ñßqp@•‡³î}º÷‚*Á+茑žôïÚ¶o n?QqE܆ææÞ" ’^y„0\ŸÏðÈŽ¯ñ²¤Ì…1†Ñž "ËŽC|I׎-UÈiH9M}âB[ãCeùSxhÕúŸt+ñ'žApÒ·-­éP;©‘ u$ÑPø¹:•n’Š"t颱*—|îÓ<§yÿìT·º;¹ãÅײa<•š‡:âiŒsÝÇ~ÏÓá#æé§Ðq×Uî endstream endobj 830 0 obj << /Type /Page /Contents 831 0 R /Resources 829 0 R /MediaBox [0 0 612 792] /Parent 815 0 R >> endobj 832 0 obj << /D [830 0 R /XYZ 90 720 null] >> endobj 829 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 835 0 obj << /Length 1852 /Filter /FlateDecode >> stream xÚ­Û®ÛÆñÝ_¡¢LÁáš{á-@8IŸ>¤mrúP4ÅñšZI„yQ¸Ô9ÐïÌÎP¢t$;1 =ìrvvfvî#¹Hà'e²Èµ¥)Uû"a臒w1 Ä3Œoï_¼þ!• ™ˆ2)åâ~='q¿Zü;’I¶ŒU°è»µë6uç–±Ö&zT¸êhpk7¸®rËÿÜÿõÅ_îÌR¥># b<'W i„6™bq²Â© ‰c„’Ë8ÍT´úýο®ë½óÈüò)ðVY ©ø%÷[ÇXjŽ¥¤(SÀ 8Dô1‹T™ ÏVcÝw ˜2‰~IÒÄýº¯—iÙÆuKUDcs Ó žÁ­èkìiµþš(2SBŸ˜|âiF w'i¢nðG¥0"9%š²ŒjÆßûK¹Vî—Dš.(j«,I ZÔB¦ç2Å:Ï£§m]-UméÓ¶[ÑvÝ´a…†=Чó"Úö~ô¬˜gÑÝšÎ(r¿'‹ ã–7?ÞýLTvçFÄ~BÖýðêx¶–̤qÃc]¹ðj|MÂïôµ­ê¦„ÀRFJ’ÙÈ£ênê7g’ Sm²l†e*£[~“&"˳ Ô“q‹V@¾õÊY‚=ÕMC0Û Î®~V‹}¬m rÛðÐn=ª/\F+<ƒV¶#«J“ ™Ÿkc7ôïí{ôY iÒ?Ä8ÌBÅ““¬TÀV†Ïº£»g ¸BH—ÆÓVŽÇe¡#_§éÉï—Å%#ßù ö™œùœûºÝY©µ–¤Ùͦö#‚GâÆûzÓÑq=ΰӨ³-\—º$hí-¤3ÆóZÝG Œù¼™ÕÉ/›©“ü”ázéh?.eô5ù‡–‹B”YfBö)D¦E.å<ÜE)ŒÒ ÜIññ›¿w«‡†_ŸRFR„ä«:ddȰiôgZ0rhçíÆÒnD—ÇM¿B³1Ú1^æ|w¶ú`7ùŸ¡ùŒËô¦iÞö­ûÂRè;Í3ˆ'“É#oë·#¥ß+úÛÝÛÿ4æÂ ªe·hü³†º~¤¬p•ÐNg·^Tïêîa°Ýæ–éïþþž"@ªR$ð“` * GÒðÄ4‰þHÌÖ´›ØOï¨w´ÚÕjpž‰ûU}™p¯•ù¿ [Ø~w÷ýOtª¥cÒ,ö1¿ž:£„I³….(;ŸºücYÉr1¸ÅúÅ?¨ƒ9 p C¦Jè Í)¹©úv·ÝCׯnFÔ[xÚQÕn%c­.•»gº „6×FHH¸AB‰œ€” Ûl¶§3­.Ìx© ¨™†×(‘@kðM¯IàÞPáŒ1ÑAñ\Õ¹¨Ý.N:À•â…OBæù…çǶiØ”ŸÊ‡»íÁ×Õ­øxÅÇŸ#&ψ=€úáp‹æ7QB‹ý¾3t´ª[Ñví]k9²|µ}‚NÑ çì/ÍdžZ˜„eú§Ç3Ö¡gÃUE®ƒ.¶ß{‚N~Lg+ôxê=A m"95@7УΊ·CÛë> endobj 836 0 obj << /D [834 0 R /XYZ 90 720 null] >> endobj 261 0 obj << /D [834 0 R /XYZ 90 720 null] >> endobj 833 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F54 28 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 839 0 obj << /Length 2020 /Filter /FlateDecode >> stream xÚ•XA¯Û6¾çWøóI"%Yö6Ûí.° и‡¢]li™¶…È’—¢òòúë;ÃÊÒ{rƒÂ‘ÃáœùæãÐÉ*†_²*ãU!¥(ÕvU]^Å,ýô*áÖ6ov¯¾Ë’U‹2.“Õî85±;¬~‰¾=ë«3v½‘RFêíz£T}{Ô'Ó®ÓmähÀ𣱦­Ìz“f²ÜFI\¬ÿ»û÷«ìÆÅ³4ýÊîPãëÛË·J$RÑöÏu…û8ÃÆò4ºÝöo ]ʨ;¢,‰ªn°½ñBé¦!é¹ë]Oͺ¥É­q'Û ë$ºâÞaétºt*c!³ ¶êW¾<±~Pží3O…ŒG]ó¥2WG«;»d=“¢i˜Ð_MUë7¹h}+⛲nK7*QB¥jµI¤H2ÒíÜÙØ{f³DdjÜ´ÀX«è»º§=­·2zCÁ~B‡ƒŸ £¢‹ÆÞè¦ïHÜ{guÅðp¨óè§Ñpp]Oã¯w64~ì N h§EôX·'¾è¶5VÐÖe²ÚŠ2Ï•?kšŠ¶ŽGU|TŠ €*‹þNŸ_ã,¦Ößöõi Ÿ—lú s.ýdÉO›t+¶°V8,i±î\ÅÛè·Kícè_“ ê.Œï˜_ãDšÊÕŸQÇ€[IÜÔ0M;ÓS¿vܸ˜ *î!­@˲ôhÑ7—¥ Ë6U–!†Óc.ᨠR•ë#™‡(„}}© )«,¤ÈUÁ`J8ûjwö±+ÌÒíB’ã=YžGÿ:ÒhÛµ†ZÝ‘´(Ö àLÄ&ØZJ<8RCÈY NUlE&“[îáþļ,!Kþ‚Çâ¢Êp†ñô†ýTBeåÜO#ÅgÝst$ ðÀ^AÒ–JÍÑõOΕ&·„Si †‰…µç0½Zó¹î†Þ# ú4®Zs`ý£iO5†O³®óë nD~w®{š¢1ÊDÖ킪Ñ=«Á|þqû“ã×-Nížå¸vq\ï{yl ´ž§¨ãyxÁÆè†ûæíÈ­HØB  ïà]Ó|Zõ=A-ÉŠNè»¶}âæpkv¶Üt¦iôœ €û¸ÐO³õ^j‘}äSßêÆÖ£›§›tºL (LoË|óñýóóòäÅ®î’Ûè¾\äq2¥·$§`xšJ À ]µõéÌUŽŸ‰÷` ¯¬¢­¡Á%*„ñ?žãº“! :±*¢t¶b_¸SG‹kŠ1F·+ í¯Õû&`rôÚ˜/Ì…ÇyÊ,Ì Ð•3œÖG ŒLwŸ¡#YH?4‚YE{ÝCÁ2]ƒ/U#NâkXæ`|¤â`W_Ì=„}ocný§kšÑô^?%!ø/*,©’ΖA›n+yÿ¨8wj¡ Âö‰º‡±FíGâL{F€/û5 01hÄñ[<N;ûÂÌò’D¦¤‘•èB•Rm‡£“õbrZ}ša!¹ÕN\º4¡,Ãú¼çµ ªí™ÍÓò‡èKE!þ,¾0IŸï¼¿&³bRZAG_¯˜ýMæ[lÑê ‚@]ö!ð# 4Mdþ¯]íÏ|gQ‹ÖôCãhBÍö§éYPzâð8çÝïï~àñÑgŒõE¶–"‹‹[#zßzÝ•…DîK_Àÿú§˜ß ¦;÷ :)ÒbŠúpoö‹C&¶ÉX6M÷³T1€M™µ:ã†ÔßyŒ/Æé LÌ»õVEþJè ö|œB±û Iór]e“rªœ¨Ò-5©7V2ö~j«!*$WGµD‚èèû±)™‘az ý ¾š>ýÙøçÚ‚ŠÃv _±èiôî>¢ÂÔ8Ô©÷~¯¶;Y}¡Ž/]à{0æbXÑßðI;¿!e½æIGþ:úBÝèØ–¹ÔÒôÚà <Øñ¼ßñ8Ævèõ¤Œj—Ï&Ï<Í-OQê—Ÿ™¢œU¯߃®Š¶&o6Àλ–#“–åxûÄq¸ÛЈÏu;ýÉVKb_ –åÍUØ9ÂÛΰùŸ]ˆ(ðˆòÖÚªðšG“/¯@ñê©§ù;̹1¾û§Îyùì‘€}Ï*ð tûÛƒ?'4ý”æ£ôv©C.bs§TÆ 6± ›6Ï–å<²¤L1Ïì+[_]°L¾YxpPׯّiöü%Œj ‡š÷Ð û†Ëÿ[æS•ú2qV1œõg󿪺C—¯öuûæ?…ô}zû0Tû‡ªzýþ ÔWŒ2o„ +x¦•* 7lq âˆQñ±ö7u‡› Ö¸Uf ž> endobj 840 0 obj << /D [838 0 R /XYZ 90 720 null] >> endobj 837 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 845 0 obj << /Length 2166 /Filter /FlateDecode >> stream xÚ•Xm£Fþ¾¿Âß‚¥1C¿A3Òꔜ.:EÉÝI;_NI¤cì¶A‹Á<ç×_UW5›Éîj¤¡é.w×ËÓõT!V ü‰Už¬2¥â\ÛÕöø!áÙÏ6 °™HüðüáñG#V"‰ó$«çýt‹çÝê×H$v½‘梿ï]s¨·Þ(¥£W‰Ounï:×lÝú÷çŸ>üãy<ÌHùmPâNL®„Ž•N%«“Z ¥IK8פ2*Û#h"¢~-"×½®>zTâÖ$°Yä±lÑséXJN¥¤ˆ@Õ¼îÞöïl™š8åYxç¶uÑCÕ6à+“D ê„ʹLè’•XÙ8OS@Z“®À¿q.î ÿ”®«üè½ÐÊK_mû§'ð1¸)rUŽW…Ð$±NIô—b(QN¦ÒDàÝcÑ€Ê^ܹs®×FK8 Lã4×{ ¶äÑÑ!~ÖC 'Ru‹Rœ¨Ö˜%XŠ÷Ø·58 üó;!ÐS}ïÑq!Œ@Î(ÐÖëÙñ~Õл:hÐ’À‹‡)ŸS•sÔ’I,Š!tk”à[€`Gß{4 º#øWk·èeÑìh®¯vnºÙ(n#ت:4Ç+Ha®qŽ蕇ç˜5赨kð5ß„krYº…ëÛs·Eun£}×q”‘8Å÷çÐ"œâµ Àq(Y;|%³P‚Ìò¿ÙßüfnD2WAWOÅ0¸ŽÏy]›nqµ˜?Š—z™T¬…ÒBØs‰²8‘*{@¦9gyy/§QØáHTšÎ¯e.`/‰äüŠ'Ü€Ã[ͲVŠ9™Ï*Y¢®<’S‰ ¡(ˆµ3`" tÉ"û ’ld?¼=ZGŸÜ] 2mVÚÚ8ÉáaίMŠ€ ´¹J-”%7[ùƒ?á|É*¡Ä÷ëˆaoÀï$p*œ …Ìn5UZC¢I'š.”+Aè¯5½ÙŠ]ä)H,N¡®™¦ûŸÝ@±=sŒ¤îGÜG †?À$…ØN(h!¬Â&PШo@®sä½ ÊpCj}Þªz·-ºMÃÍ2+μø¿E}TÛÔLõùÛ’&ÒÆ©JƒØwä9 ³y6ƒ(å— <1ö[º_^û::`‚VVÚì¶c%‡"”ö´èû3µôÄ™’“•7ÈÊ‚s"áÙwc·2Ægf\–™˜¯»u™á{ßúЃ#©†~^©ŽgH†þkbRºNdng4úO.+…~ÇÏÊ#bO²‰Ã õ@7Ãשâz!pÌ},±LeÉ`.¶Í“Ô¯ôÀË0fY'¹RLg$‡&-áÞJ ¥tûÐW-EJ£ë· ¤Íå¯6±ûnc6Ç.@7Mì˜r™ždáIÖ⨠~À¨YhšL‚ørc (A÷M&’6=wÔ;V®iyžÒL¶\?m”„ì’¨Û¬ý×éð“Oñ£2°«þŠËðЩoºY„·¯#¢/ûDÉØ$⋱tŒÓÀšœ]ðÉ!ÑÞ¨ÊÝtšß f ô«i¾eqª±±¸É4ÅnçB•ÖÒ=çj rÏéÔµ'Ƚƒ›|1‰Ù=3zò•èÄo=ù™¤Ñ©Úú9Ðs4Œà¶­ ^]øG­«—¤IlXý½Ñ/ö0%#OäIúÿHN¾rÖmË43!M ýŒ÷‹«RØú…uº }ÒÀãZzbpJr®Bçæò6/ª%²X ó~ݯoø0ÉG ¼2$¶ÝCÑ ô‘Ðjïá}‚oô©LŽ”Á'+jÉí¸ÞGª9Lôßu–Ò×Noy¯oD`yá7¢™Ø‘ÏÛÕ²xŤi¨QÁç¹%v?Ðg¡Å‹e¸Æh>úú!ù8%ò™ïr¨jÕx_wt"Þ…gA¾¢ÇÛ²…Þ 0Æïô©cò›²:”õ%ô&VÆÜ|j¹ú–âr„H8Ür‡ööÿ„?í endstream endobj 844 0 obj << /Type /Page /Contents 845 0 R /Resources 843 0 R /MediaBox [0 0 612 792] /Parent 841 0 R /Annots [ 842 0 R ] >> endobj 842 0 obj << /Type /Annot /Border [0 0 0] /Rect [174.545 485.343 344.606 496.252] /Subtype /Link /A << /S /GoTo /D (mountables) >> >> endobj 846 0 obj << /D [844 0 R /XYZ 90 720 null] >> endobj 217 0 obj << /D [844 0 R /XYZ 90 720 null] >> endobj 843 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 849 0 obj << /Length 1511 /Filter /FlateDecode >> stream xÚ­ËŽÛ6ð¾_¡¢‡ÈÅJzåÖ¦ Њ] ’¥%zM¬,¹¢¯ÿ¾3Ò‘w•MQ>h8ÎûeeðcQE¥i-«¨ÙßdûpÃ<”A2£øáîfý6gËÒ:«Yt·³¸k£÷ñ›:Lz\%BˆX¾^%Ræñ›­º×ýŠWñD£ÞêQ÷^%<u³¬^}¼ûåæ§»‹ðœó¯h‡ÏÔ+yÄd*dÁ½zE%S&$©'S.VI^ðØÜ÷èQèS“ÀfV§Œ{‹þÜꉨE|F †#dl {ëf•°Ø¬X¼=Ó…"âQ7ÇÑšOøFÊ"©Vcƒ¸ᔥïA½¶þÆëÆçºqÉR Öf¤ÛÖtÚ.ÙÀ«´E »]bU¦²’b2íy‘O™²ºTøÄܱ2Ð4Ãá_pRÍd†þÒ#«®ýz¢C×"“(2OëJ@HDÊrzl‡½žÌ^£ëDwæ!8NÓ@_ýØtÇÖ#=NÊôth ÄfFlÇaïï܃ xÚ‰P.ðµÇͳç)è_°øgÏx?„G²—L¨9#Õ/¦ò¼ŠO¦ë<´‚TR¡Bƒfà·õßig,ACßó > ǤA#X¼W}K7eÛYžY­+ *=ÁBë¸N;HeŒ¬§¢Py:«!QÕ¤»3°d·K&nŽh‚,g¶Ê <ÒVuv h¯BÜ@ò¾6ª#Ø—¨ƒ1 ènVÄwä @ºÚ Œ7äÏ­wàÑN·ášc¦ÑmÛ‚•¦¿§#9hBhÏKvQb‰#Ò«—ͤÍ4ÑØsÔ#/RÆxT§uÁ ßhj¨fAü?dL„ø÷¥ÉÕþejRc—{ÿ1‹Z¸ShÑÉQî#É‹Tr|×EÜüNÝðZ`mA”p〻ˆÍÄf®Zsâ ö’Xh°,åå\¨`QÏ éºȪ2å%¼œ„’ë^“SŠrNÍÛ:‡ÎÁ½ç¡NÚF­]Ïjo½¯W{ª³kíÑμÌÿ£ú×>ƒ ’ó:-Ãñ/† )k üÂôT.[꫉ä"•àØ„•©¨üÐz»ª¶k—}úQA-w_GG¤U^@›…·Å³ØP4˜†êϯg·Obõí¥t²zc@¬ÎãßFýI÷p⸠ÄCúŒsÐUsFvmü®§ý ÓNÓàþ‚˜“éÛáD0tChr£çuͤ ´z¯;0Ô.sòȹiNÉ9žÝä‡þÕÌ`‚@tã5ê†æáZƒ%¼ o¾[’´ª[wf³¾ïkÇqë¨Ñ™Ï¥úËé×ÓpøŠ°I?®·C?ÙèôÔ¼p{:¾¬Äþ8™Î"¨ôb˜vÃýbäešAÅ΂„_‡^ÏçwÚ6ÌM0˜p|š-ÏÖÏø–^„]ÂmoÚ}ÂcqK”Tr°}Ð,‡Dm=÷ã貉ž®†x­mãßxéÇV;«¥yäP`Ðh F¡à¶¯=-‚»©ã¦7“¡ÝÒÑ 2¸¶´Š–nå8ØœùHrí @œÌt¡Òf$$u_*ÿ ëÉ9àBðùrÉ–ùV £uµNC©¥ê–øš¨¿G¢,Þ¡¸ssØZÌpfKßÏ+%Ô¨ p=t @dñ_‹ëlž¥EqÙTC©<Ûg9‚ê1¼Šlwö:Y/} eMÙL³–Ùl÷xA5ËUÅ‚ÐÐU«ž¨†M“\ ;7Oc×! ­JÀؘkRù,‚ïѺhƒIãoIÞ%®ï¢å'ÿží¤q³®$niT$·ºƒýÝùOô=í` ¨<æÂξ™/%ÐÎ% Ì:ÕS ~/öGXÇ­z¢iTÜþxÍè¯ÙÕ‚ç,ýsøÇá/Çá¸é^HΟýÒzù›k}JûõQQSyþÑiÊ@ûWÆkꆸî–ÐXñÐn½`,-·xGåèÎô6 »Ê?Û! g endstream endobj 848 0 obj << /Type /Page /Contents 849 0 R /Resources 847 0 R /MediaBox [0 0 612 792] /Parent 841 0 R >> endobj 850 0 obj << /D [848 0 R /XYZ 90 720 null] >> endobj 851 0 obj << /D [848 0 R /XYZ 90 720 null] >> endobj 847 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 854 0 obj << /Length 994 /Filter /FlateDecode >> stream xÚ…VMÏ£6¾¿¿‚#H ÅÆ!°Ç®¶‡zŠzi«Ê“X &2λ©?¾3ž!a³Q«˜/?žoG$%üDҖɾªŠV5I7½•,ýò&˜ÊÁ ßXü|xûé—HDY´e+’ð…8ôÉ©e–Ëdé§Á¸“u&Ë«J¥ï¿UêÍ`¼qÉþ:üúöùp¿l'åÿxƒ?¸³—‰PE¥jÉîÔ*D¥ÈUH•å»Z¦vº€2}À›Ÿã€@E[Éa²¦Jg8Њôèþ‚¤L¯újҌڟ IºÙýY uºzììH’‘ ¬Ëd“†™¸eÒãh<1h–šYˆ¿¡å|e`íøîÅj8ß!»ñÚ3Ó[oº`ßñ¬)0ÄSUˆ‡t¶ˆ/¢¯½E/Á‡‰ ÄžµÖÑ—œ_…}énÄõºÙ=éF3¤DzÖ®'Ùb{ÖÎÏPdOn2 }ʧ,©•¥gðc‘ "„܃ çÏÔéEûźiªÙ’¢*²\ÉSš…4ÆécŒ=.3!i¼g; ½5|#!†‚6ݽÓQúC+ ÉÒy{ Œ³þ*®X˜M£³H£ö= ˆˆ‰uOщtB_ÇÀ§L‚cU båA\nÔ‰úÛ¦âzÐuÁÄr4)_e—44•Hš¢­k…3#›¢Ir ó¸ú=]`¼¢)¥0´f æ6êµ»}Üh%kùt7§q>êñïØ\\ò|5­DQ5™ŽÖ]¿ý7T4Ù"=O<Çå2øy"Êh?ÚXÖJmÊ›0&7‘ƒäÛè7²GÌçèQSKD«ø2.êˆÍÉk+LÛ@m·A%öE]ïÁ]J°í²ônþnü¢_­UJ4«}±þ›ù‰$mv endstream endobj 853 0 obj << /Type /Page /Contents 854 0 R /Resources 852 0 R /MediaBox [0 0 612 792] /Parent 841 0 R >> endobj 855 0 obj << /D [853 0 R /XYZ 90 720 null] >> endobj 856 0 obj << /D [853 0 R /XYZ 90 720 null] >> endobj 852 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 859 0 obj << /Length 891 /Filter /FlateDecode >> stream xÚ­UËŽÛ6Ýû+ˆ¬( bøi › ÐìŠz—dÁ‘([YšJr¦ùû^’’Æö¨ †m>ï9÷ÁK†(|²B+ *Ï;:¯>îØ<Ê_!~?ìÞ}T 1J,µ êk‡ }ÆïOîiòC– !°Üg¹” ¿¯ÝÑw7xJƒ¯ýà»Òg9WÂÌ˾>í>VrÅùÔÄ+yGL!5Ÿåi# 2É“„«,Wšã¦Ëà µv¥ù»Œqd‰Õ\‡³à;8*KG¿P&¯"¬"¶0H’P.‚ŠÏ_)ª`ï‚ÃÖ çˆ<#É5‘<œkÑ_»?“Ú[FÅ …k‚°¶ðÒ ^J˜µHà§ÿËK‘á€å×´‚!¬ZÆB­BZ2€éDÚtKdö)4º¸>A$“(çP‚x lÝ8.q¼1òc,Ȉ¸ý–½œK¢Š;‹«„Îý†]­!ï‹ÙÎOg7>þ¶a\D+sÜÒiˆ÷gÜÃлªtã´eR„âôu–BBU¡~6M·Õµ¬ Kt¡×ÂàÿYiùk òž—¥ Ü¶‚\rA¤€;É " åýG wÜXü=\ÿþKñÉ…Ù·ðãÓʹ|N'×¥QßÍK´Œø9šÓb“Jª‘·ÁJØLÖ^ÈXõi±Ëî§4~nÆÓL×§ÿË8+™N3kåkwi§¶Ú ‚òðTBBá2A˜J9Ðå¨Á¡pA˜`Œ6cX´xôåÔô]Bœc¾§ÉC`ÂóYS¥QV 7Ä_¸ói½¾ ÓiÕ•ÎÜÄf¼¶sGSÜÉ—Á¹Ç˜ŽŠ@ÏfÅ×ÞM—!^Á؃«sO,]t„BCjg¿ç†AßVñ)€áÙO§i\Í{uúý45Ý1M–Û'®›¡/,­WÕàÇ1MÀÓTŠüº…â¤àë¥/ûnúv¿UµRʱhO6Ìçpˆ’ê67­åŽD€œ•ä[¦4vCãÚ(!q 5ðvýü@BTÞ¦­²öݱ‰É†õæØÁE™Ñ)΀Y+5B®sŸ–ÀÿP4ÇËàBí‘ô*øÇŸZ¿ßè…¹"Š èÇÐ»Ùæ‹ßu۱ߴž½×•«µs¥Èò¥i륳Âýת¢DêÕ ÿ3¡þ ²s*© endstream endobj 858 0 obj << /Type /Page /Contents 859 0 R /Resources 857 0 R /MediaBox [0 0 612 792] /Parent 841 0 R >> endobj 860 0 obj << /D [858 0 R /XYZ 90 720 null] >> endobj 861 0 obj << /D [858 0 R /XYZ 90 720 null] >> endobj 857 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 865 0 obj << /Length 2095 /Filter /FlateDecode >> stream xÚÍÙnä6òÝ_¡¢ÆŽhñÒa`ò`;A^ã·™ÁD–ضb½’Úÿ}ªX”Zj3±'H‹~hŠ,ÖÁº‹1üxÇA*%ËU”íEìvï/¸[E­ ~¸¾¸ü—æYç<¸Þ¯Q\WÁ‡s±‹D{á{ÓÝÖÙERªðAà¿ ³7ƒéJ³ûtýÓÅ?¯bZˆ¸Aˆgì¤"àŠI•ÇN’)Æ¥"vÉ.Ò‰›º»ßE<‘î¹ &ÏNˆë;`Zè,ŸÚÈÂ)웺¤m‹ QÙ¯ý±+§ºïè«v»}gq¤a¿§iFz;˜b2ãD_‡æ8ŽÆ]ª;ºS.O‡»…;-f¦ÆÉ´n«jë®§¡ˆP.+ˆd\“Ä•i8õ¼4l)%Ãwî'aÑ4=Jø8Ü~ôÇÓ%ü¯zžvðñh!À0ÌÃÛö 1ó°Äó;cÿî l¬»ÛÆÐº±7î¹}?Тì‡Á”SgFwRt-ûnÁbž6rñc¬cD"2¶Å=RÅW˾wKûõžþaç‰V(þwýD óh.þ¾sAäñà$NŠâà–·61::=q`ìùàˆ~Œ¹j´U4üŽ3Ö·XEE7«)òÉ‹¯ÔÆL†¨J¡ÀX­É¥2lŠi2­÷`cÇÁÐÇ P‚º- X[Ã>6S}h”S (‹¾ûaÙ?mÒ{ÔM>¼0`œO‰µOÉD2¸XÆKé.ú\0šá7â.bH T[Û`´cO;ró°Ó:,ꦸ!#ᇾ%€ÉÏד2ŸyÛ×ñÆ)O²¬(g‡Rá{ó,€I€V< ÿ±ÄÈìá*ˆÍPÑ ÌWÏ‘YÞ›år÷YÖøé ¹Ì¡¸u/–ës&U3¨5“žH;C½Àä92Ë$£8`c(ò0>u¨¥©øbí9’©Ã½ T#19”+(VãFm#]W¤!È0AÎòD$.r§ aŽ\Îÿw'×,O³@ç M+ʇOqPÁx“y•}ÉWTÆ8ç³áFßøæAmЂ,B-:õQó+˜é)ã,NÀ@ß*qî!ÏKãt{òzfþñõÌœáƒÍ jÂ?˜¢p LOóÖù°\£•LËdFû,¡_7cß'ƒ ­,ƒë ï—¾é1À]1T—ƒH\?\øØç nB¶8£ñá•)KôÚºc{c†ËºÛ_zÞPƒõñ6öQkWiò\¤•Z¶¯&˜LôŒ²„ {?[q%!¶¨rª[ãc Ó,MrÇÁÖ]Ù«WHÿ¯ê7r™/^(úÁV°\ó× %À ZJ[/£! vÓk±V¦¨lÍãs:•²ø”úïëÆç4ÄI±/ºÔŠ¥WóP7ä™Úh¾2{¨ž_¹lŠql ô{­Ô]µ‚Oä-â¿Yd•³ ž kÐ4ýíË2OÃÑ\ö>ëÁÎ*Ë_ÏÔa€i¿÷q˜rÈzé6DCté‡öÿë«zzû{ÉIýoLhtÝ ÷‚{H-‡ÑTÞºq:è G¯éÔY@;ÔДî!ªøk¨Š²ôñ¶ÚÁºH§úO—;Û* Úx Ï— Kün]‡ Ïþ¢Âîœ.w¾®6ÍŠ’cƒX‰ÕØ@b‡~Øiè)wZ„e]4´ùP µmQ<ýHž²”/æõ-6µ7ðÌfx0v¥>RÁ’EÛ%,:¢tCÔa†ÇÑàWE'u磞çë>môÑÃW>"Œ@pú"á6Ü·5ÔöX mKüeÃ8 aÞÏ“€T¿< 9q®±ßí©¨ ¶;4VZ:†eÄ ©_}CËÓ8`J;wq×:ú‡^çØ¢ãç܇ØY .ö½¤á£í€ikh¯<žï“9Éåê)¯<•ƒ…©ml´™È‡U[-–qåÃf]4º‰H»+¼¥Ò¶ Š¾÷ äÐ\Š%S!þyê?#Vø§A§L ½$_C6‚Û!»|±æËéÏs{±„ÆUÆÿzÂ~Ê›&äågC .0àC8Å‹ÚYë;°"Å—‘.í|É­íl šÉÕdƒ´‡³#û¿ãá©úr nZ϶­xŒƒ#üBèº+°ÎsDÀ‚;Zuã<½°øf(7ÂÂQN’fŽó½jÀ3Vœ…‘\„7Gœ$:a2š}w 8 öš'‚"¶ð¨  ;N,†ŽÜ ¯ŒtPãÑTèÇ< ]C“A.œo"Åf¹Ôu3“(Âé/Þ™4µB.úýƧSè#Ä’ì¾Û2u[ÓH¯{ãfb²YáhO&2|¼«iX†ŸŠÑÐ ÷6tNS¬æèÎ,Eض%`êÑR„ïP×{:X°¸a l-zI¤›ŸÂbedN/ÈBï èâ<™|ƶt“ÒÆcçÃH;>•Ê™7-¥gzUdrôz¥õ¢V5˃ä¾m‰{e-Ðm÷k¾¥ ¨ÄÒsE?û”Ê5ãé¢Õ™HŽÖ”$­!ß+ñ‘Òšâó$tnÃmºñˆÕÀj¤dS™ÆL¨8¼á4Wʦ´týÛ f{eÉI_Šö0'3ÊHàúÖí8C©«S¶£Õ8AzkS4›ë¥ß³Bh endstream endobj 864 0 obj << /Type /Page /Contents 865 0 R /Resources 863 0 R /MediaBox [0 0 612 792] /Parent 841 0 R /Annots [ 862 0 R ] >> endobj 862 0 obj << /Type /Annot /Border [0 0 0] /Rect [332.418 609.676 460.564 620.585] /Subtype /Link /A << /S /GoTo /D (files) >> >> endobj 866 0 obj << /D [864 0 R /XYZ 90 720 null] >> endobj 296 0 obj << /D [864 0 R /XYZ 90 720 null] >> endobj 867 0 obj << /D [864 0 R /XYZ 90 296.636 null] >> endobj 863 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F112 68 0 R /F67 34 0 R /F31 21 0 R /F53 19 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 874 0 obj << /Length 2683 /Filter /FlateDecode >> stream xÚ]ã¶ñý~Å(8sE‘ú ÐMš ×§·o—Ǖ镺²äŠÒíùßw†3”%¯6wðƒÈáp8œoŽå] ?yWÆw¹R¢ÔÅ]uz3ôùäÑö ŒŸÞÝÿ–Ê;‹2.åÝÃqIâáp÷)ú¥6çÑ»½R*Ò?íöZ§Ñ/Gód»]RD#- öhÛUv·ORU‘”j÷çÃÞýú0ž&É7¸CŒWì)yWˆ2Ë4r'e!Š»,W"Ë51Ø6ݳû »+…–únŸÀm€’_ý½¾¸¦rÂMþ‰°´È㜱$aÝOn¸oûÊ´p,O£ý?vÀMÝÿí8]3ZøJšÕ½ýŒ6 I*ˆPg\ÝŸ@™Šãï£4ÉM2v¬îí'Ó´¢:¡™àÌó=®{ä§¶4í~¹‡é¾¾mó8Ó„`ÊDu…dn-e¯OsŸ”"YÕÑvOM·WyÌ3‰u45Þd.494ƒ­Æ~hÂêKÝT¸^3òÀDû¿i'#@? µæÐtO4™Îô{þjÍ;Ñ4hÔ™ÃúŽñŸ÷§ zì‡ …„ã«|=½~Å91„(’ï©¥da È~ñëÍš#} }þˆ¥ny LÀÅÞ¯σýÒô“ë*¼*zÎï­iº%)FöêÄ3x:°G¨P=²Yx¼3(Ô³çu¼¡˜ÏlŒÉÒ•ˆ z0{g¾ñ £Õ©(d0AÀª”d;øõ6Q&žs°#”ƒŒ:yó‘Ñ{à1N# â?â%.4>y;øBv¹ iè3XºV ¼À˜ØK ‘Ó8:¸o„ï£SðŽàið!$;á…³×!\®Dô@É@Ø'ä›gz¤§ÃYU¦#ð# œq:onÂyjáòSÚ &Ç7̼´64‘¤RÈrVÆþ×-5ÈTäypúóØôÊC&Ñã4ý¾ ‡¢‰†ýà<ôO^ͯ:D’e¢Ì“•/ ÞQ¦QCÙʦ²ÿÙlÑ“0`ܱnPôRƒˆœ%˜¡|:L’‘ç&//ÜÚÓ÷êƒ8sÓ`i3Ò® ®÷_W¯ Lt°Žêã_…Z¯ h¶üâ±y¢d\›Ó‰2¶¦p0>Žó¸»¸ÑzËøó§&5¤]Èž²±VK;‚ I‘ Ú1˜ß`Pg3UeÏÕЧCv§ËöÅgc ÅïÙ€-hÄmYÑ>°“(¡ fg¼œíß ;ËW6WˆLeÁœj3îÛ‡_ì½yt};vË ¬,ôZŒŽ”® ‚îŽ §XòF_<ó=f– €!3ÐßózCN?ZÆøhímµÑ@$P è$v–CÀº_\TLk¿@Û(ên‰ù‹~„H@*4¬‹”ÆŸþͬ†þ|ϦµÈ𰥸ÎP ‚@ ÉI™Ý^B ˜$»¿9(x»ì XûÚÆ%n‰Q¬÷Mâèãeai} …„g‰£(O†“ Në°jŽ )‹°G@L(¢`Q8£\ìøàÇͨ´ÐP ²A[ÜLHp©, ˜ sël Ú±–¼J´Ù:´ùò$ Y+äñyì$P‚H³è¿>Ö#ÀÓ ù8ŸÂCÏf¬ Žušq_É’ý‡U‚½4mK°9y$>C½`P°\GÛñ¡n+\\,üÙn$µ $}‰Cßš¢XÅcª0<é’>Zzw{"ŒÍb!>Òk¹°¥ÈOɲL@Z,ñ7ˆªXÈk ›T¥:Õ7dà çä>ßý¯¥ÁI/~þ«i®Ï3YB­½CåT(*?|iªuý†c_Ð^Ó¹ÑÀ+%šPí"‹aýé`oÈUŠDÎÆ¼x¡›vÓú ŒG岓çÀò3Àùc½:â-âPˆ¤:½'WÊ¥PùZ^/”}í•“IS€Ï¹lFð¢á×Ê&se& 5Ÿ(î…ø^æ@)x¬O>9úôNÈ­qäÝ:e·F@V-d“Ã…€K«AEq¨h³fg„üZU¬"J×Sfe¢˜Ý6iyMŧé¬Ç¿J¹)¸ÉUž­R-¢-º4Æ=¨‹ðÚaYÅÃ…=} ‡_ñ u (Ðá¨íýU¨bJ_˜xÉd"²Z[!ƪlcßSÞ´_Ϧã—) \_»°Ï½NPe> ½¶C?2¤éèˇËÀ>€Bœ†Sý8“·oÁk”E•žÌ׿ÄÙª ;Î5aké]Ѻ5†ç> endobj 868 0 obj << /Type /Annot /Border [0 0 0] /Rect [392.261 423.176 522 434.085] /Subtype /Link /A << /S /GoTo /D (Hard links) >> >> endobj 876 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 410.631 188.626 420.328] /Subtype /Link /A << /S /GoTo /D (Hard links) >> >> endobj 869 0 obj << /Type /Annot /Border [0 0 0] /Rect [258.612 225.745 426.867 236.654] /Subtype /Link /A << /S /GoTo /D (copylinks) >> >> endobj 870 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.115 164.261 415.237 175.17] /Subtype /Link /A << /S /GoTo /D (copy) >> >> endobj 875 0 obj << /D [873 0 R /XYZ 90 720 null] >> endobj 872 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F67 34 0 R /F53 19 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 884 0 obj << /Length 2819 /Filter /FlateDecode >> stream xÚ•YKãÆ¾ï¯ÐÁqÙ¾ Ä@âd l_vÆ>pÈ–Ä E*|ìÌÀðO½Z¢8”׋Vý(vWwU}õUÚDðOmòh“æ6Û”Çw‘Œ>½SÒÚ‚Àv&ñûwï?Äj£¢0rµ¹ßÍ—¸¯6Rön«3 ¾ß¹v_·înkŒ >kü5Aïv®wméî~½ÿ÷»ÝŸ7‹µþ‚6(ñV½P'Él¨ŒeuÜKÙL•ûnöþC’Îemf*ƒ¥IòTŒ£ë[¼>£RašÁÖÊ„*féûC=À9ó8èNcݵØN‚²hyðï pÜé݉»Åè*9¯ÜvLGü_¾ëy¹nÇc}t²ÛØñÔãT7²Öt’5y¦©‡Q4ÛñÈ/‘²ÍBul¦‚âˆ-XÎ Ççs)>X‡{ë$x†õË¢¯éêÕíž;§¾£ïK7 áÝÖFyðwžÙ£âÝcÑp÷ó] íëâ±qkÚ TïÕ‚’ÍÐq µKI;è näÆ(³5à3þ×=ÝÉ1pžm ­˜n¢#Û8øäÞ¸®±Q˜j»I¬ ððMp šœ¹¯—ÚÎÄV"j¹ì“+ÅÍ@ðï(4ŠÕyÛÆ ~ý+ &œy/‡°ñ›8SY˜§s]×B…¾ êb)Ò4”º Ë­Õ¼žÊCã¡¢Þ·]ïÖ.NÃÄÇ%Gš“>“…ú'ê‚gÔOwlXœ'ßÂÆ¾aÁ¶lBíªîñ?‹qèq¹qp,•€÷à6Ÿ ;è¦è)u%_üÅ©GUØ7ÇU¿ä ´*£ ´*e½Èi˜Uëúç‹¶âŠ^‡a‘äiðŸ¶9Ÿ™–iÉø`vkrx<Åî‹K°†å¥‹÷4בU¤Û=Ÿ»œÁ7zT? n8SáqY_‘{‡*®YžlÉvÏy'ør‚Åþ&·ÓñÑõï×Öµ*4±ñ‚u»[ó#€¿0NÕµ-Ä¡’ t›D ›Ûæ•[gLÃÎ4 ž¡äs=xŒ {jÆúÔˆ¡_[ ¼À=þô“Gá7bã8ŒóMœ$alÌ ¡íLj%(K]êfC„š\`k¢4Ìó+Gxøqv$üàqŤJp‡1Ï/ΠSXÄšM›Ðdæ²x©íLlåËÅ[¶±I‚;ÖaKÚ™%màDZ@Yc¹ŠŽ çn B„š²†Þm×nùz”†»DeçTÍ|ßbv­âà¿®DËŽ”À’4øç<¢Q®`€Ði‡ÑwÊ^h‰´ÒðjAÝ­n¹=ºA!%¶kXã÷Ôy.{F‘Ï…0$¢–Ö÷”a˜Ñ«™¤ËÜ!÷W +\xN¾¼ÚÁËÊÇÇâ¥>"HMGXc8o÷49ØÄ1B7÷1Oã`wfHè ‡nBF„mÁy2* Vn(]+…ìT#z’mÃV!ÌhÐ1±_À­B›ž‘ëèŠvÃìhõµ‘êo®­GT?K¼Ê]‹8]qçÌ3lq:¸#©AdèlYzFgòÆŽRaŽÈ‘/eÂÄ.Kr›òÔŠO­pø’çvc3x߀,/µ‰­Dûr±h£hÎ5¬0A’ñT[*Êß3 îP‹Ì•\$/õ%—‹ýÝÑZVœóÊíÀ¢ëi/ £ÜûNÙÃà-ñæ¦Ò0^$4„C¨¸¨È2ÉA8@ô~σÓDðaª’¦( ±Hàà…ù²kºVËîx,®?«º‘ƒJpY–ØØ@>ÇóhE§Y¯5 `f®ˆÂá‰bÇê0‰™>Ø8óù›œ5&÷‡][¢zÐ?³t“Y“Ì“Âì‚ô(X”uSžëÀ•]Û‚×g\máðè·œ†[ËÏІ\ÏT>ß7,´ëzÉ+jX»¨]º‰prä²Èšà§Ÿ°a} ¿BÞ8R~Q6øØòXa¬Ë©)zþ¨ùŽRB=;°›†—Ô°‹L¨íǾù%Š£GÈX®ÿìzè¨5§L2¨XRÿ(È©övÅ i4Lñõѯ¸'y£”¹S[¹~ ÛØK¹ìö%ß/öý¸ÿ²nšiÑA¹_xžˆÙÌëc÷ROL±­ÑÁ÷@×€á÷ó¸À »¦!úÿ öù–oÁ¨ ”5 äLY˜Ñ±’$÷¬\ŽD7`p¥‘ýÀ¥i©”ŠöõÛÙ¬–Y¹“÷MW¢gÇ:¶ßñïûo~ eü¿g›ü.‚kô¸w„ìø^¦Õ<|4Ôän¢‡íˆÝY+Ÿîa„BŸRŠæÀÆÁÿMœ°4ò**zÇ>Ëó•éh+rb$‡¹yö†a`2ò/†|8Êw0<¢=€éÜVK*pää „$N¯üïî– C’¶Ö^ Ø=3‡<87 þÁh|!ˆ˜ó&,Á”/(=ºHÜVTG ðƒôë"Øqt!õþà­cxBËq¸%PPéìŠgªéœ¡õùuÅ]P èe 5¹“g)ì#ŠZG°ØÑqÛÛ3¿¶£¿h@õ¼ï‹#YÕ¬1 åašeHã²øV$RÛ™ØZ´XlÁ(@fÜxÛæ3b­ÃW§d£¹×1Û°* Œ~Èt ••…Ò|ÉØdÃKmgbkŒh±˜GÖ$רÃåݬ¢Ä‡c—D„½¢‚B«îÖò‹.€¿{ù}7±—ö¯‰¼ZÄ’£Ò`DgèÕ! øÍÌÐä‚ñ|«wE®® ðEL¤.)BpP©›ú’HÌQºò eÏäËQt!Ü=»/ˆÌLË“ì¿øñA6î=²ˆÑ)\)Q>Ò<¥}ô¢*‰r2¦xÍ4Ýñï±/ÚósQ_esyôíazÆzÄ‚÷«ˆ‘@­a¾2G§:„ÿ 3)KB“ðÉ~ê0ßYƒ¯iÅÈ-çß!…‚ޝ8š þá<Ř!:Ž?^]lÏ‘ûä‰ôÍ8OTÁà ß/ºåÎt?ØàÜGÅ:v»Ý*“³Yðöu^ ø_j®Ÿg·šjɇ© ŠÇ¡k&b0|ê뮿°êThÌ'x©ŸbSÃÜP¬&Ò2¥æOØ]?¥Î{Fæê”h‹›y~^iá{RœûAØÛµÃÄå5éXxÒj`“|ñ $Þjü£øØ3°NqöfÆiÅÏ…`ç¯äs ü„'ô¢™{è-0~vòèêè§Æ‡P·œó•ˆóŠõ21R¾¦p§À(à’ðŽó4þ M*ï…Û8ÑÁ襗÷ÁÔ?àÕV+·è Ų†ü™PÇj ulðåakx¥7#¾¥®Y3¶Â¤nÎæûËw7þZgãØË`0Íõq§î4ŠÝR‰ H2˜ñ´½(z~lÁ¢‰óÏìEð²,V“Vè­ Ä”X^U¨òE‚¼<樈Ñ~‹¶Ü=ùùz’7ƒŠ2d†/–”€V“¹ mü[¢ ‚!(hwSÃm΋´;”\Mà Ißí(¬ŸÑ>à@!çý-ë5®t)«nVJäbo %(ô•½®“ޝô†Àµ®ÿ&Ô” endstream endobj 883 0 obj << /Type /Page /Contents 884 0 R /Resources 882 0 R /MediaBox [0 0 612 792] /Parent 877 0 R /Annots [ 871 0 R 879 0 R 886 0 R 880 0 R 881 0 R 887 0 R ] >> endobj 871 0 obj << /Type /Annot /Border [0 0 0] /Rect [340.724 641.955 518.97 652.864] /Subtype /Link /A << /S /GoTo /D (excludelinks) >> >> endobj 879 0 obj << /Type /Annot /Border [0 0 0] /Rect [455.59 564.412 522 574.109] /Subtype /Link /A << /S /GoTo /D (Multiple Links) >> >> endobj 886 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 550.655 273.143 561.565] /Subtype /Link /A << /S /GoTo /D (Multiple Links) >> >> endobj 880 0 obj << /Type /Annot /Border [0 0 0] /Rect [166.994 484.902 311.873 495.811] /Subtype /Link /A << /S /GoTo /D (ignore) >> >> endobj 881 0 obj << /Type /Annot /Border [0 0 0] /Rect [409.788 284.858 522 295.767] /Subtype /Link /A << /S /GoTo /D (binservers) >> >> endobj 887 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 272.313 127.264 282.01] /Subtype /Link /A << /S /GoTo /D (binservers) >> >> endobj 885 0 obj << /D [883 0 R /XYZ 90 720 null] >> endobj 888 0 obj << /D [883 0 R /XYZ 90 181.013 null] >> endobj 882 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F67 34 0 R /F31 21 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 892 0 obj << /Length 2491 /Filter /FlateDecode >> stream xÚXÝÛ¸Ï_± ¬ŒÆZI$%yúÐà‚¦8´Y (îˆV¢×ÂÊ¢!ÊÙìó%Jv´Iá“Ã9Ÿ¿2½Ià—Þì’›B©x§Ë›úø.êó»TF[`Ø.8þñðîî£IoÒ$Þ%»ôæa¿Ü⡹ù-úp¨N£6[¥T¤ï7[­Môa_=Ù~“•ÑÈ ƒÝÛÁöµÝl3£ve”¦fóÇÿÞýò7Yöéã;ñTzSÆ»<×(]ª³X©ü&/TœšE¼;ûá®suÕÝ=¶ý¶1Ñßþ¾Ù¦‰I–‹]ûxw²spp(ðÄ:OewuLQàçá}øSä¾6,“(Û,ËLD±_Ñ(vx;Á6¿'©î,Q2]èh<¡i[xy÷l¹{ª²8шx­âµ×r¥*‡±™¾l=ŸÖµý3ÉÖðÜ¿qú+#×µ°u÷*:f©ø¯vÃ`·d0Ð|’nS§FìæO¼Iß´ýÆÃ¬8Žƒ˜ y\ì²ýÞP«Lâ´L'þDç>èŒ<úrýžnùÀ;TCUKàšhï†Úzæ­÷¶j{‘•ÅÿÁžºª–í\×0­æYõÔ€] u©ºPõ,‚oÑ¿8DÕ7iÔáq8¯ºÁVÍ+Oì·Ö )ÊŸÑð¤ó9Ì?X öèP©æ=PwYôr€D«„×Mß³½¯wðÕâ{&=âD„©Nì8Û7Û¨œD;SE_Öü—¥q–ÿÅõÞW_áÏi—i9qÞòžlvÉ$°}u”ùgk¯$3eœéìÆìÀª@„€ƒhq"×vÁ¶‚s×›‘pŸ!![× ØÅÀnr–ó7ˆ0V9ßbÎþñžé'Bf7Ùµ¼Z¸”f)ï èM\?‘÷z3I M•™ØhØ+Íc• ýRq€te-F‹ð‡Ùpî=Ú‘ÿŸéi…<w~’]#xàöÓªì¶B –ɼ:C‹à R =Æ$íÚ7’b__f+aᯈ0ET^Ⱦ0€Üih«‘%ä¤Mª  1 €­ÔˆFѧ=ÛÛf›Eç9'ª=\ä_1å(_Z2D>áç$NÓØ†ŽÉåb%³:f9˜Æ/ÎôL|<£3²IS |Óˆ2–È_0˜ìñ(m†ÇñÍU =™ã‰?¡qû 4LZïÏ„.øù¹KøéløØ®å¾*` %ORzûëj2q’†2T»ã1øY•bxwéèN YEP†% u„ xž=‹ ­¤èË¡¥À8ð´®¼l!°¢'»á7žÿÛÙÝD2 ˜Še7eöJü¤c¨í ü™gѯÐOD¼Ôć¶k áYS}]Ĺ’<”•† Ì-ßÃJ"éÑ~EU,“XÚ”ü uç¼ÅúŒkƒí à^a rM]ä7ÌŽŽ|Ý+AƒŽ¹÷nàõüÌÉ‚W?Ú£Çò¤uôi\+ bÇŠ ü²¡¨ãªBÞÛó±zdJï]f—]‹ÚÚå Ð[ž/î6+‚Øön–çA•j™Åv]û„­è-£c•6~p½o›©« Á²w]G%÷$¿gß^¶Ÿ*.MNæÝ'év?•fX‚0=$¬«þõ~±šÉj¶Ú×A*×~n`ñ·¯mЯB£¨.ÛP޹$gï®e±.—uùgçÐæsuݱ§¦OC„u’²ÉE«…,‡ 1+1Œ]@ñw¦V h»ß=ó”#xªž K¬çj†,‹òEBÇ­ îcÕ„DÑ`ð¿bè:)¶pìQ ;H+Ï4‡¶ öÛÈó0„;®œ!q £ÙþH³ß  eþ£­zJ:}ÏÄqb¬¦ ÛJêù”?ίRpþ+ùŸC“Ø”æ¢Þ'”i äU‡’³•ʶ;ƒ¡¸è‡*ž€½œÊå?t9K^>vÂ4XïÎØl¿¿P@ÜÕ®®¾'èFç2r蹄 ^g´ .§cÎÞLJÖ¹iCò9üÝ™®m„or/Œ}p-šhªyÛŽ[÷ìyÎNG1×tYŠ‹í|†4k–q„´/”Ó·<ùn¤ìràè*4'’%@3î«"L°d÷#/°| ¡ vJ1Ø’uH¦æŒŽöL ä8|Ïh{z;ÉAY²aÁøZñ=BëÅ©Áçt“ÄU’K޾2©Æ¤ERè4:‡Ú„X–P‹B±ÀÔ;þˆc xjÊH^hEº=È!ˆÝW|D^€¦O¼€–(-¯<Ñy%Žžò[cømä¹gíŽ^@ç ÌŒ kÀ™]'‹\,ѧišáþ®bK—slÁjÐ Ž¼Eû•¹Øåo§ ë:°¹2ˆg¼é ¸&K*éàž\€Ñ5åÓ4Îóp!ó™D©XíÊKýc dþ÷`{^ªxêKH}•ÁUcÑÐ’ÍÈ&À,Œµ³ìx³[˜ëŽ“}PóíÁLݶ)çÝ”áÆŒãù2RFÒÝ®äðåÀ{Pi"Ýô=©akÖù$Ç+áÄ -õu"=#PP  §EôqS*zxÀ À×.ï§Ž¬d ëΧéæJÙ¿ƒ°aœ.ÁéxH5R¦a~RjS—€5ççÐà†Ç),|÷wp/¶w8|ûÉ +vVd‹GœÄ!ôÅèW¡~§âOrg’£ð¿tÜŠt°V@ÏwõJµ*å¢ëZ“·Ìâ,U—Á‹ç ^—æ–ÜåÜ×]¾, ¶í/U üA'ÙpÑÛIŽ«RúƒçCÇz¾ ­v™kúB‹j´™ý#¹“ÇIf¤ƒV¼öOKL;¾WáÃTE™²'–S' ad\ÔrœÂý€B>_¾ ïø}Éd$ÌÉŽäéZc;^%üä©N”¸„7œ7_®o=E™FŸÏrç„ѲÓçÌ“ÃâQ ) Xð‡UÍQï82'e-yw”­üIª*ÝüŸ±¶rúÿ(»å,¾Æ‡&S)Sù¬çš÷¯Šàìþ5§çI¬>ïwDÝSë„cªßÖ#„Þy޹¡¢7Jø,/¸l—•ÐGuÞ1ùR3:PVÎÞNp›€c¶•ìWÊ~ì‹bÙ/oY›%ΉžÐÓÃãÅ¥/<X¿rýËàÆôÿ]þäzg;°Óàúµà䜿bSˆ°„-ÝÝô…øë‡WA éï®”o\8¿…m¡Lmeó+9h®GßÚH!‚ðóOH­Ód endstream endobj 891 0 obj << /Type /Page /Contents 892 0 R /Resources 890 0 R /MediaBox [0 0 612 792] /Parent 877 0 R /Annots [ 889 0 R ] >> endobj 889 0 obj << /Type /Annot /Border [0 0 0] /Rect [258.242 594.209 430.485 605.118] /Subtype /Link /A << /S /GoTo /D (repository) >> >> endobj 893 0 obj << /D [891 0 R /XYZ 90 720 null] >> endobj 809 0 obj << /D [891 0 R /XYZ 90 529.809 null] >> endobj 890 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 897 0 obj << /Length 3131 /Filter /FlateDecode >> stream xÚ¥Yë‹ÜÈÿî¿b?¬…­ºÕ­G çKŽøIˆ—\àîÀZMÏŽ°Fšè±öÀýñ©Wë1ÖÚ†`³jU×TWw×ãW%uÁ?u“G7i‡¹ÉnÊÓ«H¨^)í€a·àxóðêþ«nTæQ®nKû›Ÿ¥’Û΀|pÍSÕ¸Û]›àYã3:wpkJwûëïþò0-fµþŠ6Èñuu’Ì„*6¬Î±¸ÕYðŒP$†£ Ü/‘Ša¬‚r`J{Àg”HìnU@³ÅP50~bž‚ûªsåÐvÜ(¡—J¨Ì†:Î@iÒáþw¿D6ê«V´êÞÕðË®mîë¶,jùýj*¶aj•ÿ}ÑìyQPØÔuÕˆ*•¨ý±Ž<‚¹=J¼ÙÅäeùÍNÅ¡²,hhM§AQ×<  ëDδ‚ë…Ö…ßlågÚæêwUSÀYиwŸw÷ZØOíØ epûÕ2—~p§ðvgŒÞ<Õ¹~¬ùaÕxMhS‘ìFñvܧ‚n.‚²=ã¨Aª<îÇé=¢c¹µIP<Ñ 0‘öOÞrµh¸Þ ½ï«þà ³(xe=ò¤,Ô´B{2žùyÁåÛ±{Y4úsQ:8kmðpt[Û$8¤(÷Rñ%»2mœîÜ©¨²d(Û±Þà h|h;æC;k'äGÒË1?lbÏLÂ}{pø§èd68œ/˜ÐŸùXÈq*Ü%NÖUéš~½'ÞËWxøÅÀ£cÛpIjèˆÖ»²mD%ºC¢NFþ¹ÛEà6³Û}÷²%*LMìyÑ3XYú}ã`»ýðš_½}Ófɾa·èûfæ_“ói£C©õ=ŠD8)c'Ú˜…Ãð\Õó³¨ùØÉ’·wlL˜¨Äï‚â $YùƦA­Ôæžýã±*Qö‘—;¹¢‘•‡cO^Üó­EeÆbp=kŒÇEòÝøkǯWr›–-ˆ…}ªúAB”ÊÒ0Níú”Ä"Ë‚]ÊJ‚';ªåèÑáAâKÙžN¨ÐQ“ìU~ƒÎm!â9Šã†gßûüúJò£:$¯ÐýÍæ¥’É]³ïyˆžs¦jå²sï( ~°ác…SßP+C`û¿r œÜ†MàâhЏôa¤”º Q«Ÿô"# ¦lãÞùd:9 _~ƒ-B>W6ÌÀ„iõ· \'Sœ{탛Ƥ\ŒOG1ðûañ+0(áLqœ9¾ rÐp„m¬à©s×>õ…§Öa)§êFd=8‡ù·ç‰‚¯ $Ëž ³¶çã;UŒàñ86Ó)+Á c+¼QòS¸‡J(‹pp›ÅeÎ(ø‰öˆóhìÅùÌvÔx1/Æñ`ÎñL½ðˆCx[q¦–ÙVÔîä·aÚåñ¨`kþi#ÄC§äm糎µI@­Ýa`’ÀMá 5eUxgxb01‘Â’ˆO€Ãwå0" Q”íµõç¥9"{Óò;^´Ä)œxŽRN–‚VïÚô•@Ôët<›,^2;©÷_Ê ø"KÒ’ã-­¬à¸A‘ s,N5%£nñ/œ^ÅS½¼(vàæ54ì´ÙQˆuþ‘:Ý8²¾sŸ!o“ØÐhscã|Q#´†A“ ôí¹v ¶ ~-Œí„¡ªmX€ç¹DÁTD.øgQ÷×;Ü(&À6ô·$ÈíµæÊ&aY¨â0IÔ uƒçÚ-Ø64¿FÚ •iüÝIЇÝzÑm u;€›(ZÖë9 X¸ÝÿŽW„¯oOž©åL€‰°6R½½¹)Ъž°þ\xóæíèL‡IžN$þ±YçáFæ›ÈÃñX*:pÚÎþ`´¢J^+_f÷‚Ï)òV˜—©C ïàsY´} <ø&qa ƒ—=K§¸Š^yÖ$î[<˘X< ZÞ8ìÝæavUjÃàNgê5EOã(ÁT[O77M¤€Î°…TB¦LùÄ ¢„«P W¢§PMDþè¼È3•0Hcáé,|(°„z"äŠ}[ººµ¤¢{rÃVŽi BÖËŒ ^ôLAt‘%œE¹#”ú,šñ®ìä>j!QG&Ù(îÓr=•IogE·$¤ÞéËW5Wç$²åçÓœ 3Ÿ„pÐ3/ÓFæ!ó=í+-ã,™#E‹.¾Q‰ü›n§b øÇ¬ãâ–=Æ é‰ïµˆîY4D¾º¾0­`’‘ôe_X?±ùÜuÀÒþþtÁfÆŠú1Û•*ƒTd¾Œ¥1Êþ‘`W}m4ïÆZP¤Ï3S¸ˆj›š§ ÀèôeÍ¿”•5„W1ì`Pa© Xj–þ•:øè;DÿF§ŽÕØ×áç÷ Pˆu*ö@Ëu/¯ð‡_çÚp ")ëñ˜*ôn?ƒÈ~ 1o<59 ¥"oWÁwÌq\ýœi•H©ÁšÒj¹ð+Ai|î5ãøF+jO¥¥ª}7TƒÛTp~šõ€ @¿˜xró.<>Rv€AÁ}EŸZº©(E"‡$–g£Á1ÖnP‹šÚw¼o¿@u%sõ°'|¿!Pea¦óoVÎ|M¹)6È{A=“…€ù¿éwÚä¡fUqÌQÄP…QÄ€qÒÇ#$yc4Tlv{¦JtÀ!ù#šóò;NÐg 9 R‘ÔKû¯äÏ0Ëoz *… ðáÈà.—.>5¤ø©i›£ê »°àÅÔœ€¿«v”„îŠr¨JÉÓÜÔ˜P€è#¼SÓ«­;$XÂb¤ÚèuBæúç?Þ½ýàÿ]„Þ¤Ñ;C†ÄGJI¤Ì)ügM¶¶Hß"î¿GëàEý6"ºgÚ%ò1ºóa|àÌHßh£ëäÙû_Rs"—ï‹À.= †qðæÝŸ™Î} ¼£o¦<þ7?ð£RW•"AÂX/>_m»ºê9~¡]+&žïI¦¦Í*´Š°`Õ1éܹ½+]ß·çª|ùå_%œ³‘…ÏƼ\/^Qq¥ñ“+ÄÖá·j¡Öf¯¡íœd.lZ”EO]‹Œs!P–ÍÓ4›[*b©Çí8Éö:÷>V{c–Ü”iêÞ¥Ùç '½ êî«6ѹÿæÕž¨K˜iúVÈ£ê$¦Ó#^vLd°Œf8¸îÄ^¹ÜÒà.¥ëáû3P䲩]Å›`0¯ÿëÉ]ôä.Ú;ðijÀðÖW§ ÁŠôdÿ‘ × endstream endobj 896 0 obj << /Type /Page /Contents 897 0 R /Resources 895 0 R /MediaBox [0 0 612 792] /Parent 877 0 R /Annots [ 894 0 R 899 0 R ] >> endobj 894 0 obj << /Type /Annot /Border [0 0 0] /Rect [465.424 534.691 522 544.388] /Subtype /Link /A << /S /GoTo /D (files) >> >> endobj 899 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 520.934 156.005 531.843] /Subtype /Link /A << /S /GoTo /D (files) >> >> endobj 898 0 obj << /D [896 0 R /XYZ 90 720 null] >> endobj 900 0 obj << /D [896 0 R /XYZ 90 500.071 null] >> endobj 878 0 obj << /D [896 0 R /XYZ 90 272.196 null] >> endobj 895 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F72 4 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 903 0 obj << /Length 411 /Filter /FlateDecode >> stream xÚ…R±NÃ0Ýû‰„¸qÚ„C6`0ñ¥µÚØ•íõïñå T,(R|ïîåüîåxVŇg]•mëºìD› ÓªJÙʧ¨ˆ„âŠq߯nŸžñªìªŽgýxÝ¢WÙ+{ØËS—u]3q—B4ìa”;0ùºe Fp`È‹uSw-ã|›¿÷Ï«Çþçòf½þG2þ—·iEÉkAòìæ£ŒòDÓ°·Š‹#ÜDÐ6LEÙ°G¡³'4Œ`vÚ!íý ©"éøD¶tF›]â:ÏX÷Gl™õ©Ãd¬”XÞ2;‡ïËujô=¹6Ë£y$^òV°­Š¼.yCƒ½8‹Ì³V€sl6,]ÇYàQ›E4i N à½EC6Û8PÅ:Ã>%¼œ€8‹i9græ/>ÀD”+§"R·`ŠÐÿvºVÍI¶2 Õ¸vÄS°½tŠ2¨9?pº ;¤[ ÇÒ"g=q–!1©Í¯ãˆCç ßä¸?÷ÿô£ý øDnjú Õ–ßkû3ó×ö endstream endobj 902 0 obj << /Type /Page /Contents 903 0 R /Resources 901 0 R /MediaBox [0 0 612 792] /Parent 877 0 R >> endobj 904 0 obj << /D [902 0 R /XYZ 90 720 null] >> endobj 901 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 908 0 obj << /Length 1198 /Filter /FlateDecode >> stream xÚ•VMÛ6½ï¯ð­2qEŠ¢¤½µEƒ¶‡¢Àº@4F¢×ÂÊ¢KÉøßw†Cz%­Ó$ðçy¾ç‘|“ÁoêlSæ9«eµiŽwY8}¾ãa— !~ÚÝÝ¿/ø†g¬Îj¾Ùíç*víæCÂyµMEgÉÏ{3E}÷¼¥Dée} ÞÎù¦bµRÒOAŪM*`ùz\•38L(0Á††Øÿüço¨–¬(‹85à/¨Ì˜ý‡ûíîÇ“µý},ýzðRU2Y+°§˜zæTÈøg<÷í±…¬|ònŒz•¯,f½9˜æù–ň¦¨#´±Ç£Z2Ò ´NäAeÃì§£o‘¡WΞ <Ò:X*"ýÓÒ:룙Âz9(7‒Le|ÙLßǪfEUƨ¨cÊØj¥[öŠ’•JÎó6C. È‚U¼ŠHìÕBE*”)ÜWI'¾Jí\‡Ôˆ{žÂ&¸§}Ž.=j¢–p •3²ñ|ÇkȈª„×ÒD˜1 ”¸õÎèöBcrШåe1*z"ÙŠ¸ò˜–yÃ0µDžUŒËY‡æÈÉžr öñD³IÄç$€WÃHÇ3ï ‡»$äP­Ùkhû ±„´ôÏ)¶à¸j:ݧ”ÉÑ æ¡Uq“"Å‚÷Q„à $L÷Ùë|röÉé#²w&’ß[ðÚc”>F®ÃúëŸý=÷!ÀÂè_™–Ÿ\QÀB,Ÿtß-jK°|c(8ôº’WЏ?î‹sW,SWâ¹ÖQä³:Â5 „§”~øþóš>‘XÚ¿Þ¡àöDg”¯sœŽ_K‘e¬ä+¾XÅY|!Nxôp®®a~ɰ]p€a Ä0Y wU¯/7H¢:|\_O¦ÞÒÃSô÷5E|2៨ýá n{v‰ý¬X&V M“Íè4oÞ°<çLp¼V³¬ôT8ôÂÙ;6¢ÒìÆÓz­Ì{ðhš×»»d‚çC³wM|_‡(ü9üñÁNú)œs¥Ö¾çî`9wýÆ<€¾âùJU(l°÷Õ*-‡ endstream endobj 907 0 obj << /Type /Page /Contents 908 0 R /Resources 906 0 R /MediaBox [0 0 612 792] /Parent 877 0 R /Annots [ 905 0 R ] >> endobj 905 0 obj << /Type /Annot /Border [0 0 0] /Rect [131.212 456.351 318.94 467.26] /Subtype /Link /A << /S /GoTo /D (cfrc resource file) >> >> endobj 909 0 obj << /D [907 0 R /XYZ 90 720 null] >> endobj 910 0 obj << /D [907 0 R /XYZ 90 720 null] >> endobj 906 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 913 0 obj << /Length 2383 /Filter /FlateDecode >> stream xÚ­kã¶ñûþ £ý8ëD‰z]‘í¦‡¦h4Ù¢’ áJ´M¬$:zxoÿ}g8CYöis‹"X`E‡ó~ÑbÁŸØ”Ñ&O’°”Ŧjï"†>Ý ^ía·ÀøËÃÝû©Øˆ(,£RlöKõæÇàþ¨N£î·»$Iùa»“2 î÷ê »m\#ôz¯{ÝUz»‹Ó¤,!ÊíÏ¿ûëÃÌ<ã/H‡Ÿ‰—Ç!ÃDf1‹—2‰$ñdÛ]šÅA ¼E0-H$‚z@ö·Êö¢ E̺}Ü ºmA©8 ÎÛ8t?Û! âP„[DïPé2¨X镯óögSë€{ÚžÖãQÓBÒÕ4΄ힾUc]󽩫c a€É/åOò<ŠHþ?¬é˜†yœ{ŒV;ƒ€£fƒ\”Q˜dÉé#DŒ HX„eÆL@:ùç’Ó.)E zM‹Á´¦Q=mFôO‘m`›š`CÅ =}[&85z@'Dið8Lç¨_nø˜öÔè–ãR{ªcÑçþ{ñtÔ蔊XAú¨¦±ˆöŒÚEPÙ¦QNÛ+ò% ¤G‡‹ÿ´v'eP›Ÿ"‘`ZøDô£F¦ølÆ£a*Š>ÝL'.ONç8˜ ¤ n‹î@Ô•«m½(èºZõu¸¦ÏR´ÈjFÚ±´©öº;˜ÎíRŽóC¯ÚG{Ñöìþ÷ j’EÁóQ÷Šé“‡‘ÑÅ0ì¢~¯*ÏõSÝE–<`îϽG°áŠNÎzP}TçšÈ`¨zsâ²Ô¨î0AÖ†ØrØPUJ)]EˆÊli¥T‘¢‚ w(J@=˜X%ƒš .šÍ’« ¨ I·ŸU5JÍ®1OLëÔ#ûé…¶¦#sÌÜ¢`o™žÃÔ­ùj; IˆP]pG†3tVî’¡ÿÁb$ Ž!2šZŠ‚7,·K Ž"8ÈÓÒÊÕ/8øål›©UÿBðï¿»ÿê-]¨Òòùhª#-9úq鄎Qh½Ê¶$ý‘“¯ehg!Ä'.‡¾Š>§‰,ß¼Ð~!(nÖƒB,íQðp4ŸL¦©ym<Ín4»áäî´­Á t< ô êA¶j"xÝ1öã²$g‰Ê@iZSb´÷$$µ|qT#­æzQÃÑNT+#R@ó¥¶\ªâEK°otgЫsÕ`?èþlæƒ5ŽªzþD•ÕÔèÂ.Ù®yùœ¥z¼Ñ†”qÜSÈt3¨ú¬:54A€x;èæ¬]mÈ]í›OhÒèö4†k=h-UŠÒè{Ÿ ߢÕ`Ñt/•Ÿ ¡C‹KÏÈ}ψ‚‰ê“ar‰fR8$àìL¤Á·žSàß« ››z·’ì|è .…ú§ÕßÞøæÜ­;ƙ݋ja!HtÀ® î§Æ9 ޏ†`°ú"\±I«ãt6½í<×Ȱ"t }­†ÕFym,ëàT™ÿ0®¿4„šãáfd58=©~4ÕS‚“ û^Œk°1LzÑ—#d’rö:2½…ÈlYuäfX{{­ÈßëÁ6¤DMÄ·•kÍ¿ãci?cX;Sb À‹“Ü„|âá|…m‹/+º÷8\‘Ú‰úz‹ò\æò2ªà6…>ˆl&:ÔÄo¥0*ñØUþµ¬Y$ +?£8ÜÙʈÂÖ¿ÅÒ‡ž ¤'50s32Ùþ0-‚ÈÉ‘ûZ3ª @S]’RŒK!Ý”¥«‘64>Ã\45Ô8¤o Ò•NX¤Î_`Åù¸U~¢á¶È]ÂuÌyž­˜ IÍ!8Y±ÝZUxt4äã`Э¢rbª@LÙÒn6ïÊ<.ÀLoî¡vùZî“,ÌÓâíôÀ@¹ÁŸIÌ«zê´`m\X ÷ºÁ4p1Gþ»Œ‰bµþö)R|”P1D|ÛÞU£vÂ$Éê-T´½§ÝMW5S­11á-£†+9% \w€»Œ…ƒä7O[ž3/îiçŸc¡ËEx`£Fm72w¦ò€Á ­º­1bÚx”Wà Ës+œíq¢º_¸îÁ} ËB’AÓ=—|Ãuº³«QTа(ã·?ë®­„½fz¯ÑÏòP^Âf•<¬ù]ÉãLTrOvSpi¯ß$QøÎÔScwÑçðÞ¿éœn,B³À³ço<"Il£”Œ0ök‚˜ÇVï.Y\Lî©ÿ‹s7ð2`âÜ[$›\ôH‘½nŒ›„Ü~pão0Ü #B¡ë­ü;p{pC4óF\øjùpEžZ¶¯qø•½—t²™|¿Ç­ËàŒ§¼£^ñcLûqWľ"Þ¥îîž~(ÉøéŽ‹ZWv:58¿:ã¼ò>U«ÆÜü†ôë¤Ý¸`ïØÒTŒív¶,`á ãœ6øÇÎûjG–Yœñw¢kä0( €@ “‚éùªùßNµz…nu>™Ë&É eæÑ\\ ÷)xC¦ô»˜ûv¶[cP@YËÊÁ‘™Æ@µdí}‡q²~ýËš ü•ÏÑ¥‰ GkV¾^6…è(æ:Š¿Æ(pÐ(º›õpK–vËÆÐ }#úŽI]‰Øëq껳ê×™‹0o¸Îujfe˳5õª@Žüª:äÿRžß°G‰Å¿‹=˜Ô7ú³î×'qX¦bN;lï ƒ¯[½0;¾weuh´ÚSó2ÚU%dqzáEz¨º†‚9¬ªB®T±Ïݺ&PMâË8€Å×ÝÃxWþ9ôPßDôð¢ìÄcmÞ hÅžÝû°ªÜLüFÁ«coíøeÇðTx´ŸˆÈÛ¿|^h±&§yúÿVÚë_F›<'ó¹´Ç¯¶”\ –û}:Ê Wá¹þ¼Ý«ð endstream endobj 912 0 obj << /Type /Page /Contents 913 0 R /Resources 911 0 R /MediaBox [0 0 612 792] /Parent 916 0 R >> endobj 914 0 obj << /D [912 0 R /XYZ 90 720 null] >> endobj 915 0 obj << /D [912 0 R /XYZ 90 720 null] >> endobj 911 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F54 28 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 919 0 obj << /Length 1736 /Filter /FlateDecode >> stream xÚXKoÜ6¾çW,ЋȪ¢Di¥¾ô4ri ôÐô@K\¯=\=ìúßw^ÔR9Ú‡‡Ãá7¥vü«]íŽI:ß•í«H¸Ÿ^)¡ pð$~º}õãÛTíTQ¡v·'_Åmµû+Pq´?Ä9ð‚ŸO¶»¯;»?$‰cüM‚Ážì`»Òîÿ¾ýýÕ¯·ËfiÅ”øŠ9*Ò0«wY®C•h¶é}?NûƒŽ’ ?áoLg;Zf殜ê¾yøT7 SwpŽcà¤L[7µd4ô-+êA“0Ëå¸4êÛÖtÕîYšúÖòŠññ lY›!Ø›|PI¨R¶¸ïìÈp™AðëúÉVÌ»c M¿‡Ÿ§7¨pˆ}Ào*‹¸`}†Ž(‚+ÀÒc˜4IÝžq¯< :Ó …€%¹Àö*°L·v:÷NÅŒ‘Ò,˜Îfbj<÷sS1-󠲸 ³2Wwn¥Ì·=IWsC àŠz°åÔÏX$P)ÁêĨðz@j´Ã#"ƒŽÁ‰3¸?Üé@‡_uê‡Âó¡yžúáZmžê–LÍR‚ ¨KËŒ‡¡¿kl+Ó£4²~4Ï<ñTÄ@iH\ÍÜÊ¢¢V)f”¦c¢±¦bŠ ]Pa«Ê¾;Í#úü'*0ì€~žxüQk‘ŒÃçÔŠ 0Xèuö"Š.^¤yÛ!È€ìA+űƒü΄Èã²™˜%°™Ê– ö†7á4_öæÓ¹.q|æiSUƒ%YêIdöœ†í¯ô¡sáTÏÑ– áß?ƒæ¡{4ÃømÑóɘM9Û‹àqŸfif;òCÜÈQ …ÒP›»ÆºÅý•’@˜!à D:$ÄV%gà´Zv€!zŒûíÜ .Ø1Ò>ôX0¦¦¦2 `Løv2‡òƒÉi0ÝØÖÕ5Tp‡úžeòl™Éή›ŠùW§8ê”Cï¢{#¨Ø+—òÉÛÿÏâsoä·8œÇÉÄäÇÜD°áùûBí÷FG+1§‚¹ýÕ¬ïv{€½F¤É‰§à~b¢ï¨ å¦@pøŠÕªl#ºlüypØNªUg¬Rg)iå_üâ>\ J¯Ý¯ÿ‡ ` endstream endobj 918 0 obj << /Type /Page /Contents 919 0 R /Resources 917 0 R /MediaBox [0 0 612 792] /Parent 916 0 R >> endobj 920 0 obj << /D [918 0 R /XYZ 90 720 null] >> endobj 917 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 923 0 obj << /Length 990 /Filter /FlateDecode >> stream xÚ­VIÛ6¾ûWIrqD‘Ú Ì¥ƒ˜¢KÚ½4=pdÊ"BQIM3ýõå&GÖÈ 0íÌÁ\ßûÞ÷6Á(5ÿ0ªÓ¨DÔ¸Šš~“†ÓV‰Hfßî77ßç0‚)¨ÓFûv®bˆþŒï:rÒTn„PŒwÛã<¾kÉ‘ŠmVÅÚ_HÚRIEC·I–£ºŠa·íØ|·?ϳì+è¬Ä3xF¨‹[t0C O˨((Jì!¾Þš—yÜ´@±þÄ©5aP¹$3ž­N®„–ß¹û`˜‡{è?“ÞxŠ2o½â÷ižúÕïN¿—;ß9G‰aºÞi´ú”—~¦PŒœYi4„¢GO/Ì×€iÖÓAº’à%‚U œ(E•gb-ésšcß?]ÁKÄÓÒ„*.™|ý‚¿Éù9©Ôê< p†t·»ïWûŽâCb¸u? ßa AB ºcâøj ÆoTRüA$#œ*KÇãÀÏB6—¾ó4/e—åféË,îÔyíü"|QÑO´µe·8ÖÎA¬;oýNwÔ £>maÖTé³ÃÀ<Ä¡i©82AwýS7(½›—Én*Î âL…ÃÄgj*?·•¼eG¨Â¦5äSkÁ ®LCÖkI£vóëZ·ƒ©‘Ã8By ²@Æ}»àUQùh{ÝÔ…ïŽbBüÏߌ"!0¶Zcp«Q(kÒÙ{³–5@¦ã ƒDL˜¼IlûÂd|ǽ…:rÍ¢Bw¤¿z&=b0* Mdef“"5¦}F¦ ´2 ²"ä¤YVšPYü£}<•0n·7kÓ•BZª5lÆ” @¡eï;7)ʸ8¶Yi¸³yn‚»©LÏæœ:Wí•î±&ÒŸ¼O!v••(…ñïD«ïCxÂt¸4Ýß GIÇÉHbœ._xÚ]v`Þ¯sê{?ØCF/f–!®rª´úïíq>®.jkú%—•èw-›ÊNw$”¼ *¿|ãK|ÁÜ}x«ºaä¡x‚f&& á`T# cïÄI3A±iê2qµúºËÿï´¹ø>p“^Λå,^‘ž+µ“ú²—_El^G~/”6QÝiN)d‚ô¡|{Ãô›£Ï€×¾ ¼ÿ·æC‹y}+Ánú=©nÝÇÍJ ½Hø¹*e».•·™ë1¡óÿ aº endstream endobj 922 0 obj << /Type /Page /Contents 923 0 R /Resources 921 0 R /MediaBox [0 0 612 792] /Parent 916 0 R >> endobj 924 0 obj << /D [922 0 R /XYZ 90 720 null] >> endobj 925 0 obj << /D [922 0 R /XYZ 90 345.834 null] >> endobj 921 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 928 0 obj << /Length 814 /Filter /FlateDecode >> stream xÚµV[o›0}ϯ@݈T æ’IyÙºHÛ´‹Z¤>l{pÁ (`gÆDIý|ƒAÚ]ºäc;çœïøØ´<ñ…Ö³æAal¥ÕÄ3½Û 4-GLpz3^'wA z`á- •¬ûIf}µ¡ïO?}ö›5&›‚à©¡½÷å3°^c†IЧߓ÷“·IGùþjäŒ'ä@/£¡5›…B-év¶P=ß·«©ÛMÍÕk`¤æ¨,Í Ï±é¯0Ï©(dngÝÌ“Iœ œµÈr~lgM‰kÓ• §œ²£ùÁ7/òe•`<Êò-j¹ ŒŒ^w?f6bnj t‡ÐÒMÊ´›·²œÏ×®Þ]f &$…»  ƒ…0DúãÇ ls‘f{ñ¥]DCÎŒê‘N±h‘äE­[íýÄTíJ¬_”é™n¯‹_ê&Ï×-‚qf8ÕÏ;<àФh ¨4G·{k#_ÝýÐpíõxIu!#làV×v 2þ¡}l€n½Óq]1Z%ˆÉ8µ’@à]ºMÍÜ’¦¨t7¤‘)8kÏ9®È/6 Ø› '¥„3Z¾Rc!˜{sË b3þQ-ò'TÉsa6ì¥.M3(RØÀsŠ5ÒÄÇÌx'“D|®ìÄTN±U{‡x>‚7´Ø½kSÖ‡R*Ѹ¥l{U°1P^íWd`nhÃR> endobj 929 0 obj << /D [927 0 R /XYZ 90 720 null] >> endobj 926 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 932 0 obj << /Length 893 /Filter /FlateDecode >> stream xÚ­VÛŽÛ6}߯œ<Ø€%‹ºxmÂb»í)ŠHŒö¡ÉM,Â)Ô^äßKŠ”¯Š±DfæÌ’B^¨ÿÈ[†ÞmËdá‘ú&tÖÝ r#_ü#Ä/ë›ÙcŠ<Ëp‰¼uqìb{ÿŽJÜ(?Žãq²šøI’Ž ¼6‰ce €˜øQ/cÅ“Ïë?n~[Qô?ÙÄEz1òÁr>OLvÚm†·Þ|‘(NlŠ|‡_W+N»ñ#Í%BveôöS˜† V¥~¢Yw0êph,¢¥GLÊœŠ¬{c-Z© ÿ‡‹Ý¯Ttïvö‚VÀp ÆÒùñM>ñü4ê›ødïR4µ´–A‚’Ó ßÈs¢‹˜Ž5cÝ3–]&Ý-‹Œ²Â kMZfJ´` º±Yh¹¹¨1 âEü“¨õ%‚œ*“˜Ü÷Mk0™÷˃Æ/6ÃïîÐŒpVÐm+Àç’'>¯Å¹o`ù»â/þ±%埔¹ÒŒ>òTIÙÖÎïîîFƒ¾uóg•W ”+[ÜêÍpæ‘ «Ëe÷öP­`cAñFWß”Œqvô ¨°”,[B@Ê~z˜ý™óÀ•øÞ5`Fɘðº©àÅšá›™Pi[údŽ}Àtæ>Sô¬âÆø¼²aONÅA’Ú¨¿ƒºg¸z•´ËzôöKƒõù¤Ð×ÑTpM?εZºõ(2k4Ëç|4ÃÐðÛ×ÄìƒôL¿VëÒIÃHÎŽ¸ÛXª_2’áyoÄÊŽ ×îÉŠç­î‡ÞŒCÚÁDQÎ2RÖ›©·ÕYZO}ŸÏÃ?;ÀœaƒÉÎŽdÉÛÊå»q0‚« ö@±–Ãû×F¡ª¼,¡V¾6èËaÑéN§/3<ÝLÉ4¿Jw_M÷Ä®ª¸«WT:®îðë¢ôĈUy`gNó=‘ªºÂ“³êõ´`%fyï÷PZzІÃc½HÕî_)õe:DØ&ìÍr]=hjŸÑ´³£Á³çL%—ªÛ͇;á cÀ VÁ°¤IO ²ŠkŘ Wºö~_´Ú‰Íu/Bs¸PïdÄ÷ͬ¹:Ö«øFÇ"†cþÌtžQz ³¼m2Á¹¼:,È~5Ì´Tg¤¶5·ÅŸ¤4þ²™ª›þûè?ꀃV endstream endobj 931 0 obj << /Type /Page /Contents 932 0 R /Resources 930 0 R /MediaBox [0 0 612 792] /Parent 916 0 R >> endobj 933 0 obj << /D [931 0 R /XYZ 90 720 null] >> endobj 930 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 936 0 obj << /Length 2416 /Filter /FlateDecode >> stream xÚ­XYoäÆ~ׯ¬ „hZìƒMrƒ}°ÇI„¼Ø†ÃåôHÄrÈ1É‘VüßSG7G‚HS죪º«ê몒›þå&7©Ö"7Ù¦<ÞÄ~ôÓôÔìf+¾¾¿¹ûc"72yœËÍýaÎâ~¿ù!’Êlw*ƒ±è›ƒkªÆmwZ›èIᯎ:wpkJ·ýéþ/7¸…%Jý†6¸â7Ô‘±Y³±™RÖéÏ p»32ކG$â<:œ›r¨Ú†‡?¢Ê‘«šž-‹ºv{ž«ú‹­åv'£ÃVF‰>$.:uíCWùãßxBPPÍT©)žˆ4+âè†Çv?¸~ðËçI0‰Ë'¶;›šèÛU ºŠ¾}aÿf§­2N7; ¿ ï;‡f6*º‡óÑ5[8ïп‡íÚÂ4ŸçË–çüáhÎ$Q{àOÛ$6ì)>ÖÎk,¬ç vÔ>—(×Ψ­@Ê/¾E)9_7Š««ÁuEÍýС‘Vî5K…Jwkb‘N+@¥â¨ÖiX—eorÊ…œLX4{ÖÍkœD?ÆÒtlN0Ø;‰oÉ{tÃÒ8ǃ[yãã§å+†af3«ÚÓ«î”g"ÝãÎ åúÂó~Mm»ð#£“èo ³îÜpîºyU—J‡R„ìyàÁ ^a÷Ù•çÁíik¶€«Õg>X=WuÍ÷!­D×áÃñáT%ÆÒUÃØÁ|aàО;¦‚¢ ‚ÓqµÜd"·ÖP ÁÍ€%lÊR¾ü1Nâ?¹á«¦¨_úª È- Jòzîãsås{ˆ š^¹ý$_Ž1ê2;øì]]3Y¶Ç#í®­ôϦ‡bœÚ‹ª;×îjÞ‡Uå¡x'¦1Ež ¸ ½Öƒ= \¸,ß7\ï¿|M8E0NŽn–Fî‚Ñ¡¥û¼ƒQöÎ|%ä‚òeùµ÷çƒZĘð8JêÎ_ÆÂ2OD‰1”LCaùÃOñfS€rBçÙæ™Á[­0 ·Õ›Þü Ð¥ÔÒZbfõø&ËxEl, PÚ@µ#¬zS.¬Vê›|.÷²ð¹ Ïh¿¾Ÿ½ÃïGжBúÛøëdžïUn¢ø“ÌÓˆEi—Y$CÀ\°„ ýÂh-ÄQàˆZœ;£ ™ôï‘Vdj½žøÀ«®é!U,ì O\5à–º¢´mà/|ü ¨NÕèÓ8ÄUН!XjÛq€+›û9Œq¬¦K .]å‹3›Tè,YÜùìÐþæѹÿk× ýš±üÆPææ[*Kýg€b<£9èP‡»ÍœÿµÍ´çZýU_Âd#xSîý‰ ëë bÇì)4.¸Ð‡0¹Á%!‘èýŽ.ìÀ´Z-l8ešgKÃÍ|¤¯Ä3!•.AûN<¯PCPYsqBBfÞëpP¼t>(ÎS%€ÇµÜäªßHƒuMré8Kœ@HIÒäŠ%@å10Ò°+½Z]…D\™äöÿ„‰—r׫d'óï’·“b¥\©¨ó&¼3"ÅV`E®Ô ô<Þi›Ð`)O.@Ô¬œ§ä1XµÎ9}?Ã-\üŠÝöAäŒVLß ÇÓÝ¡ªÃÜ\Ê\á/xzDŒÝÊ¡æ°Ï`OË‹€¬É}øI¸A„Ç ¤7ð—pcXÓÍcFà…‡~÷倷üõÝ-S )øÕïn}+ïgº…+—ÊgaI$oéG]m­×ÃO"² ç2¬þh!üº¢éÕÀa«BÎOÎvM©|¸!$:Wø}Ï·;¡N;RÃr){­×˜BDÛ±*÷ž²Ö"5sº]ͼ DÙÅ‹åÝma¶ì_NÉ–™ÚÁÚ,Ò>÷¹tUË0RÏ×íº9'w<Ñ ßvE÷ò:‘\ï[ˆûxjjNa²ÖÔŶ¯šõ5êMBÉ×BØÆÖÓ¡Blb |?èŒÅÍ­ªó›ÎÝÌ7` ŠÁo%oˆCÿšx…µ¿Ç&iU î»s§Õ+!™®¼.{j5¡«¿¨:Ç6ªf UFÚúr¾[Ls¡HØó'©dƒY``R ëŒTFσçtXçˆí"&µxÞk0²^ö uª®³/&Cß ^««—™ ?«ÅäjM(E`ÚËæ–ɬöû> endobj 937 0 obj << /D [935 0 R /XYZ 90 720 null] >> endobj 934 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F55 85 0 R /F31 21 0 R /F112 68 0 R >> /ProcSet [ /PDF /Text ] >> endobj 940 0 obj << /Length 2292 /Filter /FlateDecode >> stream xÚ­X[oä¶~ß_1MVìh%ê¾€Ql‚.š ‚ÄoIÑÐÇCX#MEÉýñ=7J[î&@aÀsxHžëÇCÆ»þâ]íŠ$ «´ÜÕç7‘pÞÄB`ÁaµâëÛ7ï?eñ.ŽÂ*ªâÝíq-â¶Ùý|sÒ—Ñ ûC’$AúaHÓ,øæ¨ïM·We0òÄ`Žf0]mö•%UÄ*Ûÿãöïoþz;ož)õípÅ õ µ‹“0ýD½¼LÃ8IY½4Te¨ö‡,WÁûC˜s?‚I‘§Þ¡zE˜ßôùÒ‡*=7<až$,ð;3žz°¢ ǶպcB·®G* î`A¸q2ÍÔš†WûçÌo¦žFÛ‹ÿ;x-ÖÒ…¬Y­5+ÁhW…•ÊY»_¢¸Ø2"Važe` ­úºO¼ ç}Ψåä$`'Ãǽ7¬Ýl#‘µµnùÓº¿ çIŒ82w<É—çÅeÌp£îþ­·L:ˆ¢‡¸ £Dý£~˜îZ[ó¨ŽyÚ´ìŽ41ÞÿÝÝûØÈüˆüÏ$ÇtÏ ªÙ°š–z´Ý>îWû?÷±®û’9Ip?hŽ *÷<ñ«l¡®¶Hdßâý£Þ×GÓÝÛμ.õ?ûiÜÖ, UûïÞJZˆ“ê£3ÃcC »ƒb¯Â2/€HÃ2*ø‹}v§êYn¤ñUEÀ¼uÌfßÃé³PZ¦Zþž³ñwˆ„˜›ËÈ4"¬qý,¶iìµSðO ¿IƒHy”C;l æ_“…Z•‚€*=dE|äÙÖ2¼ä\À©û¶ÕŒ =%Í=ó%Ìàx|Ʋ›<8-†hG±’b‹¿'ãųCßò¾ÎÔb6Ì‚hTtmÎfbœ&>¼Ó¥Ñ£ Aöq+òyá[°>…í¿íP_€¡ÁcIÒP•©'òœ!è!vÏÜÙRÔˆÖ` Ø YSR㌞Æþ¬ Ú§=0Þ¿J°('–¹T ~rg[§`s>ç4ÚÓ–µ‡4ªB¤Ù‡¼Ø 0 <¤®Dwh({›Ð¸]— L^¿7PÄUõ¬UÒÖÈ©‘ÄxTäyÊ Ta ÒñTSIî î0m>PФa•P²°‡ŠW§^ó§h¦²à†~‰²H ®XmRdaç^'ÄŽÊ?¡²x©WžC­Í¹1/ÿ3ÿ|G¡Dê¤EE‰( þ²çgŸoE0Σ°„6"‰Â¤ëoO3iIÍ"5š¶År¬*ŽòVM ?Ÿ,Ÿ<ô‡6Òr®’ žŸ¿,ülǤo !`‡†¬®ž0 Sñv7f¸! B;…'Û‡]µP´Ì8 ]Ýj猻馶}}ô^îÈG½¹ÈM«/Pt7Ð|mšJ '“xŠ+¿ç&K)_Ú@Q¿öŒGêEÐhÔó]MÁñê˜ojaPÂÂGó­D=o²Pb7W•ïǤ”tq+Eè°ÌõdßµOL±”vêþW¦\«­nœö…©^í–Y.@ .z­Áö-MJjßb´öÒÊwS×´´®nb3r5ÿ`YuÖ‘âå¶SÂàû!)ê¡kklŽˆEàÀìÝPÓÚîZfßáà‰é@êÖ.·mÄ;Žç“àŒ='°XëÉqÛ¹ ÉQÙ¿kXüã>ƒu°ú®å¹RÃIp­ž!°-¤¶xL*îîRµêîÙ€ad!ºè¥á„–¯s?µzàO­ÜjÖ©%sÒ|Ýñ¶^À˜ž*iÉ9ðÁ%í"΃Û=4‹½ì½¤°iÜF¶£0Ü2R:ÄIX½œ:ÅþìFÚßQpþáEùÀ+ºëØYG0¬§ì=L)aÞ‘ä{ÙŠõ´ØJ5‡áÇÔN#nt^&W`E©?GHwí/5t׿¯G£©Ì[2&TK©òbªI`oÖ$=ÁýKû® Wbíùd…áêr £Ï~€Ñ`™À|{gÛÑ×|‚MÍFxänTŽÞ~:'C>ƒ±…ƒÜ#L‚yr0µ±\uŽ9¾:£E`†>84¹¤…ì$nÛ–Ù]/[,C¥ôg0k¤Â9{:óV„ÚpoeÕh^²ÊyÅ„ñÔIIp{#5xcEU³(ø[¿`¡l‹¹[›‘‰¯¡+LA'H[Ù†ü”så"^û¨æânvÕ ½ÌFÌi|zOF |‡[,U `ÈÑU 3|¼Ðd?Ô¨Ò““ÙžÇØC ½ÇKÚ„®¥°.ÌÓ`}>Ò¦ÎMF4vð¨UØm¦Ýyóà£lå¦}zz÷ÒK‰¼ãh¹!Nô¶sœZßyyW[_ƒr×Î4LÒ\É»d’„Y±> endobj 941 0 obj << /D [939 0 R /XYZ 90 720 null] >> endobj 942 0 obj << /D [939 0 R /XYZ 90 720 null] >> endobj 943 0 obj << /D [939 0 R /XYZ 90 138.452 null] >> endobj 938 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F60 10 0 R /F52 20 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 947 0 obj << /Length 946 /Filter /FlateDecode >> stream xÚ½V[£6}ϯ@êJ%Òàø©/­:R÷­jÞvW*L‚Jì;›É¿ïg ™ÐNµÚVyÀ8Çç|wC ?’(œäŒ!Å‹dw\áa÷V²âÇíjó$HB0RX‘d[Ï)¶Uò!%T®3ZÀ^úS­Í¾1z1ÆÓ/4ƒeíu·Ä( Šâ5ãm‰‡n¹øÚ¿ëf‘ç(/^ºŠþm7¤*¾U7¿Ö%1·ÃŠ.¢3’C;ªˆ~Z,µ]wú¹<žÚ¥”rÚ'2ƒü«!Ÿ§ÃÕ5;ûm(À›„·†!(RÛVqá®Æ—Ï=Z!N^•Û|îÊîêt÷Ew›w±À®ñždsóç¦*}I"ïJßÞrýG{s:{‘`¨i¹húÎ×8¯ÿ< _ïæôM:º1ÍÝãäqS[ñ/«xòòðyÿp(»ê¡1¾[¬}ɰJ4Ìíí¡qpiª> endobj 948 0 obj << /D [946 0 R /XYZ 90 720 null] >> endobj 945 0 obj << /Font << /F51 5 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 951 0 obj << /Length 1402 /Filter /FlateDecode >> stream xÚWKÛ6¾ï¯0Š•ˆ+¾ôX ‡6M=¤@ë[Óƒ"Ñ–º’¸å}üûÎp(ÙÞ•S4X`E‡Ãy|ó0ß$ðÇ7E²É¤d…Ê7U“êý «â3Ž_v7·Ÿ4ßð„IÁ7»ý¹ˆ]½ù+úД“·±”2RwÛX)}Ø—3lEMt0š½ÍP™m,´,òˆ‹lû÷î·›»åq-Äh‡oÔËĆ+&U*‚zi®—ŠÔƒ“dëTD½=[É£©üÚ‡¿6 lçã"X¶kLàç\‚³B¯çA¡×¦ S‰šykSuåXN­À y ÆÔ´²C÷B«¯ø‰ mŽnfh÷ô}AŸÚ#mÊÑóåÀ×¢U{3ÚÁüähß[/°ÞrÊ£ŽÈ{;ÎçGŠSŒlâ\0)8B2®Io/[*}þô'-¾$\É/n2½còŒƒ·ZG§v"¡à¹>œ6ÖMai÷ô}jÊé­`¢ŒÆÙãX™pÅ›ì[‘E[FeÛ‘îIК“ÚàM+S}2LµµÌgµ«kÝDl3…Ü«v “Êÿ‡*˜OíÔ¬‚$LBè¿¶ƒ3ã£×a™P o9ÔW`§õ‚»Æöæ[SVdzfž,ÅV n"/ÝTÈÞC‰úÔ´º¶¡íE¤‰TâGE‡ö]i¢bXéÀ5€OZMÛÅçïÂõª²cM˜‚cÐÍ“§&(0˜v=b!œ¢óv@¶ !šBš§\õÜË€êOå3í=ÆÎå‡0ÃÓ­»#ßI¾ÉY‘¦ ]¾Éuê}¤ôë$ÒìüTÅI€ûEp*$€s+Â…bú—»;Š‹f<CüTü°oOy …ö~¯×åºÇs–ËË{£)k,&ï*äÙã ¢Ÿ¦óãû²sæÖB€åŠ¢Жd3ïíŠÙŠe'†i<‚¬aEPœåLç—Jzìf‘{¿"ò‹—†½‹óÔãJ6ô€X¤,¥†Ø7"+ ðÿYñ=‘ Ô lPÚÞݺv2·´¹=ò¥‚ùi³³UÙ­1wíp|Æ, üËþ{®>o\ B3b™±dòÙN-¶u™H©Ã ^9¾à:õͱhÅu;šj²t¨ß Q‡‹}ûlÂÕýhL®40I@õN“挥X¿/e—½ „XÜj}{UT¦–±/6¾ÂõfV>œª¹óÎ"®tž_î‡rE‡+…;•KŽR(Õ¾Xzó,T¿0ã|¤Jì]Z€"m*ê4- ¹¬ë° Oݺ{bóíñt°TìÐAôPŽSº¾`/ä‡ëƒ™pÿä‰ã=Ô{•—:`oèê“>TÆæz~Ö•–r}þ² /cÛx]ÎçPªKõ](Z{y­ƒ|þ}÷¦Wè0è$éÐÉðÜQGãVã0ÿÊš(8 8Rãü3‚íZ¡¶ÄPÛ§ [$ò ²xÐY”cïƒh?© $oR0?FÒà2Y®û®/§ª!XâHh×¾U㈹äfJ ­Ÿš™ÃxðkðPó|á‡B™,€ãQUDZfv¤Â|c ŽpäG B嘂ïˆBHN¢² ø´ñd7e{h<€ >™Ê±/Ú…ŽËt ÷Éœ Áq²ñ7à1燇)fÎRÄÎòª²}eå F#±ü¬ùžó}ôW_ÿXö5ÏBçP0”„«lþ ø/ÓØÛ2 endstream endobj 950 0 obj << /Type /Page /Contents 951 0 R /Resources 949 0 R /MediaBox [0 0 612 792] /Parent 944 0 R >> endobj 952 0 obj << /D [950 0 R /XYZ 90 720 null] >> endobj 340 0 obj << /D [950 0 R /XYZ 90 720 null] >> endobj 949 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R /F67 34 0 R /F53 19 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 955 0 obj << /Length 1987 /Filter /FlateDecode >> stream xÚÍX[oì6~ϯ0ÎËz€Z±n¾ /g/ÀîËb‘´À¢-ZgFžÇ—9¾4É¿/)Ê{¢œ Š¢(d$ŠúHQM’1üñ ƒTJ–«,Ø77±£~¾ánC´âøtsû/ͳ<Îyp_®!îÁ!Ù.п—¦=V­ÙERªðW¿2ìMizÓîÍî§ûÿÜüó~¦…¸¢ r¼R'WLªD8u’L1.©+|éD„§¾D¸7Ã`~y8+Ï€¶~7TíÎ’ðp|44° "›A,­,öU]; ¿ì2~äTÃÝD<û]ÄâÅIŽgÃè¶wý,dÇC+G„æ¹Fk$»Ô•kñ)Š·fp†êØ51ýëøsU×ð˽ZÃÑíY%㚎Z´‡]¤¸»ÓXu€T¿Ð¼'Acуn#Ò4FC«Å±¨Z¶‹’œ¯.›p¬@ÓŽ“¶ž¥rKD)ûÎYã`x£7nƒÛ¿ïš•\«Î7º'`¢ß£ÑÍ0kÚwÓñqƒŸÀŒ§i|-¾r»fYv2‘-ŽS †°tó|Û `¬YVG¿M1’>]­RÇa –‚Råön‘4«…ãÍšáäç«bí«\p¦³Xà“ס9gJë™çopS*—áý¬Är œœDjÈe¬–°ÜvNµÇO÷뎮)xrÜñ0ß+Ñ× ¶Ø´N–IÃÇo¬iÀ0’ÅJm-Ôµèz' Ãô0Œ}Õ‚AŽD±2& ÖîM,h^<­Rî´Àï¬Ùom_<—+gZÎE³<‰‹9SJ’Ö?Æ\Îáì˯rÍò4 ’Ï—cÀúá§88À8“yÝýÃÀܳ¾s¶z¡oœÙÌôš¾Ë{LéÅá,ãÙïQ÷ŽÚ6O–iβ<Ý–ŽßcÅñÿ]¦lã'{,DTF/Ñ{@xVK>~ù=jB™¥Ï1äÜ4@Éì!¡¿SíJ´]˜*é¡‚î`¼s…Ê‘¹mÕ ÃÔØ‡V®ZÆÑøX jW# %÷ÃH“ê༴BrñP;&Kœüïê÷~†&8SPÑN³š:<8Ì‚aÕ›|2g`¼Ð7[#©ô÷¸d&¡#†¥±†«ù„§Äu)R’ÎÔ yyµ8±~…¬'Gxz¬\ãÆNi\´G·™úC8z(à´{{óe‚ÏAƒçLÃÑw.ìÆ¹½œ‡ó/)Ê…íApÛ¡ƒ+iS;1qÜlä¡oËtÝRå(¾88@2 –6§¶ájÏ{V¾±Í¾×-AçZ=ao0ªÄõÚ€vÑkjÕk2¬F"V-ý6¦ÁR'“!ú9×Ô•Á•móÅ9ç’|L¨•.½´„dã4©¼aæâÞñœ³œiµ¼{O¼¬c¶•¤Ï­¤³#Ábé¹!¶nL•]]w¸úd?èHjLÑÂdîlµŽœX®%©ô—i+~!+¿,ÓPÊ9¾­)³eÏùšï©í)âULŠÃ9l¹%·bÂ%î’~ ú™…ãxõp:ãSPŒÏmB»ïüí|a)j…ýâ·{׫:ÓÊ##ë|n³æKr$u¶îvæ«ÆÃt)ÿ]Î[íÕÃh¶î]hM5 ¤Šáލ‹å‰Ó%7¿ iW endstream endobj 954 0 obj << /Type /Page /Contents 955 0 R /Resources 953 0 R /MediaBox [0 0 612 792] /Parent 944 0 R >> endobj 956 0 obj << /D [954 0 R /XYZ 90 720 null] >> endobj 957 0 obj << /D [954 0 R /XYZ 90 720 null] >> endobj 953 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F53 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 960 0 obj << /Length 2172 /Filter /FlateDecode >> stream xÚ]›Êõ=¿Âº-+Å,CúШ‘RU7QãV•z«vŒ†x_ßó5ØNH­´œ9s¾æ|Í«MjSD›}’„EšoÊÓ«H°Ï¯”@[ ØÞPüéðêñíNmTQ¡6‡úVÄ¡Úü+xsÔ£3öa›$Iþáa›¦»àM­Ó?ÄyàxÚÚXÓ—æaï’"T\<üûð—W>,Êwqüëâæ©tf›,OC•¤lá$–„Û}œ‡#‘ÆY0µM¯;†{}2ƒGÔŸñŸ:Ï1O³g8Ý·}3}-´ž;¡èÚɽFwÁ¹uGAjÛ˜î‚G‡#mUªXét_i[µ_LÅ>ó*^ã2 Ú ¹ß&j“‡E–¥xÜ4 tŠÚ…»4fIÇyŽl¿ ÔlÀ÷¨ûf X¯5 ÓL1qÛ;!Ž…0ÆÚytwäLýin‘\í¢ rB­ F?àÔ î:Ó ÿv1j™œK×ý·³zE;a¦2ÓîšÎÁ&ó:óúÌÉsî…“0ÿ“ëÑc.Œu7hqcîq #h^J3~Ï€gö¸AŒBNÉÔ¶§y. ¡HŸµƒ]cšLóê0åSp'Ó;Mö{­çn-¦Ë¢Ò§Ì“®˜²{F1¦AÌ¿LΜ.u·z±EG²M>µÎ¶uæ^Tï­3/P^‹&â^‘ª;{òR}j¨AoL7”Ï«ég®|>ÿ¦¡vgm½A@Ñö7îú~ŒfÛx‡ù´Ôb{9ôU{•ã¿ïßË>TooºµH¸aôVú´eÜAÿí¢Þ—Bm9¿sØQ«˜Ü";ÿFöˆ5v8”óì>Ÿ×öój ÊcW }ìÙÇ|§{gyï”Ƕ«–LpdÚ·jh¹*Š‚X}%×]+Å26VÎ6^É“.Ÿ;Ì}u=ë¹v P7Ì^/Ž®}–œ9Þý*þƒÂäóÌnœ}£©¯Árãöî?žºûÝ_ï?Þø^¤ÚÁ7ðdéà óñVô8LSûÔ™¥êK9Î> ¾^°m™ÊˆÞ|ø»8£=‰¸®=­_/õôÅKÛ­J«Û«M_¾+Ž¥}v\Í$&ö•ô¹µnöi~µ‰‹|­ÏØ¡ö6ùšA\Û--û'¤œÛ¾<ú@ûòd5œ¯EÛ˜Õ$é†É—FìKÚi˜­¿Þ˜Â§‚i^û¬+[m©g-tßd…ôœÉ*Q’øzš'#YW™ºí} nûÄj‚¬ØËR?/+æqå~<Ûú%ÎìHXÁ¯¶ùD%0iiÇPY›¾Á¸JÁµÝƒ :^P#CíàZeU_oÂXeø÷:m³C´á4û 4Ô¾ ÌÄDѽœDDô¢ fÈ}°:¸Éíc‡lyÄEp.‘ãÈ+ÝË×›SCœ©ëá j¡O© ÁUTÈ}6š@I*) q˜ÜñЉء‡‘’ og 4Ôw :i¾x9g¹`ºÒØ0&ÝÇßy¤ì"äÕ­ypÒì Z<‘3IL±ŒÚ"}à/{<#F]5µ}ë®jÎǶD G^öƒ=ÁÀpY; ôÐ’b£2 á)™tÒƒƒš4ïºI6ùÒî ÷Ño‘J›ÙÊ5ŽHÄtÆzNÞø.ywø¶ØÆI˜(™µ¯™¼¿0S¶¿eJ‹0Ý¥`<'ËÑt‹úÓ Fþ5Eû8L²Äóü²ZHYÆjï)¤8‘ÀÆ)$ GD¿àÓ,)pÇ åCŒÅkó :éÄ0Æ›w‘.UÁ»úNz<Ó+érÆ|€ÞÄÈÿŠS~ÏK=Ž}£-ø8œVkrî[¾“aèŒÿ!m4pØ`÷ÁžîËG2o·#×"táUoØbËKp¾nDO ¥Î”Â,3´êû@w[±o~Iyÿ&ÇÒ§3ǾL1Á8Xål=‚r5>¼ÿøîŸ¡ºV a?þão)£¸=r`IpüEDäÜ$.%}ó€îW¨§4\IŽ·9OºqÝC„"»Š8`ß!¶Ö0ID¾xl²èØd@‚«¶C½]\‚œ^…¡øî¦("Rn„Nøï'>æªÖœÞ`Àv™¿Æiµ§<dÜ]Í1ÚÙ gÏ.[8dØ ÿ4îåÛáî… «…ðÖFìæ*Y.ÝŒ“×ßׂÓþëÿÐ1)¢ endstream endobj 959 0 obj << /Type /Page /Contents 960 0 R /Resources 958 0 R /MediaBox [0 0 612 792] /Parent 944 0 R >> endobj 961 0 obj << /D [959 0 R /XYZ 90 720 null] >> endobj 958 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F67 34 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 964 0 obj << /Length 2553 /Filter /FlateDecode >> stream xÚ­XYä¶~ß_шVLkuP`È:6°~qwà‡8Àr$v7±:Ú:æð¯O]TK3òÎ< 4ÉY,V}uá.€_¸+‚]Ç~¡ò]Ù¼ „úå](½=LØ/f|<¼ûðSîÂÀ/‚"ÜŽK‡j÷/Œƒ›}”ÍûáhÚ“mÍÍ>Ž•wa{½9šÞ´¥¹ùïáçw?æÍ’(zEœñŠ8¡Êüt—æÊcÅýÙ57QîÝY$QÞÊ癳m+&ü$Áx–¯ Âáü‘Ç•6M×Ê·¾£µ¥¦<œmyeÞ™‡Ç®ÿ‚kpÖn‹¤jY4L— ñé7qìPpÊ}ûa‚›G;‚l!ê-ñÆs7ήOJM½ùžm]1½ìXtKÍd`ÃÐóoö* ¼¿ó–ÿž˜…­_;pϵ ÍšÃ-lz-‡0=S†²·—quŒÏÁJÊIIy ZdñÆÇ|èÔˆX6V6 ”1°%v“9+»'~enF)ÀÛWv“a’úA~•_áñÌ”þzøÇ/ÿ>p_G:yž¢QÍèûÑÞ„^{zv®%l|RÐ>Ì¿ˆòµž¤}`V`¨'`F4Ž<;” B’Ѝu78ÒÙ0íbÅ8<\–ö®~âYºÆ÷Ÿ#À’ªtáº8éók]Š(/ ˜P!2iL78È<ô"’HÐé iˆ¿®= ?“«à'=ަ¹ŒB¦CB[ÖF·u=˜ÕÔÜmri’¬AúÛÙ –£È¹ƘIVA‘%Ë8AíúF×+`ÍD±{šž»G`¦/ˆŒ¦§ Ì(󩮎y4û-o*'Tf”KEåꚦZvML(Äå’Ÿ‘~Ö϶íÙ\m‹ŸæÆ”@RÀDwµid…9¿Õ&` yØKÿ±#î\äÞ'Db^Ë1¯Ñ` c&¡KOÐë.£åb•ËlÉz¨æ$]ª¾€VP²v>8àಆKš‘”è{Šœ1qÆFÊÙH(¾ŠDqH峪ִ•©’»ñ“yjÕQ,4²²¡üƳ–)Wu™k&”—Â~ç¢ej9¡lÖ &t;WÐjpE—²zöÐ#Dì©w‰Ì‘ÙůÊäƨÙc=ëÏ{B…ZH*yï©× (Åü\Û/(ªaJÙcÃ<³Q#ØrX‡ÏlªZX}úðËÌ“«ÓSÁ¤òGìÀB;bb‚ÛŠ#sl{®ùöƒåü5/ä€ZjñÏ,'ÓgR˜erá¢:…M)Q=+Ä1áSKR8gÆOÇYÀ J`ÍÇMóqà—," Œ#ÀØpÿþ&$[aÊgˆeT:¾çñ‘­œÒ±n™¶¬L”'ˆIl}@&ÅDtá\”RF•ÏLÛnÕDT™%ñœ ŽC²k”dŒ[¤hn[XöÒÀ9VXxÄ<Õ ‹Koî ?ó ‹©f8"ˆQ%€#„÷øؓԎÚÜRùl—·¥›FåÙ ›ÙF%~æ.Û´bÌfŽ C?Ë£ÍëRšÍaû»Ûâ`.ðq åMšò¥(A±£ÝÚGKÐ@A§Æ¶– €á­znÍ£.eq+ßPó˜ænÕD¨ ¬$­`pòh8ÍØhßL¡j¦â¾æfsküÐ OÞ-Ãݘ0vÒžeŸÞœ¦ZË2óTæ×kϨˆsØ"~ ˆ½eÙõ•¦é\6b£Î_œ 1Öã„ü Ò´,ç«X (ô¹ì<œ…óç-äÅAêÇiá°ôí«¯ïÑÓÁƛܘ)7õû×™ÉAžÆèj¾A8ü0ÏÖÚœo™ŒËå­hDTÚ£T„Óê±%– º›¯­î[m;¸àrñ^K]Ð6PñÞòiÀ?s¿Hᔨ½ÜBÅÏ÷û ä&ïp (ÖÀ*܇¥>B[YÅ+í oŠs¨«OÐ`åËíèô´²Î†€î)<žAü槈ÊAçÛ¦ ü`Îæe ÷fŒ ›¶Í| ,MK•‚Êñ*V£A0 ùZÆdªâ 1V¤Z n7|Ç!íÄ3<“ õæó»10tÈ2–k›™‡=r‹h˪[¥ÛòQk¶ —¶Áñ*D‘â¥m»vÿ§é;ßeŒÿÔ0Zö endstream endobj 963 0 obj << /Type /Page /Contents 964 0 R /Resources 962 0 R /MediaBox [0 0 612 792] /Parent 944 0 R >> endobj 965 0 obj << /D [963 0 R /XYZ 90 720 null] >> endobj 962 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F67 34 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 968 0 obj << /Length 1559 /Filter /FlateDecode >> stream xÚ­XmÛ6 þ~¿"» ¨S\˖ߊ݇µX±0 ÷m0]¬$Þ9’g9½f¿~¤(¿]Ý®†IÑùðEÊñUÿøªWY³Bä«Ýé*ôÒ‡+î© (l&/ï®¶¯¾â!+‚¯îöSwåê÷àÕQ6j×›8Žñb½" ^íåAéu”m´j¯Z¥wj½‰’¸Èóõwo®~¼O¢è?¼CÝ‹ž¸—æ‚ñX{ª¶ªTûJ«[$‰M‹«JÓ‘ÀªF¶²S%±î(ÒÜ“¦ó@YÞXy À`/‘»®z¿N’`´QíiíÀðB!9¹è’p>áÿÞœOžÇ2s8×Ò Õ‡¦UÖVF’ÝneÁ@Aå×Tk˜G)𣔱\(Xš§ä:mô"ü"dှ­ZÖÛÒle«·÷<ý¸” ž1Ìât©ˆÀZí幯²˜«4õÙ﹘aíŽ.P0MGÁ‚”d°kh–U½æBŠÊ¹¾øM¥K¢$Y"ïIô.LÂÊŸe´?ü”¶÷ò]È…†$NsF¡œm¥ –ñ>©OA9('sÜ–pŠs&x¯F¡‚kÜÛ6´RŽóà8œÚ´Æ•ÊNa-2(ë$€>°Ý¯êï³/Æzìõ‰a«ºmb„›Ð¡$A÷óQFý)Ø2K¾€¿E8 ñ솲§9‹ãbžŽÝ^éC…å*wn‰Ô×ÐãcN¤0MÎí6mEÙ÷Ú’”afY¸HVªNVµ+0d]âé[¬´,Øaƒ)?ù@þè2O£g¡C†’tDæëHä“YÒq–aò”0ªg#Ò@;ôÁ%µÌbú“r; þ™5m7Øõ.nAi‰‘-îMT`u‰yZŒv3'ÆÛC#"þJuµÇ>˜ä @6ë\»A4ê- õ][A_U’¸=dŠ‘?"biBÓ¼H=ö?Á=Š€§ƒ,‡ö×Ä«òÔÔŠ„Œ6m@6‡të+ µÈ'¥>lÎÿ¶¥°á¢™«"t÷,\ÄÁÞ´;YèKç â[ðRÒpÝpï…' VÝ»!På= p.×ʾ œÆ|•Cì©pÉÏYI êŸÌ@ýÔNæã\L”°Û#ºôÀ¸ ÷yŽæS¸£Œ*WI‹…w^AHÈ#3AYx‹s!Æ?ˆ9[å¿ï\"j¶“mç…G¯§aîZÕ¾¯v^€=3ñä­žë½³Û©Óÿ†ž%Û/¼˜ˆ½‚Oä5zWÎñ}¨êšC@È\o϶ÝÚûJo+ÍüwKyH9Ë’'yø;¦šqÕ¼Êò^<Hnï\—Dˆ#Cˆ#EoŒ0¨©_ͱ{w÷1 Få^!ÔÌÞä^›ªý‰-é?…€«ŸƒthË–ž†¾´òJ+wpé{éi5‹Ðzå}×Ѫšž£È4O&Ê<ƒÓ(s%79uytºwÀÌ|€ëÌ=꥘ú¡h:Ó=Ò¦CÌÕ~–}g üõÝo¸Çxp þ«Ætbךz,Ò¨˜W)=-¼˜è7–ã--øV$jh‡aƒÓƒkn¾Y_|;‚¼ºß*_ð’–±úÁŠôÑe)WtH@ï•®œ‹‹æQ8u†ï«O„4ýÑÌ‚y HåýÓÆ?çJ¢º£ô²ò|jì ŠÑ}óeADã›âØcÿQ üiKYþ‚yö©¼q8)øÅà˜¥ä9j}!úW­NFC;RäíÅ5“£Íˆ¿²=²¼!’zjÞ_'gq|/›Ýdì¹ÿ‚=‡ægÏçS÷;D hú…ÒÛïÝ–çÆmÿ»Ðm–¦‡ÿ"ð/‰(PF endstream endobj 967 0 obj << /Type /Page /Contents 968 0 R /Resources 966 0 R /MediaBox [0 0 612 792] /Parent 970 0 R >> endobj 969 0 obj << /D [967 0 R /XYZ 90 720 null] >> endobj 966 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F67 34 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 974 0 obj << /Length 838 /Filter /FlateDecode >> stream xÚ…UKoÛ0 ¾÷WxÝ¡òkzùU¬— ëa‡]–C‡®@UGIŒ:V`+kóïG‰r‘dŠ)‘ÔGòÍ?žÔ,)¥¤µª’fsÁâîóRÙÅ×ùÅçÛœ'œÑšÕ<™/CÌÉ=áR¤™¨`|[š~Õö&ͤTä¯ð«$ƒYšÁôIæ?.¾Ïß.Ë…x·øŽäIEë¢P ÜNkÁ“¢”´(Bú˜‚gN~Z\7fhöüí§¹d ½3QЂqôž¯!‘|µëô€ŠyÝf[Û£þã‰Ãxœ šKàC$úéÜ¥œS•ç“͆Ûhפ¢"k3â†îSQ’=*½?Úmüÿ“/61•]⊾zÐ3Ã8ƒÍRÑâ¡[·1hc7Ý/PŽï\ÚÁN2. äU ‚¤ÃÝì-éƒ:Ÿ€ñ7O{Éú›+ðâÕÄf»uá…((¨'_¡ë ”B}”Ì#M©Jr›VŠà>¸ô£Ó0) *ª`¡r~›ä¥ÃÎâÎãÝÝÝŠXÄg‰«ÃT“,¢<Êí|a¡°à}ô&ýA;âÁj0ÚMÖn¸’`3<·}d׋w·»n1©'¼‡Ö™k,æÑ0ŒþíEˆ.røz"±€ÊÃP §—úeq¾=f¼ù"ÜÁrvÚ¹`…´¼ å<7 ¡:U^à4Ä+~™˜ °ÙbrWŸ2xà-Næ:¯ ÊXžä¬ U]ûÁ ›áð`¶OVÙÙ™ÏÍi°«AžyŠú¤=´û€ êëÌTéÑ 3´ÜêUL‡3~ŠZʊ‹8@sæƒÞÁ|*@ŽpDxrÙ!b¡¼íÌ+*q(‡×L'ˆÿPåê¶ endstream endobj 973 0 obj << /Type /Page /Contents 974 0 R /Resources 972 0 R /MediaBox [0 0 612 792] /Parent 970 0 R /Annots [ 971 0 R ] >> endobj 971 0 obj << /Type /Annot /Border [0 0 0] /Rect [196.005 504.172 338.52 515.081] /Subtype /Link /A << /S /GoTo /D (filters) >> >> endobj 975 0 obj << /D [973 0 R /XYZ 90 720 null] >> endobj 972 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 978 0 obj << /Length 1586 /Filter /FlateDecode >> stream xÚ½XÛnÜ6}÷WèCµ€Å/’(yhÓhÑ iã’<Ð+îZ°n¥ØþûÅ‘,íÊvS¤AŒH"‡3çÌ ‡Ã¥^ÿ¨—†^Â9I…ôvåYˆ£7gßf?_žm_GÔ£!IÔz—û¹ŠËÌû࿼VM§ÛMÀ9÷ÅÅ&"ò_îÕAW&ýÎM´z¯[]íô&`O¥O9ß|ºüíìÕåd(¬â1Úe1â!;­ÌØ)…‹ò1E‹rØèãêùÎAGàžCÃÕývæ>Q¡AÎèh˜›¶.s3ŠÙfiPƒä ­L7:Œ­ÑŸ©¬Èœþˆì„þ1ÉuÍàœB?KÿºAî¦oñÍõ¼3Þ0¼ÇNúJfXßþ?V®žÅtAfŒaoïRƬ$Ñ83ŽzKÈ<4~wùºlmO%Ñî—*ÜØ)Ô 0J§æ”=Ú[IÉoÔÛ¥xвùïpWvÒƒý™&ócwí÷ƒÚ’±Xþ2Þ¦Ítt·ñgƒaÐ^ÂàNƒW£ñ9ÝOmfÚ«J¥êðGC°Z‡sPE4Ü\¸œ¨%kÔ(ƒ*::Ü×8 N6¿N·ðæxÏ=ýU`Í—+f¶•XÒã~V»+º oÏ3Ú«¤íáÍ%s´“ôkxÏêÖÓ¼ÿKï÷ཤk7Ã?º7÷É endstream endobj 977 0 obj << /Type /Page /Contents 978 0 R /Resources 976 0 R /MediaBox [0 0 612 792] /Parent 970 0 R >> endobj 979 0 obj << /D [977 0 R /XYZ 90 720 null] >> endobj 297 0 obj << /D [977 0 R /XYZ 90 720 null] >> endobj 976 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F53 19 0 R /F52 20 0 R /F60 10 0 R >> /ProcSet [ /PDF /Text ] >> endobj 982 0 obj << /Length 2769 /Filter /FlateDecode >> stream xÚÅZ[Û¸~ϯ,DbF¤HQ´Út›¢Ù ’Ù}ITcÓ¶0²äè’É Èï9<¤,ÙòŒ7@S̃ÈÃÛ¹Ÿôð‹þøE^è(b©L.Û'¡£Þ>á®5‡ óÁŒ\?yñ³â„\ãiÀ»M,V ö¶³Vù7i$ læ'½*›6+ Eð ªéûûn]gKCv“7ÔÚe‹™H‚Û™RA¶vÃùÊOs„Ï8ÇÔM^•DXTÛ]Vçï/+Th`ܮ۬µÛnq;–TÌ¢(½˜ó˜‰„ÿùk³­>›)D‰Ÿó{™÷ [:YÁº»P\âÆN\ [qíLC±¸0c$.LŠ ÝCqÇÌ9× œ‚§Lòˆx\lwSB(Íb/Æ?Mkê-¸&ÇÁ¦Â#î¨C¬Bã3ŠÓ³ „jåg€´v’òÚ° XUPÛKTä#•Àê»ÜªZ7$)uHf鎨üQY‹Òçs1®œI›­]ä`\iW²nPŒ{Ò+Š1¡1­!z¼>;é&Ô%#¦E¯°¬mëü¦k ›Í¥”Á«jšü¦èíŠ2q‘—‹¢[šËI'åàyZpç¥âÏx©ù4Å-W [nÎõÀÙ‚ó^¯¯-ê«kZbÍ¡ç¸æS—y/¯&ÙJ4ãÀû”*Ä\²T$ß#nÑþq Ó4>R³r’¯a¤Ï“7aQ}OZÿ y×µÉ <,²5“ø,‘#ÅD*¾ËÄæÿbbK«œõv!cÆ?K:bI¬¿G뤊őõm‹´qFì‹X0)äYÚ€°áߥŒò§Œ²j}Áðè,'\éøŒê1P?„u‚Aeî¹]šUÖŽ™¾rÐØÊ[À•VìôÈI×L§dÁ¢0z¤Tp&÷J¶¨¹„r§’qÆúµÂã¤Ô}>O ®)p>—†¶òóMGÖûÃdX‡âÄ]ö’S‡Lñd¡´g¾¹]¿žV„N˜Œ÷€ÁUç\Ÿ0ÅiM™ ï“ý±Yë( Q¨hC£1­]d]¹vìÒ,LÔwZðõ ý09Hó¯JÊ®î(h-@͸u*h$¡×m É&&¤:×ÁtÞ#è,«ÒµºÒÂÍ©ÐÐŽõY¡£8Nܸ1ŽW “|‘Ûb‰}* ?Œ Žª“c3„P®ÞG©ôIý»E*%µÉNyWî³ÿL£‘”%aï"e5 è@ÓÏzöŒŽ+ò¦µÕ5¥L‡´-ÛJ 팆vé–Õ¼çç¹ï×\ÜÛ¦lŒìEV:ü'±À#æãAq¿‡É= ‚¥›MŽ/v”,\†¸CV]áfv;ó;"÷Áu¦lÜ:Wcì²ŒÊ _‰€|åMðYX$ö);äŽu5Îd8x"€ò¥\œ÷"toGÔã$6f:~´ …,ŠÓ£‚Ö£À;}[G Œ_:›B ‰ÄA)ª³ ~ž%tµ€¤Ì—l»³iF•@—Ð!,À'œŽ&uþkZU .·Ñ8bÿZï¶'2¾Ð½Ví©.Šðœácöá Õ;v( —wµ›½k«ð@ n4ÙÖ¶TPw…Õ«öьķo^ÉÂol`ºÅ‘¼¥þa·‰$;îlþÃ~Ý•4£ÝÔU·Þuá¼­™¡6æ¦YN” =Š;ï·öWÝÎïŸîáDkÁó²zF‹H¸‡±u‘Úæˆ0xý«ö¯©£möhF÷-`¡u±no&íb22_võà–¦}~𾻪,ª¿µ/£k÷<Ü'ÜÁÛ° aÇGV{A»á媆x9åáœvÅxQ¶ð ‰Ñô®E¸Þ6@9Àæ<%0Vrª~8¨ ‚ZVôòË+œýqZÒ—Y;"œ“Ð;.~w[Ì í¬™ºÊLÖˆíÁã‹›¼|qBT©X²G#XC$'€/A%"Y3Iü2,Hð¬!’ lxÀ…n Hâú„tŽ/^áƒ6Àbö“Ü-Â¥sŠç”³PŠqh4M·µöè$´+± ;ä.ÐèŠÊ4µE(tA‹¸; ŽY8ƒ$åhß®\‚bx54÷: -*¨;\$é‚IaQ;~ Yž~¼ 914¤rnd«.ܚ̆žž îE“¾š!™Ò;…QȦ‚Pž ^Ç?³¾ObÑjÂ×½‚™$¯?0šiECã™ûš¬¶iª'Åä`i›ù´£µÃõ­½·'ö®œù,€)á…¨±»iW]þU/·H¦'«¢Íwö7XpÜr²Dê};uE‡JjÜHûw± ­}U˜3t|•b¶²oj¥)€Î-.ÖîÎ%Ê)~‘i \¥É—”Û駪‰KYâr5  ´|˜Oë6t§ÆÄÏA"<üi1ÄjG1ŸÅðIÌo^˜¬qÍÐU%,Þ¿‚Z;S[Ç\c›þÑdÄð¢ÎÁõòÌ]OH:}ðÍbô ×Ô[\ KÅãl'OA9HlçÃí‘»¿iInШjÚ5)íûÖõ‹m{±‡o†A‰ ûãç ô/B_á.ñ ( ÞO$œËƒµïçp[šlÊ…® 2‰`r -²òœ €ô¦'ƒãßS»ÉeÞÓ @G%p|9ýCBÊ„Pòa ;ÿDÕÿ//ÿ6¥ìX2%å¶#IÇéĽVãÓéÒ¸çDb' ãê´þ™óDîN ço±Coè:tX[ûáÇWYí­ì¶(ò[W,#´à H³wþ#µÌçvï?8ôÓÓ¯Wo~{ù˷˧_ÿ¸zûîÕo¿~›?ýúöêßWwõídùÓ”éOªX@> endobj 983 0 obj << /D [981 0 R /XYZ 90 720 null] >> endobj 980 0 obj << /Font << /F51 5 0 R /F60 10 0 R /F52 20 0 R /F53 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 987 0 obj << /Length 2298 /Filter /FlateDecode >> stream xÚ½Ymoã6þž_áC«\¬ñM/rlq]´¸Û»|k‹V‘h[YòJò&þ÷7Ã!õb+›8°ÈáÎpž™aø*„?¾JÃU,%KU²Ê7¡£>Ýp×ÚÃfÂñþáæöÍW›¶+ÁÝN#«büfô9Zò'ð"ìQ{–ÁM0–¥ÁŸ|O¤Él§’7±ßûá;ÐSˆ+D87'j }릟)œäìŽÃ²y¹=£²c:²œÉ;h)‚Sm^&“z§ ËO2v'0PÕwD;dgj мš-¹x=SJyƒý°NànÂ9UŽó’Ž•q7ÜsÎ^‚ŽU¬‚3Þ<;vöö>¯Áé Q2ú€¿áÈÓZëÀš‰dàÊxÒ0]†)– ¸°mš ¿,Ü,ÂB$Xš¦,¸u­.dE °à`¬èœ"fI˜ÎÏ™- 2Á¿»{÷ò5±âØcÏNâð,.-Ózp£üp¼ßõ¯"à`=¼‘p –&19Zâ I‘÷m|¤ƒS§oOÆÍ~´dòìXE®¦#&µ¾7¥øh>ê~Æ-½*%Ƹ…)lg51MÀÎ #Øáº,~¹•%qJÂh3襣¢sÙFwtB{+^à›õ×H.…ØIÆFûÒ "A %\üÒt4kØ;ÏØÉ.D£åÅ2ˆ#ƒ…"`@œÖvP{HhO•!–=Äá%ÑÇ•Ž‚Ç¬+sP4ºµƒ5DÎ*e?;ÖK³ëÈ™KGË"â‚VõSN문î²sÄ3’¬ Ó+Ï5¼Mud½O:KFéÜT–‚¡d“hüØá`ñÃöÙ“èeôÙšgj˜—¾Í®šÉ›ºèÜÍbÄ›êè%C'—•îKÎ"¥ :i J‚”ñRcÕ îbËZ†÷&+2·‰ª0‚°%oßè˜A$’%^¾cÓö¨õŸ'fž0§mŠù<i.ë›Ö޶e¦ÝùNÞÖÄÔ¸†ób×»Ài¿$¸ô’oAà†øÁ& dóÆ{YÆÁ?)‰8½ŸÍƒÎ>!êÍŒ/xä|'ü鮨UÀ·4ëã¹ß#¢`û@—·@×yÅatQ`+²ò åÓÉ´gjZíàXwî@"Z½ ñ·+Lù\wqÈv©¶àx˜…ôrɇ06ÍH\ÎýiHªE¬@Å |§cZýëï᪀AØŒ©xõl92K¥¡U­þ}ó‹Ë½g» ˆ6zÍX2ÁÒÏt' õÜmÆã)‚î2<:º¾4øÜ¬„±›wÃg„Œh Ñ¡åÅC "Úå+OF„™{Øžîâɧ©±Ê±“ÇÚ†¦øÝϯڸúEì¾Þr#)A.\j.ù âbU5%l:Œ1N1{%çìîìZŠÅ–ÌàƒSVŸïÆÁÄ ºÙßàcœ¶'øu„z|ºÂNãG³Ö±wô­L×ù‰™cæŒG›V¼Ž8Íwƒ]ê‹ý¾Ãr¤ë¿ûšÝ©ÂÖ£›=¤Äw~×™ŽÇMÖæûÛaû‚1?齓›ˆYŽYÖ½wÁé¢ó£øÎQ'æÓ©üœU)½sBZÔÚ•C³cý  Ý”n)Ž7_Ð^a¶¯Úk wK¢ÿí~ª‘Í¿ªy2ûÄŽ¯=Üé¸8>í^­|H¶ùTŸ…+ùO‡É?Tp0y«"õé{ýÿÙÎél IØcWøø_ÙÖP´ endstream endobj 986 0 obj << /Type /Page /Contents 987 0 R /Resources 985 0 R /MediaBox [0 0 612 792] /Parent 970 0 R /Annots [ 984 0 R 989 0 R ] >> endobj 984 0 obj << /Type /Annot /Border [0 0 0] /Rect [205.2 428.948 522 438.948] /Subtype /Link /A << /S /URI /URI (http://www.gentoo.org/proj/en/devrel/handbook/handbook.xml?part=2&chap=1#doc_chap2_sect2) >> >> endobj 989 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 415.797 268.2 425.797] /Subtype /Link /A << /S /URI /URI (http://www.gentoo.org/proj/en/devrel/handbook/handbook.xml?part=2&chap=1#doc_chap2_sect2) >> >> endobj 988 0 obj << /D [986 0 R /XYZ 90 720 null] >> endobj 985 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F54 28 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 992 0 obj << /Length 1775 /Filter /FlateDecode >> stream xÚÕXmoÛ6þž_¡u&%R¯.]Ûݰ­CóeX‹‚‘([³,¹¢”,ØŸß²-GiÖ +0)òxw¼×‡æNÜYN†leN¾= ìêæŒÛ™ÞÅw—gþḚe°äÎeyÌâ²p~sy˜,<‘Ášû¬TͪjÔ ÃȽ8†n§JÕ©&W‹w—ߟ½¸Ü ‹…x@¤x@ÄL8I1F¤ÑÅ"C©ê»7ÏAÎÝõ‚»RÓ¼êú–¦7 ‘¹m·©š-Tîe]ûÃnÕÉBù…ªU¯ho+¹R[Õà¡Þòj;¼èêññ˜ÄïdŽ4›E»pD³…—¥Âýu‘En;,¼(MÜ\64QU¿VÎcw¢8òÆX&ŠZöJ÷4¿FƪÓUk—]»¥™¤cFxŠÂ>Q“~Ú¡ÃÜVW}ÛÝ¢ZÉcpã±B½ xD~ IÜVìê*¯zZžèbèZ"³Vd(Û¿¹“±e’DÆYËO€2Ù’”ùrNŽÇ3ôѨšÀe6x óAWÅÙÅè[CÓv½¦iëû ,Jì…ó¶é»¶~bö–,GMöŸ«Ruÿz³úqÕ«sÞq0JWêJûe>'È*öŠ.ó¬ÝBÐ÷0|äºóõUÕø»Íê½,,¡g5øZ?:æYÕ¿àûXC é{ï:kiYʼg¶¾ÃSÜïIƒÞ©¼*«œ¾®GïOÝcië6—ö4DÜlÇVûzgÝ÷»'¾¯U—÷w²_ûÖQÑ^.–¸‡"—dLð̉yÊâ, ]Ä–f†àK§SNyö ·iº@E‹–Kâè“Üíqƃ÷â>¯Ÿ–P/D=S mbþÔšÊcþKLù8÷CáH]•cªJ¨ª·T;aªD|Z`§-G>–â¤@N¥„n¥éÜNvvå˜ÃLAÛ{_dÉ]済å¬VÜÚoc§> U§ìQ¸‘›¶§É ñzd11i:PÈâ4EŒæ¬³Td#…×ͱIqöQ&P/£=“mkêv¡ £Dbé¾²j-¹ESJ‹˜³ “žd®f1\IѤ_;Ãlê0X(M€IÞnÁ •nlËÌý\>èþ„Œ›Å3ŽÍâcÛÏøŽšF8i†æ(Å~Ž Mçĉ¬µm8WV¬iÚ–]Iã-6Ãñè¦i‘îflk&ààûáéËo^]¾8·¼½eæEƱƒæxÀk¿EŽv8â7Gú@üêÛ9ðëñ]™BÊÛt-T‰ÝqKÕˆ‚ßì1F’BtÙÖŽ“ºB|Š3|5à˜×Òô½§mi<üÌ_UyÂIO´zò‹?AÏHpƒÛÒŠ²a¥f!殫Ær=þ~BHЦo/7F@sŒk#ÄØŠËÔ¶Æ`d\›’ªÖêcˆ»VŽ|˜¥à~de\B+ãˆVÖ{º–ƃ…ñ«*é°å’ÍXWïôpîN­ÿ¤‡¯›ûŒo Ï'š;Ú?#NÌåà/×Ü endstream endobj 991 0 obj << /Type /Page /Contents 992 0 R /Resources 990 0 R /MediaBox [0 0 612 792] /Parent 970 0 R >> endobj 993 0 obj << /D [991 0 R /XYZ 90 720 null] >> endobj 990 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 996 0 obj << /Length 2271 /Filter /FlateDecode >> stream xÚÅYKÛF¾ûW  €!Í&›/9l'Èköä´ÉCµ$©e“3`üÖ«)Rb2q€`¡»«_UÕÕU_•ÔM?uS„7Y…Îoªã‹P¨_^(iù0ÁŸÍøöîÅëïu£Â  us·›oq·½ù·÷öPžÓoü8Ž=ýfãkxowåÞ´›(÷èÍÎô¦­ÌÆ’¸È=g›_ïþùâÝÝtxEÏp‡3®Ù‹.ØKs¨X3{e5Ô]‹G] ’dA ÛÒ¬Ï'à+÷LUÿ*m,ôŠÂ{<˜á€¢aZÜ8• öe“¤H)sí¡›-·á̱lš'îm;¡’>ž†CÝî…rO§vã€ýü|„­aÇ7ðè«8P ³Z‹F‘ÑvkVø.EòÖìʱ‘9»NîµØÒÒÉüŽémGŒÓ‰I¤ùý&=ØŠ•¸P·*‚$›ÔX·vÁ×´­Ã ,ܼ[Ç•áÃå’ˆøXÃÔbíˆ\Cùeež‘Yõn±EìU_yÝñTöõFy–z­³½aì[‘{W6Ö°”~RišŠ¬é³²FaD“ ãiß—[³*«ÒÜÍ+ÛíêfQ ÒÄMêͱ{XÝ+ÖAœÆ3Åi±Ô:R“â°ÍŠÓQxV’Iq9)»¨8œ3mQ±Ò¬ÛÆi‹4¤"dq&¨˜‰™ / …¬P‡¹W5¥µø4°S·k È¢ V“``¶u»®€<È•z^›a¤Ý$üýþ†)ˆ¤¦k­›eóˆŠ*é• ëgM†ðHoÎlñÀKËôòtjꪼoÌ­h­ÐAžf‹gÛ›}ÙocÅ»›þdÀó7`—îh¬ÉŒºÏ‚"Ÿ}{sO÷#OCÖ³T¬g§– ScâhÉU-&‚¹ñ¨—ܧU]Fˆõp¸Xd¿ðdbH©hU× N‚vîB‡òæ ö€Ø·Ü×Åjì{‰:è|‘Ä-œšÁµ>ÙÁ¹]çÁkGÛ›ÿŒÆ ƒ±÷@î§·pIâ¾JçRº¦éðÔGû†ÕŸ†sõç®ÒåCkÍÖnJEAšL^áÓÇñ >Û ôåúÀŽe‡wœ^ÄòP_¶ú Ç~÷ñ'”æ‡ÅÙŽ( ¼ý³'§_sòçŸß/…þמ÷U’þ ÖÂFÜ-Îþˆ#]?€þ­2SÀéùöów³óã9ýúüsª¥ xÇoèÀ<@éktL4t—Áp±Äxc…›¦š+x_’.Ïøðá‚€e‰÷ ~ “[/_¶}_·¯w]Ç$ß/û½åö+ëhÇ®74ðrÚB­©Í^ffÔ“i16Ë^h$%|«nì-ÑÀëžÐÉ–  &Ød ö4oy0™dÑÏ#=ùÜyk ½²kœÂ.§¦¬Øs$â‘. O/1$ÛòhÜ´ J9¹â¦¶Ã2Š®èS“>íjèô)".ÞÎÀ¹yøü™§¡D‘ö8ÊV¢%|Î&æ.|Zžq?qŠ˜K”W=?‹x…ƒ"šÅO3ˆ%zÒ\âä[@•5L$uÎ1 ¡ÙòN×÷ÍÓZnÕ­¿r‘dSœÇ@Ö—Óöøå<­yÄDÿ bÙù ÃÔ÷Ý`Ü"|´lg»£Œ] ÄÉW4ÇùP¤ó vaÛÑÆ¶5•¡–ýå½PžQŽ.Ç0<Èé5NôÄ wp®AØÑíüÑÛ¼Ze™CoØ$ô† Šðuèhgô~î¼þ•,®å{†_ØãK§ÍùCÀbý¡ÎpF:œ‘)Á’¡ÃáJ¸"^@öUÊjqy2‹­ÃÈú Å塜¡Åu@uvQ›a7®>€Ž£%¸yÿáîÝ\SHe†¼XãИÊXƒfªªë·\«„QΑ¦2hJ¶TgD"]V!ê¡SæHõ–«›ä·èÄÖ9Q:FâoŽ(€Äê1!6pòjüÆ ¢Ó‰‡X³Á M°³žÃeP4Ú ¸ë[#(ûÈ^xkQÿ‰t*Žæ·òx¢ì :âù´ Âò5ÀpÉçÒ-Q!Löó é’Z©ðJ]Aêú|Ãîñ·Û‹޵øÍ²ÄkͰ—o/K§hf¬›·æéãJö'‹lÔ\Ù®,÷lq¼C¼pq =¼„3ç2ÚZtA3•É"Âð\ÆÇN'_Vnèžt¨<¬OÀ%T³Ô fÙ±‚`kw#9àýyÇcaÏKd¯p%Á¦Ú ½?ºÍ0=ã7á~™®™ßèÏÈëÇ–üØàÚæÿ±àk‡N×bf44žø+ Z;0E%Ç ëÃ¥M&N7†m×JK°Eä²…È% ð Äz*8b½ÍµÅßSÌÄÇêLœ ø“¡öŒ¶s¥ýfVßpõÛÌ{ZþÉñ¥å)ïc7C¦±·¯æÿ,¬¦’³4|æp%9L€ËÕÊø;ö$¤ñO¯ÿˆ|™ endstream endobj 995 0 obj << /Type /Page /Contents 996 0 R /Resources 994 0 R /MediaBox [0 0 612 792] /Parent 998 0 R >> endobj 997 0 obj << /D [995 0 R /XYZ 90 720 null] >> endobj 994 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F60 10 0 R /F31 21 0 R /F53 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1001 0 obj << /Length 1790 /Filter /FlateDecode >> stream xÚ­XÝoÛ8 ï_a àkY¶{èËív@¸»Ý-oÛ0¸Ž’uìÌvÚõþú#EÉÛÛKERù#æ…ðc^z1çA*/ߟ…–z{Æìh Ëǯ«³‹ß%óX¤aʼÕf,bµö>øŒ'‹e”ͳÑÕ¶¨ôbɹðï"ür¿ÑÝè*׋O«?ÎÞ®ze2Š^°9NÌáÌK‚T)Ö0–‰§0.È C–ßf[Ý^¢>×£Ô[Fp‚ˆG£×»¬ûœ|/§LpL¡,Ó^,`.CÿN7mQWWá% @Í’±&ý|¸Ò_h|¸Ýî·ÍUsØÓ\—­^ë øâªÒzÝ‚0ÐóØ•K¥!ЫÀü”ô^Wà6!ünW´4ú2Ñ´Mô×l(õ9Δ¿ˆb_ÓJÖØAYÃ…Ä~}[T[¢lêÆ µ±wo8÷¢˜Ã¨ôÞŸý3Π-ˆSiD ‘ÉÉŒJ)‚ñŸ¢R&AøHcH¾¡›CÇ|%Oì²––ªš¾ú`y é|sy;Z¸ßãia÷™+GIm¶·^v"ÿÓMwÇ”ÿž¤ê¼Ø<`Øà=BXC§· ±!Âп/ÊG nÍBúÎê#-Á—ùoˆ¡kêãM©A¯bíDº‰†¶áøHGž[mS(šøRA¦èncÝ3É&„É5ËØÕ¤âÆ¸QÓd­1Õ*ŒTTZ€ñ'"‹I ò“@r‰& € žAÐä|Û)Ì T…šj2¸«º³—3e‚yBjVk^WàÕòi,£<ºüå”ÖÓ›ìXvïn·nB°+ú|¤Qm@b6>ÆØjy««®®ŸÁÕoÑu¨›Î`ÂTÁáÉËçÑþôð/¡}vkÕ p/¹Œ¬wöX\‡Ä6à=®<‡ø‘ Ô€÷Qìò4†<ÕpŸk"h%)¢½‰UäÂ|ïKÇBØ’o‘zgðµ)2È9»¡¦o«;ÕKX“¢ššáÌdOá6xìŠ*àì™çG²®kŠ›c‡y%85£C± a½ ŒÀù,X9&À•8æ¦Á®Ç¬¤ñ©–6;‘`0 ¾p]Öµ8,Ãd™ë Ù:7Ÿ/NB@5WÒ2 Bê[¾·R ˆ(D‘)8‚?Yœ„„°béOQ©€_ª©Êй‰ ŒiñŒ§Z—˜´i …ìjtŠý€;‘Xc l—\Ú å2¶LÛVÀ J€8Ø6:ëtãvf‘ݲþb.Ø,ÖD²½ŒF€Œ-“ƒjJ`{ï¸;/³¶ë`¨!.÷å'}¹øA~ £Ù€t8òï»?¯)¼ßÔû}†83+èÕűm.Ú›¢º8¢uÖY {ݾz•£Qù»@ù›1׬@Î#‚Û<~±ó¶ï†• åPwŽÊßc¤]‡…+e1Drq¥¿á倰Áüµ Ñ¡iWÌr}èÜ®ÌŽŠ‹]Øguݹí‘ÇQ³€;^O‚׆Ýð&K¤‹dþê½±&&oàëòcCË&öbæÄB{[9Î f:ÿÇ¡Co¼9ZmñÊLrBÈ»ßEÌi„Žmär ±Êo޶y@{Ý…ÂJ¯¯gD( ód†õà°@(.gÎÂ)–Z Éè Îû;‚Ñ \õ}.г¥ngŸ¾}?oŒ êÚÑgÒ‘LÞç¶àÝ‹ # dÇÃÔhÙbR VÉï¸Ü³† õ<´çãçt6Œ”¬ zÛGÿCüõ÷ê-â‹ômŒÐJZ´’Ô9Ñ_R’1ٟ丟2L;]M SžvÒ¢*Xϧ8‡ è2}ù=‘çR"ê[D'º¯ß6ãx¡Mo°ÑÛ¬Y—ºÅ'sœšX¦ø`‰ökN<êÉÓPqÒó­Ä  ¸Þ¹o¿'ÌE;ÚÔ¶›ci½ìJíh”o Šmk:…Dtß®P—Laæ¿%W³-~Þm®øÎ½­¡íLµýéÿÍ(3• endstream endobj 1000 0 obj << /Type /Page /Contents 1001 0 R /Resources 999 0 R /MediaBox [0 0 612 792] /Parent 998 0 R >> endobj 1002 0 obj << /D [1000 0 R /XYZ 90 720 null] >> endobj 999 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1006 0 obj << /Length 309 /Filter /FlateDecode >> stream xÚ…‘1oƒ0…w~…Gb×ç³ îÖFíÐ5lQJL‹Z ‚¨Rþ} 6"‘"Œïq÷½w@¸{€NRDfdFÊ&âáö'‚p¢N@Š×'TJo«â˶‰Èâ³/ô¶²½mK›P¡Ðd1 IùGô–_‡+!Њ¼T ¥Og’Jç*˜P¥…Ch‹ÆŽC×–œg0 Dpô2xæ®ß2þ}Ø~¨»ÖÆg_SÓIW‡ÿ ÿ9\ÚnŠàÒøûª )ë¡øüµ¯ÛY»N50äH´VŒs=ZuÀSq‘Ƭ¢ Ù…­›Mw¶<_ý¸¸´gÙ´ÃÆWNnþ”âͺ¸ËÖÈ%何ÕÈu³ ’Í#ÿ埜 endstream endobj 1005 0 obj << /Type /Page /Contents 1006 0 R /Resources 1004 0 R /MediaBox [0 0 612 792] /Parent 998 0 R /Annots [ 1003 0 R ] >> endobj 1003 0 obj << /Type /Annot /Border [0 0 0] /Rect [361.303 662.279 504.394 673.188] /Subtype /Link /A << /S /GoTo /D (disable) >> >> endobj 1007 0 obj << /D [1005 0 R /XYZ 90 720 null] >> endobj 1008 0 obj << /D [1005 0 R /XYZ 90 720 null] >> endobj 1004 0 obj << /Font << /F51 5 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1012 0 obj << /Length 280 /Filter /FlateDecode >> stream xÚ…1oà …wÿ F å^[µC×°E"'V'±ÛJù÷ãTȉ1Üq<Ýû€x8€*ŽŒ”¬RÕÇ‚ÏÓCsGƒ€fŠ7W¼~–€€³ŠW€\›¯p ZcPœPaà ¿·¾ßu½'TJ…E¬¾õƒïkO6î«øpÿf¥Oh¢âÇŠI¥ÅŒ£­b U‰/„–Zß ¡€ºÁ7Ñz$$…Š˜s¸}7&àTÞ¦ëxíO=_iÞÀ§!õM7Æ—$\ù»ˆB¤uÉ8ב?øOYĨ ™äÁçK&Ô•¯¿»À4¹†ì*±¬'˜ÍLsÞî|ê _bIË™)mŽöà÷oª'xËe"»Yþ*G‹‹ endstream endobj 1011 0 obj << /Type /Page /Contents 1012 0 R /Resources 1010 0 R /MediaBox [0 0 612 792] /Parent 998 0 R /Annots [ 1009 0 R ] >> endobj 1009 0 obj << /Type /Annot /Border [0 0 0] /Rect [247 662.279 380.758 673.188] /Subtype /Link /A << /S /GoTo /D (disks) >> >> endobj 1013 0 obj << /D [1011 0 R /XYZ 90 720 null] >> endobj 552 0 obj << /D [1011 0 R /XYZ 90 720 null] >> endobj 1010 0 obj << /Font << /F51 5 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1016 0 obj << /Length 1612 /Filter /FlateDecode >> stream xÚ­XYoÛF~÷¯Ò‡P€µá¼òÖ à>Ea (ڥŕE”â*<œøß÷›¥›Š´ðgggç¾d¹ˆñ'E¼È´…ÉëÝU°_É­@°:¡øáîêÝÇD.d,Џ‹»Í)‹»jñ{t³-÷ƒí–+­udÞ/WÆ$Ñͦ|°íRåÑÀÝØÎ¶k»\©Dy$\þy÷ãÕ‡»ƒðD©W´#Šêej!Ð&UA½47BjÃêá&Y®’TA…Þ5K-#K’ŸÛÃe!¤ fÝm¡ª‰UôG,M3½P§/Œ¦HñÐ?xg‡õ;–!Ö®ÝÌÉ(RËbzÑïáŒ<²ëšdØžå “àÊnʱè £¶Ü-£ÞväVr8m\l¹&ü–O[××e•ïgÿ¬iøTžHƒ¢°]g"‘ ¯`㼂ëTQD•Û•uË0)$À±½#ŶKÕ`ªãxr™§[—áAÙôޝáŸ^Zt|WÃq2rÝ®j×^2‹î&iX—]¼ËèÒµÍS@‘˜œEÎÛÃ$[6lëö´•0ocÛ‡ºµá4v]È\âåQhË{°Ïq ÛMݶt‘E=ù`ï/ÏÍØó òÓ1hÍ“Wl O·nl*¾û › rÃ`«9¼’ãÎvµe ²aÇÛð7d“ŒnæoYU°¦çlC>Õ¾& |"~nìÂÅS?ØÀlW’¾O!]HÉQi+Ø4”mõLÚ`¿ '*Íh_CA©¨¦¸fšsgÏžk‡@¬9À#i(­ÆÎV‚ ú·enØ‹ 'ɱþÐÔýÀÏÊÀvGñ)Ûš NäÇáð¹î·”‰9Ö)§Â‰Ï*æP³ÚdgµJç2à9¶¸=-¾YRwò0Ù@I–§Ü‹×ñ5¢Cì„uKÓx_™4ªpö)‹+Jfpîê á=ª£8 -øv‡—óC…L­|ØvÖ—>ú-¹(ÒÔPëS¹È+…Ör«´žvQ# ®Ñ*Ñâýýîé¡sãþ= ÃKjþž"pªÊÄB)êñ“α0éK¥ÔW)„žë×8BëbS‘N^7ÜL†Œâç›Éb®»L¾Ì.Br³@í9à¨ÒC. ¼Õ 29fSöýÜÒq*L%¸lÎØHP Dôò$‹~ÝÚ ý t \ð3‰!R•>O„Ùa(êÌLBpg5¡ÐáÚív¾}è> ‘ÈK"r#;ÌÛrM¢·ŸF¿VÌHÊc!óƒÍTÁIB¿giI?g&ñ6L"(J=‰/Zœ)!‹ƒ%a8Îe‘.2‘êì¬S<.T]W—÷/!ƒ©™Ä½ ûÔ•5¸9áòVªIöX;Ѻ9ÙûOz DÈiëѧz–\‡Ê.ç$¥àP˜oÚr¡2y”ÉË ð}‡©mÐt˜ë(8#ŒÁʇµD§gFQ&'?/é©ò(ŽDùj—øÊƒ ]ãâ‹ ]$ô¾CùÉ T슲‘†C³I–I‘åù¿)+#2•s®x‹ó- Gžß„·ô“ѯEŒÙtnwÔÌ—7a…¾ž'ß’#è-1›œ÷–±m°› 5Šü’CБ9݇Ý~xúÅ‹º¹”ˆKrÈÆge9¾`cäÒ#ÁŽ¿o‡n´oFÃLuÝtÈ åË-ÈÏÛzZÆéX†äyÞµ)jê´ì;ûX»±÷3•a¿ðƒjáþè‹ÖuKÑúXD –×PÉ\`::W §*áÞ«´—"¦ [Ò)2üvúžça=ÁwbÉ)`€¼>Ûù渎áÀ[-€’?ŸFG;­‡{l&~WÎ3ö<‘Uá²uíêÜÃŒŸ,Îóä.–£~rp°å$·8{ýÞb¢Ë\ûñÊ®.wûÆþ·­E¾ºµ¨ÿmkyó÷ OÛ| Ÿ¼9£Ä>g˜æ¾n«k75JíÍ«KODÞúÄš~—h£î¹½à'TÏWŸiC¥hø Š’?>šÇ-Œä¬Ä^¶£­‹£þ×U|úë˜ Xk»·Œõõ«óðÃAûâ´á…O_XÖÉ1ýâ˜e· endstream endobj 1015 0 obj << /Type /Page /Contents 1016 0 R /Resources 1014 0 R /MediaBox [0 0 612 792] /Parent 998 0 R >> endobj 1017 0 obj << /D [1015 0 R /XYZ 90 720 null] >> endobj 1018 0 obj << /D [1015 0 R /XYZ 90 720 null] >> endobj 1014 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1021 0 obj << /Length 2442 /Filter /FlateDecode >> stream xÚµXKܸ¾ûW4ö5`É¢Þòmí8€Ø›`fÁîáHœn­ÕR¯(Í㔿ž¯XEM÷Lï:4Ð$‹¥b½«Hµ‰ñS›:Þ”iÕYµi¯b~}¥d!<ÁxwýêÍ_rµQqTǵÚ\ßž’¸n7?*K¶aR¼¿5îÌ6LÓ,¸KhLƒÉÜšÉ ÙþrýéÕ‡ëõ°Î $ÙiÔ<¬Òº=èÁ1u"fÁ‚oT`Z^Í#cÛîpì»[9Ô±ëˆxEéfî £ÞwóþL%6aµWI`}ÓÓ´hÍ]× Öó:9Ar†Ã¨y°³žMo¬}u?þYðn´õ¤3¯j§¯ €š—'^*€q ,¼#[m8W§õ;KŽºžäL]ùó3×]XF@m`ØQ[©]9e:!øÒ£¤}O¬ßùˆ'õÀªyü ø¹ÎW}‰ÜØzÖÕ¼æ}Wlœ"Á`È}Mدýž>3Xø|KÂk¿¥yx t×pH²Gx«æÆHßž¸!0F*H%ÇõÀ[š‡cw|òàZj8}ÉŽÑ’¢&Q®pqôÕ®m[¡lí sú@'WvOîwcú™ aã*v6&‹f¹˜6Ë3ÎQ\s2þ¡›÷XÆs}6ÐÖ=0„Å+¹ Àz?JÒH‚žª-¹ÞÀߢ#b–^OüE7!•+ÅÄÉÐ^(HüG—ûëØ»aͼªékJmyç~˃=/]þbi)ö˜¤ô`} H¤Í49ó`ÚŒ¬³É5_´Ÿgòõ/D{ÉamшôT» Ô—ï/e$ßÝ…eq¤ÃÞàJ'»÷®+‰Ï kji×€x–[Œ•0:âkó ßÎ’ø© `¥Îë/#¸[š—Òo™¦Ó½PÐV¾vå ñ@Üp’ÓN’”Q’¥P‡cÁÕéèí¥QYGqæ±Ï8#?Ê—}¤wUTH¸ý ÓDE8ë\é|J˜Ô%'`d6nÒ vvIŸÀ$Å)Ú?/É¢²8JsÏÜ››nxc÷—„ÍñO®§IXýD|½ÑЉãQŒvœs;><®ÕiÁ™÷£øH/AÇ  Š£,SgñC~vIž"*êò?7M!€=zÄ(J%›:ª‹¤ ”°VNûa¥‰ôG(D©¿nÿ¶Þ§ë<ªËj“æy”%tŸþé—xÓb ‘¥uµ¹wˆ‡M†©1ï7W¯þÎ÷îóSq…Ò²pÄpK÷§ÆN#U×›¤th¼©`&§g¦jSáÈ"sWý4J«rƒð‹â<½ À·¬ž¢<ý(Ê`‘0JOëáÎŒzF?É¢¼\uýö­Ø6T!DÎï.œ“Ee\­fE% -2ÄÌËsò$ªÔŠ{‰‰Âaœ„î"ùê¿/iãY¶á‘…úñ{naò…¼Ìÿ;Ÿ»UƒŠŠâòÉ‘“ßudÂLÊôäÉÏÏUÙi<Ò:BbC”QžûïrwF½Ïl¶¹ výKHô^ Æ- ‘Ciy}óÈ#_¿1ùxu~øüý—ï¯øÓ/f¾wO´ë2?Æ ¡+'†Þ ¼ô\ðè¿üã‹G†rve¦»n%ªöYhof˜©ä  Ì{ªù{jŠš=£þ`û‘÷èåɽ:=òÎûѳ·…^e‘ù¤ÝÑôœu‘Î~ÙŸ¼s*&éMiœ1¼8˜ÃÛž.fUÇQñ"­ž?,† ,D*­ÖçÅRž¿•ºŸ½3>=Ž&õ¤|Ç\Üu,ÉèaEvt7Q¯Cs÷–fBÜm[êD4kûÕò´äËɽºÝ‘ÇõG -ø¸®ðu>òÀçÍT¦Šà£°Ñø2wñ± œ¿¦’˜­Þ¸%z_ê{žQÿoPl¸'M~H„QvÐx ’æÁ6äfôF†û²¹•‘ŽÐÂQWâ–gíAœB«•»IðÑHP`ÿc Â`ü¥w¹7§´@w>;yÒ¸^_P°B£p{vý³ë˜ôNvÜÕ¡ð7VL¸àPçlðèÓ…Ñ×{øJºõ½5Ý'éñ•¤ò§·dÐp³Yf÷º´Vå¾MœªÒ ‡“ì‘_´®÷kn™§ñð¼g–«ñ·.u„ùÈ6×r?ôȹÏ-ãlžµÚ ßäõ=MO´Gù¨³ûsO¯X˜Õ˜6òEäßJuz$ endstream endobj 1020 0 obj << /Type /Page /Contents 1021 0 R /Resources 1019 0 R /MediaBox [0 0 612 792] /Parent 998 0 R >> endobj 1022 0 obj << /D [1020 0 R /XYZ 90 720 null] >> endobj 1023 0 obj << /D [1020 0 R /XYZ 90 720 null] >> endobj 1024 0 obj << /D [1020 0 R /XYZ 90 180.024 null] >> endobj 1019 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1027 0 obj << /Length 2032 /Filter /FlateDecode >> stream xÚ­XKoä6¾ûW¹¬ ¤iQõ˜ —Ín€É-ˆ÷”Í–ØnÁj©#±ãñ¿ßzjÉ–§½IÐ@«H«ŠëEÉ(ŸŒª$*”UVFõñ&ñ³O7ÒS;`Ø-8þys÷£–‘LD•T2ºß/EÜ7ѯñsrv¼Ý)¥âìÓí.ËtüÃÞ<Úþ6-cÇ/F»·£ík{»KµªÊXfêö·ûŸnþ}?+×izÅ:äxcž”iT‰*Oó`žT¢(›÷ßDΊ~Ÿ%UZTEIœp‚¨_K¢Þý%싞‰óei.²×uÑ/7?o©Ôi)T‘¿Ñ›lèM„¬ª(“¹ÈUù5½I”VRdI±Ô«dT‚Ú<£*¡Ê"Ê-OrÖ:l×ÕÃñhúfú„úï~Ì‹å"‘IíR8OØ­©;3M̺’ŸfBB\ŸHZ´“ZÈÜ HùÕ7z2Q$eXë ÚMnlûÇ Uy'¸¿aE™‚ÝgkS]{´ÃÙ}¿¡P"×U1Ùz6Tí<ã\:˽Üód 9/X«åNR¡ò<vãÙnh‡óÔånoºÉn©Ö¥(AÔZõÑLO[§J³”¡v¦»…Ðq>>@¼mÈ÷KX¾_÷ÜÛñºøsÛ\è ~‡óéºÄǯK\úσ©ŸPjßlᯥ(fOZ@»Æ¿JÎp9¤µò¼É«“¯Mû|€ÉÖn_>{}‡aÛOSQiù!¹žueïi´´öùÝ(ß:êJ¨¬À‹©-_Fî»®œ§"Ujm[Ûï‡ñ¸u†ëMÿµCÔ‰HóW¨˜sӺ마"ï†~C*–”²zË›„V¬vp7ì÷›ÐP2[å­~0ÓɸÃf‚)DUãïñð j‚Z‡W»·9M¶Ùh­üØö›9Ós­0·_Nà¼fï¶ó‹†²Y–×{®XÝ·½½;T·v];¹hß—¾J4káë"Žõ^úOWñ7 K†FJ97é» rÂnþž~åµZ9ƒ²h÷ 3÷.UBëìýоn5d#@_ ©½†ûC;q3ÈÏ,vË^ÜÀo U,bËûÅÖgg±i#+KSðÒrÕ)¼k™?æÏ{T¢ãlU‡32hÏ’}83œ\;ôP€Yœ^Š“ Ô~Î9æ}Åd®d޵“ÍÑBô| :Ê•õ¬¶ÞÛþœ”u?·]Çó3GÇo¼y:žN U}»“q '™ÝJNÆoÚ²\`öê<–½" ® Sೌ[ÇOû¥&):)š`ÀùØþˆ‘Å8›†`9ò œI'd°Ôdm¼h¿b"¹Ô¤³pmH+ï"(¡6”¦¬•ÍŒQiìÚögĦÊc¨<!;"þ Ö„ÅTŽ€¸”#t”‰/J´‡&LÞe=߸KIp8ã–嘭T–\Í‹€˜^ 䎵yvf=›¹b íÕ¾CpBXN‰Ôÿ™€ðÃÁµìsÏ;ñÜDü$ñ;ñП+Æc;aÔú׫JÏBB°ãÀ,!³Î¯¯!é;®óÇf ­¶l96KdÒ›‹@†æ†b—{ Jœä:½QÌ—…õ²»|»1>ã¿Mr)^œÙÅý‘Ï<‡cÿ o±TñGŒ>Æ„m/_Ð7•¥R’“ Q¾g–^‘Ÿÿõ‰©aÏOB",ÉÛìäÙ¸bÑpKn‚‘ÀBpž¨“ ¶"¿F&—ÏU>clvp5Öž÷°%â·œ/Üï î¦Õ«’>‡;5<JÖì*Îûs÷Âe _Ó¹3Ügjçg 6 6üGzt—lk熖«àõÖÍ}ÿMdÏå¾\`ƒfè=Õîùy¹ÐìÄÏp) "Bù/ã‘Sþྃqª€8Øñ¹,ÆF:]_ l¢éî×u‹/#üAÿhÚ>DZ%v¹9#Â+èà·ÐH†E*t+² =85c~¿"Ü„ÿûŽC¸ endstream endobj 1026 0 obj << /Type /Page /Contents 1027 0 R /Resources 1025 0 R /MediaBox [0 0 612 792] /Parent 1029 0 R >> endobj 1028 0 obj << /D [1026 0 R /XYZ 90 720 null] >> endobj 1025 0 obj << /Font << /F51 5 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F53 19 0 R /F55 85 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1032 0 obj << /Length 1995 /Filter /FlateDecode >> stream xÚ½XK㸾ϯh ¬ËzKÞÛÎ&Á$@rÈ4rÉ»´D·™–D‡¤ºÇùõ©bÕ²[ÝÓÈ!ð‹õüªèô&_z³Knê" ‡×½Ð/Èîu|çzr'4’+æôèíjHwm™Ù ýº»48Û[Œȳ½páÍ¢ùtŽv¤1©–ÝÄœˆ£yzä³ÓhÏ^øãhô¨þレ3R 6¦È½Œó ‡nïª Øüñj”'DôóQŒ÷|¯»d%6QvïemÎj´áSr£ï/^ûó; TA£µûžwGÉ$Ù’$Kã²ÉÑë¬ò<¹ túä”Ù²ŠÈh ×²æ †/'ãÓ(ÀÉÒZÚ5$ÚÑra&\B¬ûqf‚ÆÀó>9Ÿ8ùÀÇq¶)›¸.²‹hMô›;r¢˜ß~ ý§£"±iɰ԰ÄMÔziqÂvDQq.}´¶âäµâ#£A»è3 mN– Xë{ ì ß«_)V1i6%5µ7†qÿiô\`‰Ð2YІì½âYÀò¸ÉÓÙeþüšg³¸)ç09 # ˆàÖ.’$‚«Z–Hаð!._:w)ã›*Úƒ·ÈUi!ÙÔ—jë‰sßë‹èDK2Ç|WH,9âþ£‚¤pxo®ŸŒ|TòéÏ•¦ifK½Î«å^æ ”AŠÑÒÔyÄ£™¤‰=ʾ‡xG+RíÄ]*g8Ù}ašk,ä7ÙNÞ:¸ê&3'FUÆIÝ\—uÝ’8«gÝ6›Îœ7X×,UÅU=ÇãÃ"Î '¿UFie±`Õ°¨¶ø¦) .ì¸/úž2×Ï%WË8îCvâbðpëû“-"la¸Õ.˜Ú¶,®ŠòHæB¼ŒOÛu ›K,o]¨¹X `ú¸¶ÖJë‹tP ÷CxøBrÔSß­”IÆ“¼‚ÙzÄ3ŠTqRr+ù5H—Aî–&¤¡ü ôÁiÚ •>£c¹à6ÞÌ}àÓŠíÉ£•PãØþK¨õÜà 3T^H$£ûžß` 7Ú³urxïó«“ìA¾ÓRþžKÑ•ªoµ).Ž$ùáêåya)‚ddýìÔbY>L¾Ñ»®ÿ¾­ÔE¼ýTë¨+ Äô"ê 2ûíB᜾ÙÐÕ•W:þ¿ £Ä¾NŸöÖ)7=wc>µy°Ï—¯CÅgêêÊè‹ {&X§è¼ü& ÌÉð¿¼Ì|ôVƒ74žŒ€á^Ä%ªÚ½*P¿Sü/Šî.cëÛi,~äÏ <øøkF_?n'k¶½ÚoÁŸÝv:uP»ýG~-0»Ÿúþ ˆüUšGilüu;q~‹?¼ß·£¶ò ç_¨eVFÛß! Xå$"­ŽÚ:¿šR""š³Ý@8ƒ›£„êß”ï³¡Õ ¢þñWá&³ti§ KH×n[á¬ÓxÝæ‰Ç¿°àÞ\ºýh>†ÿZÿ 'Äg endstream endobj 1031 0 obj << /Type /Page /Contents 1032 0 R /Resources 1030 0 R /MediaBox [0 0 612 792] /Parent 1029 0 R >> endobj 1033 0 obj << /D [1031 0 R /XYZ 90 720 null] >> endobj 1030 0 obj << /Font << /F51 5 0 R /F67 34 0 R /F52 20 0 R /F55 85 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1037 0 obj << /Length 1531 /Filter /FlateDecode >> stream xÚWKoÛF¾ûWAR@¸â.—/9$† ¤H/µ’]Sk‹EªäÊŽûë;³3¤(…nÑBîc^;óÍCrÁO.Šh‘ű(t¾(÷WŸ~»’¼ œP|Ø\­n¹‘(¢B.6S›íâsp½3g»eÇq ×ËPë$¸~0¶Yªé*s_[²Á;tö¶ÙÒ‰¡ƒ²õN9,eP[ÇÔuÕ;ZyG¤Ó÷O„qÀ::%Ç öI¦„’);…¬zßP~a²e`£ ª¶kö´åÜ›Zþtp}»”Rï?}ºþôþîØnîøªê‰«·ÌnðuÓ›Šuú@âÅCÛí#že£ÊE¸„|•ÃëÛAçÍÝ;ï¹öEŸX1 r• ÎÂÍΛ£ýó’S`ðd¸ù†N°G»ã!tm¸5Ž©Œ?×ð>Æ>VOÉ Ý9t¨&3=WnG«¶©™‡üÔc@=¥O“<ر–Ž%Œ@ce˜`|ã“#MC{C¸Ê; ·Wµ ­ÿ˜CºeÙõð8çM)…Nô@ó3‹îHÙ¬X%ERä£Ô.´ÍÓœðHur!¼4lô=|¨R€ª#¸·÷ÞÝÒ-eA::‰vÄ›ÔQžª®%„ûî‚'ø”£tQðÊ8ÍÏÒe”¼€hÖ5­F³pS5;‹…q;Ü1>`m†±$úÓ†IË–Ì2UÃWŽª„Ùâ)a b¦‡ f¼ãoÓºÿ Nz:M‡j@ùpèZC/Ã4ViÐW¾ÙâmßzÍJýKïì¾§ „¤wyE¸m£Ôt¸pdœuæP±Fê<²p,kxÅ¥£·”<¬™‡pu̳í(9¡¤:üpäšsÓumG3¶†:<·»kʬ¥qÄ`ƒF5ó`ƒ åoi×z(ù¸WÅEA,Ù=v˜$ ÀÁ¾í "Ó ¢Y1–Ïh/ö µm˜¦?˜ÒžÌG;øÌÓ;éÕÖgÍ[pδ  ¸tp»ÌcŸÁ¾|7ûCm×ÿ\‘I2 ÖumíiñVÁð*Èfµ(@%µ·i|ÃÉä݉Ùt²ÁÎ:33õ; ívÒÌD4ôàEg"MòsžL'ÍþãÕø•Y߯ËñPÎèfõ ó÷õËú¯ æP‹,ÊÎõŸ™¿>=^ž“½YÝWÍÊ–»–dú9m÷ÂÏŽ½:Î^òE¯Óq6`˜w†sa<ñå æú8’>Ð×—#\Ð8¤#šz€SœwÖ^NçqöÀx© €PVàø vûËÉ„>P…²™?—Âü3ïlIÍ ­ÒB‹˜–Ÿ?úWW?>Û'ê×·\÷S6aR÷«”ŽT óˇI• åþDdªxå¯Ç@NÈfv)ÌkÇ*¯ ?“£ ãL®#IsžRh«æ‘¶„C øV¨IZroÁ3WíYJ]í+GKDŽjHÐ[Èó-MºþrÒ½rjÄ¸ì¹ ”¶`,vA3&¨wÄ´>ÆîäÌð¢Ë£ZÙÝèµi<Î ÓA³tôð»[]y G4!è(¡’iNo€Žg‘ÏYÚU8ºy"ô*ö¹½}Ê·Ö“¨tp#H8î‡gjZúĉÎ,¦ö~H%LãuºÚ‹fAìŒ endstream endobj 1036 0 obj << /Type /Page /Contents 1037 0 R /Resources 1035 0 R /MediaBox [0 0 612 792] /Parent 1029 0 R /Annots [ 1034 0 R 1039 0 R ] >> endobj 1034 0 obj << /Type /Annot /Border [0 0 0] /Rect [356.689 296.152 522 307.061] /Subtype /Link /A << /S /GoTo /D (Iteration over lists) >> >> endobj 1039 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 283.001 127.108 293.91] /Subtype /Link /A << /S /GoTo /D (Iteration over lists) >> >> endobj 1038 0 obj << /D [1036 0 R /XYZ 90 720 null] >> endobj 1035 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1042 0 obj << /Length 1182 /Filter /FlateDecode >> stream xÚ•VÝã4ß¿¢:!á¢m.þHÚ¬tÇéBˆŠxàÐáMÝ6º4)ŽÓ¥BüïÌx&iºÛBy{<3žÏŸ#g)|rV¤³¥ÖIaV³òp—2÷ËäÕ‰o×wo¿ËäL¦I‘r¶ÞNM¬7³ß„4ù|¡VÀ¶®ÙU›/´6â¤jáÝÖy×”nþûú‡»ëñ²L©ÿð%^¸³T3imrÅîä+“HmÈ8YÍY®D¼ nW¹/~Ä)‹D*Žâç‹ð¨T|J³´jæj%‚o1>±éK·¡C8ˆ´ã5JŠJ;ßU-«$3’6Ö;^yš«%¬AåLŒvKôX•ÈýR5;bl}{ XµsáZ¥¬m×Q˜1.ÈŒÂò¶Ù´‡ú<_i‘€°.ÄGíï¡8rEª´¬˜Z$…8BÔKÑv]õX;n{ß9:Æ»£t `¶ýžxœù3ív¾í´Ä¬Šì4ehzÿÆ}J¥i ÙÓx$d;jªm[×-¦ð©{ òj9[%Ež¬®Z%«¨h8—fˆâ³"1ÒÌ B±é¿¡mT&çσÿŸm]Ù1­QV‘lt^>Æõft5ML.'2jÑ×2=ˆ|…é9Ùºw˜”×mšA!]&dnÛù'27²ªÍ™Rd’eº¼vò½OÓ‡WóøvßÝ~´áÝ7Éá¨ikwî]úòæ©q…ÆÕÿ0þdOÏŒ?Ÿthã¤XB$2O$£Äz飯³W{ç÷Xhéd¢Èæ“û0'JYbt®ve@¤@fUdÇ®Ê]ŸŒEŸtÁtŒ@ãÊ  ´5έ÷_š 7έÉóɈ™|=F®%ÂC'Oûjª6^fŒ¤ª°¿¶à|°æ`sôí£}¬ê*\–¬Œïª&àqaÌõ¤2zºó`&ˆÁU»}ä/ú®@î ʱᓆèŸ}”uQÄ‚ Ï»£wk&†”-]9ûêÕ<M´s&Eq¯¬l¸@1¹ˆwFŠ_÷àÄB4_ž­uPß7÷¸2¢ ̹ôhÅ^ZŠ/mÛA?v Pò ÂÇ ÷(ÄžXF,‡ÝØ öàà/>#/ß… ¢:ƒD!Ø÷´)mËØ:ôþµù¹ÁöÔø¤s6‘3LÏYGêx°Ñ6Øk»ÞÇ-y¢P«Ã2ò-‘îÜw`Ç,_@‰»¿U‘ËÚw4rpßv¹ì› 6‚\=U¾mì¶­i m€»Ž•iäµxôÎò„s3„8ÈIšã±ý/óD†UÉ@#†=à°½.¯/œMJ8ßÇÇMQ€l[ˆnºìMâ;Ñõ—Ò1hþÁ¨¦¨2¤©´E×n>p/þò–‰Îõ ò5Y¯ºÛ2î/{Xè> endobj 1043 0 obj << /D [1041 0 R /XYZ 90 720 null] >> endobj 1044 0 obj << /D [1041 0 R /XYZ 90 720 null] >> endobj 1040 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1047 0 obj << /Length 1943 /Filter /FlateDecode >> stream xÚÍ]ã¶ñ}…ß"5-R”(mÉC¢ûvw@¹µVŽ(ížóë;äP²èÒ·×Åkr4œïÎîbø£»"Þ‰$!Ïwe÷;èËu« 6~|8þœÒIt÷XoI¿”å$™%Æ2º²lcB‹bÇà—åìk|ãhHXºe›Ð]\3n1±^ËbAâÂéjÂÊ™$[\Â!, ¼Éœ|e+µFT,ã$|ñó‡µCJ_È1–‹“/š98™qpr ÆvüÏr‚ªÖ›¾lçJýà#R’Ð5.ßš¶*åX覧 ˆ3:H8$K×XîçîI H"íp=Ù¡ö†ÈÒœä¬XÈVò²ïÁayuó{"¤~šd7‚ªî<…¬|pØHÙÄåü „¡òvêØÙÿ.õ“ r*HÊVdiÐBìsJb¸#<Å *Ú¦Ñ!8#I¶’}Qê|4ñ{¬T«¦ wÂã0vÀ#H?a¤H׊øqgu”mûùø1¤#dy¾†D-[­ŽýЫÜÀ% ê磞Ÿ‚~†jßÚck ?”Æ×´ÓÓp>¾ØKLCªA ]3ã8ò ¯:^¯`_– jˆà‰RÝyTú\c-7ô¦SÈ׈Å'"¾Y‡¥"ß  mWªnzõ¾{m9k=sQ=õˆrŸxJ‰È¿‰6bz2CoÐÏïËü/ÚÕ÷PÀ®u°€ J2.|å¡ÖÁûÿ,¡œ«f V./Qþ7f4Äþ}×Ôª•g¡`ú@º‰µBtM¼Ö¶\«/g¸Fe 7c0*½"u®ÃòÄ­›öMßáˆý^“êÁ FÄ5í¾CbÛð‡íZ”c&$P%Z'+âËQ–øšj°úêk²†óWßß“-¿Êf;~6¾=·òÒ‡—²v½ `c­=ïiÔ™ÅÓzm«ˆ§ÍBD/e§¥øé“jÛkEÔ<­7Úàˆ/wª¥†Ï€7¯šúÒ(k7ÌÚ%æ³…ƒ_|~5¾ç€‘˜|±¥±»ìFA>ÐÑÞ÷†È„×`/qi7+pl<•0²Úú 0äK­·™{±5Î ´Ë‡Ú> endobj 1048 0 obj << /D [1046 0 R /XYZ 90 720 null] >> endobj 339 0 obj << /D [1046 0 R /XYZ 90 720 null] >> endobj 1045 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F53 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1052 0 obj << /Length 3068 /Filter /FlateDecode >> stream xÚÝYÝã¶¿¿bß"kHQ_(®@¯hÐA4 ô! P­MÛÂÉÒB’ïnï¯ï|‰¢¼tvóZ,°&©Ñp8œßŒÔ]ê®JîŠ4+SÞíÎïYýôNÉh [âãû÷ßgêN%q•Têîáà³xØßý)Sn¶º„µèoÛ›În¶ij¢ÏÓh°;Øng7¿=üóÝßÜf™Ö¯Hƒ¯ˆ£Lçwyib•–èy£Ë¨¿àîEôe£‹¨îpiâ•©çßËhyPóϯ‰2íd‡5ո٪ȶv7¿}²¹ïqV®÷Oý¥ÝËØNLñ_<>H¯}éuQÄÚpZ’ü©ž@€îß„vuÒLÅ™ÉfÒïdcÛÎÇ@ÉൻmªË¸¨@s*UÆäþáÒèKÓ¶|I]?ñÒh-PWœ‡&rHy"¤uÛÆ¡Ãl3¼Š­*c£ok¿îÚËÞ~`ò¼ðÉM—ªœÏ"íwõ°\©¸(çóç‡S#bí{´¿ˆ¥„mTć2xùp+Ã'&<ô/˦ѩ?Ëhß pÅÍg|Áþ™ÉÄ@Ò…þØöµh®9vý ëm3N/öhÆ·j‰Y…•”ÄIõ&1,øWþÿ¤!Øú2Œo±£îr~´Ãû¦;ü1KÒøÀëiנݣ³àêdÛVv.Àé tw²pn¡êå—Š^ëùWDçICÎ5?/´á.µ‹¡fÂËKq'ÞlMª¢ÂR<SU±A/ÝÈóš‚>]k†¬ °n`°Ä}xï‘Ùã®é޼vú3g›¢ŒU’†Žœ¾ð¨½ŸU:0?R\ýl_€ÌŒI–HHã¼Ê1ûƒ è¡fª­G ×ÌHÈŸ1œõ‹ð¡Š5ßë/ÿ&—…g¿ÝóÓ§ú(ªÊkAÑqwèI@23Õ+‚^3#AÃA2Í„£'AÎ`ŒÔ‡³Áìëç1dV©MÕLõ@—˜%>SìY¸ÀÓ9`ày¬íkÌÏ#¯öi°£å 7z/'ѹéš3®_Î"ŠY \ÅyéÐN½Ûsúgǰìh~Ž~jÎ"¹q[?m”@¹=¯³Øg(XpðIç:.ÍKô„a,›±Ž„OösÈp±C"£*¢:¦é%] λ{žÕüs{›ÂmPt²òZs߉OõÈNB‹ˆV¨w;PŸÝ‡ÂæeÖk¶Ê˜9ØD±XŽ\o((eqšU×”aã­àv³«ß6ݧ1h½`—ižÎœÇ©z? õg iõýÔ쟃Ҥ±N‹õÿÕg‚˜ÌÊÜOæ0ó0NYƒ¸nÇŰ%¥ï’Ó7<òÂè|ç.šâó/§f‡ô'žÖƒlÅ1±ft™°:s}døý2!ŽÏg|÷ì[à ‘8eµP()ãÚR(´$2üϨ®QÃv–‡h>þ£=ýB~“ù¯I–`ì/Bx%8Hr}Áð(6¹eÛ6ÆL\.Üìúóó+aÒ´Z__+¥e™ #7È¥xþŒ:›«¯3[OŽ cƒ¹DâÜ=sX•t¥¤B¥ˆ”è% ŽLÝŽ´R¤9×ÒWY\ébaÈbº†¸€é¡oÛþËXŸæBÄ¢öBÅ×Nó°)!rm0,zéüðÌ+<æ”ÉSw!ô–À8`dƒ N *gÚ‰v¨Û°RR›%2…µ¡€UYú‘ãõ;#8« XLv»¾}wBÎYeX¹Ö }‚ÀeI„¼‘3?ÁòÓЇ:˜UZ@M¿äÃöKMI61Qf34§BG+áBså!EÞwU2drC Á£¸.ÞpíÊÄEj^õlÄþŽg¯;7â–hà…æø‹K4ËAcuÇ« ¬‰Ñ;Lvv˜êFžÔ„ëFžP¥7Åù‘Z¢Éõæ¡Ü8«%UÉÊ$ 2¨ŸÎë¹Dæ•æOÈ(Vç«?V' Q¶³“Ûþ&³{ÕRc8Xs¢ø¹é/Cè<®1Xb$f¥$rçÄšç4÷{¼èš^…®ÃV=_½Tøw6v2dP~{è±ÿïÝ,“Ôù8#„[`›Ò%BþodX·Tòâ̺ꉮˆ³p·N¥y\æNœí7Z f¢ß1;§Üš-—=‹ƒ8)óº7a¿îìeÝBÂŽ8 à¨‘•%çÁÄáRœŒÎš\«r‰ÃÌÅžy4Ô Qe¿ŽGÜÔÜTnITP¿ÿt–.\%’— é.^ŸËÔÛ±"ûYQã®Ã(‘ÒųE(Œ8è9…ÃÀíWÌ`Q(Ȭ5:ê±£Óm°ýŒ„O@EZÑ~¿ &¨Lþ€“/cnmê’Ÿœ^G6<7ÇÓËØâªÔùn…ìzÚ†©k,‹-ß3l|ŒCÙ½Ârk6Ye>½n×÷!6yœ/U°ùø–FÙ >¹ÇšŒ65ÒU{̃ic=®ÇåtÀ¯K—…kí›±~lÃí8ü(¯V½³—Ÿg* ¢æÁ¼éùé-°j‡©üý™þ×”ÖCú+ã*7/þؼòñˆæ"ÇhM1œWþÀ/u~há$´šŸnÑü݇ÂÀàj@f͈¹ççz/O¸7j k@½åERÐàæ ø2¿B úЉøm"½ìJµ¼ÈŸ?„Î"Cìo“𥡠KTHè¹t>m=ò×yš Ôr:Y°‰ž«,á>Øšò&$”¿Îßÿs€× endstream endobj 1051 0 obj << /Type /Page /Contents 1052 0 R /Resources 1050 0 R /MediaBox [0 0 612 792] /Parent 1029 0 R /Annots [ 1049 0 R ] >> endobj 1049 0 obj << /Type /Annot /Border [0 0 0] /Rect [277.055 520.969 442.752 531.878] /Subtype /Link /A << /S /GoTo /D (Recursion) >> >> endobj 1053 0 obj << /D [1051 0 R /XYZ 90 720 null] >> endobj 1050 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F67 34 0 R /F54 28 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1056 0 obj << /Length 2369 /Filter /FlateDecode >> stream xÚËnÛÊuŸ¯Ð…é ¢9/ŠLáE{Û¢¹‹‹¢õ¦è-†Ù„ùP9T|ÝE¿½ç5¥0ˆá…Μ93çýZm2øS›2ÛìŒIK[lêî]&ØçwJ -l|xw÷§6*KˬT›‡ÃòЇýæ_ÉOOÕqòãíÖ“Ø·[k]òÓ¡zôý­.’‰7Fð£ïk»ÕΔE¢lyûßýùafî´þtHññ”Ý¥ù&/lªŒe ë¡;Vc†˜—.ù‚r½2Ü ð[$ûæ×LÙºššH45gè×Ìe©(X(FŸ‚Bú$”m¦ëÓóf=°=Ä,rv8œÉÀ æV™T9–…já¼q6yÁcUàE‹§ªôûôvë²]òð$t5óF´®:ÏÎe#‡§HÊòg’ó™y“äÝåý€è2põÒÇ;‡ñBlÅrɨ~ìšÀ¢ÈW+ÒÕèLXbV/È B„W5®fý¬Í’_†ÉÇãÕ$öü»oF_OÃØx’R›döæp´j‰MEÖ$¯î6+’À*få"|ève’ÐP ã&ëä_oIãWFWõÄhÒaª¦›æV%ý£P´à—ÀD•HŠè^ØwÕ3Ý"Ÿ&¬È2´1Í:_õMÿØúR$‡ìÐËìØ:ÌŽ­Ú¥ÆÈ`¼¶éŸÃ=Óç»%½S©³˜é³÷Ç»©Ù¿Þí} q%.ò/O3ç.múðDö/r0’ËAó“çeD‹ÑšþÝûºÙ ÕË“+¼¨¾lú¸Õ´m<@Lêij § /9.‡f®LÌr%!E¨$Á ¶öþPZ A¹¨,9Ð ë¿ìCl¼$„PxŽWÇØ6ÛÂ.içC+žniáf×Lcõ•õ^ñÉ6/Cg8r±³Wü /ÍÄöB‡ fèA)t6<¢ÙðõÃÄÆ…œù7úá–bÿYø°[vè[˜oÜB×ýÈ-h&©–„kTª £H—ICM'ƒn[®W`ËŽ!á5ÌxÂé Ȳ›ù¼Þ‚xä%ÃËo­ïb¿[›ø”»ïúÒ¤NåÑ•cÜWýhŠ4/w‘ŽÂå&Oþ‰‚'fÓ{Ê'€¾°e§'á/rPqrË«˜/ ‚… 2TÇ#ÙÆW#ÕèÄ:ÕÊ\D‡²¶e e»Äsqìy{ÅаM¾{S8;›j7“¢3ðÚà±÷Zv* 0ž¼PË8²K„†ã©(~%Á²ƒNDëðJMD,ØBÀý,ª þÐöÊÕÜ •TÔÌ ðõ=;5Ï!sâ©ÅÜK(Û#¯>ýé÷‘œk§´6Ä ü{gk³ºˆD¡«:2š¦ŠrýRi%fl)¹As(HTàS± u¯kÁ$È—±¡BȪ®¡1\§vÏûFúäÄ[¬6l,ÕÎ-kƒh°×þœÆ™‰ÑÔUåø÷¦¦ð&ß}xcä¤[í6K³ò˜'w¨Úà襁½Ãz±¡p3 .ÌùË0vpÝ­ŠeS%F#Ø·åG ÐÌ- á«v”%Ÿ¼#‘P,è3N’‚ÈþýŒ Üð&X¯_óüY8½+cªB¸¢ðz•fù)Pç¢AGÏÝ—ÎŒ±úÙ¥±´ÒiYDûî8½®ÙT©5sÖ£tVí·xâR)*@ «­J­Ú] ç?4NtÏ‹i8û .ê s&ÃýÀDD8Ä-/ÄL×=bÀï¸öÁòÔ·”7‚“ŒBä`|˜xÒ´ˆ…eà ³Öd(t¡çH Ù ‹f*!ág •ðEНÒw¬d*TjŠÙq~\ó™ui¡f×b1.57ë!ŠQM -zDqxµŒ# ½صz—êÌ­´Ý¢L8B¤Ö^E"âYž}‡‹ÑwÑ,€Ã‡H®'^QÎ%¸Lâ/'n ßÏPn"5ª& ápì^VêØy¡Ù^¤42s!ê,.=±/ÄýÀ´CßÊyf{QGÞø>ð¨?®Œ5¼&CÛ„é‘æi›h-M™ß}C×UŒ¦)2ÓÉžL@ïÙ‰&Ó C$Èv¤D Жô0G„˜.e ÎîØúxGsàߪ—ðÀSò*]ɰ®’鸡WœÁ\ä‡pWoMߨɃÕÐgý(Ï3ãd¼« ~ÛCv¬ BH)æÿÛ¢ïóçSÎS» ˆÃ8à\f C¨}¿gUÊ‹‰VóÓ`î¤2ßÄó ŽP÷)ã8 ÜBÕ­5hP§©%j«-Ãx™•—ÔêM|;árŸÆ&¾xÁ¾O2ŽZæîÊt8ËSZò5í@ÃìðÌËjº`co‡ÙÙþ·ªƒAÿ#»Â¨M‘–yn)¾ ¼¯µN3R}àAD´eS¥!ü5¸NkÞýCÛþâò~ü “ÔG!,ÒÂÄÜÓ@_’rxJ(Ý×Z^¹Kþ~ßô| 9œ î³ÙØYjóïßðþ‚¸:¿{ãùß½_?o2™ŒYƒBô­ú×%eónêŽwp¥Ê2äqÿ5Ëõ¤*Þ¯Ö代ÒÁÙ4vG¢iò[ËÈA?ÕgÅ0…Ôÿç-È\–ŒpìêŠožÖ6O‹ F íÒ]&?õ<(H“µ”M#}¬„uC<\B쌓œwÉã8œŽkÅBg*ÍEà2¨Öä-LªÏ½Æu¬¨2â0Óï»8éãz9@¡L«ã;@:pY¦E~Õ9vŒ5WM­äù3ç—5òÅ €ÏèÆ†e˜ — íÞ Ô¢ž¡ÿz,ÄG>îñ‡ZÄà'µµG·*S{n_¾«êõG·NÍn&û"o¦ÓqE¼Ïk|r½|´Cæ­µG˜KÝìÅ›±ž¹´4åEé\eaÒÌÄÚßc0,º‘Ò*–¤ê[I= çA —hN­yZØ@î8”Ç¥ÚšE‡r»ø,‹ùC_à5»ÖPJ9À¦”n&ÆÅì.†6X†i”B|y0íëjÜóeR¦hÊ96¸,Ù´´Wïu¹ë¢Á@ sƒá/²±q˜«6ÿe@£Ö᪇Ðãw¸ïú\{jÃü]IþòHÚ±• endstream endobj 1055 0 obj << /Type /Page /Contents 1056 0 R /Resources 1054 0 R /MediaBox [0 0 612 792] /Parent 1058 0 R >> endobj 1057 0 obj << /D [1055 0 R /XYZ 90 720 null] >> endobj 1054 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F67 34 0 R /F54 28 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1061 0 obj << /Length 534 /Filter /FlateDecode >> stream xÚ…T=Û0 Ýó+¼UjŸdùsmÑ th;(2s6âÈ­´¸_ʤrÉtÈ Š|"ß#«DâO%L­ó®l{9HöžŠ­ ÙâKxù^©Dɼ“JúÓcŠ~H~ UÉ4+Zô‰¯'p¯“ƒ4Óº‹pj±Â VpÒ?ý÷þ^¬*ŠØÄt”,1Z&u[æJ—Äéç‹+)ì;%Ù ? l¹m°nŸÈ— 5L+X¿¬û<¥˜2cC1ô)ÉéÊ”ÎUE²üD4k~çFçzsyš•ºýˆ¥¢ûJ‚q|õ£ñ  )&G^k6ÎJja¬ì ’ñ£YN½÷->ä ÀC¶Øµ«g{4LäˆÓ`3Ý.U²HE*©'Ê‘0n7P!l8 oÎÓº\(| ½kÄùvÅ>Ôu‰}`ì>¡‰LöÇ…¥îUñ¸WE«sYHn'•ÇEÊ× ÃŸÖ°AµŽhf‰Ö÷z×ÙXª—dºªóBVÏâ÷¡4Šû×ÜW]q5ß(°«Qï[³ßÂt°UUS‚ï>‚†7#¼ÝúçâZä=†Lo„\—ð·‹ Ðbìæ D)f0Ç™yúå‰81y/ ´ ~ VC?ÿ«Ç'¶ endstream endobj 1060 0 obj << /Type /Page /Contents 1061 0 R /Resources 1059 0 R /MediaBox [0 0 612 792] /Parent 1058 0 R >> endobj 1062 0 obj << /D [1060 0 R /XYZ 90 720 null] >> endobj 1059 0 obj << /Font << /F51 5 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1065 0 obj << /Length 1484 /Filter /FlateDecode >> stream xÚ­WKÜ6 ¾ï¯ð¡ÑX/?È¡  =(²‡IZ[ÎñcâÇnæß—å{ÖiŠ¢X`G")’âë“yÁ²(H¤d™Jƒ¼¹‹<õë÷«=ì¿=ÜÞjðˆeQƃ‡r©â¡>†oŽæ4Ú~·—R†ê~·WJ‡oJóŶ;‘†#1z[ÚÞ¶¹Ýí…–YrÍwŸþ¸ûýáb\ ñïPâ…{‰¸bRÅ»§Šq©È=ÅT´ÛëX„SÛtS»“|Ë·÷‚‹óŒqá¯õpWUz9FWAB9µùXu-îø’=¿íÚ}o¿MUo ¢|ЏªípFÛx!Ót¾·ÍnÏÃ5<á?ë%ÆÙs:õ;8õ•-ºî|•ŒkrÕº?S¨Ë¾kp¥H’–x–y¬A©¥Ý§HG>&b®KDöœ¡ƒóC9ÀÙ­Æn9Ëv¾"0O;­CS{?ÁgX&Š‚Œ gâ™ïtª<½jNèç™ r.‚Œe±ˆÑà^pÍbC0"ù`ÀUå\Xß.•“i–%i+Á"„Òùø9 àA0Ôcðì$›@‰˜)çêàýÝ_Tbk»Z¤L&1hã,â‹ÝhÃnÄx–:âL§âŸì‚´„ZÍâ¥]ɃÌÆÊU¶d2M‚ª4–Y¥êï)N’Îø±Æ JBç]un¨„ÚŠ.µUV—}©k/SChV—)lmG[Týk_r©;aQ"gåc?Ù­ÅL_j»4õ`·lÇ‚#)ñÒ´ë„-ãJ(Mþ…ñˆÿÜ|"X–¦Þ¼{Ùõ¹}½¡*S¨Õµþ ¸‘¼FþG–¡M“ÃUiksl±e|ó¦j·Jmï¥Vjí÷LKSŽl)^ÇsV¼î4lJèÿÜjëQ03¤¾Nñé‚’Z«ÿiªÜÚå[³v¯$IïyS![bÏ+ Hx ƒ·tIÂgÚžqÝM´;:mwdNal›¾ªÏı-qЇªHzÎæcןiû\Á ˜f‘|œÀ¢gº²Uí¢Tã Áæ‚&ÌJcÀ,K°¾-älY8âey׸·PÊ>ô,|µUþ˜-ÅggaјU«Öܹ-¨äÑe¾£Ž…ÚÃŽH3èÓaiÍ8õ–Î xC×MuAüçëõ¯´soYøýõÝZø§ê+/ÏNI¢$Õàð`·n´¸€ÊUíÑö«o‚“ÓTW0tÆŠ$¥³‡¿ãü:„¾mˆ„vW¬Û—­œG„¯ÐL)p,†)àgä{È ^ ¦¢ËO‘|Ê“pùäúíH.f ih»‰@uñ²¯¾$Ìl¶½¬Œ·î…Òpè&? ÀçÙ÷EP¯F Ã!ç‰sÎ¥sã\’amMA$7Þ’wm9 0$ý¡?¡h0¹:D'Ñ+,Àf=ŽPÃ©ï ¬tyøš£>„ZNw8hˆ ŒÅ—ß+Ëh‚"ŽèãE(øœœ.\º°àâ¢ÍCT5§™i¡ÄUzC{o€ÛÏZ1L+ý”‘«² kýå¶UæÕ8غ|µ¬ÛÅg×êÓQº<4 ›Ÿ©³õ endstream endobj 1064 0 obj << /Type /Page /Contents 1065 0 R /Resources 1063 0 R /MediaBox [0 0 612 792] /Parent 1058 0 R >> endobj 1066 0 obj << /D [1064 0 R /XYZ 90 720 null] >> endobj 1067 0 obj << /D [1064 0 R /XYZ 90 720 null] >> endobj 1063 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R /F53 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1070 0 obj << /Length 120 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h CS#M]#  ˜†sZj^zf^ª¦®±±‰F™ˆ6Ö(JMK-JÍKNÕŒ ñâr [fjd„Ý5Rç%” endstream endobj 1069 0 obj << /Type /Page /Contents 1070 0 R /Resources 1068 0 R /MediaBox [0 0 612 792] /Parent 1058 0 R >> endobj 1071 0 obj << /D [1069 0 R /XYZ 90 720 null] >> endobj 1068 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1074 0 obj << /Length 935 /Filter /FlateDecode >> stream xÚVMã6 ½Ï¯ðm`í±,ùkoÛE{è¡§ôPt TcËccb+°äÎäß—%'³ë Å"SE=’TX”ÁEMUœ§¨£vzȼöåy)ƒäÆâ§ãÃã/‹X–6YâcëâØEÆ_y¶j9$œó¸øtH„(â/½QË?)åì…¶_Ö™ÄEõjQs«IŽEÌ ~øëøëÃÏÇ L‘çÿ-¾ƒ[å«ÒœÂÃ-k‘2.nqHŠ2€‡„ÅòÀb„W''ˆWœîÛT@®ò"OkÐ:ßÇÂáuE~ó:viu'Õ¤Ñc]Æ£!] 0±‹>TGº'Ô\ÈN’êkÆÄÉ»me0-ã¿= üPÎ!ðR0‡§¥*¤pU¿‡¿¬Ó*/ƒõ‡ô”™¸‰âBå­uOWÛá&†G ÏŠ´i¢„ñ”…t ôçu‘vt±‹òŒðyuŸ€dKZuºzÒN»2¨‚—¶Wóó8«†ÖQ¾†M¬+X²ï®÷¹„…6Q×ÄO«¥ƒ2çÑzpvpÇ ßFdÆi<Ée´£2‰È`‰ˆ¹ˆå¢HeÔYb(©sÁ°S@g±4+|Ïüq¨y¬W¼ Ø&=ôÕ¨½¢–,-Ó¾JÏ‹^Ïf¯š¼–ó`‡dÞcKáÎ`4Ng½Ø»Î¶KGê¤íp[NCaXím%_HµžwìF"•·ö]@Ý2 VUlÉÒQ Ž»Ï:–±J¤90ö]Q¶ñâ|B! *¹XR´z¢ösƒÇèui·ú™µÅ+?ª }O£±†;ÖƒŠ¿¦¿iGh ;H$¯jOÒ—X¸lÞîîö2ã%” ùÁ^&Ç[¿ÜiúÎ:€ƒÖ"é‚Ùwt¼‹Ùe¾ƒ6þøë0¶xn Òä¬Iëì› 0ÈkqáaÈòX¶zC2Ö ¿=œV…n\TkõB­&˜oU‘±škÀÑŠfWn¹Æ‚Æ/Fé,ý„uWY«ˆŒnB\!±{ýлv´ëÈÉÅ¿qÀ5ØòF¯ƒš·9AÂVdª§Ì £ºûÜú¼Ú!@mÃ@«ÿ–4¾¦ \†RA¢vïPMö–ëÎLÔ,'… ϰ ^|ép“"a—®<¯RÆê@ÀGeÛGõ†ãÅü?º‚cŸÇ'ÆU]¿Ïhâ‰Xü}ß|#_ŒU4¨ûr é~÷ˆÁºw¹àb¯ ÜDls ‡Ç™žó)ü=ùúøbY endstream endobj 1073 0 obj << /Type /Page /Contents 1074 0 R /Resources 1072 0 R /MediaBox [0 0 612 792] /Parent 1058 0 R >> endobj 1075 0 obj << /D [1073 0 R /XYZ 90 720 null] >> endobj 1076 0 obj << /D [1073 0 R /XYZ 90 720 null] >> endobj 1072 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1079 0 obj << /Length 1096 /Filter /FlateDecode >> stream xÚµWMsÛ6½ûWpÒ‹| „3“C,Û­Ó¦ÓŒÕ^’t8& $ëh¦?¾Ë/™”àˆrÜÑj¹ïíÛÅbA ?âØñC'(?ÃýÛû3Ò?¹`àŽ,.ÖgËkN‚Q€⬓±‹uì|\î»T»Å*QÅ]Z¨s—1oñmV¶0*QF‘:ÿ¼~wvµÞqJ°i,èB‚ŠaÈ÷YGç&lú{ç)à(ðek€%¸úø;1ü÷ÎÁˆÒyh-sÇ£y´ù.snÏ>Ø 9•ˆùâ[p1"Aàxaþ=TìᣠàcTF  Âkã”ÃßBD<ÑaFº¨ŒÎ^7¸ËkáÍ‘G<Ç¥7а³Î²Teg<ñÝ, ÑÚ½ný9.ለÞéþŠu¦Å9ä…/ÞtË'̱ŸäK2¸¼üýÖí¾u‹0W ¾@Œ{ƒ=8%= К0¾Ibêb¥ó<,âC2íÓ+ 'é!ŸÑ£ŒLº©–Iš©§8$<°µƒ ç. ÅOÝ›µ®TuŠ<Ý ÂroÀº3ºÞ”ÇæÊžôÏñp`'i‘v›ù‚kJÓ|£M5é&‰^—Jwk÷ýL°0ÎSÀj?ü·[î`«Ï…?y€{}ôh)5Ó’«§0úTÚl[_É^xH³8 M\.‡ê³jÎàådJ"†ãøÿº4Œc&/3=%f¸ì¹ÛFëê…t:ÎÄxgiYÝÁª;$lŒP\Nv£.ï„Íõ‘ÃTó¼KáÁíò éã%”>yùe0.‚/s÷ÝC%ê TÀ endstream endobj 1078 0 obj << /Type /Page /Contents 1079 0 R /Resources 1077 0 R /MediaBox [0 0 612 792] /Parent 1058 0 R >> endobj 1080 0 obj << /D [1078 0 R /XYZ 90 720 null] >> endobj 1077 0 obj << /Font << /F51 5 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1083 0 obj << /Length 1632 /Filter /FlateDecode >> stream xÚÅXKsÛ6¾ûWhÒ¨™Æ‹/urHz&=t2©oM Eœð¡TÿûîbAZ”i+“C›‡ ,»»óƒ¿|•³U*e”«lU4WÌK¿\qß A!<Ñøõîêú6æ+΢œå|u·;5qW®þ nöú0˜~J)ƒx³•Šƒ›5ý×’„ºõb×[jöfgzÓf 0¬Çë¿ï~¿úín q-j\€Ë™‚QµJ2q©ó{¬‡ªó`º~Uðu'î+½­¥¡ÊÒ®ën-²à˜ò5îqÄ}}+ù*‹ò$QΫŒ²8Y…"ãä´èÚ¡ïj§¾Ê#ÅÕ* *ñãêjXÚâà }>±˜QëÕìr¹…}g‡º²Ï]ÿS_œõåsŽÈOYõvòÁÁþ©“mÕRË 5êj{øV[ó èë£íÏ&‡>xvÀYøéGÿŒpœ1G—M5Ð>qÈÏÐþŒè2"ºv=ŒˆÃò8IcÜ÷yfbräi ¶“HæÞvoì±Æäk_Ê-ø¦cn}ÐÃ~ó°ëi$iÿpÞ°)‚³U‘…·´æy\Ìê÷]7¼¡­YŠ×9¸)1¾ÿÏÑA¶þ¡û®ì¸ÛÊŒOŒ«Ú5¯XH3{Êe@ºÓ 2É­)FâS̬‹ÂØ)ëv]ß8zŒY*pÙR%Â!ãĨ¡È"‘úú‹Ý‚áJ>:„Z(üQ0Y’ƒE¢%,»$Êò|²1Zyÿ&ë²ì tzÝ~^^ÒI%½Ãò”.lŒËÃ6äN£‚šˆMØ}¤xO÷¯ñ<“ŽYi؃ SºÍ¡Ž=P¯¨p—LIÒÊ«jú8ÿÇúÉ= àþáš”aäÁ{«ˆ`œ;±¨Œxì³Ã·vè«ö³Åã‰ÁNú)"q }Ljbg\ ¶KÓv¢ÅÎÖ9¦6F‘b.Nc.`ëò8Îù«¥}‰£TLá’ »–¼hˆOM{‡ëç®_b×Èji­7ïß}¤ÖòM­­­§µC’@„ñæâ¨A¨8I6軮ѕ¿$|ìŽÄ–¼`ñ´kØ­Á׉»õÜ®3åá°ù¦›Cmê†ü¤ä…ƒ@æQ*—ŽÆqh‡]‹—UÂJˆ…B,i Æø&eÌý—‘³Hw»ÍÎh±Q©d¡JsöC3¯µHaÓI…vRš’¥™û=BQ냉%«`€ð:%²°u{jîºùMŒ¤c¾b[“a·½O+,‡J,«B®ˆ'$è$‡¡Ñö‹CAù5jGˆ#¿Ó4Y.fî‹™‹`[9vÉý¾*PoO]ÝÒ(º¦AVFáÐùAú|î»ã´Èwtd!é’4 þ@²®ë‡u&ƒ×#ØÊÒ„Ê»Vnø]¸f–hdÆ_jJä–Ö Î¾ ¶Ç¤{Cøj¼ÄVôÔîͨÆPApåãÏ„MúeÊ)l2Øõ]C­ivmvÞ'Å4¥˜JÓÓeѪp-ߌ?îvc‘Â1GÛ•ý‹? ëz|¢`ñéZƒ;8{ßWuYè¾´ž¦ú1O½çµ9Ÿoþ9Vôì¨} 6/2{B —IC]P E¬–ŽçÜ Pgá7™Doq}R÷7”[P¹öv«·êò}çrTflöê"ÉôØrîî2 ¦§ ¶Ü%'ÍÇ 2=tMCtsÈag-Öòo3‡1ÑÒÀû9?©ñLÉg5ŠZÅô–;°ßõÈ¥*c‚%“¹†I@ˆÙ-ÒžÛ´4Tt `C˜æ0Lì–Ó• åšúþf‚{hzs§3ö‹–Ÿ\TžVôAä¾~us¡+LÉó Ô¦q,.ñÒ2Î}Œõ} yöxyrj5,¢¤vÕ4¦¬€©‰Ü"‚ïuu;·°°G²Æ> endobj 1084 0 obj << /D [1082 0 R /XYZ 90 720 null] >> endobj 1085 0 obj << /D [1082 0 R /XYZ 90 451.468 null] >> endobj 1086 0 obj << /D [1082 0 R /XYZ 90 423.573 null] >> endobj 1087 0 obj << /D [1082 0 R /XYZ 90 209.467 null] >> endobj 1081 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1091 0 obj << /Length 2442 /Filter /FlateDecode >> stream xÚ½YKä¶¾ï¯äb5°-K¢ž‡v×6²6ña|Š„-±§‰‘ÄŽžüúÔ‹’¦G/rÉR±Š¬ÇGv|Á_|WEw…Ra•–wu÷.’ÑÇw±PG`8n8>Þ¿ûþ§,¾‹£°Šªøîþ¼qßÜý#ˆ³üpLJ >Mÿ`{s8*•¿%ت`0g3˜¾6‡ÞÿõÝ÷ËbY’ü6ÈñJ"¹‹U>¢N^¦a¬RV' ãPŽYžÇ8h[wPIðôen'{mÍ'×÷¦ž¬ëÇŸhç:ÔëÖJ؆¸s¥XêýÅŽ`MV²<ЃէÖðÈxqsÛ0]»þ”Á¤mÏ´vœxÀ¹ýü3·O¶mj=4"~rüÁÅ“ =]lB/"qu5šãOøÏˆ£í° ÆêÞ¸yDÛÈÆ`!3šqDûá‹*jZeÁt1<0šá79„‡c{÷Ñ涺À7¬ Œ÷nbÂ.Ò¬|"¦W¹çÎDób£9ÌN‡8pLÖ|F^¿ö™?sèCp¤ï÷Œ²¡uË(ACàƒ4So.½É íõd°›ºox|0ËzØE pÞ äKÇCfœàØíxáaÍMožxZö•ÔPâ28Î-‰Ù*Îz_û͎–F1yMW¬"p • g¦IÓ <ò1㽘(‡ß 4Û?ðˆ÷t~ñx1E`èxa†ö‰^”ùuëÆE ìo÷ɶnDÉ0³w"è ¼M*KƒtÒ-Q@‹®fñP‘a5 v0‹²Åï€ñóÏßÌUk{bC¹smuMŽp$ò“ ³² ûÉ‘ …Á‹ÆUÙ`žtëÀÐêëõw,¬a·%ÆÑ6¬ ÷k”E&|SRAàh÷`ü$6ÎWîO¨¥Æ¯âà¼Õ\äl#ºl>ÃŒDT-ºrZU0ÙÎÀò1­]øÜìk…÷5Ya’ CÚ ƒv¼´Ûôƒ‘L™l3e‡•ª€Ÿÿ´—L³°HJÏñeõE(õšŽ¹j4~z ¬i¾¯ºã©ñb œÙŽq•…‘úC Ï2ÇËJrLÒ2L“‰0Oʵž¤;õäðÝñ­Ê‘n+G¥’‘j ç"#3|Æž1vgM$¥L$(A»x=ÍÞV€-çšÔ–ÁŒ’ìÅ0ÝhÓQ¶Ê¡¢ýÍM~¥‹žöœB‡ò·Š)¡)YÂqŸÖ×>`€âlƒ®V€GžŸ-,MAób!’ækm®³Ÿ÷™iXÎÌr!éÖ<ÌiïyDßN¡Šž™Eól§ÑbÙãÑÖ™¤Ã_»6ëá`'¶ TPaŽiv] Hæ½ãÖ«‚%ªðÄÙ ~ûŒ|¢;>Eæò,û‚ {>¸~{> endobj 1092 0 obj << /D [1090 0 R /XYZ 90 720 null] >> endobj 1093 0 obj << /D [1090 0 R /XYZ 90 720 null] >> endobj 1094 0 obj << /D [1090 0 R /XYZ 90 575.186 null] >> endobj 1095 0 obj << /D [1090 0 R /XYZ 90 347.477 null] >> endobj 1096 0 obj << /D [1090 0 R /XYZ 90 303.094 null] >> endobj 1097 0 obj << /D [1090 0 R /XYZ 90 260.833 null] >> endobj 1098 0 obj << /D [1090 0 R /XYZ 90 179.119 null] >> endobj 1089 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1101 0 obj << /Length 2209 /Filter /FlateDecode >> stream xÚ•kã¶ñûý ýˆu’¨g€~h6w¸kŠ @÷[S \™¶ÕÕÃ!©Ýs}çEÙ¾uz XÃáœ÷ ™®ø¥«&YUJÅM^¯Úá]"Øçw©@ Ø\PüøøîýÇ"]¥IÜ$MºzÜ]nñ¸]ý3z8è£7v½QJEÅëMžÑÃÎû²e¤hwv´fg¬[³Þd°q¥Eµþ×ã_ß}x\˜)²ìÜ"Å·Ù-ëudüþ_ñÏOi4ò¬?ºA Î F?¹Ãaù‰Ñí4go¾ZÞ®³*:¬Óˆ6oqá³›ž|¡}¬›ÝÕªôâÐÝdÐüÙvîyó¤Ù¢Ö@›TÅiÁ2öÉ4=Ïǧ߬²Ì' Ô Pgy\å“q7ëMQf`!d¬ô0 ÚV_kϪâ2(ôñÐÛyRFÎÛnÜ3p$  –÷Ö#(a‹¸*z=të4¨†¨N¨‰iæÁ+ú-ûŽõÍkQ݈EóUi¾˜t/ ¬&oúS „ŧ3W,Yv)Yž¨X•9HH’±»ÞÐÀ&²ÒS!g•ÅëM]'Ñ/ú@^Õp˜ö5Òz@±gß¡Zü÷`ƒndR½Ývµ34SDzö‡Évÿ5BжÆ99abœgSÜ;ï…wÁ=rëí>~·Üδ¾›F»¨2p8VUÅ ªÀsor6(Rüš‰ŠÙͺDÊÃŪ8@ñè{ÞšT†ÊÓ=Ïž`uQDÿ¾qÔþZTu“ັíç-úëÛøe_ÁLEæ9 ˆáT1õpn×âlN9>»{ƒ,M8Ê~2ãZÁ¦?êíƪ €¿gwG¼}Þ!¥;«‹ˆ¿ [ãejºeå À,ØxÚín¥õB:Ëšâ@’9îýÚõ=C¤J< ‵N< vFèÛö!z™x=L΄9ÎV’©­áÝB¢®ÏŒð0YÔ )FWu àìÚ7§}ö·³à¡e’Їß;=÷ž¨D%,« ; …nÀ ã@åNΛA–ŠPˆ#Îo;†J%<]lO™2<•¤¢)”àÒCE0‘'ÏsIÀ茭–êz´†k +gà^ïc’iÇX*@@…ú÷ƒ¿óâý^ûï˜r 1@¿ÌRÈÊttþt$¡ ªî‰ô:$¦qä|â>®›<²ÓpGL|šz–Ê( ÊG(×Ä’?!ÀaBQíä(+lÆÃf`ÓwÎËz }Ä¿HBZÖ8HÁXóå ôù ¦_EgÀ«::²&/£¯­¥ÂìaÍHùrë€]:odÕkç -zÆê¿—zÎ*pþŽ/yxžçB ©ªÉó+…b¹T?Å>Þ€¨€gE†]ælai4`êI[ÛËÓ;Êaiþ9½\æÐ¯:l‰Ä{l©@°Jd—¥Å jÜ`YÜËÌR D¯Çòädÿ£‚þ@)Tœ ?ÓìC¯˜4Ë< >Þnö³4®Ó2´xŸwt¹¹a‘ÇE¥–k(bãŽzXöpÕ €¬Ÿ¬îÝÄÐ1wØfá¨ãMn6¨iUÅUUœ¯_¿+iž“60œÄ-äB3"ô&ˆ‚Üc ™ =ž\1k*(›ê:g-½Ó&ƒÌ¼§®ì‚WDì´e€•VÕ3î;òZ˜¢S½¶NP—}ºñ8ËÖÜZ SÜŒ©u<Ȧ|iBÒ%¡"~vFЩXl‚qn$ãNz6`Áôàed½"]úHiãøÕ¥± 6\±1¼ãâs3½¬SÒ~Ã,´«àöîPÈ9þFmÁþ/}Ñ®Ü[ÿ¡äÚ®øq†¾PÛ¿gМs 6Þ'Y1/>•*¥ðí¹Àw `nž|1ç|!BèÜ Ÿö{ŠÝ‹Óá¶è¯Úö”¬Ë"ov a4ñÛRÔmC‚Ú¸j7P¤Ÿ–‡êYàGµ½ \]k¨Bðv:hæÓ$ÝZîï =éñ %ÃÊÑÞk¾õÈÎ&F‰K@3öÀtmg®nø©°&¯‡¼!dêk?UÜ’€sIÉ‘7ÆpòrEÉ/``¾,¼ôPÙ¸rä%»“{„—Ëßq^–æüÛ¾]\ùö‡±µ§#ô„tÝÑ£Û{÷;@YÈ­¿Ì%×ÁÇ1Õ‰Û“Îtå ÂÖü6çyR2HNɳ,–ëmÍ™µ”·øî­”N@ùùÚ_b+C¥°Ò,NŒ‘zœ²J)òPú[nÐ.1Ρ¥–ÌBKžÿ–î endstream endobj 1100 0 obj << /Type /Page /Contents 1101 0 R /Resources 1099 0 R /MediaBox [0 0 612 792] /Parent 1088 0 R >> endobj 1102 0 obj << /D [1100 0 R /XYZ 90 720 null] >> endobj 1103 0 obj << /D [1100 0 R /XYZ 90 659.059 null] >> endobj 1104 0 obj << /D [1100 0 R /XYZ 90 577.226 null] >> endobj 1105 0 obj << /D [1100 0 R /XYZ 90 508.544 null] >> endobj 1106 0 obj << /D [1100 0 R /XYZ 90 409.465 null] >> endobj 1107 0 obj << /D [1100 0 R /XYZ 90 260.175 null] >> endobj 1108 0 obj << /D [1100 0 R /XYZ 90 190.887 null] >> endobj 1109 0 obj << /D [1100 0 R /XYZ 90 124.932 null] >> endobj 1099 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1112 0 obj << /Length 2583 /Filter /FlateDecode >> stream xÚ¥koä¶ñûý £ýP-p«ˆ¢žò!ñõk‘»b(š¥%î.k­¸ÕÃö¢¾ó’Vë“/i 9g†ó⬺‰àOÝ”ÑM®uX&ÅMu| ôá’Ѷ ŒîÞ|ó>U7* ˨T7w»%‰»úæoJ‹Í6.Üîl»w­ÝlµN‚Ç¿:èìÎv¶­ìæïwzóÇ»ù°4Ž…Äø‚<¾Q:Œ€a'+’Pé„ÙICªl³M³8øi³Uy¾õmk«Áù¶G^ «<Ì´fw×o¶‰Î×nâ<ìÞv xܤi`šÑò´·aa@ãŽn`ˆo4,ŽæÙ7qŒG^!âãFG܃óÀ"Ãr˜ßñ·ÂåƒkjžÖÆ™xÄ;ØO›L #áæéà*<é€Ò’x:T 3‰WízÛ=Ö|5O®iø²þ±óÝà rÓ×w5JŽÃÁ3ÚÁ´uc§{=úaÿk´ýЇÀA’‚^Û›' õÑ1½Ð&Zà?äë¹¾`à?ŽÃTe‹ûÍù~ï6%=ößí¹¿)“ óÇßpÅ?úžnNå ]ÑÔt–ù©±喝õ §ïÀV¢ðÒ{¼s•]6›qðG3¸Ê4ÍYð‘M[¿ËÚ1t¾ œÔý(°=SkýÀð‡Ö#‡Ok· æåðв$8÷c¦qú€{H³çM‘€j·©Îĸu¦á–õ$sÚ~µ÷ÜóŒî¾³‰âÄ>³]¦ÝÛZèßÎÖ8b]@œdAеfV2UeO€ÃÍü\ †SaŽQvxá6 8ø^v;ù.ÔŠxx¯~R¢Y¸û8 R´Bn‹»¯Ncp}ÖNÆ­PUÄyjCú¡óí~UÖŽiñTÆ'ØJjÌ`;ô¤8>ÍvhyÑðgº®8[j$CíypÏb[! ,±"*äk>¹á€#pKAûðYÐ뺳}ÿå,X—ó⨵tjw%Ë%'³w'šÕ†­Ÿ@m¤Åù’-ì3ø‘Ex —¦@QÛÆë8¹GŒó%*IìÐê¦Ë,KÐíÓ8Ô:Þâ0Oc‰¾… i¾%¾“0rˆ/)bY¿›ã ™V§Áwüù%J#©¸ue˜góšBÅÀð÷ ‡ç Y夨(L2õ¿öMœ,ÏS€´z^?Þ·vX‹¦Û4£Dßlu–ù2¦Sß)LL®ú'd ˜^ìWógr\u©–Á§uA­š‘B*‚)ÝÀ—C*Ž8 Çã ²S¡Çi#&ø ò(!hÅ´­Ø®óS9™ÇÖÜ”„ŒÕí[1×pO¹.¡»eúy èÌ5 öîqŽÆ’[‰CÄYp¨“…UëàÝ·Ÿ§DÌ«†§?|út'+›â<®Ÿ:?ˆ“ûæÿvÿݹ5h F¿f¦9”bQ¢× •ÅÂQ7iü¥EAäƒ-`’´?@ÎÔEº(`Š êŽÊŠr{†Ášk>ïÀ¤Èǧe$ºœ³l f`°ˆk§'‡`ÎGC(¡ôk…rÀKÜÂ}“»$W©ÊÙäEïÆUM¨‘ƒE–ä©99]bæ©j‡6C)‰ÄÁ…öR_¤Å ù栓ΞSMYM²Ä”‘5åP2æ§ë“¡ÎI+|¼ôM½Â&«tÁr^éî+PTo,Q¾FÔ/Õ”¥a\Ôô»5M"ƬHÎØHn.uV¨&“¯-ÃXO“MÄ 1dN1Ç1üîÁÚ)ÕS­”$Š VÈp®‘{P9¥‰OÿK¤´çœ‰hà’…iÞ°óû‡~Ökü¨PåU’F"+2«",bõ_kJ¿Œ|œ²ÙAÖȧ ±¼øê2›0øÝ‘¤â¸rF€Ô /Ž¥â‹â‡¶S5Íd\ÄâU¤š¯BKÍÇÌ7¨% Þ±(í‹-NvàѤìR‡1>[—¦¼dGi”†FÉ’^ú7É*LGÎ *™‚À¬éGWŽ`1%o4•Ì%4ïºWñ‘(l©ÙÕ_ ø¼üt%#Þ»¶†°Cæfgi˜$’S>òÃl•¢iœÌ>wõ¼@géì|töwÎyðúÑÜ›^P)ºáÀšþÌ£ÙöǹIÙØvÖÈ)à>Éóoe€f¦Y,N1k8á(á Â ŒL}t-x@GE=> áü¥ä…‚h 6`¶(Bh>‘eö`ÐY×ö<œH  ä…¾5Ôœª_}[5¢¤Š_:͹zA…eD§e¨[š/õ³þàdžvfXlÜ›{|ßâÊ¥æÇMS~˜êu@'ë„µÓØím!?I–’νzõøãjMï»7Íë(ÅST^UX0}Q,¤õüµbÁGxFÊE|)ï`(Âhìeï‡ÏÉÞ²ïÈëq‚®Îw ƒ½mm·]1´ËU§.I?rˆ…haúéù㥎¤RF“»Prévḭ̀ôÓ÷º•Òq.qh“P©¥­3=Šq< ÛH@”‹Y.º3I¨“,žº3Y˜Nè” ó”ŸæR>OålÔ–Àç×z>YGñL7TŒ§¢+D9[tÞß­”‚wõP‘FT+Ò‰â çת­ú¸•unâEø,:2,æö\¤&û@ÐvCæ.rG(â§ ¢\[B DÕ‚,9¡^%Ø`çH€¾7]Ý̈ÀÆ—pæÞ&ÜÞh©‰Óe=%ÚtSt5ˆSy>µˆmr,°Á©•àý¥àÆi'wà)¸F'+Ô¦„ï”{°P]¼˜pxêÜ£WžˆžV¼½õívq –Ý“d5O/¹äÞ«.¥÷Š®“@„Ž´Ž4ŒÒNô]e·‚ÔAëÝÑ5¦jž1gªßÿ̃¬Íé²¾]“Ä>K{«ˆ¦ÊœFSÀ”~.ñðÛzþRƒ•{DyIW‰Pß *Ž<—pÌo@‡@-d!wd¦k·;3ʬB\¥cˆ3Ùv)5©1•·fDn¾ýz9’ò¶_¼\pðîãÏÒsDP==à¢> endobj 1113 0 obj << /D [1111 0 R /XYZ 90 720 null] >> endobj 1114 0 obj << /D [1111 0 R /XYZ 90 720 null] >> endobj 1115 0 obj << /D [1111 0 R /XYZ 90 643.657 null] >> endobj 1116 0 obj << /D [1111 0 R /XYZ 90 498.431 null] >> endobj 1117 0 obj << /D [1111 0 R /XYZ 90 231.204 null] >> endobj 1118 0 obj << /D [1111 0 R /XYZ 90 203.338 null] >> endobj 1110 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F54 28 0 R /F52 20 0 R /F102 799 0 R /F53 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1121 0 obj << /Length 2545 /Filter /FlateDecode >> stream xÚ­Y[¯Û6~ϯpŸ"5Ûn-ú ²@E³E ,Ú«È´-Yr%9ûëwn’ìs”äløAäp8$çòÍ6+ ?³Êõ*uNå>[•ÇgZ¨÷ÏŒ´6À°¹âøÇݳÿŒÍÊh•ëܬîv×"ߣW‡â4„n½qÎEñë÷qôjׇîÖ‰E#r×nvaºÐ”a½± ØG&Î×ÞýëÙë»i3±µ_Ø-r|y»Iæ•qž·[õ°Ck£‚?Ð3Q(Ï]µ6Ѱ¶itá](†s¸S5ü-‹ž(.:Ý€SΑ«áÀ­ºÝSв }Ï“†–iÃA䢒Ö6‹P}$¥µg[oyʾ+äJ³( ŠØ§LÌÇ+¶Ûj¨Ú¦¨AÏÞDhãëÐcÇFïQÒ…ö,U5{¦máØ Œ‚›:V}²d´åÁ²Í¦õ—#Š|Oüm )y¤®šûž'T" àî'ê«¡í.LÞâº@G*ô.ëÌEßßÎðé‚Ú+t0ý‡ÁÖöÚÖÖ+ë-L"æÃñ$\7a-6G®çŠÚ8«¬Na¹DÁ‡†^âb0È¿6S‰J€`•V=>ÓÑ[òe¤N™°r”+¦8†-³L`‡ôj÷€±lO‚ïØ‘”Xˆ~­(\—{•èI1lŸ%•8¯\âG>Æ2íLåé­T* ¢Ù$"Õ¤yTŠô¨u:P…óŽU ÄàùÄpÝöA¨@Ô*w¡L¸G0ƒ¢Å_ƒ¬X¶GßqͺԂ2´!þPµÝ}%so%g4ïÞý̾YWï»@>óÑgÑÎÎèÖ›8±€¸ÄŠÜ V,¨X/øDAÙ6M8ÄhÇ>BnÏÍ3¼åèÁÏ/ ?Œ‰/GTÃ΢¦$HYuىȈ/øm»m‚~©ž8—ÖÅlOAØ´X ˜]?v H)ÒcÍ^¡(6uØÚ•´(9Ãw_1âRF –mùuàÎ5<1¾3/%9—­ðFÐ…B ùè?؆:…Å 7zð† î·°†céÝÏû%\Ú’7œw½±œp Ï[ÃÖÍÖ¸dêíƒ^œ±d‘Ld)–ô?n3´–L=³Mϼ瞳†1‚cØ‚p9D«¥£¼Æ…œÕ™D{ €%G¦2r÷Ì #åBɃ±£Ÿøó‡Ž5·LŽÕ…Vú¨B°JºÀiÁ¶“ÅÆ6Q±ãÅ00(·ìLAº”A)Ÿ ©ØG¦•ÇÖ™O>×J¿¼½{ýÝwëM/çóœ`>ÆR»„—£7¥«ú{nIéS¥8‰+rjCшH7lMƒV:ž ¶©(‡âŒm|¦Ð§î!|º.º† ¯2à,IœÍžŽý¡=Sa®ã«œÑÑ…ÙÊ¢#ï²ã\3•$ÚO$‚Ÿì ~püå\TÅ?#öôÌ1J*–üO2ÒÆ™8âùPums”pÁâòè Úî\äÀÉn € pîÐP ‡ )l@Å„û㡚¢œæüu®xMF ª½ŒÖRlÕÜ%”Aqמ@¸2eÈœ>±c†HU Î,Â]+3W’OU?ß1—Cø6&WÆfcdvù}hBG—&ñ ««§(yqäA:PÄ¥–&As|y;xßHg6Æ–<ÖÆØUbì5ÈûÂã†U”¤Ws@¥ylF•J¹ùŒñ¹ ›î›%I a3UouÛìÇÚ5Á p]ô½Á¶æ¶å-)¥«µƒ ¾R'·¦È5È2i¬™À ö“ÖGÎ8¿õ®»œ{¼cn¬ÌœÉ%ÕUx5^º®#³yJ¤˜x²—”OFk§cK¯–K¼À9KU'äJX©LÁ/¿YTû󔊈M†áꇓ¹ÃvL')­$“í s5"÷ߥ»DfzÂé¡b†Rð!NÐ{èC½£ÛsNׇ«Û¶åº1…dTsµ#WyÞ™*/L«Wl—xIÏL<Ó·üiÝV4¾“%·7wÙnû0>fa—ŸQòq<› D2&–›Öpl™ÇUNࢠÉÛª‡^Ê{…Kâ«U»ýyL€ýH’±¶ÛÃuùo~ZÁ7„¥¤ºkkP&¦êþ‡%dÆ'S~ñH6Y¦|š}£ Di6ÍžÉÆãó–ù&lâX%Síôÿ@rÝ’7"óXá9¸ðŸEgÈýÆN©stšÏKMJ|ú•b åCÿitÿJõ>BwãÐMâ' »ø0©ÿVŽô`Ý' »¤‚ŸùBAvuyz˜Ðá0ƒÆ©¶ÀÀ4yÎZ*¡bZ}RbÈ“lÊ÷ Ë帇Fý`kˆ(?â J>Í'vœMG"YÐac2¼Zå77I±PÐc€,F‚¬·tVªt~Q*wˆ‘ÃÒiÁÅÒ¹(Á‹"”§ç¢¦÷±¥E§\Ô->5ú†^w`¬j7Q’é[Å¿) ;n7e&zñz\~üçA׳Œ,z«‹Oøíܼ>]ðÜÏvKë'™JíÓÏħs•D2 \ù‹†¾“‘GçókœÍÙãÓ¦³V«d^¼Ž.™Î+=«Ùª2HšâªV¼}´¸ˆâ Ì]?¸¯ mœNoncÐ=â{È™žpt:_R†àòÞO$èt>¯£“út:¾A‹Š#øÊ‹Íh§!¼fÒ-ö~||ÒÙ²Äë·ĵÿŒ3 endstream endobj 1120 0 obj << /Type /Page /Contents 1121 0 R /Resources 1119 0 R /MediaBox [0 0 612 792] /Parent 1088 0 R >> endobj 1122 0 obj << /D [1120 0 R /XYZ 90 720 null] >> endobj 1123 0 obj << /D [1120 0 R /XYZ 90 591.363 null] >> endobj 1124 0 obj << /D [1120 0 R /XYZ 90 523.656 null] >> endobj 1125 0 obj << /D [1120 0 R /XYZ 90 347.067 null] >> endobj 1119 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F72 4 0 R /F102 799 0 R /F31 21 0 R /F112 68 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1128 0 obj << /Length 2665 /Filter /FlateDecode >> stream xÚ­YYÜ6~÷¯h`V¸ñе@^b$€÷!ñÂã§$ÀjÔìiÁ:Ú:<žüú­ƒ¤¤Ùã], ¸IªÈ*ÖñUGbø'E|È´…ÉUû*v«_I7:ÁqEñÓí«~IäAÆ¢ˆ y¸=¯¸=~dßUkÑ›³íîëÎÞµ6Ñg…¿:ìÙ¶«ìÍŸ·ÿ|õóm`–(õ‚4Hñ‚826ðÕÒÜ© Ët{Abýyµޢ L€Ñ?9ší±R˜Äxš¿óiewúƱ:*-±o¿zlòäØþ:Õ}7:ƒ½lnT•øß£ÿ8ŽskÛñÈ~±ÕÍQF󌦺»çÕj±ÌÛö“mor½†%GcÏŸ¦K9í]èXh¡’ìp”ZÈ„E~mÊÇÛºµ{·KŒÈTÐ@ B«BEöXj[Mõg¼ Š@ËÙ¡ç_GWô¤¨oº„*dtéÇÉ3Ú¡.›åqÌÁoý<]ç‰ÇO5H‡\zœ>Œž5_\eç»ÊåèÁ—òÊ’ÙŽµ k}Ç^NœÙÍQÁnJ-è`Éîy”…H³‚Ïý ÷U}סbèL˜Oh‚ó4œhXxi£×vEÚi²íu´œ £þn*kÏe°'P0ˆ?þFÞvGJaû¥ÂÙ¥ÄcïYAì•:>’ýábGÛ>t;V&2R¿gøåT&ªÝ2ÞF)¿›×ˆeF,­#ïÀy-z1ù·rwQ(êÏå‰ýrmꪞwPY‘çÛëä·‘a€ræq"Qãè×~h×Á ÆÛ«‘ÌQhT”Êà°{¡‘¡ŠÇÕy˜»½€ä’…ödס¿Ê–Á„Ífd¶°ŸÁÉy´ºhnÐß.¢?â$njÖd—~§ «Ç£­æÁ/¶i^ïÕA´q¼ìÂU&d®<kîhT.Š-*xG%iÝ s –-1Ù’dÇÕ²cÿytA%£úÌ¿ ÁùA[vÞguÀ"î‚M}ÂíßÇì\‹47<Þ~hÃq Ú¬]$"@é] ¦$†É›&ì ¼¾ÉƒÎ>ðÀÇÜ"Ñ™Weê“ÌææÄãE³07rË5x±«Êwb´eÒ¥2Xî; %bÚ Àzƒ.áèõ:ã|ò˜WÕ'/hÝß µx| öÎU°79 2±È´|’½è „a=»Ó ¼)ðÿm^Á40|¸ÔŒÉéÓ}ëöÚ<îÝänèËSUŽœ5MœBQàÚ“Æ%ÆcšêèÃ&=gÁEq5~  W-Û‘•ê—榜ÜÎç" Âðç$Õ<×vm .šY`ïz×ÙéyRÏ}OO!ô!Êp¯ÇVM!I@C.Xg’G¦å:?teëö/˜OÏDìP¾Àïä\´  ñ=Õ=*´¡;U‰ö)ÔûìŠÛW[,2‚J ™jÄ9’4¡T˜Üò|7ZÎ8Ê%!ß'+$"9¸n¦]ÎSªúÌe7.ÜÆÉªØœè»Q;MÂÙAL‚±q,;çT{ Wírì 4qYCFñ Ô;pŒé¦›ƒVI'^å;ØC~uåîïË$¾ŠÛ“ &eʨGGºaVV•Ç—Æ—¹s¨Ò"YÁós ÔrÙúµ'[*Á$f+?nBQ·'žÉ¨ôóÊoçlGº9»-¿T—º9í­„NÃH7·w˜#Ñ`MÝÖÓ. Þ²6" &ÞöqW¿îÆŽ ôýö‡sÙŒö{µsWw§©¯;(ZÏ€j{,²DhŒóö_¢<°9ã²#9*¥¶’KlŸeìw|Õ“îÙÔ@HÄÁBÿxÉ5®ý0Ã5¿gzÎ1´×jûATwU3Ÿì‘b¬'+…ýºêÊFpÑö»HÃÿå.%®CýÊÇM_ß3^ £;-[¶ …ð–dÉÿŠZ[¬,àDDT½À³ú*<#e ”ÿx~ÊWî%°£ÑLÍŽY¬«ªÌg© =êD÷0ù4W¦Zd!Š–ìþ!'Jnþƒ‡_!JÜ»8¹Ë·Ø> endobj 1129 0 obj << /D [1127 0 R /XYZ 90 720 null] >> endobj 1126 0 obj << /Font << /F51 5 0 R /F52 20 0 R /F112 68 0 R /F31 21 0 R /F67 34 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1132 0 obj << /Length 2237 /Filter /FlateDecode >> stream xÚXÝÛ¸Ï_a 'k(Q_ò»4hŠ"84ŠÃ]r%ÚÖ’ }ìÆÿ}狲´Ö6…D‡Ã™áüf†V›~j“›4Šü\g›¢~õé’Ñv3Ž_öï~þ« ü<ÈÕf˜‹Ø—›?¼_Oæ2Øn»‹¢È‹ßowZÇÞ¯‡ÞvÏ%M#ƒâÐ ;{°m »Ý… X{*QÛïÿþî¯ûI™8  -rü@]hXÕ›$Ó¾Š4ëüe€cóÔ«züf^U_`ym7˜f YZ^7e)„“åAÙÖ¦jv©-³0+r8¡JŸ­‰Bo¾ö2l•Wµp]ñ¸väÍ@Sª’z¶¨PÀUl–ÒS‘þ€>ÛìÛ¸S‘¯b6‘ Â{ ÓÌ;µýð€Ït–i`”E³Òœ•Ò|–I7½€^£^è}U͑يƒmޏ ÄDÅ6v¶n{¾n³È?'*÷>ã¸ÅhÌA㦇û,ÀK;$hRJ&áZ]¡-tÓQzOM‹³žµf2<}Bo˜Þ¢H@¿ +9JðG)ËM+«è`$¸[9€Š ÃšQì@ÔÁ :¢H{EÛàu£ÿÇÎ ©ôVÀ4œÌÀ#V –jS ˜x#PkïwòÌÈ|/|»ç’¹_ºj°Vþð=áÚ¹zBf뎪ú÷¨öÏŸ#µÉüЯD±À3ö5ìHBï3ÜÛË6R/ ÄT² ¾~ÜÂuìû54¡¦¹¯Âœå±p4‹ C|A •<þº¬*LüX"CAÅó=†F'—³ÚNèBZU ¶îa¨˜%á­žàÄðgj®ûN^,é0ˆ`lƒÔû6^¤Növ¥šÝžt½A¤þ`ss³]–¨õ‡ÁKµuÎ}é*®üƒHùòÛ®3Í‘f‘Ã8ÔÀ¯Š»cÐýŽNq¾ n·§nnù;²•åtè°Þ˜4 ó’Zµ8…TÑÖ<2ü),‹ï(1Ct‰U<ëL‘o‚ ÞŒ ³¦‹ ½4?¸‡»G×:â«^d7X†¼“ ^ÝŠqSv€=’ Æ­òv›éö__2-¶¯ÄÍ}÷-I$8ùe¤JÇ^J±G”)ÜprKE€Ñѱ|ð qñ ZñBVï@†ÄôîÑÙ÷,Æ(«Ðë*\`Á®Ox"ò¾Äˆ;ñðO¶‡†Ø5ú¤¾ÏÂt*¸C*;H/D,ÿ"xàÒt Ín®Ð‚tôS¹ÕS'Œd)N¸ÈÏ6Yà xèœTùñ" !–@,ŒTKq 7Ι0žgÂDAšÏÜã Á‘¬$Mû)¤da}GAžHùýx+Z¢Ã(_~È@̸Èé«ÇêL˜ºNòŽyX϶& Œãœ1Ž#ãž]ÊO²åe/qáS¨»½OfÅrz‹Ã+ãâ–`l{\9µ7 Ô7Û÷/ÀÆ.ƪm70½˜þc ýEßY¹'évx8êL·r$Ik‡“bàÝšhLçÊN Ou¶á¤=È.Ç]ÚƒÏÛmBC@ðÇîóùÏÄ¿ÙN²JÕ»——âà?k•>ç/z ¼ŽË$ôs茅ù'Thí}_ûPñÑ-FðD+¿íŽkŒ)°wüPxQöÕ±áÞîß ¨BçÉ^ûC7NE*UÃЩÒ*ÿç!S8gz/É€š¤O_«~åøõMjõ-1=go‰=•ލ;ol1Èlh¡–%:÷”$ÇhC™s£ £˜ÿ¸y2]ÉËSèc«œ(/\‘.%%.K ^p*À!Áö;`úÍ•g‡{Í5ÚÒ]G·ØëAO{Îíø–¿éSÒÃw|ÿÓM endstream endobj 1131 0 obj << /Type /Page /Contents 1132 0 R /Resources 1130 0 R /MediaBox [0 0 612 792] /Parent 1135 0 R >> endobj 1133 0 obj << /D [1131 0 R /XYZ 90 720 null] >> endobj 1134 0 obj << /D [1131 0 R /XYZ 90 373.599 null] >> endobj 1130 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F72 4 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1138 0 obj << /Length 120 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h C3#M]#  ˜†sZj^zf^ª¦®±±‰F™ˆ6Ö(JMK-JÍKNÕŒ ñâr [fjd„Ý5S9%• endstream endobj 1137 0 obj << /Type /Page /Contents 1138 0 R /Resources 1136 0 R /MediaBox [0 0 612 792] /Parent 1135 0 R >> endobj 1139 0 obj << /D [1137 0 R /XYZ 90 720 null] >> endobj 1136 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1142 0 obj << /Length 2427 /Filter /FlateDecode >> stream xÚ­YKÛȾûWL6‡¥“Ãæ›‚ÄY¬v’Ã9$Á¦E¶Df(RËÇÌ(¿>õjŠÒP¶7æ fuuwu=¿êQw>ü©»Ü¿KÃÐË£ì®8¼ñ…úøFÉÈwÁñ‡‡7÷bu§|/÷su÷°[nñPÞýÝù¡ÒÇÑô7 C'y·q£(v~Ø™S”LìÍÎô¦-ÌÆ â0 •„›>üéÍóÁq|E2äx%ZÜ©Ô T‰hIy*ŒX´dãÆIÂl\åXÒ" ’\ß”¤^ò6[Xû<÷úx„;d](‡Ž>Kßÿðc¿íZw×õõF9íþ-è;H,µ9tíb] ë`…žb§÷¦ÝÀv#3Õÿö“¬Úâä‰Çº,ëv/cþiêVä;ù­èvxz îH÷éYêndó}ÇÇê-"¸†Š@úÆðg·c>£ d«˜:œ†ÑÞ±öBu—yy’‚ÌËèÀP%| ÿ6ôÁAìüæ ?÷ÓÐß7]¡›ûa[·÷…õ!œt?¬Ù OÉâ~Ï÷S>í¡"ÍÅ©ƒ6¡i»i¢Ç «‡hÃÔ¡Uzd*ÛîY•@®›†é{32 ìáP*rÞ·Ö"0ßMãq0¤éõhJžš GYéþÝmß’y\SG—F’ƒAï[v9þÆ®§mÁuË´‰j‚¥j ü,O›Ý?éþÞ^ìž%Öªß ¨dÝ÷ž˜å^g¢çÄêYd:öݾׇ5)’ÄS²ÛY‹®…^¤–±³a:ø=ð¥5^Å"P èÄŸÏäq6ú(ž^iÙl¬Ä·w]ÓtÈúÌÑsÝq¬»vXól7½<ĹÅÝÜŠ=ƒßu+Ó1¨ç¸ó½(“ºå’³4Ûi“õiÉúdúm7˜WÌÂûó’·íÜáØèÓÍ?\qc²ºÉ¬–ÌdË›œû%'ìiö}7µåMþã’ÿ¨ûÁÀþÍéÖ?-Ù›Òmêm¯û¬+»æ›²&ó Î(¢¡!E¼Åd:õŽgNèÝ4³á e—AÊ•Ë ÊfÐFÆ«Ñ DŠÎ.;zE×îÖn’dÉ•"°—bŽS ¶â¤e&ëòP·õ0BAlP ‡~ä%é·¥sÐucs„Ý0 v‰”ÌÍi‰”\n×…=[ÀuǾkÞYƒCòÉ¡ÊÓÜpƒéŸ0¼åûÎoÏÀ#¯š¶žyчcc¼®?û øí¯ùg¨GãÏïyð\Õ…nòÓ`ÔÍ£,]Âù+ŽeÔ i%X©üý yTœÎ¡è<ÿêÍ0ð*”ŽçCVÂæG\ùY¿|‚<.‹–BÒ“t¡t(i8'àvÅ,¸}‹8¶#D¦F¬)kêöJì-7_Œª˜¦ÛRÜ%Ƚ8¯\º1æ8`H†`ýÝó×(@<à8'ÂdQt}©©SÇoÔ Ìðe"îM95óV’<šº8m@0TEÚ!±îþš—OXFê¯.ºVÉY,UD©I9¬-B"@;÷Ð`‚ôÃEe«ÐÔÆ2“îÍÕ²­ꂇóƒË]¤ô4ðüà\é°È‡E†õJ§ä_²"$QÊyß`2¦8²kEŒn'É=Š<„o¡Wî;«9N¦XCÓx‚ 'æ×Èœ¶cr¥û¤ÁÀ7»ç®ïdNË© >¶ò6Vñ'=ŽñÒVŽcâܹÀ]?± ui\~öqqŒZ|ç¿ûXåHè4 * ÍÚa`[,œi ,ŸŸÿV»Éì*3¬f¯È t­`×ù,WÖ½€ÚÊl!OƒØ5+#` À hÛK€IJ,Š©g@3?p-à z5VÄ8sƒ0à~ šEeà×!5ø¤G¿ði;CˆEw8bßêR ¥5¸ ¦Òª…lrº>ór„¢TËU§Ût|4=8é–SÜ–¬+ùp8Ú/(™µ¼©Ò—<‹Ûê:'×[à$ö1oûóKÈ×±Éò%Ë[{ÈRaè%ÁU¶ýÿ<Óò¯¼×c=݃>ßÉ ±È×¾¥É¯?à,Ÿ£4'Ôû ÂÃÏÅ›k”b`ᥱfŽ‹ …tµ8ƒU š§käñì6oGѬö‰lA¤–z4LFèþÙ¶½í>dóÈo½yÉùùö ¶¯4n9L[½)@Þ“±Š||‚fOÄ1£‘þ‘9.$T˦aÒMsú¢¬4vñÿøÖ¬.5æÉÄÇLþ?ô_¬*Õ4 endstream endobj 1141 0 obj << /Type /Page /Contents 1142 0 R /Resources 1140 0 R /MediaBox [0 0 612 792] /Parent 1135 0 R >> endobj 1143 0 obj << /D [1141 0 R /XYZ 90 720 null] >> endobj 1144 0 obj << /D [1141 0 R /XYZ 90 720 null] >> endobj 1140 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F52 20 0 R /F67 34 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1147 0 obj << /Length 856 /Filter /FlateDecode >> stream xÚ…U=“œ< îïWlif^ŒÍî’.—"EÒl—¼…æð0c›»ìäÏG²ÌÉÜLf $Y’¥G¼üPšòp¢häùÐNwe²þ¸ãIÊÁ!ßy¼»Üý÷±æ^MÙðåߧ¸t‡¯Œe–Wg°±÷½žͬ³\Éž*ü æt¯ž[ýùt÷p¹]VWÕ?ªA—s<Ë‚ Iå´·$—lP…š)ÒŸ²äÑt¤ú)«Î,,äãµ{B];:m³œ3;gœ}+¹|\îÈÑrx6ã˜Ò‡ §%™ƒ%ãDæ&Qf¤£Y?“àô‚¨1ëBª¢ zˆ@9¯©-õpÚ4Lu“ÁªŒNëŠ,?Ê’}X—Ñ´* üÍù¯bœKG~]§½Ç~PlVØsìý†Fôp‹M²"_Jª±QHlŸ¾qøàÝ)ÌsÍ΂´Ã©ŸË€ç«¿‡,d¦Çl‚â«sZé[7Z3?ÒѤ=‚ëÕ£Žib7“?Ž}hDh±óx%ÛwÊDfÈÒ¾SÕÑí!ŸâÜ(¸MþXÆ)„ÚÖfT~Q\Œ­åj_ã`ÊÆÓwÒj»_$ê.Œç g¢÷‡mî 8g'Rü¢¦)bƒZäù‘®z6a ì¦^Ç`–‘üÄÌÜ¥Ô@¡ñîé„“R²·žÝÛˆ lJTÕ¶ö·2tÖHàS°µÎ½CŠM¤ õ£+¶oìêI³Û‹bü–ºÕ†ˆÚÝÿ:éɺ+É&\×hÈ%¼%:;<½ŸmÐo`…DM£ËeÕìù·L@7¤)Û ì 4]h&9´jžm 9n–u?HC®ã÷­k2Îí¸v)6˜)J°^:eç·º_&’ ¼ z­902àê R’%Õ«&ê#3…Æù5T:Ü ¡¨Tžª`íèY©Ós€G±Æý=j&]Ú…t0."ÂYrjG­.â–þ•EyºÜX–ÕËÚ¢Y‘mÏ©B€Æ?âµj±½4¬ŸK(óË–5Eôq‹Ða÷÷šì:B©4Pô²¹‚Þ_iàFÆP0†K@Þ“¨¶zIk1â%r{|ðpЪӮØþ>É+ / endstream endobj 1146 0 obj << /Type /Page /Contents 1147 0 R /Resources 1145 0 R /MediaBox [0 0 612 792] /Parent 1135 0 R >> endobj 1148 0 obj << /D [1146 0 R /XYZ 90 720 null] >> endobj 1145 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1151 0 obj << /Length 1410 /Filter /FlateDecode >> stream xÚ¥WYoÛ8~ϯpÓ+­ƒ’­n»{a³E±5Ú>Ð2e‘ECGÿûáŒ9qÒ‹æp8œùæÎø gY0[ƱÈäj–ï/æ^_„Lù àO$~]_,þLÂYˆ,ÈÂÙº˜ªXog_½ßJuèt3÷ã8ö–ïæ¾”‰÷©±›Jï‰ÙÚêÆÔ»¹%YœzašÌ¿¯ÿ¾øc=šM¢è¸Pâ°e4 —" ÉÀÒ•a, Ørî'iä}šû¡7ÂYÊ` RÄ2P8/c‘ £NƒIG^ qhtnëÕ$Þ–гôÛµ]£tð-e¥Iýiè@}˜‰0âÈ]Õp!ÈÐ^£šÀËU«[bçÑʳ=ñoMUûÙªÆßŽÎ:K'MÏêòB×;SkÚÙšÄÛ:¶ Ðî&Zµ5bž‡Þ®o‰éH¦h,K·y£º|-½R@’!‘Wë)·Î½X„ y7ZJÏ´¼Ö´*ZnP›nŽ´Û¨-ä#þç«Ø{ Ü”ÁéÞìÊÁý$õê9†Ÿh}ƒš@‚pÇ!ÿD9¯a=¨¦X%“ÐáŽâAQ8N}ä ¡\#B¹ôd°†@å!W½3%%›‚£ZwÖùj›kb’ç|¹vnqhÐÇA{u$î=:½%ݶ¡“ÑÆï?ÓÉ· ~·{åâÕ^Ÿsç³nnL®A ?Žällß1QЪrŒ Vƒ ½5æÊÒA©+l†(ìš²<–l„A0¬²5]OÁ ]ž£tš¨¬sÛ^ó…Â9‰¶YAÞ˜CG¶rUU j¼èaãMÜÌ‹±•Ïtiˆ †+Nô¶49"/qzÅÞNw-QúNç}‡¡ÇÝ¡1,J"W_ŽõÅS/†ŽÝÒi½ë8cuâʃÑíh¬%ðw?¨ Ž ë{Ýìt]}‚<í¾N·]ëú4ñÖî@£ è Po™mkWT@AL\ž¨R€¡kÛC¿9š&Ä 0Ã÷SeŠÇþšÊ=ì¨ ({&q0›3)Á3óÁêEÙ …LÂ!}{#~¼š„7c8q3VÐÎóS(CU»ñ¨v‚šdÒ»bq #S–YúδLªa­ªW§÷\J`-†ë¶¦–ô—©ˆ³ä´bU³ë÷÷=$Wà £zhì ¨º»â#ž«û]ªfëç•j[ÚSSM¥ó¾iNÌM¯ã4Ñbw6aqˆ8•CüûªkÌݹ<ÅðÕMÇ6É#È}I±Œ–§þÿ¥Ý‡)æ¸ÅÓãöúNí•~G6âp¶YšºA´+P#Eré¼~µØ˜zÑ–ãð „LÙÆëóLxz$Óšs{D+¢ÀuìÇÅÆŽ<( öRظºîqŒÆëÙY~‘ŒöOÌ6ƒïƒÐ0%§púš¾sS{܇N¬c9tÄì&Ÿ GIƒ×—cnT~ݶ¦ù°0ý¢Öw}»¨, ^ÜjxàÈ_°ä{/ˆíU1ÄC@CÝÚú'˜ë«·Dñi„>øÜ5 Vól0òš¹îDî>>ÅÓ!ðÏøcóWZ^Ñâ3fŒÄ¢ÑøÐ÷5óýçÑÏúQœ8¾:/é'xl•îûáÿûüqŸÏÞå›ð’¨Ì€©Æ´—O$.2”§ˆŸ/ˆKú ÜÛíSJ`|ªö¦mÇ i|Pˆ.9‚›z9¤7c/¦÷'©Îè9Ÿ——øÞ–jko/ÿ'üØÿàe¾¢‰ïÌx¢ ØuŸsÿ8*øÿìŠìû endstream endobj 1150 0 obj << /Type /Page /Contents 1151 0 R /Resources 1149 0 R /MediaBox [0 0 612 792] /Parent 1135 0 R >> endobj 1152 0 obj << /D [1150 0 R /XYZ 90 720 null] >> endobj 1153 0 obj << /D [1150 0 R /XYZ 90 720 null] >> endobj 1154 0 obj << /D [1150 0 R /XYZ 90 653.136 null] >> endobj 1149 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 20 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1157 0 obj << /Length 2338 /Filter /FlateDecode >> stream xÚYK䶾ﯘl ¤ØV‹õÚ '±³92lØ{àHÔ´°jI¥yüûT±Š’º[ëôA|‹U_½Øâ.„Ÿ¸Ëû4Š‚\ewÅù]È£_Þ n`ÁaµâûûwÇbq' sqw_­IÜ—w¿ïD’ì2ƒ±Ý?+Ó>Ö­Ù¢Híž$~£Ý`*3˜¶0ûÏ÷ÿ}÷ïûù°XÊopƒ+n؉Ä]äI¢!² »K2ˆHCÅs`ÿ˜V‰Zñîûÿý‹*ˆ.V‰«­î g»Áº¢=¿Óçýwâ=µþÁMÝN/<öùïôO¦uÄp&S›ÿBŸƒezG3Ç^[û\UÆáîó·ó*HÃìòSœ:"÷³‹SÝ>Rï\[;wè jWuc¶9>Ôí±èiÑwºø2õe=0»;M®Øv„ÌÖšZUÓ”—ÊíÜ5Ü" ²8Û%AÂþ©c‰ØèS·ôµÝ™'Šz(¦³5àÎ~À±lW4w®O{™í¸û€ðÝñ>Ý÷C×µö'Œ}Í‹ß^,(Ç ÍØ=šñ´HBìwºÍ0ß5WÊ]DijêjжÌÓ-†ºƒýAEr÷©ÂÁ5»ž¥v7ý4ZZ¡y~œ6q¨Àã»ÖÝL×í<>ÍËÈ"–kË, â$Í;ÞÞo©!R™ú^‡~0E×VM2ì†Mú"L%ÕÛ飾Bµàû B(%X†ž ýhZ¯Gð7ÏuÓÇY±ãúæÅÓXw-uëóÙ”¨áæ•v‚²Öêƒ%¨Ÿ€øL%Úp¤‰|¢oHƒy×É8¥Ã2†ï@ÿùù—_iܾÚÑ¡FÏÝD'Xê×ÔftÝlà‚£)ÆŽP ¾¨-I¦3vBüÚ’Å×TÑÚ'';mßuÍÑ|-×,ƦßÀfð©õZ¯-U[Vù"[è<“,š’ù.Ë+¸@¨7›°adQB°ð¨è§—q0Þpƒ2R&tï áËVj®¬€°;k §ˆ³ Ъúå—À{N/fd,u-‚ç¡7oÌ\.·uYPPAºñðq• ¹a7úÖËÎv;Q,S@Ú^Ø/JáÀbXî8 ?Ãh³Ç Äчp¶iÊJºTñ cÑQ‚ Ä+ΙqÄ;¸5rzév-)$éÀne’S»:A&ò­'ð¾7‰˜Z´|¨ô´Ã'¶ºjNÏ©±lÀ^ižêb3 v,t½³ý•p`¼®½dX?tOæF:þ–·Å !ä§ Ý™¿?a}}‹k2@F*oi7]¡)+ڤÄ2»´3@xÀÿø•3ÈTl`ö±–Ó¼Ó ÍÀ‹tã¨Þx`YxsÒ-ýyФô7VSo¿¥Þ’¦7ϹPù‚Ö‡×Kê@Ù6gî‚ÓËÑT0,¶d•izs®|“6쉶[ó„žÊ ¾kxo®bqá(qÜGzKÝ©äp{v€¸¯4E]š5­pWòsБ Iwh×6ê΋ î*!/Xb>N°9Õ”Þyiˆì¯8!Sôl0ø5cwåò/¹3£­Ò&UëÒãÏ3-Ä*^§»\$DÊøB/«gŽ ªJK_HÌkWP`ûe4­­É=CßvôÕ¼vä¾ú~Uªà úÐí†çÈ0è®(§†èTŒèÄœ„ù‚\T¸,:KIØ„—ö« sÑ^æù:#ÿÙaïÙe• bÅÊ…âPëmw±&®TH\dìH‹ºŠ¾ºixzäí«¸û5 ¶æ™Nm4UaMÅÜqtIˆfwFUoîS¸¤*Ö}>¡3÷A÷ª@So^q “äM(R81£èä4´ù‘Áp6梵é5p|Qq€|‹ˆöTCw¦ÖèY xe—1º.¥ñbWYÎ-u )?ʃ$×uŒ·.ÍÅô*/ŠKXH#ysè[ÃùUŽ)VŽØ-õ¨yÅ8LRꓯry%Ÿ¹<¿¸J §DÕðÛu#”IˆEãžöb¯©+×ÎÌp×¾b€,Ê…¡¼\Äh¹~ÀRsÞÁ0-JÚÉÏãrV>Mž4N>­˜Xé»×k2D¬½~ýUˆ|dXˆ“SJdºtÀÜ+VhÙǘg4¯«xrXÉ¥³ã›Z¸Á=üfô‰ ø, ý°E0 d$oÉÉMÀ¬r^Ì1öš &£7£o3à›Kî^ËPB VAuT·¤1×…¯Ô©¦=–.©ð)BB1á;óZ®:Ëcÿ¦”Ç+˜Bg~&€jµ+õò˜‹O¨žÛŸiœ‰ó ?b܆G´–q[.)ÔË[['Œã°)0åháŒ5:gˆê*È%jõ@ŽbƒÓW<™Hg§7?Öé®å»Pi Ÿ0¸£ê‹ø2Ä8o%5Tó[E…«¨Uv´Æ=b¹ù h<µzOÚ’^¨Ö2ù†ôÀÖç—•ŠÈ/`‚Ž­ñ%‚Úƒé]p‡$€ ÞFè{rË „=äav…¼A_¸¼„E;='E\ÒãŠÿóäÿ¦ƒ³- endstream endobj 1156 0 obj << /Type /Page /Contents 1157 0 R /Resources 1155 0 R /MediaBox [0 0 612 792] /Parent 1135 0 R >> endobj 1158 0 obj << /D [1156 0 R /XYZ 90 720 null] >> endobj 362 0 obj << /D [1156 0 R /XYZ 90 491.528 null] >> endobj 1155 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F52 20 0 R /F72 4 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1161 0 obj << /Length 754 /Filter /FlateDecode >> stream xÚ…UM›0½çWp4ÒBmlôRµ«®´½´‡*µ=xÁ h N±Ùmþ}Ç%«H«˜/ÏÌ{3vXBáÇ’†&çy#ê¤74ZŸ7,Jd_v›%KÍÚ°d·¿L±ë’_ä¾—G§æ4㜓êcš Q’³yÒjD£5úe˜iV” ß¶­Ò?»o›¯»sÙ²(ÞéËG¼Ó£¼"ÙÖ"g\`w»´æÄ@é¦"V)/Ôd¿h}B›ë Ãx”­C¿Ù£íµ—¥SZTÄ,¨LJuñ´Á¹¨T\ÇÙÞ,:FŽòÙ»b1¹6”fŒÈ9e¤õÞÍ{3_5Wëf ÐzÚµ¸D1D1ž³A/Ó©KFºOñÈQ‚çU%€×ðpÉÕÔçwžÕ™‡0AóÆû´Уë.§}Ž÷x ¯á?ÚŽr–‡Yû|ý¿ø—æ¹D endstream endobj 1160 0 obj << /Type /Page /Contents 1161 0 R /Resources 1159 0 R /MediaBox [0 0 612 792] /Parent 1163 0 R >> endobj 1162 0 obj << /D [1160 0 R /XYZ 90 720 null] >> endobj 1159 0 obj << /Font << /F51 5 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1166 0 obj << /Length 120 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h C3 M]#  ˜†sZj^zf^ª¦®±±‰F™ˆ6Ö(JMK-JÍKNÕŒ ñâr [fjd„Ý5U%› endstream endobj 1165 0 obj << /Type /Page /Contents 1166 0 R /Resources 1164 0 R /MediaBox [0 0 612 792] /Parent 1163 0 R >> endobj 1167 0 obj << /D [1165 0 R /XYZ 90 720 null] >> endobj 1164 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1170 0 obj << /Length 786 /Filter /FlateDecode >> stream xÚ­V[OÛ0~çWDÚ‹#-^|É¥HÓÄ¥öP$Èž¶=„Öi=Ò8Ê…Ñ¿ãØ))(Ú±?çó9Ÿ-ˆãÃ/q&¾1†'á«¶J© j$µëQB|†H8q&_O¦ÉNK@é±:â@mDaJnÕ†1Ç„q£6v½ ¤hêz=»õ2£`D&€½LÐöºP)ãO 󵨀ˆ“ÉZ”šimsh(«ÔÆ v1O«•];ȯ׻ü ShÁc!úÕÖÙÒ(µ’O.‘Í¿ÕcÕšZmzYK‘ÖØõ AÉZ ø­ÙSŸ‹0Là°Ý¹*õØ‘ÛÆµ¥þr$ jݤEºéƒé9G%h–è…n²ÉTµóƒÞ ’#`•¢Xl ¬{Ç1ã!})0‰˜m&¦y‹LóBºÂe5ø2³Ÿ'Æ“0ìZ{cÇc>ö{†ÿþÇ‚?}™|ÌCK½‡‘„i࣋Ùt~u3Ó4@·óÙÍÕ·»³äævn ÙíÔ²fôÙ|d‹×Rչ…OñFÞd­­¨i2™[Þ¢»¡•R©"ßâãIþo-wÜnÜçžüÝ:Œöó)Ø ™¶Æ‹-ÞW²q!rSªª9í–À™„»~¤üZÇ}™K[Ùf-‹•-¼¾?¦Ì÷Qˆò0ª‘Ëí›â‡*Òb{j4ÆàvÊ÷·,2¼ªT[Öc|°¸Iá*/uv<¬¹Þ¤še·âõ)‡e[—í3(ò‚H¿«Öó±¹,l »B`Œd¬<”²Ö¡œú]¨…Æhë¶àÃôz>׿M%»ü<ꌃ 2›UB<ÔË¡ uä-_\ÚÆoõ­¿Ó¢Ù÷ÄRíaýðåÝf8ËókxóïEõ$ªÚ·;[ sÓ³ÞÊŒ`³ñ;wü ÓùeO.Š•,Ä_]¹×¯¾gÞíý—Ÿ_þõÿ ½k ñ endstream endobj 1169 0 obj << /Type /Page /Contents 1170 0 R /Resources 1168 0 R /MediaBox [0 0 612 792] /Parent 1163 0 R >> endobj 1171 0 obj << /D [1169 0 R /XYZ 90 720 null] >> endobj 1172 0 obj << /D [1169 0 R /XYZ 90 720 null] >> endobj 1173 0 obj << /D [1169 0 R /XYZ 90 627.98 null] >> endobj 1174 0 obj << /D [1169 0 R /XYZ 90 111.582 null] >> endobj 1168 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1177 0 obj << /Length 746 /Filter /FlateDecode >> stream xÚ­Vßo›0~Ï_´ú€‹˜´‡¥?ÖMZUiH´íÁ &qâØ‘¦ùï{ĆŒ4MRòÀq±Ïß}ßÙ>l¹ðÃVìZßGqY£yÏ5ÞYËNkÄ0é]Þö±…]»1¶’¬"I­?6¸ŽϾʨ3A/ßìg¯zû¶¢UTŒèÅ¿äGï&ië{Þ4ÕˆÿàøØŠP†A…ãEVûô鬧 ‹;qš€[>\;]ßeh¬d¹Èõ§£_™TÚ`%š0™s‰„쎲?t2a&jÆ85ËIQ&ÀݾkεárÄIn¦¤4c‚LÂØ÷ftîSõ X@¸:葌o¾}¿ß%÷ÝÔí 0nåóú/ ¥þm”o๮˜4ôçrN[„¿Im;>+õ¬/úõ´Ó– /e-rµIÆL(:.9Ñö“Tc#*yÑ—Êà /u‘,¥Êêa«¼Pr®¿žåŠŒ©ZÃò=ÃnÞJ“”)6±ÊÔk,¿±ƒLëªNóX™-ÈdcSc ¹ W„+)º(. Ä NS¹&o27Y&DšÌ#'/(DMÇ„ñ´^mIVÚ˜Uhk&óIÃ5^/íÔÉ· #eùŒÓjÓàþ CŸ¶[mhØÑ> endobj 1178 0 obj << /D [1176 0 R /XYZ 90 720 null] >> endobj 1179 0 obj << /D [1176 0 R /XYZ 90 157.689 null] >> endobj 1175 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1182 0 obj << /Length 890 /Filter /FlateDecode >> stream xÚ¥V[oÓ0~﯈BíC.nš^&!РŒ! ^úÆr§1sìà˺í×c'vÖnI:`ÕÔÓcûó÷s|làEú¼Uä-â8XÍ–^ZŽ"ë½kùz‚0ã|3 ?%ÀQ°ŠVÀÛ䇛Ìû>þPÀJ">ñã8/Ï&þl–Œ×w°¬jœ)£×˜í‡3Ú8‡ 1ñ§Dñ,ÀäÇæËh½i¹$Óé ²fÆ3¶1ð–Áj>Ÿ²,ƒ¥7_ÎϾ¯&z]2ÞX4VŽ Qci¢bjý;DÇi;”ã]c ©òܰÕ,|™ÙÜ!ú€uþïŸêh½ôÅû7œÏ×—_­”<(µÊîÉÝ Ž8X· gä¬:Àzàˆ$LS$êGÑøm³÷u”DÅ“­誙êY–ì7JîŸÎS$³^ECš$vpXšÚIÇÆXlÛ!7cutzhc˜ ÂʆqĽ€YÙ‡“qœË÷Ãh‡Š8ª˜VŸ Ì3ÀðòPTŒ‘0ÍÝaŠzmz(’%7$‹¼i’î?V*q‰˜ÙD]¿Zo†h.ä}…ú¨èááàDÞên‚zIè,œáPR¦¨ì‰òteXšv2DD×y“C=¥aPA©Û*íK÷kc›:7 ͯ‚ Ù¦!Ž+Q‹ÝMQ½.îæS/¹Ì›ï½­>E3”·µ(Û¦»Ç²píè°Z}Û¤£»_l;ÐÑdèñ^Bƒ¦•å–$¤14šÝ›À-"eO™<²K b°A¦ fY½‰žd91Ôc­W0åÌ¢¿i/$!!•Ö ¹ ¦…¾µ¤S—±=ÝCž 7j¿ËŠq)¶Ü*ù™ºV\­_U6vÌqäNO}‚ƾ`Ì®À‚íšÞ::®T>I¦ÖˆNçÇFV·9]í5›¾Ó„UHÑ!a)$aïá1ý)¿5ÏžNÀlø¦ùÖd#ž/^@hGUHð¶míáÖe²^¯Ð—ê¢Sm‹9 ‘Ëê„fYOˆÅBx‹z/BxwârÀ¦®àyîB$Ó?k›Â–L›×jÝZÐo…hjGrÆyì^*†P®ylÀú•â'Íú+½ÓîÐT•A‰+(ÒÊ::–ÿñs½¨/vÇá3¢³3÷Úþ:U endstream endobj 1181 0 obj << /Type /Page /Contents 1182 0 R /Resources 1180 0 R /MediaBox [0 0 612 792] /Parent 1163 0 R >> endobj 1183 0 obj << /D [1181 0 R /XYZ 90 720 null] >> endobj 1180 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1186 0 obj << /Length 498 /Filter /FlateDecode >> stream xÚ­UËnÛ0¼û+Tô"Ä’"õ2ÐK‚EOE¡[›ƒL­lÂé’’‘öëKQNc5”“±2v†û˜Ê$ÀöK‚¥¨`yÀ»>G+rþYBtÁ¸)W>'$ ¸ AÙ\¦(ëàGH²xŹ…· ȰŽ(eá)Ÿ4ÔЀÉa}W~]}*ÿKâø™nFÆ“v( rT¤)»!,C˜Ñ Í(J36µTñ^(ià×àÊÚ4Iøq¬n鈌9í<,%û'N°ñ<ÎÕñ·/Þ©AöUÛΰ HÈFyóízÑÁ%ÁGÐs%±óŒjOà):HWÖwÈì¡m¹êºJÖÆG¨êÚö‚­ƒ¾i8VÚÛp#Zð&¼x¯´€+ù¿ƒñöÞU¢u’½rÚ®ÝÖ­}ÇzQ{WZ Sm[ïŒP‹Þ͹,À“ &ð¨cü'­éˆ‹Û«ƒbÆìÓ^1kM‡¾û¢1Þlf–u8yKƒû,õ¬q®ß«j͉h†Ò$÷XÂÁ3ô%š5Jsði¿J³ë’Í¿hÝ%›=ÀbDÓt¾Ô÷oòy¨{9ú^u`@Ÿ@›eO‰ÁŠçT‘p?œwär+ä ’!ë­J 3&Í‹YÖÿT±\»öá~dE–„[¥wËåÇ÷ÂTóð‡ò°3Áu endstream endobj 1185 0 obj << /Type /Page /Contents 1186 0 R /Resources 1184 0 R /MediaBox [0 0 612 792] /Parent 1163 0 R >> endobj 1187 0 obj << /D [1185 0 R /XYZ 90 720 null] >> endobj 1184 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1190 0 obj << /Length 653 /Filter /FlateDecode >> stream xÚµUÁŽ›0½ç+öP¨„ñ؆@¤¶íöÐCÝH=´=8à$h#c¶Yi?¾œ-é’MªvÃ!#û½™7žl>pìÌ)E ‹´œa»z7kùàïV³àc`”àœÕfìb•9ßÜ÷;^k¡<ŸRêÆ Ïg,toö¼¬ 1,¦²úŽm[Åu.«a±[)DãùSæÔû±ú4»Y=i 9#¶Cƒ"¡èêˆ]ä*¼]„⡲ Ä2åÅ Þd­ƒÏâëm­òJŸÁ]§J~<›‚­¥Úöa;c"ê€Êø¾™ÿÆgÑ(ü£qò&í›gªq,¦È«vÿø¸QB¬›¬ëMçá‰3èûvrQɉþµy]ýóσÞÉá4Æú×Jò,åRLv^VfÔ{qãMKÏĆ·…V²Õâôt¥<…PûÛŸ§çôuò´”hdq/F3N£ƒY¤ ŠØ‡Ø½]4S ¡¡D(ŸQ^6²B»\6…D•œèC ‰P’ g2¥êUk¯óìátÑ®¦R¶ùÝÊR Ö¶ëCwþü¶n¦‰OqÈqœ@—u0vk®—o=?Š»™XæÕÆ<2‘±¯—“Wnû¾çljAý-ÛD%‘šJ5¤„ ÌCÍ;"ž$ .`óE®xQþïLŸ*j¾­Œšî"ب°û «7z0ÓHïSªß…³ÖN4¶²Y®Dª¥Ê‡ñïž÷_ z_ endstream endobj 1189 0 obj << /Type /Page /Contents 1190 0 R /Resources 1188 0 R /MediaBox [0 0 612 792] /Parent 1192 0 R >> endobj 1191 0 obj << /D [1189 0 R /XYZ 90 720 null] >> endobj 1188 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1195 0 obj << /Length 654 /Filter /FlateDecode >> stream xÚ­UMÓ0½÷WdÕ-RœØN“”#ì®ÐÃJ‰4uÓÔ.±Ó.ÿžq픦›m@<ÏÇ›7{!üØ›‡^B)šG©—oG¡ÓnFØI>øg¯£à~†=¢y8ÇÞ¢8±Xy_&8‰¦>IA7yS0±æ‚M}J£Éž˜•NjV°š‰œM¿.Þî§d3BЋ'p(öR4ãÈ ÁQ‚ˆzqBQœDRPÉ<«‚Š/ƒµh¶Íret›À@€Ð>ÔŸc­·»¾ÝB÷ªwµüÎr­:{xK.-wW2|š=…ºvJÐùƒËÝKïRëÝ*È¥(zƒ4ª6ÕÒ¬b•\ó|Ðòíí]ŸÍ')õ‡ŒWïåºÝ&pxˆÛ÷ùŒ§ÐéÙäÎôÉŠ&• ^1§|†„q_ž›—Ä?OEÇ• C|ÀØ ÆvÖƒ]«÷¬¶ò*Ó™•¸°ë‘6dÜŸ6ÊÅ^2­ÛBj ú¡™•uÉÕÍ0®ŒódÚÏrër5PNÛ ¾iH»®ùÞi²ßM²’t胳M’Ä 01&†KÇH —Â(Êù ¦US'4yæü›°Ü…·‹"—8qz(™s­!¸p¶™º‚â›K¹úù¢·k=¤‡£.DDàZê2ÿÏß› }‰W\eËŠ½:îáaHÚIn.‰ ”J+Ä~4|ß;ÆFH3ÿâÙù7ã˜XmaÈQa'Òo3RŒhJNå^=¬}7ÀÇ[׸A|1ìßIÜ'ÄO£˜˜ÇÁt!õü(D$ž[ËÁk5‹ d˜úx‚PÊ5³Þ—ÅúBA8¦ÿ£ËP x{À}7gíÁæ *¹T•DB¶Ïê/vèîI endstream endobj 1194 0 obj << /Type /Page /Contents 1195 0 R /Resources 1193 0 R /MediaBox [0 0 612 792] /Parent 1192 0 R >> endobj 1196 0 obj << /D [1194 0 R /XYZ 90 720 null] >> endobj 1197 0 obj << /D [1194 0 R /XYZ 90 147.228 null] >> endobj 1193 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1200 0 obj << /Length 713 /Filter /FlateDecode >> stream xÚ­VKo›@¾ûWPµ[,ËÃzp”¾¤F•b©‘šXâ­×€Ø¥qÿ}vyÙ„Tmíëy|óÍìÌ`lØðÅFh—®k…^`ć…­¥ûÖ' ÌÅf»@ï|l`Û íÛt±MŒoËë)$-W¦ëºËàjezž¿¼9’CÁ©Æyö`cï±*‰dy¦„µ„S±2Œmw‰/ýÕ÷í§ÅͶãâ;Î dk‹3¶.6+\¯½š,ÆëÀ³°ë)¾¯ë8àoBNÞº•–¿Üî˜P§”Õäë—„eZ.˜ÔrQИ¥,V¿"ÉOk…ÿúiA¸§ýsŠôææýÇ[ej5©½ˆp¬áà(1gÙ^\5 j#õ—’¤¤W gœâyL8ôÄ8™o7ôæÁöíš<±úÁÐò'-‘òšàŽ*Q¶˜þ²÷0§x$ä8ÅRçX…À¢^€xÑ"ƒ.£ÇJÌ*Êü%´TI a{£)„.H…‘ÈŸç5-8ÎRŠ/Þ¡®I's¾ßä¹¼kŠ:“ûÌôÜQ©U¡ždXl$SYDBëJªÕO;Zê™"\ßÓ½zÀZ9°lºŠ:¨Ušj ÖºGoO iÍöôèZ{†¡çÛ'ÍÒkÏ pbd‚`m¤ìQLµÝÈŽªE):‡©ë¦2FµC!I´‚…7$×uSU3,B÷Cø•‰ýK TÏ6Ê-9PÕ'bnHjÒ˜&Vë'…¨Û¸¶Ú=ö3aüC½òfHÐ,©Vœ¶_MÎç¹ùy|§Íͤ°DÎIÉÄÜ&û[.qb–Iã£c›Ï¯QKRº—Ivb þû‹)a‚Dœ*º¡åan£Œ§û«ä²Ò™lh¹§œþÒïK«·G–èµ±ëßÝ0Sý]t»§ý¯ñ-–Vƒ endstream endobj 1199 0 obj << /Type /Page /Contents 1200 0 R /Resources 1198 0 R /MediaBox [0 0 612 792] /Parent 1192 0 R >> endobj 1201 0 obj << /D [1199 0 R /XYZ 90 720 null] >> endobj 1198 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1204 0 obj << /Length 833 /Filter /FlateDecode >> stream xÚ¥VKÚ0¾ï¯HÕCAj J¹ô¥ªR¥UiUU3€µÁŽlgYþ}'±“&Û@©Lœñ7ß¼!^„_â-#/›Í‚e²ðØá&r§7ÄI>*ø=÷«›ðsJ<ËhI¼Õ¶±Úx?&$›Oýxg“[;.`êÏfÉä1®g[P L®¾Þ|ZuÆÒ8þ›Zã/:3â-‚å|žÔlH¼b’xóEYb)½žâÍtB‹Â •Ø€²bÈ«PÀS¥ÃB2Z„_‡Ê‹šÚôÑÑdÞ¢ÔgË !©çÇ$Ó¼Á°œjÐŽOÐxMµÑ"VëþþþÔ#(Ü!zz÷®L†€¯ÖÉÀ‰\ÓuÁÅÎ>š=h°b!ÝÙ–H¤ÅÉÊ¥‚GFwN]Éè»ÍÛ’ÇΚ–ö„TYuPÔt §ŽCÑYaÃõëqÏÜá ¨6˜ž½1åw:¤ŒÖ¿OIš¥% 5á4§1èq”†Á‚Ä$ŠÎƒ\À¥¤ºãÛ †Dé8ÌùÊ$êçï+—tª¦ì­Ë°JqÓååé| ü$È¢lh‘Š~¡¦Ãš+­š–'¬.]—·é’Ï«ÛFA¹ò¾¨(rÐ}»ì ƒÔÕ¶ Ь×gäYˆ^úÄݱiZêl¿Þ*(©ç Y‹x92"Òl¦8¾0χ<š'‰s)¬ s%¥ë$ÊLndÅöc0½Wlê/’è¿¡†³©u€j}ÜØñÔz12Âþä¤v§l.Y}}Û»\bÿ«Ž—"Ç, ÊÅå6©-è=ÝÈã -Œ:ÜÆßA›«|>‘ IHV“ɲtê'1Æ—7/ÚH£ínϨœ‹í5Ó€IÔk&@O\ec~¾Ä Þ ÙŽûk.ü²ÂýÁÐf…S°.ì6ÀY–]c÷\hɳ> ê î}pŒt¥œD…§? gkJw®€º³=}„g ‡I¥€™ ¶J'ÐÔŒ–Ru»”‹v‡JñÆcÝòY·Q3n#"‘ÍùÙÜÛÈþÐP jOK÷ŽŽMl…k3°âjÏ&×¼º“U­fì0K`|ËYgçý_ì7pù²Ë endstream endobj 1203 0 obj << /Type /Page /Contents 1204 0 R /Resources 1202 0 R /MediaBox [0 0 612 792] /Parent 1192 0 R >> endobj 1205 0 obj << /D [1203 0 R /XYZ 90 720 null] >> endobj 1202 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1208 0 obj << /Length 1008 /Filter /FlateDecode >> stream xÚµVÛnã6}ÏWØkºº;€’b‹EÑE‹­ßº} %ÊÖ†U’Ê&ýúEÊ–9ÛkŒ@´<¡Õª‡úa”C„V-¯h‘%Ép“/Àbía0]ígkQ4]mLH©Šºy"Œiê@ ,ü8]pòÓ®Ña§Yb¼`Œ'/‚seÖû‚«Ã˜H ~®€ãtªÊy¼j„ü*ú Eô& Òÿ@Eç$§üMðeúÿ û˜ƒv´ÒBhxŽ>~´'‚ÞÞŽ&g6B]–@(;KJãø¨h†Bñ¡<\÷sÇØ}Óñü THÿ#•Êg¼Ûæ;ë}ãÇ89ß0^6óë!„Bó}¦`þ¥£bL„;*tL†àC_ »¡¹±›¸©›¹R‘º½E¡¿‰0O8kºY¨¦z> mV oÚõ’dÐ ÁG`ð4ìG¾·mÖB¦ÒôZ¦æÛtWäiÌÍIìg(¿pŽÀ*%Ì!@2ªz)£ñ fÒ•x.Ôqhè{q’-SÀV•ê¹§E«š–.Ìo‹{Oʇ¡σiiÈÛ¼§å/Sú#•³Ê,v# ýYG=UÇ6d-x{Q»ù8³È+¸³èiÙLç‡jç{ÍA§þ/…×–…Êòµ)ªÈ³ôÍr;—’|…™²P‚?5aï,ðÝP Ý[ù228ií |Ó[Aê«€¤“®õi\ò¶%]%õíàõ‰gб½€´ ̼d¦èc—Åõü/[_…ÿTF× endstream endobj 1207 0 obj << /Type /Page /Contents 1208 0 R /Resources 1206 0 R /MediaBox [0 0 612 792] /Parent 1192 0 R >> endobj 1209 0 obj << /D [1207 0 R /XYZ 90 720 null] >> endobj 1206 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1212 0 obj << /Length 755 /Filter /FlateDecode >> stream xÚ½W]o›0}ϯ`í¤%|!}™Öm]5iÓ¤¤ÚöƒMðb ¸Y¤ýøl:’B›©£Éƒ/æúœ{¯ñá Gþ±tŒ…çYK?4âlâèÙíhË”fÇãr=±¯æÀ޵t–ÀX']ˆ52¾MÁ"œ™n(ç¦oÌ6„á™éyþôÖ­GoZâ—˜Åxöcýqò~}G6wÝG¢©=î…ã#´–Aà×ÑZ¡,<+Xø* žbJã<Ë Cü¢&5€oWâ¹2 Ù¸}œïÐ —·¸¼è¸¹Ú (·ó™Œb>½„"eJXeÆ+H©º¨R¬=Wï”!C(`E"ªo ¡²B›rÈ4MY[?8dKÊ<;‚Í ¯pÙE²y Q¾ë6VÎÔ¸Ê), oYº©ŸÙ4!µ‰°#Âì&7UŽ+ ÃÏ"^ò¡ÌEÑYaÖ{á.¹.a¼ÅuÎ+k%‚{ëºtœßé¯1ÌÛ;íVô@÷Ä¥ ö nuúP |/Ë¥k5\º:‰ëDþ%¸-^«™©Re½H°W\Å%)ªþ½ê+íËïÎ܉Y$i[Zv³ïE¡¼€¾Íï‰z7e$2xÖ—ïXlàYÙÜØÜA6ïYÙüÿÿ “ÍŸ5µà‰i\Zu¡9ÛüÌ£A-}Zr¨¾+¬µ$mÕ5±Ö†RDáúBp\êPSxÛ P‹LPXa­õ¶‹UˆkÉ@-YÎñ¾€å¶}t‘šiVHíƒ(«—¨É“6ê!pwLpoLpÿdðÇžx0&8|œå$ôÉèD ³¯çRºï$wÝÇOòMä9<ê¤>|¾i{&†š¶¦u‘Î0‚Ÿ[F6iÕÛ| v&šQi [4Á ¨¿¶‡ýû4Ïp7Øâ©.•Z®ïéØÓ~} `DªºäÕÓ;]<ã»o€N‹¬E’TS-ýôkqÙö­rËõ[@7` Ãíþ…º¸hž¢!­?.þÅ@r¸ endstream endobj 1211 0 obj << /Type /Page /Contents 1212 0 R /Resources 1210 0 R /MediaBox [0 0 612 792] /Parent 1192 0 R >> endobj 1213 0 obj << /D [1211 0 R /XYZ 90 720 null] >> endobj 1210 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1216 0 obj << /Length 695 /Filter /FlateDecode >> stream xÚµUmkÛ0þž_aÒ}HÆ,Y¶“Ø…}hK £ šÁ`C¶åØÄ‘<½4 cÿ}²%duÒ¶¢ÓåN÷<÷Växú9±çÌ‚Äa䤫gµË²’« Ü‹ëùÞMƒ<{1ræùîóÌù:º)p- »AŒ¢Ë±†“Ñí¯êŠeÊ蓇…âX–Œe£©ˆ»>B^0B³xümþap;ÿƒeâû¯€m,^  x: °(˜©;Ó(( âŸcí9ÁgÌ¡¨«`Êm¿$NäŒÉŒâúš¸ŒßU]šÝçìQ¥ÅÇ’óÐÐ3çÛ#Ç›'oâ¥yRêTLLó5ÇõŸ ¦xµvtîé…ð«Uº!˜yÑ>¸»ù'Aø3á——­ Ò„›ô´6þ>q"S( RUâ,šPC„2E/´ÃnKqTµ$øÀ–[<@ ˆ,ð/׺$çÐÓáetçå'Rl@¤›eÕ0Ñ¡m¥²Ç+#ªÌêÖ¸”FjÛÆ 0Œ[¶wfÔ»²[Ú3ZÚ=±ÿÊÈ.J6Jœ‹RÁÖ*¬û:a^0!÷+ï¿R„ñÅ~ÍNp¥EÉDÅeçµ VYx¾Çë$4ÛS'g+$Y59‚ØÎ¨å÷”Ê÷ÈŽáó#à‡áþ\ü“O_Õ9ù¡JN²öÖEÖ ÃèŠnÐt•‘Vª“ ülS€w'ã½(ÁÂÜsŒpStiDY`y$z7{dS6=mBQ;ccK«„Š2©ˆ ÐlÜt7ÚÍ-YÕrÛ,áþˆ=‡íò¥$íînozìÍ&nU†ßËÍü·²Zh)«·‡úXI‘•M`ÂÙ’P›`›®û϶‚Ùrn˽¶§Vx¸³oJk›«lAºù¿Â/ endstream endobj 1215 0 obj << /Type /Page /Contents 1216 0 R /Resources 1214 0 R /MediaBox [0 0 612 792] /Parent 1218 0 R >> endobj 1217 0 obj << /D [1215 0 R /XYZ 90 720 null] >> endobj 1214 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1221 0 obj << /Length 856 /Filter /FlateDecode >> stream xÚ­V]o›0}ϯ é¤%ÒBl _•òÐv¶I«ª6“:m{pÀ+ÄF64åßÏ“BHÚ,yÀ¾|Î=ö… ÿИclÛæÔ™îºttÕ‚zÔ—€~ q=o ¾ ¡9ShÌ—å%æžñ» ' ×·&2Ö½YbêŠ{}ÛvºÏ–ºÚ]Ž—˜cêâÞßù÷Öí|K6´¬#jbOŽ ‰9¥Ú–9µ 1š8&´\ÒEO>9ì¢ü²$!ÎG1'‹$&ŒjˆØÆx1ŽxšO 3¬™O¯Ü8Aa˜ª<¤¾¾4Åí0ÆÑ ®Ñ ‹"¨éE*$A>Þ0¾ÒòŒr%qÀ’8ŸÜ}{lïPÁ‚K¡ÌW¹cÉ‘×ì·?`(*c!Çp 0&n¡ÄÃ"ž pìVâlÆÓ¬þŒIÁZÏšyxFŽS“ò>YÀD,LÓ´JW½S&Üåè×åÕöð‚ zy¹Ÿ9l#& *äMI× ºGBl¼Gi"æuª4,£Œ2lÉ‘}­eÈ»ö"ßÓylÓHT†œ“?Å/‰hØŽAÈ\H’ ó–"F‹ê™Ñí(…ne“\ĸI„¬Nĉ0Û'îF³ï¯ÂÎÞfßKEø†Ý îU°Ïäs–D¦¶¦J˜Ý<÷CB“—7cn©™=øí>âB-Ý;<°&¦å8»9^œ÷+Ò(Ûq&ßÈ‹ÜÙV é`ß÷8‹:²J8–ŸâSÎV$ kb‡pWAGVT'Ô‰õx8–åw |‡ã§”ÕQà)Ž_ø x O#õÊÐcp\M-õN†Ë|”¡e{q\:\s!ωzÀàÍÃíÕç·µj²Ó¥{…_,Ñg“ÑúŠ ¿æKäãvM!jªöÓµvôÅ×Qò£ƒ ×.}QßydŠæº¥ÙžYÝFq§E])¬«K™º]ÿ”E¿ÃT‹XîÆ<”6¨ØX7qî¶íT3žÐB^˜?ˆuwÇb\´eÅ}Uø¸’[ÆrùÃìR”¾vaKŽh‘k¸®8dÖ™çs´Öj]ŽŠíW«ì1}¦}Ã\ÉJ»˜ˆ­š ¡Ç^Ñæ,_¯„nîjÈ›‡[ÍÊ{ê+ ?mª™ÿšÃUd endstream endobj 1220 0 obj << /Type /Page /Contents 1221 0 R /Resources 1219 0 R /MediaBox [0 0 612 792] /Parent 1218 0 R >> endobj 1222 0 obj << /D [1220 0 R /XYZ 90 720 null] >> endobj 1219 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1225 0 obj << /Length 810 /Filter /FlateDecode >> stream xÚ­VÛnÛ0 }ïWÉ’+–-ß ô¥[Òe‚ËžÖaðl9ê,m1ìßGY²çÒvÝZ¡eòððbŠ ~±Z†ï8($ç–>½¿ÀÚ2ÁÁÜó¸^_Ì.6°…B+ÄÆ:݇X'Æ·ÉûmT ZOMÇq&ÁåÔ$ÄÌ£¼Ê¨:ŒËâÎÂdÓÔ‘`e¡åIFùÔ´1¶œ ðôûúÓÅ|Ýsqmû²Ò㈭ƒ…žG$YL|dÇð|y>QŒGq]£©„¶;álSDÙÕ¶©¦&¶\k2ž®;ùøõVbK9Õf©>›*‰í_³Z™PgÊ6²  `ˆxXgd‰LI,k?¥öµA^¨Eùβ2޲ODû÷“I®Øõ{® v®2j®‹²îÈ”WšÑ{QkÂI“H©¥ù°ÕgiYo¨h` ßõ4gEc<,9+7Ê(cƒºB¡NGÊ^°“÷žeÙIa*Pæ g}i–ƒkH\ëÈÕ´dCŸM#'ÐJŽÇãS8gÛêæ«º—)â z¼ïú\¸J5[ø6ÌrˆgËñ“´Ã$²½PyÈ… ž  «”—"Q¡ƒÁÕy6éSüãÏËb ´ :r#ázËô¨¥,ÓÃØ4œ&ùâ0‚Ý=RFN96ú¡LÞ&ÑÓ!8l”ólho•WC¼Zÿ£5\ËÞî·4âz~³\½±'}:S“Ù¿ °°`Ed—j „m|ÀöU}®JV>ìkß°]Ÿd¶ˆ¬Ð›dC ZG™ö§â¹Ë¶Ï*8¬@ì`ØW ãÖ·²f¬™ô±áz—Â#ñLJgªè>Ÿ*±úÑOb»|“t¨u?@4zj\š0!ys%y·´ö‹ûu>@Ã\Ó +n격–éà–|EºšFï$ÅF’ѨE Áî°Ðy^‰§y!XM%ÐmF#NO)²,8­Å¢oæù,¯ |«BokZÑ"Y¦«òKo?ÃW…ÆØÍùpËÔM±›²6]œEœË4—ícTÇÛ]Ró”.EÒê{ª¢ßÝ?*?æQ< endstream endobj 1224 0 obj << /Type /Page /Contents 1225 0 R /Resources 1223 0 R /MediaBox [0 0 612 792] /Parent 1218 0 R >> endobj 1226 0 obj << /D [1224 0 R /XYZ 90 720 null] >> endobj 1227 0 obj << /D [1224 0 R /XYZ 90 502.894 null] >> endobj 1223 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1230 0 obj << /Length 973 /Filter /FlateDecode >> stream xÚ­VKÛ6¾ï¯‘#êe)€/)’"EÑK ôô K”Å”& ’Þ­/ýíj(ÅÚxí´©}àÌpß<86 øÒ N‚U–‘:¯‚v—xéŸwÔS1(Ägo7w¯ß4  ©“š›þÜŦ >†´J£8­@þØ3¹ã’Eq–åáCêÎ,Ô¬gšÉ–El~¾{·™ƒizÓø NFƒŠÔe™;44ÍH‘¬‚r•‘r•#¤î㢗 ç%õ—…§ß¾ûéïH¶=Ù+ÛÝöð$Üë÷«4 9Éò2uà ý\œ•8E튔¥L!JÓ Ó­—…vAjBS_çßf¦¡¦U*Je‘8Eiª#2hÈ*dºWz’Fºû2ÆÝW!ky#¼„éÞ2ƒ\?y¡½Šâ<ÉÂGn'­æØN¢Ž>>@ã^Þ*iØÏÎÅÊ-|¹‹R'¡WᚉJ<öµsž=Ê„!·#`à1C%x{Šª,$Q\Ò<ü ŽLë" hªÄYåà²UB°óšÜË•“Í1qïK³ ŠeÞÿQ¶*^䆩)_X ¾\l0Í)øFí'‘ 2T”(æZ3ߨ"ß æR[åáfpusŸš‹ˆ†ÞÞ@~ ýhÐÁ<Žy;‹W³¸UGáuÊÇ•ÒK-ÃV=p­ä~êlœù4EØ_SöÜ=öåÓeEnÇaáA°Æ0tÑA*J¾ô{Æê4%nÆv>È—!‡‹ —ÖTi§a^nñL.¸¹”–U¶Ü6š7’à \ì–´"U§¼áóÅò=Ÿ»”`ùYt\ŒÇø>ÁdàÊE¤º´—®8Æy½qÁ|0%mÃ¥—»¸H™¬Šž·È5­{(æÛ3ù¿j–ÂjL¿8ý¾ý>oÝo\ð ~“óTš½¯(ÌJZ/AjµU¸ãŵ7·¼;yãÖ<]Þ %wŸÕö jÔ$‡%³,Á•\÷ÌÔEßÐÏGc‘êðÁ÷²;n(ÇãÊplô“ï¸f“—»+ag/vž®é4MÏŒ}åõ„Ø2>Å9{…׆ø¼8Ø_Uƒù¡±k¢e,D¢´(`‰íØ:¹dv±·þ=@3|Eg•{‰ô0׳ã7Ææ ÌV¹B–°zÍ¥ûi+WÅî²'Ö lË,I¾2§— Û¯ïðäSÓô¶éßÿÙôÅý3¦ôF¾ë{Ò=ðþû²Í¡Ó0öt`kXG{v; "Ôî·óøEíÈý3ÖÙô·öu‡ÑÑ endstream endobj 1229 0 obj << /Type /Page /Contents 1230 0 R /Resources 1228 0 R /MediaBox [0 0 612 792] /Parent 1218 0 R >> endobj 1231 0 obj << /D [1229 0 R /XYZ 90 720 null] >> endobj 1232 0 obj << /D [1229 0 R /XYZ 90 610.81 null] >> endobj 1228 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1235 0 obj << /Length 841 /Filter /FlateDecode >> stream xÚ­Vßo›0~ï_Ô=IÌ*ES›uªVu›´¼­{pÀIÜ@¶)éú·ÏƆ…’V]úÐËÁ}÷ùî»s áˆ?hDŽ1ñ<ù¡oÏíÝœAmYâkï«ù™ý%€t@äDИ/÷!æ‰ñËœ­QÁ1Yžç™áÅÈòýÀ¼Þ¡m‘båŒóìÞþª¤ˆ“bÊ@šg«‡|(füBEEÀ‡Aó¨NÖ8Þ(³dò@ˆjAd9WFE G‹T»yþBeUNÓ¤gjuB”%m@½—Cýg5ø)É6šÊ½hU‘“Œ“lÕ¼_Iñžª»¿=dô6Oð4·*õ⸤ «þ׬by3L—d‡ÒT¹Î÷8M9Iž†'aÇ0cõÍÒ¦šAò Tc¶¦±^-§Z…vÿ_ª¹ÅyñÔ#Pò†:N#K­È7l­;´Ñ½ae£ ,æôŸ@•µF:u}Ë¢«ÆDì®VJY‚hr$+ü,€^3Uté(™–<ËK7AtNôb«¶™Ú:’³Z“æXDãnpÁ»žå‰mlPS¬§ÒVªœ¯¦'e¬k¦g\ÞYb­½zX>È™ÛÊ‹ŽÖÙå¤Ù)YغL0{2Ûgº/ÙCrƒ8|³êÃQî–ƒ@ËÇjë6ÛCjüõ4Э׏×Io5‡{wýí³¾#—@-Ícåì8U.ù‹ò/H×Ï} endstream endobj 1234 0 obj << /Type /Page /Contents 1235 0 R /Resources 1233 0 R /MediaBox [0 0 612 792] /Parent 1218 0 R >> endobj 1236 0 obj << /D [1234 0 R /XYZ 90 720 null] >> endobj 1233 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1239 0 obj << /Length 728 /Filter /FlateDecode >> stream xÚµVAo›0½çW í02 ƒ!¤—NíÖIÝ¥9Lšv0Æ$VÁF¶Ó®ûõ3ÁÐ$M²Lk“ÆØï½ïûÞg€^dÿЛGÞ,ŽÁgm&‘›½Ÿ@7 ì‚`kÅåb^'Ѓ˜Gsè-ªmˆEéýða†§Êìœÿ©bbÉ›qŒýÔ]c_±Š)&(›þ\|\-F²¡¿¨éV¼3CÄ Æ)rrÒ ã^NfÓ I‘O«i} §Ð—5Q\wôáu ½ ÌÓw›Q2/@sd.šwÿûëX¬øÀf §Ðž´á%V&ÐNßæ>è/•Tý€¯ÁŠK]K ä¿b/VjÅkæø¤0„ 7·M­[FyÅi×CWLïÀŸ¢|­Ä!k5[öôlþ^õåÕç›o/2{vÞöd¸é’+FTœé‹Ísƒ$N÷´žPµ2¦-CÁŒ¦¤u…x$Âô#3–ÉÈþÊ~qmöŒ eãvü7QÊÝ(F´G³„Á,ší ×Z…5/Âî³c; ïÆý%5¼|:žÄðXmri[7J¢Îƒ†)‘ë'ÛKð¡™,YõªçÃdWô-áõ—uqÑ“l/ØæhìªÑ玺µÇU:Ûß‘ø–FïúS?+Æ{”'¬uS훨”L‹÷æ“îõxí‚Ò=|Qˆì¯-‰aÍQ<öÀ„s«3*)†#hp¹Z‹g¦Í d††Šž¢¥Š·ÆEJY!¥1¼a§ÎŠt4C(µ2Wr¾Ü7yб#£†K‘¹¦«C‡Ä`ݰ7k¿iÀÅ(Š:°4=l—½‚ÓÅMeëzϾ@¡~¶ËîÆÃGk¢œG43ëöù£?º£—Œ¬¹¸Œ@ÉZŸòTCèjóùÐ;rÄ(ÆzðÑ팫=ËIç¦pèkex—ep¶-jII\„†ê•ë&¦M¾7×È’å³$>hþÒ>; endstream endobj 1238 0 obj << /Type /Page /Contents 1239 0 R /Resources 1237 0 R /MediaBox [0 0 612 792] /Parent 1218 0 R >> endobj 1240 0 obj << /D [1238 0 R /XYZ 90 720 null] >> endobj 1241 0 obj << /D [1238 0 R /XYZ 90 720 null] >> endobj 1237 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1244 0 obj << /Length 817 /Filter /FlateDecode >> stream xÚ­VßoÚ0~篈Úxˆ‰óƒ$H}XY§ušº©åaÒ¶“˜bÕ±#Û¡CSÿ÷9‰S˜ ¶Q¡ßå»ÏßùîOÿA'õœ8@&NV <³û4€fåjwÇãz>¿‹ =z)tæË]ˆyî|ÎV¨TXŒÜ †Étä†a4¼ùŠ’âv3ãì›ÃÇJ E8k7ëŠåÈõ!ô‚!L¢Ñ÷ù‡ÁÍü•Käû [{°  “€t2 k²0ðAêCg`‡-ã1å¢cR±ÊÆLÊg¢² ±QÎ4íȆ9–êªï¢O²¬i:nb/v\_ë¢I4°—Eë§Å '°Ûl°>U¢]0Tà¼]J,ÖØlW²–¢^!㇟;ÛõíÝÛtùs¥Ú…Z±ÂÂAòΆŒ1ÿŸ ¥íja|KF†]ÅrMàø‰8E¢‹(0aZ>JÛ[Ÿ2›bfóN‹ñШ §ÓÆÁ"ë6[rAؘ0`4 ã×$URX­ÏñUE6FGpÀ”# ½È;ßwú»(Z/¡voš-ÊŽ“5ÊÑ y¦ŸŠc+ö«í â !÷Dz)ôÉ!îý4lJºº(çOU V˜–ºLzŠóhðÃ0<,G±MÿRg ¿ZjN×@W_è{Þ^üž=€]Ê»èÞiØ’ßz¼}ÅÑ)Ý4#ÝïëÖÚœª¯ ¬è®h—ÿôéÕ¸)_œµ$ºÓ·¹ðà‡a?èÏö‚·­«É'iƒzS–˜å·Ë;þPe«¤kÔP£©©F?Š@÷õ.lò½ØzÑ.‰/QE•à•ÚöÀ3˜€$ðüÐuÚ¸~Ö™«ï*K×P‘ã/3ÎôÁgÑé¨Rü‰§­…³ Ky±\Œ†Ûìæ~Þ´¬DmÌDAzf¶Ë%7ÃlÍ©0ëŠ2,ЂÐúSGÆnšDQðŠ©íTÞ“å=’«/ ÌT­‰Ôb(DaF”µï#õ,¼°‰rÊ’ò²Üü&õvqÿ_Õ™`9‘hAq[s0I°7Tkýå„™²Q›_Õ…jm8µ;¢Õ¯)æ5í´Î endstream endobj 1243 0 obj << /Type /Page /Contents 1244 0 R /Resources 1242 0 R /MediaBox [0 0 612 792] /Parent 1246 0 R >> endobj 1245 0 obj << /D [1243 0 R /XYZ 90 720 null] >> endobj 1242 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1249 0 obj << /Length 724 /Filter /FlateDecode >> stream xÚµV]oÚ0}çWDåa -‰O¨ÄÃZuš&u•ÚL›4M“IÈpìÈvJûïçÄ¥4…:Êí{||ï½@ ¨/´¦ÀŠ}ß™+-ÀŒ®ÐX¶Z`wV\$÷s-œ)˜B+É»IfýÁI4¶½‰]æ˜. ŠÇ¶ï£{¯yú#ŽsÌ1Mñøwòup•l7 =ï›fÅ3:>´&Î4Š‚† ô=gêA+Š}'ŠMiØì¤lE;ˆàfPÁ…£d‰Öf^,´‰¸»úvs{}óýî£~Íý µI°1ä—[²3…Xõïn=ÐòmàŒb‘¡ÇóóvlNÜ®ñô÷q—T.a ¡ž"]âLoÅ™DÏpYÉÇ>ôÖe¥»–eõ ´ˆâ~§.Ï'Nc;ðxî£äv¼ÀJtxÒ§ï­>&2gâMw"ƒeêVHˆufˆ–3Ž›qÆŒb‹Sq#u* FgyñPTÐÞ 4Èb‰2¶î pr8Ã9ª‰ä¬–Ï·—¬N—¥Sz{‘A޶Èjv¬|B µÆoV÷†ûB}n}î^»ÐGÄbûI^µlµl0Žcí :®YÁ…N”¾{ûþ‰¢ŠšÜ)"pgË=ñòê6Ñ–ÀiÍ •ãí[…äŽl}•l“‹µà.«0]Ô«ß*-ÅŸ‘bÎUí蕨߅ѼXÔ÷eOãѬTrT2FLûN<|ÿ0‹%&$ee‰h&^ö'B. Šøãæ÷˜ çÉš«*ïFÙÜùÂØSò‡½QoE¹F+ÓhD½iYÛÞ£xiÃ^é§k GÅYÅL§ËD;=¯6×Y²í|¸‡²g[UR$[mNÙ׆aê¸jâ¬çT¯sþ ámø¾£™=ÖWï¿ õI»o.¹ê(ŸÈå…X¼žÌ‰ÿÐÊuò4ôþ`÷­e endstream endobj 1248 0 obj << /Type /Page /Contents 1249 0 R /Resources 1247 0 R /MediaBox [0 0 612 792] /Parent 1246 0 R >> endobj 1250 0 obj << /D [1248 0 R /XYZ 90 720 null] >> endobj 1247 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1253 0 obj << /Length 764 /Filter /FlateDecode >> stream xÚ­VKoÛ0 ¾çWxÍ%9X¶dù‘=´]:tŠÍmÝA‘åX¨#–œvöß'Gràt^Ú= ¢hŠüø‘¢½Ð|¡·½4ŠÀgÝNB§}œ@'ùÆÀX\­&ÁM =‚E¸€ÞªºXåÞ—ÙuIjÍš¹EÑ,;Ÿûdzå3ÙÖ³J*ÅCñ¦mˆæRXe§©˜šûÂ0šÁ,]}œ,W,1B¯€í,~AA/‹$ÁX3yI†Œ°ÅËr® nBŸw=”„#Ï ˆ2dM¦û'† “6N`¯4ñâÙ¥]jÂ…ñ¡ìî‰|³‚–v%yîa׆‚JRRÙ¢ ¯õñ]²ÞÔ®{GHŽ€´"ïXïÄ{Y‘†÷X¸.e뜗dÇÅæ8PÁ7eÛXnJ+sÁµ&ëñÔ™6@ޤïöXÀ4 <¸‡±(P¬ÙdÃ#ÎÏe]3‘ßwò¾¥å'.\ÆgÊaö¼u^-ggc˜~Œašž kKÔ£sV˜Ð®@O%=L;¥Ò¤ÑŽÏžW.JÖpÝŸ[»Š“ª¯i»®IMO¼¨ÚqÿpA«6?¥Ðõ§ŽEvlPM+meîèJ’Ä a¾3?°ïˆAG:ÛüÐ]\½^Z8VZÔ•6E=jGÇhÿܰßvÀzˆÐ‰Bú£÷p:=‰y„ÞåÝ{+Ð(w-Æzb̃ܤȃD8AÝéežC€’…µ4 $A&È܇3Pq1Ь}¶ç&=m²‚ItˆóoŸ?åÄPatûïOºáÁ[Pr©* „|Ýó‘ãUÙ_ŽnV¹`Rh3UÕÖ¼ ªf”œö³TÓ’©·§õ¿öü_ðzµüp{÷‚â·8©#ï¥áãý…¬.4%µ›  ÆV””n°Ú½i/ þ\W¦öŠa†é‹¬O¤wÍšÞ[¾ãJ6üTFœk.‚­l…qƒÓ=Ø4ŽOí†éH„½£¶÷„ÂðÍžºÿ?Ä9 endstream endobj 1252 0 obj << /Type /Page /Contents 1253 0 R /Resources 1251 0 R /MediaBox [0 0 612 792] /Parent 1246 0 R >> endobj 1254 0 obj << /D [1252 0 R /XYZ 90 720 null] >> endobj 1255 0 obj << /D [1252 0 R /XYZ 90 366.904 null] >> endobj 1251 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1258 0 obj << /Length 662 /Filter /FlateDecode >> stream xÚ­UmoÓ0þÞ_6¤¥bqâ8i> 1$І‹„Ä‹P_Vk®SÙI!þ;Nì–¾do°V/çóÝsÏÝ¹Ø ô;Yà$„ ,Jr> ¬öz„­äioÃâe>ò_ÇØÁÊ‚ ;yµé"§Îg§éØ S­sO+WLÀØ#$r—a·WBD ã¯ùÛÑY¾‡áh:‹=8;)Ê&“¨CƒqŠRg’4I"èð¿?clœt€ E8r¼P3 Ñô(SÅ”Ãó~Gw0{l!ô;šJÍ[4Y+u>±{ ²1RA—LÕ’6ï”J‚dÛ¹¯¦Lø”-<‚JDo§+€Âˆlã|<&Ö mºçL\+K‚®B˜íàäuYp¿Û”j6öpœÄ®÷B A¸7\Û³œMýyÁøÞÙ§_ô¢XzÅæMÛ‰o äd¯ÜñГ4óð‘ûe' ¬©KÔf7Ý£Y.‹ù´0"…ªh¹myMÁH€*#6µY§vKAƒzPoý2'}hJ_ͧ¨¬E5”ÕXð¢„Î̓$Œø‘53«œDÑÁPøß¦ñoã✉ö‡å¢hlŽÌ殫þÓfÝ´ Fí„ ºÇR±{ ,ô Õò["çŸÖ%`‚5¬ÇFQ73ß™Z±ÕáµzàLoò®GéŸ,‡ˆ?Y,@Ð7Õ»ú²-gçýeÛs­‹ b¹÷èâ,÷°~˜×W—¹_£ÀׂFÖIäh»H7Ö(¼»FTÍ—Ï,;’‚dâꟙ˜Õª¹±ßK¸Š>®&èÝÙŒHJî1³ºå¶£fÅVãÂv’†Ê®Z «öã jÛ¬»£žt7Óœ}6Â}68Eª^ÓÑý‘þ&}Ûm endstream endobj 1257 0 obj << /Type /Page /Contents 1258 0 R /Resources 1256 0 R /MediaBox [0 0 612 792] /Parent 1246 0 R >> endobj 1259 0 obj << /D [1257 0 R /XYZ 90 720 null] >> endobj 1256 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1262 0 obj << /Length 776 /Filter /FlateDecode >> stream xÚ­VQoÚ0~çWDô%‘'vLHú0imaí61iåaÒ¶“˜Æªq¢8TEÓþû.±a¤0º©…‡˜óÝwßÙw_ÀN_줡3Ž"”ÒÄÉVƒÐZïØ®|pð÷<.æƒ`:ÂQ¦Ø™/÷!æ¹óͽ,XÕðÚó£(r“sϧtäNÙª’ܳR}1½[׬¥2ÆÖ"¹ö|‚q¹8I½óƒÉ|ÇeDÈ3d[¶v”Æ1mÉ∠”`'N(Â5ŒßUWùÍrVÞ®³â“PÀsDFî0Xë:øŠñ—8b1l A"Ч± ýÕÙ|ŠÆáØñ œ PèvÎzÞxkì€? )ÍŠ)Un„º3¿V\kv‡p˜ÈÀÉóÓ„¼É‚¬.Ê™›@7Lå¬Î·P]ˆeqÍtqY®V\5m±ú²T jGc¨y¶®E³«Á–Œá°_ó‹?Þ‚#® .eÌ¡6}Þy¤ˆbÚgq]‡á¹ÙíH’>È©‹™ •²ÌXc[ g [0ÍÇìS´ÉMÏ,„ ÖóܶO"4Šâ'TÎÎNa8™]™E¶DR¨õã_{åi¼ÉLǤ=–ˆÆ¤Ÿ$(NÆ6¦RÄRx>vѲæ|¡sÓ1ôYû Û-Å›…†;Ë t_ZK¬.L½$rêâöêùÏL{âr&c{5‹o¬‘º¬¶º¡× q&¸ò ¬‘³¯ÅJHf§)ͳ`­ÏƒGÆ®fÚܵšcìËÒ"0)‘)§§æœp„bš¾R·ÿïÝÕw÷Ю}óèX· ±F…(µ,‘*ÿ¹%Lè¼Ú¢ iû>3’`í»¬ºâ™XŠÌüªX“OÔ ŸnÁ×9°ÎÐÅäýͬw¤ÏäÚŸy˜Ã{+Gº„¤}†"èª,Aó) C× ÃŽB7x`Û# :!’–4™. fø'x·q:¶âµ<ˆÝŠT·y,¾u€w^ á͸‚7Šíº€nvæ­p¤þW¹ööÀoâ5 A endstream endobj 1261 0 obj << /Type /Page /Contents 1262 0 R /Resources 1260 0 R /MediaBox [0 0 612 792] /Parent 1246 0 R >> endobj 1263 0 obj << /D [1261 0 R /XYZ 90 720 null] >> endobj 1264 0 obj << /D [1261 0 R /XYZ 90 358.057 null] >> endobj 1260 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1267 0 obj << /Length 744 /Filter /FlateDecode >> stream xÚ½VÍoÓ0¿ï¯È:©´8v’æ£R/”MBPHÀ!uÜÅjbG¶³®Büï8±Sš­Û€!¶ƒýžß×ï}¥Èú9t’0Y”:¸>ƒ–»=CöæiïHâíêÌ¿ž!AÁ 9«Í±‰Uá|qQ§^jž»ÜvK™za¹wAw†® "Ãdúmõþìjup6 ‚¢é$…"'YG]4¥ uâ4(ŒL@Z9ïœ9H³m'Ðáë³ö[)|U7Sm}æÖ¼ ”$‰!ùޱœ+CçXQÎzŸWUoÒÙ ŒÍ‹×þõ¦á8PRPõ–Áï §ëů|Éëš0 ƒ·¢¿TºLÒ\7§,©Ö&G•ÔÊäŒñ=e·†Â¶Î^E·dÅ ± º4Ä®¤¸´| k¸Î©ˆÜ±7×"ߟŸŸŸ6|œ(›…ïFË' ûXp¦òõ©|Þä²´YùС_v’”PM Ë~rÊ틪;B¶«[kFùPÙèþø_-gbÞìM·)¢pœÀ7_á Ö¹TDô}©IÔ'½”)œ7W´ï¹Í [©£÷£‘ƒqp#Oÿ ÜŹό–,IUa]”\7¢œEã(n„ó_¯³±I¿H*º&÷ûǹ" m }ë“`4Ö”ùu¾%»2WÃxõ²ÌÑOlÞ“ŸúwäÄ6^tAö(O'7ÀÓ#yõñÝ0Ã`-‹gglÄ4žüë$è6QÅA·~»ê¥zOCèØzÉ ýA˜Åv1õ+u)HwwÀœif˜èÝÒ*.h^«£nl† 8|e?ü>>“•Õaã6ß.I4KhÔŽo7 ’ÅWàˆ@“q>‡eÉÛÊLë† u(ü­àmcñ•úÛ<ìx+ÝJ2Â.•h±j¹–>eãD_ó˃o½ðÙåÃHžêaïòaG1%x5~Müu,$ˆ endstream endobj 1266 0 obj << /Type /Page /Contents 1267 0 R /Resources 1265 0 R /MediaBox [0 0 612 792] /Parent 1246 0 R >> endobj 1268 0 obj << /D [1266 0 R /XYZ 90 720 null] >> endobj 1269 0 obj << /D [1266 0 R /XYZ 90 241.375 null] >> endobj 1265 0 obj << /Font << /F51 5 0 R /F31 21 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1272 0 obj << /Length 469 /Filter /FlateDecode >> stream xÚ­”M›0†ïùHÛTÂH¨TUj´=Tê ©‡ÝÕÊ5Nb­?ÆÚäß×`%-hWUá`3̼óxfGÈß8ªP´&Tù&bj…&ëË O»Ô;¤W_ëüVà#P¡ GõîZ¢n¢‡x{ mÏ»$%„Ä›OIšçE|¤ª•<™Ñç{×Ñ^ŒƒEr›¤ƈĸÂÉSý}u__XŠ,{vðø‹–àhª²ÌXœm@†ó¨\P®ó@ܺ_R°Ä‡ñç°<¢…t¶ƒÒ0*aðÛ‰sò)}ö4óñéGA*•±ýó{uƒûÛê8¨³]çôÖ(Eu³$.Ôüè,t T´{̨ÖÜöŽñ)»X:ÈzÜ­9úd’aô‡HZÜ×øúî_¯Ùú6Jô~²p±.â»ÝtaÝwTûwCTF@AÊÛÐw(õÈ;Æ|œ+óèyÓÉ« 8c¥Úœm{íÀ³Þ¸9pÈ{[jík3+4ƒq)€ÿäòòb£¦ÜŒê°áG> Ûq½š‡§Ž+Ósyú2¯¶tüëQ[<ýØò¹ZÿŸžO< ×§w·Ú–3Aå™WÍO¯¦“ ðsþ±üOù? endstream endobj 1271 0 obj << /Type /Page /Contents 1272 0 R /Resources 1270 0 R /MediaBox [0 0 612 792] /Parent 1274 0 R >> endobj 1273 0 obj << /D [1271 0 R /XYZ 90 720 null] >> endobj 1270 0 obj << /Font << /F51 5 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1277 0 obj << /Length 120 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h CK#M]#  ˜†sZj^zf^ª¦®±±‰F™ˆ6Ö(JMK-JÍKNÕŒ ñâr [fjd„Ý5T/%˜ endstream endobj 1276 0 obj << /Type /Page /Contents 1277 0 R /Resources 1275 0 R /MediaBox [0 0 612 792] /Parent 1274 0 R >> endobj 1278 0 obj << /D [1276 0 R /XYZ 90 720 null] >> endobj 1275 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1378 0 obj << /Length 3588 /Filter /FlateDecode >> stream xÚíKoÉÇïþ ° ¶¦_Ó3|ðcØÀ ‚¬w/IŒÈ‘M˜"µ$å¬ä»§‡ìf×ôTuK+±È²åR»~ÿ~?ÄÏ û‡ŸÕÅ™‘’Õª:›Þ<+Üw?<ãîok0/ß>»ü^ó3^°º¨ùÙÛkèâíììoç¯Þ7·Ûv}1‘RžW¸˜(¥Ï¾¨Ôy³ž7W‹¶ûuþÃrÖþz1¥®Õ9¯åÅ?ÞþñÙwo‘µ™ÖY >›gÜ0ÁµrŸ­¬ãRí?ÛÏ5üF»acïT1©JÑý¨-·4Lêzÿ“¿ÛÛH~V±º,•3ášÉÒôM*`R2SuxgÀ.&ÜðýÑûWê›þG~óÿ/R‚¨ «¸<+%gªØ¡¶Üý'Pƒ·š³"À»Úa|±6¬5ŒˆèÏ[ "ö…d5¨ëŠéJîÃ}“WÒ7/tѬ§ïíWލªÓ¼©GY%ÄbÓm[2'`FŠÅÛì’ÍKJ,ÀUJ,qÄž:­Á ¥®æËM»þØ® 5èŠUB>-5<ìCPŒ]ªrŒƒÍf=Á8¸J2Ž"—« d<]4› UÛmãÁʼn×vJ.“9 3ZJBÁURQÄTÍLÑ“Àj±ZŽx¸\&sf´ ^‘®’ˆ"$ÐQ•= PM¼P¬ærìðï/ —Ûœ(‚- ˆ)!Šà*)Š(â@ÂN:J(ŠY³mÇqào#¸|æ„Ìh!@4‰"¸J !Š8/¯{B¸Zür·"Å õ1Ý7)Ð._9ÐÁŒ SŸ¨ñÁUtqºÐÖ°zµX4TW 4BçûUo—¼õ`FS‡Ôƒ«$õ(bL]Õ’UºOý¦™/Gê÷ î“—¡ÌHê=t£\¥¨ÇÔ+ÁÊJê×Íôn±ýDa·#HmN;ÅÛ¥-Ç;˜Ñ¼!ïà*É;Š8àm¸¸õxÿò~µÙ޵ü>µÜ%/G=˜ÑÔ!‡õà*I=Š8 nçþRAê æã>/—Ïœ‚-ˆ&!„à*)„(â@¶ýæ a~ÛÌfë–\ë;Ùµ\Ÿªã`F3†Yç†d\%GŒí„¾( ãÅõ¸Šó™ú}—Ûœ(‚- ˆ‰ÝWIQD¢%«$5°¶©FI<¸¹p Î)#˜ÑÊ€¬Ê®’ʈ"”Á5Ûý렌ԚθËdNÁŒ–„’@p•”@q B1;QØÌÇ%ÞG´.Ÿ9!3ZMbè\%…EŒ… kɤè ávJõ5Sªu_öYÍȘ‘rè¢Ûà*%‡8â@•`\÷äðiÓÌnÆÅ‚{4>y9êÁŒ¦9Ðp•¤EP7«+H}Û\Àc—Õœ‚-(ÑWI9DrÐõ.*Ãü¦ý÷j9nûá ]¾r ƒ ¦>Q$è(â´ªX© èíz3'[{H.m9ÞÁŒæ $xWIÞQÄoi˜2÷§–ÜäGýy!¸|æ„Ìh!@4 !WI!DB%“…¾»iæ‹?5¿¾™/ÛÍ-˜’ÕZ?u-P]2rƒMæ•^Ú®’£ˆ¼ˆõ‹ZÙ ïî|›?Ôÿ-z=¤ÔÏò*±d¢ÐgÂÔLTœÔÐÞjÌ õ]í5T"¾R"ŠC.†eX)œ@&y M^_ØŽFž¯n·v¤€$Óâ¨/ÅDŒè &¤`‚¼îáŒ&Áj(¾#êfP7›«‡ñwFÉp}G»p¿§ZÉtá|#™ŒÖs´‹&É©Lºpq÷ÃÅÝœœîòÜdH•¶Uã'1Ç)+&uåSIàwF“`5Äßw´Kx=çôQ †ß%ÃõQÚvMn²p‡Æ;­ïhßt+ZÜÉÒÄÝ7wQ³š{u¿ÁÔÍmõ®Ç®ýÁÓzÓ%8'‹`Fë²â\¾’ʈBÆÒàuÅŒòÒøóØ_ãýµOS¦ÃfdÝË8ÝeW©>;1r•îµ3EôÝv:`ßU¦ãÎÑK8Ž8pÕµß^¿æ$lsRˆ“k鈆Ëç.Óp3²áêaà%9¾’Ô£ƒÉךÕþ<ËOFØôº]¾›/[¶¾Á²•uu”º Ø«‚i]eÙ3š½³q£™šd|%ÙG!‡ì Íü‘¹Ë<úËv;½ìµ²éjy-lfJu$ð ܵÀ$ í`EÂv&¹z<¥PGñâ¶½[‘ð‹d—›õ¥¯Ä—«»ííÝaY+ûׯ»'¹Âf+’Ì/%E(xJŠâõ뢴¯ ?+UÉŒ¿þ‚¨‘ÖDºÙ<ÿBSì#›„Däº ;²{¦`…¤Zng4V¥DŽöSl=xÔ¨L+ ãa9«dÀØ>ÕEŸ1™z«LÀ¾+×5ìá¦Lùº‡›âP=qj¯˜puàjµÞ¾êžÉh7_èàü×-õ8Í\0Si—"‚«³™Œ†T{nöó "õ.H ½8΢´c׎¾˜N[ sö²½^­»Ó ±ú96À¾ºƒÌ‡¼»”ä3!Ì®P(Äà†ÄEBAj;&Ð~ªÐL‰™áç8®tÜÝGçó™Q0#UÐCS£U¸¡TGÂU°»ýh  žã‡*} £ÏxœÅw¦>…™~˜‘ýr—胊ÀI> …“7«üzÔžü¦ýå®]N[|2XÛZ8U‘]br9˜Ñæï“g Ç©kVp·íýb6£‡YŸãÚSjÒ)Ì.a9ÌÁŒÆ s?\ÚÝanHÌQ$³2¶¥Ì?,7Ûf±Ø=†zÚµÖ%&‡3˜Ñ8aŽeâ nHœQ$§ÔvÊéa³ÙÍên¹Ý|¡›O…þ@È¥-;˜Ñ°!Y¢°ƒv ‡-$Sµk½Ã*,×̈ñzñýáN.µ¹1X0£Ç`±6üŠˆBáŠàœ•þyêfѮѺ?ÎÁîÝ ¸|æÚ…`F· ,P7¤ ¢H¨ T]³Jø¡Ûb±ú×O›vM ÝJy ÍQÍ}¦2Õ˜‘Õ¼—t®Ñ†ø¡Ç¡pÀ• ×^ÜÍæÛùòݺ*þä+:Qµ}3U˜‘U»‡C¡U¸!ÉG‘ð= ¥ ¦;®ù2±äL®šé‡»Ûç_è>ɱô”Fºe*••ÈÁŠVÈÞd—é]… NH}ôÃà ƒ¬(ÜšýËùrövõÃrÛ®¯tÆp¦žTû€ïÔùR§wꀵS×KR‘Ýöð”Ú©KŒ]¥wêÒ ÝT2`ßU²›J—o'Æ(®F^0îŸÐ8üÆl¢ºƒµG5 ‰•ZUv"&)!¤ê¬&Àl¨ÕÈ•;êHµ_Iµ&BÆ®2jM–1¨5°ïÊ•]ðÌ”K'ªVYWLú‹µŽ ždïè–éÙ?ör/†¸¡0Ç‘pÌUÉlr˜×«f6m6Ûq…,Û¥-;˜Ñ°!|O ¸!aG‘pØF1ÿ:ûÕ§›f;}?nF>h3Òe0Ó–+²)‡(¸ä(õƒz?>Eê.[ ‡ÿU~Š4½f·ë–8´zê+$RØùf‘]f´œ;1‰væÀ©(^ñm̲t«m¯¾ñæÍ«7/~üñ»±cbvÞ}4ï-fHûÂù|PS¤½Õ˜!s¤¾+7& ÇìÞ6®ÐaçÞ*1vE ;}·’,bè¡R#Wij;¡¦‹·j ª¨»·!¹o‰æËÛ»íæŸîÙ—S;øæ“‘AÌH„½¼â a GXÙ¯þÀéõzŠ?é*¾¶£[žu…Oj¦ßfd¿ÓãƒÜ¥Øi!ø!µ…µ`¤m²ôá·Þ.ßÝç0«`Jˆã¼s¨.1¹ªÌèª sŒŸinHœQ$gÉ™äÆãl§6w7¯›msÕlÚ“k]2rƒæU¡“à†DEÂÚ¼ò7&=¿ܭÑã¥dòHß¡ ºôä 3*Ì45¸!¡F‘p¨vŠW*Þ‡úÓm÷kñ6§ÚÀº”ä@3$Ì.2¸!AF‘pB³Êߢ›v ýÓ–cíìH¸ôä 3*Ì4~. ¸!¡F‘p¨\Úïiu¾˜-æËãJ:Ù%,‡9˜Ñ˜aî ÌÁ ‰9Š„c.ãþ¡²é zÈ`œ÷Qu¬¦®õõ‰Ì4äÀŒlÈ{Lx0~HþQ(|÷ŒKnUâÆ‰¯ó»g³ùºnWë9~ÿñ/Ñ?Åã>‡Šk“jòK&ÀŒnœMb`܈"ám€íñ+?‘ŸÍ7Äe0©™0òd_Ÿ÷ûa>[™­5`Fn­õ0vûaÀUjk-1v•ÞZK1È80rµ hÐÙâídEBe\sVøUŒý/ÒÆD\to\ø/ÌñúsË(9X‘B†©G®);ñG)'ÂEŽÒ"Nî áT´¾£ý`Upº`€£0¨~áS¯×Ÿþz7¾§ñ˜¾8ùð×âá¯ÈQ‚?öæ×ÿ_ò( endstream endobj 1377 0 obj << /Type /Page /Contents 1378 0 R /Resources 1376 0 R /MediaBox [0 0 612 792] /Parent 1274 0 R /Annots [ 1279 0 R 1280 0 R 1281 0 R 1282 0 R 1283 0 R 1284 0 R 1285 0 R 1286 0 R 1287 0 R 1288 0 R 1289 0 R 1290 0 R 1291 0 R 1292 0 R 1293 0 R 1294 0 R 1295 0 R 1296 0 R 1297 0 R 1298 0 R 1299 0 R 1300 0 R 1301 0 R 1302 0 R 1303 0 R 1304 0 R 1305 0 R 1306 0 R 1307 0 R 1308 0 R 1309 0 R 1310 0 R 1311 0 R 1312 0 R 1313 0 R 1314 0 R 1315 0 R 1316 0 R 1317 0 R 1318 0 R 1319 0 R 1320 0 R 1321 0 R 1322 0 R 1323 0 R 1324 0 R 1325 0 R 1326 0 R 1327 0 R 1328 0 R 1329 0 R 1330 0 R 1331 0 R 1332 0 R 1333 0 R 1334 0 R 1335 0 R 1336 0 R 1337 0 R 1338 0 R 1339 0 R 1340 0 R 1341 0 R 1342 0 R 1343 0 R 1344 0 R 1345 0 R 1346 0 R 1347 0 R 1348 0 R 1349 0 R 1350 0 R 1351 0 R 1352 0 R 1353 0 R 1354 0 R 1355 0 R 1356 0 R 1357 0 R 1358 0 R ] >> endobj 1279 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 631.408 297.029 637.186] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 1280 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 582.468 297.029 589.442] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1281 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 571.298 297.029 578.272] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1282 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 560.128 297.029 567.102] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1283 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 548.958 297.029 555.932] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 1284 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 537.788 297.029 544.762] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 1285 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 526.618 297.029 533.592] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1286 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 514.202 297.029 522.421] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 1287 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 504.277 297.029 511.251] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 1288 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 493.107 297.029 500.081] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1289 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 480.692 297.029 488.911] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1290 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 469.522 297.029 477.741] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1291 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 459.597 297.029 466.571] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1292 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 447.181 297.029 455.401] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1293 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 437.257 297.029 444.231] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 1294 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 426.087 297.029 433.06] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 1295 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 413.671 297.029 421.89] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 1296 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 403.746 297.029 410.72] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1297 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 391.331 297.029 399.55] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 1298 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 380.161 297.029 388.38] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1299 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 370.236 297.029 377.21] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 1300 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 359.066 297.029 366.04] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1301 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 347.896 297.029 354.869] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1302 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 335.48 297.029 343.699] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1303 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 325.555 297.029 332.529] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1304 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 279.281 297.029 285.059] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1305 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 230.267 282.182 238.038] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 1306 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 230.267 297.029 238.038] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 1307 0 obj << /Type /Annot /Border [0 0 0] /Rect [268.358 219.346 277.574 226.868] /Subtype /Link /A << /S /GoTo /D (97) >> >> endobj 1308 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 219.346 297.029 226.868] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1309 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 209.919 297.029 215.698] /Subtype /Link /A << /S /GoTo /D (112) >> >> endobj 1310 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 196.757 282.182 204.528] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 1311 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 196.757 297.029 204.528] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 1312 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 185.587 297.029 193.358] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1313 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 138.565 297.029 146.336] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1314 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 89.626 297.029 96.6] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1315 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 77.211 297.029 85.43] /Subtype /Link /A << /S /GoTo /D (163) >> >> endobj 1316 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 628.295 502.545 635.817] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1317 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 628.295 522 635.817] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 1318 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 618.2 522 623.979] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1319 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 605.615 522 612.589] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1320 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 594.525 522 600.303] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1321 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 582.687 522 588.465] /Subtype /Link /A << /S /GoTo /D (133) >> >> endobj 1322 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 568.856 522 576.627] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1323 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 559.011 522 564.789] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 1324 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 547.173 522 552.951] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 1325 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 535.335 522 541.113] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1326 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 521.504 522 529.275] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 1327 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 511.659 522 517.437] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 1328 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 499.821 522 505.599] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 1329 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 485.99 522 493.761] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 1330 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 431.847 522 439.618] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 1331 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 420.258 502.545 427.78] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 1332 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 420.258 522 427.78] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 1333 0 obj << /Type /Annot /Border [0 0 0] /Rect [488.722 408.421 502.545 415.942] /Subtype /Link /A << /S /GoTo /D (114) >> >> endobj 1334 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 408.421 522 415.942] /Subtype /Link /A << /S /GoTo /D (115) >> >> endobj 1335 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 398.326 522 404.104] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 1336 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 386.488 522 392.266] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 1337 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 372.658 522 380.428] /Subtype /Link /A << /S /GoTo /D (131) >> >> endobj 1338 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 318.514 522 326.285] /Subtype /Link /A << /S /GoTo /D (165) >> >> endobj 1339 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 306.926 507.153 314.447] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 1340 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 306.926 522 314.447] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1341 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 294.839 522 302.609] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1342 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 284.993 522 290.771] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1343 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 271.163 522 279.382] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1344 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 261.317 522 267.096] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1345 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 247.487 522 255.258] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1346 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 235.649 522 243.42] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1347 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 225.803 522 231.582] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1348 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 213.965 522 219.744] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1349 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 200.135 522 207.906] /Subtype /Link /A << /S /GoTo /D (134) >> >> endobj 1350 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 188.297 522 196.068] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1351 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 178.452 522 184.23] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 1352 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 166.614 522 172.392] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 1353 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 114.717 522 120.495] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1354 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 101.136 507.153 108.657] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1355 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 101.136 522 108.657] /Subtype /Link /A << /S /GoTo /D (73) >> >> endobj 1356 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 89.298 507.153 96.819] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1357 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 89.298 522 96.819] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 1358 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 77.211 522 84.981] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 1379 0 obj << /D [1377 0 R /XYZ 90 720 null] >> endobj 1380 0 obj << /D [1377 0 R /XYZ 90 720 null] >> endobj 1376 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F38 1381 0 R /F2 1382 0 R /F102 799 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1465 0 obj << /Length 3924 /Filter /FlateDecode >> stream xÚíYo7Çßý)ôh;Lóêã!9ìNb(zÙ ÁdÔ’žk{FŽœOö Ù¬f³ŠkE,M#)¥ªéúýY<›âg™ù‡ŸUÙY!%«Ty¶X½ÈìO?¼àö¿fÆ`,¾½xñÕÍÏxƪ¬âgWÐÅÅåÙ¿_òJ½š‰ÒüìåwWõúºYׯfRª—E÷U¾l뫺­×‹úÕ/þñâõEL ‘ø4ÅèãâŒ+&U.ìÇÉKŸTÇóº‹òÕÉÏJVå¹êlÌ3q͸8ZÔ—Íþ·f=o?]5Ëz×üQÛ_)Á¯”9ËD÷9¿Â^ÍxÁ_Äà;ꇟý ñ‡Ý— ņ +¹<ËóŠe\u940ÿ¤ÙYÍ€Ù!Õd$tuHŒR£ˆUa2WÁˆ°ÎjqÀ­c« ó­òäÌ"À”fB¨§ì>ÆÛ¦-ÅÛ›á¼!™£¼½+’wqÄ[å¬â!ïxí\Éâ¯!ÿbn!ºçìó€´V3`6¸:‚ÔcéÆK#Æ@Z+:bàêño¨VéGìµJºJÕ&ú{­GZ•š•®e¼6Zýe»löSmJÕ&›¶oo†ó†Jòö®HÞAÄo¡LTÇ{5o–?ÎïÞ™ñN¬?Ê%’?“âdÿߨyÆL÷yÁ€­fÀ,tèê8²Ì%JÔû"‰!GD¹dE?ºXm÷Ÿ"$ÊhíÉ ?ÖÀmVS Ü›á *ð‚î]‘r"Žä Vønäp^ï6ËßmÖWa˜~U™ ÊóÆÒ¦$ÅÒ›á,av‰ÎÙ»"YC–ºâ,ï;ç»År¾šï›Í:6ŽTÌx|þ½3‚Øe*˜¡ˆIÇWâ0âq™±œk[½ âÛËúë_Y2Íʼnp ¾Ía ¾7ÃáCUÂ÷®HøAÄü¼b:ïá׋XÏ1óýÔqfÍw©Mi› ”¸@5á]‘š"ŽVu×Ô?†{“\ |Ó,ë×wûz½3Ctož¢¬ž—‚0èBšÑ OB÷f8tksìJºwEB"Ž L6¶:(r3½ÈŸÁlìAÛ!—¹ÄÚ0C×–"‹„vA¸¢Ö–Ȉ+zm)ñˆ½ªÉ€CWÇî ]kHãa—ÈÄx˜¡ãáž¡GC€/RAÈQ¯" ÍTnãýìUn6«zZ|¨EA™›¼©dåfhåp6ÇÊʸ¢dF +‡4£IQq¯‰í|ofÓÈFÏõs.HQp9J`†…Aº¹@·€/’nrDW–L8-ý`è¾§èžò6ŸËTª{3¼ä+¼{W$â â±(‡ xW·ëv75`ЀmŽR Ø›á ¦›gèò=ðEÒ BŽzuQåš=Lþ–èÕíGz{½Þ´õÛµiåWóE}^_×w)Tšeå“XC@Ú«(9ËT‘j¯À m¯ÎæØ^Ñ’ \QDÈa{yŪÊFkVÛM»Ÿ†ê÷iÔ.‘‰F ÌÐF=`Â9º|‘BŽ$ Í·NpÍz:™qŸöos˜jÿÞ oÿ~2¸"áGð•‰Ú·W§_™¡œ|¹Ø¬¯šWüåõm‹ÆâYÁ %¿”Ê€µMû©¶éÍð¶ óÅ9º |‘x‚#<2g¥Cßþ4N–sɤΟeÅšMOªÙy3¼ÙÁLãç €+’kqÄUhV8½Ý}ß´ÿÉtfþå±Â+YUTÓ*%›Ï”¼.ˆF Ç"+RAÄ‘Ìøºèøî]³þ@)aê‚q ØL¦$àÍp @(„¼+RAÄ‘2ÉòÊÍ©v?Õ¿×íÅÍ|Mèà+½MRŠ®7ÃéÂ|t½+’n1¤Ë+ÁrÕÓ}¿œ7Ùéí3HÝ%/A˜¡ÔpêÀE=Œ8Z(áyÆr!áÞ%·?–Ó¦úcmªsÓ¤t&“òf¸†¬Mb¸"5DU©˜ÒNBóÝþ—º^Oƒ‚Ïê6\Sð½âP ß»"áGð»ƒÔYÿõݶiëo®âçK«Œiý”ÊÆÌ>zŠ™7ÙÁ,̼+’YqĬ;&Ü7Øï}÷öÛóoÎÿùëûo.~8Ñ7]JR,½ÎfWâÅ×»"YG,»ó¾N9K3+›'æ}zä°EF|º¾å³÷˜íHQšÁ[•%O‰3tÐélì$^F¼T:A¨hUÆ”»)q;_|˜_G‡ Óæ^4\E˜¡Ec€#¾Ö Ü`äÃHqòEÅ2÷" ¾Ÿ3 ÅÛ¼Ka¢Í3´Íh møAÉ¡âäó‚ÙYæöÃõêºýzâþyÜ LQwF8sÏËè2Sïå=§­»»p]Çßnõn?E4íÞÁ¢nÓ–*êÞ /êRÔ½u)[)VH»W¸½m¯£W¤NG@ÿß# .Ÿ)x3\M/ðÞ ª‚ R|> ²Ž°Fœ§çÑ€gLfÓJ"¡ûº!7_4z ¾{oXaï-:lÊhOÔ¹D*`èŠ>—H?`ßãч®¨qNâùºf†ŠCÞý <'ñóùúr³jþhÖ×Çkƒwûv¾¯¯cg¢+ŸÒ_ôT#e9EÊ›á¤`ö¸Šv[ÀJ*'Ud,/lmlëÅm»C¶ì¹:…Åk¤ÎØ,%ꌷBë L7Qg¼'²ÎCW‰:C> W/p芬3ôóÔ„Š«WWLÈÊ©w»¸™·t?ò3ýënŒä2™n3t¸5€_ŠnPþA¤8ÿîvôÌÎäÎëíwÿûò·™Lñ÷f8E‹(ïåDŠó—9“…píÿ·M[_Nk¨Ÿµ†êr˜"ïÍpòG|º Ü äƒHqòÝ›,ùÝfùq·ŒÇ-6K‰q‹·BÇ-0Ýø½.À9n!†®ãòý¸… 8teÇ-ц‰ç;¨7W/7“¨L¹~ËLˆšÅ¾ŸÍÝJaDÍ¥>\“õäÔŒU›…Tåñfxå •Ñ-_àeDг3ÍÜŸY?¯÷·íz÷¯ºÝ<òmüOã>©ž‡MR ­7ÃÑÂ|‹èb=pƒ¢ "EÑVfÊá^Èi7ûù¾þzMÞg4i™ ï­PøHeï`èƒ0Qòð6Ãöî²iwÓâý_¨ìä-“=â–ÉÀq’'vÁäŸDH­É endstream endobj 1464 0 obj << /Type /Page /Contents 1465 0 R /Resources 1463 0 R /MediaBox [0 0 612 792] /Parent 1274 0 R /Annots [ 1359 0 R 1360 0 R 1361 0 R 1362 0 R 1363 0 R 1364 0 R 1365 0 R 1366 0 R 1367 0 R 1368 0 R 1369 0 R 1370 0 R 1371 0 R 1372 0 R 1373 0 R 1374 0 R 1375 0 R 1383 0 R 1384 0 R 1385 0 R 1386 0 R 1387 0 R 1388 0 R 1389 0 R 1390 0 R 1391 0 R 1392 0 R 1393 0 R 1394 0 R 1395 0 R 1396 0 R 1397 0 R 1398 0 R 1399 0 R 1400 0 R 1401 0 R 1402 0 R 1403 0 R 1404 0 R 1405 0 R 1406 0 R 1407 0 R 1408 0 R 1409 0 R 1410 0 R 1411 0 R 1412 0 R 1413 0 R 1414 0 R 1415 0 R 1416 0 R 1417 0 R 1418 0 R 1419 0 R 1420 0 R 1421 0 R 1422 0 R 1423 0 R 1424 0 R 1425 0 R 1426 0 R 1427 0 R 1428 0 R 1429 0 R 1430 0 R 1431 0 R 1432 0 R 1433 0 R 1434 0 R 1435 0 R 1436 0 R 1437 0 R 1438 0 R 1439 0 R 1440 0 R 1441 0 R 1442 0 R 1443 0 R 1444 0 R 1445 0 R 1446 0 R 1447 0 R 1448 0 R 1449 0 R 1450 0 R 1451 0 R 1452 0 R 1453 0 R 1454 0 R ] >> endobj 1359 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 667.021 297.029 674.792] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 1360 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 657.964 297.029 663.742] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1361 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 645.171 282.182 652.692] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1362 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 645.171 297.029 652.692] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 1363 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 633.872 297.029 641.642] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 1364 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 624.814 297.029 630.593] /Subtype /Link /A << /S /GoTo /D (163) >> >> endobj 1365 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 611.772 297.029 619.543] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 1366 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 600.722 297.029 608.493] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 1367 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 591.664 297.029 597.443] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 1368 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 580.615 297.029 586.393] /Subtype /Link /A << /S /GoTo /D (97) >> >> endobj 1369 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 569.565 297.029 575.343] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 1370 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 523.421 297.029 529.199] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 1371 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 510.627 282.182 518.149] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1372 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 510.627 297.029 518.149] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1373 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 501.321 297.029 507.099] /Subtype /Link /A << /S /GoTo /D (101) >> >> endobj 1374 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 488.528 282.182 496.049] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 1375 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 488.528 297.029 496.049] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 1383 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 477.229 297.029 484.999] /Subtype /Link /A << /S /GoTo /D (70) >> >> endobj 1384 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 428.838 297.029 436.609] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1385 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 417.788 297.029 425.559] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1386 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 406.738 297.029 414.509] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1387 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 360.341 297.029 366.119] /Subtype /Link /A << /S /GoTo /D (96) >> >> endobj 1388 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 347.298 297.029 355.069] /Subtype /Link /A << /S /GoTo /D (127) >> >> endobj 1389 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 338.241 297.029 344.019] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 1390 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 327.191 297.029 332.969] /Subtype /Link /A << /S /GoTo /D (108) >> >> endobj 1391 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 279.054 297.029 286.825] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 1392 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 268.005 297.029 275.775] /Subtype /Link /A << /S /GoTo /D (110) >> >> endobj 1393 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 258.947 297.029 264.725] /Subtype /Link /A << /S /GoTo /D (97) >> >> endobj 1394 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 245.905 297.029 253.676] /Subtype /Link /A << /S /GoTo /D (111) >> >> endobj 1395 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 236.847 297.029 242.626] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 1396 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 225.05 297.029 232.024] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1397 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 214 297.029 220.974] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1398 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 202.95 297.029 209.924] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1399 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 191.9 297.029 198.874] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1400 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 145.503 297.029 151.281] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1401 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 134.453 297.029 140.231] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 1402 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 121.41 297.029 129.181] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 1403 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 111.479 297.029 118.131] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1404 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 101.303 297.029 107.081] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1405 0 obj << /Type /Annot /Border [0 0 0] /Rect [263.751 88.51 277.574 96.031] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 1406 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 88.51 297.029 96.031] /Subtype /Link /A << /S /GoTo /D (115) >> >> endobj 1407 0 obj << /Type /Annot /Border [0 0 0] /Rect [268.358 77.46 277.574 84.981] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1408 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 77.46 297.029 84.981] /Subtype /Link /A << /S /GoTo /D (112) >> >> endobj 1409 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 668.227 522 674.005] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1410 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 655.05 502.545 662.572] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1411 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 655.05 522 662.572] /Subtype /Link /A << /S /GoTo /D (118) >> >> endobj 1412 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 645.359 522 651.138] /Subtype /Link /A << /S /GoTo /D (118) >> >> endobj 1413 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 631.933 522 639.704] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1414 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 622.492 522 628.27] /Subtype /Link /A << /S /GoTo /D (119) >> >> endobj 1415 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 611.058 522 616.837] /Subtype /Link /A << /S /GoTo /D (125) >> >> endobj 1416 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 599.625 522 605.403] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1417 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 588.191 522 593.969] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1418 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 574.764 522 582.535] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 1419 0 obj << /Type /Annot /Border [0 0 0] /Rect [488.722 563.58 502.545 571.102] /Subtype /Link /A << /S /GoTo /D (108) >> >> endobj 1420 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 563.58 522 571.102] /Subtype /Link /A << /S /GoTo /D (127) >> >> endobj 1421 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 553.89 522 559.668] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1422 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 542.456 522 548.234] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1423 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 529.029 522 536.8] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 1424 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 477.837 522 485.608] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1425 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 466.652 507.153 474.174] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1426 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 466.652 522 474.174] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 1427 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 454.97 507.153 462.74] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1428 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 454.97 522 462.74] /Subtype /Link /A << /S /GoTo /D (51) >> >> endobj 1429 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 443.536 522 451.307] /Subtype /Link /A << /S /GoTo /D (144) >> >> endobj 1430 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 434.095 522 439.873] /Subtype /Link /A << /S /GoTo /D (120) >> >> endobj 1431 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 385.149 522 390.927] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1432 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 373.715 522 379.493] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 1433 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 360.289 522 368.06] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1434 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 350.848 522 356.626] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1435 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 299.909 522 307.68] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 1436 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 288.475 522 296.246] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1437 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 277.042 522 284.813] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 1438 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 265.608 522 273.379] /Subtype /Link /A << /S /GoTo /D (134) >> >> endobj 1439 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 254.174 522 261.945] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1440 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 242.74 522 250.511] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 1441 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 191.797 502.545 199.319] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1442 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 191.797 522 199.319] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 1443 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 180.114 522 187.885] /Subtype /Link /A << /S /GoTo /D (146) >> >> endobj 1444 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 168.93 502.545 176.451] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1445 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 168.93 522 176.451] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 1446 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 157.247 522 165.018] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1447 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 145.813 522 153.584] /Subtype /Link /A << /S /GoTo /D (52) >> >> endobj 1448 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 134.379 522 142.15] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1449 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 123.195 502.545 130.716] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1450 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 123.195 522 130.716] /Subtype /Link /A << /S /GoTo /D (141) >> >> endobj 1451 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 111.512 522 119.283] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1452 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 101.323 522 108.297] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1453 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 90.637 522 96.415] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 1454 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 79.203 522 84.981] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1466 0 obj << /D [1464 0 R /XYZ 90 720 null] >> endobj 1463 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F38 1381 0 R /F2 1382 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1501 0 obj << /Length 1988 /Filter /FlateDecode >> stream xÚí›ßoÛ6ÇßóWøÑfVüMØÃÖ­@¬Ь6ìÁ³ÕF¨-–Ý-ýëGÙ”HQ<²]t>´M¾¹3ïsw}u­Øt¾«æ­Êö;lú¼^–ÿ\ψàšM±æ×Þü|õÓMï™’ùh­bôÙ$™`†(Ä~6¡”>ÛËÖË“gOÒB°Vcˆ"Rž$Íb^Ïw»êý|Õ|gåÊ“ Š(æ§Žjt=ßþ"ƒÿ¥¾øÉ?pÏ/~䈒Ha:ÂüÍebþøMB§šy²# â-4uŒÄ#Z¢‚hßc„{§y`mÑsÕюëm¹<¬ªúm*ÓHC_Ô‡ m–#íd0i?öœ‚¤©$éÀãˆ4cH¡%½ªLatºØ¬×ózÙþ‡L«Út¥í®l{Ó80ƈqýÅS`D†"Rð~™“jæÉ"d†¦ŽëÄŒ€hœ­$šÀåiÐæ¶ÿ–‹Ã®|^oûÎÑgP„PõÙHåªÏÉàê󃞨>g*‰8ð8BLLíØV_Y7•Ùå›C½¿ìŸ- žW'ƒ¹ú‘¦äêL%¹G\ ³-*Ù•î‰ëÓ ×† OŽ«“Á\ýH'êÕ™Jr <†\¹VK:¬×¦úPÆz²BŠÐÇÜ”º]2t=Hwo¸j=S)º¡Ç]%çzXµ//t‡tmrt ¦ëÇ®]ÏT’nàqDW2sÞµ;{s[®VvÈm.=¹…aÓãêd0W?ÒT€\©$×ÀãˆkËŠÚýåíæïïûjS7—1y„ØF*‡ØÉ`Ä~Ð9;SIÄÇbŽ‘ÄÝ5Sõ¶ž¯"t‰F”àûáýš ù?†»@fÞ < ˜` ÞHy¶’)¸¥+.ºÉ«ªß®ÊUU¿»Tù¸Êm¤rUîdp•ûAO4rg*‰8ð8BLbª»Šªö±±Ëœ»„¤ Æ?ç.IŸ>~x«šy²1øÀ4w+‚°"¾Çx«J{ L=~ævz‰}n'Mv0øh‘^bŸÛÇQnc”ìîòÞUÛWå®zs¿P”œÁ.mQ6R¹-ÊÉà-Ê:ædìl%.GŒ Žˆè.óÖûmSîÞG¯ÌÏž±Tޱ“ÁŒý c"­$ãÀeȘiŠë.ö^üòkl*áü2‡~ÄÑóİ j&<˜>‰G4ž­T:„.Gé`v¯‚vSévUÅîw ?“sIk®ƺ€×ªfžlŒ70uÂ+G…4çHî{ŒÑµª´ÇÀ0—Øy)³ÄnôJ: L–¨¡Ñ+³ÄnôJz L¥G¯Ì»Ñ+íph*3ze–Ø×hàqT£²@ w·ºP2¤1}”÷}Ÿ»g[†6ª¹tp28|@ Ng*™ÇQ:´7÷E7‰o7›ÕÕ®\ì7»ªŒÝ&Hô}wó/ŸEŒE'ƒ)úqåà]g*I1ð8¢È$º»ô=4ÛjQmÍ‹ù:‘ FÈ#)oˆ¥ IŽ¥“Á,ýè&X:SI–ÇKÊï_"¼kæËuüvWÞ÷Zïzó3š›(â÷q榓jæÉ"sÓÐtŸ#ˆ ®ô=F禓*í10 B!ÊUn‰V•q84嬔æÛ,·D«J{ LAs“=‘¤—ØnRS¹³nf}].‡/Sóo-ñð-àà-`Š4±Ÿk_-ïâ·œés= Úc¥™X…UH¥†Í<Õ(3CÀ==/ˆ >÷ýÅ^ ·ª¤ÃÐT<÷yѾh!3 ìT‡CSö`/c/½gÖ×¾ôºdrŸòÜì5Twù¼.?lêØÃªLs%g~ÑrÀ¦ÿ+ÞÇ@oU3O6F˜6¯#yg$xŠ“giŸýæ°¸Ÿ¥R€ýÑô·¾hm8sõïdpýûdpQD³ÀÙ³ pÏÚ>ì–·ßêÅ|©ÿO¬Ã\ý;\ÿ>É¢ä|à)Nž˜a’ Kþn[Æ~‰T¨óÃÌ06b™Æ©ÀÆ}„r7x8KÉ&á04•™a’ t=,éphêÔðˆfrz}ÇL\ÅçöãË®F~tö[bn·¿|x¨—å®Ylvåb5ošè5ŠÂˆ=ÈÎ÷E®2»þÂێζ*O¶ªN<Ÿhñyf À¡§h«â’šƒ¶èà­_.0g<ÌÔù=|²]¥‹Rº=y*¨=  ±3Mï|òH¦$Òð ¼KO&B§±—/*–ž(BWñD`æ ®¥í ¿ç/?”»MtZ1iǘ¸¼‡“8§Û±Å„ àï~ô'' NsÚ'i4Sœ0SOÑ hpÞfAó@öÏâe¬`òy…Ë…ÄóŠÐT*b*þÍê·c endstream endobj 1500 0 obj << /Type /Page /Contents 1501 0 R /Resources 1499 0 R /MediaBox [0 0 612 792] /Parent 1274 0 R /Annots [ 1455 0 R 1456 0 R 1457 0 R 1458 0 R 1459 0 R 1460 0 R 1461 0 R 1462 0 R 1467 0 R 1468 0 R 1469 0 R 1470 0 R 1471 0 R 1472 0 R 1473 0 R 1474 0 R 1475 0 R 1476 0 R 1477 0 R 1478 0 R 1479 0 R 1480 0 R 1481 0 R 1482 0 R 1483 0 R 1484 0 R 1485 0 R 1486 0 R 1487 0 R 1488 0 R 1489 0 R 1490 0 R 1491 0 R 1492 0 R 1493 0 R 1494 0 R 1495 0 R 1496 0 R 1497 0 R 1498 0 R ] >> endobj 1455 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 667.857 297.029 673.636] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 1456 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 654.251 297.029 662.022] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 1457 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 642.637 297.029 650.408] /Subtype /Link /A << /S /GoTo /D (142) >> >> endobj 1458 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 631.023 297.029 638.794] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 1459 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 621.401 297.029 627.18] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1460 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 609.787 297.029 615.566] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 1461 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 598.173 297.029 603.952] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1462 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 586.559 297.029 592.337] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 1467 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 574.945 297.029 580.723] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1468 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 563.331 297.029 569.109] /Subtype /Link /A << /S /GoTo /D (54) >> >> endobj 1469 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 549.725 297.029 557.495] /Subtype /Link /A << /S /GoTo /D (131) >> >> endobj 1470 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 538.111 297.029 545.881] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1471 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 526.746 282.182 534.267] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1472 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 526.746 297.029 534.267] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 1473 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 514.882 297.029 522.653] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 1474 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 503.268 297.029 511.039] /Subtype /Link /A << /S /GoTo /D (163) >> >> endobj 1475 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 493.647 297.029 499.425] /Subtype /Link /A << /S /GoTo /D (142) >> >> endobj 1476 0 obj << /Type /Annot /Border [0 0 0] /Rect [258.119 480.04 267.335 487.811] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1477 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 480.04 282.182 487.811] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 1478 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 480.04 297.029 487.811] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 1479 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 468.426 297.029 476.197] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 1480 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 456.812 297.029 464.583] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 1481 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 445.198 297.029 452.969] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 1482 0 obj << /Type /Annot /Border [0 0 0] /Rect [253.511 433.584 262.727 441.355] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1483 0 obj << /Type /Annot /Border [0 0 0] /Rect [268.358 433.584 277.574 441.355] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 1484 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 433.584 297.029 441.355] /Subtype /Link /A << /S /GoTo /D (163) >> >> endobj 1485 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 668.215 502.545 675.985] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1486 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 668.215 522 675.985] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 1487 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 659.739 522 665.518] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1488 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 649.271 522 655.05] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 1489 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 638.804 522 644.582] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 1490 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 626.343 502.545 634.114] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 1491 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 626.343 522 634.114] /Subtype /Link /A << /S /GoTo /D (116) >> >> endobj 1492 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 584.194 522 589.973] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1493 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 571.983 502.545 579.505] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1494 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 571.983 522 579.505] /Subtype /Link /A << /S /GoTo /D (151) >> >> endobj 1495 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 529.834 522 535.613] /Subtype /Link /A << /S /GoTo /D (134) >> >> endobj 1496 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 487.939 522 493.718] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1497 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 446.045 522 451.823] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 1498 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 435.577 522 441.355] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 1502 0 obj << /D [1500 0 R /XYZ 90 720 null] >> endobj 1499 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 21 0 R /F38 1381 0 R /F2 1382 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1505 0 obj << /Length 120 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h CK3M]#  ˜†sZj^zf^ª¦®±±‰F™ˆ6Ö(JMK-JÍKNÕŒ ñâr [fjd„Ý5Us%œ endstream endobj 1504 0 obj << /Type /Page /Contents 1505 0 R /Resources 1503 0 R /MediaBox [0 0 612 792] /Parent 1274 0 R >> endobj 1506 0 obj << /D [1504 0 R /XYZ 90 720 null] >> endobj 1503 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1612 0 obj << /Length 4837 /Filter /FlateDecode >> stream xÚí][o;’~?¿Âó460bš·&{1XÀñœ 2ÎËÉ ì,°ŠÔN„Èj.¹üû%»yë«èœÌ9‰¤ Žír•º¾Å"«È¦W•ùG¯šêJqN¡¯?Uî§ï¢î3#0K$ž¿þéÙ I¯hEšª¡W¯ïS¯—Wÿs}÷nþ¸o·73Îùµþ›™òú®Û,ÚÇýð×›eûéfÆjÙ¨kÚ¨›ÿ}ýŸ~~ŒJÆ ŸÊJ},Å®¨"ŒJá>V­¡\¸>’î³Ã_ ÂEÍì_™§Q•þèOƒ »Ò¤©ká$Œ|Ué‘׉'’i#Ø ›UtøÂFßa?üâ?øÊ~7ö&T`ZMùUÍ"hc±6äë™ÐÁKͱž)pSU=:ŒYl©X“ZÌÐKYÓÉ’°¢„ G™c … 5›-·ŸgÛÃæ˜zBÁ•'V÷¸_u› ý˜ùhŠÿ¾=IŽˆÀ «ä•4(2^ƒD¤f‰X†cU½›¨]0“†RÕD1G»ÙßLÆPÒHvêþV-@ð.,D #4¸¡ªPè‹úº&ŒQýº=—D3~ÐO}^kÂ¥ÞPvR³Dì剪ޓÇySŠH%R‹9”nq¢ª·ø0ˆá‚fp¢Ê1˜Éø3&OLŽf*Ke)‰¢~6{u &-LJÂ|²ü™ä†È0{}L›<üyˆŒ«ýÊ®÷& "¹É‘™´^A„?ÄçîO¢Ì“9ZW O¢.”'ˆIË.ˆ³5ûTšÿÌ ]ÓK]>AÈ÷,áî…`Ô#´®A̽ñ‘±£e¬j³ –Äⲇ,î—«Ýüͺ]f8!…™.N‹ÿ–”Èe«¢1q”ªR⛈‰¯—é=©8DDFÌ¢!ÐÌ Ü„ÛÍÛÕ¦%ۇđq®¸ ´× Mï«ÂOÄÀQ>r; rÔ…‚Œ˜´ +JdÅž–lÚÇy€ÍÅ4øgE꽡׻\iwÙ.‘.n;¯—BBƒCB ` nˆ%ªP¶ -[êŠ4|2[vó~F`ã$¡–:Ë€,•8³-Y(Ž8—âHƒãHŠ¥dFÔ…21i™af¡ÝÌDþ›ÒÔåÊ€m»ØwÛϹiì *v–k`ç§ÀQ 8u9­à‰"êBž˜Ä çá3¢ÌŒ, Ѝ ebÑ0C7DÑ#ÜûÉßu ­ìy“Ü&ŒÉ(N­×àÉûkƒ[ Y@“€Ä»T€éwЃá866=rªcÏ×ëîã]·Ù´ýZk÷bÛ=dªž¾Öœ‘?h àឯH”IE%IÔ„a‚سÍ<¬œßB`‘±"ÿk×nwéAÎaÿóÞ®…ͯ>äŽwЦ9ÁÅ‘¬t_Ûô®Èƒè¥f‰Ø‘W§ªŒuîrœDt9f*h¸¯¹Ï¤6Ë­_Ń7Ÿ{Øöv#whKÙÓââÌ®‘”¥epª“š%bÇ NT riTb:±4Š”TÆâ}3·ífùòþ—î×ÃâݫզíCæ‹U>§a¶ÿâ]JA®wQr}ƒ]ŸúC5Y×G5 ëKÁó”’Zúµêv;·ñЕäÚOó‡Ç¬Ók“Ã4g½|…0vî*aÅ`ŒSÏÓ|ÈŒj@ŒK㊒Ðý2†øÞæ"ø¢¡6÷k¥§±áüUÂ8HÁ'ŽJ@€a3_ÙTDÔ¾f·ëú&¶Åjn§ÀÕ[ÃõÝ£ý]îŠ ¥ §§xpA˜°1â‘GÎKͱ#ŸNU ØñãJ*yj1 “B-NUåoáñ”Â158Qå–C9zÏò³js­\z8߯÷«å :*-Rmíáï ó)µ÷Y!;OÄÀì|äþÌÑúé¨D1®ÍLûìü°\¹&öu÷6‡qeÆÚ ã&#ܹ°4£<ÂS4D•Å=ªqG,Ü¥&µ?›ÓãnkVÙñµ×<ž[ƒI@Ëù°|ƒOáÈg‰ø‰¥ìÒM düišÛþ»Û¶ó}›èJ^PÍ ‚Ù9¬sƒaN}¯óã;ªažXÊÃl[ÔþÔ.^nöíöÃ|9él2Iݱ4>Cê!Ú^jéâÇsè )Õ^b¾°´xßwó=æKHR°(Sú[¡ŠùX”yâD¸•@,AÌŠØ»Š¸Î ¯ w÷ã;§ú†‚W÷8l fûkuŠ•.ï瘒Q †2õññ}=–Q æÄR6å²7™(ààlß®6ßv‡Ç—÷kïW›ì•“½ð”J[`îÑK€E1°Ô‹Àà‹j@À&–ò€ñ&v÷¦€ÙÒÕÏŸ€Ã3´2áÿwÙù&Oÿˆ%`¢ Lê-˜¨fb) k̃çy¹û¥ý˜Mm—®å÷‚ ‰{¸$Q †$õ“ÎV|5 $KyH¨&Ò÷â¤üÒíáøvZcÅ=b ˜(“z +Q  b)àR)óÕMz¾ÚÌ·Ÿýáí‡þܘo”qÇká#ôMCö-2Ìiu¨¿‹…GªCNj–ˆW‡&ª\Kàqí¤²ÙµLMfËCƒjrª (¹MüÃvnp¬ ºHSŽ] ’1åIÇE¸Ö(éÜòÖ]ɯpU}ßçPXá=Pˆ‰+FÎä,[¢‚ ³`Ó5QMýØ·«n»Úƒ IñíËGeenf›ð˜PU¹š%R™¢òH„Œé‰&,h`§ªð ?`¸Á±*00ZöáÏ׳1Øgûø*Ø· ÷õì;·Üõ—f­üþçý|á~ÔmÖùkL€ÿ@,sS`Y”Y–ú%SôóÔˆšP–!§ª ,C0² 58V…í¥ž¯gb*°¬–¤¦®KëùÐYÓíwûíÜí©€}Sö%4õEõÈytœËJ@G1èÔû´Îæ ‰hÄTÚàUùwR=ßvóåb¾sÝ óårÛ÷©d/¿0s×é¿ØÊKœWJyIƒó’ÔÁ<»s–¨¡D,(… ¿'/@¹OûwíñýЬO]V‹6×G…Ýý·§—Ð(rQEQ E©?2¯Mê]õ€®GL×sN4WÁõïûæC÷n¬m»ëÖ®‘^çv\jN]_R¯©wXi€E1x€¥¾?~©^rT¢ŒX (3N˜p}EÏ«õ~æ«÷‡ÍpÊ)BMòsyí„§sM Ï(ã™z™ærQ ˆçÄR¾ºÈAjæ_† WÝT|7—Þ…”ÛW–¶­_øµ¾ñϤLúº{xÜ[¬â;8ò a¦íÇ+®Œ10{èZ/ V¢‚3À¬›þZÕ~ÀÊßmºÝç{h-/¾7À{®0z1pôŽ@ÐÙÑ›¨áF,¸eCXýÄ·T,îÉ[»Ñž;KίkìõƽÀ—ü†!ì]ŠQ Ž)f´ÎGƒ¨¤b*ÐChRûÚÁèñ0_e^ãÎi$ÅÈ!û;§.­Ÿ¢Šsz‰*Q ¦JŠUÙì=ÑR1¨Â5©ü–ÿS¨Òí—?¨òµTqN/Q%ŠÁTIñ£ùn¢¤ b*P…©ø®äM}Ò÷fÈù¾`³ÌžºÒßéÅ“nÎ%Ü¢Œ[êL`›+Ñ↘ ¸Ñšh¿Aÿ„!¾[ù^þ/â‚°3}Ó%P]öŽ-T—1°º<ˆ*°ºœè¶ð1“SUø>þŒ‘ò¨Á±ªá›ü¬†?_Éò¶iÄW Ê”·ïzH_Þ7úôµ`ç=oÎú]@çբ̅ (Žz@. ¦<hc»¨ý.Æ‹JÅõí«Ww¯nýõçÜE}Š]Ñì}uÕ@ÿÀxY1‘‚ÊŠ#ÏeŽ”¹@’hÂbfpª IøâǪ û¡,Ë Ïgyˆ™ <Ô’P_ 9æá¨1{^ÈlSœª¾· °Ãâ¼°Ã’ˆ;,#Òl²›¨ÑB,´” ÒPl½Èn¨}°õËÉ«&üÕêÃQœ¡í`kë5Ô÷B™:å~meæ;¡:Hͱ ªcUíCYP£TÄPÕ›xXÁ´ŸÚE®å”S#ÍÏò]Í_}ƒ˜wa)öF18ö¦hÐüÁŠD\¯Vûp‡ö!Þõ×mbÑ¿/KgO0Jè7y+3„ŽÀî£èøvø©*¬‘*Ñ¢31•íø§œêßqÐÃs×=<Ø™óx™Õ$+²òéq]ßGž CJ8F1ÇÔ·Tª,ŽQˆ#b*Àh†ƒTO]L÷—g>q1]¼»˜K~.ïFÀ Þ,Q HÁ H`1Á2K€ Ä¶à§•ùª3ø¶ûv;ïß(’¹0Õ6y×'œìzW;”@‹b0j©7©Ì¶K'z@ÜS¸ª"Üï1ß½›Ûž··“«nÍ‚…^Çw ?" fåRU§v#JðE1¾Ô§´Î/A£>Ä”‡Ï^7ÝH^;œíÞw[ßé¾ÛÏ×ëÖ­Ký!p;…¾Í¾/Äޟʸü—I{7ºg+¥@> endobj 1507 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 629.419 297.029 635.646] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 1508 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 585.244 297.029 593.235] /Subtype /Link /A << /S /GoTo /D (144) >> >> endobj 1509 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 574.985 297.029 582.856] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 1510 0 obj << /Type /Annot /Border [0 0 0] /Rect [268.358 564.478 277.574 572.448] /Subtype /Link /A << /S /GoTo /D (97) >> >> endobj 1511 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 564.478 297.029 572.448] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1512 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 553.971 297.029 561.713] /Subtype /Link /A << /S /GoTo /D (112) >> >> endobj 1513 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 545.207 297.029 551.433] /Subtype /Link /A << /S /GoTo /D (160) >> >> endobj 1514 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 532.956 297.029 540.699] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1515 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 492.517 297.029 498.295] /Subtype /Link /A << /S /GoTo /D (73) >> >> endobj 1516 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 480.266 297.029 488.236] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1517 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 471.502 297.029 477.729] /Subtype /Link /A << /S /GoTo /D (61) >> >> endobj 1518 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 460.995 297.029 467.221] /Subtype /Link /A << /S /GoTo /D (115) >> >> endobj 1519 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 448.744 297.029 456.714] /Subtype /Link /A << /S /GoTo /D (109) >> >> endobj 1520 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 403.149 297.029 412.115] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1521 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 392.891 297.029 401.11] /Subtype /Link /A << /S /GoTo /D (73) >> >> endobj 1522 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 382.134 297.029 391.101] /Subtype /Link /A << /S /GoTo /D (163) >> >> endobj 1523 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 342.193 297.029 347.971] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1524 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 300.01 297.029 305.789] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1525 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 256.084 297.029 264.054] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1526 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 247.32 297.029 253.547] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1527 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 235.069 297.029 243.039] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1528 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 226.306 297.029 232.532] /Subtype /Link /A << /S /GoTo /D (113) >> >> endobj 1529 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 215.798 297.029 222.025] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1530 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 203.547 297.029 211.518] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 1531 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 193.04 297.029 201.01] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 1532 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 184.276 297.029 190.503] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 1533 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 172.025 297.029 179.996] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 1534 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 163.262 297.029 169.389] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 1535 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 151.011 297.029 158.754] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 1536 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 140.504 297.029 148.474] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 1537 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 129.996 297.029 137.966] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1538 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 121.232 297.029 127.359] /Subtype /Link /A << /S /GoTo /D (51) >> >> endobj 1539 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 110.725 297.029 116.952] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 1540 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 100.218 297.029 106.444] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 1541 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 89.71 297.029 95.937] /Subtype /Link /A << /S /GoTo /D (145) >> >> endobj 1542 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 79.203 297.029 85.43] /Subtype /Link /A << /S /GoTo /D (155) >> >> endobj 1543 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 643.427 522 649.654] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 1544 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 631.092 522 639.062] /Subtype /Link /A << /S /GoTo /D (51) >> >> endobj 1545 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 620.251 522 628.022] /Subtype /Link /A << /S /GoTo /D (79) >> >> endobj 1546 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 609.908 522 617.879] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1547 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 599.317 522 607.287] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1548 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 588.725 507.153 596.595] /Subtype /Link /A << /S /GoTo /D (13) >> >> endobj 1549 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 588.725 522 596.595] /Subtype /Link /A << /S /GoTo /D (14) >> >> endobj 1550 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 579.877 522 586.103] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1551 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 567.542 522 575.512] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 1552 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 556.95 522 564.92] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1553 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 548.101 522 553.88] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 1554 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 537.51 522 543.736] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 1555 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 526.918 522 532.696] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 1556 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 514.583 522 522.553] /Subtype /Link /A << /S /GoTo /D (76) >> >> endobj 1557 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 469.786 522 477.756] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 1558 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 459.194 522 467.165] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 1559 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 448.354 522 456.125] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 1560 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 437.762 522 445.533] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 1561 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 427.17 522 434.941] /Subtype /Link /A << /S /GoTo /D (81) >> >> endobj 1562 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 416.578 522 424.349] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 1563 0 obj << /Type /Annot /Border [0 0 0] /Rect [488.722 406.236 502.545 414.206] /Subtype /Link /A << /S /GoTo /D (114) >> >> endobj 1564 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 406.236 522 414.206] /Subtype /Link /A << /S /GoTo /D (115) >> >> endobj 1565 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 395.644 522 403.614] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 1566 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 385.052 502.545 392.923] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 1567 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 385.052 522 392.923] /Subtype /Link /A << /S /GoTo /D (114) >> >> endobj 1568 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 374.461 502.545 382.431] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 1569 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 374.461 522 382.431] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 1570 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 363.869 522 371.839] /Subtype /Link /A << /S /GoTo /D (165) >> >> endobj 1571 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 355.021 522 361.247] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 1572 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 342.685 522 350.655] /Subtype /Link /A << /S /GoTo /D (160) >> >> endobj 1573 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 333.837 522 340.064] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 1574 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 323.245 522 329.472] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 1575 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 278.703 522 286.673] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 1576 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 269.854 522 276.081] /Subtype /Link /A << /S /GoTo /D (82) >> >> endobj 1577 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 257.27 522 265.489] /Subtype /Link /A << /S /GoTo /D (169) >> >> endobj 1578 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 248.671 522 254.898] /Subtype /Link /A << /S /GoTo /D (170) >> >> endobj 1579 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 238.079 522 244.306] /Subtype /Link /A << /S /GoTo /D (181) >> >> endobj 1580 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 225.744 522 233.714] /Subtype /Link /A << /S /GoTo /D (165) >> >> endobj 1581 0 obj << /Type /Annot /Border [0 0 0] /Rect [488.722 215.152 502.545 223.122] /Subtype /Link /A << /S /GoTo /D (174) >> >> endobj 1582 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 215.152 522 223.122] /Subtype /Link /A << /S /GoTo /D (190) >> >> endobj 1583 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 204.311 522 212.531] /Subtype /Link /A << /S /GoTo /D (169) >> >> endobj 1584 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 193.969 502.545 201.839] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1585 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 193.969 522 201.839] /Subtype /Link /A << /S /GoTo /D (145) >> >> endobj 1586 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 185.121 522 191.347] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 1587 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 172.785 522 180.755] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 1588 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 163.937 522 170.164] /Subtype /Link /A << /S /GoTo /D (163) >> >> endobj 1589 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 153.345 522 159.572] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1590 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 141.01 522 148.98] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 1591 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 132.162 522 138.388] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 1592 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 121.57 522 127.797] /Subtype /Link /A << /S /GoTo /D (153) >> >> endobj 1593 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 110.978 522 117.205] /Subtype /Link /A << /S /GoTo /D (154) >> >> endobj 1594 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 98.643 522 106.613] /Subtype /Link /A << /S /GoTo /D (161) >> >> endobj 1595 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 88.051 522 96.022] /Subtype /Link /A << /S /GoTo /D (133) >> >> endobj 1596 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 77.46 522 85.43] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 1613 0 obj << /D [1611 0 R /XYZ 90 720 null] >> endobj 1614 0 obj << /D [1611 0 R /XYZ 90 720 null] >> endobj 1610 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F2 1382 0 R /F38 1381 0 R /F31 21 0 R /F102 799 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1716 0 obj << /Length 5725 /Filter /FlateDecode >> stream xÚíKs7’Çïþ¼-a €Bæ`ë;žYïH³—ÙØbwQªU³›ÛYœO¿@YÝÈ„lÉ»©pȤZÉLÖÿ‡w ~QÙÿøE[]4R²¶6³»ï*ÿé»ï¸ÿîÚ\‹Ÿ^÷ÃKÅ/xÅÚªå¯o¡‹×ó‹\òÖ\] c?»|vÛ/ß ËþêZÊúò½p_å庿í×ýrÖ_ý÷ëûîÅëL QømœÅѯ#. kµ®ý/£M͸¬Ç_æÙÛ~v%ÚËw›ÝÝónÛÝt›}Ø^J~ÌTLKeÿCìêš7|ü"&ûÍ~/¥t´â3ÃeT e‰íÿh¬®Ù‘ž‡®öúÔü(bÛ°J´0b†^°:Šh¥Ÿ"l$S2<¦ÇÆ0iL€÷þJ5—Ýzèn9Ò¶ìpm¾:é#b’‰J…Ç€F×É*Ãkâh¬ªAyEO$.<žƒ¥k…:®o¿ìÖortÃD«> Á—©WÿX ôÚ”j`2Ãk ”™¨É‰”ˆè˜*Á¤àÇL7žµfÒ~÷ù«Ôã&!÷Ò•'39¤Ð¶(òäŠDNDtÈkή‘ÿýÞvçíå¼Ûö9úfõ§6¨_šéÇÃô¢”`&3&Ô—¨¿É “ˆè`JÎ8柟ÿ-NÔ¶çÕ â‡X¯ìÕ,uËÉ ï—!^i´$_d1 Bºb *¦ªÆƒE·ÙØx-]]¾â—Ýø—n9¿ÙÌÖÃý6WÇÛŠÕÆœÐð«Î^RuNfxu†ÒrœcrEr$":ŽUk§[ò˜co1Άyï Þ¸6ûÁÓ|Û/ã·³ÕÝ]g--èc¶\ ¦+õÇÂÅ*–®RÅJfxÅ‚ñ ñ&_$"¤¢ÚÖŽaMÈØ_ö˹ãù>³aJ¨ó™nŽ‚(šÀ ¥9Ñ—  |Q4©Ž¦1L·õÍay»ZïkÎvX-¿?¼·ÿ<,ߌÙ®ÜWA4¼v³ö³u³˜öþJÚ'3\{¨¯ª}òEjO„tÚÛÙ{eÚ1ÚÌiŸ­1°Z5'[c¾È`e옂 …>˜¡}Ü„ GçÀY".ú(ÝØQ†*•©¯O~¾ñ;øjä2Q&„¯·ºfÇ|\í•ÔÕQD×M55Œ˜ãë­èˆ®ö¿G3úccFi»´Sh/±Šçe(U¼d†W<¨(ÑÍ%W$>"¢ÅW[áE|á=öjfìÕÆ¾ 5šñÊœú»7g¥€˜¡8' ã]pEá¤":œF0]‡5 ‹Óµ˜¹©lÚV?ÕE ¤ âÚ``†¶Á¼FW/’:ÒQo«ê:UbGý™[zÏN g0ç¶å(ˆPª²É ¯²POü…)pEÂ#":xš³Cvvâ7ö óÝ:­øó‡ìlP0þØ6a5l|ÖR‹Vxý¢QÕ+z"áñU1#Ã&# ÆÎú¶œ.›±ÏìgƒïÌÆß®6[?~ýuؾõéíz·Ì®ÔÛ }ýù–Z0õý“”äOf¸þP®ñ*’|‘ˆA]1!yèÕFë•Ǹé÷+%]UËZÑœó>¬-ô‚•ÚÂd†·…P{‰ŽF+4Ñ-ÓBOëš½HàÛÞ¿÷þf·ã×Åj2íÈ®œ‰š)®¿B‰À@ù.Jf8(¨]ƒƒJ®HPDDŠ·ÖN„y?¾ýϼ<«7g0Ìü£~ ¬XxyKÅ"™áÅ’"êäŠ,DDW,*ÃjVØB±0êòû±fölÇ9ÖÖ±’n×½¯ÏÃ]÷&_gyÅ”¥aÄü“—ˆ%3œQãc›äŠ$FD´Äd;‹­-Þ’ªš ßÀát+ðf(ï ¼†Wo*¢ãmƒŠ*,×­ûn{°Z‡ÀnesÎ/¾‘sP«0bfèˆy"<¯Ðu à‹ÄL„t˜Ítå'Hvx|çÇJnóå0Ïo «[ÛP´O ³Æ`{ÍJ°“ÊÏktÿ ðEÂ>Ù;edr¿È?â®Ör¿ÜôüøœRuqm ¿çÏ^ŒÅákîû‡üakôßõ„µýR²†gWÀ oû½Í¸8ŒöõÀYNˆˆ®”ÉxØ8ü¼ïæ‹Õ~åbveÿ÷.W «Tým•xÚLxKÍD2Û „kt¿#ðEâ'B:ü\0U ÿ¾AøçêÎ5 7ƒ•ßìÞ„ ©ã×u¿Ùvëmvnmì8ýËôÿ„%4É GÅâﮓ/ Ò¡©83aÓñóþfè¼Ü¿8Ýx jºôïÈã™Ô=¦ÿØõë|§Î¥ù{uŒƒœ‡d†s€Êp‰W‘ä‹ä@„´DË™heà0[tiùÝíúA_†jÚOm)Odæ4*ô~À íý&rKt”\Ql©ˆŽ­;i¶[¶ëþ®#âŘ0ÀV(¿¹k ú5lÅe?¶Ä"£ªX«Ì·šïÅóÏSâÌpPƒŽB€+’Ñqh*V™:p8Øtå»aÙ­Ãi¢~ý~?L]綸þ{΂áó2”ð%3TT _rEâ#":|ÊN Iïí*L7ivvFÂùi±;%¯A¡{KVhïÅäºù8y"Ááñ·Ú0Ó(Ü]7,>œiíÜPœäf-/»×¢0™á¡¬œã“/’!ÒA´£9¶ËbW;ÿŽ:Ÿ†ÄÒûÂ{U?7=/B‰^2ÃéA=9>ÿ¾HzDHGO4Lk§w3n"¸]­}Û¹ÃÒ}ò®»Ç´ôæ{0¯L©3LfxgE&Æ”ÉI”ˆèˆrk§Ež(=aPLðÒÊÑy-áž,êpôV×À,s^kê ;—cã¶®r½ñÀvBÌ—/úcQ%N]a‡àBQ¥1U"¢+ªîÐjòEõ-ªëÕî>[RÝJs{^‹€XÏâ5*õ,É ïY ÜÄ&|à‹„K„´py«˜QqÝbÑoû¿®–ÿþë²_ÿÅé²£YÉÓÏ«ž¼PZ'"Ö#\QĨˆŽ˜QL¤y”'öw;î~9ä— gU+Ïm×nСÄ/™áü ¤¿äŠäGDtüššéºÎðû‹ŸD‰Ãʵ´5ñw½iÃ$õ¿ZIÒd†K Ÿ²FW€+RR"¢“Ôö4•l¤qkÂ|X÷³í Yã6.ƒ>½11Ò  ½0C{¡‰¤Ä{hà‹H„t•dµT9€äÞ©ÄÜ[Ô*aNf8f(<±ø"1!æZ0#s”7Û.÷[ ËwÙScö[#OjÑϧ¬ð]H~‘¬ÐÜP¿¶ÁR_$GTæ *ÜÔ÷‚~¸X‰hSG¾$¢ËaôÓÅ‚8w˜¶Åå"®§,~êæÏ«Y(xb:‹ºùøL½ú‘Îx0~^ŠÀd†„ª |/’áAÈ#ˆ‚3-x‚ølµ\Ž':6/׫»c”­`Š,IwnN}Õƒù^Uÿ˜%@É £%_$ "¤ãÃí¼ƒÇuŸanL‰€%™Sê4dŸ^ ½X%ÊÉ § u'òÐ_$e"¤£\U¬æq!óý0ëá²´;Þ!£ow\ž|Nml.åu)Í¥’>—‚kô|pEò$"Zž.FÜíIà„™NȃS¶ø4Í£¦#´üS`%+””¯E1ÉEŠçî¯hmmƒé—¯òG¨*õ-Yòo^ôÊ C²B D¤ÐãÉUˆp’׬møô¾‹çÿúì—\™hXóËÄô.†,Ý5âÈ«F¯œŽz\UÙ§LÒ7+2à¡«üäLU†ñ¦)<`°*œºòcG“»§ð|î*T,Ç[E O²8Ù$²‘Rés¹¡ãé•)ñLf8O(2Æ3ùAy¡"O-Xzª´û=È&éׂòGŒ>½E> à(E‰_´ÂñM3˳{zÑ Ù)aûŸƒ÷vpùïì|.ŸÉ°þC†Í·‡Š[ÉŒŠº $½Õ50;Fyàj|U’¯ˆÉ Ê’ˆaÖœÉpÏ1Ì}ÖðwöÁ/‘ºXÙ±ÃÙd€ò{QJ$“NêÛð,Éä%IDŠ$eÅ´8hSý¶çÛÕzœ”ÍÒMvŽîxfg¾Ã\(&xóõ\D1ý#–¸$3œ T i,“” )rá.qL‹Ïõ³¾öYš\”ú¤*†nT¡D.Záà€œm¾eŒNPlx˜H­²“+=†Mw³8Hd0V¨­;ïöàA"wd¸yßy­hE^¥Öd†s…‚gœÙƒMnP²D¤€VµvZÀ6» mX#Îú 3Â8ÈU` ÌPÆå™c Ü`Œ©H‘±i0æÃæ]XDó +wkóôrD6†ÊA’0<#È¡«s•Ål¨ü##f"RÄl[WN¼?ÿ+²â)õíÆ•r›î§‘AÓ„˜¡3Ò ^gG¿ÀZˆP±$hÍê°Ê>_ÝuÃ2ÿWªoĨÖÞëXj’Þ @$u¾µOnPøD¤_)ÖTaïÆßÜ/»»>ß—ëón0º^¨Ýd†Ó…š«|#ŸÜ t‰H‘n­X_k­¶›éùi—ÕqF^'k£Îtðt)ÁLf8L(±Y˜É “ˆaÊšÉ*ôØ«ÝMØã÷»Uþb^Õ2‹ù)VV/U‰o2ÃùBÕ›&Ë7¹Aù‘"_!™jþëõÃß²9Š]j!m¾ Ê(ú^Èýd†Ó‡LŽ8¹Aé‘"}Ñ´¡#Þu‹¿ú®Ÿ§Ö:ÛR+;§ãçr5€½¥±t2ÃÇÒPZ;ÎRL~PŠD¨HÑ%7g>°ë0+ßšãÞíè³¹ Êîµ(Lf8A(+òzøA „šì ë–3ûg‚ðÇ)<1ÝH/Mûñš¹nÛU~Aåðä`À 6ü`ÀCM.FbºbUíë÷ ,ëbœO½¸ë×oúåÌ¿Ièü^¼l2µ†3-ÛsHvЩ¥)òNf8ooã3èé,ïäåM„Š´¥Ë‚«Ëû-¸ñ_ƒ®5kÚ§³|÷Ú•ˆ'3œ8ÄÀó/Ú”8*5R/V‹y\²p׎9sÜËAñÇ­{ ï0\pÃjÛî_óÊö¹¾ú_``w ˜Š¯,~è·³l°Z¼g³Õò6Ó (&ÓëÞÉÍÅlCöHoéB†Ñ5—û½Æ…a40C‡ÑÁfFgßP7hY!"ŲRI2y¾Øçßy?¬WË}Š9s¹ Ĥ—Þg/¯8¯/üùçg?ÿøÊ–¢W/^!‡„Åï;6‡‰<þ¾%£.1xðü79AÆÃ}e+˜ ·Q¾øÐÝÝ mÅpͯÕîÍnÝmýÕI²°™]ê¯ÿ‚i,ãK`†6–Õ¸Îî™~0>T¨ÈØ!‹Ýã‡Ù¢»0\Ù­÷»’6þ.ˆín¬,-‰$•Õê‹„ ž¯Pc€Ze&Rå[%à…BDŠPšÊ~&”]º|¼ÙÙ†kÇŸm}.¯]0¢^œÑd†…:Ë옸A‰‘"Q;ç‡3€ú=.è¸ƒÌ =`f8xëæ×}z¿þ>›3ØV÷/t;$Æf|Ìšh…“zµÙUÔä傇‰Xê–©pgë‹÷ÝrþŸWF‡ÎÙéÞªæ¬SG^Îd†ó„B•šÜ D"åç÷ÒŽÙeÈÏõ²8¿¿í†Åj?ògù—Ù.Aû·³\DY±cÁV•[åd†—o3ž¸Ì—•ä-+D¤PRÄþV^?«{9ôaf¸éï;;&]¹ôjÓ<ú…ÒUÃÄ£ËkŒ _ ÌPbÛìl¸ÁˆQ‘"1ãN`µXèý-d¾»TÕþj;sù`¿çù—Õòô—w0®^¢×d†s…jë<×äåJDŠ\íÈÕ„5ÙÄõ®[Z°ûe?!ÏŽy›ú\n;Á˜zyJL“Î*Ýf[WàeJDŠL5gÓ)e€àÅ)áLf8O¨sæŽä=Ðä%J„ŠHÝîÕpÈ"]÷³ÝÚõy9œ’ yž¹Š‘Æ7ÈTh|ÚøNÏnP¶D¤ÈÖÎÈtŸ›~›’¯Ü:­»ûµÙ|šŒFœ[šŒ M‰g2ÃyB•óÃ!àåIDŠ‚9:A)ãa"äZ²:$xéÞ®Ö³¸Åç>n½Ë tG\Îx%†ØKVbœÌpÈPýüBpƒb&"EÎÒF öœ×}ÿÓ«ç÷›É}Çbrß±¤î;®Ý+™Ïw/6èñOQô$3|ÐÉÜp¼×>ùAµ'BEí…`U8åkußÜw³þO¹e9eÉ'wÚ «h^·REKfxEƒò‰€6)Âv»9¬gC¿œ¿ÚvÛr˰áQ¬àh…óªËì‹Î䥋‡‰p«Šé ö–»…?¹çR§Œßí·xuû]–ÈIëJ˜3=i*Mf8R¨5Re“*)Puë†óùêC8kÝ-·a¤‡ìÄ%„ÞNëöóâ (½*’É  åÍŸ˜ON0ŒD˜@æ‹).ÇFá}ÈnXl¯³ÉNl•TU}¦U’LÈ9²ùK{ssɸÿìõÀò endstream endobj 1715 0 obj << /Type /Page /Contents 1716 0 R /Resources 1714 0 R /MediaBox [0 0 612 792] /Parent 1615 0 R /Annots [ 1597 0 R 1598 0 R 1599 0 R 1600 0 R 1601 0 R 1602 0 R 1603 0 R 1604 0 R 1605 0 R 1606 0 R 1607 0 R 1608 0 R 1609 0 R 1616 0 R 1617 0 R 1618 0 R 1619 0 R 1620 0 R 1621 0 R 1622 0 R 1623 0 R 1624 0 R 1625 0 R 1626 0 R 1627 0 R 1628 0 R 1629 0 R 1630 0 R 1631 0 R 1632 0 R 1633 0 R 1634 0 R 1635 0 R 1636 0 R 1637 0 R 1638 0 R 1639 0 R 1640 0 R 1641 0 R 1642 0 R 1643 0 R 1644 0 R 1645 0 R 1646 0 R 1647 0 R 1648 0 R 1649 0 R 1650 0 R 1651 0 R 1652 0 R 1653 0 R 1654 0 R 1655 0 R 1656 0 R 1657 0 R 1658 0 R 1659 0 R 1660 0 R 1661 0 R 1662 0 R 1663 0 R 1664 0 R 1665 0 R 1666 0 R 1667 0 R 1668 0 R 1669 0 R 1670 0 R 1671 0 R 1672 0 R 1673 0 R 1674 0 R 1675 0 R 1676 0 R 1677 0 R 1678 0 R 1679 0 R 1680 0 R 1681 0 R 1682 0 R 1683 0 R 1684 0 R 1685 0 R 1686 0 R 1687 0 R 1688 0 R 1689 0 R 1690 0 R 1691 0 R 1692 0 R 1693 0 R 1694 0 R 1695 0 R 1696 0 R 1697 0 R 1698 0 R 1699 0 R 1700 0 R 1701 0 R 1702 0 R 1703 0 R 1704 0 R 1705 0 R 1706 0 R 1707 0 R 1708 0 R 1709 0 R 1710 0 R 1711 0 R ] >> endobj 1597 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 684.134 297.029 690.361] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1598 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 673.53 297.029 679.757] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 1599 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 661.182 297.029 669.152] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1600 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 652.321 297.029 658.548] /Subtype /Link /A << /S /GoTo /D (99) >> >> endobj 1601 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 639.973 297.029 647.943] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1602 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 631.112 297.029 637.239] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1603 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 618.764 297.029 626.734] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1604 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 608.159 297.029 616.13] /Subtype /Link /A << /S /GoTo /D (107) >> >> endobj 1605 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 597.555 297.029 605.525] /Subtype /Link /A << /S /GoTo /D (107) >> >> endobj 1606 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 586.95 297.029 594.921] /Subtype /Link /A << /S /GoTo /D (145) >> >> endobj 1607 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 578.089 297.029 584.316] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 1608 0 obj << /Type /Annot /Border [0 0 0] /Rect [268.358 565.741 277.574 573.263] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 1609 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 565.741 297.029 573.263] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1616 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 555.137 297.029 563.107] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 1617 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 544.532 297.029 552.503] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1618 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 533.928 297.029 541.898] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 1619 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 523.323 297.029 531.294] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 1620 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 514.462 297.029 520.689] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1621 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 502.114 297.029 510.084] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1622 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 491.51 297.029 499.48] /Subtype /Link /A << /S /GoTo /D (20) >> >> endobj 1623 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 480.905 297.029 488.427] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 1624 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 470.301 297.029 478.271] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1625 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 459.696 297.029 467.666] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 1626 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 449.092 297.029 457.062] /Subtype /Link /A << /S /GoTo /D (161) >> >> endobj 1627 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 440.231 297.029 446.457] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 1628 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 427.883 297.029 435.853] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 1629 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 417.278 297.029 424.8] /Subtype /Link /A << /S /GoTo /D (61) >> >> endobj 1630 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 406.674 297.029 414.644] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 1631 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 396.069 297.029 404.039] /Subtype /Link /A << /S /GoTo /D (61) >> >> endobj 1632 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 385.465 297.029 393.435] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 1633 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 376.604 297.029 382.83] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1634 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 331.968 297.029 339.938] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 1635 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 323.107 297.029 329.333] /Subtype /Link /A << /S /GoTo /D (165) >> >> endobj 1636 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 310.759 297.029 318.729] /Subtype /Link /A << /S /GoTo /D (130) >> >> endobj 1637 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 300.154 297.029 308.124] /Subtype /Link /A << /S /GoTo /D (135) >> >> endobj 1638 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 289.55 297.029 297.52] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 1639 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 278.945 297.029 286.915] /Subtype /Link /A << /S /GoTo /D (87) >> >> endobj 1640 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 268.341 297.029 276.311] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 1641 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 257.736 297.029 265.706] /Subtype /Link /A << /S /GoTo /D (108) >> >> endobj 1642 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 247.132 297.029 255.102] /Subtype /Link /A << /S /GoTo /D (118) >> >> endobj 1643 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 236.527 297.029 244.497] /Subtype /Link /A << /S /GoTo /D (127) >> >> endobj 1644 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 225.923 297.029 233.893] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 1645 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 215.318 282.182 223.288] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 1646 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 215.318 297.029 223.288] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 1647 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 204.714 297.029 212.684] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1648 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 195.853 297.029 202.079] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 1649 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 185.248 297.029 191.475] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 1650 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 174.644 297.029 180.87] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 1651 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 162.296 297.029 170.266] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1652 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 151.691 297.029 159.661] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 1653 0 obj << /Type /Annot /Border [0 0 0] /Rect [268.358 141.087 277.574 149.057] /Subtype /Link /A << /S /GoTo /D (97) >> >> endobj 1654 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 141.087 297.029 149.057] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1655 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 130.233 297.029 138.452] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 1656 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 119.629 297.029 127.848] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 1657 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 109.273 297.029 117.243] /Subtype /Link /A << /S /GoTo /D (107) >> >> endobj 1658 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 100.412 297.029 106.639] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 1659 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 89.808 297.029 96.034] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 1660 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 79.203 297.029 85.33] /Subtype /Link /A << /S /GoTo /D (51) >> >> endobj 1661 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 682.391 502.545 690.261] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 1662 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 682.391 522 690.261] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 1663 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 673.432 522 679.659] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 1664 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 660.986 522 668.956] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1665 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 650.284 522 658.254] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 1666 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 639.581 522 647.552] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 1667 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 628.879 522 636.849] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 1668 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 618.177 522 626.047] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 1669 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 607.474 522 615.444] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 1670 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 596.772 522 604.742] /Subtype /Link /A << /S /GoTo /D (73) >> >> endobj 1671 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 587.813 522 594.04] /Subtype /Link /A << /S /GoTo /D (70) >> >> endobj 1672 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 577.111 522 583.238] /Subtype /Link /A << /S /GoTo /D (141) >> >> endobj 1673 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 566.408 522 572.635] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 1674 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 555.706 522 561.833] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 1675 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 545.003 522 551.23] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 1676 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 532.557 522 540.528] /Subtype /Link /A << /S /GoTo /D (77) >> >> endobj 1677 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 521.855 522 529.726] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 1678 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 512.896 522 519.123] /Subtype /Link /A << /S /GoTo /D (111) >> >> endobj 1679 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 500.45 522 508.42] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 1680 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 489.499 522 497.718] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 1681 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 443.894 522 451.864] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1682 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 433.192 522 441.162] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1683 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 413.025 522 419.999] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 1684 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 403.07 522 409.297] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 1685 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 390.624 522 398.594] /Subtype /Link /A << /S /GoTo /D (169) >> >> endobj 1686 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 379.922 522 387.892] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 1687 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 369.219 522 377.189] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 1688 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 358.517 522 366.487] /Subtype /Link /A << /S /GoTo /D (97) >> >> endobj 1689 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 347.814 522 355.785] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 1690 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 303.953 522 310.18] /Subtype /Link /A << /S /GoTo /D (65) >> >> endobj 1691 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 291.508 522 299.478] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 1692 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 280.307 522 289.273] /Subtype /Link /A << /S /GoTo /D (61) >> >> endobj 1693 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 270.103 522 278.073] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1694 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 259.4 522 267.371] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1695 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 248.698 522 256.668] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 1696 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 237.996 522 245.966] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1697 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 227.293 522 235.263] /Subtype /Link /A << /S /GoTo /D (110) >> >> endobj 1698 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 216.591 522 224.561] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1699 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 205.888 522 213.859] /Subtype /Link /A << /S /GoTo /D (99) >> >> endobj 1700 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 195.186 522 203.156] /Subtype /Link /A << /S /GoTo /D (110) >> >> endobj 1701 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 184.484 522 192.454] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 1702 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 173.781 522 181.751] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 1703 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 163.079 522 171.049] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1704 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 152.376 522 160.347] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 1705 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 141.674 522 149.545] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 1706 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 130.972 522 138.942] /Subtype /Link /A << /S /GoTo /D (135) >> >> endobj 1707 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 120.269 522 128.239] /Subtype /Link /A << /S /GoTo /D (70) >> >> endobj 1708 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 111.31 522 117.537] /Subtype /Link /A << /S /GoTo /D (31) >> >> endobj 1709 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 98.864 522 106.835] /Subtype /Link /A << /S /GoTo /D (70) >> >> endobj 1710 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 88.162 522 96.132] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 1711 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 77.46 522 85.43] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 1717 0 obj << /D [1715 0 R /XYZ 90 720 null] >> endobj 1714 0 obj << /Font << /F51 5 0 R /F2 1382 0 R /F38 1381 0 R /F31 21 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1829 0 obj << /Length 5193 /Filter /FlateDecode >> stream xÚíK“Û8’Çïý)ꨊpa€ ȹízîi»·7Æ1—Ù=Ð]¥°¢ÔÓÞO¿‰G’B&ºÃvÛ’&æ0mW:³ðÿ‰7Èï ó?~×wZJÖ”õÝrû]áþöÃwÜý׃1xÿùö»?üEñ;^°¦høÝÛ÷ÐÅÛÕÝ?/ŸÚçcw¸R.ê?Þ?”¥Z¼Üï–ÝóqüËïw«î—ûQ©F/xÓÜÿïÛ¿}÷ç·!¨"ó[Y‹³_K‹;^2YVÂýZU]2.Ëñ×ú«ò‡¿ˆ»š5UUZS4óêJ:‹v»Þ=š_±‹þxhë®ÿ•¬Á?Ӝɺ1ÿzøWìþk>þŸ˜üé7ÿåçñò+ÿr¦¹¨%…º«ª† Í­¨†òðC »·zfƒöPÖ¹«A&^Vg!Í ÑÀ ÔÞŠ ia«Ú°×e·»Íâ¸7µ¬YìG¦?Ý‹zÑ.í>Ü+½h;û¹øS{lßµ}7šý÷©;¤ÁóÒÔzÅ?üùÏ0®@9Ñ 'µáR¡$¢/’Ò’(5+…oT‡ýéy”yÕÝóÅó@¤3`·L«l­n>·È_¡%9rü¢Î*Ê ò‹¾H~DHËOV¬lê3~ÿSðÒ"ܬ^ŒÑ­ÖG›1 MC)å1œþ쌨f5—AŒèhõÌD§®}Ž®H DD T(¦´ë-ÐT»5«4¿Xf_â/±zàôÌÕƒh†×ˆ¦*Ðz]‘õ`QòYE0ÃJåêAäà—>¼ù²©}Ô1—ÙƒžØ^à#¤à‰¤Ç³ì É´P «÷.¯LNïlrߥ“yU3^]KbÀˆ:urH£Î MA¾Hª³g³eç#•K!¯²³œWíî1LsžãyÙõ}z®£XÓˆËbÿ+ ÉW©Š©‚çò80Có¸·d*kŒ9pE1§"Zâ¥MóÚó<¬Æv¼Ü´¦%÷ýø§]»uÓ›å~³Y÷ëý.5¥1µKhùmf{ ›+~[4ñA%9:®®HlDD‹MÚü,"¶Íz÷!ÕèJ΄Ð7×#©ÙË–IÍÀ MÍœ£©ø"y!-oa3wíy÷O:ÜÒÿnå‡Ý^Ï\»fx»‡hÎ C=ˆ®Èz@D´õ€ Vå¤ ½ïþ}œXo’•C™¡W}-•c.²¶œA«³zfçXg®Æ^ø|V] #§€SXqæjˆø­¹tCÍ%N]5hÐE 5—ˆhknÁYíZÉÓÞ'ì|a}è–ÇõÏvEµKM VHyÍk éQ±è`…sÒ *8")ãá ä²±«Ún¾òÊQ‹Õ€xo—ÂÝqdùÁÉé>" &K\ewˆåU§P.¯F3<¯B±9¾» |‘h‰m!™ªø´™þÆZ VÉ+[ôÄx:Yr<£Î*Ì+ôÔðEò$Bž²±*Çó4nÊÅÖô…ö]½xZïRk?ªa²W9ñD{¥2ˆŠx":¯Ð“zÀ…xòlóXšù†Ð.E|ŸÝ<^?îö¿­h*Â~»mw+äÌ@!¯táÚ³*MWdzSÀ ÇîlÜÄ]ï¾HìDH ]ÚDîÆÛßoí‘Ìz±?'»n]aœÀÔ£Æbmÿ»MçÇëÔ¸«1“⪼e'¿$G2šá$¡¶œ£}.ðE’$BZ’¦pyFrí³5±µÔ°FÞT–vZå G32”‚}‘‰2·IÜ Ð׻忴rÓŸõÎ¥â÷f–šÊÂ%Õ¥ÞùU£,¯Qn4ÃáB¹‰Q3ðEÂ%BZ¸gšûx·¯7ûq¯îؽ˜YÿŸÛ@?íLÓN4áš•—ñ¢#Òv ™¦­Ð– õäø.QôD¡›Å›v¶Òüw£ùô‘Î×é·fÂný…¿wS­üû‰Ñ~3¼sydK#bcŠRUŠ5èÎ’·zfglç®)äÙéaUØ# FL½¼ê¬ÈˆsWéa¾½|®k•)¢·¢Î\›œÉ‡e3ųËÎ#MžQ õVI3¯b­üq¿êΫoY0-áÍÚÎ6©g@Ì€¾º®ãxn'\w4ÃqCçׯÜÑ Š›ˆh[Ž  =dŸsŒR›ùEy㯹`à†9ðÑ qœwSøèOD à…é|¤;}öz½î*¹Ó ›Õ!Y ”`²vÞ™!’¶ª:9îÈY=³óîhæÊt(Îû#ÁT©`Èd4Z‘!ç®þ¨¨×:SFo• 8uå «dE¥Ë—“3TTnæ¡TÔ~²!ïÖ»öðq¾¼Ü9( 3Œ¯¿BÃj+[®ÖE3¼ÖA™8/ÑZ}‘µŽ9w•©udc­#N]‘µŽ._NÎPë ÉŒŠgµÎŸIn—öiIÿ¡_$Û¤¨Š_ÒAn§AŽ\4ÃÉA9¹J`£”Ê“Sfb­”äÜœ¹}×ï7§còY'ÉŠZ]õ…OÂË“ ÌP¨¥ùx®qøÁ R¡Tm¦zMêªÛtGÓ(ùÂjîí&…¸¶ˆ¿ÑÑËÙÙ¤ ʌͣ`•˜ Oφh¬gž¨ž 8wE÷ tcU$N]aë;CU¤Ë7TE"T¨Šf]úÓ3°*¾ß–á°ƒùƒ;¿ß=t¿¬û£ÛIÉ]_³îu]~áë,A7W˜‚h†#€º`Ù úA¡3©uÁ¶ý~%J™ÿTõ-<·p8rd£NÊÍyr9øAÉ¡Y3s•œ'ÈÚÆsÚ×ÏÉì^ ÖH~ÕǶ 'Ql4ÃÁBµSs 6úAÁ¡X¡Ùd縺í~ØA·’V]»Joe4Ÿz¼å÷‰qÈa V85 %–gƒ”' 3Ó$Þœ#ë ªd#TÜü~·ð Œð(XŽp°Â å±|¼ „ñ8°®U"øxh‡F9>ƒË‡>4Ïx°= ŸK¿þÍíi’â÷9=€ Ÿ]á2Ãçh…Ÿ¡JÄð9z"‡ÏDÀ¹«Ìð™,`¬odÀ©+røL—o¨rD(_çì[°…¿+òÚ}¥c¼?gßæí?¸êõÜ.ýÍU3ª+¢?®ί$ê0}ÑWIB%_Þ %`†RšH‡,?%*T d&B&¬§ôxþ‚Š—½j»ìe¿¶ âøÔùŽÂO@PÕL4¿ë1dÇ—6³ÌÐ œ‰p:9¢nPDD¤€¨*ã·I ¢õÒßBýñ¿ ·é 4º¸ÅÚÃq’å8G3œ3T_ð$çèå<‹”>IR É¿)ø?Iâ~›méÖ#N»¥=ŸÛnü±¿äsVE]_÷¼É+Ó:?šáð rvw€Ý ð‰H½4CöM»v-üýa¿uIø}÷K·LM˜´düÊ6k}GèUÉô©À íS'ó*™°Œ%*°¬ V)=g·,Ã’öøL‡½õ˜þŽlU]ðE ½Ó#G1šá¡´œ'ǯÀJ‘(Ú”ÙŠö±×ôQÊÿê(’톙T ÌÐT<Á¡’©¸AÁ‘x¥˜ò/XZðaÀ»?Ùg´ŸOGdaòýsÍt¼@¹öÍðö µæUr øA±¡ÖÒòËioÆýƒ1 ߉±«éïykûBzseÏ „vådÉ5Ñh†7Q¨°N•”%)°”+y‚%öAB3!õ-}Î)40§T®­F3¼­BÑ‘ÕJàåK„ |¹fµ*ÏùÚOa¯¬+~K|}›sJåšo4Û/i¾Ñ Š—ˆðš ‘hxÝ’_ü°àf?<V<üº¡× “‹M¦©ëßuÿkz®”¹¦Íð¦C”Í,TòZ€½É¨¥ôp~y¹ßíºa}¡?_‘°¨é°ø¿“)K¦xõmjÄ+îUÈÀf(¼‰ ‰Wv,àƒG… ì̼†û ü7Ýcëo“õ¿í:Yc܉K<ÉèÈa‹f86¨%²Uü ØˆP[¥YŶÃãôõk{¡¾O}{ÉŒzËRÝî2¯×-Óù3´ó› ÐÉc«À ›ˆ`j…âvß·ð³¤]úÕÊ®!^î›fÈå@/Fær 0C/Nt-ÑËÀu9Š8wE_¤‹+)pæ ùtîPIéâ •”ˆ*©™„•M¨¤Ç§q–|¦IV¬iÄ­.€a‘0×E3¼#‚,8Oç¦èÅN„ ØÅðM…3êà ×Ñ?$Þ‹aé/—ñÂTXþ%–®?ãñ‘ ïXè©`…ƒêaœ‚'P2S,é¦×ý²ÛlÚ]·?¹²o÷§q¿ÞM¥Æ7÷Ý>É#<&¤nª¯q„'H7)Ç Xá €6\$'JÑ ÊöØ“;¢ñf<ݲ:mfŸžNíÄê‚5åîÍc=¸"׃G3¼‡š ‰öàÑÙƒç®2=8YÄØƒSg®ˆëý™â õ“ˆä+¨}BPøs °‚ò…»Íf÷“Oö£ ãq¿ív|¸«=v›É,¡˜*š¯ÐÏ#X| 3X€Še"–HîB7*RÀ¢VÕi,/Â"Øa²Al˜<)m\éêrßm ê;Mr £Ê+«$ÈèID í÷RüAoö»µI÷ñÔã“ghwûô‹¸Œ÷›0jN€µh†SƒZÊäÊ3pƒR#"jªdª ÔN𪺷`”›Û]eñšå@G34”ÿüýøttƒ‚&"Ðf¶SÕ ô°0í¦2ýþtX†3®à“9©®O0οô—§üÿ«gÞ fè[xQcGÚ/êH;rîŠ>ÒN—1 øé€SWØ·×ÕTR´R¡B¥2%»à:­T~åÖÖ?öÇnÛ§s}ò–¾hËNŒ\ZˆfxZ€º¦æ7(A"R È+V×s‚óMŽYzÈUÊK|ê4´'@®áE3¼áA-‘¹6ðƒb#Bl…ýö€Ûÿ܎̶.“׫ô±ÅYQ—7°.‰¡v¢åPG35ÔŸ§ç­ÀŠšåQ7œéÊ °÷€ŸöÛÎ=„¥u9|üò®Œº‹g®Ìô¶h„Ý_ƒÒ•èkTÑÕÕÑfŽèŽž,Z¨ƒd´‰#ìA^[¿è’Ù HÄñõ¾úÆßCÏ¢Øí¹Ýûå)ä’¼Òtƒ°%ßl l‰7[gލÛé©÷Zÿá34ã endstream endobj 1828 0 obj << /Type /Page /Contents 1829 0 R /Resources 1827 0 R /MediaBox [0 0 612 792] /Parent 1615 0 R /Annots [ 1712 0 R 1713 0 R 1718 0 R 1719 0 R 1720 0 R 1721 0 R 1722 0 R 1723 0 R 1724 0 R 1725 0 R 1726 0 R 1727 0 R 1728 0 R 1729 0 R 1730 0 R 1731 0 R 1732 0 R 1733 0 R 1734 0 R 1735 0 R 1736 0 R 1737 0 R 1738 0 R 1739 0 R 1740 0 R 1741 0 R 1742 0 R 1743 0 R 1744 0 R 1745 0 R 1746 0 R 1747 0 R 1748 0 R 1749 0 R 1750 0 R 1751 0 R 1752 0 R 1753 0 R 1754 0 R 1755 0 R 1756 0 R 1757 0 R 1758 0 R 1759 0 R 1760 0 R 1761 0 R 1762 0 R 1763 0 R 1764 0 R 1765 0 R 1766 0 R 1767 0 R 1768 0 R 1769 0 R 1770 0 R 1771 0 R 1772 0 R 1773 0 R 1774 0 R 1775 0 R 1776 0 R 1777 0 R 1778 0 R 1779 0 R 1780 0 R 1781 0 R 1782 0 R 1783 0 R 1784 0 R 1785 0 R 1786 0 R 1787 0 R 1788 0 R 1789 0 R 1790 0 R 1791 0 R 1792 0 R 1793 0 R 1794 0 R 1795 0 R 1796 0 R 1797 0 R 1798 0 R 1799 0 R 1800 0 R 1801 0 R 1802 0 R 1803 0 R 1804 0 R 1805 0 R 1806 0 R 1807 0 R 1808 0 R 1809 0 R 1810 0 R 1811 0 R 1812 0 R 1813 0 R 1814 0 R 1815 0 R ] >> endobj 1712 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 667.528 297.029 675.398] /Subtype /Link /A << /S /GoTo /D (146) >> >> endobj 1713 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 656.604 297.029 664.574] /Subtype /Link /A << /S /GoTo /D (135) >> >> endobj 1718 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 645.679 297.029 653.649] /Subtype /Link /A << /S /GoTo /D (107) >> >> endobj 1719 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 634.755 297.029 642.725] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 1720 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 623.831 297.029 631.352] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 1721 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 612.657 297.029 620.428] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1722 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 601.982 297.029 609.952] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1723 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 554.758 297.029 562.628] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 1724 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 545.577 297.029 551.803] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1725 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 534.652 297.029 540.879] /Subtype /Link /A << /S /GoTo /D (116) >> >> endobj 1726 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 523.728 297.029 529.955] /Subtype /Link /A << /S /GoTo /D (99) >> >> endobj 1727 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 511.06 282.182 519.03] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1728 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 511.06 297.029 519.03] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 1729 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 501.88 297.029 508.106] /Subtype /Link /A << /S /GoTo /D (99) >> >> endobj 1730 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 489.212 297.029 497.182] /Subtype /Link /A << /S /GoTo /D (72) >> >> endobj 1731 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 478.287 297.029 486.258] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 1732 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 467.363 297.029 475.333] /Subtype /Link /A << /S /GoTo /D (108) >> >> endobj 1733 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 458.182 297.029 464.409] /Subtype /Link /A << /S /GoTo /D (96) >> >> endobj 1734 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 445.514 297.029 453.485] /Subtype /Link /A << /S /GoTo /D (127) >> >> endobj 1735 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 434.59 297.029 442.56] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 1736 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 425.409 297.029 431.636] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1737 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 412.742 297.029 420.712] /Subtype /Link /A << /S /GoTo /D (160) >> >> endobj 1738 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 401.817 297.029 409.688] /Subtype /Link /A << /S /GoTo /D (161) >> >> endobj 1739 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 390.893 297.029 398.863] /Subtype /Link /A << /S /GoTo /D (165) >> >> endobj 1740 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 343.668 297.029 351.639] /Subtype /Link /A << /S /GoTo /D (109) >> >> endobj 1741 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 332.744 297.029 340.714] /Subtype /Link /A << /S /GoTo /D (110) >> >> endobj 1742 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 321.82 297.029 329.79] /Subtype /Link /A << /S /GoTo /D (110) >> >> endobj 1743 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 312.639 297.029 318.866] /Subtype /Link /A << /S /GoTo /D (160) >> >> endobj 1744 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 299.971 297.029 307.941] /Subtype /Link /A << /S /GoTo /D (87) >> >> endobj 1745 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 290.79 297.029 297.017] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 1746 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 278.123 297.029 286.093] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 1747 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 268.942 297.029 275.168] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 1748 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 256.274 297.029 264.244] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 1749 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 247.093 297.029 253.32] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 1750 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 236.169 297.029 242.395] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 1751 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 225.244 297.029 231.471] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 1752 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 214.32 297.029 220.547] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1753 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 203.396 297.029 209.623] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1754 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 190.728 297.029 198.698] /Subtype /Link /A << /S /GoTo /D (145) >> >> endobj 1755 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 181.547 297.029 187.774] /Subtype /Link /A << /S /GoTo /D (154) >> >> endobj 1756 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 168.879 282.182 176.85] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 1757 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 168.879 297.029 176.85] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 1758 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 157.457 297.029 166.423] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 1759 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 110.233 297.029 118.203] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 1760 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 99.308 297.029 107.278] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 1761 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 88.384 297.029 96.254] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 1762 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 77.46 297.029 85.43] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1763 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 664.173 507.153 672.144] /Subtype /Link /A << /S /GoTo /D (31) >> >> endobj 1764 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 664.173 522 672.144] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 1765 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 653.356 522 659.583] /Subtype /Link /A << /S /GoTo /D (72) >> >> endobj 1766 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 640.796 522 646.923] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 1767 0 obj << /Type /Annot /Border [0 0 0] /Rect [488.722 626.492 502.545 634.462] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 1768 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 626.492 522 634.462] /Subtype /Link /A << /S /GoTo /D (115) >> >> endobj 1769 0 obj << /Type /Annot /Border [0 0 0] /Rect [488.722 613.931 502.545 621.901] /Subtype /Link /A << /S /GoTo /D (114) >> >> endobj 1770 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 613.931 522 621.901] /Subtype /Link /A << /S /GoTo /D (115) >> >> endobj 1771 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 603.114 522 609.341] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 1772 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 588.81 522 596.78] /Subtype /Link /A << /S /GoTo /D (113) >> >> endobj 1773 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 576.249 502.545 584.219] /Subtype /Link /A << /S /GoTo /D (97) >> >> endobj 1774 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 576.249 522 584.219] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1775 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 563.689 522 571.659] /Subtype /Link /A << /S /GoTo /D (113) >> >> endobj 1776 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 551.128 522 559.098] /Subtype /Link /A << /S /GoTo /D (112) >> >> endobj 1777 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 538.568 522 546.538] /Subtype /Link /A << /S /GoTo /D (114) >> >> endobj 1778 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 526.007 522 533.977] /Subtype /Link /A << /S /GoTo /D (113) >> >> endobj 1779 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 513.446 522 521.417] /Subtype /Link /A << /S /GoTo /D (112) >> >> endobj 1780 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 500.886 502.545 508.856] /Subtype /Link /A << /S /GoTo /D (97) >> >> endobj 1781 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 500.886 522 508.856] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1782 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 488.325 522 496.295] /Subtype /Link /A << /S /GoTo /D (115) >> >> endobj 1783 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 475.765 522 483.735] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 1784 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 463.204 522 471.174] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 1785 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 404.035 522 412.005] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 1786 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 393.218 522 399.444] /Subtype /Link /A << /S /GoTo /D (164) >> >> endobj 1787 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 378.914 522 386.884] /Subtype /Link /A << /S /GoTo /D (118) >> >> endobj 1788 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 368.097 522 374.323] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 1789 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 353.792 522 361.763] /Subtype /Link /A << /S /GoTo /D (163) >> >> endobj 1790 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 341.232 522 349.202] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 1791 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 328.671 522 336.641] /Subtype /Link /A << /S /GoTo /D (112) >> >> endobj 1792 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 316.111 522 324.081] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 1793 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 303.55 522 311.52] /Subtype /Link /A << /S /GoTo /D (115) >> >> endobj 1794 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 292.733 522 298.96] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 1795 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 278.429 522 286.399] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1796 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 265.868 522 273.839] /Subtype /Link /A << /S /GoTo /D (79) >> >> endobj 1797 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 253.308 507.153 261.278] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1798 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 253.308 522 261.278] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 1799 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 242.491 522 248.717] /Subtype /Link /A << /S /GoTo /D (119) >> >> endobj 1800 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 228.187 522 236.157] /Subtype /Link /A << /S /GoTo /D (119) >> >> endobj 1801 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 215.626 522 223.596] /Subtype /Link /A << /S /GoTo /D (125) >> >> endobj 1802 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 203.066 507.153 211.036] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 1803 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 203.066 522 211.036] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 1804 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 190.505 522 198.475] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 1805 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 177.944 522 185.914] /Subtype /Link /A << /S /GoTo /D (36) >> >> endobj 1806 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 165.384 522 173.354] /Subtype /Link /A << /S /GoTo /D (31) >> >> endobj 1807 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 152.823 522 160.793] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 1808 0 obj << /Type /Annot /Border [0 0 0] /Rect [488.722 140.263 502.545 148.233] /Subtype /Link /A << /S /GoTo /D (108) >> >> endobj 1809 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 140.263 522 148.233] /Subtype /Link /A << /S /GoTo /D (127) >> >> endobj 1810 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 127.702 522 135.672] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 1811 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 115.141 522 123.112] /Subtype /Link /A << /S /GoTo /D (125) >> >> endobj 1812 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 104.324 522 110.551] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1813 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 90.02 502.545 97.99] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 1814 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 90.02 522 97.99] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 1815 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 77.46 522 85.43] /Subtype /Link /A << /S /GoTo /D (114) >> >> endobj 1830 0 obj << /D [1828 0 R /XYZ 90 720 null] >> endobj 1827 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F2 1382 0 R /F38 1381 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1925 0 obj << /Length 5627 /Filter /FlateDecode >> stream xÚíIsÜȱÇïú<’Ã2jÃrðal?9ì°gïbûuƒ$B½ðÝ’åOÿªP+ÀÊ,ÏPu“ЉQ­df#µ/ЋBýG/šâ¢âœ4¢¾Xm_öÓ÷¯¨ýéZ\Gxûêw¯%½ iІ^¼½]¼]_üã’ÅÕ5«Õg—¼ívwý®»ºæ\\~`úO~9t·ÝÐíVÝÕ¿ÞþõÕÿ¼õÁ$c™o£-}Š]PA¸(™ý:e-åÂ|t”ß½f5iÊRhõHT¹Pa,Ú­þ†‚]®ö›M?öûù^G¿$ÒÐRýîô;äêšVÔüÁfÃ>üÅ¿ðÄÙ/,h(„¤¦ü¢¬ Bk®Ó­¸OÿqVבÙD%NøÒÕ”BZ=ŠØT¤`M1QœQ—E¬*l°¾¿ªËË· ®¬ e#žÆõ$`ö/ñ¨gP0ƒÅ)Ã_( $¤TT„6šjî¶íø>‘~^ñÔìŸÓ°æ¿ëØ~̦0×%3¸KŒiÈD\¡è‘ˆ ½lJR³P7!ôʉš=}CŸ@ïR˜A™èg4`ô‘+ =Q£¯K=öèuËûQ‚öÃ{Ó6¿^Ý8š¦ù­ž ínܨö:9ñ¥j†TT_qæ ²šÌ`@qΤW( $¢TIR— 6t°pöÐu2ÉNµëtšé:#3°ëœe ™*F¾PFHHͨ”jŒú«*Ñ~HqÔÔ”Ó¯ BcŸ0‡&˜ÁhâdQÙ€h‚/ R£‘‚4E… éͤ¯nÛUç¤c÷AÚ í&‰§ Bò“­Gö™s°‚ +NŸj>@XÁ ©a Aó°>šê2~ÝöŠ^8êƒãÃÕrªì<=ÝÜœÈêÄc föÑsÌ‚Ì,Î"-ÁiCä e†„ÔÌâÅüÝm²5S3øæ¥Ÿ¼Þ&Ã>:€Ylw$013 Wjts%$¢. ŒQÚ`?¼¾1uøŸ›.Tmói»[›Öýh›ç•n‡ï»•n¸ßë%‚Dù”Pñ%å1ö±r8‚Œ#ÎPã®PHDCÕÆ¦^âØîfÑÅþU!ÙOMìºÛÌШáæñ°÷æ]²ÝjôR~¾Ñ DÀ>IŽ@0ƒ ÄI©á)Wp…@"j#²h|‹9I>™­KM»¡Œ~ÛrŠ‚Mi®(3¸(Ät¶1¸B‹QѰÉÎTÆ¿Ü|ç6Tý3+¤³O=x—†^ñ“.!À°Ç% 3ì‰ÌÀaÏ,—Èjiä #‡…ÔäjJ¤p•xï‚ýŸ÷D‹bZ-Ó†•`ÚÏ?þU\¬Õ?þõ¢˜¦,'ÓíS­¥Þ3Ü\ܼúùq4=Œ­j6¹înÛãæˆ«š ÎùçˆË¥òÀçqU™ûvíI»³b*½tëþî½ë’HÎϯá‡úk›˜\Ìàþ:ÎqÎÚ"W(P$¢Êš†°ªŒîí!¬½ùó~¯7Ò:·¥9t+5:N5lòv’µ ç2!™äfÉàÚ}ä #‡EÔäêšT Jn«YŽödЬzš-ëô¡­’°²>½SA6Åö©s´‚L+N |B5r…ÒB"jZUM8]ÐrG¶-p&@¯€=ï{zf›®æ`cŽ3ŸKˆ\¡˜‘ˆs©‚òj†ùÐ ;Çù0—îý%·Êmj¥Ý&ý¨mº.}K‹Õä·­!û¤9BÁ &'­ת"W(!$¢&$+Âe寝ßÛ3!îÜÎDã­;4j„TÅíH`ôéR}Ffàès–M*ÀK‘/”R³%©«:ª]]7Ì»ªägvzqE/ݤîÐo»q>ç[ítçù X„)ŠæTaôCç@Õ¸XŠÏ[ ž-³.P85¨Ô@+NÜ6…bó¡ï>úÖq¼ï6›Õ~»U3¾¸WžÀau i´–iƒØ0Æ9BùO( 8žÆQrRøªÒ›îèuŸlyE*A¿ÝÐOV=“Ç\íóVpŒ€ÀS‡àE‡Óè%#²¤žý‡i·Ð¿ÞÚ:Ç $E%XùL¶¡úl”«ÐÁ ®Ñq®)ÏhG¾P°HHMV0RÔŽì›þlupööÖØuënÞþ/%{Þc S%—úp­Õudöî•ٰÑO(Z$ FË)) _iM%]é}@­ggE¼öÆ.yªþÖ'©çéõ׿*Wƒ\ã´S×ßà …Œ„Ô%”1²Ù±è¦…¸÷Adîßýx˜ôLÍ1½[`¯â·:ä ¡±O˜CÌ`4q²(Òe_($¤F£‡ "‡Æ]`ŽXDÐ3”q„XÚ”äX3˜eœ]ÊÁ½ßÈÊ ©Y¡e†åØßíÚÍ );«S’B›‰Â`#Œ“ŠUÇà Eˆ„TõªµÓðýéønÓ¯L3ø~ºšô)yPyì ]ç?Ýù0o± ÌÌ[‚8o‰I”à (8 #á´Àw£ šg>Üuß¹®O=ëT7Çõl½'=…©kõÅŸÁ&£ÍGa°Ɖ…—‚# á"Üü@+W?7k£ÿœÕFÿù¸·Ç¥T³|Ћô2yx½,çÕ ’GךZ|—GwV¨XùÒ•ÙüªRòø¸4ú$¿Œ”¡¬¤= ô&[Þ´»µWNÖã¬ãVÿÿ½µ˜<×ÎHY=—F‚ÏÊ©ÎÁf0|kc§;IøÁ ‰äÑSI*'GiÀþÅŒõ‘‚éÁÄùö¸[šªí”žï Ì'ݦ"Ç/˜Áüâ¬r‘äÜ€üHž_! Ž_×Úæ¹†vž±ô¬Ò¹?P—è¡¢>Û6bjÓ“cÌ`¦q¦i™dÜ€L‘HŽ©l©œ¼åÁôоK"U³,Øù°\æ]>2#3â,µ4Y1#7D,’‡8ÍM#ˆß{|‰9QI Ê_ºX‡‡dS—ãÌ`Þ1…t¥Ü€¼‘HžwÅI]D¼áM<}!ü…ÞûÊ€·9Ìf0øåIðÁ ‰äÁ—œp'ÈéÀ'Oj²”?ÕTMÙê³-K›–Ë`³Œ3œMEn@–H$ÏR2R‹ˆå$æ t¯BQóW“!Þ6u9ÞÁ æS:éàäDò¼õëgJÏ{u¦¾%® $'µZ¨«~&wô!¬6C9¬Á Æ'ûñ¡Ð kpbE"y¬œ’Ú ~¾éÖf¸ë–m¸ˆ¿mWÃ~Lk.²¦>Ãü>Ù69nÁ ægSInÁ È ‰ä¹1JDá¹é·P|˜NbZ›~÷>©•!'ž´ÜXÔ„V•ÏÙZ]Gf!/\Ù2éSðRFByÊú}¡ÌSÞî5âp@?e_KUŠøÏi]¾mr肌.Î'M]ð¢CBytEA„Sº|Œ.~µ×lb&z›~É^IÊ/Ö—B ìÓä3˜Aœ˜„<íÄ ø ¡Q7ê3Ï`×n£[`ÐP¥œ4êžñPè]²2Ý`dvƒ³¼WÉ2rÆ"yÂUCB%{Ø´«aS¥ÞE‹ºkL‹‰p!ίg„hšÄä`z+˜e”á*9ÁN@’p²lˆ;´¦@š·šŒ½^ ØŸâýqU‹ËZý²ìäû˜$ÕW¹˜Q1O™£â­`*QºdrÓ+8©Àa<Yi7V‡nÜo>Õ~w›žá³‚¾œ>ÐOÚ„eºÉ`ö’qæ© IÂÞ HŽã ‹š~·zBl.túKºÖ݇ÞÒ|ò=—¯³úæ2m3cÌ`hq2!jÁˆ å¹ñŠÈ*âvÜAÚpm,1ÿã¤büÎÿ\¾r”ƒL9N}âµRåऌ„ò”YEŠ&P>´ƒ½ñŸ½9HÒ»[ó]»Þ¸c¡“žžøê .O _t)µÏ™£Ì`:qÊçr':ÁH åéÐr"ðt†ÞÝŸfòòpß™Æþ?ÓO¬¥©OÞõ»vÔ¨ŸÝDÄüÎÞ ó-€—¼CÕ˜µ*×fhða¿nnôÌàáGüä"=* nÀ#‘|Ž‹’PžÌ±Þοw‚G&ÇæÁl‚7»^bÏ]ÙC˜`^eCª§tiû,9Á §Ü€HÀLÍùMgG£[g4MÎþýña!€tó¾ø_½%Ô ýí'`p^Ôô+êP¹&×¾ö­¦D½t½ÓS§¾žÀ`¡<˜X“yØ®ûäiBVþ’Æå¿?ª“ð#ªÕKWØú".’mð#¡<þXªùÍþÐüÚâFk6fÏ”ë-9úûkâ‘Í[Žv0ƒiÇh™œDE~@Ú‹Pé+œ*+wfé&{¥b\µjöä4 6ãïÓÛÜ¢ª_À¨èøpAjßñaòÐKW€²œæŒ‹QO%‹äÊÁLLy´wÆ×Gà>«P_O~{)À‚;*m¸#BÓKWf‹!¹‡‡ËZîH$Ï=VW¾Y ýÃa\¼jÙ¼aÓž5»Ý[h5Z¯lIù5.¬2®BíeLzéÊN.d *Am ¡<’XNÙ"±[nŠ„¹Îh‡:M´Î’Rô/Õ÷?µ-¨¡šÔ¡! ÑKWÈz\ÚàB"y\±„òMצñtÀ&êÑÔ¤~—JU%)¹—Š»íÓF5”ªOõõÛMT¦:ÐD4£—®…ñ‰&ªPmh"‘<ÍX>9Ðô“‹[÷b³ûýÖk梯Ô`âéïcø¬Ýª5° ÊÏKWÀû2&,¨Î´Á‚DòXb¥äÛ2¶k3$Ý­’«ÊúbŒ(Ïÿ8.>z4D zéÊK.QåiC åéÅÉ7úøºIðƒ~ÃIjÒ-)‘UõrÏ4¸*†ÊT‡ÚŠˆF/]aƒJT¢ÚðF"yÞ±¬òÄ»?D‡À-2ž$Îeód#¡ºêZ‡º¨L/]a;!¸¨µa„ò¬cqæëZ^ZÅ•éÔŸAß®ºq±Yu0÷M?@Çæ)çD_xZ1AU¬DRzé ÛžÀ¬ $”c2SP»õìenÓì!)wD‹æÛ-1ÓVârÖ¾ÙÅÄ¥—®ÌNr„KYOرH»Ód¾é6±˜ül7¾ß9mO7ˆßW yâóF[µ`=k_C!¥éØ6‚Ŭ ž_V•š ór©á0Ýöú³¾oœ‹nʳWôU¾• ¢^8Þq3ñÂ4¯ 28Œ§i,'¨ý­k×Ý~G ¯šó´@Ū/X=záã… U^pÏ+VO¾évcÿnÓ%åüõ‘¥äý“†eý¼Æ \Tµ:ÐE$¤—®™.Xm#‘<áXByNxÓ+¾ÛÞ-_»ëÑQçÇ|ç×ÎWn’'¤D£žíóUbˆ*/( jÏKWT[ÚP@"y ±ÊñMwÐïñ RÉí¢'_ïyvÛE¸êt H@/]á‰ä†1.8mÈ#‘<ùXDY‘çžV›VÕ¿°ñ®£»Í¾Ûï®Ý1év^8––a´þüç@qEévDÞyé ÙÅŤMÚ‘H>í±Þñ,íÇÞîÒ¹ön0ÕÝ난\ñ¤Uœœ]WOoç~é2&.íˆ.óÒvä—6PžB,Y|ãNãš’ŒöZ¦ö¹èoüŠ…-\5:ÐF$œ—®ìõÿ4mT1ÚÐFB9Ú±Pñ~á»”µÕ¯S«WîMmÝJUEBÐlš§·ƒøI¼F=DbyáÈΞ“›s¨œóD‰ã€Ä²Ã7÷Ó•þ¹‘‡ÔZòT=¼ÓC¥Ÿ}Ÿ‡H?/!”ìóÿH £ endstream endobj 1924 0 obj << /Type /Page /Contents 1925 0 R /Resources 1923 0 R /MediaBox [0 0 612 792] /Parent 1615 0 R /Annots [ 1816 0 R 1817 0 R 1818 0 R 1819 0 R 1820 0 R 1821 0 R 1822 0 R 1823 0 R 1824 0 R 1825 0 R 1826 0 R 1831 0 R 1832 0 R 1833 0 R 1834 0 R 1835 0 R 1836 0 R 1837 0 R 1838 0 R 1839 0 R 1840 0 R 1841 0 R 1842 0 R 1843 0 R 1844 0 R 1845 0 R 1846 0 R 1847 0 R 1848 0 R 1849 0 R 1850 0 R 1851 0 R 1852 0 R 1853 0 R 1854 0 R 1855 0 R 1856 0 R 1857 0 R 1858 0 R 1859 0 R 1860 0 R 1861 0 R 1862 0 R 1863 0 R 1864 0 R 1865 0 R 1866 0 R 1867 0 R 1868 0 R 1869 0 R 1870 0 R 1871 0 R 1872 0 R 1873 0 R 1874 0 R 1875 0 R 1876 0 R 1877 0 R 1878 0 R 1879 0 R 1880 0 R 1881 0 R 1882 0 R 1883 0 R 1884 0 R 1885 0 R 1886 0 R 1887 0 R 1888 0 R 1889 0 R 1890 0 R 1891 0 R 1892 0 R 1893 0 R 1894 0 R 1895 0 R 1896 0 R 1897 0 R 1898 0 R 1899 0 R 1900 0 R 1901 0 R 1902 0 R 1903 0 R 1904 0 R 1905 0 R 1906 0 R 1907 0 R 1908 0 R 1909 0 R 1910 0 R 1911 0 R 1912 0 R 1913 0 R 1914 0 R 1915 0 R 1916 0 R 1917 0 R 1918 0 R 1919 0 R 1920 0 R 1921 0 R ] >> endobj 1816 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 670.183 297.029 676.41] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1817 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 659.703 297.029 665.83] /Subtype /Link /A << /S /GoTo /D (161) >> >> endobj 1818 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 647.48 297.029 655.45] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 1819 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 637.001 297.029 644.971] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1820 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 626.521 297.029 634.391] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1821 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 616.041 297.029 623.912] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1822 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 607.305 297.029 613.532] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 1823 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 596.825 297.029 603.052] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 1824 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 586.346 297.029 592.572] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 1825 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 575.866 297.029 582.093] /Subtype /Link /A << /S /GoTo /D (161) >> >> endobj 1826 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 565.386 297.029 571.613] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 1831 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 553.163 297.029 561.133] /Subtype /Link /A << /S /GoTo /D (111) >> >> endobj 1832 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 542.684 297.029 550.654] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1833 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 533.948 297.029 540.174] /Subtype /Link /A << /S /GoTo /D (51) >> >> endobj 1834 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 521.724 297.029 529.695] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 1835 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 512.988 297.029 519.215] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 1836 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 500.765 297.029 508.735] /Subtype /Link /A << /S /GoTo /D (51) >> >> endobj 1837 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 490.285 297.029 498.156] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1838 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 481.549 297.029 487.776] /Subtype /Link /A << /S /GoTo /D (69) >> >> endobj 1839 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 469.326 297.029 477.296] /Subtype /Link /A << /S /GoTo /D (144) >> >> endobj 1840 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 460.59 297.029 466.589] /Subtype /Link /A << /S /GoTo /D (120) >> >> endobj 1841 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 448.367 297.029 456.237] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 1842 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 437.887 297.029 445.758] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 1843 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 395.652 297.029 401.431] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 1844 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 383.429 297.029 391.399] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 1845 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 372.95 297.029 380.92] /Subtype /Link /A << /S /GoTo /D (163) >> >> endobj 1846 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 362.47 297.029 370.44] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 1847 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 318.492 297.029 326.462] /Subtype /Link /A << /S /GoTo /D (133) >> >> endobj 1848 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 308.012 297.029 315.982] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 1849 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 299.276 297.029 305.502] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 1850 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 287.053 297.029 295.023] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 1851 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 276.573 297.029 284.543] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 1852 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 266.093 297.029 274.063] /Subtype /Link /A << /S /GoTo /D (97) >> >> endobj 1853 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 255.614 297.029 263.584] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1854 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 245.134 297.029 253.104] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 1855 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 234.156 297.029 243.123] /Subtype /Link /A << /S /GoTo /D (31) >> >> endobj 1856 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 224.175 297.029 232.145] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 1857 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 213.695 297.029 221.665] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 1858 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 203.215 297.029 211.186] /Subtype /Link /A << /S /GoTo /D (161) >> >> endobj 1859 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 192.736 297.029 200.706] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 1860 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 182.256 297.029 190.226] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 1861 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 171.777 297.029 179.747] /Subtype /Link /A << /S /GoTo /D (144) >> >> endobj 1862 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 163.04 297.029 169.267] /Subtype /Link /A << /S /GoTo /D (31) >> >> endobj 1863 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 152.561 297.029 158.787] /Subtype /Link /A << /S /GoTo /D (119) >> >> endobj 1864 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 142.081 297.029 148.308] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 1865 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 129.858 297.029 137.728] /Subtype /Link /A << /S /GoTo /D (129) >> >> endobj 1866 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 119.378 297.029 127.348] /Subtype /Link /A << /S /GoTo /D (131) >> >> endobj 1867 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 108.899 297.029 116.769] /Subtype /Link /A << /S /GoTo /D (130) >> >> endobj 1868 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 98.419 297.029 106.389] /Subtype /Link /A << /S /GoTo /D (131) >> >> endobj 1869 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 87.939 297.029 95.909] /Subtype /Link /A << /S /GoTo /D (65) >> >> endobj 1870 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 77.46 297.029 85.43] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 1871 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 668.439 522 676.41] /Subtype /Link /A << /S /GoTo /D (77) >> >> endobj 1872 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 626.205 522 632.431] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 1873 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 613.483 522 622.45] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 1874 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 603.502 522 611.472] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1875 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 593.022 522 600.992] /Subtype /Link /A << /S /GoTo /D (14) >> >> endobj 1876 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 582.543 522 590.513] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1877 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 573.806 522 580.033] /Subtype /Link /A << /S /GoTo /D (13) >> >> endobj 1878 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 561.085 522 570.052] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 1879 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 552.847 522 559.074] /Subtype /Link /A << /S /GoTo /D (14) >> >> endobj 1880 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 542.367 522 548.594] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 1881 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 531.888 522 538.114] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 1882 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 521.408 522 527.635] /Subtype /Link /A << /S /GoTo /D (113) >> >> endobj 1883 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 509.185 522 517.155] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1884 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 498.705 522 506.675] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 1885 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 488.226 522 496.196] /Subtype /Link /A << /S /GoTo /D (73) >> >> endobj 1886 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 477.746 522 485.716] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 1887 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 467.266 522 475.237] /Subtype /Link /A << /S /GoTo /D (52) >> >> endobj 1888 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 458.53 522 464.757] /Subtype /Link /A << /S /GoTo /D (141) >> >> endobj 1889 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 446.307 522 454.277] /Subtype /Link /A << /S /GoTo /D (141) >> >> endobj 1890 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 437.571 522 443.798] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1891 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 425.348 522 433.318] /Subtype /Link /A << /S /GoTo /D (130) >> >> endobj 1892 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 414.868 522 422.838] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 1893 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 404.389 522 412.359] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 1894 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 393.909 522 401.879] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 1895 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 385.173 522 391.399] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1896 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 372.95 522 380.92] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 1897 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 362.47 522 370.44] /Subtype /Link /A << /S /GoTo /D (134) >> >> endobj 1898 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 351.99 522 359.96] /Subtype /Link /A << /S /GoTo /D (161) >> >> endobj 1899 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 341.511 522 349.381] /Subtype /Link /A << /S /GoTo /D (160) >> >> endobj 1900 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 299.276 522 305.502] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 1901 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 287.053 522 295.023] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 1902 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 276.573 522 284.543] /Subtype /Link /A << /S /GoTo /D (145) >> >> endobj 1903 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 266.093 522 274.063] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1904 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 255.614 522 263.584] /Subtype /Link /A << /S /GoTo /D (97) >> >> endobj 1905 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 245.134 522 253.104] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 1906 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 234.654 522 242.625] /Subtype /Link /A << /S /GoTo /D (101) >> >> endobj 1907 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 224.175 522 232.045] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 1908 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 213.695 522 221.665] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 1909 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 203.215 522 211.186] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1910 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 192.736 522 200.706] /Subtype /Link /A << /S /GoTo /D (76) >> >> endobj 1911 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 182.256 522 190.226] /Subtype /Link /A << /S /GoTo /D (101) >> >> endobj 1912 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 171.777 522 179.747] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 1913 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 163.04 522 169.267] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 1914 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 152.561 522 158.787] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 1915 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 140.338 522 148.308] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 1916 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 129.36 522 138.326] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 1917 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 119.378 522 127.348] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 1918 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 108.899 522 116.869] /Subtype /Link /A << /S /GoTo /D (130) >> >> endobj 1919 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 100.162 522 106.389] /Subtype /Link /A << /S /GoTo /D (110) >> >> endobj 1920 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 89.683 522 95.909] /Subtype /Link /A << /S /GoTo /D (107) >> >> endobj 1921 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 76.962 522 85.928] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 1926 0 obj << /D [1924 0 R /XYZ 90 720 null] >> endobj 1923 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F2 1382 0 R /F38 1381 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1994 0 obj << /Length 3794 /Filter /FlateDecode >> stream xÚíëܶÀ¿ç¯¸oݼŒø”T _šÔ@ÚmáK\´)PÝ®Î'ܾ*ií\þú’âS»2©Ýøî6’{d<³œ‡rH_ò|UW%¥¨fÕÕjûEa~ûð6ß-¥À2øýÍ_¾æø ¨.j|usª¸Y_ýsñÕ}sÛþzI)]T¿½^2Æ_íw«ö0ê_~³[·?\/‰àu¹ ¾þ×Í¿øÃ3Ê É|*%qö±ÈU…j!˜ùP¢bS¦?Ô›n÷nÓJóŒ,6ÝîaP6¿|M«àÏ0*ΤéO ë%.±þBf?ýì_~-ŸÜÞ‰×IE)¸ó›t«ä<ýÏÀóVjˆyÿTÕäPŒÉ™ÉºD©C“ØV*iR/)bu}ü?²Å‹ãþ/Æ6ž3Tzàψ—¨ÂÔ9"®¥–X„ø\Õäɲ{UIà ‹ ¸ ¨Tº±°Å•„Û'¿ŸÔÔ5Œ‹s]ËÁ]#¤Å9Ø5¼ªd×HXT]ƒDHi»ÆÓH@ߘµrجõÏÝN]wCs»‰õŸ²DDþâ™ ]ã¥]/Ó ^Ât½ª$Ý„EE—aÄUö1ôÝá›u»»&õbìîc|„¨.g€p·åp{1wH Ì^Uw¢ÂMe¶É¹ÇýÝu%m¯`OáÛìÖz¦?o7Ýjyè»÷×¼\4£‰ûÕ9ÚÇØä¥mÌŧŽp(¹2MÉ%W^ N®B¯`^ƒ ¼®$ƒ„IÅ€ˆb3±Û)ØCÛ¿¿&•DK§åÌËÊËI§3±gü—‹=/Ç^ˆ"{^U’{¢â^ÔHæÝ&öÍVÔp”³èáзÃÐíw±y“ Zj}ió¦ =ã”\{18ŠCÿbÁ@š^W’f¤¤Éëv¡þæ ×àrX”$WÝZ#=ÊE“HU¢´1ƒ§JŸb#gY£š>ÃeÕú&5¡ÎÜŒYA t¥ ¦L*¨U…&ê¦QƒóãM·mÃ$—,Vãþ ת@˜=ÃeÄÒ¸$ÇÒ‹Á,CïbQ€,½®$Ë„IÅR®7ÊR˜iö°éÆXÊR¡ª¨]ÓÆ:€šw„p~:€‘ZbçàD•îçiVE®Hh1ÆßH¥-ž¨š,¾‚2ŠLmF‘68W•É(2Mt]L[¦ï̪ñëfln›Á”PÿvlÙ»ª_t‡"Ð40^ ŽÀÐW˜Âْו$“0©ÈQb÷·‡ƒž){“ßí{ýÍ®ý i ÃØn£4 ¹„ O­Ô3íÎób0°Ð…XÀC¦×•–0)±š QÙÍðãpèVÝþ8ìš-”ÓpN^Öz­g2ƒc Ž3'Ã9M *E4eQ•Kï‚Û%ˇnœFÄ{³J{¹$¥úÛÛk< ˜Õâáx8ÙaÛ¦½·X`bùAðçO~ n¦ý9n^ æºRP›W•ä–°¨¸Éœ’áê§r;v›qi‹þ«M3 ñ9 T”Ÿk‚eƒåÅ`X¡ÿ0˜ª’°,Q ²²ÕSñV¯ 7ÝJCÙtÓîAíT:¨,®f½î†Jãµx¢e`ⳎÈL|8ñÍ|š¨º’&A®êâ'|¥6·Ã~sŒžÏª+TòêyÑ3NÈÑób0½ÐŸåו¤—0©èÑqüsáõí¦;]çd¨,Ù“Nn ŽÚ9ŒN ¦ø5ÑiJ2„í)„¤BUi&W¹ ƒblg• RÒ_wVSs¨qdnõbð2I$ª^U’¢ê¸B„ÚÕÇáÏûwß¼ÿâXG+A^@Gø¤çÜ 6ãÉ\ðbp¡P8‹òª’=àÄbI®0C”IºÐJ ª6îFc?Vqµ”€”ÄJ¨ÓrۃƣÙ.#ˆÕå¥v wÐR® ÉõŽ@ ìV&Sy T¥zGʢ꣺!ùatË!¸°*3ò"vu?®ÚjÝ—ÃîÅ`ì! ì T%±',*ì#j¶¿nºõ£]òN»zµ;vÛÖ¤t[•Ì©Ÿe²gŠ6Íôcl)\Ë¥ðçØ·²6ÓÒLÖæ¥À¬-tfàÂÉkJâí):L®ªlíÝãÙìg§í†Ùv/Y‡¶…j-•Ñç4©C±f¼’‹5/ÇZèàK¯* 3aQѤÅަ^Û­:;ªèz Ükµ™=tÇpõbÝY¿äBÓ‹Á±º8q€2Еš0©€Ê1Ž1šÄ'C¾¨ÈÃx·åx{1˜wH3ðÞ` +ÉûÄ$Å'À u‚ÒÔ]ÕÄ·?Ž¿;Ï£Õ0àVÑvr¸o7›•ºLºÝ6»uô`4CÅÇÞ(ù?”Ûl«s¼¼Ì+t fà–G +É+aRâ"u…dËl|N¸ÌæðúØ»`íÆ¶—iÌ~ßÒ/¨ÙÓÛÒ×µM̰ Ä@63oa®7])6)“Šœ¹Ë<ÕzcoO{é3$;7’ÅÞÜ8ØùÑU]Æ´™OÛ÷û>ZÔèÉ ’ëLRˆIÍ̵œUIŽ ‹Šc©öêãq*rÞŸÜ ‰Î„²‹ê2Nåš 3îÊÅ«ƒã5ô<.ÀÝ£@W’sÂ$Å Õ2–gï2Œýtaä½ÚóßÈpìlõ-ºˆI}©ûʧ¯”j`,3ïeX©ä㧪 5©zö$ýVÆô0JÊ”ë%E"Ü&ê[sðËbqoöÚšÕ_¿þ|7O‹ *+n=à4BK/uNs®Hße”¥S¢„Í8’‚"<Ûñ뻃¹?t½9½wwÜ­TbÔ¨ÛÓt©ÊÏ£ŒÎTÉ_~xÛò8*+µ ÄΜxªJo œ¿HTÈ‘ÓÐbŒ˜‘JZ«ãè´æ›ûý0F3vŽJŽ/ï¿‹ãµ\ z18C‚GQ{5 êK³-+Çšà鬽f­8ÿ©}^÷ö¶ ™ß”$Â%gú9”¾^9¢2˨ŸÅÜï"̸"¬^ ÖЫ˜ÇgF¯$xbj^¶·y‘½…÷m¼t¯^5ÔGà ©£âE_’c2ñ­J>Ý9†æK+³tBçùÝL p÷‘É•¸zÌÒ©‰ ¶2)[35ñ¼ŽÉ4»$$Ý,#“4ªÑ—œwÜ‚ Îx²]V&al®ÈWM,¥Úå‚2e*Tí.óÐP8ÂF\( „½3rÜ­Û~Xíû>®î/ì…|€‰Ñ:%31bàÄ8ó/Ž.€5 Ç„%G’ ¹¦2æÛÝv4¯Áœ{¯M©=î§zëŠ4Óæ\¬y18ÚB÷a}7Ð’J˜r¤G¢,-©¡ßŒÍØ&Ž0r&•òË«²º(2ˤƒ2t>.J5 æ„%‡Y]9.Ì‘·ªaF+g—¿kÙÐj¿»;Oˆ¸L‹]eá7±Ó‹¨ÂÏlLþ4 ™Ñš8OCÝCK-±H÷˜«ÒÖ¢½Ãk{lj! .äW{Gì»\<=÷h/ÃüÆ]·5KôcnGIŽñôc¹þB'¤ìÀÌÔbgK 8Æ[sI!üoÊ”…˪q{zÆNía±£¾™š‹j1ªJqQ/úv8nFýýþNm´ÈtäBÿfµŸN]Dōм7 «öCf†Õ@ VgíÅÑÀ Ô€žMXrž- TxVæ¬êýES¸ÑYO¿ßÄ.!S„Ù%”hã¬a/ýŽE”°WNXr„yíßÕý®ëÇc³q#ž‚ÛöwÍ*¾:!/¥15îÉ1õb0ÓÐÓ,º: Ô€LO,ŧ;F1âö*û[xºÃVb3wnùÒÜê!ŽöEˆãfã.€Þ „<%"ó>Àéáz1®‘ÑÅ‘ødçÕ€p–ZUγ—¿ÎÀõív?š"ì¶ïõÙ¨uœET<ñ—;\6aZKL¼œ˜„Ä8zæ!вJ˜²¬h-Yý¼í6ëUÓ»*‰:ÎÙÆgMÅ%M›ÚI™tB`¾®£¦S…m8ž2å#vƒÉ=Y Üï·í¡å¼­:Ê^ÃyâAg]jš›cãÅ`:¡çXœWJXrŒJ]iԌ޾5‡¨Õ™z÷v¼=Íj„ÌjØ {3Îa0ÎÉõb0ÑÐÏñã艥x:CÕÓþÜlü=›Îü°nßÇŠXÅTÂxù7Ï*[b½¢2)¬0\ÛÒRË@,RÝš«JЬ’yL]…£.-•¶x¢ ¨rÕ2—ɶP ¥ÍÍAG—L*Ý>WéJ> endobj 1922 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 682.391 297.029 690.361] /Subtype /Link /A << /S /GoTo /D (112) >> >> endobj 1927 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 671.755 297.029 679.725] /Subtype /Link /A << /S /GoTo /D (77) >> >> endobj 1928 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 662.863 297.029 668.862] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 1929 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 652.227 297.029 658.454] /Subtype /Link /A << /S /GoTo /D (75) >> >> endobj 1930 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 639.848 297.029 647.818] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 1931 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 629.212 297.029 637.182] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 1932 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 618.576 297.029 626.098] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 1933 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 607.94 297.029 615.811] /Subtype /Link /A << /S /GoTo /D (164) >> >> endobj 1934 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 597.304 297.029 605.274] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1935 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 586.668 297.029 594.639] /Subtype /Link /A << /S /GoTo /D (160) >> >> endobj 1936 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 576.033 282.182 584.003] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 1937 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 576.033 297.029 584.003] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 1938 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 565.397 297.029 573.367] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 1939 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 554.761 297.029 562.731] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 1940 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 544.125 297.029 552.095] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 1941 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 533.489 297.029 541.459] /Subtype /Link /A << /S /GoTo /D (146) >> >> endobj 1942 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 524.597 297.029 530.824] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 1943 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 512.218 297.029 520.188] /Subtype /Link /A << /S /GoTo /D (135) >> >> endobj 1944 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 501.582 297.029 509.552] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 1945 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 490.946 297.029 498.689] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 1946 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 480.31 297.029 488.28] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 1947 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 469.674 297.029 477.644] /Subtype /Link /A << /S /GoTo /D (10) >> >> endobj 1948 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 459.038 297.029 467.009] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 1949 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 448.403 297.029 456.373] /Subtype /Link /A << /S /GoTo /D (113) >> >> endobj 1950 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 437.767 297.029 445.737] /Subtype /Link /A << /S /GoTo /D (113) >> >> endobj 1951 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 427.131 297.029 435.101] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 1952 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 415.997 297.029 424.963] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 1953 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 370.878 297.029 378.849] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 1954 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 360.243 297.029 368.213] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 1955 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 349.607 297.029 357.577] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1956 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 338.971 297.029 346.941] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 1957 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 328.335 297.029 336.305] /Subtype /Link /A << /S /GoTo /D (148) >> >> endobj 1958 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 317.699 297.029 325.669] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 1959 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 308.807 297.029 315.034] /Subtype /Link /A << /S /GoTo /D (143) >> >> endobj 1960 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 296.428 297.029 304.398] /Subtype /Link /A << /S /GoTo /D (145) >> >> endobj 1961 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 285.792 297.029 293.762] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 1962 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 275.156 297.029 283.126] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 1963 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 684.134 522 690.361] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1964 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 671.917 522 679.787] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 1965 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 661.442 507.153 669.412] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 1966 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 661.442 522 669.412] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 1967 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 650.968 522 658.938] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 1968 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 640.494 522 648.464] /Subtype /Link /A << /S /GoTo /D (160) >> >> endobj 1969 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 631.763 522 637.989] /Subtype /Link /A << /S /GoTo /D (65) >> >> endobj 1970 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 619.296 522 627.515] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 1971 0 obj << /Type /Annot /Border [0 0 0] /Rect [473.875 575.356 483.091 583.326] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 1972 0 obj << /Type /Annot /Border [0 0 0] /Rect [488.722 575.356 502.545 583.326] /Subtype /Link /A << /S /GoTo /D (128) >> >> endobj 1973 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 575.356 522 583.326] /Subtype /Link /A << /S /GoTo /D (143) >> >> endobj 1974 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 566.625 522 572.852] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 1975 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 554.408 522 562.378] /Subtype /Link /A << /S /GoTo /D (151) >> >> endobj 1976 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 543.435 522 552.401] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 1977 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 533.21 522 541.429] /Subtype /Link /A << /S /GoTo /D (2) >> >> endobj 1978 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 489.27 522 497.24] /Subtype /Link /A << /S /GoTo /D (110) >> >> endobj 1979 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 478.796 522 486.766] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 1980 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 470.065 522 476.292] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 1981 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 459.591 522 465.817] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 1982 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 415.905 522 423.875] /Subtype /Link /A << /S /GoTo /D (70) >> >> endobj 1983 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 405.431 522 413.401] /Subtype /Link /A << /S /GoTo /D (119) >> >> endobj 1984 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 396.7 522 402.926] /Subtype /Link /A << /S /GoTo /D (96) >> >> endobj 1985 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 384.482 522 392.452] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 1986 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 374.008 522 381.978] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 1987 0 obj << /Type /Annot /Border [0 0 0] /Rect [478.483 330.068 487.698 338.038] /Subtype /Link /A << /S /GoTo /D (65) >> >> endobj 1988 0 obj << /Type /Annot /Border [0 0 0] /Rect [493.33 330.068 502.545 338.038] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 1989 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 330.068 522 338.038] /Subtype /Link /A << /S /GoTo /D (149) >> >> endobj 1990 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 319.096 522 328.062] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 1991 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 276.899 522 282.678] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 1995 0 obj << /D [1993 0 R /XYZ 90 720 null] >> endobj 1992 0 obj << /Font << /F51 5 0 R /F2 1382 0 R /F38 1381 0 R /F72 4 0 R /F31 21 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1998 0 obj << /Length 120 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h ##M]#  ˜†sZj^zf^ª¦®±±‰F™ˆ6Ö(JMK-JÍKNÕŒ ñâr [fjd„Ý5Q % endstream endobj 1997 0 obj << /Type /Page /Contents 1998 0 R /Resources 1996 0 R /MediaBox [0 0 612 792] /Parent 1615 0 R >> endobj 1999 0 obj << /D [1997 0 R /XYZ 90 720 null] >> endobj 1996 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2024 0 obj << /Length 1763 /Filter /FlateDecode >> stream xÚíZKÛ6¾ï¯pOµ˜å[b/E v‹Hßš¯±%ÃÒf»ÿ>C‘´hY$d·ÙE±©og¨ùæÅ¡ÉÃ?2Qx’1†Ï'Ëí¶«Ÿ.ˆý4ÀÜC<[\üòR ÁHaE&‹¾ˆÅõäïéóU±kËýlΛæ¿Î朋éË!dútFóé_æÉUu]þ;›ÓœÈlJ1›ý³øãâ÷ÅA³ 4±58Ù[F'$C”n÷&sŽãfo° *`ŒtÛÈ„Ýè6Êã’ê?…÷æe83ùÔ`è$GJJn¯¤E¼oêÍM[‚\N§»¢]éOlZT׿C³*gdºÙ,ëí#‘åžH "¹ÑH4›“Œ˜ÿèÑ·¯[˜–æ Q,&’*„ѶF»‡žyjîÁ:û6Šê¶M8?Q©2„©òUŽ0êP'*©V si¹y–äæÙ¾XΨš~ÒX¶áèxWìËJ¯¶«²)X"æáº2¬-7EÐ[L¢Œe÷ÍÖñ³îàÅ ›0<ÏÂÜÔ܃pw,ª{ JCÔy¢bÔ 5žR'ʱKIêžÕÏ­  ¶€²_Êý¾Þ›·«²2¤íËmm"ˆ«wšò»uõqŒ;Á‘Àä¸ •`Ω‚ʃƒÊaLP‰,ÈL/+ÊLD¥æ…‚7qHâÕGm9kÖdj5­›u[ïïŒ}«b lŒ]icîâ«ûØ®ëj4ʼnåBÞ§á­Ûý§"¢‡…#Â7…GD/*j÷ˆFmw"&ÊÙ½4‰ª¹Ù6Æ´mñI¯XC·µ®™ÓÚ|ÛÔ†"³®©‚ⲃ"„.Ï„x—·orùvyß1—ïeEMQ©Mb”m._{^×Ç—MNîP±¹ÕB{ù]ã<»nÅ,¼Ã„oÊQ×§á.±ÅPàX+¤§‡…Ç7¨ vž¨({ÀWIjËIJ]o].BjŸ‘k3Àå)‘Ê#Òç?Â"—H*òà=š±¨{É9,HΑ½Âäx¢bä 5žÔy.¡¶­x®ó6;(«u±1Ư?˜dÖ”ûÏ륥µh[Ûı¢‚ãÀ7qr?±xvÖäz\)SYÓƒ³¦Ãج)‚Ôö²¢ÔTžRKÊ•má.“-Ü¥ßK¸ÓÏ[· lë›v<]ÂùK}NC„A:8ÙÙy°0acK,HX/+JXD%ÐÅ TsóTuks`[´~I2«æô3Æ}â±$Â@Qs¯(j,XÔŽ,(Ãtõ¢¢tE4jº2(iĶ7—µŽ“[Û<v\peøéZÄÏP¯íøGŸ¨ 3Y»Ž½Y•ý,è·1.%¤áü<*Ca7œ Œ ÿÝ#)Ë“µtD¥¶´¤pfÊΰtSºžÎ|·Ŭ}0#jZ›Õ¡1ÃCÝÁpBC,˜ÇÕR|ßM„œMPDE: ÷°°³YLÒÙzYQg‹¨ÔÎÆ B8[kÏÙ˽Ýn´ävú´>dåëu71Š8ÿIå %]û–©¤ÛÃÂI×7XŽƒìô¢¢ì 4·› >«ŒL$‡„AmF¸ öœnWWm¹/ÚC²­ít Nôvh¸Y7£]ggNž?ΓÄ9©ŸƒY¼Q7B—y€n‡š{°º‡¢L4ª“›œ!"˜¯qì¶Æ¢¢‡¢:ON(¹H¼¢CÅD™‰Ÿ»ŒJ¼ž¾Œj÷d}w¡”õä?“ž¼1“¨e±ª›vp7áF§n,3$1ýÜøë»IǾq,é,èè&5Éž˜ 5ÜŠ’pWX¯’nðê…pã- <5&.Žçæ-:{R| ÐáWßÚ œ#’eàÊxrD‹š{°‘x,*4ï<±—ôĪqOä*G2³W䯓žøº]›ž}eªàxÊÉ[]]¢àpPdÁ˦CÎñ`Áœã0ëWÍ£'&ÄôPS€i!åvîô&Éôÿ:u8Ußíë÷ú÷ åÖÍò–§Wµc0¸$8Ûƒº@ˆ5î—³$k=,ÌšÅD*…'&ÈÚ@S€5¬ í¶¬½M²öÖ,˜ÈÜjÞnš~¤´·<Ý®ÍÏTà„ìý|…™Ÿ¯ü_î©0è±’R4U> endobj 2000 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 627.288 297.029 635.258] /Subtype /Link /A << /S /GoTo /D (144) >> >> endobj 2001 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 581.229 297.029 590.195] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 2002 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 535.668 297.029 543.638] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 2003 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 524.972 297.029 532.942] /Subtype /Link /A << /S /GoTo /D (52) >> >> endobj 2004 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 514.276 297.029 522.246] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 2005 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 503.579 297.029 511.549] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 2006 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 492.883 297.029 500.853] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 2007 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 449.066 297.029 455.292] /Subtype /Link /A << /S /GoTo /D (155) >> >> endobj 2008 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 403.759 297.029 411.729] /Subtype /Link /A << /S /GoTo /D (143) >> >> endobj 2009 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 393.062 297.029 401.033] /Subtype /Link /A << /S /GoTo /D (155) >> >> endobj 2010 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 382.366 297.029 390.336] /Subtype /Link /A << /S /GoTo /D (65) >> >> endobj 2011 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 371.67 297.029 379.64] /Subtype /Link /A << /S /GoTo /D (143) >> >> endobj 2012 0 obj << /Type /Annot /Border [0 0 0] /Rect [283.205 352.256 297.029 358.034] /Subtype /Link /A << /S /GoTo /D (143) >> >> endobj 2013 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 339.816 297.029 347.786] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 2014 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 627.325 507.153 635.295] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 2015 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 627.325 522 635.295] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 2016 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 581.895 522 589.865] /Subtype /Link /A << /S /GoTo /D (65) >> >> endobj 2017 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 527.747 522 533.526] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 2018 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 484.315 522 490.542] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 2019 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 439.139 522 447.109] /Subtype /Link /A << /S /GoTo /D (65) >> >> endobj 2020 0 obj << /Type /Annot /Border [0 0 0] /Rect [508.177 384.992 522 390.77] /Subtype /Link /A << /S /GoTo /D (144) >> >> endobj 2021 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 339.816 522 347.786] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 2025 0 obj << /D [2023 0 R /XYZ 90 720 null] >> endobj 2026 0 obj << /D [2023 0 R /XYZ 90 720 null] >> endobj 2022 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F2 1382 0 R /F38 1381 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2030 0 obj << /Length 120 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h #M]#  ˜†sZj^zf^ª¦®±±‰F™ˆ6Ö(JMK-JÍKNÕŒ ñâr [fjd„Ý5RB%’ endstream endobj 2029 0 obj << /Type /Page /Contents 2030 0 R /Resources 2028 0 R /MediaBox [0 0 612 792] /Parent 2027 0 R >> endobj 2031 0 obj << /D [2029 0 R /XYZ 90 720 null] >> endobj 2028 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2075 0 obj << /Length 2273 /Filter /FlateDecode >> stream xÚíœßsÛ6ÇßóWèQz0x¼¦i¯7íM¦ñÝÍÜV¦mMdÉCÊMúß(âÇJÁ.œÔN¯)'²•å®´ßO°‹±àîXX¾hªŠYeë»Ü¿ûö…ð?]8ƒ `ñÕå‹?}£ÅBpf¹‹Ëë…†Ù&º¹¼Zü{¹Yý÷ò¯/^]F?ZÊB ÑâƒH\ˆ†I¡ÕÉ}–Ú(&*5E¹\YµlÚv«‹ªÑËýõôúr¿[Uby覗aü,“+Å*UËÑ•ûVJ0®êÉ“X]!õò»é’~ï<‰åÕÃú°qÎŽ^ûéµï®»¾Û­}лöxÉC»Â¸œ€0²–LUãw<†a.LÝL/5ñ[éͳä*÷Ulµ¨UŸ9&Ï}ˆãßüz£ `Sœ>ð™+ŸœóxšÃ`1G‹"b#¸rR«E-kVk‰BpÎáÝnÛcþ‰u€«û˜u9­Oë?Îu`Ši¥ƒV`“ÑE²ÊÈ~æŠ,zAù¢âD¼DÅ”µ/éùúçÊTË}ÿÖý#®ªåÕ¦ïÖ‡}ÿK5kX=£ö,Ë–GÁKTÂ*™Q\è+ùAÉ"CE´8wëfD«òh½¼îv7›]7¡uÛöWÓOk÷÷Ëm; ÝÃLHWF¹™ACßÄðñ2”ðIf>PS™Å'ùAñ!C|´i˜°¡Æ2åñùf³ívíƒäHM»;⣖÷íáG1£äS÷_p?A‡?ÀŒàçDÔ,?ÀÆ*òÓ(×À6íùùºûéáÆ­?7?ï6‡Ûé§a\6+±¼ÙµÛ<>«èù=TH½‡Vøê$ß:«jrƒªJFU’éÆv‚ªÃí~ÔõÝcdU–U²þÝÊŠéóR2YBÂ7Y!“TH2’Rî}ßy¨(d{ãÇQR Ƶù” ‰¡•V¸’'9¶9%LÉóHùê¬êŠ5µðrƹ†T𣠮­ ²û½9r»Oáö¸jÞ<ÝuHE‚*:0#*ú‰úyÐ’42TMs–8 óË[¿ÿüê8 u¬­|l½ß]çw.è_%¡“%4L>"tr„ MÆ BWÖ0ÎСÁxs¿ºpµ¡[oÚmT»NjçDu ¹phÍá±Ø„ì°f6'RŠ:‡ p„aCÇŠØÅŒn6¡«øîÐõí!V…ýØ_ü<Öƒ®ŸÞÙn¤.¸ÆT×â7ÝÜþ¿×“ö/ÉŒâj(L–—äå…ŒºŠª¬á±ÕÙ£´5qxÆ+&„œáø¤ë0š¼(%š’ETXd;TॉŒWm˜Ö‰¦|wp:nnÀ1É…ìT¤+£Íc4Ÿ• LQŸ˜’¢ÉŒRfYfÛàU”ŒUš)®“¢¡ ùózÝ9¯¾ê®÷}—_ Sz^?v úúœ—`If,P@–ä……Œa©$“Z%XâHã¶ÝÝ”X‘ÕÜ¡~|ãáS^b%™Q¬@ýV’#”2VdŽºæ!±/ÇêðC{Xê-2™·ÍÌÊG^‡äu(”Ì(€ ¨@É +Ä5³¤Á}<¯Þc»#Y#çc'=Áê{EJ(%3 %(/‚Rr„¢DÆ (I+™á2¡T{”¾í÷÷8KV1Þ43KOÒõ ô3‚žEóôG=t¬HOcY­E¢§ñôüe?~Ÿì:Ô°¦™ižt—”(!”Ì(„ ¬BÉŠ+"T7x„L˜Ú _wãAò®»ÊAÔfæböœíQP¦„T2£‚2Ëìý†ÀŠ+"¥+V}»MDmúKÚíÀæ3‚ßêÀÁËUÂ,ZQ”åÈ¢”1*PDLÁçÆi}¿Ù½Í®X‚Õvn™>Pмy/¥¨{êÎQL©âý{t¬H•lWªøhâðzÛn²O%6×z.„Ÿ+¯N «dFa¥F°JŽP¬ÈX+Q1c ÀJF¬þÖ½‡M]yÛî°S.«êy”ý‰wa„ä—¨If5PI„šä¥†Œ©áœ5ªÔÄóô×øÖN2ý˜#ѹ“úèSУR2£@‚â" %G(Hd¬’pû}m!HaÞýºïîØ>¯¶ò ´©ª¨_Wº‚v€ÁΉžyv€#Œ:Vd§QL)xªFÝ?v7ë»{d2 ¬˜‘y†^•NɌ JŒà”¡8‘±"Nµ`Ò‚Ñ€¨#N‡‡~7ü«Cžˆ±L˜¹®ýÊÒ_â&™QÜ@-n’#”2VäFWµ 7͇ܼ¹í¶[ì.šÏo ŸáÉŒBÊ… ‘¡h±"•bÖ‚?D`¿9ôX…ªY=wÉÏ9»ª”pJfNPb©²8%G(Nd¬ˆ“Ì(p´/ÂôúïC×ç±’)>÷ÉOD¡DO2£èŠ"ô$G(=d¬H7¬¶€™ÆÒßö]{ æ<öq@ýaÿG Ÿó,ÉŒ‚ ˆÀ’¡°±,V3­À2 ›¿ï†e¼óC뙓'Yi¼v’”3ONrƒC ÜÉ* ìe˜&¿zßÞÝǧî†tß»"£Ðõñá¿/(D|ŸÈ‚øÉŠj’?¹IâÿÛðëv endstream endobj 2074 0 obj << /Type /Page /Contents 2075 0 R /Resources 2073 0 R /MediaBox [0 0 612 792] /Parent 2027 0 R /Annots [ 2032 0 R 2033 0 R 2034 0 R 2035 0 R 2036 0 R 2037 0 R 2038 0 R 2039 0 R 2040 0 R 2041 0 R 2042 0 R 2043 0 R 2044 0 R 2045 0 R 2046 0 R 2047 0 R 2048 0 R 2049 0 R 2050 0 R 2051 0 R 2052 0 R 2053 0 R 2054 0 R 2055 0 R 2056 0 R 2057 0 R 2058 0 R 2059 0 R 2060 0 R 2061 0 R 2062 0 R 2063 0 R 2064 0 R 2065 0 R 2066 0 R 2067 0 R 2068 0 R 2069 0 R 2070 0 R ] >> endobj 2032 0 obj << /Type /Annot /Border [0 0 0] /Rect [441.93 643.088 450 653.051] /Subtype /Link /A << /S /GoTo /D (1) >> >> endobj 2033 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 626.65 450 634.226] /Subtype /Link /A << /S /GoTo /D (1) >> >> endobj 2034 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 611.378 450 621.075] /Subtype /Link /A << /S /GoTo /D (1) >> >> endobj 2035 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 598.228 450 607.924] /Subtype /Link /A << /S /GoTo /D (2) >> >> endobj 2036 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 585.077 450 594.774] /Subtype /Link /A << /S /GoTo /D (2) >> >> endobj 2037 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 571.926 450 581.623] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 2038 0 obj << /Type /Annot /Border [0 0 0] /Rect [441.93 542.167 450 554.919] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 2039 0 obj << /Type /Annot /Border [0 0 0] /Rect [441.93 512.578 450 522.541] /Subtype /Link /A << /S /GoTo /D (7) >> >> endobj 2040 0 obj << /Type /Annot /Border [0 0 0] /Rect [441.93 477.41 450 490.162] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 2041 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 461.64 450 471.337] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 2042 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 448.489 450 458.186] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 2043 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 435.338 450 445.035] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 2044 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 422.188 450 431.885] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 2045 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 409.037 450 418.734] /Subtype /Link /A << /S /GoTo /D (12) >> >> endobj 2046 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 395.886 450 405.583] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 2047 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 384.857 450 392.433] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 2048 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 369.585 450 379.282] /Subtype /Link /A << /S /GoTo /D (19) >> >> endobj 2049 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 356.434 450 366.131] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 2050 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 345.405 450 352.981] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 2051 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 330.133 450 339.83] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 2052 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 319.103 450 326.679] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 2053 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 305.953 450 313.529] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 2054 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 290.681 450 300.257] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 2055 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 277.53 450 287.106] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 2056 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 266.501 450 274.076] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 2057 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 253.35 450 260.805] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 2058 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 240.199 450 247.775] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 2059 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 227.049 450 234.624] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 2060 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 213.898 450 221.474] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 2061 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 198.626 450 208.202] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 2062 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 185.475 450 195.172] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 2063 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 172.325 450 181.9] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 2064 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 161.295 450 168.75] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 2065 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 148.145 450 155.72] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 2066 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 132.873 450 142.448] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 2067 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 121.843 450 129.298] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 2068 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 108.693 450 116.268] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 2069 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 95.542 450 103.118] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 2070 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 80.27 450 89.967] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 2076 0 obj << /D [2074 0 R /XYZ 90 720 null] >> endobj 2073 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F91 2077 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2127 0 obj << /Length 2593 /Filter /FlateDecode >> stream xÚíœßsÛ6ÇßóWøÑ~0J@>:¶s×kÚfwúÐÞ-Ñ'å’r÷¯/)ág‚]8¾øÒXœÌ„‘¼ÚUöûñX¤Ùø‡”Ù✔yq°X=Ëô»ïžQý¯ãÑàØ³x~ñ컂Ќ”YI.®|˃ß›æè˜•R‡§WuwÝtõÑ1çüð=Û]ûúªîënQý÷â?ÏÎ/l,ÁXâËL‰oC³|üi~ Æ÷2®v_)'òè˜fYvX-Ú)ìø©ÜÿTž©ädkNFc©v‰¼ºÿ›ýÜ?âK|Ï}„FÎK2IeTµUßþÐÃÃX{fD>v¶Õœ‰ObŠÌÁq²HÄ¢´$EQÈRŽW‡#¡ȓކé7#?\¬»#Vnúu»ûU©õë¦bÔÒé?"yÛ'†‡ÉqÏ #,‡ç‚eá(8Q\:8˜†ãͺ­úfØÁp2±pú2JB©HYˆ½áK¤uHäÌ0€|Q™Œä¡±,@*#bÔßÄ5@g/Þ¤á)Q÷¹ùÍðDÞ„PÒŠ¤PrfJ¾¼LEQrŽ@”ÐX%¡HÎ=”rÒO–$’ÄH.Õã £ö@(­K (g†å‹ å@¡±,PyNX‘; „êצ[®§²ôçµ{qþ¡ZÝ´utØ#2ÂÇ ÀÓ/X :¥)œÆ‚¯+¢,8G h,˧„rîX0Ó²Wë¡ùð™$ŒSAQûZp òº^Ö¿g4ïšéõóU¼^Eżd§ ÉjÏ Á!(ŽƒçÂeq($É•ƒiƒŸÜ.Gý»k`áµ”sóñ1^ )’œFR n´“í9IBcY’'œ ¤Â’´YŸí*J c(;>_fcdHñãÌ0~Mãü8G ?h,ËÌU¹ÇiN?oºª¿Û®ÙVËåX’NßV}ü¦4Î÷÷vÆ¡óš™a@"ÅpŽ@ ÐXˆ\‘Œù@ØòHÄòâ¨à‡ëïw½äº¿ªzãwÓí®‹«êzÚѪ£«ãØ6±¿qZ ÕuòRª;3Lõ@‰¸êΨ:˪Î9)÷U7-ÜÓ·õbRûÝp»:«6Õe5Ô»ÌK^’—áâ[’RW')¥®3ÃÔ 2W×9ÕEcYuÙ8ÀdÌW—EÔ}uÛ_Ç竌QÒyË6‚Ô9NÁáÌ08Áhç„eáÈ*€ƒGàøåf»’³¬6Ð1…œä‚ÎÀ ÜÎ £"P*N…sRÆ2Tðqz3êSaº£§ëÕM_Ãx]UÝ2 ÃtÔê>GžXÁ(0ÉLPà™!„ÊD)ðAà±,%ÌïqRaKCÓ._6—»ùÁæ-´”"æ{Ÿ±–¢óâÄZa˜øÒEw797 $X ˈ,Æá„ψ´…âf¢ãîeÓ½ƒ4©bæã­.;RÐX+ _Ë84Ö  ÈB#rRJùŸšèY}UݶÏÅöïÝàØžF÷"ˆ çÎ £#-އsòƲ€ä”4ØRT„€¼zwýãu¼!5ú¼œëJz|jÒœâÙa|šÅùpŽ@>ÐX–V)>JËG[oêŸÖÝ/CÝ¿hZøXu¹‡[¹!t>S 83 „@œ8ÎË‚@Ô£²ìc~þ³ÃHÉäþ43LIïÌ0é9¢[=G ôh,+}Æ—þ**£±ðcÕ´P {8r€8ÐéLqàÌ0mâ8G h,Ã+ÊQù€- yIä^ô®éMÒ{fˆô¡Qé=Gôx,+½’cíö—¿™i^.׫ªé€},›‡‡Ñ7z¤@rfH¸qœ#$4–I2RRÙ“™~çÙ«¦9è¿ô¦>¬í)Êqšò4‡à:o)Á&x B\pçek¾’þŠ'3½Í³þîõm¼rpR”t®Q9´)œR n$ç eAâ’H€d õ²Ù\n·ÑLÛ°ÆéGó°¾*ƺÁæõUŒæÎ ã#Ð,z6ÎsòƲ|0Nré7È™òøÀÉ(sÂïse~ÖÎ}îUZ‰BÎ C(5Žs"„ƲM'˜¨¿ËL3ô|u³ÙvÈ_×ú}ºî® g¨Èûœ{šG,! t^S@83 ˆ@¤8ÎËAKE¨ €0ÝÏó‹¶ZUÓ‚øÑ5?½ë!Sd“ò+žÂJ¨_”ÏÄ ˲Rä$óQᙇÊí²6+mq\ RÎ#“à²ËzŠk…Áâ gźQÁYRTF á/Êr¢2­äCU…Ï£`¢SžâÄ™a úEÏzŽ@TÐX–¡ˆÊV˜eå¦éë“«MÝCO{ÈÊùÓCŸö`2ŸBÆ™aÈ2Æ‘qŽ@dÐX™<'B§òM¯öÅtª ¯ëçoÎîÑe“ã´K>±þ-$¶ÎYJlg†‰Û9ÅFcY±9%yæ/ËòüS±_׫íá×Ý#×0ÍÕ´ øÍo(…TÖÉJ©ìÌ0•ƒÌGIí9UFcY•iA˜T¾Ê·m{~D»EwÎHF¹*ç!æ=8ÑéNqâÌ0Níâœ8G 'h,ËI&F8üZnz¤ÿ^¯j½‰x0tÐãòùùP]ê´§xqf/†q^œ#4–ᥤ¤þª.W—aÓU«ú‡únðæÉShÓ¨!{beÐ]§/!»³BT”ˆ>Cܹqšÿ Õ™µ endstream endobj 2126 0 obj << /Type /Page /Contents 2127 0 R /Resources 2125 0 R /MediaBox [0 0 612 792] /Parent 2027 0 R /Annots [ 2071 0 R 2072 0 R 2078 0 R 2079 0 R 2080 0 R 2081 0 R 2082 0 R 2083 0 R 2084 0 R 2085 0 R 2086 0 R 2087 0 R 2088 0 R 2089 0 R 2090 0 R 2091 0 R 2092 0 R 2093 0 R 2094 0 R 2095 0 R 2096 0 R 2097 0 R 2098 0 R 2099 0 R 2100 0 R 2101 0 R 2102 0 R 2103 0 R 2104 0 R 2105 0 R 2106 0 R 2107 0 R 2108 0 R 2109 0 R 2110 0 R 2111 0 R 2112 0 R 2113 0 R 2114 0 R 2115 0 R 2116 0 R 2117 0 R 2118 0 R 2119 0 R 2120 0 R 2121 0 R 2122 0 R 2123 0 R ] >> endobj 2071 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 710.037 450 717.613] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 2072 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 696.887 450 704.462] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 2078 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 683.736 450 691.312] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 2079 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 670.585 450 678.04] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 2080 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 657.435 450 664.889] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 2081 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 642.163 450 651.86] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 2082 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 629.012 450 638.709] /Subtype /Link /A << /S /GoTo /D (29) >> >> endobj 2083 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 617.983 450 625.558] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 2084 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 604.832 450 612.408] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 2085 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 591.681 450 599.257] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 2086 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 578.531 450 586.106] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 2087 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 565.38 450 572.956] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 2088 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 552.229 450 559.259] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 2089 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 536.957 450 546.364] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 2090 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 525.928 450 533.504] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 2091 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 512.777 450 520.353] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 2092 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 499.626 450 507.202] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 2093 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 484.355 450 494.052] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 2094 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 473.325 450 480.901] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 2095 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 458.053 450 467.75] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 2096 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 444.903 450 454.599] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 2097 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 431.752 450 441.449] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 2098 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 418.601 450 428.298] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 2099 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 405.45 450 415.147] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 2100 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 392.3 450 401.997] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 2101 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 381.27 450 388.846] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 2102 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 365.998 450 375.695] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 2103 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 352.848 450 362.545] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 2104 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 339.697 450 349.394] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 2105 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 328.668 450 336.243] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 2106 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 315.517 450 323.093] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 2107 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 302.366 450 309.942] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 2108 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 289.216 450 296.791] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 2109 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 276.065 450 283.641] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 2110 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 262.914 450 270.49] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 2111 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 247.642 450 257.218] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 2112 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 234.492 450 244.189] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 2113 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 223.462 450 231.038] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 2114 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 208.19 450 217.887] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 2115 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 197.161 450 204.737] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 2116 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 181.889 450 191.586] /Subtype /Link /A << /S /GoTo /D (44) >> >> endobj 2117 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 170.859 450 178.435] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 2118 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 155.588 450 165.284] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 2119 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 144.558 450 152.134] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 2120 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 131.407 450 138.983] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 2121 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 116.135 450 125.832] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 2122 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 105.106 450 112.561] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 2123 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 89.834 450 99.531] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 2128 0 obj << /D [2126 0 R /XYZ 90 720 null] >> endobj 2125 0 obj << /Font << /F51 5 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2179 0 obj << /Length 2539 /Filter /FlateDecode >> stream xÚíœßsÛ6ÇßóWøÑ~0J?ù˜Ë%SwZ·»w7÷ÀʴÉDiD¹û×”`éÃ.œØÎ¤gNfbÙ^íjöû1°X€àG…ûǪâÈÁ*i«WÅøÓ¯øøêÔœ‹\¾úîâG¼`UQñ£Ëë#ÅËáuðsyuôŸã¶mOþ{ùë·—Á•*ËL¬Á"ŒóŠYkŒûY!Ì!˜dî;aONyQÇg×o—õ¦o®NN…Çmwøºp¿>¾>áÇõM3¼ìNJ{¼>¤‹!'1dÁ$/ÝgÚ{gÎZ›Ã=ù.ùØ|£ï»§—2âSíqRì 4óV§À,¡Û}gÝÌÿÄTŒ—`d°ÈÄòŒèJ»¯Fª‘‘w'VoÛ¦»:»éëmó~OÅMó)‰„PŒ›*Ä×Vñë|„ Ÿà ÀŒ cªV’ à#ƒŽȰ‚¡²ð£ÇMç`8;ŒÍöº^820*¤bÖˆ—CÆÁ˜ÎÑŒâ`¢Mšƒè倌80SVA¸ç »^oW)Õe¼´/u(xÒ÷a<²äxŠfOm’§è剌xR†I1á© <å¼^5É…K¦]”gcëï[±`¨ŒÏ¡Í(T&ò¥Q‰ŽPTÈX)Yi%DEøâ¤]6o?íš®o×]qbm9sòpNÆtç8‰f'íÒœDG('d¬À‰àŒ 9‘#'?Öýî¢iº!Ö2%äçX€ËTÀ$,À +Àb†Šc‹°\¶Ww߯WÍPÚöXƒM ñRÁh“š£!šQ4LJÓ¡4± Z1a! ¾óºZŸœº…ðÕí²¹"Grxß<‚ƒÅ!Ë9:‚,ÍFpƒ¢A d¨’•eÐPE@ãöÐ$ÙÔ;W‡v镯`·3.Y}Âs”D3 ¨ž.ÅIt„‚BÆ ¤ 1 D”oÎvÍnU÷“ _ã>¨œùxÊ…¯W"‡P4£‚²"EG(Bd¬€P©XUNòýØóu÷z¹ùPŸß®ð¢Dî=Õ¼<*7f3‡A4£0€Ò¸?ìÑŠ+`ÀKf ÜV¾×Ú]÷»aιÛìË’dWÞr·–1s/í9*˜Q™RÑŒB ÊŒ ¡H‘±‘Áí É#Lr:VÜj&ÍDrßE}ßlÞ|¨·X#~®WŸ¶ ë•È!Í(„ ¬BÑŠ+ d%ÜV:"´ŸÖ}‹-‰+ËJeçM¿ÇU1^ƒ<ÑŒ‚ ŠÀ¡ð±<ÚU£î+ߎ}ÿËO bŽá–I=o>drsœƒ#šQp@Á8¢#2V€Cºuo9ÃF8P‡(÷Ž0´`ºéËéÍ(Ý¡ˆîѪ;+è.Äþ"ÐÝwZ/C!ú¡Z­H§¤2b®Lž²SâåÈqÍ(Ž ¶nÅšâ(:B9"cŽÊ‚™îkß–½h·Ã‰ØÍmú´|!˜~§åŸ¬˜3ŸC&šQÈ@d¢#2V@¦0®™ Ã2]ßþ¶lÞøŽ>Öʯä Îg 2f<‡J4£Pò!¨DG(*d,Ѝ$“%ÜÖå=T.Ú?lxVóªçˆŸú 3ÀŒ`f¢cšàc†Ž˜±œ•°g«}ÏöâÃzTþx½Ø¡d û¼Ïëüí©Áp9d=GK°¢`*™d%¸AQ¡RôðD$Å·b/Úîf˜…6ûúx+¤ž—Æë©Œ ä¨ V5@L„šà¥† ¨Q’UDо۷»æ»ëzq»ÜQà¨yñôÈ‚Æk'šQä@A•J¢¡ì±<’3ËáÆ²öÜ‹íæìª9Ô½íõVÔÌçj¿¸¤“Ÿ£&šQÔ@%j¢#”2V ¦´Ž“ 5¾ƒÛ¯'ŸúfûûÉ~#ú”o‘]€b®‡=cRäŠfCPW„¡èeˆŒâŠ)>©‹}£÷b³¬÷óÕe›~¼°2ÌŠyÒzì¤5*C'šQè@9t¢#2V@§(™Ðp[W6Ù¤*©˜¯uÆ+”C+šQhA¹´¢#-2–G«´+9DË„öñ¸¯íþ7Çë¥lyÜh8ö-æ½J’Ÿì %ÀŒ d¢œÒ)J€#Œ:V ÄhVhxüÁ„Žñ¯çؤ”–UÏùxü7¦ü˜ÀœòÑŒRª(¡Ê“±‚òºd‡ÛÓÆ7€ûÛ~Ó.ÚõmßÕ+lPÌVr®y©AaÌphF¡åBЈŽP4ÈX Y1£á¶ñÞþ®¯¯’w°Ø’ñùTݳ¬Œ¼9¢):BA"c„fšO@ }à»~¹¾I^æcXaç=ÈgÈX)™RpWÜò$?ÿÑ p ë+&¥}ñWÔùtæ8ˆfP„ƒè倌8œÉîlÛ’'~ª÷Ezˆîµž‡ˆ)c†shD3 (‚Ft„¢AÆ hðáÑ× "KôK1_b鳙à šQ@iTòæ(àÅ€ŒÅ ÷×,-ÕþN0Ÿ&˺ïÓ³‚.™.æsà߯’z”/Ç]4£¸ƒ,èä5BÀÊËsWqV©¸míg¥q®\¹µâ3wßÐé¨b†¾hEÀÐÉ‹f¢›ˆÞ_8ºX endstream endobj 2178 0 obj << /Type /Page /Contents 2179 0 R /Resources 2177 0 R /MediaBox [0 0 612 792] /Parent 2027 0 R /Annots [ 2124 0 R 2129 0 R 2130 0 R 2131 0 R 2132 0 R 2133 0 R 2134 0 R 2135 0 R 2136 0 R 2137 0 R 2138 0 R 2139 0 R 2140 0 R 2141 0 R 2142 0 R 2143 0 R 2144 0 R 2145 0 R 2146 0 R 2147 0 R 2148 0 R 2149 0 R 2150 0 R 2151 0 R 2152 0 R 2153 0 R 2154 0 R 2155 0 R 2156 0 R 2157 0 R 2158 0 R 2159 0 R 2160 0 R 2161 0 R 2162 0 R 2163 0 R 2164 0 R 2165 0 R 2166 0 R 2167 0 R 2168 0 R 2169 0 R 2170 0 R 2171 0 R 2172 0 R 2173 0 R 2174 0 R 2175 0 R ] >> endobj 2124 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 707.916 450 717.613] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 2129 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 694.765 450 704.462] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 2130 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 681.615 450 691.312] /Subtype /Link /A << /S /GoTo /D (47) >> >> endobj 2131 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 670.585 450 678.161] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 2132 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 657.435 450 665.01] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 2133 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 644.284 450 651.86] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 2134 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 631.133 450 638.588] /Subtype /Link /A << /S /GoTo /D (48) >> >> endobj 2135 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 615.861 450 625.558] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 2136 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 602.711 450 612.408] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 2137 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 589.56 450 599.136] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 2138 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 576.409 450 586.106] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 2139 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 563.259 450 572.956] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 2140 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 550.108 450 559.259] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 2141 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 539.078 450 546.654] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 2142 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 523.807 450 533.504] /Subtype /Link /A << /S /GoTo /D (51) >> >> endobj 2143 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 510.656 450 520.353] /Subtype /Link /A << /S /GoTo /D (51) >> >> endobj 2144 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 497.505 450 507.202] /Subtype /Link /A << /S /GoTo /D (52) >> >> endobj 2145 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 484.355 450 494.052] /Subtype /Link /A << /S /GoTo /D (52) >> >> endobj 2146 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 471.204 450 480.78] /Subtype /Link /A << /S /GoTo /D (52) >> >> endobj 2147 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 460.174 450 467.75] /Subtype /Link /A << /S /GoTo /D (52) >> >> endobj 2148 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 447.024 450 454.599] /Subtype /Link /A << /S /GoTo /D (52) >> >> endobj 2149 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 433.873 450 441.449] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 2150 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 418.601 450 428.177] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 2151 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 407.572 450 415.147] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 2152 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 394.421 450 401.997] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 2153 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 381.27 450 388.846] /Subtype /Link /A << /S /GoTo /D (54) >> >> endobj 2154 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 365.998 450 375.695] /Subtype /Link /A << /S /GoTo /D (54) >> >> endobj 2155 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 352.242 450 363.151] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 2156 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 339.697 450 349.394] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 2157 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 326.546 450 335.698] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 2158 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 313.396 450 323.093] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 2159 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 300.245 450 309.942] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 2160 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 287.094 450 296.791] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 2161 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 276.065 450 283.641] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 2162 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 260.793 450 270.2] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 2163 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 247.642 450 257.339] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 2164 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 234.492 450 244.189] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 2165 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 221.341 450 231.038] /Subtype /Link /A << /S /GoTo /D (56) >> >> endobj 2166 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 210.311 450 217.597] /Subtype /Link /A << /S /GoTo /D (57) >> >> endobj 2167 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 197.161 450 204.615] /Subtype /Link /A << /S /GoTo /D (57) >> >> endobj 2168 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 184.01 450 191.586] /Subtype /Link /A << /S /GoTo /D (57) >> >> endobj 2169 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 168.738 450 178.314] /Subtype /Link /A << /S /GoTo /D (58) >> >> endobj 2170 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 157.709 450 165.284] /Subtype /Link /A << /S /GoTo /D (58) >> >> endobj 2171 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 144.558 450 152.134] /Subtype /Link /A << /S /GoTo /D (58) >> >> endobj 2172 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 131.407 450 138.983] /Subtype /Link /A << /S /GoTo /D (58) >> >> endobj 2173 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 118.257 450 125.832] /Subtype /Link /A << /S /GoTo /D (59) >> >> endobj 2174 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 105.106 450 112.682] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 2175 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 89.834 450 98.986] /Subtype /Link /A << /S /GoTo /D (61) >> >> endobj 2180 0 obj << /D [2178 0 R /XYZ 90 720 null] >> endobj 2177 0 obj << /Font << /F51 5 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2231 0 obj << /Length 2526 /Filter /FlateDecode >> stream xÚíœKSI€ïþÅš®G×ãˆ{×;>¬¹ÍîA†ÆV$B³3ÿ~«¥êÊlT™…g°×H Gƒ“L‘ß§êzt#OšøGž„æÄi-‚ñ'Ww¯šôÕ/¯dú×Y 8C¯/_ýô¶•'²¡ òäò§¸¼>ùu2ûíôL£üä⦛šÍ»Ó3­õä7µý¸ìnºe7¿êNÿsùWo.s­V©Ê‹é#*¯FÊ ¼÷'.~­Ñnû’ŒJÈÓ3Ù4Íäjq_ÜÛW_œœü>½»¿=•“ÍKŠÍ(ccDÛØø 6¹Düë¶ìè³âŸ²/ß÷§ÑAô-HD^‘Ôæ?Ò!ê …°>N¶AaÝNͶÁõ õ•ZƒB6Øø+¤’BŸ.¯·úÜÎæ_VÛÎæýG“ýšÍ?u21•iG'B‹¡»-P£ÅUY ”ˆÒ‚¯•µðZ8m‘:iqyêõdG?×ÿÝ»p7£±&Šq?ëæÛOÿÝHsÛ­Š’h/´=¼1‡r%µ¼æ „q®`~Ö]D¤+l­þšŒ9±®­o³+ƒ)×ÝÍôáv½\<¬‹×œ ã%'Ôñob/P7J©D¦¦„qJaÌ6•‚D¤Rl­¬Të„Ñ ””š­¾Ç’Ö õ—}úò-¾’/1¬Éaœ|X×åƒD¤|l­,_œ¼(o²|m–oÙ]­ËYùræ¥Á‡³gÿ>ʯ„©æ„q~aæNý‚D¤_l­ì—–ñ"©³_·éÇÛâ¥ÒÚ8•?oßéA —¸Õ„ƒ0N8,ÓEá )[+ '„sI¸îz¶fæçÖ ßº£tÿ_黚tÆI‡Ep¶($"¥ckåd”ÏkÒ彩ó›âb¹>ï×ëÎæÝ/ÓõUÿÉgrC!Ž€‡4Á£tH]­éaœ‘+/!©[kС«=ë%ÒaØg:¿v ®KäRªã(ô ɧ4§PãÔˆsÙ)”ˆrН•Šn´;¥wzwó~ñ¤ƶBíÙf<õ­Â8à‘ÀÙZxd¤=âmʼ?<œÊI¤í&Ÿ{ôå ŠÞéÃY®Q.l[ZS!Gq& :®¸?iH¸BYƒV ¥ò }’«·§ÞL–‹»·³ò2K†F¸—4É  ¦Õ¨B‡w›à ‰H°l­L¶¯éð;Üî’½ì)nÆôžñúb±9~XOgóò1ƒoâÔѾØw:Å8µªÆÂ8ƸïcHD2fkeƪAaÆÃzôü!.Hñ9£®-Q¥j„´ò¸éö„1!µ½æ „q¾`†„/ˆô…­•}‘J8ç/>û²^\,»)q¼§ƒÁq˜Iݯiaœ6%¡ $"µak Ú˜„Ui6w‹‡íUãçͦþ¿ºÕâayE 2N möe JpÚUáŒÂΣÞûâi JDqækeÎÞ ã0gÙ$Я§›ß—‡ûñÍ+µ‹Š6¨#%HêsMãÁÐA )[+ â´ÐªÅ‚ ;‘¯»O³ùß–‹‡ûw7?w½óZôÂ5‡p1¡è§&ÖèCG!èC"’>[+Ó·q†è ¦¯ ôã:‚`³. ±=4´¬ÆÂ8Ö¸ÿkHD²fkeÖÆ‰FXëë~õÿæ÷Ùj]ýÛ t³ŸÇ^ðÔ·pã€cpHDgkeàz»‰‡€ø»Õûî¿ýl [–ßß6ÎñÌ~-$)Ü©k5ÜÆáÆ|ñÆ ”ˆÄÍÖʸãjߩёb[ÀÝï ¡M!j¿ß÷ûýê姨¦æÔ¨BGwš  ‰Hªl­Lµq¢u#ª– Z=Ãqñ],_úÐMN}ª†00n:‘€ÙZ`Œ0 Óå;P0à ·<ïo=Þ+žð -­¸€ÂF|Ê. D” |­ì‚—Bá½<鋳ñ'ŽáÁ eôK°‚¹íGcŽâ0¢Ös"W(3´>.¢0Ã@2¬ŽØ¡‰þo8ïú^ äÔ”ÈÅDý%@æ4$H®PÙ,>GUM‘$?4·mœ‡½ ‚ÏöÞMí«1‡0:fAP‡D$v¶Væn¤ðŸÀ)Yäþáa‹¼‰ÂaöæªLaNݪa†03n=‘˜ÙZ³òÂÚæ¼õµì¦_Í©‰Íð8ñòÍqâ5ðK=­Éaœ WE )[+Ë [ÑJ<óRÃÞØÅ`ܘ[~D\ }|ÆêO/Ð5u ŒSã$ÔD¤:l­¬N£6Ïé"u†]¶‹ÅÝ]7Ïwq¯¶ƒ‰‹9!ï³”ÂìésRùÔÀyãÈcyHD’gk ä•qj0"ßä?¬§Ë5…<ÎÃN‡öU¸£0†ûˆE™;JDqçkeîΊÆâ#Sew¹¿ß€/ß–Õn^ó#ÿË»ðCkr@'FȉH9ØZY«Dø”M¹]9¶¿&âi›¶ý.ñ¾ÈBÑNM«Ñ†0Ž6&@ІD$m¶V¦m‚p±©aÇn80¿¸®VÄ@Ða]8_»4´½æ „q¾`†¾ø¬)JDúÂÖʾh+¬ùùòn»ÁPôeóháñ×P=ÅÔèš!Æ‚©†@"Ò¶V6Dia,Þ?ÖM6ä¶[w›iÅùͺ[^~ž­ê;ÈR„õ˜24õ¥Â8 ¸ÉPHDeke ñkZŽÓ»@ǧ9?¡ÿ?ÃA`VÞlnýÌT£Óë­5¸Fãžh4$"ÍÖÝwõO; F«ÝFã7Ì£6?ay®lûÓ3üæ6¢ùÃÏPi> cš?jˆ7¥æ£DTóùZ¹ùQÀfÔ{½Ûûaü¨ïÜâXµýÎÏ~ÓÕþíOQë~ŽâšBô>§![ÏÊ ßâc*mv[¿3ŠlîúZwwʼni\ g~˜S+ŠVúÉk¸ Œã…ÛHƒD$1¶VFÖ:áš²¶ˆ V<°&f ?èQ?…/u¡†Â8|¸¥>HDâcke|ƈ¶Å'GÚñ [2üØ“zŠ`jD „qqW ‚ˆ$ÈÖʵ¦ÁÇ=Ú2›wqÍ®Ž¿lêO¼ÝSÏk²@' HȉHYØZYé…jG²ø‘,_±™×áí^ËCÑOM¬Ñ‡0Ž>&BЇD$}¶V¦ß´B6øG;6o®gë_›Cáëô ΧóôK¡?ÎæÓåð”6s›ux‰OßS˜S·j˜!ŒÃŒ[O`†D$f¶Ö€y³M‚tLƒ(¸¿Oý½?ÈÛ?¾éa@BQQ¢ƒ0Uß–‚4àÏÿë«‚ä endstream endobj 2230 0 obj << /Type /Page /Contents 2231 0 R /Resources 2229 0 R /MediaBox [0 0 612 792] /Parent 2027 0 R /Annots [ 2176 0 R 2181 0 R 2182 0 R 2183 0 R 2184 0 R 2185 0 R 2186 0 R 2187 0 R 2188 0 R 2189 0 R 2190 0 R 2191 0 R 2192 0 R 2193 0 R 2194 0 R 2195 0 R 2196 0 R 2197 0 R 2198 0 R 2199 0 R 2200 0 R 2201 0 R 2202 0 R 2203 0 R 2204 0 R 2205 0 R 2206 0 R 2207 0 R 2208 0 R 2209 0 R 2210 0 R 2211 0 R 2212 0 R 2213 0 R 2214 0 R 2215 0 R 2216 0 R 2217 0 R 2218 0 R 2219 0 R 2220 0 R 2221 0 R 2222 0 R 2223 0 R 2224 0 R 2225 0 R 2226 0 R 2227 0 R ] >> endobj 2176 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 707.916 450 717.613] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 2181 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 694.765 450 704.462] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 2182 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 681.615 450 691.312] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 2183 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 670.585 450 678.161] /Subtype /Link /A << /S /GoTo /D (69) >> >> endobj 2184 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 657.435 450 665.01] /Subtype /Link /A << /S /GoTo /D (70) >> >> endobj 2185 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 644.284 450 651.86] /Subtype /Link /A << /S /GoTo /D (71) >> >> endobj 2186 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 631.133 450 638.709] /Subtype /Link /A << /S /GoTo /D (73) >> >> endobj 2187 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 617.983 450 625.558] /Subtype /Link /A << /S /GoTo /D (76) >> >> endobj 2188 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 602.711 450 612.408] /Subtype /Link /A << /S /GoTo /D (78) >> >> endobj 2189 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 589.56 450 599.257] /Subtype /Link /A << /S /GoTo /D (78) >> >> endobj 2190 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 576.409 450 586.106] /Subtype /Link /A << /S /GoTo /D (78) >> >> endobj 2191 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 563.259 450 572.956] /Subtype /Link /A << /S /GoTo /D (79) >> >> endobj 2192 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 550.108 450 559.805] /Subtype /Link /A << /S /GoTo /D (79) >> >> endobj 2193 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 536.957 450 546.654] /Subtype /Link /A << /S /GoTo /D (79) >> >> endobj 2194 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 525.928 450 533.504] /Subtype /Link /A << /S /GoTo /D (79) >> >> endobj 2195 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 512.777 450 520.232] /Subtype /Link /A << /S /GoTo /D (79) >> >> endobj 2196 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 499.626 450 507.081] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 2197 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 484.355 450 494.052] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 2198 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 471.204 450 480.901] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 2199 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 458.053 450 467.75] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 2200 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 444.903 450 454.599] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 2201 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 431.752 450 441.449] /Subtype /Link /A << /S /GoTo /D (81) >> >> endobj 2202 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 418.601 450 428.298] /Subtype /Link /A << /S /GoTo /D (81) >> >> endobj 2203 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 405.45 450 415.147] /Subtype /Link /A << /S /GoTo /D (81) >> >> endobj 2204 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 392.3 450 401.997] /Subtype /Link /A << /S /GoTo /D (81) >> >> endobj 2205 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 379.149 450 388.846] /Subtype /Link /A << /S /GoTo /D (81) >> >> endobj 2206 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 365.998 450 375.695] /Subtype /Link /A << /S /GoTo /D (81) >> >> endobj 2207 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 352.848 450 362.545] /Subtype /Link /A << /S /GoTo /D (81) >> >> endobj 2208 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 339.697 450 349.394] /Subtype /Link /A << /S /GoTo /D (81) >> >> endobj 2209 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 328.668 450 336.243] /Subtype /Link /A << /S /GoTo /D (82) >> >> endobj 2210 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 315.517 450 323.093] /Subtype /Link /A << /S /GoTo /D (82) >> >> endobj 2211 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 300.245 450 309.942] /Subtype /Link /A << /S /GoTo /D (82) >> >> endobj 2212 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 287.094 450 296.67] /Subtype /Link /A << /S /GoTo /D (82) >> >> endobj 2213 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 276.065 450 283.519] /Subtype /Link /A << /S /GoTo /D (82) >> >> endobj 2214 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 260.793 450 270.49] /Subtype /Link /A << /S /GoTo /D (82) >> >> endobj 2215 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 249.763 450 257.339] /Subtype /Link /A << /S /GoTo /D (83) >> >> endobj 2216 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 234.492 450 244.189] /Subtype /Link /A << /S /GoTo /D (83) >> >> endobj 2217 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 221.341 450 231.038] /Subtype /Link /A << /S /GoTo /D (83) >> >> endobj 2218 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 207.584 450 218.493] /Subtype /Link /A << /S /GoTo /D (83) >> >> endobj 2219 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 194.434 450 205.343] /Subtype /Link /A << /S /GoTo /D (84) >> >> endobj 2220 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 181.283 450 192.192] /Subtype /Link /A << /S /GoTo /D (84) >> >> endobj 2221 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 168.738 450 178.435] /Subtype /Link /A << /S /GoTo /D (84) >> >> endobj 2222 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 155.588 450 165.284] /Subtype /Link /A << /S /GoTo /D (84) >> >> endobj 2223 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 142.437 450 152.134] /Subtype /Link /A << /S /GoTo /D (84) >> >> endobj 2224 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 131.407 450 138.983] /Subtype /Link /A << /S /GoTo /D (84) >> >> endobj 2225 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 116.135 450 125.832] /Subtype /Link /A << /S /GoTo /D (84) >> >> endobj 2226 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 102.985 450 112.682] /Subtype /Link /A << /S /GoTo /D (84) >> >> endobj 2227 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 89.834 450 99.531] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 2232 0 obj << /D [2230 0 R /XYZ 90 720 null] >> endobj 2229 0 obj << /Font << /F51 5 0 R /F54 28 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2283 0 obj << /Length 2474 /Filter /FlateDecode >> stream xÚíœßsÛÆ€ßýWè‘zÐ÷ûð˜¸rªŽ›x"¥}HûÀHPÄ Eª$Ô‰ÿûHÜíÂÆîÑ«5%Œg$K^îÊû}p{€äIÿÈ“º:ñZ‹Ú„“ëûWUÿÝß_Éþog1à E|wõê›7VžÈJÔU-O®nO¬tB•ó\Ýœü2ûï鿯þöêü*'²J*u…RRÖ"„pâã÷*í÷¥Œ^yz&«ªšß?´§*ÌÞŸ¯ºOíbÓ¼Y,›wËf¾mº*æ4ƒœÖ çUüvÙDÌãüþ“|5úÍBþÿ¯û…ѵèþ󩋱ױ˻D8RÔ Aòa²]ƒý¨¦­p½ü]D¡VÂïj?ð«„¹mþÒü«’fÕ¼^ηÛf; ]ÅLUýœ¡¾©½/PãÅ€Õ¸(å_+{´ðÚa/tòbuóýfýø0&Cí…¶î…»pøë(kúæ—¬0ÎL’°‘Ö°µ²5¾6XlkÞ®OÏâyd=jNˆ?­6esþ×ÐŽúèÓã(yaœG˜-á$"=bkelw¼xd“G<ÌW7ÿ8 f6ß,æ¿.©³RÒ¨é¬4êEßÞ’ÆyY^@"Ò ¶Vö¡‚Á^8ð"^Ÿ~{Û6›Ó3­õ¬¹Y´ÝÅ %ˆ‰´ ^·r¡oiÉã\À|‚u‘.°µ² Z ©5vÁ÷.ÄUJ§Áu¯„7úé ¿¼ëJ«žNI+ã´Â¨ ­ ©[+kEªÃ@«µú#^Åüxûv±_þʯëéê÷pKúf—,0ÎLް‘–°µ²%•A+lI,9 z¶ÞœÏ¯»¡É]'ËŪ×ÅsQ9™tùÏãºmnÎö§¬Õü~T1„–Gq•LïW"aqL ‰Hâl­DÜÖR¸ q[õÄ¿_·ë·ómKâYÇ…é¸p°%©ÙKPcɀܸ%(e _+[ß V,IÓԿηw¯×÷÷Í~˜Úɲ}½Þ1_¬«ßFÝ©­ÐÖƒ;˾%%–ƱÄý%XB"’%[+³t±õ£T Ê¿ÏÛxÀ÷³»S9£X'LåŽoÉA‘Ý7¨6Gq\Q¯ ¬9 I•+”¡Z%”ª1UÍP½lç›–ÄY6øþJWÕ¾C%¬ÆqÅí&ÀB"’,[+£íjúÁ6 /nÏ—ó‡ms3:³V¢Rf:;Z2ÊžBÉãìÁD { i[+Û£¬¨ÕÀž4r¼X]oštXx×}\/Vݱ† à {]ÅÓ¾ýàÂ~÷òÇûî㯻981¡°ñ2Ã~ Šyߺsã˜cÁ2‡D$s¶VfÞ]˜{¼ùi]f~»ÞÜ6IŒë¸ Õt9àèÐ7¼d „q¦`z„)ˆ4…­•L1u-œÂÛ¡ÖgS¶Í¦ínŒ N.θi[ëÓ^Gè“(ôAaŒ>¤ãú D”>|­¬Owåïú„>Ôè 6¢ª¦‰âÒ§§PÒÂ8}0RBHDêÃÖÊúx-´ÂÛ¡6Mû=õëyÛtíW¡avG­YŒ‰KдB©Ðw´¤„q*`<„ ˆT­•UpUäw@]Cî®L›Íu¡º[ÊÆš}Ò¼IUQȯô€C±ì[Rb aKÜ_‚%$"Y²µ2Kãw+OÄRβøV¯»ÙF} ou lߟXãÀâf‡0 ‘`ÙZ¬Ö"x¼‡èÔá`Ù™S-E}T·µPlû•ØBÇ÷›` ‰H¶l­ÌVUÂ+¼óçÒñݦyدìW£ƒ¦à…´vºùàKÞÊ”p”<‚0Î#̖𑱵²GU·†xdF<º¸ýa}Ð…—±¨|&rQ°ûž•`C `C"6[+ÁÖqgÞt–€}ùx*gû$r?ÙVBkýV…„©PãÁ€Í¸(å_+{¤PxÞèÒ¼ñ§æúq3þTMÐBM7F?ÅÊ¡ÇQÒ(Gq!²„D9 éW(+ä‚ƒÓ†Ï =,ç×»1À?íõ¬Nõ”7½ó¥DßÙ’ 9гA"lÈiH¸BÙkDíðv¶ C¾].¿¡uÂZ9Ý$?ªCßÚ’Æ 9F@"R ¶VvÂH$ÞÉtõЉ7‹Í¶¥­ÐV˜Ú¿Ôƒ¥CßÕ’Æé€…zTHDêÀÖÊ:Ä7¹sX_}|ÆŒ“Þ,šåÍø*ÃÅ\Gÿ|…¸ïT 1„qˆqÛ ÄˆDÌÖʈ¥VâëJ/ñþ¡»í¢]oÞ¶¡­Ã‘ ™žô†¨ÔÝ’ÆiQZ@"R ¶VÖ¢RB;¼ëèUÖbÛ´—Í|³ÏZPé¨Ñt×òçn1¥î—´0NŒ’Бڰµ’6*ÔBÉ6iÂùÓãêòz³xh‰½j©']¾È„#1(ȃÂy@ëjL”ˆ’‡¯•å‰W•Ã[ÕÞ|(ÏÅíAMçâñç™Ë)Ü}×J¸!ŒÃ¸!‰›­•q;%j‰·0½ý÷#ìÝøãxO8Û¾E%¶ƱÅý&ØB"’-[+³5µðïbú4­¼lZt§ünÃrüBR mìK='PBô}- aœ!$"…`ke!t\ýÉ~TˆóñýÏnÜd¦aÓ¨}kKN@çæD8‰H'ØZÙ ¥…qxí8Aí`%l˜–Or)Ñ)™aœI˜.a$"Mbke“â÷´Ä{¤¾“èeG÷‹ƒL=ÝUñEG=‹’DÆI„ÁÖrT"HDJÄÖJu7½I‡% iØy¹üìpzºã«}ä>õ¤…10 ‡‰Q0ùZf0¢°”Ëòú‰p„³k ë¾;%ª9ŠƒŠM0ÍiH¤\¡LÔW"X¼]‡”ü6.~nËÅÔ¢WãÀâ~d!‰–­•ÙÚngiÀ6 /–‹öÇqs‹œ†ÌOcR¤d„q&aº„Iˆ4‰­•M2FX‹w,Cš!^¾ß.׿øXf7°ðÓSå‰DjxÉãLÁôS i [+›¢¥0Þø iüøóý|û;ñ+”ÌS>‘9=囨”t‚0N'Œ˜Ð ‘:±µ²N2e:¥‰çÏ«ÏX:—,öÙü¾—ÔžWã¸â^×j”+$"¹²µ2×Ê YáÍàI®å;íÐN?Ó{`R«JŒ!ŒcŒûN0†D$c¶VbÜ=eñ¾ccˆØ1߬¨c?Ýõ²g×÷³àD1`4ã@àOŽÏí endstream endobj 2282 0 obj << /Type /Page /Contents 2283 0 R /Resources 2281 0 R /MediaBox [0 0 612 792] /Parent 2285 0 R /Annots [ 2228 0 R 2233 0 R 2234 0 R 2235 0 R 2236 0 R 2237 0 R 2238 0 R 2239 0 R 2240 0 R 2241 0 R 2242 0 R 2243 0 R 2244 0 R 2245 0 R 2246 0 R 2247 0 R 2248 0 R 2249 0 R 2250 0 R 2251 0 R 2252 0 R 2253 0 R 2254 0 R 2255 0 R 2256 0 R 2257 0 R 2258 0 R 2259 0 R 2260 0 R 2261 0 R 2262 0 R 2263 0 R 2264 0 R 2265 0 R 2266 0 R 2267 0 R 2268 0 R 2269 0 R 2270 0 R 2271 0 R 2272 0 R 2273 0 R 2274 0 R 2275 0 R 2276 0 R 2277 0 R 2278 0 R 2279 0 R ] >> endobj 2228 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 707.916 450 717.613] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 2233 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 696.887 450 704.462] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 2234 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 681.615 450 691.312] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 2235 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 668.464 450 678.161] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 2236 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 655.313 450 665.01] /Subtype /Link /A << /S /GoTo /D (85) >> >> endobj 2237 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 642.163 450 651.86] /Subtype /Link /A << /S /GoTo /D (86) >> >> endobj 2238 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 631.133 450 638.709] /Subtype /Link /A << /S /GoTo /D (86) >> >> endobj 2239 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 617.983 450 625.558] /Subtype /Link /A << /S /GoTo /D (86) >> >> endobj 2240 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 602.711 450 612.408] /Subtype /Link /A << /S /GoTo /D (86) >> >> endobj 2241 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 591.681 450 599.136] /Subtype /Link /A << /S /GoTo /D (86) >> >> endobj 2242 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 576.409 450 586.106] /Subtype /Link /A << /S /GoTo /D (86) >> >> endobj 2243 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 563.259 450 572.956] /Subtype /Link /A << /S /GoTo /D (86) >> >> endobj 2244 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 550.108 450 559.805] /Subtype /Link /A << /S /GoTo /D (86) >> >> endobj 2245 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 536.957 450 546.654] /Subtype /Link /A << /S /GoTo /D (86) >> >> endobj 2246 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 523.807 450 533.504] /Subtype /Link /A << /S /GoTo /D (87) >> >> endobj 2247 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 512.777 450 520.353] /Subtype /Link /A << /S /GoTo /D (87) >> >> endobj 2248 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 499.626 450 507.202] /Subtype /Link /A << /S /GoTo /D (87) >> >> endobj 2249 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 486.476 450 493.93] /Subtype /Link /A << /S /GoTo /D (87) >> >> endobj 2250 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 471.204 450 480.901] /Subtype /Link /A << /S /GoTo /D (87) >> >> endobj 2251 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 458.053 450 467.629] /Subtype /Link /A << /S /GoTo /D (87) >> >> endobj 2252 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 444.903 450 454.599] /Subtype /Link /A << /S /GoTo /D (88) >> >> endobj 2253 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 431.752 450 441.328] /Subtype /Link /A << /S /GoTo /D (88) >> >> endobj 2254 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 418.601 450 428.298] /Subtype /Link /A << /S /GoTo /D (88) >> >> endobj 2255 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 405.45 450 415.147] /Subtype /Link /A << /S /GoTo /D (88) >> >> endobj 2256 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 392.3 450 401.997] /Subtype /Link /A << /S /GoTo /D (88) >> >> endobj 2257 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 381.27 450 388.725] /Subtype /Link /A << /S /GoTo /D (88) >> >> endobj 2258 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 365.998 450 375.695] /Subtype /Link /A << /S /GoTo /D (88) >> >> endobj 2259 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 352.242 450 363.151] /Subtype /Link /A << /S /GoTo /D (88) >> >> endobj 2260 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 339.091 450 350] /Subtype /Link /A << /S /GoTo /D (89) >> >> endobj 2261 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 326.546 450 336.243] /Subtype /Link /A << /S /GoTo /D (89) >> >> endobj 2262 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 313.396 450 323.093] /Subtype /Link /A << /S /GoTo /D (89) >> >> endobj 2263 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 302.366 450 309.942] /Subtype /Link /A << /S /GoTo /D (89) >> >> endobj 2264 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 287.094 450 296.67] /Subtype /Link /A << /S /GoTo /D (90) >> >> endobj 2265 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 273.944 450 283.641] /Subtype /Link /A << /S /GoTo /D (90) >> >> endobj 2266 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 260.793 450 270.49] /Subtype /Link /A << /S /GoTo /D (90) >> >> endobj 2267 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 249.763 450 257.218] /Subtype /Link /A << /S /GoTo /D (90) >> >> endobj 2268 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 236.613 450 244.189] /Subtype /Link /A << /S /GoTo /D (90) >> >> endobj 2269 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 223.462 450 230.917] /Subtype /Link /A << /S /GoTo /D (90) >> >> endobj 2270 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 208.19 450 217.766] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 2271 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 195.04 450 204.737] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 2272 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 181.889 450 191.586] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 2273 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 168.738 450 178.435] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 2274 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 155.588 450 165.284] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 2275 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 142.437 450 152.134] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 2276 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 131.407 450 138.983] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 2277 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 116.135 450 125.711] /Subtype /Link /A << /S /GoTo /D (92) >> >> endobj 2278 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 102.985 450 112.682] /Subtype /Link /A << /S /GoTo /D (92) >> >> endobj 2279 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 91.955 450 99.41] /Subtype /Link /A << /S /GoTo /D (92) >> >> endobj 2284 0 obj << /D [2282 0 R /XYZ 90 720 null] >> endobj 2281 0 obj << /Font << /F51 5 0 R /F54 28 0 R /F55 85 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2336 0 obj << /Length 2695 /Filter /FlateDecode >> stream xÚíKsÜÆÇïú<.cÞÀÑfìJRR’Š˜Ê!ÎZ‚$Jû`€¥l{ˆyôÚÓ=¬X¤(¥Ãjw{»Áùÿ8ÓÓÓXò“Êýã'Mub¥dªOÖÛ7•õãîÿwæ ΀Åwo¾ùAó^±¦jøÉÅtqqyòŸÕ§þôL4JÔ«ó«nwÝïºÓ3)åꓘ‡îªºÝº;ýïÅ_ß|ci! 3Y®†ó†Õu}bÝk•´ó%)Æ-«›Ó3^UÕê_»óývÛíNÝ%.Nk¹Ú¿uWù®=¬§—núÝõtiγ:ò\k¦kë®äÞ'sÞŒÌѳì‹0y¬Ïýf˜•lØô#…rãèFðþM0ÔÁê ˜e†û·Î¿‹©+/#ídQˆ¤5qPÚ¦ŠÒŽÝáÛÀzµY+éb˜¯OÆ'ùxÁ&Œ~`F`s$eàÆŽ±©%³Nx€ ØŒÝû›n³ÉñR[&»àò}cÈKQb(™Q A]†’#”!2VdÈVn Ð!áú÷´´Ãî/W§|õC¿éÞõãèÞ[õî9²¢HÅ„l^+[~ŒKp$3 (X#³p$G(d¬‡¶LÉ#8dŽ)Ù8ß»ôîm¿ÃÒ ­X¥ùK†Àc €dFEAHŽPÈXå~ŸkPs¶iñlSiöñ?Ã:ÿœsÔ0¢%’…”A!9BQ cE$g\Jˆ‚ÆPxh‡†»v]É×B?¬%’ÅÔá!9By cE&ê#Lއ¿í¸:ãv1òe­˜è~ìJ¢'3Jt("zr„ŠNÆŠ¢WŠÕR@Ñ-.zqEÐ 3F¾È„SÞ`IùdF)Õ@”OŽPåÉXAyÝpfj•¯qåÉ`Jy…i`ÂøÀŒÿH¼øÀ&>+Šok¦å‘øM^ü÷wóoüA~õ×Ì4êÕ­þô¬Æ·F2£À€b!`$G(d,îæŒF©m4“uä"Ìß_ö‡+®6Ý8WÈÝêïÕê»~ç0i‡_æ§SQaÌïj7¿¨¥ŽpŒÉ<Ú%J¢ ÎmérŒD7("T HˆLˆ&"æ€GF|ÍY%øRŸ|~ÙK³D`2£„d¸½dŽÁä…Œ°)¦MUÃB¡üý/ó©YûsE+™Ðõk]­ž25ò•ÈJfYPm„¬ä%‹ŒÉš5’ÊçÿìÖwÃØ»¥/Ó¨G,‚¼h 1†¼%†’ÅÔÕmur %G(Cd¬ÈÌZ  Uö?õC·>ìç|I®nï»aÛXHꤘ5¯è4£Áj‰†dFÑBhHŽPÈXÕ4Ìh%÷ó›î¾Ÿããx·ç ºÝ]ÎhÌíîÚ÷¦lÛ]{Ým§ã:ß’ƒEpãöâϦƒHF¤ %0#¤<^·ÍH aRÒ±¢”µaÊB)µWA@sY3[Ç,ãf¿ [ç#§Â0­t°º¼ŸúO“´Ù¶’nõ’K~ƒÍkV‚-™Q°AØ’#62V„Í%«Rh[¨Çÿý§]7ÌÓ‚Ÿ/ÔêzpñýÝíüì§~s¹n‡ËüŠb“æë=ÔÿÐ’iâxaBÏVgÀ,+ô±³ûrƒžU:yB•&ƒE¥MÅœ(@éP„Ÿ *÷JoúÝÇirðøÍåÐe3Q.$ãJ¼ò‰cÄt‰‘dF1eÃIžPFÈ`‘eY% #¡8wØßÍÉBŽcéÒö˜^ƒ×§DV2£È‚bcd%O(Yd°H– Z[ È 5½õе‡l2bj&–dä)°òâ”°JfVPi «ä ÅŠ  ÅJTÌŠx´,*X(>tC65qS¡xÈtµÔçe{æ1ñÊ•˜Kfs^ñ,sÉÊ,Ne•eÚæbYø|¿½Ýt¿™ ÎÉr÷s;½9b- ÖêÞÅâ¥ò£WÒ=™QºC)ÜœÕ=yBu'ƒ…¹F6Š)ϳEPýzp;¢ñ›õ¦GDߊ3£êe%û,3GС@0#:•W&Gð„D‹ÕÜe4 PóŸj7c7ÌU™ü’Õ¸ÖK†ý;z/J‰¦hEÁôåU¶à›ü (Q‘"I.7æi •ÿþz·ò¹4gÊ6ËÑÑ—¹fÕJ¨E+ 5¯²5ÂäEŠQÓîÑÄ^ Îúí-u¡Ñ.•Zf¬/T¦ ¢•PKfkγ;:à ¥ qSœÕ<‹p»@?ŸGuÃU»ÎgYÖÞ7 /Ä=ú™‡ÇÂ+Ub,™QŒAÙ9Ïîà€'”12XdLÔ̘ÄX8ò˜ªßùæ2í²»e2{Õõ ^ »dFaIà<{×,ð„bG …É5Ó<åÿ&õ“õ»ëM—Ž`ò{Å*k–²Õ\½%|’…TÃ'yBñ!ƒE|*Á¤1Ÿ°|w·9ô· ·@.OdF¨e{ø\ㇼK2£`úqž-VO(,d°‹¨&8„%ì' à  ASŠiãe8©º]»Íw³xïëÒÍö´›» W‰´dF‘Åç2»ßžPÒÈ`‘4É™ªâ ¼T‘´ÿÝõCw™Æ83zéýxê¢RªY2£ ƒºs•í`žPÈÈ`2^3¡d:B6î7ø­÷F3S-í_jNó¢•pKfn®²+à Å q«4ãU<é—¡™m\oúìW<¸µsé–å ¯d‰ÁdF1±à*Ûš<¡ ’Áƒ gŽ 2ŽÓYï·Ûv‡|ID%ÙëýßyàE(Г¬x ž;ÉOBçWDÕ$‹ endstream endobj 2335 0 obj << /Type /Page /Contents 2336 0 R /Resources 2334 0 R /MediaBox [0 0 612 792] /Parent 2285 0 R /Annots [ 2280 0 R 2286 0 R 2287 0 R 2288 0 R 2289 0 R 2290 0 R 2291 0 R 2292 0 R 2293 0 R 2294 0 R 2295 0 R 2296 0 R 2297 0 R 2298 0 R 2299 0 R 2300 0 R 2301 0 R 2302 0 R 2303 0 R 2304 0 R 2305 0 R 2306 0 R 2307 0 R 2308 0 R 2309 0 R 2310 0 R 2311 0 R 2312 0 R 2313 0 R 2314 0 R 2315 0 R 2316 0 R 2317 0 R 2318 0 R 2319 0 R 2320 0 R 2321 0 R 2322 0 R 2323 0 R 2324 0 R 2325 0 R 2326 0 R 2327 0 R 2328 0 R 2329 0 R 2330 0 R 2331 0 R 2332 0 R ] >> endobj 2280 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 707.916 450 717.613] /Subtype /Link /A << /S /GoTo /D (92) >> >> endobj 2286 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 696.887 450 704.462] /Subtype /Link /A << /S /GoTo /D (92) >> >> endobj 2287 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 683.736 450 691.312] /Subtype /Link /A << /S /GoTo /D (92) >> >> endobj 2288 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 668.464 450 678.161] /Subtype /Link /A << /S /GoTo /D (93) >> >> endobj 2289 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 655.313 450 665.01] /Subtype /Link /A << /S /GoTo /D (93) >> >> endobj 2290 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 642.163 450 651.86] /Subtype /Link /A << /S /GoTo /D (93) >> >> endobj 2291 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 629.012 450 638.709] /Subtype /Link /A << /S /GoTo /D (93) >> >> endobj 2292 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 615.861 450 625.558] /Subtype /Link /A << /S /GoTo /D (93) >> >> endobj 2293 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 602.711 450 612.408] /Subtype /Link /A << /S /GoTo /D (93) >> >> endobj 2294 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 589.56 450 599.257] /Subtype /Link /A << /S /GoTo /D (93) >> >> endobj 2295 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 578.531 450 586.106] /Subtype /Link /A << /S /GoTo /D (93) >> >> endobj 2296 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 563.259 450 572.956] /Subtype /Link /A << /S /GoTo /D (94) >> >> endobj 2297 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 552.229 450 559.805] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 2298 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 536.957 450 546.533] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 2299 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 525.928 450 533.382] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 2300 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 510.656 450 520.232] /Subtype /Link /A << /S /GoTo /D (98) >> >> endobj 2301 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 497.505 450 507.202] /Subtype /Link /A << /S /GoTo /D (99) >> >> endobj 2302 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 486.476 450 494.052] /Subtype /Link /A << /S /GoTo /D (99) >> >> endobj 2303 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 471.204 450 480.901] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 2304 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 460.174 450 467.75] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 2305 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 447.024 450 454.599] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 2306 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 433.873 450 440.903] /Subtype /Link /A << /S /GoTo /D (100) >> >> endobj 2307 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 420.722 450 428.298] /Subtype /Link /A << /S /GoTo /D (101) >> >> endobj 2308 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 405.45 450 415.147] /Subtype /Link /A << /S /GoTo /D (104) >> >> endobj 2309 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 391.694 450 402.603] /Subtype /Link /A << /S /GoTo /D (106) >> >> endobj 2310 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 381.27 450 388.846] /Subtype /Link /A << /S /GoTo /D (108) >> >> endobj 2311 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 365.998 450 375.405] /Subtype /Link /A << /S /GoTo /D (109) >> >> endobj 2312 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 352.848 450 362.255] /Subtype /Link /A << /S /GoTo /D (110) >> >> endobj 2313 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 341.818 450 349.394] /Subtype /Link /A << /S /GoTo /D (111) >> >> endobj 2314 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 328.668 450 336.243] /Subtype /Link /A << /S /GoTo /D (112) >> >> endobj 2315 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 313.396 450 323.093] /Subtype /Link /A << /S /GoTo /D (112) >> >> endobj 2316 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 300.245 450 309.942] /Subtype /Link /A << /S /GoTo /D (114) >> >> endobj 2317 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 289.216 450 296.791] /Subtype /Link /A << /S /GoTo /D (115) >> >> endobj 2318 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 276.065 450 283.641] /Subtype /Link /A << /S /GoTo /D (116) >> >> endobj 2319 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 262.914 450 270.49] /Subtype /Link /A << /S /GoTo /D (116) >> >> endobj 2320 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 249.763 450 257.339] /Subtype /Link /A << /S /GoTo /D (118) >> >> endobj 2321 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 236.613 450 244.189] /Subtype /Link /A << /S /GoTo /D (119) >> >> endobj 2322 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 221.341 450 231.038] /Subtype /Link /A << /S /GoTo /D (121) >> >> endobj 2323 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 208.19 450 217.887] /Subtype /Link /A << /S /GoTo /D (125) >> >> endobj 2324 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 197.161 450 204.446] /Subtype /Link /A << /S /GoTo /D (125) >> >> endobj 2325 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 184.01 450 191.586] /Subtype /Link /A << /S /GoTo /D (127) >> >> endobj 2326 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 168.738 450 177.89] /Subtype /Link /A << /S /GoTo /D (128) >> >> endobj 2327 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 155.588 450 165.284] /Subtype /Link /A << /S /GoTo /D (133) >> >> endobj 2328 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 144.558 450 151.588] /Subtype /Link /A << /S /GoTo /D (139) >> >> endobj 2329 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 129.286 450 138.983] /Subtype /Link /A << /S /GoTo /D (140) >> >> endobj 2330 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 118.257 450 125.832] /Subtype /Link /A << /S /GoTo /D (141) >> >> endobj 2331 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 105.106 450 112.682] /Subtype /Link /A << /S /GoTo /D (142) >> >> endobj 2332 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 91.955 450 99.531] /Subtype /Link /A << /S /GoTo /D (142) >> >> endobj 2337 0 obj << /D [2335 0 R /XYZ 90 720 null] >> endobj 2334 0 obj << /Font << /F51 5 0 R /F54 28 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2384 0 obj << /Length 2584 /Filter /FlateDecode >> stream xÚíœßsÛ¸ÇßóWèQž©qHüàÃ=$Ž3MÛëÜLݾ´}P$ÊÕD=$•KþûEü²‚](½8ŽNÌHË]ßÅ ›QóÍ*:SEAªRÏ–»Ô~úþ³W—Æà2²xuóâ§7‚Í%­Øìf=æšiîýܬfÿžØl.þ{ó—×7Þ•à<k°Èc´4ß–3e>£…ƒ•¤Ð—ŒR:ïúvÑ×·›º›»Ëøn¥“… v¼˜{¤È{ÿK~x†ÉyßðãDêÒh( éU2Z_Fr;«ËÈ,!ù©³£v¬”Ÿ4˜àk°Ès|ÉJ­_•å«ß¬>¥ÈŒœÁÕiâ‰Ç/BÏ ˜A/2CлG+U ½È„Ì£§ ¢LP‹^I-z‡ý®9ì/¸ž÷ɾMÊÕÔ·}õû À¬L9À‚X¬9, XðvLñ3W)ùÌ åR("ŠrŒ#Ì_ȸ˜_­»ºý°º¸,”˜/ööb¹n mÇ˶^×m½_Ö#wæW¼r> ¿ÕÃu~~Ö¹ Êü6°V—‘Y¢uNY)ФÁ(ÅI0àY/¡•Õ]fõe3>çm³5 Å|i¾˜¯/ؼ.Žj%º€J‘‚—Ó0ôÝ=æV¡Üc̰Ç<–› ‘d+xÙBƒ1V™QFÏ$W†1áÙòt½ýu„j±Zµu× ÿ)çíb›Nš\ßä²Ù†më%Á £$¢$x)AƒyJL¨ªˆn)y¹Ý6C'ôÛU³ß×Ë~Óì»7º˜·Í.‰I)7Ÿ?&¶%s 3ŒXˆà d 栌Ȳ § ürØö›»m}. Ú$£ÕSšhCšÚ–ÉiÌ0Mãff"9<š¢Áœ¦BkR ¼¦å©¦ÿ4Y_²Ã7wr*§™Ä—ÝätÈ™!Ý (ò„ó)a’cŽ Cß\¬—WÍn7LR@A ?'ý±X°-šc!˜a,Äò@,O h0Ï‚ä„U ò„…·ã„ÅÌL.„™DnÓ‰¤&Z–S"‰$’®¡sˆ3 ‘X5‘à D æ)+BKQ‘W›ýêfHÉz±¬Ç9Èfo'¸¶‘ÂFšÙŽÒÏ«/ä·˜“?˜aòÇŠ@òO üh0/!ˆ®‚únAæêõrPý}wؽ^ô‹w‹®gœçH¯$QåÓ•Ryl«œÈÞ Ó8jvHbïT‹äæÜhv+"Ç:!– PM”’SUêì’“méÞ Ã#‰äºEðâEòxЊˆ¸`nÝâu}ìö?½Z¬®ÌÔãÒ\Û!$(RÕ4ûÀ±m#$˜aˆÄÂAŒO $h0GIYI£®Ž(a'”œ]mªHA«çÜ«â»&̈™!âßÓ?ò‰óâëâX! â»Z㟛®ß/võ_ëO]œ–x^Hͨ¥ž×tÝ6]Nô`†‰ë‰<¢£Á¼èŠævmEwÅÅ·ëëí⮫W'3Ó¥.s ÔJ¢~¸´Ä6s`†k<€ Á< B’JËW©ü[sûr»¨ÒÄh1Ušîã`5‡C0Ãpˆ‚pž@Ð`‡² ºˆq‡ëý²ýt××C=á¸dÙ­6fpÐâ9ך émæ¤f˜ô±ôÁ(=ÌKoe©ãkWeüeñ1× B²©¶ˆ‘aÛ7GF0ÃȈÅbB'Éž@2Ð`ž o[ÈpÅÅca±=tý:¾9ö À„aØêóËÓOp|8aèv*Ï Ãv8:C9aÙíTx0Ï DŽ9qeÈןÌüb³|9ny6ºpãå!+Uß7Z ¶Ms43Œ†X ˆ†à ¤ æ6×#¼ðKàn²¹Xí6ýŸÆÉÆ­É!ƵÇÙæ¸ùÑ|¾²ÕˆtÆ9fÓPCãš>Md†@sOGšÈ Ìu!…Ò„j¿ÒÉ ³ ðØÚüf‡@Û4ýÏ)TL‡"+6Õ2¿vV¼vÁ Ã.&Â.x±Cƒyì¤é³Š;žÇ®gC?÷í¡Nž ¤¨Ø”ñ|é¦/§EŽ¢`†Q ËD•¤(x)BƒyŠ#J³@‘«µýãýæî_Cv\EµvsÁæëäà6 (§±í«n!wªäx fO±ÄOÁÈÌgP…6ANEªKâ%Ña…~<4’àªöpTS_ô]ð8ªšÃÑ[a4F€@0z? ‹X$"¤ôkG®DüfÓÖ¿ ™úb»í\\08^ÿýåÐçݳ=~ÞÞ’i_‚{” Ƿ¸‰Ôd2yÜ-ø¹¹é³Ãn¼®Ø(Òv«?ÖËÕÛ˜«w,ücõ{¢ÍµCæx\d†»×¨L&ÇEž íð`ƒx²2”£¬x¿¶Í»m½Åëší‡Íþ6)]É ¥ì I‡pt‘S0˜a Æ-ËdòhIä Tð$XºÛæÂLYl•X…ókr×ÖËf¿Ë-‚ƽAM?¼Ãánüâ?”•Û:]…1sëRüà™*ÐSÛVÏôÔÁ é©c!X¼,’G¥¤„U•c…‡ý…ˆ¶îšC»´ÛG4hA„˜ŽÂú¯“%S0ÃhŠ56a“8O O'Á>=XAªÊöqڎ׻»mm·7û ÛC»ÇG¦ºä1w¦‰™fËþ ìß– ‚6Ä Åd2ƒ<‚œK?á¬RæÁ´êëh4XÜŽõöžÇ„T]‚-¦JêÃ'ùN£Ìã™!û=Áº"O]x0O—^–âé ã¹m›Ã]”HÕôB¨‡Ë€ ȬT9È‚Y¬;YðB†ó)F¸p‹¯¯Èv‹M²ò%‘LLe†GMbœl9à‚\ÌS4 \ð‡óÀ 3PRå€+pݦO¦¿BrzÔ÷1sêå¸ fw1 L•Iî‚';4˜ç®4?…çND]Ó'÷cKN8ŸR´Gîè¬l9à‚\ÌÓÉ2mä  æ+ÑT:àdbZ«iÏç#guËÌ0âb˜æIâ‚'84˜'ÎL饎8 ­ÍvÑnÒÌ)RÐéUŸtÌÅI–ƒ-˜a°Åú›ô? [ð†ó°QA-l:À¶Ýk‡Óìá{íâ¬v9ê‚F] ÓÉ#‘':4˜£®â¤ºpdŸ¬Ûº~×ÙÝ®?¹³–d_÷çÉårE*=¥wgàb=CK°B`‰õc:YÚ~ TÐHþ…êá´ð¥YêQ9ž¿%a­®?ôM»ÞðÃ5ár:¼$¶½soF÷VØ‹Ñ#éX•,G?’ßüˆÿ– endstream endobj 2383 0 obj << /Type /Page /Contents 2384 0 R /Resources 2382 0 R /MediaBox [0 0 612 792] /Parent 2285 0 R /Annots [ 2333 0 R 2338 0 R 2339 0 R 2340 0 R 2341 0 R 2342 0 R 2343 0 R 2344 0 R 2345 0 R 2346 0 R 2347 0 R 2348 0 R 2349 0 R 2350 0 R 2351 0 R 2352 0 R 2353 0 R 2354 0 R 2355 0 R 2356 0 R 2357 0 R 2358 0 R 2359 0 R 2360 0 R 2361 0 R 2362 0 R 2363 0 R 2364 0 R 2365 0 R 2366 0 R 2367 0 R 2368 0 R 2369 0 R 2370 0 R 2371 0 R 2372 0 R 2373 0 R 2374 0 R 2375 0 R 2376 0 R 2377 0 R 2378 0 R 2379 0 R 2380 0 R ] >> endobj 2333 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 707.916 450 717.323] /Subtype /Link /A << /S /GoTo /D (146) >> >> endobj 2338 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 694.765 450 704.462] /Subtype /Link /A << /S /GoTo /D (147) >> >> endobj 2339 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 683.736 450 690.766] /Subtype /Link /A << /S /GoTo /D (151) >> >> endobj 2340 0 obj << /Type /Annot /Border [0 0 0] /Rect [425.791 657.534 450 667.497] /Subtype /Link /A << /S /GoTo /D (153) >> >> endobj 2341 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 641.096 450 648.672] /Subtype /Link /A << /S /GoTo /D (155) >> >> endobj 2342 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 625.824 450 635.521] /Subtype /Link /A << /S /GoTo /D (155) >> >> endobj 2343 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 614.795 450 622.37] /Subtype /Link /A << /S /GoTo /D (155) >> >> endobj 2344 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 599.523 450 609.22] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 2345 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 588.493 450 596.069] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 2346 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 575.342 450 582.918] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 2347 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 562.192 450 569.768] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 2348 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 549.041 450 556.617] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 2349 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 535.89 450 543.466] /Subtype /Link /A << /S /GoTo /D (156) >> >> endobj 2350 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 522.74 450 530.316] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 2351 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 507.468 450 517.165] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 2352 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 494.317 450 503.893] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 2353 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 481.167 450 490.863] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 2354 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 468.016 450 477.713] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 2355 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 454.865 450 464.562] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 2356 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 441.714 450 451.411] /Subtype /Link /A << /S /GoTo /D (157) >> >> endobj 2357 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 430.685 450 438.14] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 2358 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 415.413 450 424.989] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 2359 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 402.262 450 411.959] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 2360 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 389.112 450 398.809] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 2361 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 378.082 450 385.113] /Subtype /Link /A << /S /GoTo /D (158) >> >> endobj 2362 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 362.507 450 371.962] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 2363 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 349.66 450 359.357] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 2364 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 338.63 450 345.661] /Subtype /Link /A << /S /GoTo /D (159) >> >> endobj 2365 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 325.48 450 333.055] /Subtype /Link /A << /S /GoTo /D (161) >> >> endobj 2366 0 obj << /Type /Annot /Border [0 0 0] /Rect [425.791 299.278 450 309.24] /Subtype /Link /A << /S /GoTo /D (163) >> >> endobj 2367 0 obj << /Type /Annot /Border [0 0 0] /Rect [425.791 266.999 450 279.751] /Subtype /Link /A << /S /GoTo /D (165) >> >> endobj 2368 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 251.229 450 260.926] /Subtype /Link /A << /S /GoTo /D (165) >> >> endobj 2369 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 240.199 450 247.775] /Subtype /Link /A << /S /GoTo /D (166) >> >> endobj 2370 0 obj << /Type /Annot /Border [0 0 0] /Rect [425.791 211.208 450 223.96] /Subtype /Link /A << /S /GoTo /D (169) >> >> endobj 2371 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 195.438 450 205.135] /Subtype /Link /A << /S /GoTo /D (169) >> >> endobj 2372 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 182.287 450 191.984] /Subtype /Link /A << /S /GoTo /D (169) >> >> endobj 2373 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 171.258 450 178.834] /Subtype /Link /A << /S /GoTo /D (170) >> >> endobj 2374 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 158.107 450 165.683] /Subtype /Link /A << /S /GoTo /D (174) >> >> endobj 2375 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 144.957 450 152.532] /Subtype /Link /A << /S /GoTo /D (181) >> >> endobj 2376 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 131.806 450 139.382] /Subtype /Link /A << /S /GoTo /D (182) >> >> endobj 2377 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 118.655 450 126.231] /Subtype /Link /A << /S /GoTo /D (184) >> >> endobj 2378 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 105.504 450 113.08] /Subtype /Link /A << /S /GoTo /D (187) >> >> endobj 2379 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 89.627 450 100.536] /Subtype /Link /A << /S /GoTo /D (189) >> >> endobj 2380 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.636 79.203 450 86.779] /Subtype /Link /A << /S /GoTo /D (190) >> >> endobj 2385 0 obj << /D [2383 0 R /XYZ 90 720 null] >> endobj 2382 0 obj << /Font << /F51 5 0 R /F54 28 0 R /F72 4 0 R /F91 2077 0 R /F52 20 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2390 0 obj << /Length 336 /Filter /FlateDecode >> stream xÚå”;OÃ0…÷ü ö××Ïx„ŠH°!E,ˆ¡´Š€€"Tñó±óhM›&bepâßs}¾8€˜¿Y†ŒÔÊ ­_ÖÏ>'Ðߥ^FŠË"Yä 0j™T”q‰bƒîñ¶ª*’ò,3/KW?Uµ#©oy%n\éW¯y(n’«bç¦8Ÿi'(Žú1¤Bj>ôãÛcÂtýÜ+ñª©V/¡£ðu½qŸÁ{‘û-DK)š‰Ì[µ+)IA›nÐOçOþŽäG뢖\Qãw?Då³ôQ´/£¸UÉF"?,Ö¦V™*Žð Š3ÏWCµ²ÏòÍIïç Õâ?¡RšAÉ&Ð~‹¬CU:…vÚ, •ŠòþO’à _øvoTZõ'éŽJN!ïÒ›#¾SM@p6z”÷uö¸¿SEp endstream endobj 2389 0 obj << /Type /Page /Contents 2390 0 R /Resources 2388 0 R /MediaBox [0 0 612 792] /Parent 2285 0 R /Annots [ 2381 0 R 2386 0 R 2387 0 R ] >> endobj 2381 0 obj << /Type /Annot /Border [0 0 0] /Rect [425.791 710.037 450 720] /Subtype /Link /A << /S /GoTo /D (193) >> >> endobj 2386 0 obj << /Type /Annot /Border [0 0 0] /Rect [425.791 674.869 450 687.621] /Subtype /Link /A << /S /GoTo /D (197) >> >> endobj 2387 0 obj << /Type /Annot /Border [0 0 0] /Rect [425.791 642.491 450 655.243] /Subtype /Link /A << /S /GoTo /D (203) >> >> endobj 2391 0 obj << /D [2389 0 R /XYZ 90 720 null] >> endobj 2388 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F91 2077 0 R >> /ProcSet [ /PDF /Text ] >> endobj 2392 0 obj << /S /GoTo /D (Reference introduction) >> endobj 2394 0 obj (Introduction to reference manual) endobj 2395 0 obj << /S /GoTo /D (Installation) >> endobj 2397 0 obj (Installation) endobj 2398 0 obj << /S /GoTo /D (Work directory) >> endobj 2400 0 obj (Work directory) endobj 2401 0 obj << /S /GoTo /D (Hard classes) >> endobj 2403 0 obj (Cfengine hard classes) endobj 2404 0 obj << /S /GoTo /D (Filenames and paths) >> endobj 2406 0 obj (Filenames and paths) endobj 2407 0 obj << /S /GoTo /D (Debugging with signals) >> endobj 2409 0 obj (Debugging with signals) endobj 2410 0 obj << /S /GoTo /D (Cfkey) >> endobj 2412 0 obj (Cfkey reference) endobj 2413 0 obj << /S /GoTo /D (Cfshow) >> endobj 2415 0 obj (Cfshow reference) endobj 2416 0 obj << /S /GoTo /D (Cfagent reference) >> endobj 2418 0 obj (Cfagent reference) endobj 2419 0 obj << /S /GoTo /D (Cfagent intro) >> endobj 2421 0 obj (Cfagent intro) endobj 2422 0 obj << /S /GoTo /D (The file cfagent.conf) >> endobj 2424 0 obj (The file cfagent.conf) endobj 2425 0 obj << /S /GoTo /D (Cfagent Runtime Options) >> endobj 2427 0 obj (Cfagent runtime options) endobj 2428 0 obj << /S /GoTo /D (Variable expansion and contexts) >> endobj 2430 0 obj (Variable expansion and contexts) endobj 2431 0 obj << /S /GoTo /D (Setting variables with functions) >> endobj 2433 0 obj (Setting variables with functions) endobj 2434 0 obj << /S /GoTo /D (Special variables) >> endobj 2436 0 obj (Special variables) endobj 2437 0 obj << /S /GoTo /D (Iteration over lists) >> endobj 2439 0 obj (Iteration over lists) endobj 2440 0 obj << /S /GoTo /D (Cfengine classes) >> endobj 2442 0 obj (Cfengine classes) endobj 2443 0 obj << /S /GoTo /D (Setting classes with special functions) >> endobj 2445 0 obj (Setting classes with special functions) endobj 2446 0 obj << /S /GoTo /D (AccessedBefore) >> endobj 2448 0 obj (AccessedBefore) endobj 2449 0 obj << /S /GoTo /D (ChangedBefore) >> endobj 2451 0 obj (ChangedBefore) endobj 2452 0 obj << /S /GoTo /D (ClassMatch) >> endobj 2454 0 obj (ClassMatch) endobj 2455 0 obj << /S /GoTo /D (FileExists) >> endobj 2457 0 obj (FileExists) endobj 2458 0 obj << /S /GoTo /D (GroupExists) >> endobj 2460 0 obj (GroupExists) endobj 2461 0 obj << /S /GoTo /D (HostRange) >> endobj 2463 0 obj (HostRange) endobj 2464 0 obj << /S /GoTo /D (IsDefined) >> endobj 2466 0 obj (IsDefined) endobj 2467 0 obj << /S /GoTo /D (IsDir) >> endobj 2469 0 obj (IsDir) endobj 2470 0 obj << /S /GoTo /D (IsLink) >> endobj 2472 0 obj (IsLink) endobj 2473 0 obj << /S /GoTo /D (IsPlain) >> endobj 2475 0 obj (IsPlain) endobj 2476 0 obj << /S /GoTo /D (IsNewerThan) >> endobj 2478 0 obj (IsNewerThan) endobj 2479 0 obj << /S /GoTo /D (IPRange) >> endobj 2481 0 obj (IPRange) endobj 2482 0 obj << /S /GoTo /D (PrepModule) >> endobj 2484 0 obj (PrepModule) endobj 2485 0 obj << /S /GoTo /D (Regcmp) >> endobj 2487 0 obj (Regcmp) endobj 2488 0 obj << /S /GoTo /D (ReturnsZero) >> endobj 2490 0 obj (ReturnsZero) endobj 2491 0 obj << /S /GoTo /D (ReturnsZeroShell) >> endobj 2493 0 obj (ReturnsZeroShell) endobj 2494 0 obj << /S /GoTo /D (Strcmp) >> endobj 2496 0 obj (Strcmp) endobj 2497 0 obj << /S /GoTo /D (UserExists) >> endobj 2499 0 obj (UserExists) endobj 2500 0 obj << /S /GoTo /D (IsGreaterThan) >> endobj 2502 0 obj (IsGreaterThan) endobj 2503 0 obj << /S /GoTo /D (IsLessThan) >> endobj 2505 0 obj (IsLessThan) endobj 2506 0 obj << /S /GoTo /D (Examples setting classes) >> endobj 2508 0 obj (Examples setting classes) endobj 2509 0 obj << /S /GoTo /D (acl) >> endobj 2511 0 obj (acl) endobj 2512 0 obj << /S /GoTo /D (ACEs) >> endobj 2514 0 obj (Access control entries) endobj 2515 0 obj << /S /GoTo /D (Solaris ACLs) >> endobj 2517 0 obj (Solaris ACLs) endobj 2518 0 obj << /S /GoTo /D (DFS ACLs) >> endobj 2520 0 obj (DFS ACLs) endobj 2521 0 obj << /S /GoTo /D (NT ACLs) >> endobj 2523 0 obj (NT ACLs) endobj 2524 0 obj << /S /GoTo /D (Windows ACL Example) >> endobj 2526 0 obj (Windows ACL Example) endobj 2527 0 obj << /S /GoTo /D (Posix ACL Example) >> endobj 2529 0 obj (Posix ACL Example) endobj 2530 0 obj << /S /GoTo /D (alerts) >> endobj 2532 0 obj (alerts) endobj 2533 0 obj << /S /GoTo /D (binservers) >> endobj 2535 0 obj (binservers) endobj 2536 0 obj << /S /GoTo /D (broadcast) >> endobj 2538 0 obj (broadcast) endobj 2539 0 obj << /S /GoTo /D (control) >> endobj 2541 0 obj (control) endobj 2542 0 obj << /S /GoTo /D (AbortClasses) >> endobj 2544 0 obj (AbortClasses) endobj 2545 0 obj << /S /GoTo /D (access) >> endobj 2547 0 obj (access) endobj 2548 0 obj << /S /GoTo /D (actionsequence) >> endobj 2550 0 obj (actionsequence) endobj 2551 0 obj << /S /GoTo /D (addclasses) >> endobj 2553 0 obj (AddClasses) endobj 2554 0 obj << /S /GoTo /D (addinstallable) >> endobj 2556 0 obj (AddInstallable) endobj 2557 0 obj << /S /GoTo /D (AllowRedefinitionOf) >> endobj 2559 0 obj (AllowRedefinitionOf) endobj 2560 0 obj << /S /GoTo /D (Auditing) >> endobj 2562 0 obj (Auditing) endobj 2563 0 obj << /S /GoTo /D (AutoDefine) >> endobj 2565 0 obj (AutoDefine) endobj 2566 0 obj << /S /GoTo /D (BinaryPaddingChar) >> endobj 2568 0 obj (BinaryPaddingChar) endobj 2569 0 obj << /S /GoTo /D (BindToInterface in cfagent) >> endobj 2571 0 obj (BindToInterface in cfagent) endobj 2572 0 obj << /S /GoTo /D (ChecksumDatabase in cfagent) >> endobj 2574 0 obj (ChecksumDatabase in cfagent) endobj 2575 0 obj << /S /GoTo /D (ChecksumPurge) >> endobj 2577 0 obj (ChecksumPurge) endobj 2578 0 obj << /S /GoTo /D (ChecksumUpdates) >> endobj 2580 0 obj (ChecksumUpdates) endobj 2581 0 obj << /S /GoTo /D (CompressCommand) >> endobj 2583 0 obj (CompressCommand) endobj 2584 0 obj << /S /GoTo /D (childlibpath) >> endobj 2586 0 obj (ChildLibPath) endobj 2587 0 obj << /S /GoTo /D (copylinks) >> endobj 2589 0 obj (CopyLinks) endobj 2590 0 obj << /S /GoTo /D (defaultcopytype) >> endobj 2592 0 obj (DefaultCopyType) endobj 2593 0 obj << /S /GoTo /D (defaultpkgmgr) >> endobj 2595 0 obj (DefaultPkgMgr) endobj 2596 0 obj << /S /GoTo /D (deletenonuserfiles) >> endobj 2598 0 obj (DeleteNonUserFiles) endobj 2599 0 obj << /S /GoTo /D (deletenonownerfiles) >> endobj 2601 0 obj (DeleteNonOwnerFiles) endobj 2602 0 obj << /S /GoTo /D (deletenonusermail) >> endobj 2604 0 obj (DeleteNonUserMail) endobj 2605 0 obj << /S /GoTo /D (deletenonownermail) >> endobj 2607 0 obj (DeleteNonOwnerMail) endobj 2608 0 obj << /S /GoTo /D (domain) >> endobj 2610 0 obj (domain) endobj 2611 0 obj << /S /GoTo /D (dpkginstallcommand) >> endobj 2613 0 obj (DPKGInstallCommand) endobj 2614 0 obj << /S /GoTo /D (dryrun) >> endobj 2616 0 obj (DryRun) endobj 2617 0 obj << /S /GoTo /D (editbinaryfilesize) >> endobj 2619 0 obj (editbinaryfilesize) endobj 2620 0 obj << /S /GoTo /D (editfilesize) >> endobj 2622 0 obj (editfilesize) endobj 2623 0 obj << /S /GoTo /D (emptyresolvconf) >> endobj 2625 0 obj (EmptyResolvConf) endobj 2626 0 obj << /S /GoTo /D (exclamation) >> endobj 2628 0 obj (Exclamation) endobj 2629 0 obj << /S /GoTo /D (excludecopy) >> endobj 2631 0 obj (ExcludeCopy) endobj 2632 0 obj << /S /GoTo /D (excludelinks) >> endobj 2634 0 obj (ExcludeLink) endobj 2635 0 obj << /S /GoTo /D (ExpireAfter) >> endobj 2637 0 obj (ExpireAfter) endobj 2638 0 obj << /S /GoTo /D (FreeBSDInstallCommand) >> endobj 2640 0 obj (FreeBSDInstallCommand) endobj 2641 0 obj << /S /GoTo /D (FreeBSDRemoveCommand) >> endobj 2643 0 obj (FreeBSDRemoveCommand) endobj 2644 0 obj << /S /GoTo /D (FullEncryption) >> endobj 2646 0 obj (FullEncryption) endobj 2647 0 obj << /S /GoTo /D (homepattern) >> endobj 2649 0 obj (HomePattern) endobj 2650 0 obj << /S /GoTo /D (HostnameKeys in cfagent) >> endobj 2652 0 obj (HostnameKeys in cfagent) endobj 2653 0 obj << /S /GoTo /D (IfElapsed in cfagent) >> endobj 2655 0 obj (IfElapsed in cfagent) endobj 2656 0 obj << /S /GoTo /D (IgnoreFriendRegex) >> endobj 2658 0 obj (FriendIgnoreRegex) endobj 2659 0 obj << /S /GoTo /D (IgnoreInterfaceRegex) >> endobj 2661 0 obj (IgnoreInterfaceRegex) endobj 2662 0 obj << /S /GoTo /D (Inform) >> endobj 2664 0 obj (Inform) endobj 2665 0 obj << /S /GoTo /D (interfacename) >> endobj 2667 0 obj (InterfaceName) endobj 2668 0 obj << /S /GoTo /D (fileextension) >> endobj 2670 0 obj (FileExtensions) endobj 2671 0 obj << /S /GoTo /D (lastseen) >> endobj 2673 0 obj (LastSeen) endobj 2674 0 obj << /S /GoTo /D (lastseenexpireafter) >> endobj 2676 0 obj (LastSeenExpireAfter) endobj 2677 0 obj << /S /GoTo /D (linkcopies) >> endobj 2679 0 obj (LinkCopies) endobj 2680 0 obj << /S /GoTo /D (LogDirectory) >> endobj 2682 0 obj (LogDirectory) endobj 2683 0 obj << /S /GoTo /D (LogTidyHomeFiles) >> endobj 2685 0 obj (LogTidyHomeFiles) endobj 2686 0 obj << /S /GoTo /D (moduledirectory) >> endobj 2688 0 obj (moduledirectory) endobj 2689 0 obj << /S /GoTo /D (mountpattern) >> endobj 2691 0 obj (mountpattern) endobj 2692 0 obj << /S /GoTo /D (netmask) >> endobj 2694 0 obj (netmask) endobj 2695 0 obj << /S /GoTo /D (nonalphanumfiles) >> endobj 2697 0 obj (NonAlphaNumFiles) endobj 2698 0 obj << /S /GoTo /D (nfstype) >> endobj 2700 0 obj (nfstype) endobj 2701 0 obj << /S /GoTo /D (PortageInstallCommand) >> endobj 2703 0 obj (PortageInstallCommand) endobj 2704 0 obj << /S /GoTo /D (repchar) >> endobj 2706 0 obj (RepChar) endobj 2707 0 obj << /S /GoTo /D (repository) >> endobj 2709 0 obj (Repository) endobj 2710 0 obj << /S /GoTo /D (RPMcommand) >> endobj 2712 0 obj (RPMcommand) endobj 2713 0 obj << /S /GoTo /D (rpminstallcommand) >> endobj 2715 0 obj (RPMInstallCommand) endobj 2716 0 obj << /S /GoTo /D (schedule) >> endobj 2718 0 obj (Schedule) endobj 2719 0 obj << /S /GoTo /D (secureinput) >> endobj 2721 0 obj (SecureInput) endobj 2722 0 obj << /S /GoTo /D (sensiblecount) >> endobj 2724 0 obj (SensibleCount) endobj 2725 0 obj << /S /GoTo /D (sensiblesize) >> endobj 2727 0 obj (SensibleSize) endobj 2728 0 obj << /S /GoTo /D (showactions) >> endobj 2730 0 obj (ShowActions) endobj 2731 0 obj << /S /GoTo /D (singlecopy) >> endobj 2733 0 obj (SingleCopy) endobj 2734 0 obj << /S /GoTo /D (site) >> endobj 2736 0 obj (site/faculty) endobj 2737 0 obj << /S /GoTo /D (SkipIdentify) >> endobj 2739 0 obj (SkipIdentify) endobj 2740 0 obj << /S /GoTo /D (Smtpserver) >> endobj 2742 0 obj (smtpserver) endobj 2743 0 obj << /S /GoTo /D (SplayTime) >> endobj 2745 0 obj (SplayTime) endobj 2746 0 obj << /S /GoTo /D (split) >> endobj 2748 0 obj (Split) endobj 2749 0 obj << /S /GoTo /D (spooldirectories) >> endobj 2751 0 obj (SpoolDirectories) endobj 2752 0 obj << /S /GoTo /D (suninstallcommand) >> endobj 2754 0 obj (SUNInstallCommand) endobj 2755 0 obj << /S /GoTo /D (suspiciousnames) >> endobj 2757 0 obj (suspiciousnames) endobj 2758 0 obj << /S /GoTo /D (sysadm) >> endobj 2760 0 obj (sysadm) endobj 2761 0 obj << /S /GoTo /D (Syslog) >> endobj 2763 0 obj (Syslog) endobj 2764 0 obj << /S /GoTo /D (SyslogFacility) >> endobj 2766 0 obj (SyslogFacility) endobj 2767 0 obj << /S /GoTo /D (timezone) >> endobj 2769 0 obj (timezone) endobj 2770 0 obj << /S /GoTo /D (TimeOut) >> endobj 2772 0 obj (TimeOut) endobj 2773 0 obj << /S /GoTo /D (Verbose) >> endobj 2775 0 obj (Verbose) endobj 2776 0 obj << /S /GoTo /D (Warnings) >> endobj 2778 0 obj (Warnings) endobj 2779 0 obj << /S /GoTo /D (warnnonuserfiles) >> endobj 2781 0 obj (WarnNonUserFiles) endobj 2782 0 obj << /S /GoTo /D (warnnonownerfiles) >> endobj 2784 0 obj (WarnNonOwnerFiles) endobj 2785 0 obj << /S /GoTo /D (warnnonusermail) >> endobj 2787 0 obj (WarnNonUserMail) endobj 2788 0 obj << /S /GoTo /D (warnnonownermail) >> endobj 2790 0 obj (WarnNonOwnerMail) endobj 2791 0 obj << /S /GoTo /D (classes) >> endobj 2793 0 obj (classes) endobj 2794 0 obj << /S /GoTo /D (copy) >> endobj 2796 0 obj (copy) endobj 2797 0 obj << /S /GoTo /D (copy example) >> endobj 2799 0 obj (copy example) endobj 2800 0 obj << /S /GoTo /D (hard links in copy) >> endobj 2802 0 obj (Hard links in copying) endobj 2803 0 obj << /S /GoTo /D (Too many open files) >> endobj 2805 0 obj (Too many open files) endobj 2806 0 obj << /S /GoTo /D (defaultroute) >> endobj 2808 0 obj (defaultroute) endobj 2809 0 obj << /S /GoTo /D (disks) >> endobj 2811 0 obj (disks) endobj 2812 0 obj << /S /GoTo /D (directories) >> endobj 2814 0 obj (directories) endobj 2815 0 obj << /S /GoTo /D (disable) >> endobj 2817 0 obj (disable) endobj 2818 0 obj << /S /GoTo /D (editfiles) >> endobj 2820 0 obj (editfiles) endobj 2821 0 obj << /S /GoTo /D (AbortAtLineMatching) >> endobj 2823 0 obj (AbortAtLineMatching) endobj 2824 0 obj << /S /GoTo /D (Append) >> endobj 2826 0 obj (Append) endobj 2827 0 obj << /S /GoTo /D (AppendIfNoLineMatching) >> endobj 2829 0 obj (AppendIfNoLineMatching) endobj 2830 0 obj << /S /GoTo /D (AppendIfNoSuchLine) >> endobj 2832 0 obj (AppendIfNoSuchLine) endobj 2833 0 obj << /S /GoTo /D (AppendIfNoSuchLinesFromFile) >> endobj 2835 0 obj (AppendIfNoSuchLinesFromFile) endobj 2836 0 obj << /S /GoTo /D (AppendToLineIfNotContains) >> endobj 2838 0 obj (AppendToLineIfNotContains) endobj 2839 0 obj << /S /GoTo /D (Audit) >> endobj 2841 0 obj (Audit in editfiles) endobj 2842 0 obj << /S /GoTo /D (AutoCreate) >> endobj 2844 0 obj (AutoCreate) endobj 2845 0 obj << /S /GoTo /D (AutomountDirectResources) >> endobj 2847 0 obj (AutomountDirectResources) endobj 2848 0 obj << /S /GoTo /D (Backup in editfiles) >> endobj 2850 0 obj (Backup in editfiles) endobj 2851 0 obj << /S /GoTo /D (BeginGroupIfDefined) >> endobj 2853 0 obj (BeginGroupIfDefined) endobj 2854 0 obj << /S /GoTo /D (BeginGroupIfNotDefined) >> endobj 2856 0 obj (BeginGroupIfNotDefined) endobj 2857 0 obj << /S /GoTo /D (BeginGroupIfFileExists) >> endobj 2859 0 obj (BeginGroupIfFileExists) endobj 2860 0 obj << /S /GoTo /D (BeginGroupIfFileIsNewer) >> endobj 2862 0 obj (BeginGroupIfFileIsNewer) endobj 2863 0 obj << /S /GoTo /D (BeginGroupIfLineContaining) >> endobj 2865 0 obj (BeginGroupIfLineContaining) endobj 2866 0 obj << /S /GoTo /D (BeginGroupIfLineMatching) >> endobj 2868 0 obj (BeginGroupIfLineMatching) endobj 2869 0 obj << /S /GoTo /D (BeginGroupIfMatch) >> endobj 2871 0 obj (BeginGroupIfMatch) endobj 2872 0 obj << /S /GoTo /D (BeginGroupIfNoLineContaining) >> endobj 2874 0 obj (BeginGroupIfNoLineContaining) endobj 2875 0 obj << /S /GoTo /D (BeginGroupIfNoLineMatching) >> endobj 2877 0 obj (BeginGroupIfNoLineMatching) endobj 2878 0 obj << /S /GoTo /D (BeginGroupIfNoMatch) >> endobj 2880 0 obj (BeginGroupIfNoMatch) endobj 2881 0 obj << /S /GoTo /D (BeginGroupIfNoSuchLine) >> endobj 2883 0 obj (BeginGroupIfNoSuchLine) endobj 2884 0 obj << /S /GoTo /D (BreakIfLineMatches) >> endobj 2886 0 obj (BreakIfLineMatches) endobj 2887 0 obj << /S /GoTo /D (CatchAbort) >> endobj 2889 0 obj (CatchAbort) endobj 2890 0 obj << /S /GoTo /D (CommentLinesMatching) >> endobj 2892 0 obj (CommentLinesMatching) endobj 2893 0 obj << /S /GoTo /D (CommentLinesStarting) >> endobj 2895 0 obj (CommentLinesStarting) endobj 2896 0 obj << /S /GoTo /D (CommentNLines) >> endobj 2898 0 obj (CommentNLines) endobj 2899 0 obj << /S /GoTo /D (CommentToLineMatching) >> endobj 2901 0 obj (CommentToLineMatching) endobj 2902 0 obj << /S /GoTo /D (DefineClasses) >> endobj 2904 0 obj (DefineClasses) endobj 2905 0 obj << /S /GoTo /D (DefineInGroup) >> endobj 2907 0 obj (DefineInGroup) endobj 2908 0 obj << /S /GoTo /D (DeleteLinesAfterThisMatching) >> endobj 2910 0 obj (DeleteLinesAfterThisMatching) endobj 2911 0 obj << /S /GoTo /D (DeleteLinesContaining) >> endobj 2913 0 obj (DeleteLinesContaining/DeleteLinesNotContaining) endobj 2914 0 obj << /S /GoTo /D (DeleteLinesMatching) >> endobj 2916 0 obj (DeleteLinesMatching/DeleteLinesNotMatching) endobj 2917 0 obj << /S /GoTo /D (DeleteLinesStarting) >> endobj 2919 0 obj (DeleteLinesStarting/DeleteLinesNotStarting) endobj 2920 0 obj << /S /GoTo /D (DeleteLinesNotContaining) >> endobj 2922 0 obj (DeleteLinesNotContainingFileItems) endobj 2923 0 obj << /S /GoTo /D (DeleteLinesNotMatchingFileItems) >> endobj 2925 0 obj (DeleteLinesNotMatchingFileItems) endobj 2926 0 obj << /S /GoTo /D (DeleteLinesNotStartingFileItems) >> endobj 2928 0 obj (DeleteLinesNotStartingFileItems) endobj 2929 0 obj << /S /GoTo /D (DeleteNLines) >> endobj 2931 0 obj (DeleteNLines) endobj 2932 0 obj << /S /GoTo /D (DeleteToLineMatching) >> endobj 2934 0 obj (DeleteToLineMatching) endobj 2935 0 obj << /S /GoTo /D (EditMode (binary)) >> endobj 2937 0 obj (EditMode and binary editing) endobj 2938 0 obj << /S /GoTo /D (EditSplit) >> endobj 2940 0 obj (EditSplit) endobj 2941 0 obj << /S /GoTo /D (EmptyEntireFilePlease) >> endobj 2943 0 obj (EmptyEntireFilePlease) endobj 2944 0 obj << /S /GoTo /D (ElseDefineClasses) >> endobj 2946 0 obj (ElseDefineClasses) endobj 2947 0 obj << /S /GoTo /D (EndGroup) >> endobj 2949 0 obj (EndGroup) endobj 2950 0 obj << /S /GoTo /D (EndLoop) >> endobj 2952 0 obj (EndLoop) endobj 2953 0 obj << /S /GoTo /D (ExpandVariables) >> endobj 2955 0 obj (ExpandVariables) endobj 2956 0 obj << /S /GoTo /D (ExpireAfter editfiles) >> endobj 2958 0 obj (ExpireAfter editfiles) endobj 2959 0 obj << /S /GoTo /D (Filter) >> endobj 2961 0 obj (Filter) endobj 2962 0 obj << /S /GoTo /D (FixEndOfLine) >> endobj 2964 0 obj (FixEndOfLine) endobj 2965 0 obj << /S /GoTo /D (ForEachLineIn) >> endobj 2967 0 obj (ForEachLineIn quoted-filename) endobj 2968 0 obj << /S /GoTo /D (GotoLastLine) >> endobj 2970 0 obj (GotoLastLine) endobj 2971 0 obj << /S /GoTo /D (HashCommentLinesContaining) >> endobj 2973 0 obj (HashCommentLinesContaining) endobj 2974 0 obj << /S /GoTo /D (HashCommentLinesMatching) >> endobj 2976 0 obj (HashCommentLinesMatching) endobj 2977 0 obj << /S /GoTo /D (HashCommentLinesStarting) >> endobj 2979 0 obj (HashCommentLinesStarting) endobj 2980 0 obj << /S /GoTo /D (IfElapsed (editing)) >> endobj 2982 0 obj (IfElapsed) endobj 2983 0 obj << /S /GoTo /D (IncrementPointer) >> endobj 2985 0 obj (IncrementPointer quoted-number) endobj 2986 0 obj << /S /GoTo /D (Inform (editing)) >> endobj 2988 0 obj (Inform editfiles) endobj 2989 0 obj << /S /GoTo /D (InsertFile) >> endobj 2991 0 obj (InsertFile) endobj 2992 0 obj << /S /GoTo /D (InsertLine) >> endobj 2994 0 obj (InsertLine) endobj 2995 0 obj << /S /GoTo /D (LocateLineMatching) >> endobj 2997 0 obj (LocateLineMatching) endobj 2998 0 obj << /S /GoTo /D (PercentCommentLinesContaining) >> endobj 3000 0 obj (PercentCommentLinesContaining) endobj 3001 0 obj << /S /GoTo /D (PercentCommentLinesMatching) >> endobj 3003 0 obj (PercentCommentLinesMatching) endobj 3004 0 obj << /S /GoTo /D (PercentCommentLinesStarting) >> endobj 3006 0 obj (PercentCommentLinesStarting) endobj 3007 0 obj << /S /GoTo /D (Prepend (editing)) >> endobj 3009 0 obj (Prepend) endobj 3010 0 obj << /S /GoTo /D (PrependIfNoLineMatching) >> endobj 3012 0 obj (PrependIfNoLineMatching) endobj 3013 0 obj << /S /GoTo /D (PrependIfNoSuchLine) >> endobj 3015 0 obj (PrependIfNoSuchLine) endobj 3016 0 obj << /S /GoTo /D (Recurse (editing)) >> endobj 3018 0 obj (Recurse) endobj 3019 0 obj << /S /GoTo /D (ReplaceLineWith) >> endobj 3021 0 obj (ReplaceLineWith) endobj 3022 0 obj << /S /GoTo /D (ReplaceAll With) >> endobj 3024 0 obj (ReplaceAll/With) endobj 3025 0 obj << /S /GoTo /D (ReplaceFirst) >> endobj 3027 0 obj (ReplaceFirst/With) endobj 3028 0 obj << /S /GoTo /D (ReplaceLinesMatchingField) >> endobj 3030 0 obj (ReplaceLinesMatchingField) endobj 3031 0 obj << /S /GoTo /D (Repository) >> endobj 3033 0 obj (Repository editfiles) endobj 3034 0 obj << /S /GoTo /D (ResetSearch) >> endobj 3036 0 obj (ResetSearch) endobj 3037 0 obj << /S /GoTo /D (RunScript) >> endobj 3039 0 obj (RunScript) endobj 3040 0 obj << /S /GoTo /D (RunScriptIfLineMatching) >> endobj 3042 0 obj (RunScriptIfLineMatching) endobj 3043 0 obj << /S /GoTo /D (RunScriptIfNoLineMatching) >> endobj 3045 0 obj (RunScriptIfNoLineMatching) endobj 3046 0 obj << /S /GoTo /D (SetCommentStart) >> endobj 3048 0 obj (SetCommentStart) endobj 3049 0 obj << /S /GoTo /D (SetCommentEnd) >> endobj 3051 0 obj (SetCommentEnd) endobj 3052 0 obj << /S /GoTo /D (SetLine) >> endobj 3054 0 obj (SetLine) endobj 3055 0 obj << /S /GoTo /D (SetScript) >> endobj 3057 0 obj (SetScript) endobj 3058 0 obj << /S /GoTo /D (SlashCommentLinesContaining) >> endobj 3060 0 obj (SlashCommentLinesContaining) endobj 3061 0 obj << /S /GoTo /D (SlashCommentLinesMatching) >> endobj 3063 0 obj (SlashCommentLinesMatching) endobj 3064 0 obj << /S /GoTo /D (SlashCommentLinesStarting) >> endobj 3066 0 obj (SlashCommentLinesStarting) endobj 3067 0 obj << /S /GoTo /D (SplitOn) >> endobj 3069 0 obj (SplitOn) endobj 3070 0 obj << /S /GoTo /D (SysLog) >> endobj 3072 0 obj (Syslog editfiles) endobj 3073 0 obj << /S /GoTo /D (Umask) >> endobj 3075 0 obj (Umask) endobj 3076 0 obj << /S /GoTo /D (UnCommentLinesContaining) >> endobj 3078 0 obj (UnCommentLinesContaining) endobj 3079 0 obj << /S /GoTo /D (UnCommentLinesMatching) >> endobj 3081 0 obj (UnCommentLinesMatching) endobj 3082 0 obj << /S /GoTo /D (UnCommentsNLines) >> endobj 3084 0 obj (UnCommentNLines) endobj 3085 0 obj << /S /GoTo /D (UnCommentToLineMatching) >> endobj 3087 0 obj (UnCommentToLineMatching) endobj 3088 0 obj << /S /GoTo /D (UnsetAbort) >> endobj 3090 0 obj (UnsetAbort) endobj 3091 0 obj << /S /GoTo /D (UseShell) >> endobj 3093 0 obj (UseShell) endobj 3094 0 obj << /S /GoTo /D (WarnIfFileMissing) >> endobj 3096 0 obj (WarnIfFileMissing) endobj 3097 0 obj << /S /GoTo /D (WarnIfLineContaining) >> endobj 3099 0 obj (WarnIfLineContaining) endobj 3100 0 obj << /S /GoTo /D (WarnIfLineMatching) >> endobj 3102 0 obj (WarnIfLineMatching) endobj 3103 0 obj << /S /GoTo /D (WarnIfLineStarting) >> endobj 3105 0 obj (WarnIfLineStarting) endobj 3106 0 obj << /S /GoTo /D (WarnIfNoLineContaining) >> endobj 3108 0 obj (WarnIfNoLineContaining) endobj 3109 0 obj << /S /GoTo /D (WarnIfNoLineMatching) >> endobj 3111 0 obj (WarnIfNoLineMatching) endobj 3112 0 obj << /S /GoTo /D (WarnIfNoLineStarting) >> endobj 3114 0 obj (WarnIfNoLineStarting) endobj 3115 0 obj << /S /GoTo /D (WarnIfNoSuchLine) >> endobj 3117 0 obj (WarnIfNoSuchLine) endobj 3118 0 obj << /S /GoTo /D (Editfiles on Binary Files) >> endobj 3120 0 obj (Editfiles on Binary Files) endobj 3121 0 obj << /S /GoTo /D (files) >> endobj 3123 0 obj (files) endobj 3124 0 obj << /S /GoTo /D (Syntax) >> endobj 3126 0 obj (Syntax) endobj 3127 0 obj << /S /GoTo /D (Recursion) >> endobj 3129 0 obj (Recursion) endobj 3130 0 obj << /S /GoTo /D (Directory permissions) >> endobj 3132 0 obj (Directory permissions) endobj 3133 0 obj << /S /GoTo /D (Checksums and change management) >> endobj 3135 0 obj (Checksums and change management) endobj 3136 0 obj << /S /GoTo /D (home directive) >> endobj 3138 0 obj (home directive) endobj 3139 0 obj << /S /GoTo /D (Owner and group wildcards) >> endobj 3141 0 obj (Owner and group wildcards) endobj 3142 0 obj << /S /GoTo /D (Files linkchildren) >> endobj 3144 0 obj (Files linkchildren) endobj 3145 0 obj << /S /GoTo /D (touch) >> endobj 3147 0 obj (touch) endobj 3148 0 obj << /S /GoTo /D (create) >> endobj 3150 0 obj (create) endobj 3151 0 obj << /S /GoTo /D (filters) >> endobj 3153 0 obj (filters) endobj 3154 0 obj << /S /GoTo /D (Complete filter examples) >> endobj 3156 0 obj (Complete filter examples) endobj 3157 0 obj << /S /GoTo /D (groups) >> endobj 3159 0 obj (groups/classes) endobj 3160 0 obj << /S /GoTo /D (homeservers) >> endobj 3162 0 obj (homeservers) endobj 3163 0 obj << /S /GoTo /D (ignore) >> endobj 3165 0 obj (ignore) endobj 3166 0 obj << /S /GoTo /D (import) >> endobj 3168 0 obj (import) endobj 3169 0 obj << /S /GoTo /D (interfaces) >> endobj 3171 0 obj (interfaces) endobj 3172 0 obj << /S /GoTo /D (links) >> endobj 3174 0 obj (links) endobj 3175 0 obj << /S /GoTo /D (Single links) >> endobj 3177 0 obj (Single links) endobj 3178 0 obj << /S /GoTo /D (Multiple Links) >> endobj 3180 0 obj (Multiple Links) endobj 3181 0 obj << /S /GoTo /D (Link Children) >> endobj 3183 0 obj (Link Children) endobj 3184 0 obj << /S /GoTo /D (Relative and absolute links) >> endobj 3186 0 obj (Relative and absolute links) endobj 3187 0 obj << /S /GoTo /D (Hard links) >> endobj 3189 0 obj (Hard Links) endobj 3190 0 obj << /S /GoTo /D (mailserver) >> endobj 3192 0 obj (mailserver) endobj 3193 0 obj << /S /GoTo /D (methods) >> endobj 3195 0 obj (methods) endobj 3196 0 obj << /S /GoTo /D (localhost examples) >> endobj 3198 0 obj (Localhost examples) endobj 3199 0 obj << /S /GoTo /D (remotehost examples) >> endobj 3201 0 obj (Remote host examples) endobj 3202 0 obj << /S /GoTo /D (miscmounts) >> endobj 3204 0 obj (miscmounts) endobj 3205 0 obj << /S /GoTo /D (mountables) >> endobj 3207 0 obj (mountables) endobj 3208 0 obj << /S /GoTo /D (processes) >> endobj 3210 0 obj (processes) endobj 3211 0 obj << /S /GoTo /D (packages) >> endobj 3213 0 obj (Packages) endobj 3214 0 obj << /S /GoTo /D (rename) >> endobj 3216 0 obj (rename) endobj 3217 0 obj << /S /GoTo /D (required) >> endobj 3219 0 obj (required) endobj 3220 0 obj << /S /GoTo /D (resolve) >> endobj 3222 0 obj (resolve) endobj 3223 0 obj << /S /GoTo /D (scli) >> endobj 3225 0 obj (scli) endobj 3226 0 obj << /S /GoTo /D (shellcommands) >> endobj 3228 0 obj (shellcommands) endobj 3229 0 obj << /S /GoTo /D (strategies) >> endobj 3231 0 obj (strategies) endobj 3232 0 obj << /S /GoTo /D (tidy) >> endobj 3234 0 obj (tidy) endobj 3235 0 obj << /S /GoTo /D (unmount) >> endobj 3237 0 obj (unmount) endobj 3238 0 obj << /S /GoTo /D (Cfservd.conf and cfrun reference) >> endobj 3240 0 obj (Cfservd and cfrun reference) endobj 3241 0 obj << /S /GoTo /D (cfservd control) >> endobj 3243 0 obj (control cfservd) endobj 3244 0 obj << /S /GoTo /D (IP address ranges) >> endobj 3246 0 obj (IP address ranges) endobj 3247 0 obj << /S /GoTo /D (AllowConnectionsFrom) >> endobj 3249 0 obj (AllowConnectionsFrom) endobj 3250 0 obj << /S /GoTo /D (AllowMultipleConnectionsFrom) >> endobj 3252 0 obj (AllowMultipleConnectionsFrom) endobj 3253 0 obj << /S /GoTo /D (AllowUsers) >> endobj 3255 0 obj (AllowUsers) endobj 3256 0 obj << /S /GoTo /D (AutoExecCommand) >> endobj 3258 0 obj (AutoExecCommand) endobj 3259 0 obj << /S /GoTo /D (AutoExecInterval) >> endobj 3261 0 obj (AutoExecInterval) endobj 3262 0 obj << /S /GoTo /D (BindToInterface in cfservd) >> endobj 3264 0 obj (BindToInterface in cfservd) endobj 3265 0 obj << /S /GoTo /D (ChecksumDatabase in cfservd) >> endobj 3267 0 obj (ChecksumDatabase in cfservd) endobj 3268 0 obj << /S /GoTo /D (cfrunCommand) >> endobj 3270 0 obj (cfrunCommand) endobj 3271 0 obj << /S /GoTo /D (DenyBadClocks) >> endobj 3273 0 obj (DenyBadClocks) endobj 3274 0 obj << /S /GoTo /D (DenyConnectionsFrom) >> endobj 3276 0 obj (DenyConnectionsFrom) endobj 3277 0 obj << /S /GoTo /D (cfservd HostnameKeys) >> endobj 3279 0 obj (HostnameKeys in cfservd) endobj 3280 0 obj << /S /GoTo /D (cfservd IfElapsed) >> endobj 3282 0 obj (IfElapsed in cfservd) endobj 3283 0 obj << /S /GoTo /D (LogAllConnections) >> endobj 3285 0 obj (LogAllConnections) endobj 3286 0 obj << /S /GoTo /D (LogEncryptedTransfers) >> endobj 3288 0 obj (LogEncryptedTransfers) endobj 3289 0 obj << /S /GoTo /D (MaxConnections) >> endobj 3291 0 obj (MaxConnections) endobj 3292 0 obj << /S /GoTo /D (TrustKeysFrom) >> endobj 3294 0 obj (TrustKeysFrom) endobj 3295 0 obj << /S /GoTo /D (DynamicAddresses) >> endobj 3297 0 obj (DynamicAddresses) endobj 3298 0 obj << /S /GoTo /D (admit grant and deny) >> endobj 3300 0 obj (admit, grant and deny) endobj 3301 0 obj << /S /GoTo /D (root=) >> endobj 3303 0 obj (root=) endobj 3304 0 obj << /S /GoTo /D (encrypt=) >> endobj 3306 0 obj (encrypt=true) endobj 3307 0 obj << /S /GoTo /D (SkipVerify) >> endobj 3309 0 obj (SkipVerify) endobj 3310 0 obj << /S /GoTo /D (cfrun) >> endobj 3312 0 obj (cfrun) endobj 3313 0 obj << /S /GoTo /D (Firewalls and NATs) >> endobj 3315 0 obj (Firewalls and NATs) endobj 3316 0 obj << /S /GoTo /D (Cfexecd reference) >> endobj 3318 0 obj (Cfexecd reference) endobj 3319 0 obj << /S /GoTo /D (Problem solving) >> endobj 3321 0 obj (Problem solving) endobj 3322 0 obj << /S /GoTo /D (cf.preconf bootstrap file) >> endobj 3324 0 obj (cf.preconf bootstrap file) endobj 3325 0 obj << /S /GoTo /D (cfrc resource file) >> endobj 3327 0 obj (cfrc resource file) endobj 3328 0 obj << /S /GoTo /D (Example configuration file) >> endobj 3330 0 obj (Example configuration files) endobj 3331 0 obj << /S /GoTo /D (cfagent.conf) >> endobj 3333 0 obj (cfagent.conf) endobj 3334 0 obj << /S /GoTo /D (cf.groups) >> endobj 3336 0 obj (cf.groups) endobj 3337 0 obj << /S /GoTo /D (cf.main) >> endobj 3339 0 obj (cf.main) endobj 3340 0 obj << /S /GoTo /D (cf.site) >> endobj 3342 0 obj (cf.site) endobj 3343 0 obj << /S /GoTo /D (cf.motd) >> endobj 3345 0 obj (cf.motd) endobj 3346 0 obj << /S /GoTo /D (cf.users) >> endobj 3348 0 obj (cf.users) endobj 3349 0 obj << /S /GoTo /D (cf.solaris) >> endobj 3351 0 obj (cf.solaris) endobj 3352 0 obj << /S /GoTo /D (cf.linux) >> endobj 3354 0 obj (cf.linux) endobj 3355 0 obj << /S /GoTo /D (cf.freebsd) >> endobj 3357 0 obj (cf.freebsd / cf.netbsd) endobj 3358 0 obj << /S /GoTo /D (cfservd.conf) >> endobj 3360 0 obj (cfservd.conf tutorial) endobj 3361 0 obj << /S /GoTo /D (Variable Index) >> endobj 3363 0 obj (Variable Index) endobj 3364 0 obj << /S /GoTo /D (Concept Index) >> endobj 3366 0 obj (Concept Index) endobj 3367 0 obj << /S /GoTo /D (FAQ Index) >> endobj 3369 0 obj (FAQ Index) endobj 3370 0 obj [355.6] endobj 3371 0 obj [599.5 571 571 856.5 856.5 285.5 314 513.9 513.9 513.9 513.9 513.9 770.7 456.8 513.9 742.3 799.4 513.9 927.8 1042 799.4 285.5 285.5 513.9 856.5 513.9 856.5 799.4 285.5 399.7 399.7 513.9 799.4 285.5 342.6 285.5 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 285.5 285.5 285.5 799.4 485.3 485.3 799.4 770.7 727.9 742.3 785 699.4 670.8 806.5 770.7 371 528.1 799.2 642.3 942 770.7 799.4 699.4 799.4 756.5 571 742.3 770.7 770.7 1056.2 770.7 770.7 628.1 285.5 513.9 285.5 513.9 285.5 285.5 513.9 571 456.8 571 457.2 314 513.9 571 285.5 314 542.4 285.5 856.5 571 513.9 571 542.4 402 405.4 399.7 571 542.4 742.3 542.4 542.4 456.8] endobj 3372 0 obj [314.8] endobj 3373 0 obj [514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6] endobj 3374 0 obj [638.9 638.9 958.3 958.3 319.4 351.4 575 575 575 575 575 925 511.1 597.2 830.5 894.4 575 1041.7 1169.4 894.4 319.4 350 602.8 958.3 575 958.3 894.4 319.4 447.2 447.2 575 894.4 319.4 383.3 319.4 575 575 575 575 575 575 575 575 575 575 575 319.4 319.4 350 894.4 543.1 543.1 894.4 869.4 818 830.5 881.9 755.5 723.6 904.2 900 436.1 594.4 901.4 691.7 1091.7 900 863.9 786.1 863.9 862.5 638.9 800 884.7 869.4 1188.9 869.4 869.4 702.8 319.4 602.8 319.4 575 319.4 319.4 559 638.9 511.1 638.9 527.1 351.4 575 638.9 319.4 351.4 606.9 319.4 958.3 638.9 575 638.9 606.9 473.6 453.6 447.2 638.9] endobj 3375 0 obj [803.5] endobj 3376 0 obj [569.5] endobj 3377 0 obj [555.6 555.6 833.3 833.3 277.8 305.6 500 500 500 500 500 808.6 444.4 500 722.2 777.8 500 902.8 1013.9 777.8 277.8 277.8 500 833.3 500 833.3 777.8 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8 527.8] endobj 3378 0 obj [1200 1200 1200 1200] endobj 3379 0 obj [525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525] endobj 3380 0 obj [613.3 562.2 587.8 881.7 894.4 306.7 332.2 511.1 511.1 511.1 511.1 511.1 831.3 460 536.7 715.6 715.6 511.1 882.8 985 766.7 255.6 306.7 514.4 817.8 769.1 817.8 766.7 306.7 408.9 408.9 511.1 766.7 306.7 357.8 306.7 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 306.7 306.7 306.7 766.7 511.1 511.1 766.7 743.3 703.9 715.6 755 678.3 652.8 773.6 743.3 385.6 525 768.9 627.2 896.7 743.3 766.7 678.3 766.7 729.4 562.2 715.6 743.3 743.3 998.9 743.3 743.3 613.3 306.7 514.4 306.7 511.1 306.7 306.7 511.1 460 460 511.1 460 306.7 460 511.1 306.7 306.7 460 255.6 817.8 562.2 511.1 511.1 460 421.7 408.9 332.2 536.7 460 664.4 463.9 485.6 408.9] endobj 3381 0 obj [525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525] endobj 3382 0 obj [525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525] endobj 3383 0 obj [583.3 555.6 555.6 833.3 833.3 277.8 305.6 500 500 500 500 500 755.6 444.4 559.7 722.2 777.8 500 905.6 1016.7 777.8 277.8 305.6 544.4 833.3 500 833.3 777.8 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 305.6 777.8 472.2 472.2 777.8 755.6 711.1 722.2 766.7 655.6 627.8 786.1 783.3 397.2 516.7 783.3 600 950 783.3 750 683.3 750 759.7 555.6 694.4 769.4 755.6 1033.3 755.6 755.6 611.1 280 544.4 280 500 277.8 277.8 486.1 555.6 444.4 555.6 466.7 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 427.8 394.4 390.3 555.6 527.8 722.2 527.8 527.8] endobj 3384 0 obj [777.8 277.8 777.8 500 777.8 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 500 500 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 777.8 1000 1000 777.8 777.8 1000 1000 500 500 1000 1000 1000 777.8 1000 1000 611.1 611.1 1000 1000 1000 777.8 275 1000 666.7 666.7 888.9 888.9 0 0 555.6 555.6 666.7 500 722.2 722.2 777.8 777.8 611.1 798.5 656.8 526.5 771.4 527.8 718.7 594.9 844.5 544.5 677.8 762 689.7 1200.9 820.5 796.1 695.6 816.7 847.5 605.6 544.6 625.8 612.8 987.8 713.3 668.3 724.7 666.7 666.7 666.7 666.7 666.7 611.1 611.1 444.4 444.4 444.4 444.4 500 500 388.9 388.9] endobj 3385 0 obj [583.3 555.6 555.6 833.3 833.3 277.8 305.6 500 500 500 500 500 750 444.4 500 722.2 777.8 500 902.8 1013.9 777.8 277.8 277.8 500 833.3 500 833.3 777.8 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8 527.8 444.4 500 1000 500 500 500] endobj 3386 0 obj [625 625 937.5 937.5 312.5 343.7 562.5 562.5 562.5 562.5 562.5 849.5 500 574.1 812.5 875 562.5 1018.5 1143.5 875 312.5 342.6 581 937.5 562.5 937.5 875 312.5 437.5 437.5 562.5 875 312.5 375 312.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 312.5 312.5 342.6 875 531.3 531.3 875 849.5 799.8 812.5 862.3 738.4 707.2 884.3 879.6 419 581 880.8 675.9 1067.1 879.6 844.9 768.5 844.9 839.1 625 782.4 864.6 849.5 1162 849.5 849.5 687.5 312.5 581 312.5 562.5 312.5 312.5 546.9 625 500 625 513.3 343.7 562.5 625 312.5 343.7 593.7 312.5 937.5 625 562.5 625 593.7 459.5 443.8 437.5 625 593.7 812.5 593.7 593.7 500] endobj 3387 0 obj << /Length1 1288 /Length2 6611 /Length3 0 /Length 7364 /Filter /FlateDecode >> stream xÚ­•eXê¨iaènJ:†îNéFJjhfèéFº[Ré”i¤‘DRRºî¸÷={sÏù{Ÿù3ï·Ö·ÖûÕ †6»”Ô,…¸³ƒ8@Â@UiÄÁ``q›»ÛA!²æî`a HH”ò°rÃâüÂ<¼Â<ü  ÔÙÇÕÎÆÖÈ$Ãü'I(åvµ³4‡UÍÝmÁN°–æŽ@m¨¥ØÝ‡(åèÔú3à ¨v»z‚­8 ÐÊÎÒh¶±ƒ8ÿ)A¬¡@¿‡­<œÿò»ºÁ¤€L0If LÑ qôZ­œjPX/0Ìäÿ‡Ô—÷ptT3wúSþÏ&ýOØÜÉÎÑçÿ&@œ=ÜÁ®@U¨Øòß©úà¿Ý¤¡ŽÿÓEÉÝÜÑÎR bãrý=dç&oç ¶Ò°s·´Z›;ºÿC¬þ[¶k pJèÉih²þ}šÅ4Ìí î:>ÎÿTý“üƒþeØÞ¸Úy¸8¸¸@°DØç?ßLþ«—Äje]>~ ¹««¹v/`Äôí V`o Ø&Ìɺæa;´†ºþ&??SúÏÐß$ä”ù—œ²ÿ’Sî€ÍSù—`1õHÈ©ý/Áb/ÿ!Ø à4ÿ—`,þ%X¦å?âârZ=Aü¹œÖÿ",hýÿíž$ÃŒlž /Óö ò9Ÿ&ÖfÿaÆO¦ìøaÎNO4`Î'Ó‚>A˜–ó?È ëã { Ð'‹ÁD]ž LÔõ ÂDÝþss4w{²¬¤û„exÖOäŸÔ^wänÑý5Çä‚]3f~zšýÌòm#78ÍRõÙr¦½ ÝÇîhžù}À¯>½:R‘ò²d ÷xp¿PƒIVgûÙ7¸^#ÏÆÞì7üòYŽºaõÏyh´p2\*"y#V¼pR’‘V&Bí#P[Y—O =ðnŠQ Þ>¼‚»¶D‰‰q#‹œwGÇ\úE.жÖ(À.Ä×¾™·]ß\Ñ4®Êùž¼gËpõN^ÆÛ«í˜n³½‘êfSve¸Š\t¤Ç<$qAì³Þõl×à {íffZΠCQ»!E=«’ÍÊ`Þè 2.&L,°ô;çcÅ3ÒgQTU1úßœ½tÝçÆž·Vçˆ[õ[â3t2«¤D––Š›ÈĉbËõxí;j‹œtõ_’ðÐsYJ» ùrÌÆ¼uÂFÓáÏ眫~¤¸‡ÆŠ<÷[ƒÉ>Q†¿©1M6ÎÑñ/bx§2Um€ÝÏܯ— €Û9­õ`[¾¢úQ=›½ÚѦ%üÃS9Ó@÷¬~_éP¯î™©c³¹l4?q«hy¬”ä41Ž‘“Ò<˜u@•ßCê÷‰vÞº 57x‚¯ü™Ð è&òk;#<ü´¸Äø1"ÜmÒr—ïÆfa…>(—~Fì7ö?Óm ~E«÷[ܹf.˜ŽŠ¢·ÏXeçV½à¬WœS¤8=u·T(­Tý:Ãþ€“™0$nq6Û¦pJ ¾ÊA‹ ^ÔZÑZ ˜¸Ñhz*`ÆylwAd5•Þ´M# . ¯(Ø|éɕʉ«‚¬©V²Õ‡}aÚDsmè.¹2Ãl£± ׬%,íåÝÏxã–úâf^«œß­ºqhßó°,ÿâ¾tà°Ó&Ç”'/þM¦W;ztm-±/><Ží‰‚tÅg—ëúeù²RltwÎa "ÇYÀ¹½õû¦RËOΦR½z;1" Ч‹–nM0 ¸\›3|ÙF"±PmÒV¼³cQêˆ]ûlï ÏŽy0 P¯õy`É…œ£æ¥Å8@ˆÖÖ„p«âZü/}¢Ì‘Avt#Uý>TêÇ ¡’½SE.¥ ¯ãgu-Îí”kI/‘ͨ.—Ó±_]F[Jü²f¶öiP~Ú˜Ýz­ËÑãM²Et¾–2KXÁ§èYÅ­fˆ³øÇsàºÝgm£]f˜ÓQûݨºÉ3šˆ†¤…·´uç\ìÓÈs:»Æn”I Í7>£ŒÓÕ8=ó”Ζƒ+Wšx+kFV¯p’ÒWPºåL_ïÔ’Rã&”`;3eÏØoÉtcP0?ȯ:`Ã/´é´Ê½OH3¸²ªÛªeý&EUÔõfÂ,[ÅO`dß¡‚$Oý“nÎ7aÕ]ʽ•UÔ‚”¹enìíÇÛ499QŸ†è¬ÀÔ3¤ò3GªòRÓ4E¸g·³ çPwì;¤ ç“|Lìß¿HÄ/x”áµ$¼ 7»ÃÒ•·rå{ ̉ÄWU Û)Ï¡Ó'F½ê›q#4(öÌõ-Âz²2nɈz%Ö÷ѳ¢ö©@3ûÓÔ8ÅìhJ{XªËÐò°z"|x·‘“)ùýM2ÌÓz£I–­gj·+Èr¹úcF^¹õhË^/иÞ‡ñV:h娗®oœÆµîQ»³`Å´Íšú&€L:ˆáò}¯»“ÒÚ#¼='çÕú6î?+ ¸_Ž¼ÊŸx™Ö¸æÐfLñ ǧa9~=¤¶å(mPm”Óƒà{2Pb*j¼vTdàuu&d´˜¸¦$\x¡Iòt“…¼ÅSžQ­5çåSðØDYÉ<ѬùÍ{ôrÌÂÇœZ©ï¿t<ȵÔë‰Zn½Îë©ìôWµŠÒSDðèMví^5g¼#ëµû»“„(èðê3ßó®Y¢X-?VZ³è_Ÿsµët6pO¥ Åj`ÒºR |:jòÈÎU°iÙ…´Ü>®u‡[Xr‹éÿ䀌.ß,0î ~UÞˆ0 Ñ‘ÑÈ;’§àÊý,ãüÜmYUWצ±6)° #:[[E…be+ã„×6FõLs¾ T^2/Qëbå¿<ä¼Ì&ŽüÀ§Þ7M£j¥¶0&Ã-¾¶«”¸*Önû(è¡åð¡+7Î/Æ´V€µŠ®Bï‚qÄÅH¸ô¹ƒúÃ4y,gkí¸ë*UÿvÇ—åMéO¡:kŠwß p#;y~ëZxw›®B¢I|¤°ÌÝõ…gÿuáœHŒ p³DÅWF×Å`SHf÷h4¦ÝtV|ïŒéPòÉoþºMœ¹5:~ß?Ç•)† Ôô&4Z’?غâ8àZNÊ=’Nñ†õð™$jG…‹ˆ‘ 0°¨ôŽîÀ¯ÍXûörgwµŠ—ò2BI“rÀë3;ö«ýªwí:˜ ©É:Ó+Ü'†êy‚m³¾4_Ãóï³në;ÍÌ ½ÝΗDž+ÊéÍt.)´‡¼ýS¡ôSt-ÀiYvr8ótБ,.¿™ýY)y|Ç‚ÄÕ"­µãák  ÕEyØ€þýAYgºcÒðº7ÜZÃFMMÒ•ü±Ëh6ŽqýêCcÛ»Cg®Όkš%½yú·ù  ¦Ô×LÚ&ކå.™ñ²¯æíQ?3ö|>~/ZIïøÁ+²ø‚Äý랋̤èwº–‡¼º=Ï~pM\Tð ÝGצœp:/a¸®æ&}ƒtî­ê¢l¤šè}üèH…ƒüçå·J6Tç™Å{r uFKÏÙ#»à߯ó1Ï/6+}Áˆc…86}T—š¤pß5uK-£&!ž«p!VJ´0¾gù¥Zozåö.Ó]"ʼn›È1î!òâê>w”yG¨ˆæ/iÈ~¹®¨íÛ‘°ý.Þ¦ûä»{ù^qºôöâ÷Êlß|wTQìÂ~nÞJîÄ5£`ÆÁ}g€2[dIŸ“i}àw€b‰ª$Õ¥_@ã_]}»E“Í!=}ápkÿ°€¢E£~z8™hÅàŽ†|娱%{Öccé‘26×:z‡œñ*ÓdçR¼FÇðN3«•Z¬À&Òò^¬}ìxó=]««?éþ‡@ L¨ûLƒ»Ì¿4òák…,É!Ù¡áhÝôqßöQl…‹Õ‰„ÌéŒZè¾aâÁY4rÛƒ¨½¤„(Ûu,xwñ×€ÏòPL*Šž|QÞg…\ó볚ë;¢-ज€¦.ž0íãØNëI]ÇÎ[ŽÔ%Fƒò±«·€ã¬<ò¼¾kIFëjÿŸ) ˜ÞŠM.ëk_ Ô°Ì&Ù3ù\÷+9‹¨MêìóSóÙéÐ'RwMGa %<‰×F¬Å^é‰Ê"n¨Ê]n=®ªTijvçYú{zŸ†\uC+$ÄH~ËÊLžò®voO«KØx¸ÉÉÜõmäô¯…8ÝîõâXŸ`³}âÖú ’ø(ôÆh;^mù ^_Q¥ÃµM•ˆG²Ç%ž±j¾ÅXœkÙÖ%K?ñ€÷pF£á¨m‹qb§­©÷çæª@'ƒV$1Ô닊·fʈt¦RÏxŒ‹õô£(³ÑJÎ{[¦ê­ñŒÚ2p¹5 '<ÓÒ5ªÒÏYÃÒ–×›ì‘ÈB.Î2I¤úuGç ¾»-ù” qúä¢N ŒNóóèÓ›å¬Å£aô+/3?gõQH¥vû=$»¹w59>÷üЛs µv¿ÿÝ™”ž ÚþÚÄ“#þÙ^!º€ÐY…Î ÿ¶¯bB´ëäX¨0ÇûN°åoQhÜí qXåµZࢗ«@zzü{ï9‰ÖOŠ &Aù±ñÍSÃâAIÈÆ//YgɘÍ×$ï÷cÇÆiØì¾þŒëîè}Ü©‹)aYЯÏOnd¯¬žâ?FòbG$¾ÁÔk»Ó¸˜c§z©É³Ó(߆HÉ•)ôÃ…UàQ¡ú~Úa¡åL°Ýà6e±§³}nø1ïÓ < L‘6’–Ißßì#þ Å=So¨.‚Ÿ±žmjÐø÷õü é \]FÞ¶!í¹eb“ÙzØ­r q£Dv^·Eñ2?Ÿü–¼giÙasõ `kÔPT·Ã½À4—–£æ‚OeÝÛGkΉ´™C’zæ;3ý‰ÏÂ'Y2æÀ ± YC&3MŒhíc÷ìò)6ð¨GÌn‹Åº)Ñÿ§)W¢OÉû2Šï?Z_BO9 ·×³”f'}ÒÙ`>¥êùXsÓ*JçÙÛñSí¢ewìé xm:¯õtA™½ц}ñ9n>yËÜ»Þ4L®´Ž Û {N©†ç"3Eô€÷ähs~ ²a« ~1iòª6gȦmœPÞäK.Mû˜à_Áï+;&Õ]ì\ŽhøW+u­–%[Jû§-%¼xÞÈ3†ø™ëôÄÐdT^4¸ «Ú["ÙøVƤ#r†ÔÃÇæ¹Ï ØÐ ´ÿ,ƬÂ1”'k×ù*J‰ä•ƒ£ïºýuëà>•Þ;`>ìZ)½QêÒ¨d ØO‘½Îà5#'Ó1û×:C°!Ñß$h q¯t§“».NÍO9·¦3&w ŽKEãšd 3c—ŠVMmË@¥„µF«.ÜC”ÌÌúI³ú¸|Úp.S{pî>°—o®Kõñ{%,Ëuþ*«ŽÕþ[çãWaÙõ6ø =Ÿ×Eݨø™Wî‘ˆæ ©ÏqwJ/ZÎ]î_¾®j4#:ÃÙ< *9*G¡p åŽÓ;±î<{€Ç4Ýn$ޝlOÚR=¬JÆŸôî#1W:Ö¡µx]3dÿ£Ýï=>Ñ‹æ@á‡g;2ØÒz‚à½b+‘Xák¢)vb•Þ¯øÌqh ýõß›æÜ­w”`ƒ¯±~ }ÝJ`31Ä:C^ÃVÇð‡ÎE×ò»F~ \QÞ‚Bi²ä“-ñ›|µM&N_¿ŽÜ£&hà .(V‚W¨âB¥Îß”\þ}#A½Â¥»W%=ÁoŸpšý¢°3£†kÍŒ7©êÑÖ%¡{ºðí|Ù›”Txû'Œ^žôš¯¯ôÇ6R'Ì®\K~"O &Ýs-‹"GQ{ˆSFɼÞIó=ÀH5éöSæ£Õøþ&Ÿµ÷‡hšØ5Þ0ÚËéJâÌdËÞpSvÛóÔæ”®I}ä“ åH4d€ÖÙ3öÄ.Þ9ôF¾7Å’„sh‰@ÓO½6n½9&Ýo0qÓg§2’²Œ§¨e¢°|Ϙ–Ò$1$˜/Ü”Wú¹ÖчôãqæFÂY°U g c¯—\=R‘)!umØ]\±NážqíDÎ|îy.E<7´ Cƒ†ÿÇ£øÓ ó%‰l^Þ9çÉÖøq÷U‰ocP;Ë0PžVW3==ƒ!Ü…ô 2ÖBî·°Èó“V×_¢ˆÇnrqÛàV>ù“ɉ•º•ù)ä8s¿¼ ?°ë–J¸Ã6É5¾Iÿ~îÒ׊ͪL{À‡ô™$ú‘Û’âŒC›÷T\agìÊh‰edúœSƒÄšd±»pÙŸß8w°VljÅ‹gsY¼\€¬F}ª#V¶Ýâê¸Ë¥¨ØdHøË=½P·jÀKÖLëx~äYz¤.Khè)Ó–­ñ!£&?ª:Ò!>¸¨ðÀ‚˜Æ<¶ =Y°—(P†Ú‰h¯°bf(ßìÿøô’)'_ÁÀ X,Š^½¦`+2bA9‚§–Úy8¨dxeýn„Þß}/- ´÷öƒíæœhfŨs–È%˜äK²¤â–ôפíZ¼á$ÆIl¸ˆ*át¦ÑßPöi MqJ)sˆ‡|ºJ)«'M•™$¬BÏ‚7'øæö&jÇí^ä}ãæÏž¸!mÂGržøpe'8“ç¥ÏC·OâÛƒ¥l ±ç©'ZêRÜ1¨ç^Âæf‡wq]”-Ø~‰óçò"HT¡À×&S-Ôß!½ŽÕ>Ú6–‹—B›¿®ø,øqâÛ¢­ƒÂB—GMÇ .šŒJ³&Ã.œêVºj3Z|õ[V[P´s-fZŸöMîuWÒíoí #ß IÄïà‚ m]òu‹…¶¢„‰m¢ƒ|7òÍChK9ó&î³TEö ÌË7å&x{4ù”r /…ó’V —°ˆè..›áÊJt"_GG8—‰Ý‰\DCê¢üm}dÜÝ¿¦t‹Ëö~AøG‰qÐ&äúßžÕeÖ¹8ÉÛ3FüÔ¼ª´^îŒlþ|Ä›ÌrAAé7GE¬%ëß¼óºã¢Ù@0MRéÌ) ùfF_ä˜Lò5½d+;³÷$cØuQ{GZ_<ç%¨òþl«$ i"Í«hIC ÝÏÂJr3| ŠM¢Ó±£µ‰`¯öتL§ˆum: 6H^³ÔEïÈpo©==fzXíÃKfwZN,£ZÃÅ$3sgðÇëÑÆzpÏgw?¡ ‹áPäYåp-ÆdÑ([ïF‘×RSQ ^U¸¥~ÆÏx[QÙ—ùUwzñUW|µª«x>md‹ŒxÅ;K¸9B7Bîs¾˜àô©²ð„˜É’–‹&sÅ„n•ƒûöɆa¬BåßÂj>ÅÅFé¹ ¢³þnìÍkŸS(#ò&],o4ùZò¼½ƒÓ5d‰oÅ çQ$ž-pÿÃÙMõ$+Ú|³5WØúØws7ÚÈkAt5´P¬ ‡ ’ïÍ£òLÊÞ¨$ñÅÍ÷%Àjµ¸|äó13ëi².±[dY==¥ç+!tÄq•T'.‘€Lë%6\¹ülêhºÃv/NЭÎHº;bíâ‰îýíNdf7ÅìmßÞ†ËìëÞ #KñjÊÅZ“ÆžR’ðV…Ã_ŒYIÞ1ï'h™ IË‹Ëðb[(—kNÜDÿN‰ÏìY ,52~;\ž^pòwýýÏÚø6yÐw[l¢©IMÕ5¢Ü/U¼²/…ÜJƒ”¢äS5“ú&›Åó稒y!yb?Q¤¢:¹†®å=Ä¢oš4oÉZÅÇ4÷“äç9¾(æë]…SB XU³ CÞÆ¿_ý˜‚”qAp|ü«óšy¢L’t†o_wI©˜ëÁ™X¹ÒWÂ}¬%سZz,à—Ô&|Ù¹Ø{ÅßÙf+\‰—øá2‘ÙsÄèüyI¿Û7Ôø¨ÔHKÄàïÝ+M2¹„3gîkA ‚Ò‹Ã"òfí£Ð¤Ÿ �©ªT·Š7²‡>¬Xì™F®ÏìÓ'Ø[v>÷F¡Œ¤ð޽0 Z5ý’)(yI«Šü\š€p>½1ƒ7è6ù)¿”/‡ÝÞÓ 8™2淜ǖú£àäüêÊ17ï.§œîôF‰õf°›ÄŽ8lÒ}C7lðý·Äá`©Ýˆ¸vN<±æˆ»!(ãòˆ,3-éËlÌO4b8¬, €¹üÊ=ÈWî]ê Õ³6žü/}ê U\J&ÞÊ‚ë[Ƈú7ûÚfʾFûÁe6/j ±ÜÒçu…RÚšZíÒ´c0PãìùF8X…z¿i+Õ< ˜8ï‰-o»; =ð±Noâ>”ÿ*U‚¥ŠþrôÔS ðª>åûÒ²´]ªç_¥>ºb Ö &UáëAÑ•ä7‡BdÒ˜Qߤæ ^!e]—«ÛœÊ‘_ö7r>Þ_3vT[1KÔ çg%W¨ÏðŽ©ÈÛö¿äš Ðk/—Úã_ïDá?È`5"5¢|GpX–aQw‚Á¡BwN) ò8#šãMÆúHÈôAûÝÿàmKöÆŠ²Š“öz>ô³ø`'ufž*Q¢¤p'¾2ißT„¾c¯µo=™ìËõœ¸cªI‚£í|q q’Ý/ w«œ“‰$3QüK4B‘ˆ5V·³;…­¬|ᘂÁŸÍ7þ´‡fƒ endstream endobj 3388 0 obj << /Type /FontDescriptor /FontName /AXVEPQ+CMB10 /Flags 4 /FontBBox [-62 -250 1011 750] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle 0 /StemV 108 /XHeight 444 /CharSet (/B/C/D/E/L/O/S/Y/a/b/c/d/e/f/ff/fi/g/h/i/j/k/l/m/n/o/p/period/q/r/s/slash/t/u/v/w/x/y/zero) /FontFile 3387 0 R >> endobj 3389 0 obj << /Length1 1728 /Length2 10946 /Length3 0 /Length 11900 /Filter /FlateDecode >> stream xÚ­—eTÎ’öqw:¸»;AwÎàÌàîNpw Npw ®AƒKpw wþ÷îÞdw¿¾g¾Ì¯»ªž§ª{úœ¡¥TÕ`}k6Ê‚A®¬œlœB)%I]N.' -­”3ÐÔÕ ’6u 89oݬ\N>!n!^Z€ØÑËÙÆÊÚÀ ÅøO?à­ÐÙÆÜP2uµ:@j˜›Ú4Àæ6@W/6À[{{€ú?.u  ÐÙhÁ†ÂÉ °°1w˜­l@(ìÿ8’Y‚üÿ^¶psüï-w ³ Ä€b’±hÙ{,€–(ìÊ`ˆâäÿ‡©ÿ]\ÖÍÞ^ÙÔáŸòÿšÒÿÙ7u°±÷ú¯°ƒ£›+Р¶:ƒþw¨ðßæ$ÁöÿGFÞÕÔÞÆü-ÈÊàø÷’‹¬'ÐBÕÆÕÜ`ijïü×:dñ¿-@Æö/ìŠ:êšïÞ3ÿ×yþkSÕÔäªéåøŸ²ÿDÿ‹9ÿ0d:Î6ž6NH äóßß ÿ—˜ Èla‚\^>€©³³© äf@ˆàà °Y=@Oˆcv6Ø’€ŒÄ` vFùç8ùxìoÿYú7ñØ%ÿ?€]ê Ø¥ÿ €]æ?ÄÏ`—ýCœv¹?Ä`÷‡¸ìò¢®ø‡ êïÿD]éAÔ•ÿD]å?$QWýCuµ?QWÿCu?Ä`×üC/ZâEûA¼èü!ˆÝÿ D]ÿA"Mÿ$ÒìA\›ÿ‡x êæ`‡?ÑœRÿAnˆ °½½©ó_æ€ÿAȉ³ÿûÿ'Ò ä´íMþÊŒÀòþC6JpÿƒîÕügìö·&$Äê/„ø¶þÓdjÖ^ŽÖ@Ð_5›¿2»¿2û¿2”¿ÌrBFð§/$dþµø:$ü?¶!îÿlCæãypÀE@ºqú !ÝüÕ+'ĺËùèþWo¼pÈ/ó? ƒ.ö¦.Ö•€ˆþ9^ˆ_Wkgà_†tèêþ+RÃí/„ÌÇý/„´èñ×éA²=ÿBHy¯¿Ò¾÷sJÞ@çKýß'JRìéà ¹¬\—ÁB~~ÿ#ÐÜÍÙrý×ëyèþ›-m Ï"è 4GYù6µMo ¯ð—)šù Ï-iÕš ÜØ7ß²œm_:®èÄ´Ñ ûT™…‹±¿GáñLâò±ËWmJö<È)!cñeÏÝd/Ë»D÷*KÉkבê>ä³³eáæ„Zenc¢"E¯x(÷bøø“*ƒ´æ>â%T¿{Sv(¿®l–½VDX7¥:V†SE$OĺVJÜú×Û¤6æï—à.7œ§"¤‚äcX‹)m“{ų4/ômý§„É{œú@ÃòÛnJ™zqÕÏfk9œöW1Ù ô×,®2kzWkòŠõUÞð|–‹RàG·ùØÑ]L©UŸPKðµu½°ËÚD_ùŽ|²è©µ¢Üks¤·ðéVÓ,*UšÅÝpVùæå“‰ÔÉ!>Qëâ'im¬ ‘mdìv}Ÿe’±”!ýpŒ‚Üò’ÿû+¾ »–ë*ù8>’Ç-ŠZ-úÛíI/tŽP+E1:F°,É-C]Qû¬œ–ECK•õô_%Ñ8u"D Þ_|§-ãu-Þ`Sa5TŽC•BÐüÀCLò]ŒÎ£?Å]¹Zw(ì&ïIê3s*Ö}5{©°Ü9³‹3Ïr)‹¤]{AêSvòhš?ñŽS>ê‹®åÅ·U£!#BbšùVÄó"Ú…9~‹ÃìÑz¬Ø WUÕOö²æa†V"‡[ãƒó é*u.|Äü”}·1æ[Ñ9x‡ðbËWžxÞñàý.ß^˳—Ë;ËÂ.Ð C2.6'žÍ9äÛÒ‹ãL”u‚´¾.ž;×ô³f¥¹Ñz;qÚ±áÅþüäÂÌG•W,;Á…Ñùs?8hê" ƒÍ¹Å —7,€œšÛ×mŸÑ‘S~ ?!˜R΢SÀ¨J ƒ‰K¼$Ê:-®ø1sœ!û=¾ûª^ÆÉ[›žÑî’ %DŒáŽáßcrJ7‘`ÈÒ@/]Þ-.;/=ù¨Ÿ®æîròjú¢ý¸‰£J0Ú°"ˆøkŽÏ‘ûM´l­w˜6/u¿Ýù ôýS¦ëŸ’c-o]CÏü.ŸÉN†™'ù1YÚvg#¿ØÀíôQÓ²(÷IywÕ…Ð& ×Ai,h˜ƒ-yôåiìÃçÚÁïÍÌ]ntKc!º”¼mjþåÙþ(ƒpÁ…Ø’dPäPg}Žhhœx oSµq¯¢¿g.»¤õ£=è„ u.¨ŠUÖ¼üÓK)Bå"°UÐX[xšÙФóÞÓ½9¨ä )á!íî½= I.Y0LÑnžÛÿ­VYĺøæeœKˆUUj½’å§M†åÞúg®O ¸ÜkI•f"û¨êæh²0RÌЛA"BÞÅÛ©Ì›©%~ÀšÐ&2FØä±·#e <µËû»¤ iwùþ|5Ql$ÀäP’ë§I•E0_®Ô‹•ð«ªTŸÐEe‡Å`T «W»}Œ\}ï£ù ïôýCøkÇkONm¡s`5G°Ë #›÷ÞÅ»\xæòOâŠPŸå@48½Í¤:üvÁ €Ê>ZxUTu« /Äï·JÇ6Ò/›u\?Wtµ *'Ž0ƒŸO­Lö–1Í'õ{EE::O»ˆ`“ú«|3ñLé]¦ZtyÊ·t4¨J3ÙIœŸiºNò*û_ö˜õ€ÖÞ?XS«$­T~by¢~;#ÅxJNç¥zU¨2•äØŠÉá‹ÉÊvÌíuŽ›Uƒ'W­Ý0¼Î:ÄnwzŠÿTvíé…©_âÛr±“àQ•^ÜZõÓûñÁANž=ìpQb¨áý§sŸ3«é1ÕïØ5<Ç( ¬aʲ”ááþ£^Ø.a¸ G.[|>ÙŒõ‚)÷ï”s `~§´No¤oE$ ™8H‰žxfÈ!ÃZ°9¢mÖ¹{ø°åžÃWoô\"lÝš–FoUhiÝ…¯¾ç…eÓvÔÒ+ßù¬ Тø¬ùn waÞM¼w°i3GøÄÒ]¥ÓöW›ø‹¿!=­³ÄUfVÕ̆÷a÷ºeÚ©2@/Å>äýTnä$éíMÈ<ï0@9c xŽQø…Ôœ?ëo ܶ:vªÃ„%ÿ@N5ͨýþu¿ÖA]˜ÿ%{ìÚÜD&ëm‘‘jàŸXÐîùÌÈGXÏQò<§ß ·OQ÷Ì1^éVz훡°AXíñ[ˆid‚2Aõ1îÍ9ЀT¸Öo½[Ï™Ò!­3ÝL"ÿû¦ó$ýAñ,©±ä(¦®q-ÈÙá’ÒÇÀ48½àæ{_eq«qY­Jòê/„Å`AìÂÒÝ5—†€ Oõkõ”(·B˜7|ŽI•uFXòsâOÁÔN5ÆÞ'su´BQü(-£F‡Œ1tìðdµ"€Iðw¿ŽÕC>àÉçæ¡Eñk|~W°íͽ]»ÄKc¥3Ê-©$)¢q}›ˆ.CYA쇉 ¢Q*ÏAצ’瘐lß8ÜŽ|ð§@»à[ôàîzäðç«ÑîkçYD_#Øý្tÐýcZˆÊ@ƒNå,G'ü޶ruE™SyñxaSô•[œ­ž²ÇHX§DÄ”ŽŽ 3Ù‘¹™Aÿv¿þ4ýÏQ•Õ±8æròæ¢å°&ó…iëãN^§®K'í^¯šºN¡}LbyŸ–7¾ˆ–)ÈlÊp`µÛ>M}/ÖSš+‹ƒ³xŒ©{­ÅB:°Šv9 Ó—újºú£;bÊxáÄEZ•3ò¶_Gªˆ¿©Ã¿¯ë·5[‚–+yßÜM·ás>˜•Ò–Ëq¨‰uß\Oâ¾! »m[,Wá›üG’¢\_JoõMPæ‹¢³y"ÕȯÅ\·ˆ‹ðÕ” qª‹IËß>ê܆Dâ^xo¾-LB[2XozWó-=öÅSšÐ^ÐÐ?“_¸˜¤ÒtÈPÙ¬ÙÍm<Û² Y†fÓ÷㱑Î3w|*ïÚá1ߥPÛ¿;ÖlϰÕ:–=ˆ½5:ï @›¯Òû6¥!–Ñ{ÀÝX…Qù|XÝ–˜U½Ç̬CJ@@ËYŒÙLŽØ îö€H\Ò®×b4±V§ç8‘¢öhħ”£º>Z K*wÎ:2ø®_ “Ð))2Õ¶ŸÁ%ÖåÓt1Ísò£[±¶õ¢9V«¼™ÞÚ©¥‘î/]ôuIS%*}Cô6Éûv~û»Î>ôz»¦œ Õ™…0×–ïÔ¯[ÎdJå'‚m‚¶¬b¹jFüre«_.V:Tî·Có»ÏŒà ­(ã‚;´Š€U_6mD_z{&á|iVO„…%XÇõS cpÊW>[x¬Ûå5myy øZ÷wQ{ÀÑÑÊnX.Ä’ˆ•á"»‡£—¸år¿¹ Ü…LY<Þ¡úÙ¢ó7f4GŒvÔnú…“uÅÉû”£Š\ô†£€Ë„°+ïãS¸¸tq'¦ yË—¯ŸÄ| [¹½4EDYÚ+Š·<°Æ ¦ö2ÈKý8`­ÕyVÕ½Cõ«-8fHí½Ãâ{vŠ©¯c\Ÿ¾Ã¹Öur6ŽÙÜÄ$¿a_pQ»4,¥ðÈOÂûf]Å¥á7Ãiþ[þúËP5ia™Ð ÚÛ”wØRïÅk§Çòð¥0v–´àû).U”.¼QÄ`Ã:·¦Âõ“-R&ÑêÞGßž™,?Jã7éÂÄWCs%m–›L±º Þ :‰Ÿ £÷æ-î³Çùº,nq½xøFEê%—*M–­ôYÝ%vàfQÏDô±4šfétøÁùA±[g¿i©‘òiïö‘sÍ4:)})çqÙ¨™U—ЬmÉÙF4qÛ•,¶©%ˆhßb°™"¢Ü>ߣë;ìÊ8›1o>ej¡ znýŒÖäü°´;_öF¢ßþ›ð n)åo#+ÖOx ßíÍò↡­L¢Ïd‡³¨8ƒ[%˜–©]®£m2‰lûW¿TD`½Ó¹‡‰[8Ã9XOnögà$\óFŒ÷?z¬' ê1ê>”ðq §¦îzk³,üÌ»ã®gŽR”A~y•Î^)„¬Ý—²…U´JW#êQZiUñ¼AùÚ¯]ÎI”’Þ(Äc~Í<¹®r`šÀ2ÏjõvßšOßȆÚUbP— ÝŠ sï=¡"ÇtTµ ö.^€f©¥#0hV Ù@äªp]'þ7Èuj*™ßhv×›!%~“ÁšsÝMîZUÞvšyVtÔÒ†•â5qDB»@‘䔺k½Î}MÃMe-­*ÅÜÍÍ»œyª«®«‚ŸgüBWã*,–$fÑòLR)ÔíÑ’—È‚ Å0¨V3ñƒy“Œ¥Šw±`J~Ebí$xa&/XáFe2!j`¾ÙÕ„ç J68ÏÚÐùpÖE— “ÆL}üù}êðÜ2·¥å¹†Õéóh©˜î©‡eóæ•W¬ñ¼ _챓úŒ·Ú/Ь×L(ÆÈô®ÎéJZS_*r ×¼¨+ìHg”šÆ1øï¾ e'W÷.ïVʪoåª B*ÙÍèöËT¼'P°ãå”aýb"æêo–a¼–^’0üê¾~ù¡I˜~Ê9µó )ú×”æa #ò21.³lE+Ñ÷]T|b°¯NƒfŒ§ÝOjpÇG)kÞþÙ¸ª²Rݑň©ÂaÝCÝ{ÔZÔžÙÊvÌ•PJG‡è¸ô0¼q’£½à¾M;÷RâëÍF´RsÍ9î›fýoê-+ :"ËÎÓý²jqÅK^ME~”ÝÑÇ)ÍÞø o •Öo#¿~uÇâÕѰǜ™40&Nç±=ÞÜß-Zç±þ}j¼¸Úg´A¸¾{ôƒqë´ózL/;f洞òë~?:GO ƒ »ªÂg$Ì %ªýdÕZ‡in¡ŠÑûù=›ê7òØ ‹êiX€æí@Éöùç³,‡/§'œL8°—ò3QõR‘è=½aˆ bÊ̬|¢.U_Ò0J “.¼#"vs¸ç«.(òK${® Ì'‰…*¶´à¬¥<‘hfÅÖ×Âñ‡˜gi$°lfÀ7©™f£3ݽQ ñÎíš·™®»º–A̬­eC0ÐÖçVãŸ.}ÖkÄ8ñÉÑ|Ø—–´2û(5Ï ÇGóS” 5¤÷½ý²·\¶Ã}½<,•2¨è' k¹øò’œÌ² 4éî=¯šÁÊIi }q{åž’–‰ÄÿŠ­…Ñ"äè&·ïâÿ++}DêÕ7.lêDÖ6 ÑJvae!tÀ»Ÿ'í>÷R`òÅ|ØÛ­MAÐMÞ<ב ]ÏÄ­’B˜HÆ!ãzSA$Œ¡pS+7Xc±„ _¹>tu¦¸(ñöÃmi· NrݵW†·О¹›B$L4?çœ(HÔ›¹›ÕOxvK›˜ ÅžTÅÙ`ÂC5ŸÕ”g=Œa¢úe#›ÝªICcÜ-H;—-£lc•&h‹åÿhÏjL·äáÅ7éY;Ñ$w‚!"äæÞ4%î³?'ðQàï{¾.Šanì@3¾‘¹*0ÆO¯\qßä'Ù´Ÿ¸@X·rñû‰«ì”œýa¨…tÙq9\k0aê‹ôŒßÖl™Ùð#ù$Œ*—~2ûŒ ÷ O†˜CK†/g< éGš«7²Å¾Ó 4†J± ošã 46ÂnD Ö…|}2¢’H¾oýV~(6 [-ìÁ³¿vÏ’þ›”¿ìñíÙõr‰(~Vôævò!WçØ¬ÐÞò§‰ ïlþÜ{›8ÅyÖðÃë d†Òòe›Š£U……cܦê‹Ã™ROlõŠóhÆw¾­ dƒðÎHo帿hJ—S ŸÔ”_ÍyðeP“©¸ß‹¨Š~O¬?>OGr;µr[è5íDóg'“éö³ó@èÚÈ–?šsó¡ÂÞ4<¶Ó;Eì$íì•Ç6èM–ñG⣺OäÙ½óôº\îâ U…¡y@Eùl!ùé“{cábóã$ÞÙ…A’ZõÀH´ÏÏU;’¥¬Ð ï¯6,Š_èÑ5ûnF15d"¥ÓFÊ$í±$ÉéèŽìæ\A4­¾ßÛ75À¯¾Q¿ŽÂùCÜìl`->¶øe07~áÞºQüé-Sßå ešÜUëÆÞVü¨áNpHúŽ&æÍ0NzvŸóS+ù¥­àäKb?B•PêÂÚ£‹ìE,GʉGpCàíBU$RæÔSbá¬ô2‚ž(¸ÉÔù¥Žžv”ØÇ å§Û¬ §ÊS ”¯‹‹;̹¹`lTÅΆýÜ ‰Ë8gíÙÂhÒ¤g¯¾(JÍퟆÅ]JiMX%¥¦u†¶~±,êð¸>š¢¨ÞLúÇeù™({o{ÚÁ,Ùò™ïFJôÌ‘ˆ[ÎÃŽbcaø/ûΧní•rUò–ñɹIXBУg3NN8$5Ú¯,=š:žl2uQR¬9´b=§¼öÌSb4¶›$mœÈ¨œ,‰Äa’xø’9”¼bªºÑÞÜØ©dâƒÌäš *ÑÍú‰ßŒÑä‰JŽ2ÑŸÎha±Ô³wIŒhÐ…±Jë¡—FKÁ‘Ž"çW畜V8¼E*ÿ•o×oC¼A0}õ˜›g»µ×ª ©ZŽJ_%…•oãýY _ñ5mê„T…2—},·ÒW ¡.Á.Ñ* h¥y½ðíÉÃÖÕ >‰Û©AŒ Ó£ů»:²®GvõøDªD³þ­”…©è,øøp݃raŒ§Ý~´Y6zåW(³Ÿ{PÍg|nQg›'wÊ$Æ»¥ÍBÝ@P %Eà%÷y¸3`¢õ`ºÞÎ]{@z¸=n8P"ßh;©ñq÷EPÇ\nrHà3_­nèñ”Ñ“¤þ~ñ@Å%´òWDZÇÎ×àF„”‰# ì~×Ófõך¢: ë#ƒA@é#."!}ΓÕíá1]šY(Ýh‰ß®®~ß6}·ñ/‰µy‡æÇ í¯P×Yp¦ê<ŸW¼›‹:…iù£‚ObO~N°÷o‹r9ßÚóŸWNšS‹S²§,ÛÎe`­ÒpM0ÃT\_ %Œ…e°àFP¡ì¾Ó÷Q¿kºóz¾06+Ï‘æqžª¯¶Ç·7PóèÏH=&M&“·Òåí–ß=Á9­W)Ö ×Мb™Fm;ºÛ›ÅÌ&óxìÂÖ¯ÿ9âr¶ÃDÕü+sÆÁŽ’+™°MbiÄæÛô:¶] ®WùÖèŒþìÞ Æ Ú‹múEvêò@RAÞè+yL€åËìTÎGÞŠ…RÕ’¯Â¢_¬ýÎeUȯù‰ľAÿÊ_ò±³®—Ú~1g0ÓDÓy^9~Pù1i…ŠbSÊ€_^ùDÝË>Ó­I‘õÎx¸oùHfb¾úÝž€µ„Tž¿ "w¥=eŒßΕº€KHuæ®ÝÊ œcÀ‚êí;äî_. D|r%i¢QE÷ŠGêu6:¨qK›¯LmŠÒc&dQê×x?3Äa8[’!4nrÓ=7I¹!b‚‘L=_[ ITÆ)­2ý^.éë$}í³F ¥E ±¸Ä>{Y%G–FûèÏ_@÷^†š$Dc¶E\ð‡hJ‘n˜¥éÞUU§jt{*á¬8nÓ¬¹ )ÙŒiJX@)«J­†çO¬œ™%·’ö šyÖ‚^æN~Ô0o€Å]\C Nu0§ý¥áõ;S1üNýÑkóeù%êM¹^4Ü-\U«aZa…òÖŠ!z§Iç{W%“°;ÔÎÜÚ0fD{q¦TØãоvõþæ0úp+ÍÆ(w#ª|Íf&™l¬ÜޱÆI¶HjrÝ%5yÃÁ˜šÏþ?' <Šò,¨rDp­ô9çÇz^d•ɺTá´…ú|äRš ð¯?žªÖÈ^În7³¿øW(àýå¾.Wµ”>øô„2ZýEi!ûÔkºzV„û©{—ËGô¼ûÑX‚Ø7ÄßÞ:§i·AÂ1ÖüÎv¤çüÙ¸þ¨NæË÷.]ŠØ·˜‚ ÷!Ùb§ü Jx”nƺڱÜdaÚÒNE®OE¦¤úÖt×" eçØõtjx%686¥HN1ñûåã©k"šõß+ê¯Gá¹¥â<ë«õØAÞy¨wWŠòme‘î x(ÞWØIo(ÖÚMëâs~âR7Î:Låb6猈!ú9Â?‰oQËØJJKÈj·ŒxNPL£ÛÒ_ÛF4‚ûùÔ378‹¡ŸWñyÝ=Ë«ãpý9zQÒéâÕ¹"ï’»„3· Jcò†½- ÚÞ^íàEÍøu¤^]3–˜¬`’ô‚8ùD¼«D¶éL7 ­ÉÖ@ßnkOõo6@_«´u—¯…îy¶ºøôÊÂÛJö§šóãÊPÒ$œ‡\…×Ç~2âÓeÖ€FÑ468ÑüÀ²N>š‚P-ÁÄ<›_8CU"øKÞùÝGC¥*ô.ã?)„“pÉ9àé%е©7B7¤„e†¸7?Ä)b…}³CÜJ±ô=šÙöŒtÍ+£´ÛÙ^šE¼7ÊÆTÅ2~f+ßèÝn'‡|¹vÖ¶ò#êòØòØ3a“½:ÍÛëx[Mn]Gfì?Ó¤µó•„á$# ñÂÕ¬e5˜ ÕŸÞ;Çd`ªÎclú|ý#Ÿ¼(œÚåB9Õ|÷>{Ž@Ñæ¥×ÐÑp»œ;Nç> NM L ŠöÆÿÒœã¾o™¶ÖP¶”µTcF$Ãp[gZ3zqD ØÀD{Q7br’Ú°~cxSÛ2èŒÏÈ!×g¬ðy{‰» kã¹>ÂHâW"Qƒø9J‡¢Ê\K¦qý:–§µ<ú)Y$zÖ‚Ä{=j5Û—Æú׌¬Â›T~nØk%ØaŽfÀæÂËÀ7‹„GrXÌd#€ÚuÕ¾·à©úYï¥<.¦ñÌÃMêÄX¡ÞwZ#N¶X3xE8ñ›ŽÔ†ªvõÑjzå¿èC«Ðæy_69«ŒûŠÛUü^A_¿Ùúá×¾UÝn~“£¿³íV“º4~T0&¥PÂÜ!ó’§Ps»“Ô-r} õaÎã7‰KÔ%ÿÆ€8ŒW†®ÃÉö2L|hSD+Þ¶ìMÆgËcLÌ'”Ö/+zîè)9Ž£jË ½]õl›($Q±…¿Ÿ¢g¨dø(Mi’Ñ †Ôa.~eŠÓ)– x6 ?PÖC»¯,Fy±`Ü%C¼7VáÀÊKÎæÏqMÌéô®%uÆ\].AÓ˃ѰžµQÙÔ¼ „ 5˜D7ñz݃˜RNÃÎV"TÜ4'¦âÒëŒßà›Ž1ß뙇t¼³Îk­Um.åxŸrL;ÙŒeù Ýß‘¨aÕ@yX¼5höv]9’P³L•ίE´(Ìjjj¹Â"ßÄ cT–“[iÔå½ É ´jë½]Ë÷2ˆg +q¤€½d¸·dÄàzVÄL³ìpÆ8Þph]-Ç)Ò¬TƚεÏÕ«´D ¦RptP)–5cÏXW«»OS}Œïc J(àÕÁe¶(Åi{‰ðØ*Ä5Ça÷¤ÍF‡˜û—à¢Q†ˬ®I…?p}êÃÅ9Ò 0<U¹ž {|tE­B<4À¸˜­£„ÁÆÄç?zvz%Õž)y)ùSá-{ß%ÚäDbSÜñ—#jƆƒ.Äê ™p=¨sÖ‡².•#WÔ%¢ª„½¸ .1¡ém1øø»q¡'²ý؆ éHŽˆÅn“õÔP}HöØ2[­™ê…ò¥áï­bµ‚-kÌuíOc|I?Ð’½Â¾>¹xJ\wàW±–kŽn¨í`TR#ë«lûÍ¡/Ãyª$g£“a¨™Œ¦NáÅYTä5Š­ëôàY<­ÒÆw@×ó Âdóaì”®ø÷D©Kû ñ 9ü,™Š• ±æÃ}bá‡wlÇZºûÒ‹÷,øS†P9öúkaóÄ&ïgÃPÖAqšX€Àq(’€•CUXºëmý­/#JšóŒW¸eøG/|hn=æ¸øí´6Æ'rn¯”ÌoåýóW"öØî\g´DÈ.úÞ­U©FSž·A8¢,¸èÊDo‡ìzúGñzÆ]»H=zÒdñÒÙ¿­°²ë›“¡"Yz–‰–þ¨"ÑUëw°'!ržöjɉ›È E-Kl†tÐXSR¶EF®ºØNü’êïÈOoF–¿Ú¶ØÈ\^ÓÓÎ1¡ú‘Ëï„Æ¬÷ŽãDuÑØN,ØÆ«mÕ}^¿ÆP]îÃH!AWŒ’2Uüí2Ö:×êE9L³=C‚U¼¥Ù“ µÂm`²÷ö3:MJÛVù>ò6ÿ:H©GcVðöÛûØÅ,é†Ö|oœ ½­÷åW]·[v|&Fí¸\ßèÐो•`¬wŠxmWAӃȂ™LqNÏç_ì‰=ݰNdìÕµ2Ÿð׫«ôb½ûºÄ³…øó˜ëšÒMˆ=êNËË©õ˜þ’ÔK¿±ãütre÷5ˆMÈE%Èõµ©”U{.!ª¸xx`ücmíÿs<,óË :q(íBôý’¦ÍŒæÂóÃS¼oàì²Å/`ìç¯bƒUÅß—t5bDæòlf/iC4ðÛH6ä¬|Ié~£LÓ“³ær%ÌzŒd ¯Úþê"Ö¤#ä8IæF{-…_„uÝ$Ä+V£çQRB‰·õMÙŸï'*?ÄÊÇ.U{õ]Jó;ýˆýŠø›IL–›<™$£}”À±¦8im˜­Á‡ÙúGà;þv$ÛôÔOƒÖu¸*ZKvÕ¶tÏÒOŸtB‰‡u ûkÛdz»IÌk'™$9ßo Žçj)úÕ‚Õã¬óa8§áöhˆNzG-ÖŽ‚Øb½§Œ(‚ÍfÍÓã¿§"Ôˉ“é¬<ήº†8²•÷ÿ×è‰v[¯Rfèr\yËË"í»ÛrUºÒܤ4QŒž×òýŠéø|*ž©‰«JÁf—EiV@kµ£mI‰àZ;OGo`RöoÀemsÜP%½ïž{„ê>¨)d.%ÈUqCKžÀ¤õhhŽ:‹XG¬©jˆzŒl(¼€÷,v›c͹ïÓÚ:Þ0IJD:Ÿ® ' °7FüŽöÒä$ëD÷Þãˆ]9š9„8PºyVùÚüýB¤ö6VçJصˆ-uÓpÏI•çhWðAœ¬Ê~ê†(ždu£ €ÿUŽÐìÜŒ„ojÛ%Sy‘CIWqšÐàñ¶½˜Â\óH›3­¨Ï—-}'ˆC~S€-*§ók†€‘Pš$ÇxîÔH89JâWÚþÏ·¨{ç,:×Õâ·úMý܉Sd_B-o.¹W0F³i&Èj ˜.&¤ç1̺;ƒ¨zCî}lÒ{·iÕž.žV,\-çýTBƒÛbÕ¸ÈvÉð×ç}3Sv8‘ÁÌž¬Ûtaµ5b1Fä¤\¨œûbý“ÍñI‹Ò –Ü< ¼xšýë<•¦`ëY<æA=ý§iFc1v$iá?|Ř«e´Êù}Ç´—äÌ›®NÚdÞ'rÔà/ê¿ ß ý<¹^ï Jèx—×LèAŽU|–&5"a¼°QmÒçèw1ÜÑ5TçØµÁK”4ÐÂBxiELLßzèöÆ ê-[HŒÓ ì;’l Bì«âú+²TOf2†»äß©öÁVW ¬{a½µãgpïŠ@ú†¾ vb—=3v`æá2:©ÈÂÜôº8Љ+Ñ’/S©ML$hnÝI»ÑYIpqý¬ôÙÒÞ•¤Ìˆ3áÚŸ0¦7±®i¼³¹>8ÓÍJŠÁ©lˆé4ºÚù² zF8‰½ëÒü¤ˆÀ‚ƒ¼¥ßüžê©€ú§þ¶]ŪNé´©ª÷ON~ò<òÁ:®)h}|û1»P] 5ÒX†4]šC“‹EË]j.òW\‹*BýƒdA³ˆÁ#ËÙOwq2›Ò¥„Ãà¥zžQ\ßS ÔÃW“’wxãóI̺ y;+“Ô¥j”V3ÛYßKhI©ý²2¦úÿƒáKÏ endstream endobj 3390 0 obj << /Type /FontDescriptor /FontName /KWRTHL+CMBX12 /Flags 4 /FontBBox [-53 -251 1139 750] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle 0 /StemV 109 /XHeight 444 /CharSet (/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Z/a/b/c/comma/d/dollar/e/eight/exclam/f/fi/five/four/g/h/hyphen/i/k/l/m/n/nine/o/one/p/period/q/r/s/seven/six/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 3389 0 R >> endobj 3391 0 obj << /Length1 945 /Length2 3150 /Length3 0 /Length 3769 /Filter /FlateDecode >> stream xÚ­’y<”}÷Çme‰,Ù—æB3“±‹¬¥aŒ Ø1c­GdI)D£, !ë YB¡´X†ˆ(ÙÇVQ!=S÷sßw¿ûþ÷÷ºþ¹Þçû9çûùžsTí¡¦Þx/Ð #CšÀÜÖì´£  4á**æDEÆàq(2h ôõ€)Å8À>×1ÐÒ1@"Ts|P(ãëGö™«ýé¦ ƒFá[Ù d×@£°€#É¡š€) 8üÌ  $ƒÞšàA“/Ѓ€ýôdóÁº„½)AƒDÛ°mR `[ôÆã°¡€7è#³Ã³ïÙNþ?Lý³¸‹µCþ,ÿ¿>ýK Ä`Cÿ§ÁQÈ °Å{ƒDÜ?¥§À?ì™á±ÿºÈšŒÂbЦ8_,@õ5‘:„1$+ ô¶ÇÑ~€ KÅAœ÷?m°›÷ËÌåÈaK;{¿æúëØ…Á‘Bƒ@þ·þ#þfv—ˆ*à ׄÃl!ûûóïì?®³Ä¡ñÞ{1´u‘ˆ `o›´p€ÁyƒT¤²=Ã4qx2;`7&ðÁ~Ž•=êgèÒ`^`Þ¿!€ãæƒù ‘ÚÌ/4ÈÄý–À.‡ý õXàßÈîì71{aøßP €~C$#þ†:Œü²_Aù…ÿž…™žÕÕ ´Ù9 «èjÃ#ÿM!Aùײ³'ú'û`Ø;‚T-04€GÆøg0.GYÞyU²M$O»ÓÝ[M3Ôœk(ÖO¬}éîþ(+ê¹'’¾p¬ æí£=.Ã0èw„žíW»éÈ»„žwsçêÌyÒ*˜•0=ùT«±4¬¼:Ü´n3‹ÐÍ“YHä)øþ)*àÜóñ¡7¼•'ÓÎæ4Ø\gÆ®>[gÆßÁtJ¹e®îÚ’ií ¢é_ʱå°õÄHçsÙäWš5 ÛÃQM®¾’~u»LìÈêãCÅæó§¿\ñ¯}`Ãà=_²üX¡½Ø`¬e´Ê§a!×0+•æ½Ë_Y­ó=† /Uäåã?ÆyúŇ®ò°Ä÷Ü‘]yžïŸr<é#T¼?¿GÆ»D'ψțÓQ¤#–y´e¥­”œÏý¡1—¢ô<Š?¼-[vê°¹K6ù4à‰|J‹ÝlI–§ó[B{$´–D¿\zgÉÓrsÝÙ^³kÿ‰—7Aì¤¯Ó è‡¥ŠŸv8«IqŽTç’j÷ŸÇ¬Ï!Ä;»=Fn]f¨Ž$gö·SϨ.*Öº(81 ÛöR¯Ù~>,«*¾X«jÍPÞzº­@¤Ï ß§yîf€Ϫä0JÕÒòMÚZY5éŠTç‹Í5x5b<{V5f‹{Ò>ðY•!Qw¼Ò•gwmšï#£úÀüMá¢<ýŒ Òöæ%&8ÂnE‚Æ`=ØÀz%Üo®gàæêjYç Sôõë¿òaeÏ>Pú?uíÎÆ!>f¥wa—Jf!oÝgfu>Óð à3½‘î§g˜Ð’ÏNÑ9š®\É-¹ŒjÛ ••ö‹È{aÄ ÉM7–ù,Æ_WÍSçGrkÝIØÛÜ¡UQž õb>XÙqÝ`M}—~³FÛ¶ØPè` iXÖ£žêëÍiï»,µ¹ò°IãE1Ls¢³—ï¥] Š€Öt)™âúb¹¼ÜÜ#Š#ßõŒ‹ÚÚ‹op}m§W«eäÂú?ޝ„ÚH7h7•õ•ìS¨™7åÚÜ9‘–qœBТV`gIéY±pº)3±¥%)ØÇ)EšC¨‡`„åFâ¬cѲm†ï¥Þ:A¤cnι«FÞ¤†v9nE[-Ú¤ZšCÒ“ žèõÍ®—ŠJºrK6…UF4Lw}Ë5†ÖITÓ• ”CІuè&…ŽV ¦àc¢SñÆx[Ãr,Ü㊕֤h‹ÌЬpã£ÁË3k+âäomién5yŸ/Q.¬òÛ&|¶»ÂV÷òóÝ®•i€èÊo +H(>”põ—¿òN5Jk,~ɽ]ôBÍË÷%q31·ÏhÉP—·Fp2žiÓè~¹Y®QÖÙ¾GÝóâ;`ЕKHˆäaÅŠ1Á‹Ÿèšq9:–³¡M¥+ÑúDÃÂz4Öæßµ(f¶çHuÎÅmË[u¹wB)ÊÿcÅðÜÓ™Œ²0ÕqëȤOTž‰ÝÛuk’<Ö$¶¾ãá¡=¾–ÖCª¾ë˜°a}Ð÷¡æi‹³„ûL™‚CΤr#Ê÷Žœ²QýÓ*.B³„åÖiu´xˆªpžÆÅñÌoc‹_Fs¿Áº7Õk™¼Ö® *)æ‹Vã–Ç*èö )mSúI¡‹šËÖ®¥Ì©"\çnÕzt‚¼]yiû5ÂfݘŒzÅÝÕ3Xw[Ýî«ññ5þZ¥—iΦ¬«$èYÃcb,†÷ÅåøJûs‘GE£y±ÜŒúòAX”ÓŠþñ˜‹k³Â.ß·¯·dqƒƒi»ù *[É"J9@ 7½Å‹68È Ú4K ((ªBµ¦ê=¼wfm¾–~IqËýð06­tD”¹3'Pý|ôM”Pµë¾­’ߍ÷J¤bðöÏ–ßeÔžôys‹f†z¯&íÏ{BÌ!†o5Çâ’óR`È~=o“_Ú Äû(IÞˆ»1WdêÍs¿LÌòôÍ:\ÆÒÆ3J^*¾àµS!5[B SRlÞV6+Î*%ef7ô“Ðu_N¦‡h£{}5’ºÝ"nµÉ#“*Þ­þ¨ëJ¨üû$ªåð*mœØä¢6é9Ñ4óH-õ™GNFJ·ßÑ$>Ü$oÇþ Ü^ÎK|ÖoV¹Y <‹^?†êj'VƇ›K™êhîܵ‘F0Éß(Ö甯áfÒ*={‹L弈+ð;ØÄ%|®™¥~9aTšSéklJ«ìídÚxÚ÷ûƒ ”Ï›ç5Pöçícb­ÃXw·AÏr_¢5Ô»˜JïŠff~êÖ ¬-_¶»kñ¢(f~”Ûðpòß»ðêɲ’ÖõS-Ö’7?þ`29÷ž·¼Ý˜ä[~ue›¿)3»?±¥i¨T~„ã€Ô%5Q ý¼WåÜâ Š'àü>½9]8 ûÚw´à”•£Ü'ÓgPÉÁ˜¬6Éٸ˷$ÎøVârÃéd¤f> ¦y¿ãæÉ4½3ðÏåÑ}âzr&=ms©kä±GCÝøY‹J7MIª hÙ`ã¬Ó±h1E"Ëpaov‡nˆ¯¨Ônçæ©jæ‹<›*¾ÁÇüW"ÊŸ”œ DËr%ØQxײ—­Ä»ÚVäAo¶ÆÉl ï±ÅTø§Z¼Ò_VÙTQ?î™—5úæ{éÀxßæ±ÍôjkƒgŸòB´'H÷±'‡Ôorîa¸}Æ;Vi«^Ë- ,»Ÿ)E>ƒ|÷ò™ÿÇìí4ƒ–ÞέڗyÛÄßæ–Ì6wn\™Õ›/çR/ЛԨ"ÑUF%,{ÊúÌmOi)\ç¾ *.QÝK] 8"FU¶]8ú,0AfL6­ØÒt3~=¹®üùTǦq½u‰w3ŸW©ÃÉ'ëZæ?†t¾úÕÍ9¯‚s«KÊÓT¹ôxiÁ¦(€ P,$«wT=œFAäÓèË_ÛºÅåK¬\•(LÞ5ÝËóÍ}ØšÂTö +½ÓxÁiG .ÝVc¡m¿Wtl%Jöà3Z|òQTþ‡Ebîã‘v§‘Ü’_‹&…¯u ¿Ü›rÕäÍ;ާQáHh­ã(R£†išrœÙ‰]­ècTžÍv-"uÚãH!+™Z'µŸtwÏÆXÜ~}©?r/ì ê4¹Šˆ+‹Þ_ 2ˆäØ—5µòY¥º=–JŽò©ð„´ìÇÄÍ*aî1óé',)µcS(" Mo‡vÛ?¿$¹Ã³C≛¹nÛ«ô>—±P…ð‘ј·w-ŠN㔉_#Þ%‡Tv·«MgpZ.žj» Ð+£ÏfçÔ³rçT­¤xäžpÒCIp2—0÷ABNú9HŒë­ ZxíÊOv.{o¿{é<ÖͺG2ê.˜ˆ_¡Ñ Êsº³F+¡í½šûW=ÏO¦N—‹.A¡×5ÈᔩÖxLhFÁ+‘çÝÂýÅÉ5ÒAñëõJ©µ|Äô.©}ô–lÂvtá{“úÙõŠØ;)ÕùéZ;ÎļyŠ6üþc ×{pc®Áx£,‰ÃQ×Q,]#²¾¬{Ç !õ9…½Írí#$ÈœVz^Ÿ.ùýí¤öã %":ÌUR—%uF ¶NHê©&=^rïÖi/”;D÷¬I-G©1ï«+èf† Î4õ2[ª_½> endobj 3393 0 obj << /Length1 753 /Length2 987 /Length3 0 /Length 1506 /Filter /FlateDecode >> stream xÚ­’}\LYÇ×–bZÙ #Âa*’ym¦—ÉJŤ”MEZ±{»÷Lskº7·ij$í'Mò¶’Ù4HŒ¼Ÿ¼Uˆ"oE/²¶š¼J†6Úl{ ë³ùw?çŸó<çwžç{~ϱ›ÌöÄÈ(! ›Ïá‹w€×¢_>ð9<†7N³¾›xÆG¾+່…Îb'Z¼ÉX…GÊ`Š·CŸÈxÆ@ G Œ¡k ˆ“(*ð”ËAPß8ã ¥„‡Áç G FâƒÛÇäKHIàò!ÅÇ~:RB*ކShH@#b$!W JÜy$Ý Ò$ÿÔÀâ’x¹|ÓWþ£O_(\®ú¨!cbã$)b 4~Àó"å_4òU rõ$"å°ùBOø!ÇIðDˆâ T¤ˆ<öç! ä Ýë§àú‡ùy9þ;Øþã@'!ªXxŸõý1ÿsLÛDá‰`1Ããñi!½>í– h7›@I '"@ä ŠBT ú Ñ‘$ñN`0ÀDš™Ë!H}ÐÎ$)I1úæ*tÜXz8$Ö—g|ù//21‰-plˆ.,p‘0ù?B4ž¢ ¡èÿ,´!Ÿb)N{a"DúFuO‹ÚR’~`åìÝ× ;ÄÙh÷¥Õ”«kÝ9wÜ-oP¥õ!p|—…Ú" /ü6Û0÷“ŠîY—x®¸œÌU7[\6Âa×Ö`ÓhGøÒ¯«ò.UÉ]óD?¡5¶ÔñE «û®²|p‘;ßEgmXk| ©ñíË•Ñ)µ÷ôf9ëQ6cI^™ÿ¯paÛÝÌ«½Ï|Èݤ~O3|k·Õ;½uåíëÑ·†iÝÖå|5wUŒ°m=x^<¹ÎÂlÎÐÝ}°|CWŽçiG˜MT>6°Rðf¿ÏɆ4ʴܱÑ&Ê“ûÞðÞªè™à`‚èt]ìÎÆFïå\ÕZL=æ^íú,løŸYöa–KKVÚ›uNQ·nÛ;hãÔYìl¢ëyïÂ' D¬9áê;¶0ïïb꺃ÝÃæTUÞdÓóñùšÎ¿æÏX%xòhV¬žšpF~óxjz×Û/5eè¸FŸ¨ÀM‘ùÛ÷Øí›¶Ç<õܵõŽ.ìbÿ0ßËÁ%0´éÈôZ;½#AÚü†ÕW-ó–@i7-»U?bÓ®ê!Ä7èæÀHÙëø¤æq#l$ÛºMŸWj#vš:Ê—¬Wg¼lÌH¯µ7¹í~ý]Í Ô6DÓ>ã©eÁ óCf]~‚dOÎ_+ñÖ<ºcÒ!ñWêÞ2]ÖºÎEYe¯ƒ—àÈe))ÍôŸ: YúèÅoçûÙÌS•}÷»c3™YëQØs8¯§+ U5³ ë¶H½£ŸÕºé{5b¶·Y¹·~B 3¦(èÍ2¤Å¥Ú~_ò\žœtÖ)«2û¬ƒîÖÅS…3vzlè0Ê­ßWŠ Ó¢¦Õ÷¶?í¬hie¶•ËØ¬”w-]¶‡VK­G…?äû¶…2“5‡ÐìС‚ûpùîåBk¼v¢yè£]z›ž!na^AÉ–JÑPÛ¦±•6dvVÆ‘ª+BcÃã‰Zuo ˆ°’õøø<ýmMf~uW‰ƒÕ‰·'Cgæu37¬Ør~iQ~BbQÊ¥6È4õºeu®!äTír¿Àsku†LòÂ-S÷ñò]Õ?ü^Šÿòê@tÂÍû[-]§Öï_–ü€wIí²¢>Ñθ0U:Ç/)(9ÊÚÛPCÝXcöäž$³¢WÛ[\£Õv®ç–û>ôPµ®êmbYÝÝš”œ…!9ëY5í=cJËÐ3G˜y$2ÑŸ‹þ9Ç®úL]*Ï£â|ñSc×ÿ) œôeÆ›ì*ÞvÖvv¶ù‚ÔUì=;Ê*h&YLɰ&ƒ½Ä⤱óˆIãëÿCnÞ endstream endobj 3394 0 obj << /Type /FontDescriptor /FontName /PLSYJB+CMBXTI10 /Flags 4 /FontBBox [-29 -250 1274 754] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle -14 /StemV 107 /XHeight 444 /CharSet (/period) /FontFile 3393 0 R >> endobj 3395 0 obj << /Length1 748 /Length2 1141 /Length3 0 /Length 1667 /Filter /FlateDecode >> stream xÚ­’kTSWÇQ¡Å`«*DPÅ(‘’$! OyED ¯BȽÛ$÷¦—VÒ ØVÐÊYŽBSòˆ”áQu ЂXª„Z­ˆ Ģȣ-X¤ ˆÚ€uu ý:ë|9{ïÿÙûwþçP£…î–‡b(á΢³¼A@ÎbóžÉ$Q©A8,! –°7`ñù\¡V¶`ò¼9Þ‰ ‚0•GÒ3àD[ñ@€Æ© ‘+Í=¤bR&´t P€Ø…™ ΄ñ,¢“X,!R¤ÁéJb,0…£2 ð^¦!µêU) Æ3ÍPÀu“̆*´‚e$Æ.Ì< 6³ü?°–6U+»$Ê…ö‹Ný­.Q" íŸ L©R0ãèRé^ø%œ†µri5œ(iš®€;Ë“Îô|™G2C E#„4È$ŠLx1£ÐR³‹ŒÝ{¢ÃÄn>íb1Z‚ „H«‚ó/õbÌú+6›„#Ȥ3™,³Ð¼^í’— A¥„ é€Íá ŽK´$ó'2G c…` €5fbÅó`vfa8iá]y^€±k!Eúû1Î݃ ÜÙsO¦§àq˜ûþG(Uã8Œ‹ÿÄìÄ«X†˜Íƒa ,%™z0©Ï÷JókrB ]µV´L'}õkó¾ÒûÐGïû¬½7ÝÁµÍ³}©[Sü8òK$ã< 4duBF^Ÿ­ñ ;ZÅçÂ×Ç¥£Iï.ï,ëh_­,ýä¡iÓ°ªÉmü®ËÔ@ÖE«3Q?±x•”LJ-kz{žý–#ϽþÀdóä2RLJ.û:ê8÷h èû¹±˜3UuÚ'}>E~n¢´ßë–÷¿¡ç” VÜÑûίdÒ4²Áë$Ö ù&“ø$?BèmíĽW®ë}õb¿óÍ‘‚_¬‡nÒøCÎúUÝáí+Û¾gÚ±¶b­´ÆQá»³Š² >۞ЦôC¿98|6棵ò³]lßc,UÓqjlêì3ꯛ?µœL~úôþï/ (mãR³…Ãéå{ݼNøg¹ºÒ®1)V·ã%ÿ|Hø‡Ý·ÙQСüÁ0ûüŒˆùwöÛõü닉MúÉ{VYRþŽ ÁíßÍÆ£I! ~üetû`哟/·œ`¿”x?µEÔëÖYî’!˜\Ð2ÙØjØÜlõ Ú;û‘|ÞZ4,…¦oº5Ec­Ùk9s³ê¼¹¥Ýó>#7Š÷›Ws7äX|ì(/¤‰¶é¼~Yq1²>UÛåUß`ünÝÖH”íS"¯«‰¬ÉWj'ø+×òÏ>a­(Ïn h¾"+ËÀ×ÈÜ©m´jÊÕú bMQôÓÊT:ïßÒÖŽâèðéY]»ew Ç')ýy·_uì©*Ý‘Üñ‰^Ï Ÿ¤¼mû†øUÈÅ9/L÷íTÛØ†4_K4¡kõ÷¾{€ð‡>n=e«vñ¹Å¯ræÒfvĸ³me"SïvxÙà:_©¬·£BvÃ’tW“ƒQ@þ6|Ò5žWä‡Ô/ž5Šã9Ã};¾â:Q3•Þ¨pKx£b›Åò{–3¿; Oá–Þ ã+/„üû+¢¦+æ|nΩ÷“¯>>|ýǯ=2Á‹DáñT{YV]“cë›#ò¨ËG/Á[£ß΋½<¥¦ÛF؈¶_¹#Tñ–MÏ4¢ëºzOŽï°#W?Wí&_=ìSGW8J¦µD;ôlîMØvûœ!C:!8•»š÷iÏÀé;®·÷kšŒÁýöQCO‚Þ÷ªÄÙ­–'Òá¼CåA ·^S6P¬“Ö©Í59êQ[šÜ°åí¾¡Ì¼ 7¸êœù¦ 1«WÖü×QÜýHo]Ò5¸ê­²õQ#ưÉÒ‡ SU}wNùÐb×L„ #8e¿f´!çbâ-ñMõu1vŽóó/!eøÇ­WÊ_#ɰp‹ÞUSVÍ<…¸KËOðo'˜'݃¼ß²òt©¡IEOãßÔäÅ&_šýGÛò 餮P–v!Ÿ{Ú(?qDr¯ƒ; Ë~(êIÅž»ú»=~΢ç3ãuÁ¾ñ£ÄM–ÍQñεÂ#é…RegYõ;‘ýÆŽ±8Fpéú+wn°{ÒÕØÎ endstream endobj 3396 0 obj << /Type /FontDescriptor /FontName /OUPHXB+CMMI10 /Flags 4 /FontBBox [-32 -250 1048 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 72 /XHeight 431 /CharSet (/N) /FontFile 3395 0 R >> endobj 3397 0 obj << /Length1 2216 /Length2 16577 /Length3 0 /Length 17758 /Filter /FlateDecode >> stream xÚ¬—eT\ݲ®q‚»h4¸»»»{°ÆÝÝ î,¸»CpwÜÝ‚^²÷9_²÷ù{G3zôS³ä5k®5 #RP¦4¶5ŠÙÚ8Ñ2Ò1r„e•Œt B°ddÂ@'s[' €‘““ 4|ÿñþÇÅÊÂÅÊK¶µsw075sPSþvbZÌ l²Nf@ë÷FVe[#s “;@ÐÊ  ô; t:¸é`ÆæFNC ©¹ ,ýoI’6&¶ö›íþwÉèàø. @ñ/™”€w‘ƶ6Vîc  ,½œí{5à»–ÿ²þ;¹˜³••œõïô¿õ– ¬Í­ÜÿÇÁÖÚÎÙ èµ5:Øü·«:ðßÚdÆæÎÖÿ½*éd`en$hcj0üÛdî(fî4V0w22˜X9ÿeÚÿ·ˆ÷ÎýK½ˆ¬´Œ˜õ¿Ïô_k æ6N*îvÿdýíü/füÃïÝq0wh3¼·—ñÝñýó¿¿tÿ«–¨‘­±¹)€‰• `àà`àû>=ïÄ ðd˜ÛÝ@·wÁôt6¶Nï!€÷žxLl`(+€^ð·éßÄ úCìzá?Äñ¾?Ä  ý‡Øôbˆ@/þ‡˜ôˆ@/ù‡XôRè]‹ôz×"ó‡ÞµÈþ¡w-rè]‹ü?Äñ®Eá½kQüCïZ”þлå?ô®Eå½kQýCïZÔþлõ?ô®Eã½kÑü‡8ßµhý¡÷8ƒˆå]‹ãûxš;ZþqyOfø‡ÞÅ:Y¬€&NìÌÿØÿ}¿þYx¯nô±¾'3²µz¿§ÿÔdùm±¶þ£‚‘á]¢ñdz×hlt:š;þce~ß¾±­••Ã_qïÚ€J½{ÿC #Ó{- µ±£Ù_¶wáï×åoÛï<öÎïOªývr3²2°þ«Ú{³Lþà{ŒÉ_ÈòÍÿ*óΕù7ºüËøÛð§ëow[ç¿÷öî`ú¾çÿ#˜å}2ÌÜíÌ€6y¼ÛþªÏðÞ ‹¿ð½§–áû±Xý…ïgö×Nߟô2³¾‡Ú˜ÛüÑÎü^ÉÆÙÚð÷Øô/¿[bûGã{NÛ¿¢·ÄîÏò{ ; ÍL ãÿXÿs¦˜ß%ØŒ€6¹²ýËfnû×äüîªýŸcýMÎ@Çßï®?ãÉôÛhë46´úÒÌ,þk¢Ùþgå?ý9ÿÇúŸÎŒ¿'á¯sd|oÖŸ)f}rZ›ÿç•`ýítùë4Yß“8¾?}ÿÙì{­þcŽßUý)ËúÞ8'3à_×á½ÁN®¶¼çpþ ßGÀå/|Wæú×ø¾G»ý…ïéÝÿÂ÷&zü÷žÉèðïRÿ÷-$$dëæIËô®ðý‹á÷mç|o)§÷x9;¼ŸºÓ¿^òï·óÙÄüýÕº`çm¸ƒ,R¿”øˆæM•BR ™6ÅÊÕuÍ´Ã.ÄZŽHÛS­Õj<–¥¡!îAîº>ã9†·y)Ž‹ûÛǦνî¹èï¥y´ài\¥ÉºïÚß#}oœ½9a•Ÿ^-IÔÌïϼ8ÎQ QÙ‡^!éÖv©ïNbc×K³R ®%g&RBNµ/ e YuENŒ‡X ô±ùÐL½|iÛæŒú˜÷!;áUç#ŨYi‹ ]iŸÿ¤8?©æ­o¨J `ªì؃\ú 4"˜…ö¥*ÓWôó ¬ ÑPY—sš–6 ¢26ݵÂÏÌÔŸÍò¥ .âólË£>ýúàñzH~àÌm“Nð%Ýð;÷BJpʉRÓ¡Ô‚$Bh± ÁÒêOKŸB÷`D¼ÉPÅô%¶ãO|ótHÓô.t„5ßF~´¢|ö‘7„CêàQ8ÌÂÊj ‘îSÂr 'ˆ¸ÜŠv§«ÚÐÑR˜‰TB‘}ž–Uóê$C]E±…0ZP*ªPnÌõñßñOt š`5Á“ÄàÏÉ‚¥úïi úÅžw¯ªQN ÊÅeï{=Uiy_õˆ§÷k±ü)çØ“µŠvm[_–fŠ1tYf¢ªÕìÅÒsõt3Æ®ª 8þ ¶hn!§U¨¶ª#±n<áA‡1Rzn"韠Qö9E2i‰§ O@õ› gdñªŸ€Ô“<ÐæJ3¤Töä]ÿK(tIÅumg¦\†—¼g-ކýª²n¨lܯÏØ™öÍË7I ­G—-^ƒcÉ’Ñc ¸XÈv@ïC’BÍåutOtX (GŠýí_½ÞØ¡µA±Â ¢ðmgG ;‘ãF¡×ÏÜç ‹}  Ú@$zekp5òš7XóŸLƒ9ÖF: ]–§ÂŸí(w[5ZÂH{™,¦¯åÅÄ9ëCÉ*L¾ÞÿÀ:’‘:è´.ùºöÂdÈš¬cdìNqe~2äAYaåÖ¸kP ÒA=8ÂT¯,à|'‰w¨ùãŽUŒÏÞ4KÉW^ÔÖUšêáõza€›>âë+’c«HÝ$F!š8AÞ`θ/_=¡ÔÄ.À9ÝBFÄdkñ~ð‹eÔî:ËôôsÀðñìB,ݬ Voeù¨×c&”k©uÓœblL²¹k{dôKûÍ”†ˆœ·wœ[ÔÑW¯HÑX:Siϼq¸•çB¸4Ÿeùô\ÁfÔtvžr[óö²iâô*MKµ5#q»°2ä,íá@#z¼å‹È:ò°ãÓ78tiüôiZGw%Ã×£WÆ¡"¢žY‹lxd3¼’˜Ë#ù"' 0]ÍVÊÐr:^±ÖÒ§0§ÏˆbªŸ†\ÓÈd«£Æl[Z±ˆaž¶ƒ=n’Š®ê¤‡’òÒ~¯Ø0M§u#/˜Ýغ xFd ݱ6}‘Žß)qmÙÇVù!<Ž›µòÃÅ«'> š°U†K‘"—ßÜSWg ê³ÚÑé9ˆ ûþÔ[9§|°*îÂߤ»S)0ym6‘µ'ƒ+õh5P^89¯¼ 2=’U#¶´øB>gˆ0Ñþ56ájhÅ—0Y˜'ªÒƲ×P“¬öZþ—õÆJ™õYqßB÷5M:ú\ô¿oE’jwÂ9 ´2 pÙç_7B&Öã[Y¥~ ˜<Ìc£o»LöEr…ý…pž©¶Qd þ¬A!¸w°ô$n-œŒôdÉa30Úrh' {ÇÏ1h[¼”Ühû¢‡þpx Q2çV‰‰7Q2¬ž¥;i$š t4_Ÿ[h2¦¬&8ʨà›Å  éÚ$¬öšªe­‚4 Ì¿-ž¢iY S„o'åKÍÅñð‡°#Z»Ëôâ}¼ºD"„ŸxÚ¤k‚tÄö)¤¨°l‘ x“ÛD¶v&T×°sÝêI­Æ»jÓ^~mǪ̂¦m”¦5ÐïèÉ€ôÔ¦%¶AÒõzÒI“²z¢,H:DUªts3(d&ì1NšS â׉syµ_ÙÍYo,} ¤‹âÌh¹Ía\üÆ#/í–(}ªå‰»ÅÇer6«çŸ í5YäС,ŪÛÿ„µ1s_&ZöŠmâÁî«‹µÊŠTæï¤”¸­¥;R N4pRùÉÒè;›™éµØÈTE2 ~¹³˜öøúZ†°qmñ¹¤•̺KµÆN¡­Õ}#¬ñ^YQeó¤iÆhÍp°jtzBw <[ò®".Õþ¦Eñ³¢ÕôÄ\¿«s*¦¶Í#’l»Ê+:4 è±øMmCŠ[Í‘÷&׺'ôòÖÒD)û‰U¹Ÿ3 ®N™d FVœÉyr£Evw…ª+-A°Å$6×wØtøa)œ ®‹Ë-S¹ëiüúBÃr6’4ÉzrÁBåR·µ8PR[Õø·#3ø:6E§¾¹p[¢I‘åŒAyYwO9|Ð9„+1ÓŒ ÜÕ§[´rÈ' Š&‹¬YÔÍ–Z“Ñ­˜ˆ…)¢¶é"ðÔyè§^Ÿ®Ç¼Ý äWÓ\”®½Q:‘§NØ—ÞÇAe‹E¹LVÌÊz7¸ÀæSÎãì9DLëNRÏùAgÙìP¢Ë19¸h„ðsÀ`âíïY&¤ƒ$5sœÀΤÄM&Z„4*¾¯Þ7]“©Ó÷²A‘Z9twÙú`ð™'‡¿O@ äK~ŽãœÈÇ æŒ{ê •,ÒÓmglg «ºRé>4~¿œ…f½—{HŽ‹¹É–½Æ{+ÌNR^Ïý ЧægüÒדo2‘h`û¨í÷4aBÙ"Û´–ËÚ*˺~]c±^0^‡ÖÂ#,hNÝ=;d1©2æ¤á’ŒÐªŒG¹ £¿¸ó²¦‡E[8Oyµèíêý¥yÆúz‚ÀÈtQX8N©¶#%ù™}¢AV¸»nËp#åîVÕ;›úô8~ß퓘¤}ÇøMÀ)½Ãº’o;²Ü®!_½Þ¦ !ÍJÇ´Ô^!œ¹\t€qo¹€ïàu…Îl¦»Z6êJL=P<…´mZï~%/¹U papÙ_ü¼Xem°é¦zÎ(?áÂÚ=;{Æa7n¡)hr[šâ³92n¬…&º¿“´Š¶=·qJRæñ”ïÚ±ò-5„Ú—²/ f,(¥Œò&8›¾²Vp>.¢JƒÖÛEs`ø¢”=˜G5TÔ`ñÉÐU\W°£ˆ•Š_ÄÉ d¬Ü¦]ÀØ¥ÔËÐXˆ˜Zü¡’ùÒyisá¢g­ 4ç]îu™|mó°æHèš²¢'Èíg£Ùº`‚Ì;…Yè|·ñlÞ»òç†ÃËïm,9!行HЯ äç\**w C§;¡±\yV¸r:ÏÚ‰xÊ"ˆ¡"Õ&oÞ@ ѱojéÌw½š î뽚}’YÂ4Æ0 Óu¿Á½õ³lsìúq›ˆc‘N y–:ž€N×x€ðåIÒD¦~úœÕ´39ÔóÅ1•BŸX4“’bŠn ‹qÃ*þ—ñ*6¸ûdLëî+œa$9ƒw§¥<…K‰¼O¨Ç†ºÁ"33÷å^´™Ÿ÷4„Ü *\8?yQÙ¿æl0ðÅî‹£ÿlOÞV®ßš$‡ßöþY³ãïs_AAÒÓ6Ÿœƒ* £ãÔí[xCzÆ•áÊ£¾–Ÿ/ɸ@A=O,ê”>‚tΪªnm}¼Ë‡.B‹^5ÐÏt¢)@­”dÏSËrìšÊš©ˆýⳆWY~y …E`Ài$*×¶ÎJ“\ÊO›úHÖ8\k̦ÌRcΚÀ¦*©àP —•(.Jð5y¦Ö·Iö‚[‰(NÁ˜²~¼çÞFšAúSÂìÙ•cU‚œz|ØÙGš»çüÌåDæ’ómðl$NqˆëÜÞó”ÃMN‰‡¼N´Ö¢¦t›0„*µ»ã"W?ØYþ*¿+À²l· B(ÇéVŒ…gL¹÷äë¸ô‚ÍZ>iî§gªDÒTñ½Ä¤Bž‰BÝÛ8:ó†o:ŽÆ,qkDhÕÝ\¨ìŠìŽQT¢¿NÇOV¬Í«¡FƒˆdùU€—[%–ÓÓˆ¹TŽ·ŒÁÓ"ùE*¬(úb´;A©áÅþcî‰äp† Uê¹½tI¶HT ­Wb—E•]tbønIØ@õ+ö ¹¹{«]%˜FÌ5u’×Äø6[²bØ™0>L3õº0|<¨›Ö1$/÷òIØÏµXJ¸áÜjÎõmX¦ò^Ûi'jóÅÀ8áð³žìt ‚ÖËÝKšÍóÛl¦î•ާ…˜ˆ^^­xM´Î×¶­ͬ8žtaK‡R‡c}(¶“ÌúäÕJù ¸}B%¶´ø:‰±>§f…7Z_QÄÕwNðy¸‘\K@å©{qý7Zë Ñ®?,½‹ˆmÓ’ƒn=rW3œ¿r˜mÛ”é£%lSj@¸HŒÒ>! ×èÜþh|Mû(áÁ' ]Ú‚¤˜b²æ×ò…i¢Á2ì0e÷í3ñ_¬d ÚG!x'¡'Ò@O1«§ŸñÉâ|Ak‡˜<íê'èŸqõírÓTãð¨-(f±4Ýe_ûdŒ(ç"x윮 v ŸduÉWâùÇуfjô‰M–^€÷bå ×œ^5?¯ÑáJÕ+=…†Í}çXáí»€j1$…fOÔ™5b›Å,,üE®¸gì´Åi¾°®¶]¯1'¯ÈÙÙyx¯ëÁb6ß¡=„Ñ÷5%ùâT+âIð8wJB6c”‡fz»è†‚±ÛÒÃbâB´½Üᕼ©Å~6½¹ @‹rg^\Tô9‚Þ³¾¬Ï²ä-¿yAù©Ò ·ˆ™tò}º¶Ç6Š/«$…yéRg+l¢¬˜ Z\M„õ'4œ†…bÞ(M’>—þÙìxó;–„ÂAÏ+]-Ð.’í `a[‡2MN°®[ª„rD‰ì¹aîí“åÛ+.(N&q Ä!òÚñI&þ–#Ae\W]GÑÊ1éíO#ÞkKØíwBúA2výÀ[‡©F&™GMíF*EÔÚË«‚Cyî$“Ú§…;ðHF QŠ ¹Ý¼¥8ƒÂ¼˜)Ü>œ/wY¸¶J(•äß%K/–µ.«ÒÑÆà„à'g¬\3£épA¨+KBgBòÚ$êÓýUv=+Ådù{ag5U‘H½ÂŽ¿î[2aµ—ƒäò—õXã‹ØYšG+# ä G÷ Ìš&âV”ùËÍz?ªI?~ì±È_C!D~Ìm{Dž(!=š‰Ìû‘ÓéŽmÆ>ƒ4ŠÇÐní<í4¯\T¶´žJVoàÙp`Šú.@£,&«r€¿ÔVŒ»Ñ€¶3Ô'þ\‡Éî¤Î¸‡‚pÝFºrt˜y0ƒoL®šÖÅŠþIpQ,áÃ!ç¹`¨—¯Ô ɉNš9–ýèI/ <ˆ’Š‘²ŸììÅßGÑ-“lÀ¦ïÛàð4Ï;¾Jè»äâ²¥,†(Ú?ñ¦÷ö!Ó$®MwMˆ%±Ž&aVªÁ¦øÏ| äÆÔˆHýÖÄP?ù´ìc[jͿðËz÷Ib¾1.Æ ¾±5ÜÙ–ÍÇù_ÔÁ§PµHC´®’më½.\D&!̾Íɦt,=Þç^óˆâã\àåङá >Ââ©övpÌÙ_¨ÉawdˆÕëÕô)oÙ¥¿¦Ÿx©Ù’+æ¾=šÜZŽó êuÊ^éA%ª’n3U†O,@C ë·Úhµ«ú0ü÷m°ÉW§Ì>ó@ Ñó0MÊ, M»ˆ!õM  ÞO_È~™\CF<´#ÇÙ^À‰ˆ ÷UËsŠC3ßF_´à‹6ÜR²”v‡ÜЇ¦ ꕵ±S£§À:fZWêÝVo_Êû3J?9™©pLíVQ?HÈfß8\ò«¬¥h¹ÃÆQuŠ‹`äæÛtÁÓ}t$¯4…Ÿðu³å›Çp0ËE=ŒWÈusFŠ-”ÇYQþ ríÚ]MlËÆé@ÜOšÿà §V“%Ä=B! ÉæSeóBF µ›:n2sÚØhÖÄãRCë‰Ì ]‰ô6Ûw²ËW¡†VcØÚ¾§4¼Ð…µÅܘßN©ö8Ò¥ êêH?ÚÀzz¾¶7‡áSWRÊ ÔDôŠî® ‚˜‚6FÑ~Ūi $¡ôˆéÝÓ# Ð4†CwÀÛ¤â_heÚ KkFÓx\i¨—^lË7ªœ} ÿœnÜ@æ=‘C­‘8<ñËÅ­‰4ÿMÖå|þÚ5cxÅIÐEçºt`ö¾Td’iÈz ’ù¥F\ç$ÛØô ÇXšg’½Ž~Æ8¯ààš-–+gÿ wñ•9@ÜÕzäŽàb_êΓø¬7XˆªCÏ: ¹÷<âB(ºò‘c•{$«#NŽïß3¦v*\ ï® l„ð ”£Ê HƒíÞÂhÌv –àŽ÷ik¶”É\’âìõµa•ÿÌTpÇnq•½D&t |áA®²¾¯=) @áy)w,Á/[¢ÙâCIJpSe송÷ìä¿C.èážl‚WöÄá¦'×Tw ׿{9]3Î݆l¹,ÁO»áê´·Þ§B¢Tøy•6X˾{èC$IŸš–4 ¬Üø€¢lc`£t2ã~Œ¯ÉÎLMydL„léçïrö…¶SØÎز»×öáÒ;¡óçfܱ9|œÞ=–ˆ#/'ú¨!åæ`yœ§Q4›Gbê•âBîPj!b¹G€•ÂÙ.#zø³m+¿ËÆ´M÷ÿkïÅÔš¯ßèÄÔaH¹^/•ñƒy–9Q—éU‚¥ãò4M.>GÜtj6¸aÜÉšfŽæáíÛŠ1Íe¦oCoð|)S=ut?Ò8BÙ 4Ï»N&)q:ÀˆÜzv ºM¤WödnË.Ï:s\ó Ðwž°DkÌ£aV°™Ø¿ýL5J×8Ú¿WFÐj)*º#ô¹ÑœûW—‰~zš(˜†ÅÛ•kFëôî/D¨…ɵ)ÄߎÇÖ¤V£Cý¤d×F«µ|[€Éµyø!ŽØ®‚†[º¬ o| ÷9i=3-Ê\”<ýK½r¢!Ìǰ¦n,u¾®fŸ7&Ù=¦×c«2>+A]å™^1Ù¯FHªvôä@ÄgËñIÀõC’¥M1Mkœ5ÚŠÂÒåù‘<áÕ‘÷~/¿v(D»ÈY;3Ù>l %ÛdÎA#¨›Œ÷Çvìu®êÂ7 ØhB»q Ä·ñ,DÞXÔç!ä7ÃcSz K“¤ÍI×*; .íCÕZé²5ã‡%t°j—Xr?p>#aœ0ð }Oœpc -'éÂë±,·›¿ÅÎý8Bü<iÒ\ª!íWÏÕåáÎMø.üB)E:ÆÊ×¶Þu³#B„5J®7Û0lvÕÅ9:è (‚òø.EÚ{ºè÷Í^r¤Wý”ã§z<={ü«õðôå<=$)G5!=–z:÷ùç0”Àè)—;,È M·/;"šÕpKÍ´«­ômІõéÚe9½á_GÛ{Ä®ãèAÏdå~}Ní ®Iöèk6Øˆß ˜26©c0RFò¢²ºú|©rÑñïŒIZåÚ3àYës¼:Öÿ¼|  S÷ê£Â—¶.þ¦ ‘5“Fk %>×°ªëñ‰!ú,úéž gÊE€Ýc…C‘™%¦"¼ÐêV×ÛÌÿŽF¾F£ÊJÂϧ°¸ÙìçMêvBú›(‡ZpßfÉO+Wâ±ÖE}˜Ö¨½QL‹X.Mí¹âCÎÎU»›²¤ ú2ÿM×·Oµv™ŠßÒƒ½hcUÅšô—껬7Ý=t¤Ñ°Ý÷H2öox×Rf®\žzŒŒ”2gB¸Ö2+‡ guÀ>Àu›@bI7¾pÈÁï*vS*)Á6¡|Ä æž·©µŒiˆh{°ŒÕJ¨Có/¯ÒC_Ì[Wmi}EB¦6úš¬wmî´ÀB…ôQ Оçí)ä¤ÔðQEzd ’’Ń*ýãJ¾‹ßÉ[>X:mÿ l_¤ˆî¹¿œVžÃàè5¢I!d`ñ5´…¿¬xh´’Ð'þ±ô-²––¯A*Ç/­^ïT6 ÿkÝÏrßx2ÚKH(Ÿƒ6¨ýƩʞÄÚ_uKëîÎʆ‘=„ð±Ç 2É;Û–¸ow´„aù\]p1¥i§Þ«Ð[ÅŠs; Vi³7Dûç©UĸâP#$*!9õjU&SLZj)—6ÿ:V?y”ÌkPoV8øxº|mý…Œ§Ë>¬é¾’NR¢«eš¿¨0™ãõeæMáÔį«‘^lôÙƒn¼@É|¹Äà°2^"Èj> ¬·¯åÚEß*Ú_J/Ë&=è ú/e飋WBTÀX”ÐsvHA¸ñø«"â'òè×™@¿ÂzÈ¡éá}I’ÑT ió3j¿ƒRâ’ ´ÛK@¤Y¦ÂÏ[«E¯žop¡pÛÄF’†ž/b¾Ò#j›É³¼¼{I9 ë1‚=s,ZðÓLNÏÇL­‚f”¥¨á®bz0R¯• û´ci¿JútñTs¢ƒMÂÔ³ìÅ‘¸ ¦ýnYé*µ¶~ìâI’K `8üÒºœY‚bë‘ÉÅòÕWKìÊP¼r_$ɼ¢ç?l(Á°¨´¨3Màô-øX3o–Ü0àÃnUNŒkdVÞ-YÆWÍt$«ÞSó€©ãýN±]"éÂOk >C«_Bž‰ª÷s½Íœ÷üwx–•7÷˜Ê¸l/ǽ³8#/@¦¿'oo”qC%/z%‹–$÷A†]a±R».ø¦õbWXª+ÃÓäFì":ÔVbõ »%,8]YªWð){üÚ–ñ“ ¸\<ÇÕÖ»ÓSè­v†E/û€â“°qìï”,êÌZ§Ï{ؽAç~Ü[d™ tÅæ¡µÇ³&Üœá$­É,ËåUoFPÅö9­ vI×)R©á¨F¤_ ªwp, éi­OæDüº”ç’ /"†–1/ þÒ˜êMX_ù©ý¾¥PlFS™`×;Æ1ÁMƒ·`r‘[IÍŒf¾üZ‚`Ò²@>É    ?Céi˜0ú^¨"jx '?°È:yZÌÝ’õhJ{+QfUgÏ?'Ùd^׃£ŸYå.LíH† Öæíø?§ÄM\åÒcÜ‹ŽÒOãU]cÊšr„Ö3 ,/óü="×ÔLÐc¿H.ÝðæÅ§T¿ï¢”IÁµU˯þš›Õ¾εçi‹ÿµMªÍF® 8¢§½€O×`Ü>!õÑDVªÎŸAYä+ek é]ûs¶æ¥Ž rºBƒdJ“H>>çiù·9é–\Û3v&ì7È *PLò‘a ¬7›(=ZÀ³FF×k£%¹n¼°ïGð îât[ËÁVyÅŽ´ˆÂÞŒ–Òî¹²1×Ò—“áqó**H‰ýo…ûUêÊ׿©/GŽèÃQ8Boqì, ØJ:?ÙÞ·JÖ!TÜjÏæÙ/dî¢Á0}Ç9E}TÛ|tÊ5CÉVÄ„œ÷|쪫Å:¾.t"øå(¶ *Öƒ°Ï&Ò@BfmÖipãŽ[u,ȉÛÔ°QJš‚â<9‘‹%fTÀ›XeÁf‡1emÂj§£Í˜z¶Ô³½é2WÃ'•ˆÜPA‚åÈGRzÕ«Kœ‘ËØR¡%I­ŽW¡s­wÿE˜~„šÀVZù…#•>‘(QfzÆQ‘òÂëää¡éÊ“ãcûàî€!,³Ìzö’ôת­}£§#ØÏ«q½VÈ^aÂ>{Zþ@P.7ø®aS²ýs5†z}W*!ÔEó8 #QŸ"9+'¤¢ýTu'DŸòWÓ1-ýÿBL?w/°ë³ÍÐï'ÝÙ—¤R Tr=B­øÝ0^Î<Ìqþ¦,'ㇾN¬\‰Ü;Ò»†$åÛgu™×àÚ>=¹ Ddš&óŸ1‚€ä˜Œ«@€®5®á]…\GÉã‡Í<ÄÔ%7Ú¢¶Cc݃ƒƒ£ÏøüÇËl¹;dñåäÃêå÷‘B˯Xf{õÍ™/-ô¹|E¤L¿¨,^ê›z]ð¸íÿÅÍ¥¤©dÌ Õ÷z´8ÙYà}J˜Ðñz̽Jòh¬«ñòÈës­ÆÿÓÀ‘Êf9¯V¥B§,Ï™][8åê1‰M{ÎÞË€`š‘.Ò%k ¸_<êŽ"“×Ùàë*Ûé0ž c²‘2YôOG=sÁƒ(ÀñÙ™Õi8Ô²Úª¦˜^¿!GÈHÐ/•Ð)_Ç­Ç}YP‰ŽÓ]¿kÙ~Èj˹¦¦-ü®YãêxÕTã“„ºÈü* Y{+i‹WãéÓånÊñK/€^¸žáy´¥e¯Ž»< A#Á]Ëcß6@¬Õ¡Lõ'÷h»'þüt^˜êÓÀ=®÷ÒAÇb!Ùk·ªeZ¬-t{fŠî%íªÛ]CÍl7±GïëÙ™r!’߇s°~B‘óªËság¸,ÀþÇGïì/ ÓXóZžéüûü]póF~k)\¢¼º¢t¡Mš+>ÛåE¼\øhƺø¸#yµó\¼Èt ø–3–x芹y *> ëäæCx `2ÂlPß—Pwàª=§>aO”<¸dÓ% ug¤[KÆûZÕãtƒiùèÌ‚‡éb‘F©³m“ô}ÚmuÊ£üŽé7.Áé¹9$F˜R,+½Ô€ðõ¾‰ßk>ûÇM†º>ç¢|kªP+X0ì2³ì¡0*4˹[f妗+Qt1q»¿Ö>üŽ–£*þ‘{K3D´+Mˆo¹Mbjó+â#Ÿpœ¿mÉ—L_h}íFßF}£zú!Þƒ«IR„@á·Xÿ£õy•&]µUºm¯üsø!ò ͲÜH7àÃÈGèþ|ªü£û9Xq§À•+cùS£†’#ËÑ >¨IÛ¢"ÁíT}!¨fä]joV•ØÎÚÑà}“À·fz6ЬË2ÁŠ3ŸæHÚQ[a ÐÜ@Õ{L`¿Š6Ï£pVQÑ¿ %²ŒÊ=aÅ<–ÝŸo+uÈaôë’J‡esF[}I‡j?6?±v€gPë­Á>:}•ÒwÞÒà”â™Bï5íȆV¶¼’¢× BþùÇÚwâZ¹UŒj'ÇíÄé¦Jé?*Z¥3¶{)Õ»ôÁâžhB±Úˆ¸7²{dìšÉ½š¤R€§Š‹|ü%vg‘á:—5L=}FÒfË‹‘à—ä]™ç¼ÂÚrãC´™s ÏÏ=,ÕÐÕqì´DÆö””ƈ‚ƒY†¼òIël“¥óVÔ‡à)Gìd€¦í÷Ìì{ÎÞ¯Ìte;žë}.Ÿ×ÔÒÂ8„ÚÎ7¢(RRuúÇÛ0V#Ä—àtÜ.#*u ™!5è÷ËÜÁ_õì˜HºŽRK\ö61ä#Кš|8i ’‘À9~×R¶ž¸ß½œ$ØdÓýúÑ?‡u"½cLŠßFúnÚb:›ãím*€¡.þ…£‰d롃×N¤­wž9°!'Ǧ†+oÀÔ“¾·´þ˜›èc±UyØ2ÛsUgØìw§y(ÆXKšyò©–LWŒ¹Iû)-¸(Ù°iwá>?y¹K|Žp×M;aÜ›} ìÐñ%d<ÜúûÙŒAMñ>9†üËZM°ë%~j$D Ž¢T NG¾ÙXcA£ÑLƒÅiÅrŽ^†¥¡d™ëÒ}ÍûF§Ê=ØòîÑžÎ4ºÒS~GZyñì±B“Zß×èlzV”ÙŽ’G-&ORŒìýÜëˆÚ©×Sd7°!Ÿù+l²$‰ŠbM´Û³¢LwFc1Mnd'S~‰Pµ:¬Wøc ƒ¨qjçsûM›YðƉLZ7šMÇ)¢\Ætðk¿Ó]Ô˜ùé8Û­“A9ÖºmÇ 47_™ ÈG8ÒzHÜç_»„Óz\Imk}ÚWDú ’U>†—3̦¯‘oyî†}žc²]uvñt¨"¶mŽÙU ƒå‚è ¡ßÙVîö„PøZÓ¾š,ì¥×}6<Ÿ¥dÚjúvˆ/õÆ ³ªÓSD›SªºXF Tôa7¼ù"íÏÆqÌ-Øj‹:¢NÀWSr}†ð ”$Ÿ!è±ñªã©ëWÎ>­*¸ËøØ¸}U¬ãÿm-ˆ»sÿû­¼p}&P†¦§:ÝI7‹.ÂÂ̽^ºÙb2·°]~MÙþçñ9Ýl-lC¤éðîv"¾_YFLô$˨¤že^™:ûÆÈÝ¢—Fý¿´ÁáE§¦KQ—mŸÕ H5A]¼’Éãíᇡ³­*º9Fsõ¤žtñà†¨V]ÿŒ×þÉÕ©`»•±êåg}Ê1ål1X鸞s2 †R… ´-ÏñKŽ¡å,üsJ]ÍŒœ> ’€¹ ^Ý.¡ÒÜl4B3ZXj÷É» :ô˜/{C>¯#ô'¨@iŒ7¡/地¨Itž…Јf¯œUÿ0…h®Á‡Búo&ø¢Ñ/»ø ßdJ™%³Ù²w;ÃÂGxÍße ×Ç)¤v‰`†e ì÷ÚRÀI[=SxQy¡ í´f.—*lB[¡.dš¤°ä]5Õ¨H¸Q^°'©a ê—7•®P3#Ò í3Ñ1íÁ>Í™6’ÑhñuÊñº¼ÏÃRûRž>Õh,ùvkL®ÌÞ(ï<"•ÁÆŸIåÉ&3Ì7\‘þÊRÚt‚Ø•à™nxMâ$¤"6 U~N^~e©¼˜Š´Ÿhð}4tà†Öñ³”Æœ@;pêéîŒÏàr]lê-7Àzl¨¡ÚyVЂ]çn+™ÍŒ\,oW‰yÀUj†%•ƒ 5i ùðyl÷Móu™{´=½Àb‚Ñ KpÐñt­øå‘]¶”ôð}гeùu7IÈÏêPÏwhzºì."a›°ø•Fì*ÍAyò7 ?‡KjjÙ÷BÐãRðÐéoíèÏnJ<*˜óÉh’—Ë¡œbË_š'Aysô-÷³^Y¹  PÏä8Û`?¨ &(þrmo…áR®gÎ\à'–4!¾–9W®! š­ÎŽ?­õ…97;¸©5j*6”Œ}1ÿt(q‡Ûð˜.imA½’€üä©}†<´ó™d-•þÙ‚^Ƨ”XÛøᾄ!!º·E õÊCƯšàSNU¼ÁˆÚíîÇ;g‰*1¿0øS›Ó<îY5~bUËUÂ<‹mØXÞƒVhDÞ}Dî,°üieRÆíðyž­ËUŠQL†k¾üì]=¡0F°:¢®Qdç⚢Ò_Ëã“ý@µàÍÄLܹškxBR|Q·êŸõPZ‡Á¸·à˜/Øñ%r?& G«Ïð?‰*.”ש ÝßÔ>qê+¦®\HP⨋?`ÄX4ZçÉ‹œµ0ÆÅ¶©B»ø¥\ÃÙÎB5—°¥h~OE5oJ=\âÒ½ž0È%Ú«¿”Å ¸¯UœŽ§¿§ZMw#̸CJôdXv÷Mo.²7½/9Dz>JG~ŽÖ ÃÁEÌŠü|Ã5SŽƒïáfèHÀÊ~ˆvO¥ªqˆÃ¯‡pý£L YӀ堞!ûtf JPu‰ˆõ¶<1t<ôð‚u¹ÿ™ûú.k.ì*…Ÿ‘Jí>ÿî]G ºUæŽnè3qÚ °0,ÉõËË^àºÿÐùÏÚ+h<æ  µ‘g§„þ²ié2ºYœ†X–ؾW yåyMóBY m£ŒŸ“G\ÉÄÅBU`%šÈúåVªÈDDºÃQN§Ìt쉫ï‘'4;Yº®¶ëWþ[$7W#iéë•/Ì«›¬Ä€=iˆâ'ÈiÁ;sóæf¤š(D†³ô'î¶4I­lê ¡YrJ»ð±¯§‚h Ž®‹{ÕÑÖåÓÓ߉TÜôI$@‹ÑCË1cN›]ØaP9hÀe7gÏŽÍŠu"5o"¹Ü–UÊ¥Ö¾‰qÞôc¬±q=¾uykq.Ž¥SÁ ´P~çÍk¿i=‡Û2^Ð ±øb7ïX3J\á‡P~À0.í$ï4„I×f¸9¾×¼ 4½Ð¦‹=%Ñ• pÁ"- ×I(®Ñ7ô-x±º|\Â…öga‘/·†ØZ®Í¸ÿ÷ÌSÙøÒ_¨cd14a¶$‘vý Žn¡ªúT§hô'>ì¤_£Âà­ê –yCPOÓÀªa…êgò›ÚÝŒòÜFGXìª ñG v-M3µtpTÚH 'oñÒðÖàS0læ¬à̽ŒÐ†þ±>Peþ¾}F3£ŽQ=n,S;‚ç~låÁ.ñ³,‚£zÒ…©E}‰³õkÛ§8i7ÐÌðÆš\—‹É–Ì;þcŸŸ},UžYõÌdSÅf‘µz=Øø‚àÛʳƒü³bˆZ>í€"Eô3Aë&EMóU¡é¢Â~=X™( ‹ÿLxÒFLkøy»7T¦‘z”q!ןÜ\jßµJM©N$)2ü2U4ÂùŽŠy’‰$ãtNxþDX>"kÖÜ‚P7MˆÛš>yù¬6Ÿ·ÉfÂé÷•%#y <ÆÃ#ºMc™ÌªÑâCò2ÎúN÷'ío¹Š„$5ˆÜ”tq0úêH|¹3üæåðx§½µ%¥2­‚i¥aGîZkÔÜí”6ǯúŠª“SD“冣/·æ>D˜O»lź°ã”a>ÚÖ)¼’ M†œC³c‡K¬o{=K Þ-B«ùeàúÑ¿ä2!©Ý7V|1|b»üúŽ“ é¼UÈ‚¿¹JœÇîg É‹7Xßà0èËÚpù’r|ïÐ\ð‰Nê#.’£½1HéѲj=øÞ¦V€Ý¤aè¼((0¦n½î.må}(z·Mk9¾ bø‹NøN­–uÛÄXR‡ÞäœÅÍXj¶€!§Òû©*ò@¾ô»Ð÷>?b3 ®Y–ëÙ‡9Wöª{ÖuŸN—a·—P~–)’¥Ê«—æ ?E/þ^žÛó}™lÔµ¾²†v• )ó+áðà±oY"ËŽÚcL¸'‹[v¯ŽïrØ„qèÚ¯’3;aM÷BZ FHYš§MrI»Ë¸†Ï¡2™½ÞJ¦¶²8½< m·}Tåp³âÙ'Ý)çâéýêÓǧb½´tw€v¾eIPdÌ,øÑÏé…ç¯b4¬¸Ÿ!SìÜ÷?¯–ÆÚ `´ìîÞIœë6“,%'Ñ Œ‚ÕüèØKL¼ lµÝ@Fûqo=^g‰ ‰ž(i…BÉ´ðŸÅÕdÂ`5¼n@ÈX(*t:“än 4©´oër÷¾a(#LXf˪Ú4X„kÎ5xÃñá¶ß­˜%ñôØÈõ|•xÀㆬßW1—ÓÆÑµ öiIhÿ¥óÍëÄ÷cª.è&Kø0øÅ=KuÆyŸl|a?rR ˆ¥=¿kõ·C\êdTþ%®òöõñlƒ»Ö!“v!÷1~ÝÍÏ(ÞnˆÄЬöEX8 «¢)nX½bø!W]j•È%a-øgÛ¨2?ÆN““(El ™{ß‚ÍÉ‹¢á˸Q|C‰Ü­Ð¡F0JJXÜ>ÔúzΨ —bcªÁ¤Ã×Zmb‘SJlGmeViXI´ÇÄÍŒŽ4ççR“}ª.iÊ¥™]T"Ý&Ú¸np‘”–ß;¹¯tKÐå^¸JWl«Ab6,Ò6ª)Ç×ü¼“¼`á ”ª„hF>®ß@uwÙˆV$‡ˆAŒ3À+¬¹7\d<ñèëDËþ’Nˑк,{ÖäaÆÂ)^™”¨Gaœ ù-ÁÀ +"1†BªÒcÎÕGƒR^€¬À’‚ÂËHµó~û,?rC€±A­z µ|:.ln¦ªn]œvÍróÇàÖÍ¡Ÿ_ä ˆM•ø=ÎûjI%[íòp‹0Ði`e3m.Ä Ëç»k[ùÕkr,·’D­êG°icNñ°›8Ü]†JV¿,wBêö ê· ?ÉÂ-6Dâ|ðç³UÔÅé>R >s&ºvZÎþ„†2¹áªðÏ]­78{_0Ñú£'\k}Yiæ}|ý”Õ&u²~*~Ð ezÐÞ×zxùûŸö°nϦöh?ÉQ|Éò4y4ÏUšKź\ó²tâè™Sì"dâ/æa£rW–¼"O~¢ã£…[FFu¡ÜȘ2É¥(—¬íPT:¾ ®+í8u'î2†E`Ü{–Tå=§møÜ[Ô¯Y1–Õ„G1U¸s^0C9³yPIäOãA¶:édRR©êÊô-—ìå¢ßé9cs3âû¯M¸ƒY­X݈çR.Š]¹©vÂ:"žä4BwæçbI6é-Á•Ø 'F·s³U ð”ïøåŸBS`>™¯D7);q ø §éšáïLCt1*­¦«N\«52‹}ƒíËüÍ®¸ƒQïŽÿèÔÉÁÂÊ,îo •,d‘»ty›øÅƒ–?ÏòŠ1vHÍËј30K¦s>¥yœxNçŽH¯–'DO;ƒ …ë+íV÷ÕIfõyœÛ¼dÈ®\dwJ ¯2§Öï¤Të:·¹–fßYJ±¤dÃwí귒법Ð6«š"‘Dá8Zß*Ôì¸%—6“9¢ùô+MXû§uà®ÐyÊŽmÓO±+K‘À6­Qò¶bÄ›7ï¶ìåÄ<úI¶®ë,1Ʀv ­xUã•;²­q:¿'Ì~OÓÝ“Äw}m+PJè ¡ñD\òvbjD#$UAî­tÌ*ýˆ]Òêç>Z,!×P­£•OùœâéQì#£Ç€.¡l2Œfþv'‹I^-¨,ÊZ5¿0UCÔ¾Eƒ*o1ÒX}˜vŒ¶³ÀÅrõ’¶CÐ¦Ï ÷`ÆÄpÎOÉT'©nsßµaÓýþãvÉ‹ù§5þø ¬Šº²{™~ ¬ÓŽ.ªu:1‹òb¡}úS< žˆÉ÷¶_ä'Î;5 ÖcòYO€õž»ÈÕˆcK%ìß$j ¦@.•qçrî…m…P3ž¨ªg8f;–#y:Ik0ãá/S>I^ÒÓë$}Ú°Ó ÷Ѓ§}†õè|Éw­kg:ë J¨üvpÕ8hKïu@d™S]Œ;äúÀ´î˜LdöNŽûÊÝ×ñÑì¿ÈÞ(h1é$tAþÅ:u2ÃêrcZŠÉ׊®>ãßãÃ⎠ËNúy|çr®‘Ä3n!˜›¥d´/ý¹Ê_‚Ú-MyL6<Ù>·í Uû—‹h†óíÃÁúL…ÝØlÓéz‹æN¥2¡xF×iè.( ̲Pæ…nv¤\l¸ý­WûË”÷G_Û1«–½xü?Ÿm— NŸÓl–P`vs =_±:¹]°Ó½«¾hC@MŸ”Ù`áóPµ7ßO§/K…ŠªñüRg_GÒí“oüò?t:VõLÁ,Lÿ!IpÎ ç~æïk"T(¯ßƒc ì“LW™Š?q}úr¢²zJœÃ—€•š(étv\6†G³¬ö'ðØbÔ=L!7á²Êp¯÷tG-õd28D—YR™|"îìEÞjUÂT*ùp©ÞøtCÏ,ζ<”¶»àî®s“-\×ç9Ã…"lz—{èÕøÕ®@Ù ÄAd¾“ ˆ3?<BtÔ4¤&ŽïꢜÄÝÑ,§ðy\£QÕm‰u²¢·Å»¢@Ž›°¸?!]¾Wò'Ú¾Ø6vm!Q½¶ªÿ×à?Ï5û§ Ȫ˖g ï,êуôo‘0ÌÊU7SmÁi | S^> endobj 3399 0 obj << /Length1 735 /Length2 1053 /Length3 0 /Length 1567 /Filter /FlateDecode >> stream xÚ­R{8”Yf·–ì º*’[13æ’Qi0&j¢I¡T>3¾i|ßß0C)ŒK[Y›TšlÖ%m±‘B$ÑMJ¢mY¹”J²ûѶû¬þÝçüs~¿÷=ïyÏ{~¦ÞkrDX쎡øBª• \ù ÚQH®2 uƒp˜ ¨ŽŽTÀ‘‡P™lG6J²®˜T)CBBq`åj=FbN,C„ ø ‡BHÖ`BÆ•v€#‘Á؉ €#`Y$,²#Q©@„q‡ (É~֧̌¶H.ý E²Â°"LZ¢C%J ‚ƒIö«0â.˜pò˜š(î.—HVAacòDF_ P"QþcaR9ËÁ2t"Õþd‹yØDÔ‡$ˆƒ†H`@ùÔB"Ü,òFpa(†$ðxFEM±[°çzrÖø¬´ÿÍqÈBPÜG)ýGtŒ;^Sÿ­‰ldˆl ØQ(T‚H¬Ï»®â¢BL„ Ä80˜’É %‰˜ ¢b€*@P¬°‚ðko‡b8q‘lÁ˜Œ4ö™tG`¡ðX“ôå\\0EÌB ,¤1U*X ʶÿ…r™ Fñññ ’ø\#Dn0¬€…¤÷0¡“J|à\R^,÷ø­üÉ6š.!çÓV•TÜ.Ÿ’вWSr¢nE¸M[±ßpA–¹kr—IÔˆQÄ÷e[W7¸¿Š O˼;ÚØ•}ÑÈo ‹¯ì”š½MèÖ½tîÎ놦Ws[}^ºε#}ÕÝǼ­Ü|^h=6Õ¨Üy¶òŠÉòsÏ’¬MN,žï`*ÐË ÏK¡'·Fé¥ï›ÔÚ˜+NÖ¾`û¨+“O>®}tÿhÀ› u—²G$Uý/‹hôîÀÑmg ÿ¸¤ªuRï|ŒèØÐ}‡L>)­H‰æÍ®åµqöÞx´ ¢o¾%ýH¹:(oáìiåò¬Õ«K†æmM‰_äÿñžžÍo½£m"ž¯xx¦‰eNüô¼ºû”u†ÈsEqÒ€¹Õ@‘êÕÌ%Ïõ/³ W{äWû0’UÓYjlÂU±š.[BÓ2fokzCÚLKlï×oRÓG~†õnL=FÛu]5Ç·ö[÷æ+#qô ¢žÚê›ZÞÌ›¹Œì:ã´Š¡¤ªK–½ÃÜ»Ëß–k­ì"‰½ª³_²×Ì3`+˜ö”Ô=7v´êx´³®j—vì‹&Žæïžv(cÀ²\­Ž;•÷°{ÐÄÛuG±öTµ~cv·¾Ý•,ç’ò¥q;²«­éɹÜM%”ÍgËÝÓmÏÌ[ôã|žY½¿¡Ä.÷¿(ÆÏØgøœšáA3ÕAgú­02¬ ã;ëÏĆª6Æ,=ºzrïs¨ÙÞ˜ðk˜{ÍZs^jd(M>gèZµ¨ü¤ï]'ÁºnaöS®¸‰ªïB/*Ô)Èq ê~è¨ÜP$=°ŽíßÞŸ‘’ì8˜”gå;eÐk©Åº”“ït§´: =ýeä|³QWY.¡ëf®ÞŽ}ó  ¶å5V™´kó¦âIx~Ô‚þ·­f ¶ôIík<Ÿ‹U7‘n›WFxh°6ƒÆ†àèÓéÏjêM•W­¬¯?g¼È1žds«ô¨É» shG ßùf‹Ï"ª´gÃïè2³¶°Uè$¹)ü}‡vÎßÛîöŽYYm?ë˜Ý‡ð¯]oÓ‚L”kGXZ+;ß×ô«9Z‰³rîïe“Z §¾¿èž§¼ð­h¦u}õC!ÔMN7 ×.£ŒÇÒÜÊ|ÁòI#©™Už¶O6¨Í(.Y|¾7qÔkAˌҪæèVë$ryê  ,—¶ñ ”›Ø`>¹Œ]=ûZgqUÔØçPïü ñMDÎ}áó-©é<^Íú¨•Q?ì^ê£îàÏÐkT$ä$Ö<¡ r×»YýÄ<²¯‚¾‡{Ù³gÓthîtãM}ÓÒtùCl¿ÇæN½)œÀ/×'6µ-‘ëþ T|öw endstream endobj 3400 0 obj << /Type /FontDescriptor /FontName /EJASTL+CMR7 /Flags 4 /FontBBox [-27 -250 1122 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 79 /XHeight 431 /CharSet (/one) /FontFile 3399 0 R >> endobj 3401 0 obj << /Length1 1850 /Length2 12436 /Length3 0 /Length 13448 /Filter /FlateDecode >> stream xÚ­¸eX̲¶‹C°à.C€ÜÝ‚;Á]à dpîîîî.Á‚[°Ü îîzæ]kýý=¸»º«žzªi¨)”TE€àÏ I°##++@LA…ÀÊÄ‚LM-f2v´Ûˆ;‚ø¬¼¼¬'3 €•‹—“™ ¶u³·03w|£ýg7@ÄdoablP0v4YCr˜[TÁ& G7&€ˆ•@åŸÈÞdBfe-LŸAf6ÈÌÿ葱1¸ÿ½ t²ýß3ÈÞ" ð"’‘ÛX¹€ SdfE0¤¢äÿQÿ7¹¤“••¢±õ?é!ý?Qck +·ÿ‰ƒ­mAö0doó·j‚þ-M´p²þ¿QGc+ 3+€åßK’®  ’…£‰9ÀÔØÊô¯u ðÿŠ€Øö/ Ì¢êâ:Òôÿšæ¿BJÆ6Žjn¶ÿIúÏÞ1ë†xcoá Ðeabaa…l„|ýïwúÿ§”„ ha¹œ\c{{c7dȽ€'Àƒ`a¹@®½ÌL6`GÈÄ’¯S°=ò?Ãäâ0‹ü³ôoâ‚(þCÜf±?Ä`ÿC¼f‰ÿ7 €Yò±˜¥þ€Yú±˜eþ¤ºÜ‚T—ÿCê R]ñAªúñ@ª+ý!Huå?©®ò‡ ÕUÿ€YíA´¨ÿ!ˆ?Ñ¢ù‡ Z´þC;Ílü‡ ±Ï¢Óä?Ä©g¶¶þ³›•"øB´ƒþƒ2ÿûŠþÇõâvN˜ÿ]a‡t¯•±õ_Y =›þAÈÓ¿ðŸ ÅŸìÿ ó_Eÿ‰ƒìÿJÙböBº0ÿÓÄ5s7[sÍ_; k!¤/!Ä/Ë¿b˜Õ_qì¯VX!þüÉÌ 9jcaú+iüG ä0ø¿Âflÿ„!ÉlíA6V Ó?žr°þϪýYÍQm yªÀ‡â„ÝŸaüCN ‡žæ?çúgìú¯ì¼ÿ³úß5XY!^þå4+Ä8‡?ÝþC 翜å„lw€¼ ÿÑñÃÁÊØÁü¯ú pBzs4·ý5^ˆŽ.à¿@r8ý…q8ÿ…á.ÝÈi׿’Þí/„¸íþG$“;ÈþߥþßçQTìêÁ1†‘ ¢ rɸ ¯Ë×ÿÚhâd™‹ã¿~ó@ÙÿeS È“ ¹‚LfÁ&ü_’›‚J½$ò–ÁÓA‹š5Ç(ÖwMu øÏÇB[ý³£[­Óz(OÃFßß!wy"vk÷T“<õµ‹I™yÙq6ÚIso!ÖºHSpÛ¶}wëø¶­iúêˆúÓ¯Õ‘Òí‚þ̳Ã\¥âj»ˆËPݺΠÝé\ÜZ’iVêÁuïÙ)T0RìJC8‚W\0âàV&ü½¾#}£_:·;a=ä#åÄ¿èÝâFcš´“³«lÐá¨ì •c¼­}íªþ˜0SµìÀ/"©üñϪÎt'’0œ<×Qp>ehi×¢x¦æÒ_-Ú2d§74//d9‹ËW6¹Mhµ>Om“>Oá´©ãÎÑžú¨áŸ‘82¹tqº`Û­§TÎÞ…Eà‘ã3R+‘˜¡S¬Î°Á«ïk±bÍâHç´÷+kë¿ÌÍ: ‡XKE.ÐûÇbàß0©g[“ò£§7ã³kë¬Åßq»'! œÓå6Re‹¼À“ÎȲ}S/1_1ÁL³½cc9 Iï)¦ùˆû$[мçp€³ŠÍÃP:ù:+?~N¶ +81‘¤á‡¾‹¾Á£D¶íåöMr†¡«'ÖËÐJÛ#÷& \)ÉÝm‡¿·‚é¡è!ßBVÄ^.šã)«•y¬#‚ª KÍ ×ßÄ÷¦˜o*«ç±ò3*j<Ò²Ôà 9ãYÒ´Š•i¯±G"Îì99f< ir·+Þ.ñsz2!1û(?/n…äû ØA‘ºié’çX‘éÌg_ß¼¸YR–p‰xÜ6Ö2šÝŠ«1RßÖ#BÏÞL_-@¥™-z<d¥˜|Ãöä‰H" BÕ¬ ÷渶#­ÙÆÙÐ0éÇ ÐíõXrŠïîѦ˜_©dOa`·¼°o­»Š2§p„}ÉV ö âÂ)ñº*Ð$ˆ¸=ÞSN~ß< õk iý„•˦y¾½Ãû/êÓVr̓ÊÞ³Óþ/©†læ“4y\Àëæö6u5íÛèÏkD“»Œ4ÑÓ䫪z?ƒ…òñC¢$e­B3fc‰3ûñͳ^0VFèöR–»v40í¯®Cž¡-ÉÇ ³*Ž6îA$~ V ´jO5_­+ä »¬˜'ߨ8hA·»PÔx;Ÿ+€½¬ëjêp­]=ûã¿Z 7æ”Í_=V)ü²lÊÁo7ƒÂ1¾Íù„7ˆßÁní!DMÝ›UõÉìsÐdqŽèiV$_^š ÑèMhx2½_gÆ×ÍÒ¼ÄåXR€ðp¥çIEšA¥]O÷‚i[a‚U.ì:–ü:ÙÔ77{lÁ*?óDY<ïæ,ÁÍyÄáÙÑ_Z\J1¢x ƒç@Q‡9yã[v%Ì%iëýÃÍ/ñÇãÜšÒÖÓ™¤_?¶Ú¨¾mrÃ4Ïárc6á ÏOû•äN÷q·‹^>톽D[PKåÕÞÃD§¿s6xÏ%f>rûmÄéA‘U ;Ú,¼Äèòºì£Ú0 lÅWæ2¬·DœFHëþæâV’Ê VÌ0úÂsH²üå½ë¾$¶>j—êHÇù­ÿ­”n‚«]Õ„@/vz]Kµs–ø<ûqr¯éòqÝñ•Ë~ɹùÍA¹¨¼_ÍB0‚.=íNy““ß…?*ŸKrÙ d®øMòÕEù³Ó`Ö 4Û³È' ¥>ò~éZE–ò f_GŸÇãûæ„ßS Ÿ<` Î.-ÅMÐA¦Ìpòý•…Áþ§=挑ª.Âw±~ê@F²rÄGWnFa£Å‚©CK軟޸ÁÜ<'˜ÚHtШ\ªN—Tv΄Ôå%9 ½…ͱ7•*ÞSG¥K£.Ì+Þ¢íSÓWlÞ¶OU±cØË ÃÅ™³Ö½>e\w§Ù¸wμ<§²Ýƒ5…üOi‹Pù˜åÒ)êº µ¢b4¦¬„Ñ7£Ïš†©¦ îOg´sŠA 4ü/ÒÜ×LÌüq>_³éo¦ëVÐÊ÷½+Ñ{ùp‘7{ûS1+zûU/TÚÃqŸVÔ`v4†©‘…pŒÀO! (ØæÈÞƒzxz¨ùí–º¦xîõd®}ì¸wnçœ|d©Q4Š¥œ1eØîé=‘)‚½2É—€áYÁj²ÝNf±vX¯Cf'PBïdœÒkÃ×È Eéªî—†]lSÝ#qê1: ͇.Iù†¨|%Ö†SÆåx–_±iöo¹š"Ïß$eï.Ç©9ŽðÛ|…®¬ž†Üö EÁ6fG{Ø.µÞA;áò#,ÌkGÑÝ#F¢k~çæÑ̉â<ÐE{ÖX¬¤XÚ•P´ÿ^eÐwnþËŸCAq{6ãÞ󞳑VÜ ÛÎ…s¾läÃN•2=®Îf(ñ諱…>šÞ¦ZÏέµ²T裸ð¤Ó¸Â¤,ÆÂ‡ä”nCf!|–öÑPš}û¹â7†Û¢”ˆ”  ®AÉöéUNE÷"šÙ´–_–ö0?ÖÛ䯜uSL«Ñh~!HÄ]¥ý"e-¿ í4øp“Î )ìÝš´(ûM#õb~µ¾±Œ +¹‘¾Küf,q´ÕßÜ` ­Õún¨ù¢¼5·AÞÖxüW%Ç=~“þ ­ØI7‚-PÝ_o ×ÇuF™.u¢ðýÕ/âðXhÊ)iy·0Å,ñ]¸E[†FH³1 TwMhF¶%cÑΘŠ‰SELì*Ã߇E–Ý*g=`Ó˜ò&Z}ó4½Ë ²êt Ö$HJ·#éÑ)Çûa:_#_R³£Ì_DÿX-t$Í~í<Áë³Y.9ôÃP®$éÀ[æÃ)e;v Þ:LY#V×¹ø†ô½æ2¼”±M0²ˆ}@ÿˆ÷ñÜèP;Ð$$ìÎLs0~òB;uANXr…oû‚Ö#G$k°Â~9Ùñ‘pv¨']š·i´„fƒ~í½.Æó1cêe8!§À¡ æ/a?;ÉŸ~DÙ]ÑHO…DR&ùvk^–¢Õ-oÐS¸T-Š)Dq®ë)p®×¿­ Á¾yèŸÚ€ó° ÌŰ³¥ôýrg¾ëv¤£™ánrÐÒ>´Ý²TÙrËÊ„5ƒ+ð€^Ï£( KqZ„#^ïÓüÙí•Ç#!tpÀ½WÞ ýÓоMW.ÊØV•vÈ5é80aÚ˜È5>˜Ð÷dDuè¸*™ÖN\XÑŧòž!ú;Sш¹yß¡‚–Šb±ý@ì¹Î=kÌ&7³ÜyġՄ¦Ð:…ßeŒlaqå7,[Öˆ%»÷:ÉŒ-C™¤e|€@†’¹TÓZlOOòƒÓ”yf.Þk–R|…WÒ"1D«hZä¦Õoû8£9oµrÛåZî]×ú.Í‘Y/kŸ=±GÚ-jEišMÇ~YUÊɽÖ3Ë'ŠØæšJð)dÕy !3UàÉÄÄqö›<ô3²c6v³;dvŸËÛ¶­ve%BQŽó0|DáåY\„¨£Br_\ÂÐTk_;ï\÷]áy¾82tò+¿T*_‘¶]ò%u°púèê&;ï¸ÄhÀ×#†è'‡Uh!éË ><~£¼˜õÉí%NÐɲ~ ¶WWübô †·w§ˆd‰ÇÓöZxŒ.|ëGAòšfÞ£ð¿Å£DGo†Üôš{P£5=4~lQ¡@]•‡.K×D‹DX‹í=”ü%¬j•úŽd?/Öãs5lTËäÂìÑãtÕBÁ²¸g§‘7mÚ—ÃUœ…§%ݰ»ª sæêÃÀ[俀Co€yÀ¢aí¾µÃɃ2 ø¥q^GׄVaqx,´QV&,îŽÑ/{îq”ìßçø“6¬©½&Çqv¢Y'&H÷|s±ðeŒ"µ%\0†ìéü•bžéyÈ׬˜Þ0 +¢©zjéóý–‡®.‰<=sÈÙjíH;K,=á·?¥!ù‹ŽÓ©ø|2í]ãÉ0õgè™V&éKÎîö…JiN"iø!xc¡~vsË>Ô£7—Õ2 —_l] JGâ[;bZÒÊkz-üœ¥Iyn±‘2Ò³}¬W ƒÞ¿Ô»s£` uy†)ã’µÙw´ÕJµ9H75gù µçr¨è ·Õi2‡@4 k€K£Œ~ ý€ÝÌþqßíDŠ>7×c­Öv»A{lÇöâÚœ ¤„Ü11#}öNoBHUENÐÕˆ„¡MÛøÜ#´Wÿî³pªk• 2+ô·²z·ŒOâÓ;0T‡â^Ym}u¼.smF2¡CKv¤ø°ÜX ]ÌøRJ_,MÉû{Åĉž&ùI`ÞËO§U_X7è„Üîþv¬»`-#¯ªÌlxϲˆ†å$_øß1Bæ\ÓÕ¤úÄÙ™ÞŒùñ$ µfƒQÉ,)ãMÎ2²Û÷Þî{Õ ý’­v*¿Íg,È‡é Æþ~¹¹Žßâw×ãàOó*ŠÞ½‰œÍ8yºÌ--ɲü‘ &³ÍÍSO‰[öPellþîð_$"6Šb‡B6ŵàÇXb<Ú”SA1%¸ü¸4óýõ§„¼wãÒtvëHHј—éXΉ¼”(bï `_ŸjÝÐaé aÃcFˆì¤ügÈq@ÖE¬ÖUÖJô]¯>#Å7>_½·MUŸƒì_2àéY”vE—:ý`Rà n›0K¦0Ù "ZOm7nkÙ>÷=Mÿš¹i>è覞ú}˜Ÿ|©«­<ÆXM;3Ç€xiJÍ^ˆ•·Ÿd=¦íð·éëüúaÒöê#552;#OY$ƒÜ oñ>íýn¯¦èõ,³VKI,&p€c®°Ég*«Â{RƒnÚ3rhŽx‘$E¢ÌPÙêÄyü T…r[áÜ¡`Æ ÑL÷/¤6|ͬŸ@&q…cC«ý=7î=ÞU°^9‚SŒt×,ÝQM oÈÝËsfæï8Oì â§7Ulêaèè.+‘«øÒÞ¥H§0ÕMJ¨Õ®¼ÁXM]«øšFçPÛ¶eâ¯bI6ÙïsºŸ_«6Ïk°ìü—È‘¢3 -e=X'â”Û…¹§µ5™{£"<â}2\“©Ô¬4ìK“g5Þ E˜Þp÷Üû]øX<]ž÷û»-ESñmuø¡–âÌN’ ú<)Ï—üØD¡' æœE¿À¢öšÜ¬|ê4ÇÙ|¦õa—[ÔIó_·Ü#8‘µÈTǯ2Ïô°HçPSƒñ¸(XP7UXo7k͹s…œåȦ$\#ÇÜFÊc¨ê&$4o›[¿Zýfò¸xzýfßà¯v­Q h@J´”9Øá·â ~¢Ì×V7qG9ìc;÷|忘"~bìUÓÕ4JôOÁóMPZºÞuÄäÓd.ƒÒßaÙn§ZiÔºsÙ&Z‡ü°ŽÈê¬1†Tyù8E”10 *ÞxŠ¿‡’PäøØè2&TÉ0×J‘öKNÀ²æŒú_.ƺ›b€kX/PíRR-qn‡$ÃŒC?F¶ºqp ­ö«¹K¯/18GæîÐXÒô©û U},ì…Ñ〡6j¸¶æßÔ¹jôSì¹íµGOÊê ÄQÂ÷Ž/Y­,âÞI þ•‘ün®µÑcÀ~“n’0^/©D*Üø@’Äß) cGç÷D0ñY}«¯<ê°a@Þ·9ÍÊ£‘GëÓ,çWÅCûq·‡Þê GÌ^ò‹=µ {ú-ÙdÛ½óë—‡Øßù«v{<3®¦R–$3‡O— šR¶ÕÈ¥äzðöWíëΚԜݦn>\ø}O:µ*” —5Þ,O6Pk™¬™€<†±”‡KfgFÚœ¡ûíTÎb‡‰ªBø+ÒÐbƒá3º¬OÊ߇†­~Œ-+9IN™â—½/÷»çuLq®F ê ¾Ü<0íÐ~F‚™ŠîßÚ2dó¿Ë¨¦ ûJÔ¿ªb1‰Ñö3GRj Sö9æSë>¬ÌŽèô¹H…·À%É1NgÚ^©xOj£qôG´ ¥ŠŽ¼#¨1;ë›d·Â)ß 41û7fç{;½“¡6r¡ºyæS{ÆzTøMU.ßêw`r׳#i@¡‡I'дÈ7L„峚ÕÔh6 ¬3'Ë•EbÐOqÎ-(©zÿE åðÔ3Ð]õ€}œw˜ß|Ù!©‰¬9‡,YÚ’x²¢"\Y‹-ç ý©JyÁ‹\ÓHÌGóÉÆßfrÄp¾*ñ¤ÐALÚ?³0 —‹ÚÅÕå>\ìó¸àÀ½;ˆò ^EthMÚFÈ/ÚùØL©É®étj£¡‚t?d³Qfb/¾¬€;ŧÞoz`ìæ Muyu’ØœÌö~ûr‰±¢ fœÁÎY_¨šõ]~k]òؽwMiiEÖ¥BÈ÷‡O_OºþgÉ¡˜âÄîN„Ãôo¼_Tß´¬í¬èðB³Jû1ͨEPLÏúVqfw(ý"™¯¢£VCÿmwÎ’ªÆ CÛñ:œq‘¼aå| úÜ!·…~îêp0ÃÚϽ곮«È"ã­™47>ŠOÈþEŸÓøšómUuv}Yá¼”‚ 2¿0g]pp²b0š+ Á‹!(ÑÖ>U6A¬xŸk¨—{ÁÎtwÝ+v>eXIÔláMÄXF¶îOÜ©}œÖAßç®rk·ÔB›ŠäøGyTÄ‹D‚hûµyn­Ùy­¿ƒþ—äiÜ  ‚;Óþ|±%(‹ÚR¢éÇïFB\*qc‹ÊÌB~VÀ#)oúÞ!V„¥1Ñ&óY€`ÀéîÝi/Ðë*ó›}´¢W±7ÿ4}x$w «bÈ$ÉKEï§ì@xìÊ/“lÆ÷^â>ù9eú˪W©Ð£H³ÂÞiÚŽg²æî‰ý˜ÇÕ ‰zMÅÈŽˆ9.h…¯ÖĹ²^”©@Y^¼õO Ù/a±è`}`È£—4 Î'ðÕ”åŠâ{!ÿ¦êGë9E"çm™—,°x^¤ ã}½ÄM©Á¦Þ› Ëž Ç'd1$&(Õ½¿ ×Ùðýd¥%‰å%œâ f†e° ¾[:µŽÅ;ûŽkÝ„v6½··ÑÑ”è€9lM4P| ¥“ÜöX]! þƒâ{–¥ÉòÄ.S¨ö¯¦xŒ£*‹Ÿ)© ˆöM.w-$cºùûU2;3]~n•AŸYCqéô›¿ª'_j˜OÝë„×Ñ9Ϻ3oM–]@Ñà4: (FÕȬ¢NÇdáÒ:+¯üxðÝïµåô½ÔÚ·'žL·Us|\ Èp¥#š‰(Ç·šw/ ÿãÍòáëDþò9êu8fSIL9”5úŒã€þü.àñípÒE.jžMôd„ðšJÔê×ÈZ;—×Ó´ÓíÏH…ßf›'÷~âãá-&M]ši—þäƒü$¥¢ü¢"gFð±2UÅ::Ðdô]3ËÙ‘f5×Òúo"Õe¾¸‡aÃO”ÖwV#Õ#(‘Ϛؙü§a?³­wR´+2ªÃ–Ø—G€éOÕ´ª6¨XÏ+;Äκh Y¢¿J¥A8 ¹"E†!¼ê6Ô‘î~$šoýZJô›(ÑÏë#/ÐhAóÑBA„*у #/ÎRžaVg¨šÓ@D A$ïïÚ¹(-GÙ¥q¹íÎЕvTÏÓ|ÕÖðeüa_¡ë³)Ï_mÞºŸºG¬¸sMùÂ(€†âm‡Ç?—¿kŒ¹³= sÝ5töú²ÿ½“Äk‘FWL€{°JxÈ`8áõ¤ÖãíµS ‹Ð‘ë†îƒÛɪ­©çü·àGDq2K]Gôš¦ÇHÒ3_¯¾åòi…!c¥†ã‰"©F´¶JŸËÌÉ8Ë$Ê>þ—DXd«HÅëÄk7"M9¥­Aoy™u¸9xÈðVs»&Fw!·‹gb&l ›÷ x¹Àèî–nZ«‡ÿôªÎóøh4Az£î÷ªÚ‡å)É8q-½[U\ÔÿI»à-']PFrÑÏëêd1űo‰+ 4çjR;ü‡}ø]û!ñË+§¼Tuu¬s³Éò3p½¶–pEÊÐTá}tÀga±oâ9»ß‚ÉÐŒq~H»ºç>n/gز¨¡3î¢;‘…ˆå°sõÄ¢+€Nä¾­Û5Y†:´|D BϨšÜ^ßÈ©/M?Ïôpy|TÞðüì¯5ƒÕî#ûI§P2Œ§óÚEÔ¸ã¦G>f â÷ö³³-Pï¡=Iºv¯(à±MšÍ:¼}ÓócØz”%íÈâÑ8[y‘4˜E¢IÍ%‡ ©±ÃobuN&K‡J·ýzî«®PÓKÍ Á!h%†Ùò&ºç2£Œ’Îÿ±þ^|4NTêòòð`cåÙZ;R‚Ü…!qxÍcݱC•â¾péü[Œ_óĈq£H_Í`e'ƒ÷èˆé-$ü«ø´ùCÆDhLÎ ·Ü¥óK¢ûļq‡RËáùa†Øy0Gå\Ó’¥g—‡ ßGRÎöé—û«×Âïý”Íó\ósP¸ßkÝ£DI–nv|D£ÇD1ÔÃw#©j=.¢~©I/§žÏâ¦&}_›¥¾§(ŠÌZ¿Œ½€–ÇœLËÜF€òÙÄÁùû&æÎÕõ7A\ wAÜ(ÙMÒU=>ù»R+ÛOoÎU<1ïãz»*•n=dFºJö(ý&»&|Yz/ÕÔÎ|óG~*h»Ì0sù´?NEÙf¶ºä¿ŒMyP.3æ=hPž@1£Ònå…º3u÷Úz.²S¢ÄIêD±R>h& b?QãCIè,æ¿í>‹ÿ†T4/›½êøñ±/êÉ ™ñ‚|$”ÌrÌý“§1i “ÜÖû†œ­ˆ·àNî÷Eì½Æ}˵:]/ÏÆGü”H‚nÑךÌ.²FΕ’Öo¨‚†‹Ã„èÊóR„ ¯Å§¦,ß Âç_Ã¥=ïf›ÊžÌY¹8íàº*‰F&mr¥ ­½Â, boø’üîßV:òŠà]–}Á^á]+‰’ëæ@âC ˜Š{½Aî›Ûã>]Â,¾9™ –&@N»*¹!G¾2:`ôÞ¼å^)•’fØ®´ ‹ì»ýäñï‚ä§šE…øÆc£/BQ_©SV¤{´ÕhïŠåöHINÀ‹±Š”QBò)’n 7×^RÖëgXèÕRµRºÍqFIeÏL³Ç\¾÷<1./Þ´}ëÕ1¬{è%á½ÜI(éðð€çZ¯³&:rYQëwù©´6+øR–|Ž“¯MÚ5Rfj-W´kø•¡¿‘­â×—8Aßé/·[ É½ªÊ—Hi §($®ãîj¾¯¾­LûA…æ.ßñ.z£ïC´Í–B0 lÜÆÁùÛÞÑ¡t™„”ò« ,/χ†x– ©—5ÂÈLÇ|å„QF¿1cSì½ÏUXçv…à±™;K>á!WSG $r†\sá(F±%ŽÓ /?UŒÊ †ûàß0pcï¨Î˼½&Ü{N5Û¹±á.YÛþ¸R®_%ÁëÔ^Ô_§cˆÞ9$v´zÈUÝiùK—€w¨á Ø2R¿ú0 kæ w®ÕÞ›#øë–ò3Öä?¥’)ø{³ô$¥—t€qÐ=—XÊé†|IaÆ©~Ķ3´:½MÙr|è&2È9ÑiÿXðûº–ïæù{ˆ{]^çÝeÆV*¶uxÄYéÔLÒYdíž&|÷X¨G?º†Êöþ›Š‰àùîb•†QÝ€öÅO*úþ8’ðéÒÝáë‹è5Á>d_ {ưH¸Ì÷ª¨ÜG%¿=¬ÒÃ\ü³¼/—p?g=rÖàß¹ãù=r#žÌ t‘Þ6Mƒ‹–c"I¶ßÉ› ×!;0W¶ɽCÀž¨ña#u¦ÄFª&9 }ÃÏNz b–zoG'H´DmýÄt¨å´Y,¿Z?µÙ<笗W¬¿Æ¢#@*XGX‚ùé²WŽC+$ò5­=n~ÿ•…—C EKQÓîķʬä¾Â±åí²³¶ÐFÀ“¥´ºÅ\¼ï Ô+SÁ7Çý·_ãú6#ÚÈÝ>hu„»¸›=×µ¤+;+‰ïû]9ø&zí¡æ&±s«ŒûÔ%G½Óé¡”HwMB |¸á´÷: ¼ež>©LouOaeÕ@äâ’á˜è\z‰i ·Ô–¯Nµâ Ú¦´~º:[Å^ÆÌ†O¤‘Ÿ§´×ôÂ\gÕòJý–X'ˆC\…Ë„kù䢠ƒ‡÷´ë(B¢…­-§DŒ´GvÄ ‡FÏ Nq†ëx–éÌI¼³5(ÀÈ?t-6j1±LãûÜâ9dAÿþÚÊšRóVS›ªÛ.’\¹ÈÌ,>ÉãpêÆBëùÆ­ksÒöX(ÜO2¥¾jù‚QY,Ò×Э7ÛŸ6ÓÔ!؜ӡâßœãÒSÍý¥ÖF¸›»*Ø6Ñü:·7,µqÜʧÊeeäÆÖí5[yI.΢%‘˜}ÆÉUþ"²É(\zÍ—R6¹ê@Wƒ „Z^©¾KM>ào½å­E?…Dà úåùhÎP…DÒ¶û ÐÏJ’=µ¡$ÍŽw®ûuÓ‹zWì—Ká·Vuç3Jp~è ¾«°‡è¿~5vÌ•"@1Öê^¡T˜ ‘0šñr´ ,E ‘|_"†æj©AîÜj™“>_f]M +duÕ§ÝŰ´ùÿB%)NõŠ,ô#îHÔµ˜ÚnölËO•‹°OOÆ~Ã]ØG®ø=ÊÞjN‰¬²£¾žÂi"HõË¥¿ó¬<òg–UvjD±Y‘èÑ T¡ðÉÀ6D8Ñô™)à¿…šâ.a>’£úd%Sô-€_´@×_0­] ½W¥\>MIÏ¿<Aø¿h”U _eÉDîYU$r¦›}®l_»Žå³Na·þ~½·l QKʽ•¥*Ëþ•í½¡-|Άpž¦^gy0H©|±s[óàÛ!TA\Þõ‰î¤ômÑ™'ÃõtÏùÃìÔ”à¾qòo¥«^loÞFy Ǫ§Ÿ€ËIMù…ÚßH.g,~›‚í¹%néÜçdÑhjúñ"Ó¶LïCWhût…Ë+º›åˆ—^þõ³]É[Å{žjç{×^ÌME“^¦ãf7‘Ù—ÕÒj7´n¹»Ã¢ßó5oNäòº f{enV·GRÄ ·­=ð‡„Àðî÷é TU_Áõå’R+!ÿ‚[PŒ=j ïBu©$1šE@ãhäÐ*¶_|¨”­y'ýí¼{þÓG¶Êd/º¥µsá-@±nÒ|€m SÝ“¿K"b=Ák¦½À);É%Kp¥_6¤¶L†ÑÛ™3etúÇ Ôðë¢fÈÈœý|+‰ ®™š¬ãe[>ž|âEw(yÃâÉùì°Žäû¦—P¬ÇóŒ õÉÚ‘õo^´µŸ9ËúBeiÕ=^k1ÝäÜ­WU-íž²Ÿr l‡r‘Eq·?ç”(¬¢LU¯¾B[ŠSˆtÉf»P˜ 4¥lò/ÁVj¢¼©5Ù\vÞÝå¢WíÕÒoœ!1’~‹Æ#å¹gøQpàXPˆûÐùkÝFÄ*c““?B—5¤cp²¦ñ{õôKŠ SÃì6É1ãÉP ê6âÝ-Ÿ”‹ºßJ?# “™lO(ÏÂ¥¨äs†f˜Œ{¼ùË^F#(ß¡„ŵÍ0ó“SéE¾Ð+’„¤ÔfÎCþ$á^¸öP2YÓD§Š ñ4ë~óÔ­m2 óm!€vO‰‹SÖ¬B¢±}"ô¸—Î’Ø+£|U"¤Ó% ?ô+éÀG%5 3Ç:íì[«¥ ³øA`ÛÈÃÒ±0;Õú@þr€÷t,ú•/— Enw—-ÂXŠ}P}‚|™Ï«ÍfnÞúN¸á‡ã7L¡Ãç&qnÙ!ëã jÊ1A7ªÝ/"!ݵžK¿ Fu30gÌ`F}†ßùþöùÒÂVÈ|õ>F¨ .n±iA'U_bDõZ^!Äîô]š—C]A@™ýêY×+x ¢"º˜§u­*ßei<ŒŒÕíže’°Vº‡ ì=—²,}ÈíkZÁbÒ#6LiŒkdå¦ T„håÚvCwþ÷ÄçªFFÇ«ÜCÙyv¬ü{qGi ä'åȽ~ƒ"Eä“%h2 ×1¿c´„±Ó>‡Ôhæø„÷º¯2•„¢T, )Í9þJPäzúô:f»•¿½X¶Î0Žx‘h™¡ÅÒMÇ”î&ì¥QÇ'×C=¤ôî41›8耲,ZDU—ß­à$Ù¢Õyaä,%—Z´æFLcx\QÔüñæŠ>㎕ª GÌ›ûþ#!yÞ endstream endobj 3402 0 obj << /Type /FontDescriptor /FontName /BVUDZH+CMR9 /Flags 4 /FontBBox [-39 -250 1036 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 74 /XHeight 431 /CharSet (/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/a/b/c/comma/d/e/eight/equal/exclam/f/ff/fi/five/four/g/h/hyphen/i/j/k/l/m/n/nine/o/one/p/parenleft/parenright/period/q/question/quoteleft/quoteright/r/s/seven/six/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 3401 0 R >> endobj 3403 0 obj << /Length1 1181 /Length2 6561 /Length3 0 /Length 7285 /Filter /FlateDecode >> stream xÚ­“e\”ÝÚ· QRºFzè!¤CBPB†a†º¤A`è–”îFé–F¤Kâá¾÷³÷í»Ÿ¯ïïú2Ç:ÿk]Çœë¼XžjépƒÌfÐ;'n~~q€œºŽ?€Ÿ‡—…E ;Ávò`'¨8€ÿÙ3~ÈÙ p_â¸äöîH¸…¥€]øWH²…"á°@ìd µ½?¶è p¨“;dcÐþk‡#@êEº@ÍypùùæpˆÀ j·ÃåýËHÙ†ˆþkÙÜÙþß%(Òñ^ À~/ Ü+š#ìlÜæP.¯âþ]Ð{“ÿRÿ}ø g °í_ÇÿÝ¥ÿSÛÂmÜÿ7°µwv‚"ês(Òî¿£úÐÉ©CÍáζÿ]UvÛÀ! ; (€ûÈ¿–áŽ/ànPs-¸ÄÛ8Bÿ^‡Ú™ÿ·È}óþÖàUÓÕ)krþï­þ]ÔÃíœtÝí¡¾Ò3ÿ?|ß#$Ü `ÈÇÃÇǼþýËø¿^¦`A˜ÃíîÇBXF"Áî¸÷óqOÂO~ÜÎꀺÝóòØ!œî·îã €!¸]ª¨(€Wý¯¥¿IL Àkð=ð¾þÝß!/øºOšýC÷IȈŸÀkþòx¡ €öþEð?ª‚^‹?PÀkù¾'w{K¨Ý‰ûµ?÷ß‹Ùü÷f¶ÿàý-ðþ±÷~êyÿœ~ŸEØýaú—›ýx¯æðÞ«!ÿÀ{Çκ ØÑò€€×é¼O8ÿ÷Þ.ཋëMº÷vûï½ÝÿÆÿ;y²²7On·€0ß_ÿA *Ìçýÿ!ÎH$ÔÎéïOû~~ÿÍ0øýÄC¡nPîì4"d•TRì£7V‚t¤K) j ®M‘àÙ]” ùŠlÕ…Ò[Á?¡~ª–ñšÃ„—©ëA^½ž:¼Á߈{ È€9©:~AvL0ú²¾tÚf„mÎ2ü°oàü5ÇtºäÒ†U¡¶Í/šKý3üAñÌôͱµïðò,^²9Ó: ×8«E-újk)vðjO‘‡˜Íï£4J=%½¥îZ˜°þNò,"Ks*åù5Ð ¶2ŒËŸfÍ0klúŠÃü+žeöë¦üñeRq¦M‡……ðî°å›Ò8Yì¹ÛÞˆZšk^º§)D­'OÌÜÙ5ÎÐê“\È?… yñ¹IjW¶I Kq¬éކÖ¸Z1öºôf×}4Z¹ýêšèF&´ËxX0ýp’¸%“Öô¾Ýk–hhZ;Rù4ê‹»‘f†ï)U©qÔ¹x(þÙù°¦¥ó\ÂM—¤‘Óâ.;´BŸŠ“‘ïòˆÔÁoÀ p¶ºñîA›Íعê{ƒÞ&³ÙºémúÁ£Eâוëéóe¨é¾¾æ*Q3íq|B©M"ydÔ¤>G·B!ÞùC2ÅUúµîv¦¥g]ã5†²ÃÚImmÖýš^_6è¿øhZ _ÝÎ>TüQGãP5áõa½$ó‰ŸßÆ\ÿ#âý /™à¬báªDæò@Hä*0©õN^€ívɻڻÛ8ì7‰œq68Õè]E¯DXî’‰‹—¡Žu/…G.¾@«~ŽúFª7j7â˜76\ËþØ‚æ$º¦õ(eÉwÒW í'Êp;‹§©³«Gþ&Q{ì{vr±ªÄ¡Ë)ñÈÊó†_W?½ëÊF£ÑN=mOoPvàÀšrÞø©7(úªDž ú [ÖžsŽ8òpäRU³_eŸ­èn4}ƒ6ísù“At¡ä=B­ä2¨rk¢Áµó‰zJ5þÃøñ…<¶Ù•îäÙ6_&eËbÌ5Cëm ¿7GH¯ç‚;+û/ep\¢‹’ÅvsݨNpŸ+qùF¶½”f~Lõg¿C»w2Ï&ØNØD²9uç`hëº ž·ƒ ‚Ų³ž«ìeœ$(FZÜ8½þ8Ãäq´ˆ"0Žò[Wñ(ø¼ï&w‘}“¹þªk¨­ygÿú¨Ôý†â› Ã^|/¤½3A*Ú‚‰-ަ±Yü8D,ÁW¬åmv§ ´ŸÆŒ!9øÔã\–|Þ“ëRÇξU7Â;xâJDDFKMIÈðöYjÙÔ¥ä´G :~ Äõ’R’+åi¯cñÊP@Â@…Etv뤄î-Ï‚ºê—™›%+k¹½™ð`¯òZuH;R·Æo]'iÎaóª1¤Ü/Üdz"y!k|ùÝœø]#ý6N9NÐlö¸¡Æs*.]Oq– HmCv6_éÐ2FˆôOù®Vo<¡ ú•Å›ÝC‚† ö0ÌXkþiõ>À RUÔ9Äø{îcHSO´NÑQ?¤|„(½£h CaÙÇîëÄ÷í¦=ÜË'¼‹\g3UÂÞÛñ¾lïu¸ˆOKÿ(ZêUÀt ªyoé1H1(=ò5QEi雸­h¬Ó˜Ëæ{_zÖ ÚkÍ6W‰WŠaÚA§W6 Äàг…0k_â¬ÄHöôÞÕWÍ3Ÿ#“û,9—£fÂQ »;N–^IÄÛÍ/ ªð°plM~øŽ¤´R×¾œ8¥Y¢Ÿ 4GÙî§žLŽ)·ÐT¢‹‹½¼äKîô>{ëKÍ<Õ¸¢¤cÿö½·NHÉzkŒ°Â…ÓÚ!S Iíä¡ ^2$çôò¹?ƒu™‡|ËmS?ˆêWXùºV¸”/FMr#ä›<à 8©½0ªÞð$o·‰ Ÿ ²SÙË›û²é×dâÒjzg‘ªôV½Û—óV4Ëcÿ]··€8r¬D&¸RÏÇQ÷ªR\Æ…ÎüôH爫qlÁqØ^Wç˜)Ix%½ B|K¤‹EbVcÖ^Ú¥,yÙ‰óõð}’‘›-Y[Á¯ Æá†ÝßÑD òçùêå¢7òg¿0Α¤íÔ;´}]«ÍßÐf ˆb¸-ŸD—&a– Ý=Wˆù¹@‡÷HïGÓ‘Œ`½¡iETâ~„7.£wùÀœoú›rì …Y”¦ Ýx1fËí.Z¼ånܲ†:ä•›—±xGÙ>gÙb›ºp= +¼í¡Ÿ:#ê[Ëp¦Ïu¦˜¢Lu²ðœï f<•kX¦ tÛ¢íiY¼É{\5Ï*—5G¼?¢IW ŸÄJáœÖƒX]<×Ãæ½*ªN—Cš»ÌêÅüøH¬}šîߌAîqJ£7ØùDçV¢?«ä[»ƒSÁ¦`;Ø‹úz¢êÖÚbh6ž ¡‰cAå8³·Äh©<( ”ò[ÿ\&0žð„™îogÌ«ckõ;—{è–yøŸVñÐca ªeì½_ íûåðaù–îÁðÛƒ“³]ï-© *Ûpö&qZgDŸLÅ£–¡j¹B‰£Î- Žñ8›ŒªŸy¨d7®æ ¬æÔ<ó#vxŒ¿¢Þ½,á|Š•ë>w²5ÍŒÁîQ2‚|Ë+ùd1º>,òs+ØË¬Ž§ о¨ÓÂsÃzíÌÔb倛sÖh- GÜ÷ùˆ~K~ÿp^x½ÎÓ`Ÿ -üÝ]ñÉôs8 ¸8C1§³ÍªÌG‘5¸Úä¶Žf&ðØ*í‹ÿs•=I-Åó(òDвãŽ2Ê“y®áB¸—xÈ6:÷]ÍhSÓd¿ ”Ÿ½¸mUã;›8³{#fpìL ÅÒ•‰¦uQ}za3ÖȦ-)PjËEOo,žÜs¦VÕÿMA", Šî%O#Ì9Û9í%‹k>¨:»!šî­B½³îl«Þ3^Áü¦Ü+¹(ë}Û÷Îxˆ¬$D'P™™FŸÛí¨'’ú.!€Ã Ý ãàeŒ:~ pØÁçeÚÀ~­–"º‰výÄ€$•Ãçáql€-Ô{uiŠÏAë¢+Z<l”Ëá\ÌðP[m,–p¢#¥ú“ù{8¯U]U’{é_œ É w¼?¬j‚º¨YîbÏ-;ÊN±Ÿi阨âž ‰lÕÛEZ06pÈ©]“a&ÆöåFiIú`~sT+@?¢FRºÕŽÎ| Ì:s®³ÈΔbV‹Þ Ííà¿æ–Ñ·Tå’Ó»Lê§ôøåÁü§6÷7vÖphkM{³6B¹ºX›+D[—|,Š¥ì‡ùwÀMâiëê“Q@Fc…™˜5ÃlÐ@ô{ï&q”ì±CQ\X€]Òõ!¤¬©æ­^ç#j1ÈAñ'"³ÔtƒobÇ9 êÚ§ÉÆò ð‡;åô‡\© lEo}‘»Îª:4—¡‡ãIF”4YfLÏ}¤ £lµÚ9ZÇD›= YI˜t΂vÿ¦f×4%;i•G~’¦`›‹yw·…ñƫ̠‹Õμ×eÅßÒÐ©Ö ›Ðžx¦õ­¯‰ÝáG ûM.T)yDÀï,MSý&ºI.-6L†R\¨xSM*.—ª£$¯Ü%ßb=p$otqìêÜFMFîT¦ÈÆ}"ùݯÏÅŠCS±ë÷”Ž]ÀaäYäÉËv¸L´°&DD±|7ÿòDíy{|Ò{”ÇQ©™­6›=ö¶íñ!t±éP³iyoÊËÔŸ”©ú€Z#'÷Á‚¬œb‘ÍÔCËd'e­¥G±\å‘++J7lX/O´}êÙR õ~8x/¬ìÔ1*ô®lÃîº91k®«¸ó)–ßu3ÙcÄß ý¬t›¼øa}É3ýp{ åX÷ø.E®‚ê#rÆ5¥ã‰ýÀ׿ÀÛ‚«õ°¦w4j²‚õ!Õ'P¼ xqš²Ø.$=,P=­vÓÍtÓ~T(.Ž¥QTLS"@rˆ³ø +à–rüJº,AÑ *­ÀW\;pÑ:soKðn ýYiz;Þ™É)Nëgqñ¨%_½;^Îi[¢ÞÓœLk2Å¥›Š"Â’ 6—R=|ZŠ•H#®n`˜IÑ=Ì$ŠþÎ÷°ƒ O«[þ~ÖÆŒ!YÜ„{|2®Y>w|±êÔPþY¡¸ÅXØ0™ªÔ4Ë †GlEÖÆ%ž7ON™¿•Z4¥YlQÄ"‰Ɉ«8„ÇÉx®«Ã{²_i¯™•lðj§|?æd{ÎAñ¥Rò,¸$†Öà˜Ñ%ÑC˜äëDgqÑÖMô/lš?ñO dÌ`0.ÌS¿ÜcYùòñÕFsFÉ!nþ&‡½£µG6̈ àÏâËV'J„§öŒ”Napí>Æ;æ ÏÖÓ/[’¤o| ïO,fZÓ&Tº«ç¯Ÿ¸¤§lUpåTû}ÿ4÷±qÁoè×þÄÕ¥ZùEç¦Æcm®Ûhž÷ÅâR@OÉÀ5Dë:•g.)}•}*³_‰ÆwÐCßTµ|D¯Ÿ †é¿"‰]Ó¤*­o`˜¥Ç7n= ƘÃ6ŒÍî Í&þLàk°˜B-ŽN4GfSY»ƒ0“@FÞñ|x!õ…ï”ÃiJ½³ÐŒØüë¯üzÊM7ì“ÍÁyd¤ŠÖ äo¨ïš/e%é°F^°z'ÁŸùœ@{]š?ñ/Ü!ÄŽuä ‡6«€t¤=Q·‘)*ŸºË*ÔÏ §tì‹» (¹(w¹Îxõ;t%/ÑPYæÝsãf®mÛ©<·©Ehp«Q¬ÌºšMùÝš£i¾êãhÀÁ]á”ÐÃÛóUV’´²º­û§]âî‡Ë߇"U>t3€¨k3(㨀HýõFwû;“è:‰Þ¶`ò˜@9ÇZ~#FG4þÇçÔäßV¸/š%S¢})òT°2Cäj/xxêm‹™€kså1ö¥ÚØ%*º¢I£y1â×g2¶÷tËØx*gZ1]°}ʪ-¯Í{bM&#û¨‡j(:k¯´/K[^N ö»VœÚ%Kñœn§Ñ x÷Æ¿Ò}…ê‰H6Óèe‹^†œ +¢ðNý¹Ù´°‡Dnú¾!é(sÉF©~ZåËèÏ›^ÝC^¦´©âÕ¸‚;íô¯ßþÞ?:ÝF{é4¿-F˜­rñä^Èp$¶DÛum¢H·ÈE‡n*Չ̬Âsà1®—…ꀲ¶º/1\WmÝTõ%mÔt( &^˜Jôxùã“ h¼“`Ž~!•ìö!Á›-!û8 WÈ[ßî²ðwY=¡CÍÑ’¢ßfðe¹Úï–9xý^áx-Ï6@š¦Œ–ÿ}"7oˆïøÙ’Ö5J$)…vŽ;ƒžüÙ÷ymÝà(T«ÄÄwa4KÿÞ—<ÕàLIø¼Õú˜šõ~ˆ0žÞ’Ÿ+]QÙmÙÚÆŠ$"£ ”1v«á±I# çÏ›á.›^iû€ÙAê.úh•v7·íÊ|:Nd_æZº_d9}zƨþcHZ‚×ð“=×݆ò2¤ _¬Ú?ä4á:$.<ƒ99+L §ZJ#ß¡ûõ—ˆÛtRBYèõ§­gçÁ€4ò—}A(ðó„ÒДۻø¼ò…ê\`ZüS c×BböEn«7µM‘k4èfŽó³-äzÇ•—+ì´Á™‹d£âOøÖÒÞè¦4 bƒ¿€Éèoh,ræÃd#>“©­ˆ%¬k_ïë=™—sÖô_*ʧQ¦Q†Qf×­è¼"hÏØÛ0Ø·RóoåÆ”Þ©vø0ƒ€ââÉo+%ª5LJ 2k?B³ïøLDBÅ´÷—–G;¸5ó¢XùrÆÖCgYýȵN•d¦§o8”_1'tÑöàá ìþÂìçMïOmËl0¶ê^ªüô%¹Ì[e˜yÏ|Ú ‰'üÈb^¼®ð â,á&Îb?3¥;Ç"ê[¶ÆÚŠFUíÇî);ü$ < éÜF—kì loÀùÁ [¥W}6”ïÁKƒAœŸ˜{æŽ/¥¸3›Ëåq€B»\¹JÔô3ŒÛ=Bî® ¥¾%>Xì*û™gm=ÀÑ'¾Ñ«2ÄØôRbÍv”k% ̰Ú¾Z<»Z¸zê4kó‘9÷êmK$OÛíyۊჅÚj!\ŒKPÞàSV§»ìaÂa£¯¹æ`frJS4™NVÈb&'À.5ze\:ìcµÅV¤µe^!Ãéð7fé8e~f?ÏêÜ¢lôÃr™µPJö(ºŒ—sî~U pÌ.F&c¢‹Â{y0h¿ZCC«EßOko‹£}9‹Wu#ÖR$K=>}ô«»beÜó呯Äiý`¦ÈºÃ³ÌX‹iTš3 Ü…ÆÐ}ðÔ…”MnT½‡ÎïÉÅ:g«5-¤×ô; öiôgxD¦£äÑù·šæ0“­8Dž/÷Jsžj»kœê×7±‡ÓteS||8R¸§QJi`i|èÈ>÷)‹öÜÓÇÇ( ÃF}† '±3«ƒªVb_ Ü'c²ÍÆ8¯R_[Ò:ŽkÔ”ê[m2 wFÛ¯4¿ÑëT®&3½”n¶q¬3^ü,ÂÓJ­,ZüšÝ³É6:ú&ïgn[„ØI† A„ü“I”‘„‚«ñòï‹"ìþÏWÞ<¢p$VñÓº{•€>scÏíY:´-{Ìti]O‰Â“˜Nb2͘z,pÌ17*Ý5U¶Ëã»Õ±zar^¼ÔžáÔ*ÓÕmr…u3IP-Ü"ºyžÄflϘ!ŒªzÎ+?XJŽî¶K6RJê ñÁø7®ŽªªEÆ&‚êm1N|F{ýŒU÷ëÐâO}fJ_›:$,ÅüðPjóµ·¢ °>ÿ|³™<@4òQ?“ehÖMœª ÉßЏÃH¦åH³gx`‰°%÷'|ŒáDñ`ú@¾‡lð1xTò3 I¼£+’u€CËëí l¿ Hcs†WïU‘aåÙ¨Òž2k.ÏCǦt®˜nG²ôeâÞÓrýâÌ$Þ;TìÉúª­qü/oöVèýzÕ5É´t7¨ööÉ&V}ß’Er«œ¥ð TW8 ~òöû‚°Hâ'|avjofÜŸøíšaí 3Ê“K2ŽŠæÿÀuí³®ÊPkKwDEÂfÖ$‹ÇÔ%Cü†·²§1ÂqDîØZÜŠèZP¿t'DúWOùòüº½êÊs¾¡*•>Ëœò6GÞ8õ~.·-´¡¢ü%ØQKsØ­g›¤I­ßIb©hèôš\Ý ƒ åÒk r¯*3'œFjQ7Ø7ôr½~M¢2x’ýéuè û ¾KÜjƒ²ë±Ámžm™DJwl¡Iš Q1—|K¹”ÌÙé§PZ¥ÎéÞþêAŸ#íóÄWÆTRª3c„° jÙ‰Õ‹*Ëh39r7IMà¤r$Ácv_‚2²Q½î^ø¼€OfÌÈs¦d×wAk4@0õ'/Q Eß—£y¸qBøÈׂœ–z„CNDô‘fQaæìšGÜKÜóÓÒ¥Lm¬Ïoÿp_T endstream endobj 3404 0 obj << /Type /FontDescriptor /FontName /LTWAIO+CMSL10 /Flags 4 /FontBBox [-62 -250 1123 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -9 /StemV 79 /XHeight 431 /CharSet (/M/X/Y/a/b/c/d/e/f/fi/g/h/hyphen/i/l/m/n/o/one/p/q/r/s/slash/t/u/v/w/x/y) /FontFile 3403 0 R >> endobj 3405 0 obj << /Length1 1570 /Length2 8669 /Length3 0 /Length 9564 /Filter /FlateDecode >> stream xÚ­”e\ÔíÖïARnQº»é’îš```è.éî‘Aº$Eénîi¤áÌÞûyn=û¼=Ÿyóÿ®ü­u]sѾR×d•Á,À²0{VN6N!€´Š¦²–'€“ƒ–VÚ lîÙ˘»€…œ‚‚œIW+ÜÏ'ÄÃ)ÄÃA †9x:A¬¬] ÒŒÿ âHÚ @s{€Š¹‹5Ø^hh€°‹'@ hü+àv;¹Alœœè°[Aì1Øÿ¥IÁÞàÿäêð¿.7°“3\€.’—‚ÙC= °%»* Þ WòÿCÔ—u…BUÍíþUþöôÿD˜ÛA žÿ³spu;T` °“ý‡ê‚ÿ#O ‚¸Úý·WÁÅ JÚ[AÁVA6¾ÿ˜!β0Hâ´¸8¹‚ÿmÛƒþ[|{ÿVÁ®®¯¬)£ÇüÏÁþÛ­n±wÑòt8þÄÿ›9ÿ0|MN€!'<þûß/ãÿj÷ÖAìá7ƒ—`îäd"pâxs ö °ì—ÌÎfs§à›ñXœ0þu®||v©™þCüvé?$`—ù‡ø9첈À.÷‡¸ì ^EåÁ«¨þ!A»Ú?$¯©þ‡àU4ÿO}n×µ×K5aHaïN´æwÂT]‘/µÊÌ{î埱R·ðßçÂ&ʼÄjdJxžP²9¥U©›Š0&—[æÓ3Tñ,'7(FÞžKšQL-èéõ§`D5u§7¦¢>¿xOüåów42Œ“_Ü&õíæÍÖŽ·¦ûõy6F>¼lhFš‚N³Ž?#>·@·)kÄlÐÃaùMA«³’›ÓðRoùƶØês¾_‡‡ˆªÔLuGµä£N,-m_°¿(g¼ˆ¼Ømúï.↚Née ƒÆíæk„t·Ü§Zú!ÿY¥—–5HDú×|¬¸ÁûCýüO]ç_Ú7,b. ¬æmóÂz4Xmºw÷š'ž–相ø¤ž5#a|~S½çƒñHr¿Ûkª–ÓX,ÍX4JÞ{À3ïŒ&I•ñóW 80\FgÕIXíÑwXe¶ÊfŒ@bh´U€…tà-•r¸-âXàSt·§¸}çJ=³ùvÎñÏñ JµqQ¨ “T¹’ÊË®#kœ6ƒz¿\S•M•À2‰ÈÏvJ—±7Vw= Þ­þˆ>(é\£¡ÆO'÷þ7Û‹{õg½ ä=.ö±nfoYV‹}¨v–˜¾Íjª#‰Ç¦ ƪb¸N…yáúÛÄzá6®–‘ }ØxøäÙðÊæUš8<a÷áªLƒ=š´ÿJÍ[û§?2Óðž¤è;$6T0Äb½Gb¹%ÇY±®³l#ÞwÈs»¦§³ó¦Šˆnw8ýµ¯âG ñëN.ö¢d6d­y‚BÛIF8QV÷”ä„ȱ‚-Ÿ¾ì vVH¨þZiXQÂMQc³Ï«xñ²Qèíehûi¡ ÝhÕÓ«@œu†÷·9¥ŒfX‘9ۤ债DÐJ˜Zëv㻨*tÚ;Ç ½^w X9°HUuîu¦ž/cM4ÃH© E­*!KvšuÖ÷aÊk: ós2Èw׉xŒêIÆÐz~V¿Ï ÛUP¡Š¤o—  Ç¨ÒÄÄÁ· ÀŒUhJƒ6Ò@[iéákB:>Wÿ\ë…г‘Ä›M#f“«“srÔxú ùª3 4¿ßO"2àÅì0{L Ÿf¶n¥¦ª$¾´Þýl¾”àQŸ5ÁbzÏ-¸ì0^ˆüåwÜû +ÃÔD+L~X"½ž_ÊÉx²ýóÂR³ódÚ©–gU•žlÑ4ס'ÖÙUÒÆgD7xˆ 4WÛg”U÷Cö톱ē_G°Ö=F×kD™ùÓVó?|¹ =–ëURÈ–¢«)È›÷V…PŽº%;¾Öe°2ލ¨’Œ®jüÚâ}tvsä÷N§ZÝ-¸Î'‹lô'IE´Ê7ç¹5cG`Ž 1Æ ;†î»»Ÿ~âý}½ »Þ@tb<îg5OÓA\Ìô?SØY†%Í“LlçèzÃè¶²®ÔZ‹[ðNVÊéÉž9ª†ØjB$NÙ>ÆD>ï6‹˜|Õ…RMMLt²Ð(F;hÞ¸gSä ûÂ{ä‡peg>éª /Úî[÷£ ¯ezd=:ô­F²'ÉÖ¦J«F—Öƒ”û‡äübþÃÜý&ˉUO¼£DUGòˆ7{gÐOËù„-„Íõ*\¬ÙÙY8‹„~.Eø¨‹]ŠØ‹`‡f²9Â^”`/U%Wô¹ýÂýEê\óæ{¢H+Ž¢åñD² =©yšÚŸ.?—ÿl s“J8vÓ‘£]á};bé&¶•Åu—z»@ó¸Í³3p~r¼«ÐN¨W fòÌôJX\¦§XxÉŠK@°µíü†ßÖìúk Æz¹Å£šRuá²:dex+ÿ½vЦ¦4&(¾´·/Ÿ`|àZû(½ÂyÞˆ,Fú™5a‡Ûç9BáL½l;Aäˆþå0ñp µNO™äw Зq„@¬^›eSÎÔ¸Ïbùº ÕisÚÄèJÕ­³¢¤$Úz£G;ŠA- óÛÎSÙ³Dm¥„ƒ”¼³¦»ÎabÀÏk%&k.–×qµ7'üê3•w+Š…ŠWí£*DÓ…]æÝ¨ØO?Å*":<&;À×Ãßµ5¦s…7tß5.S<£ ¡U”93ļE—ŠÁ½zûæFÞ¤'4þ%8ë…­f²óîâÛV OÑÖiœQ|£d— v»ÜœÝæ'»'[n˜Ñ@®ŽÍª›ù€GCB¡ÅÛ«…ªß·¶ žC\qF 6òìôß4ÀšxG2ðË87†kª}0¹goìüÞaÔ4¹€Ix¶‰ ¥~ñkibt‹G]úŸPЉIdÜ1rýL¤$¸ÍLI’ú1Äoèj_ä ˜Šú%ºæN³M†Þr¡œ°‡¨J,\jâv‘eej!ë= ÆÆîû&wm rcÃhLùØ^uØ’!adMw—©œ+Ú¿dqùXàilÕ‘)‚qV.鎘ù±^ÞÙs 6Å ´ )Sª8Iã$’^‘n×®W ùñͨi²¦AË–±È<êÑFê>~êLe²TÆ—ÁÑK<<¡¥˜­#ïSèÜ\ »ç_ôÛÀ9¼²@™Ó.rdß 0Za{ay]ë‰ô¤Ñ€¥¼»ãíîm¬¬§|·! ЭŒØz)*ÝEz/ò/ÆË3@N (’—ôÞ¡E»N°#3KaÿEtÁÇ\ÌTogîªï€’v¹Ô¹Â:Œ¬Å¶ö8|Üβå Ácm&YŒÉ¡€<Ï}†×£Ü$EI9çP·RÆ•1PÝíq 'ÊSûRHUtZ”?Ý€4é} n:j“g³vZZËëuáMjäÙ/ì³vœ.ÒY<ÚoýN&]"T»øTö, æubòé"dʵT=ŸÏvµ¯±ZþRÿÛïYx¹Âjîéó+fëšbG•£®C-ÇVA°ÐC¨~’OêDìjƒf™ë+Må&º&H³{7ªf7?ôˇ“äZ£N¨ƒ©æ°>,hˆj5mºÖ ¥è;ãV¹Ÿ@ÌáF íU´½c‚oTÌfØ‚/ï^í¢ÝÓ+.Žs3´̹ œs¯WÚâÇ8WU‘ìôž‚ 3bÞ)(næ­¿a}äâ>ŽÝÓ °ÚÛµHqv•N[ýÙP¿ûü¦8s„´:£ñ0UŽoUUÑ]>)_ ‰ t…ü:¦Š.Æè8k5´YIt—§¬(ŸZtwLnùk)Á+Ô@–rHrCa¼õù¸{ §y£ì¢XfƒV›¯š)‘…‘Âm½ïªB陕{ënëBC×¶X“ƒ[ûVmCáУlÛu¬;X𻥌Ó/¼-ü;alĶ4[­n”K}4ôZÕ¡¾Ûâw=3ã vç§ÅЗ %˜T ŒãiMµÅp7hàá(1‡X7°MKd´­ᚤ5øáü°¿ÃùÀu5úàvˆâï•IqòÝŸ›âæF´ôÇU½µ¯ ò!¬\Cñ˜JÇ2ån²)‹›öQ>ÏžOgÙAl3—°Ò†o‘·%w^Xc0–¤w#GïÓ?ÅãÐ3É·•{kV3NÆÿ`œ Â=pcŠ3t]>1ŒUé1meüPÆA‚';p ™ÅzUÐÉf¾È_ AZ{ún&¸šáˆ1Tépƒu¶ejD> í¦°¨×¶Ü­qœ`ý:DZq¼ ÞúZ+ö®^d–}Þ!2¬'^yu„=—K¹îR»­Ýaù:JԼЄÎ}„âþ’¬~Ä0ÔÎZëÒŠÐAÇùœ”z$aª(­üC$ ¸&èýÌqFoåIÊù)¡¦/Lsû µãÈUeþuqÝRS÷›åŽå cÓW©Ðž[û‹n¾â_€ züÕ<ùäàBV«Tnji¢ÑAa´G¼mªeÝPâÑômL¤»Q«'Ù˰ݬóñ’þé(TÂ|fAMü#ÌLÑWáv}&¢“· =,3'%RûŽüä»QÚçŠXBå9DC®! ‚ú"Zú Q„&„#„ÿŒÆð×~wzç‡þ[üüÅRSùCÖÖ:ö0^õ›ý› Ç%5ìdü Ô´`½@pTÕY¸bTÑ+…¼*ÖŽï[uoÖR¹þhªzÇ¥Ûp¿ÏbÈ–YWYh—îëoÙõŸ]õÆÄÝJÄÔbo­x™1Ç*IûZ™ÕÞðØ €Šgaƒ)­’e`–v‰üh ™Ø*k¢¯ ¿vŽÆ"»¯°_ɾ¬ ]ÛhwÛ2ºÕUE è w· 5!)R ‘kôñŒv°¤ÒœÇ7Yƒ©ê7N£ó:^h(&ÄV»(ÁŠoyÙµ{òýIûŽÊ¡®£ë÷­çö‘Cá0²aílð”Æ#³È›_JÝ%¸§¡g§zêûíÙ16ö$в:•ʆФÖúäÞá’S‰¤ì]>u9'Ïðg ÈÙ§†¤íaì׳nM<èJ‚/â&gýûs‰‡)‡¸&×S¥Xí¨Cú4¾%ùÜä÷߆¦”•%ü.g,[–3ú?ø’Hêo+9ÉOâ׺ lÑñì½\)¬S—uo_¿ˆðxèÏŸÇÝçN[sÚ„ZˆË¾?€mÚ¾Çñî?›¶M7ÌG¸iI–Ñ'Ó'Cw49+²á Ï÷D¨â«f¯ð³ô˜&b±’>Û0¶¡ƒŸ@¼ÑuU»ŠùÌhЄª<À˜‰×³Çߢƒæ›µ71òˆvÆÙí¬"‘D!NÙòJ“ODˆ'Ò{ԄѸ/•¶¾»“Z2õ{¦õ,en2ÌPzž}¶v謨³áYY‡å”yí™îëëå¡}VÕ6Ó,©ß{³i>­À&¥xÔe詊‹áé™M¬ªŽíˆOd«xD¹ë@œ^–QwrïÁ¹HܧpŠm˜ ^»ŒH¯B"º¬# >ðdyõTž.«¾!qîͽ¥Mx)uûÙÄ|±Óe±åÛ%wN(ÿ‡Z‘•;{`h&§m‹¢3;±O¦ÝE›}ƒ˜kß¡–IÙº6?Ñ[¨·b›P_ÍtOFûcÄý©±DkU3Ü<¢%g ÇÓq•k»^0Úé†[±´¸tk­£Ö¯¼M¦õyJt£–wÙhÚºaø¬ ÕcFÎeêÓaYw'±(u´¨ÎŸ>ü Ü×ΉñâX×â¥òÃàbÖ\«mÔù²•‘ŠÎÜÛ6üÐCdnE]|Þ³„ÃùmlÁãEDß…Uâ.ëdv«­D7…bV2ƒ”) òó¼Ó#`OûŠo`ùÁU>•écñ¨žûúãó‘8¤‹c£¶#ª\rà`/핦ÞN³›÷;1AaiiÅrÎòo–…:Sƒ”a ôѦ„Èä‰-âÄJÏ– ¦p»ÂÀnÌÙ¹o6©4|VÛkƒ¸Ôa#Bm×s÷ºì,Ç €*ù¢£ZnXÍ¢ónö*h_ΑВ,ù¦ü£Â)nÌÌK“q?Ù!þÎF³‹ùù™B÷‰mix@ Íà‡kä7*çéÐVç ÿø0¥6šÂÏÚš«µÆÛ'ǼCµ\¦…ÀÃňÕ'Œ–Þîj½ÂõïkÛk"*…i6cn¦æBÈã]ÂôeÅ[&ý6¢¦—ÎVÒ6fÜ‹W ƒñ9hCñâqtn²ˆcé }úu§7ÑDˆ µ¶G‘¿Ý. í¾B+’ £‹ÂÏ\Ûëε+ßÙ ô·ä¬Ê ª¸·;úô,.$ödbå:°f.hç&Þjæú¸“ÎýVäüjØU>äò¦9½y1qO³¥Û#e*¦¸ ÖnºÍ3~™C€tb¶´¿Äz8|{Ô´÷ùQ›<ÐÉ|ãž>.!ýwª¾iÊ`†¹@jm3Qþ *þÍùݺÌJ³¡„Fã9>WEÈF² GDzW Z&ªü³ƒ—ŸPMsJ2°fõ ãŠó¤:n>Ýà‹püuê£ÈýóñüÂ! ‡9¬|:)ñì¯Êwq|”,Œ`šQ™ÌKîYñâ/~›«1Ý®?Fx{  Fn—ó¨Æ9ÆÜtÇe_é* BDw¢Go÷¦Þû §eè0FÉÏ e¹´9Ÿj É';^ƒ„ ç HŒ(uz¶ïó0Fðä'çyD_s$+#䋦«opË/¹L£lÇ·¾ ŠûN‡¥4rØH%’ÏqŒQ_($ùf)(õ~J^øüÚY­û×e´2„> LA¡NÆŒCXádéš% ϲU×û°wÜvaþ†yä\1¯ÊÏÖ’ü‰V%@Ã~ "xü }›\Ç}cáà·Ç¾‚5°èJh5#gùõ5>¥¾¨¬˜-(`A¥oªÝÌJ ¢lCÀkÆì úä‹_]ÞòAŠJ›Ë7 gb v½ãÄÑ(ÈTƒ `ØöÙ#/Ï‘(ß]cN¾”KL‚ Ë®)ß[Ä\‡Rz,u‹0ƒ°\Ckg¸Ý qæò÷1 _’Ø1—ñ¢ê½òÐ2CÇ ÉñË ¢m?–âÚ ñ|Z¸‚\¶>õŒÍc±{ U_¢oyeæ,¾B O*Íÿ-þÒcÿüó[Ék;œêâ5Úùô1ã8ùGûöšâªu3{nLîçŸñ’3VQê*¦— Y‰†Ê«©Áá8oɹ9×ReÛ ƒPš¾P7õ¾TÆF+š±Ú&J=Ù=_Œ+¦¦]‹œ<(b¼_Þßm4ûE]òŒ¯™r;ðÌþÍK…l]!²¹CäWÝŽÑûËËîä‚Ê×b$âò±ü¤ä¸µaZ"64+‘ë—Õ¯W«=üÕS¾òP¾ÁäznMÐÖ!‘ÃÆ‚lå¾¾ŸzÓ]ö<Ç%ê@ˆÁØb¿%ct^:© tÔ]&µÖ`\z_Š4d)þhu(“îô(á–ÕÏÛ~Ži„¢ÒW‘ÁI[žþadg?žFyHÝKö°âéÖÏб~l~+sê„ãœSˆèºÑ‡2çEeðõÄÅ_Ó׸ˆÑ–Œîq`ÐÂ"lüªˆ.Éþ¶æÍ"Ø‘œ‹WJÒ2û©«¥“F±‰Åïhv•ÇÌ[ø‹7¸‘öÙήûSP]ùn¦û/=XE„:w²ï(ÇâWçˆìt7¿e´7uûÁ]C[÷¢¼Él;\^Þ¼Xìš„ž¶EkÍo}O[Åò6Ù(WÚl ü ÕŸökä%Å4šDõ¡‡Žtc÷¸éIxi ‡MÔûnâ,Ý•‹Aÿ—!—•ˆ:1û¹~öoù €-rRßЦJñ 9\>G¢ê·¤Ÿ[‰ø•Ôù›D»wr@Ä/K×½êBü3 W¬ì?n„ýÞÁ0EôsfÉ_LÇm¾ù%K©*ŸC»±îaVS‰÷‰XEùŒ"Os(|­Â£ ¥¦3¦héu½Û~ޏ”üX«³CG¡M@щƒö¹hcïýâbr{lBcÐÔ•©ygSª;QXöã3pšÑ )W´«O°,{~µ¼[´3 )å-Ïd£Û’fYwsKÝõÈÊdjT4OO¬•+x¾z”S(ºýçJE÷3qT£Ö8M–ÁÖ—'‡làJBðÉ5…s;T}9|-wý`±fò½&sÚÒ•øS2Úôþšeißy.<ò!”¯ôbÿ3×Á0=Žú1°–jÐ%bÞ¾éØ ƒºŽ]¶šñX峕ÌQä7V¼í(ü–ÞzŸf-y–))BK¨í»šsë€Q°¯ú—u.t²ˆë²Þ9Çú†Çãõht‚Ü“|ò.nïí(#ÄSHØïÒYQ‚¿Ô„¼ûÝà§w¯SAêKöƒ™ÿ0Ý%”0ö¹$m!Ý™KEÎ(ÐúFÖhðÒ‡Ë`U!­lê°@2ü®Ì ÁÄÏZÛÔ¾)õ{Fäªì Û‘ø\ñ%/%.«“u{ ‚Ô•HÊåNAT;4c_Z^Ðy¿ù·oMxývF"0"¹ÍØlñ’‚à–Ç3$c¹™ÛtŒ+põýÖÙœvñ-îp‹7MwAxk\PôÅûx§¨›”RçNe­ø–¨Ë-EV§Ñ‘Q“ ]†+tSLAC}­_ÒBì;Þá^œÕïd{ ±t<QWkøé(zYaÍÆÕã÷9 È3» Ú* —q™`¬“F«È 7­wø_¬ßC±¥H1Š a g›bø{v£v—è î¬Q×ôr†ï’‚&µoP:Žü(á ¬u§•¦c§Ê«¯U~†2Ý&½ŠNW¾&R©z+^£/jÈA k ÜàCJñ¤œ(Ï9ïÅ´u=Hëb2ÑÞ`x™¦ïu2Oª>Õ'cßdÄ¥ˆ£³£[0åH] ëúÔHÊRÈt;±{kƒÊ•Ç|QYW©dPuE^ËUñÒûy#Ï'²[IdN†V?oâñFyUuvŽû•ì^zƒÍî9®‚G³c áDòßx«8îž.\ú%Ç% J6›h¬Õ—.¹úoÙÒG M³—pp#9Ô“=Û(Éyqsò>DSQ>|£ÆÄ¤ukN0}o-×Gù8&v[º4tךzéX“Y¶O<ÌgºßÇäõ|-V3Ds‡i´âçŸ-ªZtqÝŒsP¢oæ”ã:ÿ?£[S‰ÜÅÔSòp^‹ê+Õ£ä–Þ‘cVJ2Bhõk½Ð[©¼™:?‰6JPñ;m7I9^^vá„*…*„sÁú=EEJJÄSF#“$º‚<ê—I'´ìç`r1⨇÷UîŽ:¬—ÚEÞÕ<ÛøN¦È„«‹¿>uÛ$ö/ÆX¾V@+Êê΃êÕßcðoÉkWÉù"¾ã5’¥ ' ÏùŸ:œ‹<£—oý¾ b‘UǂП¿~˜øšZ)è“DÕ¸óRj: Ù‹jRè|)ú˜äpx,‹­ýlLRE»5hÿ²¯—dÿ“mÒÕD/å×±)&¼§Ã þD¨“¿½äzV ƒßßk§Œç¤Ø“‰isÀ"µs„ªYy ùj{lKÒ4±7žQèòƶíLQÜ[÷_…ä¾'“âjòynåkQ«4!9×­—UC rØ7JÇ2ãÜ*´dØüóü5f bóFã½OÆ ?¡"5)šæ^9ŸIŸú¼<éË”i€(”ð´„1én(ØW¡‹÷´_–xÚ–þ,›Ëô$Ôõ&G°¸Òk0‡¥åøàªÇßþìÁ5¼êÃàˆvÔ+¥Q]`^$n5a¤ÖÚMíù¹]X鹡`¬JÛgσͷKx=ξ|.çÉaO(åè %èSù &¾%€ƒ?©†¯“|ž³kAAáäyýÀÛ÷j¬Íôâ©J’Ì9™wÄ‹6¶§“AýuØì".Q,ø w®Ì–Zk5d ]zŒÛÏÉBÎs†åxUv9Ûu@i#F˜EúËñýÄ«5 ëãæÛ†㪠ÁöäîÁ#䎼ß]ª9÷KŠ@BSW£¡TØÖÊ~(S‰ÑZî¿ g5Z –‘SÒoáŠyÜn&òé›ÙW4·véË`·@¾fÞ )öÊDŸ½z\ç·Ë²uDYŽÇ<½iÄ¿e—“+È×\ç>äB˾‘ØJ&}‰Š¨z¬ï¸9¥÷¦ìí†òvZ™Þ‚µKÎÑïíÜÊ ‹,šZ~å=Fm #˜’TÍöÞ!X EaÆ/㬚’ôE’–þݾ!/½ô lÁy”7ýQß"‘ñgϘ‚˜ìýF>´\¹_Ö Ñ0 ‘¨¨§pNw\”.ßK.uص¤YÏÜ}“üâp ÞϺºtµ§ÑKC¯òââsî®²Þ ú„û-‡Í_\+d2ÅÛÐ…\kSFlZÅ>ÞÇOjF=Iâ38Ð?¼t6©?Ͳ²ÉvàÊ/´Rs;Ôξm^ö¬$ o&±Ÿã©”–›„. ®9q ŒYIzl‹7ÏJfÏlÃn®.¢3äèxp3z´MQWzœ†Žï¶ob†gý‡mÇ™9ŒðÜ„‚0^¡ÉƒÇ]œŸo6éSk5óˆ—/£Ež9öe"Ql;I‰Ô&¢ dGÅθgMá<ôJ¹æ‰Ô£³dúˆÊi±òÕþØúnÃ8Y*Iã DÓžÊÇ¿úß@ä\߈Û(¬°/€êøì^¹ÅS±d-ñN°ðލqîºàGÉ÷¦òäú*L&Q»}h„ɹÊg²ó[=/ƒ “:…O§j†½±Åñ˜•ãât´"‡z¨ãÁhØÖO†â#ãËP„´ ©÷öT@ˆW€aUçåÐÀîç54Û·k›ý|P£ÓÓl“I‰5aC‡”wzØXAKȱ/šù5FFm2N¢Òo#„ÊÏtÁý†ê:L%¯eaks­È€|¤^êϯÉù=2†q÷¦þËÚ endstream endobj 3406 0 obj << /Type /FontDescriptor /FontName /PYLSDX+CMSLTT10 /Flags 4 /FontBBox [-20 -233 617 696] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle -9 /StemV 69 /XHeight 431 /CharSet (/B/C/D/F/G/I/M/N/O/P/S/X/Y/a/asterisk/b/bracketleft/bracketright/c/colon/d/e/f/five/four/g/h/hyphen/i/j/k/l/m/n/o/one/p/period/q/r/s/slash/t/three/two/u/underscore/v/w/x/y/z/zero) /FontFile 3405 0 R >> endobj 3407 0 obj << /Length1 873 /Length2 1240 /Length3 0 /Length 1833 /Filter /FlateDecode >> stream xÚ­R}´©áìOPÄᢢsTän•He!L@…hœ = B•ü?Dm^îÎdz‘C××o¸ô'œ 3¬Pv8âž,*ÄA6SBÄyBT8bÄ?b"ýZ¡õ憠q2>¡3AhVÐö \ Ì¡0!ÊúËø à\(Œ„s7öÐɉŲ$Ø–¶6è@Ð ‘ˆÂÿ!RÂ9ámDÁôõ°(öñÁY•ç®E»æ?,–Å),·–Œ÷ÉÕ“Dÿ ¦ }‰9>†t^ÁÄ•©š!Z_Sì/¨sní{¥œ\ÈS¿Q!Ê-<–K¬Ãöúj âD™Ê«faþٗξб«ã ]L2ú²oÁ(¦U)‡:æt<¿vi GQmÏáó{vi“ú~”ë—Þ¡)è}l0/‰ÉjùŠ2Óþô ‡·&×MdÖIsP Z ¿ÆÒ":;-|Fïv½ˆÔ¢¾ß~(¥îJ/qW‚É\“o!Q­õä>[NóQâ¤øÊâ·‡0uzNÍýã[^àÒbÝkõê¶Y1Þi·ZxejÐñV[nŽHv>öû©LX“Ó¾ý¶rév†žËÔ©°¢š¯–ü4ÅBìÊì€Ù‚šFÅžš/@õ}]}ÎiË—¼Ú¶‰žáo2%ŒÔIœæËië¶ž‡îC±¡RJ;øÖ'ð6F|ˆì¶ºM|÷å@r3› °+³›¤kvÒÿ‡L¡ 7Ï\k`×$æùHά¶‰/]Kò®ëK]ØGµº·õ­aA[3«iXEq¿äÁ™\×Ù[UoNOß‘ÞÓèC› Ê&?àÏä7´äl;<(ãXð®wD!ºÆaþƒ‘}¶²ý :©ÏâEÂâŠ2s»9JÏßÛƒåóF6ò"±ŸŸ#6¿j±wÿ ý˜:ÙK3˜ô•V¬ršùì£ìóÞRÅgGtÿ,vø¦ÈDö节þ¬6”¬$]çºøjsßxX+e²byoMœü>míï#E¿aR›|‡Ì·vû5¿úº½ËHNʘí}jÍ ˆfþç{ã ±ƒ§Ùêí‹‚DY^­¼¹Ú仪’i÷1QÔæ«Ým8—Ê¢2Is\FkœE Pœø05ÝÚÞðåmÝ›ñ‚3ÿ.ÞH³–›_^}MÒýÚÿ×¹Ò-§ƒF3i1CŽá+|ßÉIï~™“Õ`·gàÎ+fe÷õ·Œ½ÚûÍ!÷åZ™x¼WºñtyúÕy=pÜ>˜ž\k2H‘>¡øì²u†`8ŠD Õäâ¤ßgÉû%qMÿ¦»¥É¦~¢7­”©Ë±N§qh=+)rƒ‘KqÌ•÷ýÁEÙfµ§ÚsϘ™µ•Öu_ÉÍ„†vôvèŸgVÚ3 Ž‹¿Ö¿#ãBkÛ™4ܨx=ÙérÂ)ЇÝ$……ýd¨š¦¿8ÕeÚ‘¶J,kßN{æÔ-Âü¾·O­TãdËë(3­ßW ²cÙ÷·×Wå\¿¨Bïh¹fÙå Qu:`baå¬lÆÒxçù¸vá½'òÛkT*¦ÔìüÎë…©æ•Uÿ£0•<ü[H…Ö¯®ù>—}Žù»”›%¹kˆÿrn¼^~ÞSp#¤¸Z"þâÀMS“O†¶¶[ÍC↊-±Éz_šwx#«·ê„qºä” #‹Ž¶Jÿ¨<:•(7ø,»WUËkTª²inB£´ló´*ô—äåæGS^â²ja°A]7vŽ{çÜŠÑDéR¦ðçz×À÷‹TºÊ-Šú>Œò_Ÿþ»£&ÆýÆÁÅl‰ ×þñÏG<—Wƒo_ ›&ßéŽÖ϶•ºª„2&‹±(¬mš÷Ì",yöç æKŠköJF ݪuvžeìÊÖµÓÄÿgŽ\ endstream endobj 3408 0 obj << /Type /FontDescriptor /FontName /IKQYCT+CMSY10 /Flags 4 /FontBBox [-29 -960 1116 775] /Ascent 750 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 85 /XHeight 431 /CharSet (/angbracketleft/angbracketright/asteriskmath/bullet/circlecopyrt/minus) /FontFile 3407 0 R >> endobj 3409 0 obj << /Length1 1637 /Length2 12695 /Length3 0 /Length 13627 /Filter /FlateDecode >> stream xÚ­—e\›ÝÒ¯q×â ¸»ww)P48Á)îîRÜ¥¸»SܵxqwŠ;ž½ßw·gŸ¯ç—|¸¯™Y3ÿ™µ²’P*©2›Ø%lAN ,Œ,¼Qy5if #3³…¨ÐÐÉÂ$fèä°ðð°$€Fïïo^N^N €¨­›ƒ…™¹€Z”æŸ .€° ÐÁÂØ7t2Ú¼ç06´¨Ú[ÜÂÖÖ•V8T€Ž@  # ÀÄÂØ `4³!0ý£Idj àú·ÙÄÙî].@ÇwQêɤ¼‹4±Y»L€¦L ¶ïÕ€ïZþÈúïäÎÖÖ †6ÿ¤ÿפþ¿¡…µÛÿDØÚØ9;ò¶&@Їjÿ-Nhbálóß^i'Ck ca™5ÀÀÂÎÈÌþo»…£„…+ÐDÉÂÉØ`jhíü—2ùo%ïóû—&%)9Y5ºÿÙÚ9• -@Njnv@óŸè1Ë~’ƒ…+@‡ù}Ê,ïï¯ÿ}Òû¯bâ c[ €•ƒ`èà`è†ð~ˆÞ‰àÁ°™]@×wÅLŒ [§÷%€÷ÉxLmþÙWN“ð?¦'€Iäq˜Dÿ7€Iìñ˜ÄÿC\Ì&‰?Ä`’þCì&™?ôžSþ½çTøCï9ÿCÜï9•þ+€Iå½WPýCïÔþÐ{Gê轞æz¯ ýz?–L†è]‹Ñz4þq¼ûŒm­ßþÿZØÙÿ±ØØüYÏÂü.Øä/d0ÿƒlïŠß·ÁÚÐæ¯ˆ÷žLÿà{¼é_øÓâ¯à÷fá{}ó?jÞ{6w³3‚þŠx·ý½þ½Y«¿ð½#ë¿ð½Ý¿”½V¦¿Rý#ÍöO±÷X[ð/÷»T»?î÷3d÷þa·ýk,ïâíÿœÈèøÏõögàœÿm€Ö@S§?cãù뿯“? ßÛwø ß{uü³[ï‹6ÿ÷ޱ°¼Wø“‚ã½''sàŸ>8Þ›vújûׂ÷‘9ÿ…ï#sù ß«|ýk»ÞW»þ…ïéÝþÂ÷¹ÿÑ{&w Ã¿Ký¿w‡ˆˆ­«Ëû˜XßE½7Ëù>¯ÿ+ÒØÙÁrú×ý~ý/›Z¼ßZ@ +ÐaiÞÖ˜/Ð2¹1¸Ä[<ªšÆ‘0µ(p¬3¨>•ñxïìCÓ¤ø=ÝÒ¢ -éT¶‚ÉÄ”c¯QØsÐC•)h}“&7MöÜøX÷ ÄPö@ªMfØþÉŽ]Ýù2ùͺK't•Ü! WÞi8TÉÂüË•·•ÏøÆbŠ ùn‚^v›\"Pã`=vôñDÒ6ßvéûŽnÚ Æë^ÏêŒÕ r*OD¶<ä\ê§gxfWÓÍq–t+’%­,©·êú}TRÆa—y¥ÔEd®¢"û^4"ËKh ®ÒNQج“á2µú¯Œz#þS³åƒ×Lõ ¥Pù]2ó0'›Á,z/£ø?˜©ÆycgM‹FPìM&ÕëXgÙý¢fsG…FI¾˜áÑùcç,¾2?üÖù}Ó0† ›t£–(ÂÔªÞyص” %!ŸâÞ7ÃÕ÷ŒˆÎ¨>áÁåŸ/ÛÃøiG}©ê"K)Z´ù ÎÉOq fPöÇE®Þô‡d§½É@÷ˆ2¼?— É:, ½–oÔÈ.iG¾ÈË?vZ•€­"Êx•k5Â6•º¬9y6D¼øèŒé2ÊŠ€c@ã zž 74Ÿ^„¼§iÃå0…Ú!&â¶C×xŠoZôðsêZr°¸§]yµÆñêGùßÛfÕ7õ@,¾,D*“JÕ]^>&W¹þħ팕 Ò¯DÊp‘X\©a só_èD‘ÖIÉÇjõuåƒXì¬Xju£œèmiYÕÕ–+÷Pf¿†xáµÏD§5¸TÁùÙ¿€!,ðñkÞ©µÃw9xѱŠg¦r6õU/EŠÐ¢wNÜÙ*<£Œœ…9XŸªn›E9²3ü6¯üýêõ¤É÷\ÀSXЛtoÀZâ ´ùÑÃë€oÇæ2,(åí‹ua" •(m’·â,áªÁütšÖ£:èŠ9εÁ»Èxr¸ó„ÊB¬ãˆB3ì\x|óHôìW¢:Æ5ãê$O¥ -QÏŠŠ èDndK3¾ ¢'Ô‘I£alÿ 17÷WpÍw(r¡R”wÛ«5jöQ}4ïֆ#÷p®+‡Ûjºð…W«\·mŒî´õïJü !¡°ùÇÍ [RkÆ£_þ‹h¤.Kû]$²I쓹hh:ÒÍO4'’9?2•äyl!ø‘±¡S²PŠø-ÜßÊûg¹©?3è¹­¾-Q{Uê"¯ ¤™¯Jãâ ]Ìp¡É #2w[Dèø¢SFûŸ#¨@COÒ:“¬(UÐÜ·®½{ñŒyH«ŠIM-“¿¼é^égîùk ˜`ÄËI©Î”4á/_d!U}ÉNe«"R÷ÙJMš‚Ís̹~È›f çjŒ?uït W0¸ˆ±c‰Â\6Ï—ÁK¤u`iÐÇüäðæø×Àì· x~NÞç¾m ™!mÇ+¸{ib¾íÅ;dÃ7Ž^†Q§ž. 4; ùL–'¥·&ÎÎî zÅ7â"\´µíG"À„À'‡ x ÓLšïâ⃎øÙ j©I^{0îXެE´]Ï hušéê¹>ñ֎ѳ>^ñ0 GŒà$±EÊ[ʤ Æ-œÕ€¨ŸÐ9w‚gPI˜ Ó¸Û¢ˆEx¥íspÇ84 4ÏM¢j!PWí íñòÔÕhíj(Ý( ŠñÌ÷〠~NU¦vâÃ`Òf3 Wcm}Á…2 Œ=ÈÅÄÜy N¬D-ˆ ±‰Å]ìúéRª™p–õM;†ÊT8–‰¯Ïkx„+:Ÿ2œæ* ƒ—¤!n*øZžÒø¡!¥XÁÕœÂ7ÍŠø»²ý ›U0udWc‡ØçŠÓ'd³ö<8i!®‚ƒëvºæ.wÔ¡ae•">å¯ü„gx¦o“ °a³¡¡áÖÅíÖ¿?Û¡ÒÁè`h³eÁhSà•w„aq¥LLë†ë^ôp CînÍ·ð’¿“Å ˆ[wv3©÷¨Ta\•ØšHÁÂx"µ0õ²±£íöòPHëÒÜMÍýç4K…nûü±äè–yÎ(Ü1â­¶ºl(Ie ƒÙxl Y2Cí¬™pïreÚå݆¼|tã‹ÊŠ‹’¶4·ÂÃ##GNŠK¿Õöþ%1xßZ¬C›¿„Ná'–[[ µ÷`Æñ‹·;ˆ×9CÃi’^Ã!ϾÞ¬Yü:ÖATgšÞ.­ÜËÁk>J— õ¤Ÿ˜FLò8rFêóFˆZ…ó ¯tÔ<Võ9oq º`‰²}6w“Š‹”G6ökî&n£¾—¹çéìðŸat£þ´)vµÃéÍúpb+PZÐúH°1Y«ú;†Ý‡!tyR™ÎÒàöÔe÷dc¶ý$Ù/8u@žl÷ë¡Ý‘bÉÄ–´¢Á@’¿ÊZÞâ`ç*ê9ÑW£¹ —Ói•×¥8´¹:§{~ˆ›òÎMºß}muÓÓU­g1zik¹öd.ÖAÛ•r?=ÑfÊ#M4uÍ+1Ô #Èî•É×£ýÙˆîLZÚ\3ãwDãók6Õ™@³Š–«Wè; Kœ–·Ì½Ï¨Â«ÞTö¶TH3[B[¸Ê¸Z¾¿7ïIÖVÛtÆ›P}yÒ,:œYkÕ«[c´bˆÆÏ­]Hú›£¤ô}ß-õŽe./&ryÓÞX©#Vª•OÃSÐß´f`o¸ç] ;¨<ž5}!Qž\$m`Óœ=s?(_ N_Ç#BÚoB£{ˆ ÖKð©9ËU!°J}a?jáxÉaüV ?9e?¡í©ë/“3L.цÙ+óÒFïmR‚Aꙹʲ' ŒZß•úöù5ÅÙx|æèÙ~ù>¼d<îÝß~n(¨µÊ7Ó`-B'eºv| Aæ íù0ìdî ñ|Bˆ«tóªÕ½Kî_ªïat|k ¢Ûº.áö~~Ʊ\4òí¥¶e´rÝô†3±4Š–Â®]¬oG]3ʧ°(»•˜'1GYŠan¨¿üõ@T²ºâm=RU+c±ö)…¥!Ù°WˆÛ§ˆ¢¼òã{Uуàϳ)V/AÿúÕÔ·…ÛûòÀo=Ø¡²Ãn„—‡óƒ…a]Òb6÷ª²a‹º§¼x%;¹½óGCVuŸîTÐUXý53fâdÂÓÕ¢°"qéîErv8P﩯U]³,€Ðý Ú)Å(5#’=š}B‰;÷Ì1W§…e¿Œ£(hôq¢2>×›¸V©o ¤ê1ká÷‘Ϊï¢XZ|ƒ â¤æz;o$àaijþÇ´ano¾a–søË8]$tý‹Fo|ÑoÉi+ ¸p‰o|Q Å–!Á£zŠ¢{Wݦ;<ùÆcóÊtÊË0z®{ŠÑ1]Y²DÍA½eïg] ØÕŠïþÒ2.ÕÆ‚ªÑß¡è¾ÇyEoYìÏÊ:e#cM-ôh©˜ñ2ŠÇȆD§¨ã¶ c«:dR AÚr3…òhäJaF¶0ßà­(8´ò{(Õjˆ×¢Ê_ìf¹ÇÃn(‹#žšNtà µÒ$¥Câa‘IÙ˜Ûå_¢S×.?wp7ta>ö0TXk­7BïJŸGìÍ#š!¯&ÉdºTIö®¸áwJ¦Ì[KwSÄ®àËý@B¡ë<¯$…½.'º”óÏ•ZÀl«#¦ÿÄv'ÆVëMuDš|zcÿðÛI|‰H±+µéॠ3¹±—ꪕ¬Xy«­ «»·Ö@K~E[{VM+{ÚbHv!+‰É„›a3ãºU‹/œêuŒ¹ö½Ûf?ß·&ÕÚ¯djj>ðΕ«$µÐ˜s´îG"Â0Øšû•¢¬JÈç7îæli )¸Úf“DÓuMTäÔY;ç§õä¢ÒA²ï×ý.ñ¿~0 iΟ2n÷‚D‰o­ÍtÆ"µÐñ¬O”@ži~X®k¿ø•/Ôô·Â¨^¡˜™&ŠÉõÛͽ³ËÞÚì)Fž  e'~¥¢+ ðpÖ–fßð‹oWnÆ2l†Ž!êC)A´ñSZrxÂnµ*—]»¶vüxFbñRø~e w$G|9ËÉB-¹BÆÇ1ÄR_irfu‚Üœ½ÃúwX¾( sZ„Ôv—ψLÐì#wA´+§#øíòÚ˜EÝxÜ®Ù9B* ¢t?ù'iKŠ' ÆUÆ.¦m¡]w¯y…£Ûjr³ûi/ÑPz¿¾¤ÍÜ ãRÏ¥V÷ºXÀ¼Œ|Ç`‡ÍNð”qHMs¨‰¡qi5~oÀ& tVB•ev.\’îXAZ08È¥ÎÒåmžcgVSÃÕaz\Á:ØtzMiùfRüÝØºr‡RB(‘<èZÕe¢“«=Ì¢:&¸¶zÅ8I\BŽÛ¬Æ4‘',¯E>iHšŸfªV;Ȫš~S³õ0}@5"?¡båäžMÑ?²6—O‚¢/1üæ®iCÎÈíSuß«È#míþ…aTe"C̾Ýnì⣪ö·îd)-úÝv/R`ÐȽ·#x—•ëUxøÇQ8j–¬´›|©Y.y£n¶´BÐÛÕ Í·÷úܼª²«èºÅʛÜܺFmøDP,ö `žÀI¤T£Ï[áÚÂÁypV©ñ÷ÅŸ5½èc £±¾Çí‘>&¾ÂÞáuúöÝ`:' ÂÀ ýBG¯U?'ã´Ð7·ž;ŽÝ=—Á!Lµ±¿Æó_Õ£ù¨Â!œ)ï¥Làlö˜Ú\3D LóRžp%Í^î3’Ò@‡ãç—'AKºoWSWÇ9­sÝ>ò;O rîÔgSn£"¾d^ Ã& ¤¢(âš„JCÎ ?æ•=žŠiÑz"Ö³¤DðueÈA™´%©YlH¿3†Çòª5÷Ëá‚úÌmÄ€Òr“íÖ7þCz‹>Fk,7é¸&òB»€¬[1§ Ò÷Ñ®ˆ#Ÿ_èýPP6õ¥žú̇‹O›Œ?‚—æ²¼Ùä3M³Ì[¦˜£9•÷TÈ ³ñFs4Âb3KÄKÚŠ¦­â;lÅ;†úa TVWAÒ\ÏXB¢òºÚÊÄàùÁ)1$g%œ ̱Á75ÍÏ—^’O_.څΫ*‡Û³¼~Šül¶û›«,ñ¦ÿ—­Ÿ]àK=Åõõ w™‹†ëæ¡ë éúümÄEÎODŸ†xUoMRâkn—ÕK+vâhK ±q~ÇTÕ'ô_ªûhïÇLŒ:ƒAS×°U¤ù›Ÿ_#‡E2©oü+#“HíYCœ‘ðâ7®,`ñŒ}[h²^8+ÞTÁ’ýèµg¿Ðæˆ0 wÇ íH ·&Ü}CSI¬iè¬D ž@mb”Ôv¾vóã 0µê4DŒœ$zÞ™Âåsg鿱UhbøäƬiV„ÿCìÄC ËÔ«³lóäRPÖÊ0·\bð9Ô0"ÓRúö2{ÜQ¨žbF>n§o¡+™b¨ùãɈ•›½;Z-¥élôIß|g¸¡WòSþ…í‚2š4ñNP&ƒñ£†uݸ3:-´•)µëÔÂ8šÈgUAo•ÊÞZÈfÊ>>ÈZÓ,…µE·á×@‘VGŸ÷^>¶,:ÕÙÜpJ6VköÀ^®l«+Ǽ«]#ܪ¨°té)#èËëå‡^°gÚ>¨Ë„00Ë\1ÈxÞÈ´µ6½ÄÇrT=ÑÏóßè*âÎ ùFÙ›¹%‡á@ôRŽç BãªJ²ÁV¬Až™eÿ¬L´çL¼qÎyF½\F£(‡»2Fç3_]fØS_x×e“¡¤›CbM$X`õ&ñ.5¡=U•›Ÿ3+?ê"ãÑŸ¡˜ˆ×4÷¿N‰çqq5ÇâߥøT™³á5 çLO´1Mû+ÏÇ,’Œ]„¤'QGnÖ./ž˜£bµyZF·@Ý€íD'“@gì€õœ™/A|€cÂv r‹Ã?ð¾UD_)Æ('¦«—|ÏöÁA,¦“®}RÔϬfÍb9˜CS6¢D¼w¥‹ŠA ÙÚò¢_£w>¥&5j1© òÒÕîɰ+n µ@°®[— :Kq¥*S•ú£O ÏÀà'ÒH¯VyPSlàFÑã½?™V„Z—ïŽfõ†ƒÑdøïµhTæ=}ôYw‰º´CòñsÞ~6fü/ÍÀ©šÔOB• Q³8¾Féñ¼3¯èºöš ‡?7¾…ϸGÈüEóu@Õ­YÈób>¨é‘I*=çÒ]‘Æ­Ä¢øÌ>¦À6ëÞû(õ.‘@Â/ì”Ù'Ãlsᕳc÷7—@Mm"fmk½XW†ß\y‹¡mào©ŒòT*MHqf“• ð“ ]¥Wo]sÖô2'’ýÐaT×u((Æ"œ¯26#¿¼Á‡–N*n—”ªÑÂ<4ïÅ,Å_1õ ’VAöì°*î0_ˆÍl5[CÀP( ê‚Ò•’BìiàG?ÂÛMnÖZÀ Q{¬¯ñW­ó# ¬‹…R©¡`-‰ÆB°#zfÕUõÜVïâJ;qèjï3e>(4q͘Üâ6w¼¢ûn ÀʼnêAW,6J^Í•¸'¬4Ü;Pã(ÌAM–E†hÛ¾Œ‹¥fDôÆûз™û8Ÿ8üÄ׆·Íý¥y<[4‘ìôøŀG–ôõRÌ7zÖ|Š$"cú Â5|Õó*²ò¼¯7ûEêEáí¾àãá9”V<Ún×I]¿?§74Ü(¡ƒÉÛ±­SdAK!fLÉ,òÕ4¢}kê[…ðd~ŠÒó-aCº’+õpcÜÜæü(NóÂN=lòñÔí7ßëîͶ>éw2å6ñI7«‹4k×øÕŽl½[ç‹ËðÇ=ûŸWãùN?³› $÷&né Œ5PNˆƒZ+wê±o™DÔ4kPh”‹-M/½ˆ÷ÂGA¹•õ#ÓÏ©—:¼\‡ÒÕîè`ÊÛú™Æë1ƒ8ùœv 6¦¸{rJ )O€Â}m‰™/1>#dŒ”÷1Œè´ sVh¯Q'å´¦‚q+Oø¾é“‘Wß´…~Uê¯ûö6h"ù¡%ãÂH.@iÏü£Ø¸5¤\y¬©É¶Ý½^ ލ»º&ºâ!p;¿lîéP«6)›”ﻕ¿ÓAIÄ£K¡4£n|’e£h¨O7Œ²2¼+³0C7ì·ê¦1‹ö‰DËVÜ›t3Ë`JSsá•Ô‡gP®‹ Öûö¡FjXE`ªª¹…„á9ÊxA}ŽØ¾tkU‘(x"8p3¸=\+C`qEHÃïê°öÃW ÍÝÑeSµÐk ‰º Á-^S+Q ø×P‰Ž;RÖÁŠ@¸µDq–¬r¢KïƒRmqDãÈgÀ-z³ˆÍÞè7~ Z’¸Ó]RmK«©NÑò›üê—N­ý +‰\6piº>€âôYÕ´S'1oÞÛÆsíM¶Ù¶x!+OT~<ÕŒôLIĺ1ʳ×Ùn–ò/:h¨cG% »u o7¬äA7¿ªèÖwÌCç`êõaiÄ̤ä6ä~ÇBš0|ÉI‹#d ùж’-I[}ãÊUcÕ³ùâYJ’ÃJVA1µæà¦‘²_u§*/wÙœ0ò4Y™Õé è¨êÀý•IÞåâ©r²q¶ÚÂFWQï‡ÄCöág|èk)ì¢>:õD¨Yäm‹’,a+éª"ùh‹ôKÒ#J(®z·˜e3ªj2Ù@š!ï ¼Qs5‹®ªêMp<8‘Í“ƒ'@Õ‘Á~¨¦þà¿>a¶éÀÛ¿r¿Z¦Í½ú19§ÝNá;Ú?;×g"†mÙ¾¹¬N{ÜNsìŽûÙý=yó”{¬Í½j¢jœÀ¤[ºH¯|ƒËð-ÐÂjºjN$gWºW+¼âP3§*“áƒò [&ÇŽª¡lÁXý\žÑƒ¬aœé‹<&e›å»èVDÓP… m4ëÚ·[©¶4é94çóbo'RÄ]LòxÿæS·ÓÀ9ïþÂÒíÔ¹´ ë¯.l±ñcIoŸ2@KËRj 2àfé[‹ ³ñº£ç^7y]…Å8~™‹¾e§–䨿±¾_‘¦* ŸŠ¯±ÙÛB+rý#-‰f€-[dÑ@§¹áW%ƒo¯U'<$ƒ,sÓax½K;Ý"úup€5f!)Î*Ãýg^Ç$Úñ Dg¨Ç‹Ùé´íÅÜ]IËý¤`ßóJ«åï„Úf·ó«fûÃÂf´¹ûŸyÝ5 šµÙd\D6Ï_t]ùaŒ· ×9’Æëmfž:Ž7a¼QH´&~«&Ä? Ù!RÑ÷­ôR0e™Jê†qiL6²ë 6$ 6&»1,ž-;B¯]Ä1+Åšk¯€½¸‹<ÈÚÍÝSA ή®yN@WpŽˆ?×\ž5L 0Ú ;Ëñ>Mάb=Á¨Õ@1ÝÞ¨U®á,þèëñÑ0¢û6åÚQŸå¹×>ÅC¼~Äð°0¢5'¶fë6Q«ï‘(õé5…nKUÖaü•‹É§^‡¢ð¤¹N¾Â`”Uîf|øH|†ßªÁšô4]öÃÒ. ;Š×‡“T¼z^ë\ÒÉðRlŠº¾¢¹*œR¼Cä¦|Öz¶¸¤šÌ0m WÀ\R‚¤ÃSJUýÏ5…zå}•”5éÚr#¨Ù˸’&ªAd@Ì—ÐýÁe~SÁSbdóЙñ ¿E‘†-‡ ŠÔ¼öËJݦV„t=àäª(égB©fPÃm¦áœ5£ºôÉ6£Ž ê<–«úɹ:Ùdï±[)A þ”ÀÛJb“tYª®¾‘îìðUÿ4ʪu%°‡Ù·{Mû#m[½?,ì˯æÕçæ,AEúNä­äD\É £EEsœ,m× ˜Ut.@}KfÁ#©ôGÍpæ#¬Iú¤u韫“(ü ƒó¯Òó‹Y¡‚±è‰°rþywðêM§[‚‡#Ÿå¨–ÌXù~»m‡×Rý˜4£½–ÓŒ1ÚŒ;ÿ.ÈÅq¾:2:IG#5•`b`Ä»~ÌøÜé¡°‡÷k_P‘ŠA–üþËOñjúû"õÏkUëQiTÏÀ<ï½kSîÍ|ø>|M/ŸœÁûè'ÚRpð¢#2fûC#˜À×xR ª‘ßZÝŽ#Îë#Kª /_Ä5dÝ$ˆS¤Wî{0B&ñÐN¨¨‹*·±Ë‡s2Òõî\H”Àk{ö£³Åv‚äÄâ£y.zeµ’Fð.ýz„¾mÈ«2'oœUêc«É…,(¶õd±ñ–œò+Ö î\™±4ž8|›¯˜ñAÆb¡ovRyËB˜ÄðüåtFñÖiŒiøæ–>(g´þzÑ—³m˜­„wÍmÙç¾<û%«F<ˆµ‰–©XU¸Ü™\™¶è;ÏØM™Õ6})£PtûJ.çOhÆÎp|ÔŸI™rHƒMœEUdpl!+þXid}ÿ³™+2áó_ˤpf,U²åÀqDeó}{/pzƒhÌ'Ïø =oñZ‹0#Ššà+ÖvÓé£ÁÉ<˜™ãƒRuu)àh)Û´T(3ýr•Çq‹®¡ZMº¢*¿%ÔXÂà7P6lΟcZ¢ôà0¤0«9ø úØÊ ×>ÄÁcä€o˜xO4F—4A aÄ=Øšã˜Yþô†RäðdëÅ6×$õq™ØQïÖdëbÍUózœªg8òXh¸‡Éãsy1võÂÅCEâÁþé\WE´µ'ï¨6ˆÊ‰ÖŽÆ-KgóVÑö9]sÉ-&¬…ÊX/À®S$ÿPž„g‰þ›Ž2ÂÑz,})ïcKŠ£ÔߥÌ!£’\\žê,í`u˵‚±ééöxâŽÈöUiî:ȃm§£ÿÔ®œ£1¸Àh§_[HþÀÂ5·†ò$&Àw ®rV'¦PŸŸóõ Ó(´ËF *yus‘Ôšº¦Y¶Ç"Óëƒè§*'¯ã&.JWÝ·…É9Ý~èd>Ù ü²²Ïd;å¥õ°˜öK±gŽˆÖFp¿ŽÞÿÅ·äÝˆßæ#—*ÐÁ¾‰Ã¡F6×x}Ò—;,=R—4}½À£6Ë]21HÒV=üX¥– ïç¿"˜:Ñ“{V³6ž­ã‚óû ”É8’T[œÑéÃ?UqI%Þb÷u©©¹ €"×M*&˜šW'š¦.7η¿‘‚霖ú1ßòË¥î¤"³Ú넺¢Ÿh¤'†ŠoqWÇÇä%“ËåÝfÊÚš½Q‘¼†6óL’û¾”:Bn× …7õö¤]fEº”\\ðúªý1Ùîi¬2œ ýq¾ùÛaÚ_?†’ÕÕÆnÑKtT¨©fÈxœ=~ #sÜ• ˆÑðà®î‰LÏüd6|Gp¢³È=²>S.ñÝ´ËÜú^uÏÕW ÂÔD)¿EV¥T,Tó † »°À´ñxÙK­D˜tæûXàM%"x¥“A,¨3ç…yó΂±E­ô·6ÆèøyneãÑ'X £`ìKÝÔ¦ÃÒˆü³|@î4¦?CÇ+bü´ÃŽÚ¦¾Z{Ø›zµä£Ò±ÞÈÍB¥Ÿ.Ô¤(Wýr‘æóˆZ‡»› 3îšûð3çr€‰Ÿ ãÿ妇Uð*¢T¤J†z+^•Nºð&©g ód€.Ø:¡–"iÖ×´%"þíªÿÉ¥åç)Æ â xY¼°žÛÌÀ[T?úL2Ÿáü7’þ(¬î+uId•é>c(`¸S€„f:à“Í¢êh‰Ž<Õ‡öªäåj¯wÙsCÕ5šÄ¬'Ñí/8ÔÏlˆÞ‡cY?(¤?ÚYöùó/j°Ú³…UØ£Çðëš»(H-•ávêÖ³÷âÍÁi>RÉW­GH6ÊÃÅ„sÜïð’Þì( ^©… ½Æ”qX°’°áFI;OÂ)è8Ì´ðpe(\0¸~ë·%­/Y£¨é†ñÝR8¨‡®u­8ÒÆ¤Mu6ÊT›,³g2¶x¶nVGÍÊ´ÃŒŒ’<7YqûÙVàÜrÏ«¼Ôrƒ·ç×£GM1T“Ë)K¢àt,íELëËJâ²¢O N@ͦ¢ºý£šíH’?†‰¿ö|×ÜYÚ·Ð`-áåAçl-¯ p¡CÇJU ]”OÕ¼NB½¡…Â,î( ž¦-¸c„z^fÊ ÉVœà"y´ñ~{nZX£Ëj›ØlûÆvÌèð©Lïg/i¬OD–«P5‹ãŸ¾ýÒÒÙØM”TÛy¦ -œÇGaI¹;rãþ†™·bùìPi¤zÐÀ‡Kè©=x `·ì—¼7Aãiõ" cý5$)ÔÇQ;§‡Œ<ë½/®u›¢_GúP£Æ­UŽî?ó-x{¨Ö ™ Š„ü“‹µèÖ¶ý‘¼þÓvs%;¥ÄוÉÔò1Xej¹>a±l|hëéOá,Ú“ > ¤óWÁÁSl «n9« 1­œšˆWËE4vµ­†¿M:&²sð¸ú”vgDu9´¾67m´ÖuæM¹Ñó´×¡ñÏ1¬ô1LHuzÂÀàB4 ð“ üò’¦-E™èí­5xtfnl I2jIm”Ÿ¡°d ΓšõeÜØEp­´`¤–iÝÑtÐt,7nµ/Å t9M‚ßR#dóÖú”Wàºð™ÓfœJuÑGx¶ÁH2‹¤C?˜ D„4Q³aÑ-'£×ЉûôØu-,"|ŽKößÉ‚ºJ,Ö¢ßl½9;¾WCËs›Èæ5æ÷£ÂÏWw|i¶Y ù‘hþ¼¯‹ë®êOù¬oó£Â!ë-•I&~Äݲ\w¤ÓщCš`HOÍ%÷¯1èàºK #B(v;P>iã,„σù­{㺆zà¿ÆxEÐJqáR(íT®Œäݲ€õÃÊfÀ¼Óèw² 8÷yãW$äö_é'SÆ·Y)zB«‹¸š“qLh“Ë4+ù–?å»Ëy±‹¦â¡ëûë×°bœ#E¼¦Ý*HïÔnµ£gݪn?j[e¼ö" À"8lñxC%Çæ"Ôé.'ýÔáYÐ-…cýqæwãÃZöùwÊðÞÃõmS¥Ãåc}wõ¤Òë›Ù\Á•t¾û˜Ÿ!y*¿C¬KÂÕ™©ýMÕÞ0>¸ÛTÀ n¨Æf0€uAÔN="³k×˾Ž|æ©À#à[ø)ó3BÑ»ü ³47Éí››B¯ï™´“ 1½ÙËTî ?ç|Ê y¼R$§{Ebç\wüø|6"\Æy©_µ—ùƒÄ×»â)^Ç¥ϧý 0t[Žq.&—Ÿ¬bß še vcûо¬-;1 | ñ,­¯ídf=I$#^™ë–qk¢F¹3ûùÒRÚÄ$ ´r™Z­]Ê vT„…YK¶[õ1 =ؽC Ml“AHm`åÍÃCAÍø¶½¾ˆi>ÐÌ@çq_l~JÖ5d`c¬×=º‹è¥è‹½P$K,7‰Ý(Ì¢y²Ö=)“Óͬ$xEœC4É&†PJCûƒã ù4™Ê5 ×^5i‡›îáÒÂrwŸ9dg·}îmõÌ=¤¢ôVCS×ý ½›û!™ÐFÔoî\˜u£P FrÞN"Ì7€¾¤Œ 7î"èjî ës²±†™Nü6ò›rtº¡݆þ/<û¥ºƒ†Ù`Œã¡É,«› Z³ûliö‚x{µå1ô I“G•m˹´Áó¬ óhˆqƒÛù–@Á©­¯Ÿbü{viD¤ÕCT×ÒH Äà«E,·˜2 f–_úÖkeS™·R>TÄ`.ÀÍ•™I¹?$´Ð¥·½ˆC¿ãªŠ<¡4µÉê[ÑG‹™û;8¸t££”™ªP îI ­€ç]¯HSFòVÁ9ûâÇêú½uÐñkUn¹('™%:n¿öÉÑâÿÞæƒxÛëãYR¦siôOÙÄ ó%æzõ6Ô=d}!² ô´t˜Ó¾É¤c¦‡7i±¢ydFœnùª 72¸­óˆE¦­Ø°ï搜©=ýÀi ‰$ªž£ÄlØd!3sA\Ü Á ÝdR) ´inDYcÙ¯ôyÕÂ/.ƾ¡{ufÖ¯Ýõ…¡wÓãJá{ã >Raƒ\gžåfºèëŸ;Š7M¿6„Ø@¸£ÿx1ܼï$ßæÓœ§FÓ•aToÈB ÙË€O&'$MÍšòŠkÄxa/%òå‡Áeæ@¨î F(ÈÒ”¸sÿÒï!b ¦™u­¤¶$]þ¢T0‚Ί®N^ÆUeL“»žæ³8%\H³Yxzj\¸Ò4ó:XxЈ,C6CÅ·Pd­;¼-¢±ïO16K.äàpoj«¹fZ( +BÐÐû n\шœ×i.“­lÚ8†¶¶¶4ŠY¶KI›R•ÌUf‘p³‚¾“¾Á)'"Êî¹æ-H÷ošÅPh~ &7ò4¶×èf¡ºMÓòàäGA .ôT˜FLˆ£Y-ã›…q·Á±@£â`ª\÷«éxú}dÚˆÈ]..~À(Ž-^æét•‰ÂDþ‰ßAHk¾«ÂŽnŽÈ€¯jÈ­qÿD—9Ýa©hÎì.Õнɩ¯ãïCÒÃ.B…™ òIv>¥«;¼ãˆ6 ö¸¨¿Ðwå?öƒã²^¼Ð˜H¢Ìê~ŸƒÅ¬‘|ü>”èÔº6,'£-äÃრ‚>ÛN~37cYš]ƒÞ¤`é`¹™[Îè–KNþ Â0F{]¨»zyƒ-w©OÅÆF îÇP›vå» ,nQ–R M }ÁÊp3X¿ù#°Ö´2ÙumyÍÚ°ôGñd¯AQmäpC–Ò‚÷W Ìô»(ýšÚUZê :¯ó=Ér2 Uå ‚-“³Ø%¬˜/Y±.ÀT³Ïu[èGƧh|ޱ™¡Ñ@e›F×ÀØœ±÷{îÑÔghâÒM›)„¹Ã¿&BïǾòßOirä>ú6E*"C©ÛO;~ÄŠxS\uiŒgÓ·œ¢Ïõ®£×‡Õ«’ÜZØl3e[«å‰#ˆZj åÔåeÃIFÇ;u×QÿK)‘S endstream endobj 3410 0 obj << /Type /FontDescriptor /FontName /PHLKTN+CMTI10 /Flags 4 /FontBBox [-163 -250 1146 969] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 68 /XHeight 431 /CharSet (/A/B/C/D/E/F/I/J/M/N/O/P/R/S/T/U/W/Y/a/b/c/colon/comma/d/e/exclam/f/ff/fi/g/h/hyphen/i/k/l/m/n/o/one/p/period/q/question/quoteleft/quoteright/r/s/semicolon/t/three/two/u/v/w/x/y/z/zero) /FontFile 3409 0 R >> endobj 3411 0 obj << /Length1 746 /Length2 987 /Length3 0 /Length 1509 /Filter /FlateDecode >> stream xÚ­’{XLyÇI‰±.‘K²ù…lQ3s¦™¦rÉ(”L&"ŠiÎoÆÉ™9³Ó™ÌlåÚDe[”Ú¡-‰..튭Tf(—<„M‹z0ÚuY[D7¤Éž²Ïæß}Î?ç}ßïïûûœï{ìBJDÀÅ„œtAèˆ'ðæûy„Τ98x+¡ˆÄ¹ˆ„žñð@O%ˆ;`!žLwO&—æ¼ …F‰I7ÀÑÛ©OÄ<Tbb‘ðEä(£<Ä" 1I ðpõˆA0 *£!J§!@11 " “Ó}@~r ¸Û¨Jñi •Qp¤ …ˆr\P(¡1ê.H‘üPÍ«p<@$ë³ï 鋱H†áš„L¡"¡ð *å¥!ð#¢˜J6pêGŠpLÌ“Kq\6ÉþØÇ¢cjˆ 0R¼HDxìïC9:„ ¯Ÿƒêï²4höÇ¥öÏ"LNk0?‹ûkäsME¤ÄÔ` “Îd"”z>½… ¸k‘\L ˜\ X7 R*E“²bq8 ˜…jÕ0ƒ.'Hê ‚‰BIëÛ)Û 0Ôb´¯Oûò;.$Ô1.®àÂâPÆÛp9̸ÿÅ*¥ÊÉþ…JãS-Á¨!TC1­á!ž™Q’P¸yQî­cNQStùñ×õÚ3º9ôæ‡sÆÖ+KoC»6+­U$v|Lú ÿ“ TÂydS‹½#dhïY]ií”s@hÙ*n^nV“}¹j´ì§Äg S+Jg·6Nï4Fë-~^öá¶y‘d^x÷Ž©}óÆ-µFüˆN’N Ë®X¶®ü˸çZwË"—h8Z3qíÎq½ 6Uê6Þ©óHÎæù]7¯g8ÓI-iª¥!7NmX•åáûá´1æÃ˜«çŽ´>éJÚ}*Ûóç»§uoªêZãÓ–œÎ’ŽmN–;3|Ýñ+7'à3|­}²ítžÇ:{}m,¸b¥o{b³¥Þ[P”µ.^/uÝiÇ«.´!3'¿’ŒËÂ'úÙ£ç*ÓÖ ù]ºõyþÙiÙ=³¶’«´7N/4)5‘±™ºªzj'<_{hÕÌ#-Ý‘ëÊæòòÇÙ•CíÙ]íø{oXq=DšùÛ}©wNœq­fvÑkyùbtäô¼"î®^¼h{SŽyyKrëÃÞ@'FDøz7†{B—Ù ž½v25Hl]Y±úÛÃ'Ç6¿Ÿ“»¢lwb\¦¢†÷ÇLõUÙ»Tö«wù]¯Û±tp ^oÚæù!#ϺSm [çûüBá !£èT€Twï¼ùÈ ½èh¸T“&IhƒÖÜ«ª,ÐížzÖ9`£ÆöÐM;«9©ó—·ËËJ_réçl‡Ÿ·¬íðÚ~«”ãCl˜52¿ÃʹQ¸~¢§´¬&¹SP2<äÙ?Î@æ‹ endstream endobj 3412 0 obj << /Type /FontDescriptor /FontName /ZKKWJR+CMTI9 /Flags 4 /FontBBox [-35 -250 1148 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 70 /XHeight 431 /CharSet (/period) /FontFile 3411 0 R >> endobj 3413 0 obj << /Length1 2232 /Length2 14714 /Length3 0 /Length 15924 /Filter /FlateDecode >> stream xÚ­µeXœÍ²5Œk xpwww×àî îîî\w÷ànI xpw î|óì}ÎNÎ~ÿ~󃵺ºjÕª¾»)IUÔEÍLRö®Œ¬L¬|qEuuV+ ‹%¥¸3ÐÄä`/aâ ä°òò²Dl\V>6ð‰ îàèå ²´rЈÓþÄ µ:ƒÌLìŠ&®V@;p3[€šƒèêŵµ¨þ³Ã  t:»Í™XYæ 3W€)ÐdÄü&Y{ ÷¿is7Çÿ]r:»€Ehþ%“iî`oë0Z 1+9€«ÁZþÿõßÉ¥Ülm•LìþIÿ/§þŸu;­×ÿD8Ø9º¹Šæ@gûÿÕþ[œ"Ðäf÷ß«²®&¶ 3Q{K[ €åßÈE ä 4W¹šY\Ý€ÿ¢öæÿ­ìÜ¿0‹Ê«ŠÊ«ÐÿÏPÿµ¨b²wU÷rüOÖ¢ÿ…Yÿ`°=Î O€ Ø_Vp øïÿ3ø¯b’öfæ {K'ÀÄÙÙÄ ||Àˆàà ٛ=@O°`f&{WðØ?€…ƒ3Ò?åâ«ü‡ú7â0‹ýAÜfñ?ˆÀ,ññ˜%ÿƒ¸YÌR+€Yúb0ËüAìfÙ?ˆÀ,÷µÈÿA`- X‹âÖ¢ôµ(ÿñ€µ¨üA`-ÿ °Õ?¬EíkQÿƒÀZ4þ °Í?¬EëkÑþƒÀZtþƒÀGžÙä?ˆibçþxLÀgæYVðÇÌlâb¹‚lÍÿá9Øþ¡ÁÇäbóÇv°H×?ùÁMÿ ðS3[«¿òsüC;ÿE€û6u61Ú-\ÿ¢9ÿ‡þ÷GûŸ¬¬ÿ¦m€®ÿ'ž—ý?üm[`öÄ –hæ` ¾-þÓÇ?ŒÝcXYÀ3ûã;Øs[Û¿5ƒ?óo¸þANnà»ã?{ÀjÀÇÜÖÄî¯=`?,þGX€Üÿ$áügÙÁíï"àË?EÀë–ÿÜ¿À¿CÀâÿx˶ÌÊËÑ hÿW˜ýÁÍXÿÁ'Âæ/vçO\`l..­ƒ½ü«#ð%Âü§'8—=ÈþOGìàÒönv¦ÿ\Ï–IßìÌDƒs:üµ‹•ܨãŸep Gg ýÿ™6ëÿ°ÿwÖì` àm´ÿ+”ë_ÈáÏD9ÀÆ:ÚºýÕ+˜qúÓø?È èòÏS÷'7Ç?¤ƒ+ÐÜôE¼\ÿCþuì¼ÿÃþ_u¬¬à ìÏ œÿ  û_³ã‡»€ïÝÿÈw÷_+¸þŸœ`W\­œ*°{®mçpû#\Ó |';»˜98ÿ=ð9pÿ ‚ûñøëË'õü ‚«zýÁãóþ£œÉèüoÿï»$&æàéÃÈ`dnvVðuÉâ÷ÂÌÜœÁcvý×›~Ûþ[€À!è 4CZšw0ãµNo /÷—,œª€¥ƒ³lMTjìéBYL‚´-—w¢[kÐ~¬ÌÂD݃Ý#ñx&p‰îôýøMê<È)1cîuÏÝx/Ë»@û2KÑkבì.äøý×–ÙëNHåŸkå):ECŸ/†¿¨ÐH¨ïïBôé¹7õe‡rqkKeÙjD„5P±“ª¢e8•GrD¬z ¥|‚YýâoÐF¿üÛ¡Ó ã±!?ùÕâÁ .&˜M,w±õ‡µ`D#Ϫ¾„åÃj¬>¢±¤‡™Ò4»¦/³&f¶Ã~éëݯž©MµŽú>/ˆÙç-DSºoxû# 4ðS¼.Z§ð•R(ª0Ç|’­UŠh6.ÐÕ!2a,l¥’×R„³•Oô!ºEéÔeMèÞoDòßCˆ›ÑZÂ>¤Muƒ‚[-ý U«’É—}J'¨º¾rƒäŸî !;Å´^1jÙ¯{Ž’ÞФc)Ο8 öí\Ñ|9¦Üá¤|"Æéõ§™äü|K"fã'zdý.tÕŒZ-µºâas”‘'ošŽô”é•@Qž"ÍôµÆÑ±½â§Ë’=v1‘3Ò?ÚϪ¸¾/ùgCˆ…ír‡LÏNum˜CÒ1¨ÆFó`Pモ@éåøµÔ—×àטÙU³PÓ!òhûºÇø û“12F_•H öÎl,ËÂÅÇfO}“±VùõyÄÏ4‹\cû’è§ú–/Ä ˜s4rÍØÌoïÃïl(\UQ y\/;OËÃH ÿ@–ýúYݸ›¦4UynëÒòk•AkÁöwJU$¡#­Å]9|¨¥œáØG®îiU8ÐÆ>"f“%üñÐ[w4ŨÒ®À]Ú;1ºë"¦ad•WþŒ%—Ÿÿ ÊËn…Þ%Õ=í7ÄòdÙã^gûk‚û ,„ãŒö(ôQ#é˜D¢EWåbÅŽ‘Y¼šé×|Án:¦ZËŸGäDtSz(ýß\õ™ÁϽÌå—‡Wbºt(ß–ôku ɺoHQ#ÍÞn ¿•k,õââûE6;Ð: G|«ª™“8©¤]ûð3§$'B¥Öcæ2a²D ¾*:»._„õ×:›Éùi@»vÐ&×ãlÕéCSŠÅZS!hŠœGº{wºIKÂ.”f®ÞÔ2CÔJ™ªê雷~ž9¸¨¡h÷„^y¬Ù*X}4;|‡óÞYºa™SO*OºÆÛ1??ÍÍÀ\Õ¶> #ôBèmM6D/*šB…A8*¿››Š„»”K®Þ)„:H/ìÍ`U° 4 8]qxåÝb¼ÞÅŒbô¨…P¾`釶i\ã‘1§¦ÙÓþ$öæSØá°ù½¾¾d),À`.Ĺð)ßÌ}¶¸*ëýJS¹Ø$üE«Ê®obç.o[e8ÓµŠ2LÀÔ{xã üÐN&–ÛnQáÇø§®úm9\â¼îí$!ð§ó!!/³î¿p®×v¿E9ËîH«½§Êìÿ$¸tÛ^0°£¶‹ÚF?\­М›k]¬1(À83¤êƆ~Ãóc,»\‡Ï×Îv¥báwPEÀ€]ZX-®NÅ µv°:qízDEÜ;Í8íŽTôN¸‘Žï‰Ï¡’•oòiÎÔÜu˜¿Â¥ Jb.JC«8#H¢äœ¹|µ$3­ícþܹ²FšDÚ×ú¢ÕÏ RíËcõÞ‰u’ÁÚ< ëH§µ¬“›.É<¬×( Ý]‰àqâ>I[þ…ÁÍÙ̶ç笟[±¼d«“ËZ—äáf½ ì àä.nYhíÕ¸ÛM¬¢‰¬Øý©T» áŸqÎ]ÑÆtm3‰&R¤ÃçOÎýq4[Ïâ£?Új¬šeF°V¿ã&›JN‚7‘L+Åë`ÀL†h:v%ÜT†‡{¬?Ë-ã'þƒ"àº\¬ù…À†Z,ñ pƒ|Ÿ;(à%ûð{æR%ìrÄ=¤-U#õ`vE¶`²ý‹{÷yÍôç^¢âˆ%.|&£ ¬¡cQ«ð)ÖýÝaz§wlñ ü‹:»Ÿ‰“¶Ö¨+Y8Ý¡(7Ÿ¿Ø`™3·–•oŠùÿ|4€¥G¨¿iDPÆô‰=G´ŽÜ)¥S®L/4gŽs®g¯í¬æ¸Ý_f÷†ÙÔ†åyxí‘g\Kh†ÖWIQŽ=þ-µC?cwê×ÿ%xnûöÚë9Q*Ä ÷Žó'c±²ˆªÁÖvÄëØ¥?ßÚS;«ƈî^`ŠàØJùT0Œ§ó¯²u¾0M£üò¬ FÀìMlm˜·œ©m“Óë=¯å‡(îj–x¶}ñ*3“Ï&Sãui¬Õöá£E;ínÇð½Ñ‹°°9&H d¦“:Øzûîöí¡ƒ~½ ùØÁ»KM ªŸD=i æ /@Y³ÝÚ žkÁHðòþ  •kI&¥Ý«-µ)¥³aqs™âºs·aû.¡ÄÓŠ&ߟÙTå8H$íîºO0>Ê-‰æ?°.ó©¯éòö Æc¢ÞçD+6Á0R‹¡ìÅ@}îègr¿ñz?„^Ü-ƒCÇÎe‚áÓY®<ßôã[úæ¬M b½(»ÕØYAûû‚ÕrÀ[+ϳvk@êÓ©ZW¯6­6«Ù⃸‚oçÖÙü'×»üBÔw¨–Ø#6tsR0)¶Eº¡EÄŸˆÍ Ý:¢Z_!—>pW´pØdgÁ$ ‘‹Tï;` ±µM÷ö4éÚ9V„ÇÎôû|¸‰«‹c~r><¢T[[Òd¯òñ8"ÏÑÈ/›:_¶,jžáÏ|®ê­(Ömb†ÛÙåBÞ"ÞËPIíÛ|fA1ªóÓw}/S·X¼0ô:×är`›ß§ôé«0•ráи¨yÁ*Þ|‘n$aõTÓ òˆã„4 CÑ`¡’ Š‘\{:¥) 5›’lO±>&VqÄnfnd±j5 W Ê „¤=fØ*‹ Hm”©#&”¶Ÿ<_£•‚Íäd ì$dW¯crŠ}×e˜~ˆl›øU‰´ÏsvëX¾Bz¹zóGívâ¸Ôé–ÁoEª” ?œƒÉçuÚ÷mả—¥"Ú¨øuºAäŸÑŸ´æÂ8¢}Ú=¾Âö?‘ZL ·v1­À×IÝQg\w*æÜÕñJñ°+øÂ¾u?ï.r1ÂÃߊ„nüä¯ZŒ”Í61Š$Tö^šj[~l°Û‡vˆz¾Á¾‚!_|aÁãVGÿ‰Û·;U³‰ãéGf@f6w¢ywd[ðY+ßH×¥kJ3‹Ø½4Šûh%Ù)j§šÀä=N[ûW_a-eòœ *QÝû•w›ùßÓVª(|rg—÷ao:¥Ø?ÜòìXFk Çéí  ZB{xÛ§:H$„Ýø›ìð¤˜{\ÐFTgâ4á´ÿ#[➥e}}Qð…‰º RänI§-À¢‚øàAÔÒ?"½þѧáû*÷Kïµ h§¹â£#ÄK©½´)梹Àruú4¬n…® ]aƒkšœ`ɬàNföq¥jòá³”º§FJV6Lªt™ÿ(j¤°7òž‘KÑnftBÎ ôµêŠçÞ}ÿXêZJã^ê­c¼„ê;eN®#Ô²´}Žq§êüÞZ‚KÎ …/_Í´zAcšxØÈÚ5RÖ­¢9O0ÄLOçž>ÞË–~LH±  láŲY}ŸáÑ*œøüˆ•×Àn5 3 ~S°×v…ßNÖE·ü ˜²9“Ê^H©1‚ ä¾—Zà5÷âUDÉ}s¸ü8@óöð¥*È߇ýÝ‘"XÄo}µ"Ò„p!ãÁ±Œþ¡ÈÔ µŠŽö;G7€$Ñìe:}°7ãš}JùP$8&‡m¤¼ 8u¡a§‹8|¡Á yRG§gÝÖåïfÀ¶ù  5¼ŸùÚBIi%gù–Þ‚„uœíåœ2­„T2„ÚKA¤zµÞfÂÞgKÉ÷6Vø¥¥i !æHp2wc†»ó—ØrŒ¦™Â%›=dÞìá½ãqÜå©Ò6vkÞömûLïTã…_ÍÜ BmÀµ—G2Ù|–jB”˜Jy´CŒjþ¦h'׃$ŠÍŶ󧢇¤Fv§«ÀòæŒùqvŽý…—;ˆ=y-hÍ‹Í`aIÿ-O.µº ;d¥ÜáOe‘xI¢f-¾”Öœ:_îp¨”3Ú¤ÑûÆèrÇ%ˆx/žá’Îú¤J™ÚO’‰á9:À˜A¶8–pr=ûš¹|3ñ©ñ’§ÀerLõB9#fìÉú¼û%-Ø2œHæ¹=n[½Ã¡g ›q>‹þœVÆ÷ÃTù+Ž÷©Rÿ#”¬Ów²B[Ï/€ïÉ!ñcc2hQ]µG ¬O*~{ü€'” ·øv“Þƒ,|xŒš”cŠÚÚä>f£ÈS`i€~ЀqîÝe ¾-JŒfÂmbv³ úãÖ¥Wš…dωg¡ÛQGm22²t¾ÆÎ²š,n—3I‹’Ÿ”²¦B!GOÁwF+‡;Æ×ƒ\ã§R»ÎÛ«k»cç»Bðç^ „½:=Ýïè­$õ£z÷µØ¹ÐÅ û&ß΢òÖ`RWkÛ‚yˆÔ³®Ê°{GQJ=Óø¡“'!Œ1­ÛXˆc‰ü¬Ø ÇÉ1ü#ºm"÷&_Y°K„½÷Ñç1×P,ocÎ_º¦Ô®hSàv"KsyÌ“= °ž¦ dÝ­Ú*†1 ¼¿›¡Øù½¦œ½ˆ€N>BŒ—i„"°5¢â¹VË…ŠH\vy xf³j-5!­ðH1¯ÛS¥—%µ÷{ÊXÕKÿûZ\„j̹jc5CaF1*Hp›5F¼'eÇ’wvÔêÞÀs˜ÄœBjD@…‡™~<>Áeƒ´hHL—2&1yi†qjhåY“e6Ù™iœjµHPöyɔР Aﯬ+(_…3 e|ØîRrgr­tCw Ÿ}îéd—…å}g³‘[|Ï÷¦§ì£7n"¥©…"ýOÒ’84¿0¾/_ahQpϱŽ| @b˜H£ˆ·õ‘‹ ðÝœ"3? x>¿ý´à“ïº*HÙ[…è2_1ç8=M™ýrã]±[úr»kø9¾Ç ‚.ëoqžÞäÍ3zN/ï»ßFJ ]rÅ2£¸P*îa…°’`1¼(@¢üªZ!©(v¯\†T43*¤>Á^&þÜ[¤´á·W$YÈ Øx\^ýÝÐ^ãØÈ” J½G1’1•È©üzRŸl~ÒÄ®¯ˆE.Qç ›Kðz(ûëÚÂjõ(ꬥÍOÆ1¯#]{¸cÒ_¼×oÜÑmÂÏW0¬:ýqñÐ>ža¢2•½z"ùïÎÆ«<ìn^+ij\C)+;2Ö°Ü´¯Š©ßÑFvmÐÒ&JS‘Û¡‰²‡/£GÝÆ/Ÿ×´r‡DÉmžze¢Uµä,ŽÈ y¸BµÐä6ÒLò°ÝÚº°hu#r›òAsØä^|„i% chß[ î$ÏÞN·¾,Ëæ.y‡Ûªƒ&a$r%¤ët@±åW–»£s×>Ìçº' ›Eeå”^{Q:Öš¯*#SÜ£,&–ö»Z™0ò>Ê‘Vš¢ ? ƒxïÍP¥“$š­´%7£3\P ª¼&gäà zV[r/·BmÍkPq€ˆ¯‚ÃŒN2E„1<›Beù±’ý$ÞYÆ9'( û@·ý‡½ôIÚØ¼6©’Ýï#¿Ô²ÑÐJb·:5·©Äã··7BéæÌ2-q3¥>J‹)ZÜz‘ψ¶tGpÊ¡^½KÜG›Úé—<“¤i¡ë`¿/ô̧Sû¤Þô&Z×»†+bp3ªfà{æjqЄ¿·Æ4„Ä•KÊCßWˆþO1F£§r3«/O7· ,”Ah¢ôùû†?¯’ЀC¤¸ ‹+§ÜàGÎì."²­OÑûŒ÷¡X€P!lqE¡‡LùÛEÚW¯"€.ò˜¡hê+àJœÀ-¬ -§ó¹,Žõ§¨ËˆÝ¡JzÖgsþ—ÊÛ(É«/NU×!°[¨îé´êÄØ —¤ ÉÑ!Чkø97†ØgÙDÕÝ XýY=2‘Ê5Õ=îêÐdÙªý¶£zréohý´ìIUßž¿ÞÔ r{—8[ÔÚ¦©üV½Ä¦•í5…‹_«‰må¸&7É2ÔǸϞ(wÇâE¹oQOʸ¡¬ÔF>àlEç4ÈÅ—I‘ÿxs P2Hd¢›7Û¬¡˜á#W“+ÈÖ`ò§ÍtRd©¯Ï ](üªLõœb ­Ù\Œ—î&Uܵÿ0Ï&F&.À•Äåílí úznò‰°¸=ìcÌö“==¸ô';)Ë~à<‚:TÍ ÖÛEépý /ÒŽÌÅçA®Íà–N—›Šráø©ä:éûÎDZ›µ\σ²Œ¾xdxLâ‘p3$ÛîÚ^OVál%¼E¿¬\ÕÅÝ ¹å›4~^ú|õËnab†Ìbs4I{ó Ç`½@Éon\^ÆEè=˜–É~9˜”ÆÅMÁÆëÛcZ,éËüržDÙoÙåu$>6O ª£æÙ3t8jlhûzÍ2¶G†Œ–6¤ˆSäãRPßÎ4òr§i{dˆEÆý^Ò ‹•J¸Šk,“HvLˆö´¿Éª_)Rnâã84¯ó‹û:}¸šÑO9¼’-íµ-Í´ Èå¬$½Ìù!ò)œ\¸¤føÉ×¾Bâ“Ú•IDFÕ%©Néu‚æÃIŠÖ‚Ï'h¤vø9^è’#ÜoOнÙÅd$¢¹óÎ,"gO÷,ãf¼|$¸:mÓw¯Á ãü&æ«'«Õc™·¼Ï§±°ø°=o-Ô 1y5‚î}’ê)–ßÙ³tÈ¿¸¡a¤å6•ö=À-K×Ñ=¼¥6H|¡°Ñ S ¯NºpUxýÔþDaø_=´¬³zKá¬ÞÙi+`„ƒÀ3X™,íÒÕ©n8ÊóˆÄW0£”T ‘¯övµÙÓ-|t smzGïAËäû¾çËògš †ßœ»—¬œ<&–ýpñÇ10Á‡Ðk=³ôaÊ×±ªEÁ‰VŸ ™_¿™v›íTµ•L«ða¢4šUä¼Ð…R¶yN?}«Q]+ÄÞ—ä–¦/;å™Dkˆ¸Hoû,µµ—Æó^nLÇCÀ4oG)ë°¹Q%}Äpk±Uqý“éÉœ1$5-ïÍxˆ­‘F”C‰5ð@©BÂÎ'\ß=Z„ã´…Ë5{€& ¤û³Ïc›ÓÏ(¨bÀ¨Rd>‡f Sµ?4F½Û#œåƒ¥dÞÖQ,‡vËU”©š«è=ãó]ÒBy°¿Ü I~MÉ;¡sýjœ$Þ"¤íÁ6:Ö|ìÆ€(ªc´ÏˆêH“.¡ft`8Y?³÷6Nü2í 7Y—, ûCï{ÃM¡`ãl’n{$@oË~4*IÄSX6ýrM±ÆÉÚ5֠Ըı¢\ LJ2 ^€µµ¹ $$‘Z-+\¥©Ì‚gûGˆJ¼¾ó÷.«òwjŸ, _/!*`G‡¶«´Ó6š˜Ê~©ª¹ãZ÷¼(–DAZÕŽ@øc‰SM ø©×ÎÄBêzÒŒ‚Xäi&ä úH‡Õ£¤Y\Ø÷¶‡s!vïÄzkAÑ¢šÞ„Ç€`ÙßB²Dˆ©âX…dÖÅXò 50ã1žƒù‡Q?…1] “îí)IPTA}ͦJÅÓRÑþiî¤Dˆv@ǺŽKnq£5@ö]¹Ûy†ëÕB9óXïp¤÷RäÉ9½'à|‡MàqpDlóFøZîS™UfpjJ’ןx™ŸA{GƒD¯óÂí:µ$¹ã1õ¥^Ôç¸ê#†Ð^ÙëÙ¢Å:ä+Þ»þZô×É©³&¯8ŒØÖ(cn›Ê="’hﰶݵ2¬Š¥ùSÀ,upµ^¬‡§¤fÔÌÀΰ3‰Àz¢I!i â¸KBõ8ŸjwwœI ±»0²ã‚&`Õ‘méöwœ›uœ²}7NûúŒ™“T2ÙÛýôd<9Ä]öM˜ß}Ys°²¾N…ßAÕM›-üÑÖ¶*ǨéK.ÚâD ˜O­ÀSù3ûGn$ »øö÷¾ÃWÖ¥ô¸åƒ•¦LŸfdEÉHhQ«Ðäªà%ZZ…8ªŸ›•¼† aç ÒÞR“}Ÿ´˜bÑ̰×T„U¨ÇF \R‰‚_ (dñ>®bOæk¢lƒ+–¯Ï1ÞZÆPXŒîñ[É×âçÈéñ‹%#±eíðpCD"š/ÌŠfMÐÝÍÞ™Xò  ÛSý^yÛá¤KQˆ3û”L@~Côqvʰ˜68å,Ö#w¢4ú©ÉýÑD´ù[°™7ÕÔ¸mæxwxŠÓ“ìÌG&œá¾6¢¤ tœ¦LT±½;È’ôFhµÆQMšÌ}T©{…kÝoÚiâÃp"¿®Cr;Tu? ]šóIÚ£·¿ûyÎàvf7CÈöQ’Dô›úCöµ³Î YÑPÚï ç êfÿ€DaOýƨDİLÖc±‡Ö’zYi˜ÝÀÐô¸ŸÐB§@‡ÑnoRê'?Áç¯ïl¬Š3B¾Ð;d3£R ¦©:Ú*aäs;„‹GŠøôHë*IÞkúûr![(v¸Ü†7âîâÒce7Šä¢}xwn÷©ûGxjÂÈ,bÕwÌ ƒ=R¿6;“ÓjÁÏï—@’lV9¥ëë;¶Ëº“=#‚ã5¿Y”*¸§Æx™Oi^ÎQ²ˆn$Žß.ŽIÅ¡]iñè¯Ð…½Î#<ªýžOŵ+ʵþQ‹FR²Û¨Ûˆq pz::_‡&Îää#ºâM޳/dJ•W‚1ÖgÛ ÅÓ¨.m…—‘E@"§bˆIL/)ÖWó ´<×V\„7Ý”÷>…¯ŒÚ±Äd3V"pQ6Ioâsnû¹ÛMzδÃ]±PÐ 3£ËÔ³Âç6 uìÞŸG»<§üîÆ·úHS® ©™rBúßPX „yô¥ùÎ8j0¨‡gß"µ”‰rå2ì#͆4ƒŽéÍ¡Îm:ЧÌ~« ûÒ(¤x‚¥^ã‡yÿÞ’g¥Tå…) ¿y]Ðmlºœ(.&@]‰~Ç« Mþ115¦Ò¶–½Ò,ñýYO[ôâ;<7Ý/˼֛¢éˆ®> æBÌØ·¥½OT­äÐi·LëÅV vçX¯QþÍdzå¥ûãž!óÅaIXm{ :|û™J€ƒ©ŠQ•í(‹G¢ïÒ:j.‘¨w°‡û‘iÅ”1ù§…¦Ýï!q”ˆh¥¨±Ð{øX˜Q: .sm¡V¦íõ;Så•®X_¯úàS= r“°í¿‚qœ€Ã·šÚØVß3f:d©IjôWYè}Q=»¸ ™ê·|ÒÈ£,ÊÈòý‘o*«,Ûìóõð*îö´W%[C|¸œãG³¶Õ±M EqGÅ–½‹øÏ–éBô«²>£2iÝ5íŠ"—e›³¡Ñ¤Ý›C×J·nÍóÛyÆåzáÅL{°"y£tR©%x ÓÓñ«‚ žÜ€Ì‰wüΩiE:™Ñ«*ˆd4áá­ˆN.O‡=§a5): J Ó ¸„Ì›í•.&ç)ÔGºË¦¶+a ù ̦9DB<—úÌ5Ý&9/›‚YÙ¦8‹í^°¢Æ6ôVZœ”«XKACd›0z+êžCFÌ@ü 9œ«ÃMyäIý y úÞ0LZy´Ý ±e÷Lˆá®íþTº îWú0úƒ<‹a» ú‘ã•_¥Î¶!r5´tŒRÝs5ãùïrßP? »7=¬ðÄ’?ŠaÏ‘øì“%ªX²L¢I›t+ VÉÉÏ꟮·ñ“.XJ_ 5<°êK˜hO½P3£piñpwµ¯qa¼rxèÀRmuCqo,'®kkò‡˜}ÆÝйհ|M³XjDgU>qZ¹*ÀÇÞr%&|x‚M×ñÛ“VnöÇ//Šc½R÷ò7%Û‰Î÷„‹ Ã{Ì/ð}©0Ã|Çh»žÄqÞÂýÙRõ¦Ô¾Ã;A­2’õ;¬Vìë@ldvP|F½YZ_E²3IÈ¡Fˆ@»A³Ï”Éu=µ±5) ×\u|†ö#ÞÉ€µ`·ßÁéëôo¤¡YÆ™™’—ÄæØ@iθ‚Ìê+ó™)î»W=Þ†œ¯Ý)ßêmô>^N$åAhÃhã^ñ,ª™@e%Ú…ˆT±Óü‘r#}^LyRû£±Ëh7Ñ<ì÷ÖĔޣð’¡®Ãwþ(è\±uÝfÓÎVÁ‘j\'¨tË©$H-ݘÈð÷‰­Kùó,´TZJÕ1d>ƒãÊd3Öj÷Eq³Ì< 渽t6áò¦^™Ö>ù‡@Ô#f“±ÐjÕ8}:àtýiè\^W(î ‘t-,ÁóµuÎÊ«õGœXgÌ$²iîÍ?'S©ÎÊI¬=ñ:/?̪è#ùv>ÓŸžïˆÎ–=eïåwëe…dpõ½ìE™w@g;Ôuâ¬ð.xWDÆÕ+ÑÝøl ú$§öŒ11Jlï1ª·Õ3`*4&b¢(ÖÕ ““ïŸ×pC®TeDê …è‚ä0ð'ÞA!#6¸m½K—Òs²£ÒÍ8=+ù_΃YnQ#ÐØbŽ_µjºih˜k%ÅR›¬ÌxG<[®QùÛçTt¥k‹X^_3ôDXÎÓ’z·Æá4·Å (5 ϯ®Ç!1¤UPl¥kâ!ÐVÏFÉ ç¾6-xR·]‹åÅÖ!ësMžÂ§³ˆ®J¯ß Ùî¶:ÑÈ…!üHàdÃÓ‚¶¨$éoņŒú¼æ"/\Ÿ’’EØ¥Øì”EÖ†’»ˆ‡~ …E£È×þMŒ‡mk6˜ì¥9ï?­K”-Ù h×Ý,‘dwQ >/¡?HðFyê è™hðH¼Jy6›þ>-Àr ‚:eÓäk×(èÆÚcfªý,Påu!Ê¡ç!ƒ`á‰ÞȃHª §c«I—,þ1“„¯ IÓlâGÊ]Ã[ó^_$„­Ô‹-úûÅ+%öŠj–æækÝ<¶Pªmâ“„ex{ɱEu ×:Z¦>Uƒdèãk¹!*yÎǾÖÄOÎl¼ß_ŒW\ÃÒr¯(sÐK˜1vöž¼53:-#÷kðzœq|î‚ì¸gÑŸà/ïŒòÛÙylhËr}Gp^ÿ ÄÖu×w&lQ`ÇìÚURØ ¿ìÏ0ÌÏ!øÁ·Ã.ô‹ Ÿïd7žX\{€ìyu ¡x+: ¥ÍǺ&VF„èRKäUä.)´]«ç”ŸñüàS•,¶ŽÕÌ€î°"¦&Yk.W7VRPY¥ÕˆL˜´äªÅ}ͧ²ð)Ø{m–¼(ΨØ.1½¶˜gÉX#k áÄ"¢*–TÇNÓ ð¨õÀš©_8A9¯$!‹¦DCšp´æ7Åa(eQúµ7ºyßiHê[MZ¬~9JlØôrnÊzÌϲPîjnÙÒ}asó Ù*â!¬êøþ„}¹C“r©ß(æ‚MÆ4ô§Ýñ”òÍãKÔñÆŠÒ(ýQåtWÁ)ƃ¹í”¢à€E:tJ*±srÞÚ,w¬z÷•Bj2z­ï’ ãHKÛ›õ¨¦sŽ%|Qñ >í Øß!’%8ÍM0"©9¡±C|ùÖª;³aHaVõ)Õ§¢“cja0£4A$ ùè1ò鉢ÁBVè´Á¸*’ó®”Ñúúh ·ßc+Khn;õIh„±® $:3*ŸZ÷p}§&TF‘gï`ܬ$à$5•ÈþS”œÝR\;Dj aš±€Þ êÜÖfeTUóóº¢_ôSÁÊÂr^œè¡[4'bÏ—+~³7|Ò%xÙ5Ñ›,‰'Û*A£2–T.’?Ì@RÒäµDqüc†Ò¥¥òlh2¡ä͸oµ­³‰¹l—“˜îEi¯ÜÉ'?¤£ðçæù~xGÝ¢*º÷Eàqôá¤óRÇ‹ üm&;šÓâºüMRª5 Z9, o2ÊV®s®É¶ßºß× ¶bmçk¬áÈYè|:m3Æ®ž¶¶sÁ&ä{‡ÍšÝNê ­ƒÃýÁüxœ\Ô“4&õe¼šÌ AM¡—ŸjÓ§R.ÖF»Í+KÈšrÂ|uU~óyê˜hÎWºašz»‚oxºYÀSCÀÙ‡"ÀÃf¥LåR"” ÓÊÉô3L@Å Í’áf:á÷.УXÚë{©… „¥~Ó°~»LsYˆ½ ¥ã»÷®AN<$»L s†ŒiÃú“34d,¿ÆÊ«÷kTÞ<åËmÉ1‡ß-·XûWªUvºWM÷V|o%}rÞ·ˆ¦°~]tË"‰:2UåÓÚS¾i4ÅËØ™DÀ(–pÃË;¶Ÿ¸©÷\ÎÏœ‰žÿæš|Øv¥ŠæËHAë‘qe]¿å¹~š•Ä6nßg‰ióùRrÂC®,Áï¨ –N÷³É3žó ¢ãO„ÎT_rRÑÕ®ù 7¡Î´Í‘öJfò.¨,ò a¤Îܦ>Êr® p —=úcývR "^gLßõ ØÎH“Ûâ/Œá‰/úMeN/L°Ûw6MsGb×´v¼׿Ôm8[¥Â%!²±“¸ÏâŠê¥”ñ¬UwŸRäp©e}ÿVZÊK®Oxe4‚Χˆìc“Yð»W~`É;b~ó’¶!¢îç0q¬Å¡SÿÚâù'D¢é«)Á•°5á’©U~æ·Å#@{£vs92—=èòĤÿ¡ù'9J}r~#­èÙuù9G£ÿíÛÐ[ÁˆRIËAn²&'gä×J>j‹Æ²¸îk¡gÑ»Ö=v$9ç¾’ÃsÞ íÉÝ#cæÆiÕv}ž9&’ûÏ&Yf;ÉßÉ?ëb¼A#ekÒxÜD7ó·âoŒûõ•…¦­.¦­ÄÝñ5«„¾1À2s[‰žªó-*Ìh ÈÃÅôÜ×(Í9I5dýÈ-ÓfäŸÅU(…{‘Fl·vq¦ßWHñæH¦^,˜œìY’ ´’“¿+È”¨Ó¾©ºo¿È¬³á^%@ÝT5½°Ìö2(ê2žÃšíM²Ø1¹iÆý"£KŒb[²Yß•uA7ø‘Olà±ÄD!|dh•cQâøPñlÄ“X¶šN—u_S–FÍE¿•7þýžœ!TvŸ1õÂjž/ç,×±{áv÷ö2ûrÝjYù.öT&–{l€AÈ933ÿ1Ô¥[ž6/~⸱^\êãH8ú;Tö’’vÿU#‘ÖüòUïÞ4ïÚ÷ïÊRß; ÷š²J±>wÑúUžEê]Þ½™=†ö¶OQ ¨…„w¡&&E ÓžÉmÏ¿…˜uý*³?ö:¨ûŒú‹+ü8V9>jˆ6+:Úã@’Ii+ÙdøóIIðdGˆ®Kì» å9ÌS1gÉzf)"ÇÓOT Н¶‹ð _3UØð7¢IuHÄ|¡õ9úªsIëLÑìreéë†Y9H È‘Ëúp6tÐÂú+ꟸ…Ëckcý¢U,—ä! ¸Hb´¶aåÒŒäY»—+.ÎÛ¤e}Ž Ô?ÜeJôIûžoÃܸßÞ‹ú}ŒñÍÐÉ0Ñ]DH‚ ÿ’Ôî|é=~wÜðhÇÍ$5£¤¿ñÆ‘)T÷€·r[„£3ÜŠ‚mn[Þ¬ë)ýàïÀ¥ü…{FA¸í“Èõ%Ub³ßý¼v·ù™¡£ÂˆUGÖɾü”¹˜í3µ2þÄiÏç^uÊñÂÚqš Bì_YàïóU9ä:cKÇ Æl¹Èmâ9±Š©ø)™çâ¼o¿£„>x1h•õzfY.ÃG26áòúŠ´› §úZ}-ujQ NŸ”Y˜ˆå2Õ£@;âh­ŒóÄŸF>opîv/¨ãùuýâ{ÎK3àÉÇy‰Œ~]5ó=¾2‘Z L³u=^vȺê¶þQ¶¦÷&pÓ½7 ç2ºø>—ö!’Q܇ÎLÅÃ)¥ö±âç/øoïšp«\Cqd§%ú&'E´7ÍxäÓ)ìÑÀä¤ony`1FµNËA“Т.±R“[¢ðøì²^wÝ?,!ÅÂJþ¬-¯é•ˆŠèp4to÷%=¸õY†­Øì¡9®^ÁØ%<­ÜÊd×ãÆ;_"—Š_±ì¹O™¨ô Hê7oIUnd%¥oÕ5¢Ñéià§\Cý*Ëñ÷|n¼üÊM·"Û˜çZš²iù¶‹ôGí_æ áöþÌœ ®ʺ.ú.(ö·»¯QK·"Ft±MÓ…‡'¡Ì–õë^hž"ÚQvz!ž80¨»iHò¼rùbªÉ·6ØÏ£¤Q©}´P¸;Ä‚øãšê³€¾*—åœÝ-wì"±ÆvdW‰ÆBßC6‘ïwÄå58}"Pž›+)ÈO|ƒÔ‚.q…0u´`–EûŽ©××c?GÔVm°ÝNn§­8~ §0’½ãpÊŠ+ùeÞ™ô\w¾B åÇiÉWmÄ“•šíéj‹‹îŠÓÏ…¡‚~ã…7]ùB=<_OØ `Ogó…ÌÉ ‡$Vë®Î¸°ÇÔÝñÀˆIqÎ*kUÍÙù(+9é6ÂMz¾R ër£§¸ÎÑ4Vó‹&Eÿ¥±0›<â >‰¯_/`\G5¤ìÆév˜+#×ÎÍ~;º'ïŽøM`‘¿gØ‘÷)?jêŒ1ÚÍŸt¤„r«1+GQõ0B†•wDFôBж›êjc&O‘ÅðI8«Òø²!É|+îµÎ‹ì_…#²âWÊ£ÑwK|i‘äFëê¥_sô8Ì1µ6&ïÈ¡ŸüFÿ’ú‚S1<ßï Ða7¶ÿۘÈÓY­.Ì“b >œ…Að{u…­l á¹´—R°´Ü hSÎ&îË(^éÊÅ— ti§8>Ч¦I}¹k†\Ò;CÄd…öá±tÒw Mûƒ¼yxÇ¡tcÿ! kçN·:T¹Ò“k3…ôÕ‘™K؇ôë\ü*ˆ–;ª›ú~š°e(ŠÑ›½|!´þIT†Âq¤Ýa&yÉ_‚U¤²éªP RÌwdÔ_9i«Ó!VrP³¿ Bx•¢5Fà‹tÃÈñûÕÑhUœsƒ7â|ò`n+T8q¿h ÉžéU]âÌòý°…xQ)¥p÷þ¹þîñ×O‹t¡J»ü‹îOÒëi>G{¡ œ’þÙÖþÚœúSÖ»Öäl9FùÏ’zØ yB®<ù“M*<ˆÍU„…âŽJECÁ·}óT¿¾Il–sݾ ªFÙ­â~”¦=BßQ´|2þú8"æÞÿÚ1•²LÉÕžÞlg×1õm´{ãÂ(ºÏ)Yöʸ†5Y‘+Qk7ã$ý¦Uñë-YÄK.Z•£kN‡[Æ‚ôœµ> endobj 3415 0 obj << /Length1 973 /Length2 3140 /Length3 0 /Length 3776 /Filter /FlateDecode >> stream xÚ­“y<” ×Ç­•±”%r%ÛÌ`L†È6’Ⱦ$1ÍŒ1ŒÆŒŒ]#d«ìû‘P!Š”ˆ‘5·¥Å–’"K›§ïÚ†Dì¯ù"Z+:zwª”÷°÷«„ f¬U±6GÊ6qÛûÙ‹N1Fn>§FkI:YVݶ#}µ'4D»îYm&¡"Lù±¿Ç-àÕrʧ™Uq”åY!Ög¦ýX¬'ÏcJ–"±§vÈ-ZÔEØ[Knpø…à•χs8.\S÷êfÊ™ îÁ±c“ÛV*®èë?E|Œ¨™¸ù­Ì`Ãʯ7®sâÁ'‡(4ÐÓÉ8»¯`;¼ê¯Ñ]ÉÐü䆵rb÷îˆL¢GpUÂîºbFÔÜÃsÂiæ»rØÅ3\­:%[²wÂý;ûúÉ랎6u)½A'´ñ‹Ö‚´»B™ :‹¨Çµ*Œ«ÎæMe=<­› îé7ùýrÄNx*ªP-.ʨÍ|0\2}-oqUÅ@²^„>/ø}sŽôJÖñMp¢ÄÜXÛ¼èËÝá«{Éf#Ë ÎÖ à 5£b`èÚ< ï2Óü,go·¥CÚigu¶9.Ò9F*ÚV ;QdUÞƒ?Ú~qâ¶\BóÓûòÅ9,Ç^lêÏJª¬‰Ãöš„F^l¸›aB?œëF¯ïfgÜrQÖÍôêvvä¼)JË‹ˆßÚ–€Äï­1õ¨cu<=áª3ÇÑ™ 7*›ž/\VÔq4«Û’¢S]^>C–&eó×”ÒÙð×`…,ãÇPûvî8*M¼µxö3#d¯ ±ØílÄWéÄš[ï¹pO¦o7Øèu{9Z“§DŸ‹Lšn-,zp_Ñòù²ÈkÜxÁkÙG SjGð(X#*ÓÅéà(¶óƒoÂÁØP÷^í‰ë'dç0¯+Â?pY3 ¤z•ÍI?äšÎ6ÿK²Z"¢¹´ò}é+Ûˆn{qD«ß²½Ã_îF«Ñ¼ägí¢Æ8‰3ù»Ðèm` u¾ø6·@ßIB<I{*Æ/ïÒiüÂgnƒ3ˆëجÁO¿9^ÿøÆ鲎†ÂçíœüãZmBÏÍSª#QÞm4éwr\2mµå@ˆŸýFª¤3ŠÚ0ã 뇺WX›¾–´oúNÞæX4µ¶ˆ<{½Œ»êsð釲Ôï)§Ù a…)a•šãNµïàe ë^E[Ó/5š(ï¥÷é)8)¶ óN{A|Ñ—ÎŒžnÊ3Ï`LD ààWg2N~9êPŠ•ƒÎÒ(‘Gï–Æ4ÃEÚßô ð2Y}´&µ­á4»YQCúÕÙ6Ûí/òÌÛoEè匙`;Y í"ºy˜³Õ æ~|‘Ö•òíQcüw ”5¶(›úéÉ\¿ó¾ž!ì²v•Ng0x:©h'š>z¿êKk…eGjQoëåB¨zÍt¿tšwlpŸ? ãäãQÉÅ /y¶Þ#Ú­yŸßžs}Î;ü0|ñîß§ýoFQª§<*|?* T_Å«m«€"ê¬ èÑçåî˜OÛŠ&ïçw—Ñá MYmGÖ£.%È-Ýakéï=#†9ÅuÊâºFrç£~9<û.õ~ç&DB&Ñ.>ºŒÜVR!‡I÷~ur7V̹¾QîgJ@®ÓsFfáêøä\o˜ó‰FmúóUê«„2lkít“·ÍX¤*ÙOæ- Ø'h*â¿kÔ¬Žc §¦êî7VÛKÂ×hÜ.ïgw’iã’z6#;œÓiEƒˆ ¯›c Bœµåbkç~F’Ñ®'>G›õfË|bš´—‘ÂÙ„†~k&'Èù•‚’ÉY;>žOÕOéy"4NŒf}å«PLÀÌ3E™Ö¦¾7)Q¸Ý5Ôa­æÙA®&ÄÅÛ.˜ò–­ŽïGW­yÞ»jG˺*¶wöçý.E*3(ÎŽÐ+2—xK·…\=}0ZD°Xø¯6ïòEÒ¥ðñLoHÅrÎéOß;>Òº·Ñ3{RZÏ2>:ø‰$é« Å5% åû©>†â!°ÅdM4\{+ðm‘®Zo”?ÿjµÖ#.½ÇS(K©4p¤_úÃZ*2‹ó‹HµwÑ´†’iNƒ+â×jȽøQ5AFÅÕÅ,@¨Ä»²À×û¼c%ì2k«¬½þ^÷=›ÄY±‘ô ?±èhVwi}›®“[érñ䟛?ÌzIè ?¹ öBÈf¹}ħÌF:9ªCþøZ¸jýsØ÷ÎÙf3ô$ä&á™mz®ªÀÚ:§D½P“åÖ9‘Q±{õš3K¬^ûnuÅ zóÞœ\öô•2;ò|ÊÙ24ár¶sáå·Ñ@=yÓªBÇ=±] g[(¦ó §œWÿT±Ã»(ÚzÔ\=Ö¥4P¤9ÍÓR~O¼oœ7-W±^ãº%¢‰áûò@Ê¿áL¡±É89œeïéÓy Ã+Kþ"v•†û9U*xU[jk['!2çnuÖ~N-2ÈLËZ5>³R%={¾»ôõ_ƒ&ížì{± æt­Nl üÔÉÈ4kÿ8°ÖtÚæèr-rcªç¢z'eÈÕµÔú•.œÆr‚ÎÞYóhš(Z¾vxDNYúYþ”øìäÊÖÂ;¶C^’=\ÕÁéK'a Þ×']6ÝýÞ¦k×ë?'§[5ìnÁ}xTW™žÙùP¼W̬EÛ‡J.ˆ_.õ©Û+âÈ‚”ÇX ?3o|IÌÏWþ̲¶ÁÐYIɇÉÝ› º&Ü×;¥‡g>Wòm<ö.R†ó\›% ×›¹O³ÝNa¯Ôšû÷\Ø—”Ó´Ã]šZožxön?4 ÕˆüNòZ³ endstream endobj 3416 0 obj << /Type /FontDescriptor /FontName /RWSXVU+CMTT12 /Flags 4 /FontBBox [-1 -234 524 695] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle 0 /StemV 65 /XHeight 431 /CharSet (/c/e/equal/f/greater/h/less/m/n/o/p/plus/r/t/u/y) /FontFile 3415 0 R >> endobj 3417 0 obj << /Length1 2279 /Length2 14127 /Length3 0 /Length 15355 /Filter /FlateDecode >> stream xÚ­·UXͲ5Š{ðà2q îÜ=HpgâîN‚;wwww÷w ®ÁÝÎüöÚ{‘µþÛópÃ]]5jTw¿@A¢¨L/dlk·µq¢gf`æˆÈ©¨p˜˜((D€Næ¶6¢N@3773@ÈÙÀÂ`æàaãàaaC ˆØÚ¹;˜›š9¨Ehþ âYÌ lrNf@kP#+€²­‘9ÐÉ dePúg‡#@ ètp3 03ŒÍœ†@SsÆIÙ˜Ø8ÿE;Ûýß’ ÐÁ$ @ II4¶µ±rMåmAµ€ %ÿˆúïäâÎVVòÖÿ¤ÿǤÿgÙÀÚÜÊýl­íœ€9[c ƒÍ‡ªÿ¥Mhlîlýß«RNVæFB6¦V@Ó¿(sGqs7 ±¢¹“‘ÀÉÁø?4ÐÆø¿5€lûŒš¢B’tÿçÿ¬)˜Û8©¸Ûý;é?Áÿƒ™ß1Ès7€3(ôó¿éüW-1#[csÐy`ç88¸#€±<™æ6Æ@7Ð ¤—‘ÁÆÖ ´²Ä`bë€ðÏ49ØŒBÿPÿBFáwÄ `yG\FÑwÄ `û7âd0Š¿#f£Ä;b0J¾#V£Ô;b0J¿#™wÒ"ûŽ@ZäÞH‹ü;iQø7âiQ|G -_ÞH‹Ò;iQ~G -*ï¤Eõ´|}G -jï¤Eý´hüqƒ´h¾#Ð>ƒ#VÐ>k;Ð52 ÿc™Y@¥ ÌÍÌ­ŒÿæÙXþ¡AgÙÜÑò} ÉNïùA ßh‡¡‘¥£•£Ù_ùÙþ¡þ"@.:­€&NÑìÿKÿëÿ;+ó¿hK ÓÄs³þ›ÿ¯ CŒþØAl­@ïÆ¿cû‡±¶~7†™ äÚ»#¬ CŒm­¬þÖ º ŒïÞ€>#ð?Šrü³nï zYþ¤t ¬ ¬ÿÊrÈä= (ÂÄÜ寴ÿ,Û:ÿ]bú^´núÏÛ ü;ÔλÛl ÍÜíÌ€6E€8ó¿ H¼Å_tF,ÿ‚ ¿Þ›àcttükäî_1ƒÞK±ƒrÙ˜Û¼wÄ *mãlmøÏÓmú—$ЫÏhû.”Óö¯]ÌÌ FíÞ—A5ì €6ÿ16æÿeÿsú¬  #n´ù+”ã8sÛ÷³Œµ³rþ«1fcÿÞø?ÈèøÏgð=7Û?¤­ÐØðÝ"nŽÿ%ÿC+÷ÿ²ÿ©Ž™”â¯á1ƒüy×ÀÚä´6ÿÏóÊþO Ð寉²ƒ’8‚^ë7êù¿.3HÕ{YvWNfÀ¿ŽÈS'WÛ¿6€r8¿7ªé zÉlþ èt¸üA‚]ÿºÁ ¤nAPU÷¿ h¨ïšA™<€ÿRðÿ~Ì„…mÝ<é9ô, {Äz‹8¸¹¼ÿ#ÌÈÙ4|§ÿù+ôAü?lbúzn@#„¥y[#Þ‹¤Æ ±¼_¥Ð´à¦M1òuÝ3ˆþ‹?À­ Geìi×kÕËR1÷ ÷ˆ]ŸñÃÚ½¾LˆŸ}·Iž{ÝsÑßKõhÁW¿L•sßµ#½ó?Fikœ½>aW˜^+‰×ÈÈ8<ÎQ¤UÙ‡]%ëÑr©ïI ààTOµR ¬¥d%QBM¶/ a ^sE…Zûéïc ×L·raÛîŒþ˜—÷ªö`îÇ"œ¹ØôÓâsp*= ó¤žΠº>@ãÜsÏÆæ9–{¡Œ±9l˹ùäÒˆD³Ë‹YŽÌMk")Ù CpÒF¯ýäð뇥©vj*ûebá-µŸ¾t§±Ù¦ æüÕq\F<; 4b†æô5^æS<ùRFsækz˜=3«`­äm /ÑÊ9oæµ)Êoæ…9Ù§°jÂÖ#Ç=`ë1–˜Ò8Òi#ïltêA¹m6©ðÊÁ²x£Œå3š #lÀ%ÖsøÀ|È”¦H8æÍîzm²`8¯±á‡mGZ¹Jk¸¹%¶!JÜ£ŽVØD,m´/í]5‘4…<þ`++™¬dc~¿X“›èJ¼np­åNˆVBMv%»—zâGX˜QŸDŽðƒX÷„Ê$]Q.xg‹(}0ÉB¾~Ƅ¬¥M‚îÜpZ‚îŒÚl¥í¢>jtäNóEOK¢YS5üž NÃÐ6zŸ:PQGî°AS‘ÛÑQÿKx­'«”ˆ1£¾ + GH…ZH‹é•hKØ€x ‡6 íeò2Ol¥¦Êáþ-Knï›>¡\>¾øý4f€"F¯G^šº¥S‹k­ÊL·LÎñãKçó:*‡âS‚ía k™}Þãj`Âjšäô6àÅúœÊqr>£=òšÓ­PÞWɼdÅ9_ˆ«#9yÍwa­v˜À9›¿é¶w—6§µ1Óºú«%lw›³Ð Çå!,pouL§˜¦}ŒvŠsQ #ÙNü"ÔpJ`+<½¶æÆ3¶dƒ¨é7¨ÜÏÔƒ—-Z}n!W‚¾¢ÎÌúng0?ˆˆNô'@¶,šl¸²ï;XŠMÍ»U5h¥ÄûÝØÛ¯c^£M:¹0™cþéNkâzÅS1Re´7yí*\ر!ïs¯©tBžöô¹º^’„*är&pâ QéÍ3«D¼X…ˆ„EãU€J.îæÞ‹¹¶½Ç'Ç!WáÏÄ2§\ÁÞOšB÷Ô5&eþøk“^š¼ˆ.­r%Æ9IŠ~8f~zl¢Ápï¬ÊŽxZ§R9·MñÿêXއ¸Ã˜ÍõãÏØág¿€´åÍ]ùH«Œ^²”!ýh €û{VЕd$n@óCQü~?#ìŒa;ΌՄ §ãŸ{´ðŒÀÛÔ?L´`c*7v›`¤ :ù^èhz/ÈÞÎ- õ‡3F§$ ЪòÑ£úÍK.¼ŽN¢Å(» ö:Ê3D|Lõz xSxéFuëé*Å!)ñŠÜ€%o>Éçx:»°²Üp+ªˆ=KfùdÌ µÛ¬Ô¿ç!ÓÙx–·–Á®`¼ÆÛºš1˜…Ýö%x›5Šnð{c  gr:mƒ\•F.! ðˆ9 mÿ{2+iì¸úµùð‰E|pÌz âL…ý;l7&ÏQãÇZh’sÞczÞì÷ùË}S?í­ý-ÙOÒÆK¨a«»f»? Ë辘^ [½ñ·:šŽ8§²¤+I LCÈ“éÉ®FºìA.Z‹ã·iFà Ä{d#Ó’l3ôtëËä¤UTˆŸ„¿ñ‹ .bè…Ì;§®1Ñ7§Sµ),…Ïh>‰ÇŸ³ûåðŒÿHG°íHÙó @„|Æv¶ZZ« ¼tîǽòÊ­^øÂ Äu«é|bÞC½¶°2)]]u¸þ*Ý: É»å5—nð†ŸÂzøÅy*ø¹°ì†TôC R· ‘ e—qäÂÌa‡›ò¹¤äã¢mí–{»ù‚ö©°å}ï¬eAiÑHõÕØ1T¼Ý›Wõ`gâ¶/ô¶-rå? ·=Ií‡gh0_gÈÉ1Ïˤ(–Ú<†tI]ó$czòɰyàù¤ÌŽàþÐ(T|©ž{ÀÉ¥èO“ÌÛwo _1Õ3åFjx[‹B\ÅÀ]TÁ»pÍŠsËg}š2åðñuêdýÓ#€‹;Ó^Ò’‘µ#®.¯¨1(Ÿ]vy¢Eâ.òÕa`äá~ÅÅ@b›Dì¥z…ÁQçAsIÜ¢èDW€»;¸-§³×LÜ ÄAœ3u$îr¦·ô1¡{ÐÏn‰[Z H “ÆL¡×JÔ;w›ÙPí‹UºOÔ+i›(ìÈæ¢#ÔZé%ךù“jOb6§»1Ü I»ØòÃ"OZMOSÙïŽûH>ÍË€·¨Á1ßuÇpv¯èXr¸®Á{ÿP“Þ„#’Ó~y~,w=÷™•rºãcóÙÜh¦®ïYpÖ¤ÜM=iÅŠ›¹·k[oå’Z¡þµ*ápª2FuŒ  ¹êâÑ_ú=Ül•4wŽÚdØpœ¨ÁD2nÈ4¬(ß$ÄMØ „T Ò†Ñ.žL˜õtY†´˜ÆRÈÏ-¢D÷pÚÖË*ļ8|þtÜ;k{JilcÐæt6cÁ²bv°ö-ßoÇ'Ä·b…‘j'.Z?‰•|e܈Y˜’I¦Kˆa`|“ù)c1x‡ûlØ\Bª‘‚7æxYÃåPì\tYž¡¾j¤1t2å¢Fº‚JD.¤ŽÝ‰3Š´QKµ¶j´cp™MaÌ z2JÇÀ‡sЊÙ€to)ÕC@ƒPÀ§ýÔt¬ š÷" ÙDOÖêÒ ¯nr4åìSZñÇI¿ÐC.¨œ}%ú·ê"©Ì÷,[)•ö1›XœÇ3*)¼{Q{+LÛvQòš_Q¸åkãbà˜>Åßú:^ÎòÎÌûú¾â±:’¾^¡¼~Ç]ïC4›‡oº›‘ïkñUó[PŒ¢yœÅM²Q8’\†Âæ2¸!šÐ=eGG47‚_«ÉS–ƒêðíZ^¬¢æ,ÖÊM*sŸj^–­$Þ PêV“Ë¯Ê v–¿#7åø‰2¿L•!¨³uB´ÐÏH>/ÓZty2Ác¦—ƒå›>^[¶Ö£›]¬˜×úÁ{8^ryÎþ- ûÉk|ˆ§…Ž£q¡*éÉî¨ØºÛ…Jtíâ;¢‹;ê…™W_CBŸ«¼RˆÓíO½Ø!¹V‚2¼ü 5å“HxÿnßìkƒJ †¬£©ªêV®1mž0_¿NQéLƒî°.µ%ÝB¹^ORza}QÎ¥à™^‚žnrí‘„8¡ õÊnòüå©w`·p¿Òd2æKÜ®.7$DbqxÙœ<×möS&±â!ëáSMñ-ÆLÉé³]4ž‰6úB ÇL’Alå'u%fÞèW-j«úcØ)ÏéÏüÔl9ÏLxÎ)w.WNÎ3s˜ÒKàöÉÉDqϨüÏçâqlÈÙqÆê»jgØ è–ü~¤&š>*°¬,üXÐã!¿á¥ŸŒ_Káê.qï&6  ß#…¸ Îg,6Sæ8£|èP9‚O{É1ÀšEíyh üE›qË.;rÌa§æc¸ ·CÔ¬…Ÿ§ÁÁR%ÙÈ·“õ€¢0DY(`QAy°˜ný!å©€!G´+¼°hªdûÃö2ºÊíïÄ_QR–ïIàcÊÄzY-DÔ\*!ªò¨¿ìï¬|YÏn£eÈWƒû3: ˜N’‘¤‡iDcéFJó[û×:ãKå´à5¨Bè|G ˆTQfáÕÐn\™ÞaÙ·è Û4]Ä€ç´Û ‘J%ñ|ÃE ø~DG{úú}ž„øÝó"Ü´¡=F´ÞPmë¢vºv¹íço>ša㔆òí÷䥟ù„YB´bxŠ,ï•ô¢ƒ¯íû1¬vº¢¾«U¦t¢âŠhXýjTPßKΟ^æÔþ°dÊ‘JKºc8´$ØË¨Vˆ übÎiì> W½eöIŸ)i>T%„ª ÿrc‡ùù#; ⸃j{` b-Uû JèŠ_EßfšÙÓ›„È-X溺Ïð´2_¨Êó3¼gæ}ðç!è›ã]úºYBö]ññök\uŠXä¿×Ý~ Ny¤Â8“ľ+Ã÷eÓŠ"? JZ©œKF!ØÄßÌE4îB9qQñ t‰ÿŒ‘ãmœm]äüúuåz‡vmæ&BÛ¹KáZ@ñ|0 ¾+BÅTí•ñ±C]L ú'¶¡óù¯Ã:uœ3$¡c?Qî Ÿî ¤9ÔÁGÌQ˜L|=™ƒãjÄë˜qŒ}Ký¸BÁ*eû°È[í¤åõÄ™“££‘ù´Ø7£D)µµ$JHA0½h¶èŠŽð0+C+Ú‡UˆRÙj-3üVHÄ”ŸÚ±±Ð¾aX\|zÌçØ(<hà©Ãä›Ú†EÉFPÈ$þâ¶ëAy*΄?RÒ¢ºÃŸñÜÅU`Æ›À5j."Û)éà~žÖ?™£²¾“/Õ·7ЙÅ÷¢,›ù¦^» aëïÝ0Â+¬ÞÒ%]å `š§©ã\II¤ÆZÌ!C X˜³“í_2§Ý­=;}<.œ g4ù_(.IC_g~Üò2Š\$?{‚4"˜£ÄnRU×t+ôɼ¬¯Íâ(¿Å×Ô*\À» ù¨’¥CîLcÚbÙ.O§P£ŒÐÔ…#‚{hˆ§ ‘‚¬ù¤ýŠ´‚¯»¤‘ýr‹×Gßš–øNkrîXCmáBÕÏ­ÚÉwT;+Ë÷Ì”é Ð:G¤ZO‡Üzï!^ðûpm¹>!gX_·C³ˆ¨¸©zßÊêæ»ÉµÁÃG9ƒmeô°[n\¸hÞ>… 'ºœT¤’âgaèKFá2s?„[µ·]l þá£ínb°ë»…cœ§öa?Çê ¡¸fêïÓµ ë‡QCŸhœ]·è[aVå"5‹<Ì9’Õdñ`(/;êNô0Æ’˜ž?©½ƒH 7$²Ù…9ø¨Öqc.…;n¡–Å+ü §ƒUyCrÔºMTw¼Zýp‰ðyl=MüŠ SÇ€{‡ZúKUŽâì=žž;Ñ_G‰‰>!ùÃñ$°ã‡4¯ÀEþ>|…âÄ—`0DÛôZ(l ø–xÝ×m=§¯a¥ê^b½büÕaoNÅŸ4Œ?Ñ E„”Œ—ØX^û+ršâ)Dà ½>ÍÐK%3ç£æÚü‡ÀŠûê`ɯì3ôb¤h^`(=ô´#QZþ.JáÄG$âåKϙֿˆÙ÷=]Ñ`?„®RGâò©Z1Ð[½Ÿ·Ûà Ô§©jE©¯ ÍwQí¬5—^ãåŠÚDûûNŠƒò¤Ç[=ÿ¬k˜­}Æ)¢Ùmp0¤+p<Ì×»)Ž]Éc´¸²› )StÔþÝñRJª}˜²²êÖ<ù{ôaGŽƒþMÉn_—¾öÜ|cL`&ÎCaÀOÚÄ)$ƒä]§œsçµÓ¾†¯v‡>E¾bÛ|S²¶;oÀ覜‘ú%•[\™#O§Bããw¢jgwªJ˜Ú¹§V®.ÂQé«7Vó\ß[ø{Úuiš;Qh ºýfSGWã¸~{|­cé–90Üz :¿LA3Û*{}Êö&°úA¥¶}¿½KGà(³í#€Ù%úšAž+l>û¦w+)Á½¥”3Ór»Ã>Ž¡aÇè-xÍŠE¾¢¬MŒøWn “²8Cä6±gž?‚âáÜq·!ït2lÁõÇ]ájáq¼@gÜ‘1ìû]œˆÝ± þ,Íä<±ÉÅUã5ðT&= râ—[‘S ýw|˜Ó+©¬oìpMjŸd!ÁìÏù(XˆâíW>Myü'û’.ÙãÑ}Ù¼zÏ›4¾mÿZËÜÖ¸@«ÄÕ “‡Ö¨€ýÊKÑÌ”Iœ »S«>©9ÎÚFÚò¸LwZëÒø‚bëzßä53Ï™½‡ h™)  MbÕ¯_P'+Jò÷öü©ât^–ŒÒo>†0Û6•« öï_O¦~VŠl„; CP#&Í9+ä“£ÏD毵.{vôo= *u„| Á+Õ;»Z4 Ö«¤—0©À?’ZކÚ€¦*úb®4;#´±Ùn|û¢ì>Ûç' Ì~×àt¼ÐÚ¯[—©š1{ûtR#åíõ$FÇÛ™ ™è(åúÑ ”ý¨½þ‘ŸKlàªÌ4³W/ _;‚~F¶ßé0|ñQYs³›>Åô@¥+[Ê­°%ætdlDX"m¨¨t=K£ BM^ü£Ï'ðp®‹ë|wˆ.åaþ«ð)šo(Yåxjk_•»¢ŽÌ«¬ºÈGÌ‘Q”i.Z¼6ð,?í[9p}Û·¾™Dã-‡ÇnëøŸÈ—`Ö}à­\sfš·Öïôx ”2z˜¿ùiÝÍ<Åj/ÆY£EòBÖ ¬ÁË£ˆê ¨»¬‘‡0péeÕ~JËihǵážê Ÿá@ú”¢Ùç{r¦Ú6€±²–œÙÓ–þöÒ›xMËjðÖëRBE¡ò=Ëô”µp»s~‡Å‡]QV™³ÜP–-2[ð+W ÒÏi͘8’§s‹êb|¦eÃZv+𯮆å*Ân?fÁϯ?¦ÁärÜh[xÔ¸óž_PêòE__ë$á±+lœâ-¡Õ‹.†E?Øî ‘±²>e.”IQ{W_>lÆË?Fœ—$Ò'¨òœ] W‰x ˘²õhÙZF…íw‚Õ…¶¸¸â ÀB¿m8xnâi.ª$“á?€“%~hñi)R- ´1ò{Z0Ñ~ ­¶/*LºÕ ½ƒI÷ ‹rLˆì…žîé2w‰Á¢¨à;R©*œ«8`rM©¶'¢6ø\‚BÉ£àŒ½9“ ó¬|”•× IX]4”ÚFEµÏ]°ø ‘„Âì›/ê¼;ÅTÍLH nwÁOe|g†pЯžãÒ™Ùì /M%Úuv÷´mQœÌÀc²¤$›(®…§â»•û Z=„"=?¾â‹e_ÌYbÊL)É­M¼ÃvVYtpœ{]oŒ•ö—cƒÀTÉ€<Žè?_ âeí–]á¾Ã“ï ¡?\Bã[‚a .¹˜\¬#®-''Ðaëc¼¥f T"(Í™"IÙl¸‡iöÁ>'#Á…aP—cH2TõÕ 3÷¿5®Ó:SÕ~jÔ ˜4Žsü§ØÜŠq2Õ%ÕDôñŒµL àFÁÀtv”o—G»­ËÅšzêZù X¿éñ5ú‹[|Ú"pƒÕÎvDú$–’« É6ºÔ?ÕS.L•L’-TV´#jŽ8º¶·É?­šÔl†DСoB¾öqÉÌÀoó׆ŸXªú>š'¨$¯Ó·7íÖ(4« f†Ÿ‘§•­Ùyæ rüWù'†p`ˆe1“³Í6ùMåNbÊ·§Ã‰°}ë<‘eü“¢¦®)‡]¶ßL;gUŽ]‚?è3 Tç‰}"¬€]PôX›àmõ¼ˆó‹ˆSò{Œ>Jí Úžˆp 왡yuv>DõõË_1礖Ôn ß\7ñËXb„\ ¤HñWœËøÝèÓç”w5Ⱦ&¤—{W‘Ãܬ9ÜùÁÌ ë¦W$Å  -P\'G»1P)7Ì)¡Ç%Ÿû˜E4Ö·œÄóôT¿U!KäEzwÿÉŪ[è·c€¯¤ÿgQ'\dý–™Xiá4«rEQ4ˆ×÷šç!îÍÐÊKâøÉx0lí2ᅓظHù1™ÈWÎþ…«ÕG¦3üÈ–ß8[n}rb‚ëú(“'+wRÌ®ýÏàðŸìLma¢åpµŒî)aG‰\e´“û‰_žì#Þ´ZÓÐyˆøÓè;f^½œ i!îR}Œà¤Ôð®v UõíœNÑ=ÚÂàÙ¯¤¾ùµJ:U®A¾©"j‰Ï§€3Z:8ë¾Ü†ìÓK'޾|Ê›ÈQ-!n~i¼Ò—Ú^¯”f Ðp8Ül’Ù#=-X•³¬‰‹>Šª nG!Bh Œ!LÄ}»/«4Gß™e_Óm©S:ïÆÝ^™Œ™ïKIÜÓ3~å¯ÒÕG´ÊåÁæÑÄØKœEOªjô­h:`7ßÄ¥ÓDͻݜ«“³C~¤ÈŒ±P¹¦±ÐËa¨·à”Žq%BÃôgRÝíÌ­¨üÓS½ý\-q¬l°PY;‡‘á#+rs6"ž“‡† íGˆE’îO3¤+Ë UQK¤ÛÊóf}$XK½+ -\v¦\žk9þCj “S—“^©lüÂuôaCÆ‹a Vt,§¦³òÚ:XU<ä Êé’­SFã¦!e¬}á‰ZU÷ôV)³Û´ý Êè ˜IägØ®ÂChG¥ã“Ó¶l\Â=^k‰*ºÅQ îSÓüf7`9ç.t#¦¯á¢b-5°\© çÓ.]ô)Q×H‹ÜP ¡´!‰ù e»ÄFEIƒêð’ûSAyr^ma¦GØ·ŠcÁòMµ‘=%÷ò‡JâOÞ+ ÖMbZ¢¶SÕ]i¼ÃŸÃ= ŸË eǬøF°µ›ÝJ>Ü:xujŠ;wõ†=)ÃdnX9†ÚÊͼºL1±êá~7´ÍüAóòn²S¯øµšP`ÉôÕ:÷Ki”þA´ÜšÄ>Á¸ÁþK’{C¡è üÉH´ðPêʼn;tÍü6Ýœƒ4lhF‡YçDò ž’©JÚB=wÑŽ©ÈNJ7ã<)ŠU)f.êã?°’”ÏñrKž¨:Š›#ˆ~ªÅôE8Öþ‰/Rüeci¹|ß õ¸ÔdÊ·Õm¿–ƒ=Gó›Î¹ëO_gwr5|®ûAÜù2wí“§&×6ÖdBy˜–<-Ì!ñóW/ L~´gWþKþ¢äOºX/óé3øógN B)ú',wPJcfàÀˆ¿!Zn¨åŠÅ@ +«&æ.–ïÌ4O¿PJÐzПÈ?3b\Éw¾Õ_Ù'\]ܸ<Ⅎß.e*mÚg̹DÒ«Ÿ•¡`|Í“ í'öÝ) ®ðp&Þ¡ ûYÆE[6a}JK^ÿmJÒÝM€â„¹$"Tâ¬DÓðk* ã•2wß½à>§-‡±œó'ìÉ:‹ª ¸[ñ¢¦n[Öf<üYTiƒÆ3lóéãhüw·£žA8«zLQŸé/i•_,öÂ)[;ãS¸Oº~û`ëøœóò5üãOT´Æ… ‰T;%Ç=`Lmô'$Å × ¸j!PuÛ™©ë3ʶzøJá¤`(Ä1{WP—V×¢pÅ¥±ñ­´KÎ… 1ÁýƒmÉ5J¡øý¹zh¯›å·¥ìZTÕ¶<›É·)7®zMFÈí’ÿ%û U‹07« ˜xº½ "þœÌ¦%Tž¢w¤s-lC¤,tBÇÞû\ó^‘My #?W½r¦ýI„‰¨‚Ýïd¸øY2™µväðøjGùf¼ŸôwX>P9¶ Š¢¯œóúG"$L`¬¼~l ³%¼«ë× Óî´ÿ‰Œ6½¡5Ý|ê¯ë¾ÀÞØÛ³R,è›kMyöd W’î}î ”£‡+˜Gkx‘¹®ž¿‘PÐæô%w*ÆžRbØD†®ï¬ç‰Z>óö4TmÀ å1¹×q¿ñŸê•6ײŒôÇl¥•ÔÉkNn…ãÅx$š—©<TiG°C_vä~å"È·èjÞú½Þm¦Ýk?zH¹öÍVzÀcænÝäG›Ý ø®ô²ßˆ[M¯U„<ÿ0ƒÂ‘ëŠâ,u}ˆo¦Ç1›¬¥,OLK ²²+;©ÙSa\é˜ÓF‘¢œ …íÍÇÛ“ÕúÁw0ô1’ÄâSã`x7N¨˜'¤ûØh©lƒ vI?øÏ`Áógó,„ßöúé¥ËÜK~SCP²;e—h]‰£ô©9ÇvÚ!i«œ^¯¤ ±°¹µj2–'áÃ!ÙÒŽì Ú3fæØáçQx2žÞ¾—·s7°–M%ÏEôTààZ§LëbÔÈ+¼4nõ²·½Fg«¾^é©AÐ|·Vw4|~Â/O¿ùø#ñªÉ³dFö…¤(oö¾¿ã›~ 4y6ã„IÚ§QìÜñÔÓýŠÆŠ„àûøºLx§ ]eTVó™³QLö¡Y´saÍž3š“2m!˜J£rw ²,k-d¡?"p¸4ìuøgBÕ‚ÒeÕ‹·Aå“wàu1¯q£˜úŒ¦A· œõw»pß{¤¢ú¾p‡AQüB<9"¦.]D…Çõ€°÷Ž™õ^e‰¦¶P~à6d¶,hUüõ:ï—¯á­Zi)ùþ¶“˜­%Áe=ºjj6Ëm Û8ÖÅÛ¶Äɼ"þ†“Y R(¹ÚËHL¢(œÍ”îïò§œáåx¡tÇ=nÒ[[5Tõv¦a„2"ÅGG« Ró©Ñým8fŠ:I˜þõhçð©ÑÚüƒôüõx-Y^\ËÈ2º‰yJ`f`ƒV[\™º£%<Ò•2aM(•´ôuÙæ÷#¡Cu¡BW{·bl|Þ0e‚Ö@)¶}O—!wú·ôºê© ¤Õ+­}MIÔÈpb=çB%B%‹¯²³O0Œn÷ã¨àëÉTõ²hêH“=˜ðêkK†Jkú?á§{­#­šRwèZ7v®Í pñ’Ý¥%Ó«u©|Ù»à´HKÉ^;cõ콫3Tó;Šº,´3Ò?Ó1RmGgݼ1LédIÓ†~îðÃoTÎ|âžSB"šóåRüJ2ט¶¬Ç•t =t®€0ìÁÔ‰O(ùý¤¢ˆ‰íñPn&Ùí[q3’ïlUöï5ïM-oq >øÈSÁUJ̃pè=ËG»y‚Š H°¡³*ç˜dcŒ¬TFÙ*ó{ðë:=ï×4çEhŠ r¹^#û`cBËk tƒ*îaŸ¶•Âè7󔯮6Ĉq¤ÕtRŒ!öK¤Ìê÷àúfSOæ©dfa€3ÊXãnöȪä^DÑñ¥ûâ>ñU2•”9QY µÑ1&±ð†"9!*L4gÞ“Õ[¹‡xz¸uŠ ü@ׂÎ/¥¾HÎK[URðfY•¾ÝY¹ LRMYÎç=x¶:Æ_ä0Ž”9 Žfߪrµm¨,9yE2ŸŽT¹9Ò‹g …5ÑØðû.Oz+qèT}=âÔ‘å›pHNG–Œ_w“…SO£Ëq8ýSm¬bÁü˜ú°ðŽ”î‘‘ª‹ÍŸîŠNy5¡>°w‰˜ýFÒ´3Æø$:zïVÙ‰…BpÃ`Ò&£Æõ¤s4T­‰ò îÀÆNöð‡›KlæOdSŽ\zsµ\_@Hï\À[Êô~8é'nqk>™>ô‡?ê›-™ÊpɽdBæX컟ž¦½Øõ1ÆÉøüÚ;X1œ÷—}{4׸4µ:9&!GÔ¬ëŸ$-qU›Im]ñ] ö¡×,J"ú ’3áÈê(8÷MÎCâøô4LÓ÷HøœD6@Il™“}ø ´NWDlGÑñƒ¾&Ô)Å@OîÌœ’ºgAE–ïõóc°Ž4¥ÑyôìöXOÌ0­ßJ{­îƒDoïRúl³¯UbQ¦Â¾;Δ4¸èß'í­2g"^ÒЂ 2YÞ®•B¢&3HÇÒWn §þ¾™wNaTs˜ÜÑd¢Á¯aoTÒ*‚ç ™¯¶­\—ÈçYAVŒ¿úùå,”à›{¶×Ú¡,؃ڎñ7úßïx Xa£¹í¾ÃgB—ù‡â:ªãŽ·rhÁÆURï3oúnÞã¸/ý#/ ¦-«§6óÓaúšpKÝt˜¸w¸XU]k³å U×қͻne/ë_ªwä\Dó÷ sìžíþ—¦B9q[#pùŸè8Ò6¯Å·{ËxeÇí÷Mq)EÀ?•ÒÄbÞ°ÂÅA&;ˆk6IÞa¶àÌ}‘¥u\GÈ1úÔïÙŒª'&´XN%úA_™‹ˆ¶žA{ï”Dâ3 «ô·ÓÂBVÏùHó’/áÌBk‚LnR2 ÛY1šmÅ×y“5?m/Žÿüà2Ê#Àp៖øÌM ÑËB„ÄB RM²œ{U#ÚQv”}µ· ¯<8Ûd³™ÜÕó1ÎÈ^õcåVcA*ç-y_¨®®JMñ½¹š4 üqe(­ð4}ŽÃ¢´ò“ÀQ` 0—{rÌs«©ÂgA$m¶«ðÓbv✮Q™“eÃKÂÁ°0é'™Ž§8ò†Ó®zÒ—»pb¥0&Žß]‡¡½‚À‹_VLøZådv—æu>Ð蟪W|Eò=âóä)Gp¦šˆ.»'ì,üÂk2'¼º»št±pPé uø'<2ëFgOµ¹¡×Ñ3YU}‡ßRD†²WwJYM'—æ#8 ?Ùݘ´&•1Š„v{bî¶+M}2-/‹s¸6ydvÏ¥Í ]Ë íã…ši =2Çdê°”ÓÍö‚%Ð’Wêã'Ž•^U§Ó}òq}†Y6K½nóÒ`ÿG ¨7ß/R ém¡¸œ*}ÐvR¿!Jª½ä^¯ C½Ì”csˆ#~M] wW)gëë»õQÃy¨vªÅÏt“veï©÷/§3‰z?Xå5Èd& ys,ñ?Þ4QJªé‘u¡÷Xù£u³9la^ðK4Š ï{¥œó·1Ü•ö¬¥DMêŒæSý|$.†æ­úÆÞ›ßxÒ ~Â5¤£Ooõú¤O•Á€¢Æ¥J.)ï(˜&ض7:íJ5 ™—ö)å¶ ËÀ“9V™IÜ¥¥_¿!Ê.eç¡%k ’Ø…x—&|ùlõÀGà àÎ!Ã×å‘"þØTŠÉpM£ ¦Öd9Ït{©¡x)kIŽqöÚ¢— hÊG.™“-~QÒöVõwÕÇB;ÊXë«Eáô£ô!1j~˜¥ÉÞ® OÀsè4d£LÈÛãrå Nž#Ïõç>#­>X+h)#AIQw3ývÅ9äØ÷ øzÏ_ð ”òoï9¿•†é·Bÿ•ó§-?!X²ªŠÿ7¿á·b‡pu^4Ö ñŸŸÝ&Ä×FsJ”û™¦HÄÒ`¯G|2lÄÄÃG|g~M€].¡pµ@›Cí®ÙK˜¨Æ*…@Ì|š;XüØ™ûjÜĉÃâÏ©kîë9«_ˆD{ª/P¬BOßt7›}¡øåÒi;ÔP@‚ÅË~Fºo|qÞ£(÷#Ó¹¬Ì¥¦…<_ðŠ^Ô߸„Ûª*ã†îÖCy u¯ÐWÃ=äߨ:|åÿdóŸ¼ú` …sjdÇG‡…q0–ϲOÂ.±°ÞÍ•Œ"™È{}JÂ7]<¿ïàK(¦èï=4 Å9JT$ÈÐFi@Z¾ñM-õSÛ¸©þ³Ìý¤ƒlÒÖ9a{SÍ=%úSºØ±}ãÙÿ491cçn5̼ùk îªÒƒ¬ç5'šÆVÆa'ÕÙ³ôO ºiÙ&¬©ë6ÁKسã1½—%Ï÷­Y1ÈÂCÚ£"Þ¡Þ'M„ÜeÞÊÐ˜ŠÆj¬²Nr¡ÔxTî‘q™±Ô)gBµ}wñ›"\Äx‡°epéë¶4ˆ*Éû¶c¦Ä‚–R)`Ï“ÄRo(8}Zµ-CÝópX8ÐèÄ\/c§[Lá1'.Ïz3»mXîû“þÖ3:(KFä©&Fxƒ(µ•Ì$WtWÆpÒ\]óhü°|xÙIÉÉ´íCFb†“Ø,_ˆì&Å|$µ€Ü(–üβO•¿„ŒWpô.p#ÚV׸M5/Ã\æ’ô, Çz47…±¼ÍÓig’©)eÉ zÈ·÷‹  û¬ÜÊ ëÑÉÇcüîZ¯1.êÏ!·ˆñçÍbÓŸùÝZø}|ù¿`Áìëµ1«kiÄg< 0LBÌ©Ýu§I ÀÙõñ“qó¥]{ë8úž;W!í,Žð±Ð•êœÌstÙ½×£4ä?s*Ò šî=F·£±OPž„§¹ošVÕ½µU©„ìluJó=eÉL˜Ù!mÈ¿ï}Ajv\6†1†p8RpQºÛ´!/Š[LLñÅØ{ž/Aº4ìEÖ¬‘ N—|þê䳈UøÆ£”-”4ã’ó‚Ù"û“ï3ÿì íƒ‡˜ž}­¥fr¡øLC¢ÈØœ¥yŽVùô7›‡4ÑÛWPs f*g+»G“Ú-DüMRÂKßÙÊU ës2ßJ¤-¹W–ûEPÄ"E39 ·žÐ:ð¶“0½´'ÙEÍe¥Fœ S½C”ÿˆ*’ Q&®‰µøà·¶{Gƒm±—Ncÿ„ '¢ ]GºÌÜ2V·™]gɡ厡«‘wm6V<ðêÓ Œàô®2¦Å:;¹ –?ŸÑê…§Ï6S×8|L‚\3ß·º¤<õ7ô„7?ìñóèFX¸3¥þ)ûÕH0]âãi»î~ˤøòs'ðè8´ô~ã#;‚8•EîÄ7ØQR…2ïs/ô8zªÓPjE}‘ÒÜ øBH[|KŸ®þ.û?Ê–-ùD¸ò’¨4EƽoñóŽz Z "š_-éM`¦{øÚ¹Óð d_¹ˆ~‡6öOe<‡ËÁRUôò÷'¬*.í~[ÆÐi ¹ÉøÅDä¥Íú£:qÄâb2Œ|L¬™e69š_Ù>­× àBÝ8nCîÎD½°éîP4·ìŸÎM Ñ#ë·÷!´$}¦ÂÁšûç¬V×DÙ“s†YûòŸ.xTH:UÖZÌ•\z¯!,<ÜHÏÔÉäjÈôç] bõtÔÞÞ)Üî±FÔ·°—N½­ Ö…ÆÙâÊzÔd»«±@|èl– ,èHúhv4áÑâAÒj{axZܳêwÔQ³ü;ÛamýKz¬HšBÍ|Zâ{Êøî¹Þgu¿ Oèr(ªÅ}]dc^§:ê,í†Ï…:&õ-Rô‘,/bÔA4Ú 0ßOÈZŠ¡éddFÛ¦r ɯO+ù7ªvŠ(ÆÓï`lWZ/+µ„²Ü>#Ë\çÂ%üÀ_,þmo<N&wŸË!BÕût˜6Ím³MûáÚÓ7\~´©ZG@©s@™~›¨ùCGñÁ³ø6Ú‰Æ}ö­j‰W[Ü·ô"Õ7U—fïÝç©SÙd. ¶¾™*QyŽ')ü.ƒN–ö ²cä ؈0–R`Õ1 ü!£ÿÊ Š=¬(W p[|q…=­)ã•ø¼:ÖÉw$‰\p—W%§J»3ªTdçÖN4”Xa@@ÿÇŸ…8(åBÉe ÍËú¬k[:ºyÙÄ£b5";µ«'‹c_P?×H¹ãLP[b“Ä5¢îzh/Duhê­t ÄÇ—Ð,º›ì2*ÖUÛ¹cƒ¡Ó¡—e1Êq»Fóמs’M²~­ŠÂ=†FÌrVCS·sYÑ ´®ÇŒs/^ïÂf ÑÚìva\SCB¤ûc°/ìæÉ–DšJÒl©'1tTüœ°š´{Ê–XXEXWäN7êõ¼&Ò3êÑOûý´P[B§Û8]‰´:ìÒÓðJ'0þÇ>&Ý ØÒ~‹E}|C_z¢ªr¿’úW Ë 9äúÊѶ@ÔA.)E`évs•ôIÖ@©Ï‘;ýo¬l*L.Éñ´ÚóN2ˆ©<§0Ö\s.ͨõ¡\pÚ¦?9E tÙ£³®G÷_¢~šŽìðš¬çš¥&÷Ér …ɺ’uU]<ïÔ‡ÿ¤ƒ°¯È J©4+ åÆsŒÆj´9pj©€AA1 LÄMÚE˜¬oØC þ¼ß’ëP*Z/Ȧö @+MÕ14CÀ "ƒjÏ4úŒÏE\r/²mœæãªç¬RœÉÒ¥fjg÷oúòC’ÏL"U—Âõ„®Õí³p¡Þ="•Mg®¿ƒ£<{Ù×½' EðO4ûRíj0f̶Œù.ȵ"J±žå…Ý¿§oÛ¿wÐâvÏÑî‡3ö,¡ baè°öœîÌ/v> ¿4ÿ®   ¡4§o€&ù„¶~u›j0’gÝE ®û1œ•ø)sèí×·š>ËÄ;þSÁÈ/(úÖ‘'ª«Uj¶çŸ{‚™Í‰UžÒÊJ[?¨ë—•‡D »:Ó$?Qoë«$`Çm¥¶†{´Ã‹ò*$Iþ?¥tD endstream endobj 3418 0 obj << /Type /FontDescriptor /FontName /ZDAHYY+CMTT9 /Flags 4 /FontBBox [-6 -233 542 698] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle 0 /StemV 74 /XHeight 431 /CharSet (/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/a/ampersand/asciitilde/asterisk/at/b/backslash/bar/braceleft/braceright/bracketleft/bracketright/c/colon/comma/d/dollar/e/eight/equal/exclam/f/five/four/g/greater/h/hyphen/i/j/k/l/less/m/n/nine/numbersign/o/one/p/parenleft/parenright/percent/period/plus/q/question/quotedbl/quoteleft/quoteright/r/s/semicolon/seven/six/slash/t/three/two/u/underscore/v/w/x/y/z/zero) /FontFile 3417 0 R >> endobj 3419 0 obj << /Length1 841 /Length2 1196 /Length3 0 /Length 1747 /Filter /FlateDecode >> stream xÚ­RkTSW†Q48È(Pìä%$y$ÚVH`oÁeHáJró€ja¨¼Ä(Êc@P¤ UªB׋ˆ‚ˆµB4ËÃBxD¨¥ŠÒ:é ý;뮵×ýöþöù¾½Ï±·‰`ºùr…± @ˆJÝHî$ B¥3¨!þ$"Dr'I8{{ª°¥ˆ¥±¥€‘Èd çH!Ø‚‰˜Dñ$c$HD$Ë$ë„‚d(Dôü/DŠb„/…œ¨Î 'y».Q}@ŒpØ(Ê–Æ&Çaó!¦ƒ©Âòåó!ÆBŸb '®;ŽD‚¸æ#ðGX˜€ŽÆ !ï¥4W&zWJâkÓâDÎ6WˆòÄáaBL `ŽþæVJÈøü0¶YÞîŸ(lÂWü‡ÄÞ ¢V"Á’·PÀEd‚•Uº”ÍG8¾( âR ‘ rÀ@¤œx(ŽÍ—€Å<@¹+¥±Í- Bý"Y!þ.<ÅzA¥;¢å“1éŒíFŒÈ¡=Ä…cDì{÷³BÏå¹ʃ`O/ˆ-³8ì±aÈJ!AÊrÈ1ÓwT(ÅZ ‘LzŠŠq —ŠÙ"°±€%—0i“–±}–CäEôç¡ýü„ò7쎉ÐR„‰[–ÂÁÿ!sdb1@¥‹Ï [ß;‡`Ë@8¸Ç„œärÆñê/ss7gm+j5åØÙT¯—YdÙ5—ù×W‹ø½øP†×éG~ºÈ'—Ö€Û-æ>tüAÝwÙÞqš+íuµg½[˜ç/ÜLô]¹385a32Vbèß"I91máÿë&%Eù¦ÄñŒƤ“V5ï¤Ö5Q§b:D›üä«Viõ‹m¿Ö3-£ÛŠäåñÛš¤EOÙ«Ú˜ ½µøÕÁiZ´þÌj{ò¯ŽYãä/þF¥´©ðÅ_TΦ:–9Æ]1²|jj7üùk_ð”áÖx¬çØUdŽÊÉÝVz37‘wÆÍqNmî«kzžgåhÖ¡.è ‰X-­·0 ͵ӬÛjZÓÆòfL’µBµíhìÞC.!óZ“öSG$ÁOÈ_g%lðøþzÛœõW6/¨³)ßš¬¤Œ×™Á {‚«"³šiùþŒè£o^ïØ÷°zBβÎ3±í±šï©Ö$•$´æÜ¿ß` ?Ff:aÓØÛ2]¸ÿï´pè3Ù3ýÂ!ö+¿NÝßb:…¹ÇÛLJúíW¯-Teß*W*³X„Î#/ÜÎ4&­ŸÉµ?:´ÝÙ½Kj.Ê`ÄËj×05óŽú3šúj³'ži÷}*¸{Ò°É‚±ªªèNj—䨋<¤á6LÁ5àôŠrŸ‹¬TÜ“s1™L¤”<£ø ßܪî­šþ(ý% ¨š…îÖ½ÀFUuù<åÞzæ'®Uë<ÿülW¬>XOj’”FôôҨ漹G³Y±ƒï$oøI)Ä×äë5¼aÒHß5oòSbÙ–‘AõæIÑ,ÇìÎÖýºE$« àÐeØYe¡Ýé fQ×JrUž5ñ¬»ÎNn4œÁÖÒFûœæ›²®¼™ÝÑPéaúò½r`È­B: I*cõ·÷ºŸŽh÷ýó_ôþî1¢jþýÈè©í—'ÈϳîŽM‚¢YWYÖ½îî°E*¿kW’%rï oêUmZJþ4;}Ê…rîtº«Jù]}¨ºcD¹þ0pî«:ÚK}|Í.áÈZ~…ê8µ·‹bU­§Æõ©â§_[æ9oû}´`çßúÖ.=¨ísãÞ>QøtÇtÖ{ä±Àúà–kG9µ£÷æ†üßåö6©èaf…ûo½Ýêñ0ÜàhTPHËáµ'’·ý|™§¿[¯?&h6³/üh«®DGg¾¶ö”âT“‘ø÷6¼Ýûë³áy•OϺk•ZÔ!kp8–ÆÅOËr/®Mš4¢G÷&n_ßß­W¾I›q9Åö$óı«©œÌ=ãçô“º’d“Ù9(†£=Žè×àÑn¯û,§«ðvó&žùae™FåÞ™†:‘±ô)Ü—É ^Å û©Iz‚uÎñ1ç‡9r>9¡…† p­OÌ7~©:7ߤ¬Ïnn|þòñ¤ñÍÒÉ_g#­ç 7G¸ÖóUE‚¦€Ëþq£Ý7k2¶ –ä?/ë >ŸÚh;¢x« ïv Í÷/ÿáÐ%yd@ȳ´Þ4Vå‘[óTÓ endstream endobj 3420 0 obj << /Type /FontDescriptor /FontName /MBWZLE+LCIRCLE10 /Flags 4 /FontBBox [-2000 -2000 2040 2040] /Ascent 0 /CapHeight 0 /Descent 0 /ItalicAngle 0 /StemV 40 /XHeight 0 /CharSet (/a10/a11/a8/a9) /FontFile 3419 0 R >> endobj 19 0 obj << /Type /Font /Subtype /Type1 /BaseFont /AXVEPQ+CMB10 /FontDescriptor 3388 0 R /FirstChar 11 /LastChar 121 /Widths 3383 0 R >> endobj 4 0 obj << /Type /Font /Subtype /Type1 /BaseFont /KWRTHL+CMBX12 /FontDescriptor 3390 0 R /FirstChar 12 /LastChar 122 /Widths 3386 0 R >> endobj 679 0 obj << /Type /Font /Subtype /Type1 /BaseFont /YHGENP+CMBXSL10 /FontDescriptor 3392 0 R /FirstChar 12 /LastChar 117 /Widths 3374 0 R >> endobj 2077 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PLSYJB+CMBXTI10 /FontDescriptor 3394 0 R /FirstChar 46 /LastChar 46 /Widths 3370 0 R >> endobj 638 0 obj << /Type /Font /Subtype /Type1 /BaseFont /OUPHXB+CMMI10 /FontDescriptor 3396 0 R /FirstChar 78 /LastChar 78 /Widths 3375 0 R >> endobj 5 0 obj << /Type /Font /Subtype /Type1 /BaseFont /DMKLFN+CMR10 /FontDescriptor 3398 0 R /FirstChar 11 /LastChar 127 /Widths 3385 0 R >> endobj 390 0 obj << /Type /Font /Subtype /Type1 /BaseFont /EJASTL+CMR7 /FontDescriptor 3400 0 R /FirstChar 49 /LastChar 49 /Widths 3376 0 R >> endobj 1382 0 obj << /Type /Font /Subtype /Type1 /BaseFont /BVUDZH+CMR9 /FontDescriptor 3402 0 R /FirstChar 11 /LastChar 122 /Widths 3371 0 R >> endobj 85 0 obj << /Type /Font /Subtype /Type1 /BaseFont /LTWAIO+CMSL10 /FontDescriptor 3404 0 R /FirstChar 12 /LastChar 121 /Widths 3377 0 R >> endobj 34 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PYLSDX+CMSLTT10 /FontDescriptor 3406 0 R /FirstChar 42 /LastChar 122 /Widths 3379 0 R >> endobj 10 0 obj << /Type /Font /Subtype /Type1 /BaseFont /IKQYCT+CMSY10 /FontDescriptor 3408 0 R /FirstChar 0 /LastChar 105 /Widths 3384 0 R >> endobj 28 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PHLKTN+CMTI10 /FontDescriptor 3410 0 R /FirstChar 11 /LastChar 122 /Widths 3380 0 R >> endobj 1381 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ZKKWJR+CMTI9 /FontDescriptor 3412 0 R /FirstChar 46 /LastChar 46 /Widths 3372 0 R >> endobj 20 0 obj << /Type /Font /Subtype /Type1 /BaseFont /AKRAKP+CMTT10 /FontDescriptor 3414 0 R /FirstChar 33 /LastChar 126 /Widths 3382 0 R >> endobj 799 0 obj << /Type /Font /Subtype /Type1 /BaseFont /RWSXVU+CMTT12 /FontDescriptor 3416 0 R /FirstChar 43 /LastChar 121 /Widths 3373 0 R >> endobj 21 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ZDAHYY+CMTT9 /FontDescriptor 3418 0 R /FirstChar 33 /LastChar 126 /Widths 3381 0 R >> endobj 68 0 obj << /Type /Font /Subtype /Type1 /BaseFont /MBWZLE+LCIRCLE10 /FontDescriptor 3420 0 R /FirstChar 8 /LastChar 11 /Widths 3378 0 R >> endobj 6 0 obj << /Type /Pages /Count 6 /Parent 3421 0 R /Kids [2 0 R 8 0 R 14 0 R 24 0 R 31 0 R 37 0 R] >> endobj 45 0 obj << /Type /Pages /Count 6 /Parent 3421 0 R /Kids [41 0 R 47 0 R 52 0 R 58 0 R 62 0 R 71 0 R] >> endobj 78 0 obj << /Type /Pages /Count 6 /Parent 3421 0 R /Kids [75 0 R 80 0 R 87 0 R 91 0 R 95 0 R 100 0 R] >> endobj 111 0 obj << /Type /Pages /Count 6 /Parent 3421 0 R /Kids [108 0 R 113 0 R 118 0 R 123 0 R 127 0 R 131 0 R] >> endobj 155 0 obj << /Type /Pages /Count 6 /Parent 3421 0 R /Kids [142 0 R 157 0 R 168 0 R 176 0 R 181 0 R 187 0 R] >> endobj 196 0 obj << /Type /Pages /Count 6 /Parent 3421 0 R /Kids [192 0 R 198 0 R 204 0 R 211 0 R 220 0 R 226 0 R] >> endobj 238 0 obj << /Type /Pages /Count 6 /Parent 3422 0 R /Kids [232 0 R 242 0 R 246 0 R 256 0 R 263 0 R 269 0 R] >> endobj 283 0 obj << /Type /Pages /Count 6 /Parent 3422 0 R /Kids [277 0 R 287 0 R 299 0 R 310 0 R 321 0 R 333 0 R] >> endobj 351 0 obj << /Type /Pages /Count 6 /Parent 3422 0 R /Kids [343 0 R 354 0 R 368 0 R 380 0 R 387 0 R 395 0 R] >> endobj 412 0 obj << /Type /Pages /Count 6 /Parent 3422 0 R /Kids [405 0 R 414 0 R 422 0 R 431 0 R 443 0 R 452 0 R] >> endobj 464 0 obj << /Type /Pages /Count 6 /Parent 3422 0 R /Kids [460 0 R 466 0 R 471 0 R 475 0 R 482 0 R 494 0 R] >> endobj 517 0 obj << /Type /Pages /Count 6 /Parent 3422 0 R /Kids [507 0 R 519 0 R 529 0 R 535 0 R 540 0 R 547 0 R] >> endobj 559 0 obj << /Type /Pages /Count 6 /Parent 3423 0 R /Kids [555 0 R 562 0 R 567 0 R 572 0 R 576 0 R 580 0 R] >> endobj 587 0 obj << /Type /Pages /Count 6 /Parent 3423 0 R /Kids [584 0 R 590 0 R 598 0 R 609 0 R 618 0 R 630 0 R] >> endobj 648 0 obj << /Type /Pages /Count 6 /Parent 3423 0 R /Kids [641 0 R 650 0 R 662 0 R 672 0 R 686 0 R 696 0 R] >> endobj 717 0 obj << /Type /Pages /Count 6 /Parent 3423 0 R /Kids [710 0 R 719 0 R 729 0 R 740 0 R 750 0 R 762 0 R] >> endobj 772 0 obj << /Type /Pages /Count 6 /Parent 3423 0 R /Kids [768 0 R 775 0 R 783 0 R 789 0 R 795 0 R 802 0 R] >> endobj 815 0 obj << /Type /Pages /Count 6 /Parent 3423 0 R /Kids [811 0 R 817 0 R 821 0 R 825 0 R 830 0 R 834 0 R] >> endobj 841 0 obj << /Type /Pages /Count 6 /Parent 3424 0 R /Kids [838 0 R 844 0 R 848 0 R 853 0 R 858 0 R 864 0 R] >> endobj 877 0 obj << /Type /Pages /Count 6 /Parent 3424 0 R /Kids [873 0 R 883 0 R 891 0 R 896 0 R 902 0 R 907 0 R] >> endobj 916 0 obj << /Type /Pages /Count 6 /Parent 3424 0 R /Kids [912 0 R 918 0 R 922 0 R 927 0 R 931 0 R 935 0 R] >> endobj 944 0 obj << /Type /Pages /Count 6 /Parent 3424 0 R /Kids [939 0 R 946 0 R 950 0 R 954 0 R 959 0 R 963 0 R] >> endobj 970 0 obj << /Type /Pages /Count 6 /Parent 3424 0 R /Kids [967 0 R 973 0 R 977 0 R 981 0 R 986 0 R 991 0 R] >> endobj 998 0 obj << /Type /Pages /Count 6 /Parent 3424 0 R /Kids [995 0 R 1000 0 R 1005 0 R 1011 0 R 1015 0 R 1020 0 R] >> endobj 1029 0 obj << /Type /Pages /Count 6 /Parent 3425 0 R /Kids [1026 0 R 1031 0 R 1036 0 R 1041 0 R 1046 0 R 1051 0 R] >> endobj 1058 0 obj << /Type /Pages /Count 6 /Parent 3425 0 R /Kids [1055 0 R 1060 0 R 1064 0 R 1069 0 R 1073 0 R 1078 0 R] >> endobj 1088 0 obj << /Type /Pages /Count 6 /Parent 3425 0 R /Kids [1082 0 R 1090 0 R 1100 0 R 1111 0 R 1120 0 R 1127 0 R] >> endobj 1135 0 obj << /Type /Pages /Count 6 /Parent 3425 0 R /Kids [1131 0 R 1137 0 R 1141 0 R 1146 0 R 1150 0 R 1156 0 R] >> endobj 1163 0 obj << /Type /Pages /Count 6 /Parent 3425 0 R /Kids [1160 0 R 1165 0 R 1169 0 R 1176 0 R 1181 0 R 1185 0 R] >> endobj 1192 0 obj << /Type /Pages /Count 6 /Parent 3425 0 R /Kids [1189 0 R 1194 0 R 1199 0 R 1203 0 R 1207 0 R 1211 0 R] >> endobj 1218 0 obj << /Type /Pages /Count 6 /Parent 3426 0 R /Kids [1215 0 R 1220 0 R 1224 0 R 1229 0 R 1234 0 R 1238 0 R] >> endobj 1246 0 obj << /Type /Pages /Count 6 /Parent 3426 0 R /Kids [1243 0 R 1248 0 R 1252 0 R 1257 0 R 1261 0 R 1266 0 R] >> endobj 1274 0 obj << /Type /Pages /Count 6 /Parent 3426 0 R /Kids [1271 0 R 1276 0 R 1377 0 R 1464 0 R 1500 0 R 1504 0 R] >> endobj 1615 0 obj << /Type /Pages /Count 6 /Parent 3426 0 R /Kids [1611 0 R 1715 0 R 1828 0 R 1924 0 R 1993 0 R 1997 0 R] >> endobj 2027 0 obj << /Type /Pages /Count 6 /Parent 3426 0 R /Kids [2023 0 R 2029 0 R 2074 0 R 2126 0 R 2178 0 R 2230 0 R] >> endobj 2285 0 obj << /Type /Pages /Count 4 /Parent 3426 0 R /Kids [2282 0 R 2335 0 R 2383 0 R 2389 0 R] >> endobj 3421 0 obj << /Type /Pages /Count 36 /Parent 3427 0 R /Kids [6 0 R 45 0 R 78 0 R 111 0 R 155 0 R 196 0 R] >> endobj 3422 0 obj << /Type /Pages /Count 36 /Parent 3427 0 R /Kids [238 0 R 283 0 R 351 0 R 412 0 R 464 0 R 517 0 R] >> endobj 3423 0 obj << /Type /Pages /Count 36 /Parent 3427 0 R /Kids [559 0 R 587 0 R 648 0 R 717 0 R 772 0 R 815 0 R] >> endobj 3424 0 obj << /Type /Pages /Count 36 /Parent 3427 0 R /Kids [841 0 R 877 0 R 916 0 R 944 0 R 970 0 R 998 0 R] >> endobj 3425 0 obj << /Type /Pages /Count 36 /Parent 3427 0 R /Kids [1029 0 R 1058 0 R 1088 0 R 1135 0 R 1163 0 R 1192 0 R] >> endobj 3426 0 obj << /Type /Pages /Count 34 /Parent 3427 0 R /Kids [1218 0 R 1246 0 R 1274 0 R 1615 0 R 2027 0 R 2285 0 R] >> endobj 3427 0 obj << /Type /Pages /Count 214 /Kids [3421 0 R 3422 0 R 3423 0 R 3424 0 R 3425 0 R 3426 0 R] >> endobj 3428 0 obj << /Type /Outlines /First 2393 0 R /Last 3368 0 R /Count 11 >> endobj 3368 0 obj << /Title 3369 0 R /A 3367 0 R /Parent 3428 0 R /Prev 3365 0 R >> endobj 3365 0 obj << /Title 3366 0 R /A 3364 0 R /Parent 3428 0 R /Prev 3362 0 R /Next 3368 0 R >> endobj 3362 0 obj << /Title 3363 0 R /A 3361 0 R /Parent 3428 0 R /Prev 3329 0 R /Next 3365 0 R >> endobj 3359 0 obj << /Title 3360 0 R /A 3358 0 R /Parent 3329 0 R /Prev 3356 0 R >> endobj 3356 0 obj << /Title 3357 0 R /A 3355 0 R /Parent 3329 0 R /Prev 3353 0 R /Next 3359 0 R >> endobj 3353 0 obj << /Title 3354 0 R /A 3352 0 R /Parent 3329 0 R /Prev 3350 0 R /Next 3356 0 R >> endobj 3350 0 obj << /Title 3351 0 R /A 3349 0 R /Parent 3329 0 R /Prev 3347 0 R /Next 3353 0 R >> endobj 3347 0 obj << /Title 3348 0 R /A 3346 0 R /Parent 3329 0 R /Prev 3344 0 R /Next 3350 0 R >> endobj 3344 0 obj << /Title 3345 0 R /A 3343 0 R /Parent 3329 0 R /Prev 3341 0 R /Next 3347 0 R >> endobj 3341 0 obj << /Title 3342 0 R /A 3340 0 R /Parent 3329 0 R /Prev 3338 0 R /Next 3344 0 R >> endobj 3338 0 obj << /Title 3339 0 R /A 3337 0 R /Parent 3329 0 R /Prev 3335 0 R /Next 3341 0 R >> endobj 3335 0 obj << /Title 3336 0 R /A 3334 0 R /Parent 3329 0 R /Prev 3332 0 R /Next 3338 0 R >> endobj 3332 0 obj << /Title 3333 0 R /A 3331 0 R /Parent 3329 0 R /Next 3335 0 R >> endobj 3329 0 obj << /Title 3330 0 R /A 3328 0 R /Parent 3428 0 R /Prev 3320 0 R /Next 3362 0 R /First 3332 0 R /Last 3359 0 R /Count -10 >> endobj 3326 0 obj << /Title 3327 0 R /A 3325 0 R /Parent 3320 0 R /Prev 3323 0 R >> endobj 3323 0 obj << /Title 3324 0 R /A 3322 0 R /Parent 3320 0 R /Next 3326 0 R >> endobj 3320 0 obj << /Title 3321 0 R /A 3319 0 R /Parent 3428 0 R /Prev 3317 0 R /Next 3329 0 R /First 3323 0 R /Last 3326 0 R /Count -2 >> endobj 3317 0 obj << /Title 3318 0 R /A 3316 0 R /Parent 3428 0 R /Prev 3239 0 R /Next 3320 0 R >> endobj 3314 0 obj << /Title 3315 0 R /A 3313 0 R /Parent 3239 0 R /Prev 3311 0 R >> endobj 3311 0 obj << /Title 3312 0 R /A 3310 0 R /Parent 3239 0 R /Prev 3299 0 R /Next 3314 0 R >> endobj 3308 0 obj << /Title 3309 0 R /A 3307 0 R /Parent 3299 0 R /Prev 3305 0 R >> endobj 3305 0 obj << /Title 3306 0 R /A 3304 0 R /Parent 3299 0 R /Prev 3302 0 R /Next 3308 0 R >> endobj 3302 0 obj << /Title 3303 0 R /A 3301 0 R /Parent 3299 0 R /Next 3305 0 R >> endobj 3299 0 obj << /Title 3300 0 R /A 3298 0 R /Parent 3239 0 R /Prev 3242 0 R /Next 3311 0 R /First 3302 0 R /Last 3308 0 R /Count -3 >> endobj 3296 0 obj << /Title 3297 0 R /A 3295 0 R /Parent 3242 0 R /Prev 3293 0 R >> endobj 3293 0 obj << /Title 3294 0 R /A 3292 0 R /Parent 3242 0 R /Prev 3290 0 R /Next 3296 0 R >> endobj 3290 0 obj << /Title 3291 0 R /A 3289 0 R /Parent 3242 0 R /Prev 3287 0 R /Next 3293 0 R >> endobj 3287 0 obj << /Title 3288 0 R /A 3286 0 R /Parent 3242 0 R /Prev 3284 0 R /Next 3290 0 R >> endobj 3284 0 obj << /Title 3285 0 R /A 3283 0 R /Parent 3242 0 R /Prev 3281 0 R /Next 3287 0 R >> endobj 3281 0 obj << /Title 3282 0 R /A 3280 0 R /Parent 3242 0 R /Prev 3278 0 R /Next 3284 0 R >> endobj 3278 0 obj << /Title 3279 0 R /A 3277 0 R /Parent 3242 0 R /Prev 3275 0 R /Next 3281 0 R >> endobj 3275 0 obj << /Title 3276 0 R /A 3274 0 R /Parent 3242 0 R /Prev 3272 0 R /Next 3278 0 R >> endobj 3272 0 obj << /Title 3273 0 R /A 3271 0 R /Parent 3242 0 R /Prev 3269 0 R /Next 3275 0 R >> endobj 3269 0 obj << /Title 3270 0 R /A 3268 0 R /Parent 3242 0 R /Prev 3266 0 R /Next 3272 0 R >> endobj 3266 0 obj << /Title 3267 0 R /A 3265 0 R /Parent 3242 0 R /Prev 3263 0 R /Next 3269 0 R >> endobj 3263 0 obj << /Title 3264 0 R /A 3262 0 R /Parent 3242 0 R /Prev 3260 0 R /Next 3266 0 R >> endobj 3260 0 obj << /Title 3261 0 R /A 3259 0 R /Parent 3242 0 R /Prev 3257 0 R /Next 3263 0 R >> endobj 3257 0 obj << /Title 3258 0 R /A 3256 0 R /Parent 3242 0 R /Prev 3254 0 R /Next 3260 0 R >> endobj 3254 0 obj << /Title 3255 0 R /A 3253 0 R /Parent 3242 0 R /Prev 3251 0 R /Next 3257 0 R >> endobj 3251 0 obj << /Title 3252 0 R /A 3250 0 R /Parent 3242 0 R /Prev 3248 0 R /Next 3254 0 R >> endobj 3248 0 obj << /Title 3249 0 R /A 3247 0 R /Parent 3242 0 R /Prev 3245 0 R /Next 3251 0 R >> endobj 3245 0 obj << /Title 3246 0 R /A 3244 0 R /Parent 3242 0 R /Next 3248 0 R >> endobj 3242 0 obj << /Title 3243 0 R /A 3241 0 R /Parent 3239 0 R /Next 3299 0 R /First 3245 0 R /Last 3296 0 R /Count -18 >> endobj 3239 0 obj << /Title 3240 0 R /A 3238 0 R /Parent 3428 0 R /Prev 2417 0 R /Next 3317 0 R /First 3242 0 R /Last 3314 0 R /Count -4 >> endobj 3236 0 obj << /Title 3237 0 R /A 3235 0 R /Parent 2417 0 R /Prev 3233 0 R >> endobj 3233 0 obj << /Title 3234 0 R /A 3232 0 R /Parent 2417 0 R /Prev 3230 0 R /Next 3236 0 R >> endobj 3230 0 obj << /Title 3231 0 R /A 3229 0 R /Parent 2417 0 R /Prev 3227 0 R /Next 3233 0 R >> endobj 3227 0 obj << /Title 3228 0 R /A 3226 0 R /Parent 2417 0 R /Prev 3224 0 R /Next 3230 0 R >> endobj 3224 0 obj << /Title 3225 0 R /A 3223 0 R /Parent 2417 0 R /Prev 3221 0 R /Next 3227 0 R >> endobj 3221 0 obj << /Title 3222 0 R /A 3220 0 R /Parent 2417 0 R /Prev 3218 0 R /Next 3224 0 R >> endobj 3218 0 obj << /Title 3219 0 R /A 3217 0 R /Parent 2417 0 R /Prev 3215 0 R /Next 3221 0 R >> endobj 3215 0 obj << /Title 3216 0 R /A 3214 0 R /Parent 2417 0 R /Prev 3212 0 R /Next 3218 0 R >> endobj 3212 0 obj << /Title 3213 0 R /A 3211 0 R /Parent 2417 0 R /Prev 3209 0 R /Next 3215 0 R >> endobj 3209 0 obj << /Title 3210 0 R /A 3208 0 R /Parent 2417 0 R /Prev 3206 0 R /Next 3212 0 R >> endobj 3206 0 obj << /Title 3207 0 R /A 3205 0 R /Parent 2417 0 R /Prev 3203 0 R /Next 3209 0 R >> endobj 3203 0 obj << /Title 3204 0 R /A 3202 0 R /Parent 2417 0 R /Prev 3194 0 R /Next 3206 0 R >> endobj 3200 0 obj << /Title 3201 0 R /A 3199 0 R /Parent 3194 0 R /Prev 3197 0 R >> endobj 3197 0 obj << /Title 3198 0 R /A 3196 0 R /Parent 3194 0 R /Next 3200 0 R >> endobj 3194 0 obj << /Title 3195 0 R /A 3193 0 R /Parent 2417 0 R /Prev 3191 0 R /Next 3203 0 R /First 3197 0 R /Last 3200 0 R /Count -2 >> endobj 3191 0 obj << /Title 3192 0 R /A 3190 0 R /Parent 2417 0 R /Prev 3173 0 R /Next 3194 0 R >> endobj 3188 0 obj << /Title 3189 0 R /A 3187 0 R /Parent 3173 0 R /Prev 3185 0 R >> endobj 3185 0 obj << /Title 3186 0 R /A 3184 0 R /Parent 3173 0 R /Prev 3182 0 R /Next 3188 0 R >> endobj 3182 0 obj << /Title 3183 0 R /A 3181 0 R /Parent 3173 0 R /Prev 3179 0 R /Next 3185 0 R >> endobj 3179 0 obj << /Title 3180 0 R /A 3178 0 R /Parent 3173 0 R /Prev 3176 0 R /Next 3182 0 R >> endobj 3176 0 obj << /Title 3177 0 R /A 3175 0 R /Parent 3173 0 R /Next 3179 0 R >> endobj 3173 0 obj << /Title 3174 0 R /A 3172 0 R /Parent 2417 0 R /Prev 3170 0 R /Next 3191 0 R /First 3176 0 R /Last 3188 0 R /Count -5 >> endobj 3170 0 obj << /Title 3171 0 R /A 3169 0 R /Parent 2417 0 R /Prev 3167 0 R /Next 3173 0 R >> endobj 3167 0 obj << /Title 3168 0 R /A 3166 0 R /Parent 2417 0 R /Prev 3164 0 R /Next 3170 0 R >> endobj 3164 0 obj << /Title 3165 0 R /A 3163 0 R /Parent 2417 0 R /Prev 3161 0 R /Next 3167 0 R >> endobj 3161 0 obj << /Title 3162 0 R /A 3160 0 R /Parent 2417 0 R /Prev 3158 0 R /Next 3164 0 R >> endobj 3158 0 obj << /Title 3159 0 R /A 3157 0 R /Parent 2417 0 R /Prev 3152 0 R /Next 3161 0 R >> endobj 3155 0 obj << /Title 3156 0 R /A 3154 0 R /Parent 3152 0 R >> endobj 3152 0 obj << /Title 3153 0 R /A 3151 0 R /Parent 2417 0 R /Prev 3122 0 R /Next 3158 0 R /First 3155 0 R /Last 3155 0 R /Count -1 >> endobj 3149 0 obj << /Title 3150 0 R /A 3148 0 R /Parent 3122 0 R /Prev 3146 0 R >> endobj 3146 0 obj << /Title 3147 0 R /A 3145 0 R /Parent 3122 0 R /Prev 3143 0 R /Next 3149 0 R >> endobj 3143 0 obj << /Title 3144 0 R /A 3142 0 R /Parent 3122 0 R /Prev 3140 0 R /Next 3146 0 R >> endobj 3140 0 obj << /Title 3141 0 R /A 3139 0 R /Parent 3122 0 R /Prev 3137 0 R /Next 3143 0 R >> endobj 3137 0 obj << /Title 3138 0 R /A 3136 0 R /Parent 3122 0 R /Prev 3134 0 R /Next 3140 0 R >> endobj 3134 0 obj << /Title 3135 0 R /A 3133 0 R /Parent 3122 0 R /Prev 3131 0 R /Next 3137 0 R >> endobj 3131 0 obj << /Title 3132 0 R /A 3130 0 R /Parent 3122 0 R /Prev 3128 0 R /Next 3134 0 R >> endobj 3128 0 obj << /Title 3129 0 R /A 3127 0 R /Parent 3122 0 R /Prev 3125 0 R /Next 3131 0 R >> endobj 3125 0 obj << /Title 3126 0 R /A 3124 0 R /Parent 3122 0 R /Next 3128 0 R >> endobj 3122 0 obj << /Title 3123 0 R /A 3121 0 R /Parent 2417 0 R /Prev 3119 0 R /Next 3152 0 R /First 3125 0 R /Last 3149 0 R /Count -9 >> endobj 3119 0 obj << /Title 3120 0 R /A 3118 0 R /Parent 2417 0 R /Prev 2819 0 R /Next 3122 0 R >> endobj 3116 0 obj << /Title 3117 0 R /A 3115 0 R /Parent 2819 0 R /Prev 3113 0 R >> endobj 3113 0 obj << /Title 3114 0 R /A 3112 0 R /Parent 2819 0 R /Prev 3110 0 R /Next 3116 0 R >> endobj 3110 0 obj << /Title 3111 0 R /A 3109 0 R /Parent 2819 0 R /Prev 3107 0 R /Next 3113 0 R >> endobj 3107 0 obj << /Title 3108 0 R /A 3106 0 R /Parent 2819 0 R /Prev 3104 0 R /Next 3110 0 R >> endobj 3104 0 obj << /Title 3105 0 R /A 3103 0 R /Parent 2819 0 R /Prev 3101 0 R /Next 3107 0 R >> endobj 3101 0 obj << /Title 3102 0 R /A 3100 0 R /Parent 2819 0 R /Prev 3098 0 R /Next 3104 0 R >> endobj 3098 0 obj << /Title 3099 0 R /A 3097 0 R /Parent 2819 0 R /Prev 3095 0 R /Next 3101 0 R >> endobj 3095 0 obj << /Title 3096 0 R /A 3094 0 R /Parent 2819 0 R /Prev 3092 0 R /Next 3098 0 R >> endobj 3092 0 obj << /Title 3093 0 R /A 3091 0 R /Parent 2819 0 R /Prev 3089 0 R /Next 3095 0 R >> endobj 3089 0 obj << /Title 3090 0 R /A 3088 0 R /Parent 2819 0 R /Prev 3086 0 R /Next 3092 0 R >> endobj 3086 0 obj << /Title 3087 0 R /A 3085 0 R /Parent 2819 0 R /Prev 3083 0 R /Next 3089 0 R >> endobj 3083 0 obj << /Title 3084 0 R /A 3082 0 R /Parent 2819 0 R /Prev 3080 0 R /Next 3086 0 R >> endobj 3080 0 obj << /Title 3081 0 R /A 3079 0 R /Parent 2819 0 R /Prev 3077 0 R /Next 3083 0 R >> endobj 3077 0 obj << /Title 3078 0 R /A 3076 0 R /Parent 2819 0 R /Prev 3074 0 R /Next 3080 0 R >> endobj 3074 0 obj << /Title 3075 0 R /A 3073 0 R /Parent 2819 0 R /Prev 3071 0 R /Next 3077 0 R >> endobj 3071 0 obj << /Title 3072 0 R /A 3070 0 R /Parent 2819 0 R /Prev 3068 0 R /Next 3074 0 R >> endobj 3068 0 obj << /Title 3069 0 R /A 3067 0 R /Parent 2819 0 R /Prev 3065 0 R /Next 3071 0 R >> endobj 3065 0 obj << /Title 3066 0 R /A 3064 0 R /Parent 2819 0 R /Prev 3062 0 R /Next 3068 0 R >> endobj 3062 0 obj << /Title 3063 0 R /A 3061 0 R /Parent 2819 0 R /Prev 3059 0 R /Next 3065 0 R >> endobj 3059 0 obj << /Title 3060 0 R /A 3058 0 R /Parent 2819 0 R /Prev 3056 0 R /Next 3062 0 R >> endobj 3056 0 obj << /Title 3057 0 R /A 3055 0 R /Parent 2819 0 R /Prev 3053 0 R /Next 3059 0 R >> endobj 3053 0 obj << /Title 3054 0 R /A 3052 0 R /Parent 2819 0 R /Prev 3050 0 R /Next 3056 0 R >> endobj 3050 0 obj << /Title 3051 0 R /A 3049 0 R /Parent 2819 0 R /Prev 3047 0 R /Next 3053 0 R >> endobj 3047 0 obj << /Title 3048 0 R /A 3046 0 R /Parent 2819 0 R /Prev 3044 0 R /Next 3050 0 R >> endobj 3044 0 obj << /Title 3045 0 R /A 3043 0 R /Parent 2819 0 R /Prev 3041 0 R /Next 3047 0 R >> endobj 3041 0 obj << /Title 3042 0 R /A 3040 0 R /Parent 2819 0 R /Prev 3038 0 R /Next 3044 0 R >> endobj 3038 0 obj << /Title 3039 0 R /A 3037 0 R /Parent 2819 0 R /Prev 3035 0 R /Next 3041 0 R >> endobj 3035 0 obj << /Title 3036 0 R /A 3034 0 R /Parent 2819 0 R /Prev 3032 0 R /Next 3038 0 R >> endobj 3032 0 obj << /Title 3033 0 R /A 3031 0 R /Parent 2819 0 R /Prev 3029 0 R /Next 3035 0 R >> endobj 3029 0 obj << /Title 3030 0 R /A 3028 0 R /Parent 2819 0 R /Prev 3026 0 R /Next 3032 0 R >> endobj 3026 0 obj << /Title 3027 0 R /A 3025 0 R /Parent 2819 0 R /Prev 3023 0 R /Next 3029 0 R >> endobj 3023 0 obj << /Title 3024 0 R /A 3022 0 R /Parent 2819 0 R /Prev 3020 0 R /Next 3026 0 R >> endobj 3020 0 obj << /Title 3021 0 R /A 3019 0 R /Parent 2819 0 R /Prev 3017 0 R /Next 3023 0 R >> endobj 3017 0 obj << /Title 3018 0 R /A 3016 0 R /Parent 2819 0 R /Prev 3014 0 R /Next 3020 0 R >> endobj 3014 0 obj << /Title 3015 0 R /A 3013 0 R /Parent 2819 0 R /Prev 3011 0 R /Next 3017 0 R >> endobj 3011 0 obj << /Title 3012 0 R /A 3010 0 R /Parent 2819 0 R /Prev 3008 0 R /Next 3014 0 R >> endobj 3008 0 obj << /Title 3009 0 R /A 3007 0 R /Parent 2819 0 R /Prev 3005 0 R /Next 3011 0 R >> endobj 3005 0 obj << /Title 3006 0 R /A 3004 0 R /Parent 2819 0 R /Prev 3002 0 R /Next 3008 0 R >> endobj 3002 0 obj << /Title 3003 0 R /A 3001 0 R /Parent 2819 0 R /Prev 2999 0 R /Next 3005 0 R >> endobj 2999 0 obj << /Title 3000 0 R /A 2998 0 R /Parent 2819 0 R /Prev 2996 0 R /Next 3002 0 R >> endobj 2996 0 obj << /Title 2997 0 R /A 2995 0 R /Parent 2819 0 R /Prev 2993 0 R /Next 2999 0 R >> endobj 2993 0 obj << /Title 2994 0 R /A 2992 0 R /Parent 2819 0 R /Prev 2990 0 R /Next 2996 0 R >> endobj 2990 0 obj << /Title 2991 0 R /A 2989 0 R /Parent 2819 0 R /Prev 2987 0 R /Next 2993 0 R >> endobj 2987 0 obj << /Title 2988 0 R /A 2986 0 R /Parent 2819 0 R /Prev 2984 0 R /Next 2990 0 R >> endobj 2984 0 obj << /Title 2985 0 R /A 2983 0 R /Parent 2819 0 R /Prev 2981 0 R /Next 2987 0 R >> endobj 2981 0 obj << /Title 2982 0 R /A 2980 0 R /Parent 2819 0 R /Prev 2978 0 R /Next 2984 0 R >> endobj 2978 0 obj << /Title 2979 0 R /A 2977 0 R /Parent 2819 0 R /Prev 2975 0 R /Next 2981 0 R >> endobj 2975 0 obj << /Title 2976 0 R /A 2974 0 R /Parent 2819 0 R /Prev 2972 0 R /Next 2978 0 R >> endobj 2972 0 obj << /Title 2973 0 R /A 2971 0 R /Parent 2819 0 R /Prev 2969 0 R /Next 2975 0 R >> endobj 2969 0 obj << /Title 2970 0 R /A 2968 0 R /Parent 2819 0 R /Prev 2966 0 R /Next 2972 0 R >> endobj 2966 0 obj << /Title 2967 0 R /A 2965 0 R /Parent 2819 0 R /Prev 2963 0 R /Next 2969 0 R >> endobj 2963 0 obj << /Title 2964 0 R /A 2962 0 R /Parent 2819 0 R /Prev 2960 0 R /Next 2966 0 R >> endobj 2960 0 obj << /Title 2961 0 R /A 2959 0 R /Parent 2819 0 R /Prev 2957 0 R /Next 2963 0 R >> endobj 2957 0 obj << /Title 2958 0 R /A 2956 0 R /Parent 2819 0 R /Prev 2954 0 R /Next 2960 0 R >> endobj 2954 0 obj << /Title 2955 0 R /A 2953 0 R /Parent 2819 0 R /Prev 2951 0 R /Next 2957 0 R >> endobj 2951 0 obj << /Title 2952 0 R /A 2950 0 R /Parent 2819 0 R /Prev 2948 0 R /Next 2954 0 R >> endobj 2948 0 obj << /Title 2949 0 R /A 2947 0 R /Parent 2819 0 R /Prev 2945 0 R /Next 2951 0 R >> endobj 2945 0 obj << /Title 2946 0 R /A 2944 0 R /Parent 2819 0 R /Prev 2942 0 R /Next 2948 0 R >> endobj 2942 0 obj << /Title 2943 0 R /A 2941 0 R /Parent 2819 0 R /Prev 2939 0 R /Next 2945 0 R >> endobj 2939 0 obj << /Title 2940 0 R /A 2938 0 R /Parent 2819 0 R /Prev 2936 0 R /Next 2942 0 R >> endobj 2936 0 obj << /Title 2937 0 R /A 2935 0 R /Parent 2819 0 R /Prev 2933 0 R /Next 2939 0 R >> endobj 2933 0 obj << /Title 2934 0 R /A 2932 0 R /Parent 2819 0 R /Prev 2930 0 R /Next 2936 0 R >> endobj 2930 0 obj << /Title 2931 0 R /A 2929 0 R /Parent 2819 0 R /Prev 2927 0 R /Next 2933 0 R >> endobj 2927 0 obj << /Title 2928 0 R /A 2926 0 R /Parent 2819 0 R /Prev 2924 0 R /Next 2930 0 R >> endobj 2924 0 obj << /Title 2925 0 R /A 2923 0 R /Parent 2819 0 R /Prev 2921 0 R /Next 2927 0 R >> endobj 2921 0 obj << /Title 2922 0 R /A 2920 0 R /Parent 2819 0 R /Prev 2918 0 R /Next 2924 0 R >> endobj 2918 0 obj << /Title 2919 0 R /A 2917 0 R /Parent 2819 0 R /Prev 2915 0 R /Next 2921 0 R >> endobj 2915 0 obj << /Title 2916 0 R /A 2914 0 R /Parent 2819 0 R /Prev 2912 0 R /Next 2918 0 R >> endobj 2912 0 obj << /Title 2913 0 R /A 2911 0 R /Parent 2819 0 R /Prev 2909 0 R /Next 2915 0 R >> endobj 2909 0 obj << /Title 2910 0 R /A 2908 0 R /Parent 2819 0 R /Prev 2906 0 R /Next 2912 0 R >> endobj 2906 0 obj << /Title 2907 0 R /A 2905 0 R /Parent 2819 0 R /Prev 2903 0 R /Next 2909 0 R >> endobj 2903 0 obj << /Title 2904 0 R /A 2902 0 R /Parent 2819 0 R /Prev 2900 0 R /Next 2906 0 R >> endobj 2900 0 obj << /Title 2901 0 R /A 2899 0 R /Parent 2819 0 R /Prev 2897 0 R /Next 2903 0 R >> endobj 2897 0 obj << /Title 2898 0 R /A 2896 0 R /Parent 2819 0 R /Prev 2894 0 R /Next 2900 0 R >> endobj 2894 0 obj << /Title 2895 0 R /A 2893 0 R /Parent 2819 0 R /Prev 2891 0 R /Next 2897 0 R >> endobj 2891 0 obj << /Title 2892 0 R /A 2890 0 R /Parent 2819 0 R /Prev 2888 0 R /Next 2894 0 R >> endobj 2888 0 obj << /Title 2889 0 R /A 2887 0 R /Parent 2819 0 R /Prev 2885 0 R /Next 2891 0 R >> endobj 2885 0 obj << /Title 2886 0 R /A 2884 0 R /Parent 2819 0 R /Prev 2882 0 R /Next 2888 0 R >> endobj 2882 0 obj << /Title 2883 0 R /A 2881 0 R /Parent 2819 0 R /Prev 2879 0 R /Next 2885 0 R >> endobj 2879 0 obj << /Title 2880 0 R /A 2878 0 R /Parent 2819 0 R /Prev 2876 0 R /Next 2882 0 R >> endobj 2876 0 obj << /Title 2877 0 R /A 2875 0 R /Parent 2819 0 R /Prev 2873 0 R /Next 2879 0 R >> endobj 2873 0 obj << /Title 2874 0 R /A 2872 0 R /Parent 2819 0 R /Prev 2870 0 R /Next 2876 0 R >> endobj 2870 0 obj << /Title 2871 0 R /A 2869 0 R /Parent 2819 0 R /Prev 2867 0 R /Next 2873 0 R >> endobj 2867 0 obj << /Title 2868 0 R /A 2866 0 R /Parent 2819 0 R /Prev 2864 0 R /Next 2870 0 R >> endobj 2864 0 obj << /Title 2865 0 R /A 2863 0 R /Parent 2819 0 R /Prev 2861 0 R /Next 2867 0 R >> endobj 2861 0 obj << /Title 2862 0 R /A 2860 0 R /Parent 2819 0 R /Prev 2858 0 R /Next 2864 0 R >> endobj 2858 0 obj << /Title 2859 0 R /A 2857 0 R /Parent 2819 0 R /Prev 2855 0 R /Next 2861 0 R >> endobj 2855 0 obj << /Title 2856 0 R /A 2854 0 R /Parent 2819 0 R /Prev 2852 0 R /Next 2858 0 R >> endobj 2852 0 obj << /Title 2853 0 R /A 2851 0 R /Parent 2819 0 R /Prev 2849 0 R /Next 2855 0 R >> endobj 2849 0 obj << /Title 2850 0 R /A 2848 0 R /Parent 2819 0 R /Prev 2846 0 R /Next 2852 0 R >> endobj 2846 0 obj << /Title 2847 0 R /A 2845 0 R /Parent 2819 0 R /Prev 2843 0 R /Next 2849 0 R >> endobj 2843 0 obj << /Title 2844 0 R /A 2842 0 R /Parent 2819 0 R /Prev 2840 0 R /Next 2846 0 R >> endobj 2840 0 obj << /Title 2841 0 R /A 2839 0 R /Parent 2819 0 R /Prev 2837 0 R /Next 2843 0 R >> endobj 2837 0 obj << /Title 2838 0 R /A 2836 0 R /Parent 2819 0 R /Prev 2834 0 R /Next 2840 0 R >> endobj 2834 0 obj << /Title 2835 0 R /A 2833 0 R /Parent 2819 0 R /Prev 2831 0 R /Next 2837 0 R >> endobj 2831 0 obj << /Title 2832 0 R /A 2830 0 R /Parent 2819 0 R /Prev 2828 0 R /Next 2834 0 R >> endobj 2828 0 obj << /Title 2829 0 R /A 2827 0 R /Parent 2819 0 R /Prev 2825 0 R /Next 2831 0 R >> endobj 2825 0 obj << /Title 2826 0 R /A 2824 0 R /Parent 2819 0 R /Prev 2822 0 R /Next 2828 0 R >> endobj 2822 0 obj << /Title 2823 0 R /A 2821 0 R /Parent 2819 0 R /Next 2825 0 R >> endobj 2819 0 obj << /Title 2820 0 R /A 2818 0 R /Parent 2417 0 R /Prev 2816 0 R /Next 3119 0 R /First 2822 0 R /Last 3116 0 R /Count -99 >> endobj 2816 0 obj << /Title 2817 0 R /A 2815 0 R /Parent 2417 0 R /Prev 2813 0 R /Next 2819 0 R >> endobj 2813 0 obj << /Title 2814 0 R /A 2812 0 R /Parent 2417 0 R /Prev 2810 0 R /Next 2816 0 R >> endobj 2810 0 obj << /Title 2811 0 R /A 2809 0 R /Parent 2417 0 R /Prev 2807 0 R /Next 2813 0 R >> endobj 2807 0 obj << /Title 2808 0 R /A 2806 0 R /Parent 2417 0 R /Prev 2795 0 R /Next 2810 0 R >> endobj 2804 0 obj << /Title 2805 0 R /A 2803 0 R /Parent 2795 0 R /Prev 2801 0 R >> endobj 2801 0 obj << /Title 2802 0 R /A 2800 0 R /Parent 2795 0 R /Prev 2798 0 R /Next 2804 0 R >> endobj 2798 0 obj << /Title 2799 0 R /A 2797 0 R /Parent 2795 0 R /Next 2801 0 R >> endobj 2795 0 obj << /Title 2796 0 R /A 2794 0 R /Parent 2417 0 R /Prev 2792 0 R /Next 2807 0 R /First 2798 0 R /Last 2804 0 R /Count -3 >> endobj 2792 0 obj << /Title 2793 0 R /A 2791 0 R /Parent 2417 0 R /Prev 2540 0 R /Next 2795 0 R >> endobj 2789 0 obj << /Title 2790 0 R /A 2788 0 R /Parent 2540 0 R /Prev 2786 0 R >> endobj 2786 0 obj << /Title 2787 0 R /A 2785 0 R /Parent 2540 0 R /Prev 2783 0 R /Next 2789 0 R >> endobj 2783 0 obj << /Title 2784 0 R /A 2782 0 R /Parent 2540 0 R /Prev 2780 0 R /Next 2786 0 R >> endobj 2780 0 obj << /Title 2781 0 R /A 2779 0 R /Parent 2540 0 R /Prev 2777 0 R /Next 2783 0 R >> endobj 2777 0 obj << /Title 2778 0 R /A 2776 0 R /Parent 2540 0 R /Prev 2774 0 R /Next 2780 0 R >> endobj 2774 0 obj << /Title 2775 0 R /A 2773 0 R /Parent 2540 0 R /Prev 2771 0 R /Next 2777 0 R >> endobj 2771 0 obj << /Title 2772 0 R /A 2770 0 R /Parent 2540 0 R /Prev 2768 0 R /Next 2774 0 R >> endobj 2768 0 obj << /Title 2769 0 R /A 2767 0 R /Parent 2540 0 R /Prev 2765 0 R /Next 2771 0 R >> endobj 2765 0 obj << /Title 2766 0 R /A 2764 0 R /Parent 2540 0 R /Prev 2762 0 R /Next 2768 0 R >> endobj 2762 0 obj << /Title 2763 0 R /A 2761 0 R /Parent 2540 0 R /Prev 2759 0 R /Next 2765 0 R >> endobj 2759 0 obj << /Title 2760 0 R /A 2758 0 R /Parent 2540 0 R /Prev 2756 0 R /Next 2762 0 R >> endobj 2756 0 obj << /Title 2757 0 R /A 2755 0 R /Parent 2540 0 R /Prev 2753 0 R /Next 2759 0 R >> endobj 2753 0 obj << /Title 2754 0 R /A 2752 0 R /Parent 2540 0 R /Prev 2750 0 R /Next 2756 0 R >> endobj 2750 0 obj << /Title 2751 0 R /A 2749 0 R /Parent 2540 0 R /Prev 2747 0 R /Next 2753 0 R >> endobj 2747 0 obj << /Title 2748 0 R /A 2746 0 R /Parent 2540 0 R /Prev 2744 0 R /Next 2750 0 R >> endobj 2744 0 obj << /Title 2745 0 R /A 2743 0 R /Parent 2540 0 R /Prev 2741 0 R /Next 2747 0 R >> endobj 2741 0 obj << /Title 2742 0 R /A 2740 0 R /Parent 2540 0 R /Prev 2738 0 R /Next 2744 0 R >> endobj 2738 0 obj << /Title 2739 0 R /A 2737 0 R /Parent 2540 0 R /Prev 2735 0 R /Next 2741 0 R >> endobj 2735 0 obj << /Title 2736 0 R /A 2734 0 R /Parent 2540 0 R /Prev 2732 0 R /Next 2738 0 R >> endobj 2732 0 obj << /Title 2733 0 R /A 2731 0 R /Parent 2540 0 R /Prev 2729 0 R /Next 2735 0 R >> endobj 2729 0 obj << /Title 2730 0 R /A 2728 0 R /Parent 2540 0 R /Prev 2726 0 R /Next 2732 0 R >> endobj 2726 0 obj << /Title 2727 0 R /A 2725 0 R /Parent 2540 0 R /Prev 2723 0 R /Next 2729 0 R >> endobj 2723 0 obj << /Title 2724 0 R /A 2722 0 R /Parent 2540 0 R /Prev 2720 0 R /Next 2726 0 R >> endobj 2720 0 obj << /Title 2721 0 R /A 2719 0 R /Parent 2540 0 R /Prev 2717 0 R /Next 2723 0 R >> endobj 2717 0 obj << /Title 2718 0 R /A 2716 0 R /Parent 2540 0 R /Prev 2714 0 R /Next 2720 0 R >> endobj 2714 0 obj << /Title 2715 0 R /A 2713 0 R /Parent 2540 0 R /Prev 2711 0 R /Next 2717 0 R >> endobj 2711 0 obj << /Title 2712 0 R /A 2710 0 R /Parent 2540 0 R /Prev 2708 0 R /Next 2714 0 R >> endobj 2708 0 obj << /Title 2709 0 R /A 2707 0 R /Parent 2540 0 R /Prev 2705 0 R /Next 2711 0 R >> endobj 2705 0 obj << /Title 2706 0 R /A 2704 0 R /Parent 2540 0 R /Prev 2702 0 R /Next 2708 0 R >> endobj 2702 0 obj << /Title 2703 0 R /A 2701 0 R /Parent 2540 0 R /Prev 2699 0 R /Next 2705 0 R >> endobj 2699 0 obj << /Title 2700 0 R /A 2698 0 R /Parent 2540 0 R /Prev 2696 0 R /Next 2702 0 R >> endobj 2696 0 obj << /Title 2697 0 R /A 2695 0 R /Parent 2540 0 R /Prev 2693 0 R /Next 2699 0 R >> endobj 2693 0 obj << /Title 2694 0 R /A 2692 0 R /Parent 2540 0 R /Prev 2690 0 R /Next 2696 0 R >> endobj 2690 0 obj << /Title 2691 0 R /A 2689 0 R /Parent 2540 0 R /Prev 2687 0 R /Next 2693 0 R >> endobj 2687 0 obj << /Title 2688 0 R /A 2686 0 R /Parent 2540 0 R /Prev 2684 0 R /Next 2690 0 R >> endobj 2684 0 obj << /Title 2685 0 R /A 2683 0 R /Parent 2540 0 R /Prev 2681 0 R /Next 2687 0 R >> endobj 2681 0 obj << /Title 2682 0 R /A 2680 0 R /Parent 2540 0 R /Prev 2678 0 R /Next 2684 0 R >> endobj 2678 0 obj << /Title 2679 0 R /A 2677 0 R /Parent 2540 0 R /Prev 2675 0 R /Next 2681 0 R >> endobj 2675 0 obj << /Title 2676 0 R /A 2674 0 R /Parent 2540 0 R /Prev 2672 0 R /Next 2678 0 R >> endobj 2672 0 obj << /Title 2673 0 R /A 2671 0 R /Parent 2540 0 R /Prev 2669 0 R /Next 2675 0 R >> endobj 2669 0 obj << /Title 2670 0 R /A 2668 0 R /Parent 2540 0 R /Prev 2666 0 R /Next 2672 0 R >> endobj 2666 0 obj << /Title 2667 0 R /A 2665 0 R /Parent 2540 0 R /Prev 2663 0 R /Next 2669 0 R >> endobj 2663 0 obj << /Title 2664 0 R /A 2662 0 R /Parent 2540 0 R /Prev 2660 0 R /Next 2666 0 R >> endobj 2660 0 obj << /Title 2661 0 R /A 2659 0 R /Parent 2540 0 R /Prev 2657 0 R /Next 2663 0 R >> endobj 2657 0 obj << /Title 2658 0 R /A 2656 0 R /Parent 2540 0 R /Prev 2654 0 R /Next 2660 0 R >> endobj 2654 0 obj << /Title 2655 0 R /A 2653 0 R /Parent 2540 0 R /Prev 2651 0 R /Next 2657 0 R >> endobj 2651 0 obj << /Title 2652 0 R /A 2650 0 R /Parent 2540 0 R /Prev 2648 0 R /Next 2654 0 R >> endobj 2648 0 obj << /Title 2649 0 R /A 2647 0 R /Parent 2540 0 R /Prev 2645 0 R /Next 2651 0 R >> endobj 2645 0 obj << /Title 2646 0 R /A 2644 0 R /Parent 2540 0 R /Prev 2642 0 R /Next 2648 0 R >> endobj 2642 0 obj << /Title 2643 0 R /A 2641 0 R /Parent 2540 0 R /Prev 2639 0 R /Next 2645 0 R >> endobj 2639 0 obj << /Title 2640 0 R /A 2638 0 R /Parent 2540 0 R /Prev 2636 0 R /Next 2642 0 R >> endobj 2636 0 obj << /Title 2637 0 R /A 2635 0 R /Parent 2540 0 R /Prev 2633 0 R /Next 2639 0 R >> endobj 2633 0 obj << /Title 2634 0 R /A 2632 0 R /Parent 2540 0 R /Prev 2630 0 R /Next 2636 0 R >> endobj 2630 0 obj << /Title 2631 0 R /A 2629 0 R /Parent 2540 0 R /Prev 2627 0 R /Next 2633 0 R >> endobj 2627 0 obj << /Title 2628 0 R /A 2626 0 R /Parent 2540 0 R /Prev 2624 0 R /Next 2630 0 R >> endobj 2624 0 obj << /Title 2625 0 R /A 2623 0 R /Parent 2540 0 R /Prev 2621 0 R /Next 2627 0 R >> endobj 2621 0 obj << /Title 2622 0 R /A 2620 0 R /Parent 2540 0 R /Prev 2618 0 R /Next 2624 0 R >> endobj 2618 0 obj << /Title 2619 0 R /A 2617 0 R /Parent 2540 0 R /Prev 2615 0 R /Next 2621 0 R >> endobj 2615 0 obj << /Title 2616 0 R /A 2614 0 R /Parent 2540 0 R /Prev 2612 0 R /Next 2618 0 R >> endobj 2612 0 obj << /Title 2613 0 R /A 2611 0 R /Parent 2540 0 R /Prev 2609 0 R /Next 2615 0 R >> endobj 2609 0 obj << /Title 2610 0 R /A 2608 0 R /Parent 2540 0 R /Prev 2606 0 R /Next 2612 0 R >> endobj 2606 0 obj << /Title 2607 0 R /A 2605 0 R /Parent 2540 0 R /Prev 2603 0 R /Next 2609 0 R >> endobj 2603 0 obj << /Title 2604 0 R /A 2602 0 R /Parent 2540 0 R /Prev 2600 0 R /Next 2606 0 R >> endobj 2600 0 obj << /Title 2601 0 R /A 2599 0 R /Parent 2540 0 R /Prev 2597 0 R /Next 2603 0 R >> endobj 2597 0 obj << /Title 2598 0 R /A 2596 0 R /Parent 2540 0 R /Prev 2594 0 R /Next 2600 0 R >> endobj 2594 0 obj << /Title 2595 0 R /A 2593 0 R /Parent 2540 0 R /Prev 2591 0 R /Next 2597 0 R >> endobj 2591 0 obj << /Title 2592 0 R /A 2590 0 R /Parent 2540 0 R /Prev 2588 0 R /Next 2594 0 R >> endobj 2588 0 obj << /Title 2589 0 R /A 2587 0 R /Parent 2540 0 R /Prev 2585 0 R /Next 2591 0 R >> endobj 2585 0 obj << /Title 2586 0 R /A 2584 0 R /Parent 2540 0 R /Prev 2582 0 R /Next 2588 0 R >> endobj 2582 0 obj << /Title 2583 0 R /A 2581 0 R /Parent 2540 0 R /Prev 2579 0 R /Next 2585 0 R >> endobj 2579 0 obj << /Title 2580 0 R /A 2578 0 R /Parent 2540 0 R /Prev 2576 0 R /Next 2582 0 R >> endobj 2576 0 obj << /Title 2577 0 R /A 2575 0 R /Parent 2540 0 R /Prev 2573 0 R /Next 2579 0 R >> endobj 2573 0 obj << /Title 2574 0 R /A 2572 0 R /Parent 2540 0 R /Prev 2570 0 R /Next 2576 0 R >> endobj 2570 0 obj << /Title 2571 0 R /A 2569 0 R /Parent 2540 0 R /Prev 2567 0 R /Next 2573 0 R >> endobj 2567 0 obj << /Title 2568 0 R /A 2566 0 R /Parent 2540 0 R /Prev 2564 0 R /Next 2570 0 R >> endobj 2564 0 obj << /Title 2565 0 R /A 2563 0 R /Parent 2540 0 R /Prev 2561 0 R /Next 2567 0 R >> endobj 2561 0 obj << /Title 2562 0 R /A 2560 0 R /Parent 2540 0 R /Prev 2558 0 R /Next 2564 0 R >> endobj 2558 0 obj << /Title 2559 0 R /A 2557 0 R /Parent 2540 0 R /Prev 2555 0 R /Next 2561 0 R >> endobj 2555 0 obj << /Title 2556 0 R /A 2554 0 R /Parent 2540 0 R /Prev 2552 0 R /Next 2558 0 R >> endobj 2552 0 obj << /Title 2553 0 R /A 2551 0 R /Parent 2540 0 R /Prev 2549 0 R /Next 2555 0 R >> endobj 2549 0 obj << /Title 2550 0 R /A 2548 0 R /Parent 2540 0 R /Prev 2546 0 R /Next 2552 0 R >> endobj 2546 0 obj << /Title 2547 0 R /A 2545 0 R /Parent 2540 0 R /Prev 2543 0 R /Next 2549 0 R >> endobj 2543 0 obj << /Title 2544 0 R /A 2542 0 R /Parent 2540 0 R /Next 2546 0 R >> endobj 2540 0 obj << /Title 2541 0 R /A 2539 0 R /Parent 2417 0 R /Prev 2537 0 R /Next 2792 0 R /First 2543 0 R /Last 2789 0 R /Count -83 >> endobj 2537 0 obj << /Title 2538 0 R /A 2536 0 R /Parent 2417 0 R /Prev 2534 0 R /Next 2540 0 R >> endobj 2534 0 obj << /Title 2535 0 R /A 2533 0 R /Parent 2417 0 R /Prev 2531 0 R /Next 2537 0 R >> endobj 2531 0 obj << /Title 2532 0 R /A 2530 0 R /Parent 2417 0 R /Prev 2510 0 R /Next 2534 0 R >> endobj 2528 0 obj << /Title 2529 0 R /A 2527 0 R /Parent 2510 0 R /Prev 2525 0 R >> endobj 2525 0 obj << /Title 2526 0 R /A 2524 0 R /Parent 2510 0 R /Prev 2522 0 R /Next 2528 0 R >> endobj 2522 0 obj << /Title 2523 0 R /A 2521 0 R /Parent 2510 0 R /Prev 2519 0 R /Next 2525 0 R >> endobj 2519 0 obj << /Title 2520 0 R /A 2518 0 R /Parent 2510 0 R /Prev 2516 0 R /Next 2522 0 R >> endobj 2516 0 obj << /Title 2517 0 R /A 2515 0 R /Parent 2510 0 R /Prev 2513 0 R /Next 2519 0 R >> endobj 2513 0 obj << /Title 2514 0 R /A 2512 0 R /Parent 2510 0 R /Next 2516 0 R >> endobj 2510 0 obj << /Title 2511 0 R /A 2509 0 R /Parent 2417 0 R /Prev 2441 0 R /Next 2531 0 R /First 2513 0 R /Last 2528 0 R /Count -6 >> endobj 2507 0 obj << /Title 2508 0 R /A 2506 0 R /Parent 2441 0 R /Prev 2504 0 R >> endobj 2504 0 obj << /Title 2505 0 R /A 2503 0 R /Parent 2441 0 R /Prev 2501 0 R /Next 2507 0 R >> endobj 2501 0 obj << /Title 2502 0 R /A 2500 0 R /Parent 2441 0 R /Prev 2498 0 R /Next 2504 0 R >> endobj 2498 0 obj << /Title 2499 0 R /A 2497 0 R /Parent 2441 0 R /Prev 2495 0 R /Next 2501 0 R >> endobj 2495 0 obj << /Title 2496 0 R /A 2494 0 R /Parent 2441 0 R /Prev 2492 0 R /Next 2498 0 R >> endobj 2492 0 obj << /Title 2493 0 R /A 2491 0 R /Parent 2441 0 R /Prev 2489 0 R /Next 2495 0 R >> endobj 2489 0 obj << /Title 2490 0 R /A 2488 0 R /Parent 2441 0 R /Prev 2486 0 R /Next 2492 0 R >> endobj 2486 0 obj << /Title 2487 0 R /A 2485 0 R /Parent 2441 0 R /Prev 2483 0 R /Next 2489 0 R >> endobj 2483 0 obj << /Title 2484 0 R /A 2482 0 R /Parent 2441 0 R /Prev 2480 0 R /Next 2486 0 R >> endobj 2480 0 obj << /Title 2481 0 R /A 2479 0 R /Parent 2441 0 R /Prev 2477 0 R /Next 2483 0 R >> endobj 2477 0 obj << /Title 2478 0 R /A 2476 0 R /Parent 2441 0 R /Prev 2474 0 R /Next 2480 0 R >> endobj 2474 0 obj << /Title 2475 0 R /A 2473 0 R /Parent 2441 0 R /Prev 2471 0 R /Next 2477 0 R >> endobj 2471 0 obj << /Title 2472 0 R /A 2470 0 R /Parent 2441 0 R /Prev 2468 0 R /Next 2474 0 R >> endobj 2468 0 obj << /Title 2469 0 R /A 2467 0 R /Parent 2441 0 R /Prev 2465 0 R /Next 2471 0 R >> endobj 2465 0 obj << /Title 2466 0 R /A 2464 0 R /Parent 2441 0 R /Prev 2462 0 R /Next 2468 0 R >> endobj 2462 0 obj << /Title 2463 0 R /A 2461 0 R /Parent 2441 0 R /Prev 2459 0 R /Next 2465 0 R >> endobj 2459 0 obj << /Title 2460 0 R /A 2458 0 R /Parent 2441 0 R /Prev 2456 0 R /Next 2462 0 R >> endobj 2456 0 obj << /Title 2457 0 R /A 2455 0 R /Parent 2441 0 R /Prev 2453 0 R /Next 2459 0 R >> endobj 2453 0 obj << /Title 2454 0 R /A 2452 0 R /Parent 2441 0 R /Prev 2450 0 R /Next 2456 0 R >> endobj 2450 0 obj << /Title 2451 0 R /A 2449 0 R /Parent 2441 0 R /Prev 2447 0 R /Next 2453 0 R >> endobj 2447 0 obj << /Title 2448 0 R /A 2446 0 R /Parent 2441 0 R /Prev 2444 0 R /Next 2450 0 R >> endobj 2444 0 obj << /Title 2445 0 R /A 2443 0 R /Parent 2441 0 R /Next 2447 0 R >> endobj 2441 0 obj << /Title 2442 0 R /A 2440 0 R /Parent 2417 0 R /Prev 2429 0 R /Next 2510 0 R /First 2444 0 R /Last 2507 0 R /Count -22 >> endobj 2438 0 obj << /Title 2439 0 R /A 2437 0 R /Parent 2429 0 R /Prev 2435 0 R >> endobj 2435 0 obj << /Title 2436 0 R /A 2434 0 R /Parent 2429 0 R /Prev 2432 0 R /Next 2438 0 R >> endobj 2432 0 obj << /Title 2433 0 R /A 2431 0 R /Parent 2429 0 R /Next 2435 0 R >> endobj 2429 0 obj << /Title 2430 0 R /A 2428 0 R /Parent 2417 0 R /Prev 2426 0 R /Next 2441 0 R /First 2432 0 R /Last 2438 0 R /Count -3 >> endobj 2426 0 obj << /Title 2427 0 R /A 2425 0 R /Parent 2417 0 R /Prev 2423 0 R /Next 2429 0 R >> endobj 2423 0 obj << /Title 2424 0 R /A 2422 0 R /Parent 2417 0 R /Prev 2420 0 R /Next 2426 0 R >> endobj 2420 0 obj << /Title 2421 0 R /A 2419 0 R /Parent 2417 0 R /Next 2423 0 R >> endobj 2417 0 obj << /Title 2418 0 R /A 2416 0 R /Parent 3428 0 R /Prev 2414 0 R /Next 3239 0 R /First 2420 0 R /Last 3236 0 R /Count -40 >> endobj 2414 0 obj << /Title 2415 0 R /A 2413 0 R /Parent 3428 0 R /Prev 2411 0 R /Next 2417 0 R >> endobj 2411 0 obj << /Title 2412 0 R /A 2410 0 R /Parent 3428 0 R /Prev 2393 0 R /Next 2414 0 R >> endobj 2408 0 obj << /Title 2409 0 R /A 2407 0 R /Parent 2393 0 R /Prev 2405 0 R >> endobj 2405 0 obj << /Title 2406 0 R /A 2404 0 R /Parent 2393 0 R /Prev 2402 0 R /Next 2408 0 R >> endobj 2402 0 obj << /Title 2403 0 R /A 2401 0 R /Parent 2393 0 R /Prev 2399 0 R /Next 2405 0 R >> endobj 2399 0 obj << /Title 2400 0 R /A 2398 0 R /Parent 2393 0 R /Prev 2396 0 R /Next 2402 0 R >> endobj 2396 0 obj << /Title 2397 0 R /A 2395 0 R /Parent 2393 0 R /Next 2399 0 R >> endobj 2393 0 obj << /Title 2394 0 R /A 2392 0 R /Parent 3428 0 R /Next 2411 0 R /First 2396 0 R /Last 2408 0 R /Count -5 >> endobj 3429 0 obj << /Names [(-1) 2076 0 R (-2) 2128 0 R (-3) 2180 0 R (-4) 2232 0 R (-5) 2284 0 R (-6) 2337 0 R] /Limits [(-1) (-6)] >> endobj 3430 0 obj << /Names [(-7) 2385 0 R (-8) 2391 0 R (1) 16 0 R (10) 73 0 R (100) 804 0 R (101) 813 0 R] /Limits [(-7) (101)] >> endobj 3431 0 obj << /Names [(102) 819 0 R (103) 823 0 R (104) 827 0 R (105) 832 0 R (106) 836 0 R (107) 840 0 R] /Limits [(102) (107)] >> endobj 3432 0 obj << /Names [(108) 846 0 R (109) 850 0 R (11) 77 0 R (110) 855 0 R (111) 860 0 R (112) 866 0 R] /Limits [(108) (112)] >> endobj 3433 0 obj << /Names [(113) 875 0 R (114) 885 0 R (115) 893 0 R (116) 898 0 R (117) 904 0 R (118) 909 0 R] /Limits [(113) (118)] >> endobj 3434 0 obj << /Names [(119) 914 0 R (12) 82 0 R (120) 920 0 R (121) 924 0 R (122) 929 0 R (123) 933 0 R] /Limits [(119) (123)] >> endobj 3435 0 obj << /Names [(124) 937 0 R (125) 941 0 R (126) 948 0 R (127) 952 0 R (128) 956 0 R (129) 961 0 R] /Limits [(124) (129)] >> endobj 3436 0 obj << /Names [(13) 89 0 R (130) 965 0 R (131) 969 0 R (132) 975 0 R (133) 979 0 R (134) 983 0 R] /Limits [(13) (134)] >> endobj 3437 0 obj << /Names [(135) 988 0 R (136) 993 0 R (137) 997 0 R (138) 1002 0 R (139) 1007 0 R (14) 93 0 R] /Limits [(135) (14)] >> endobj 3438 0 obj << /Names [(140) 1013 0 R (141) 1017 0 R (142) 1022 0 R (143) 1028 0 R (144) 1033 0 R (145) 1038 0 R] /Limits [(140) (145)] >> endobj 3439 0 obj << /Names [(146) 1043 0 R (147) 1048 0 R (148) 1053 0 R (149) 1057 0 R (15) 97 0 R (150) 1062 0 R] /Limits [(146) (150)] >> endobj 3440 0 obj << /Names [(151) 1066 0 R (152) 1071 0 R (153) 1075 0 R (154) 1080 0 R (155) 1084 0 R (156) 1092 0 R] /Limits [(151) (156)] >> endobj 3441 0 obj << /Names [(157) 1102 0 R (158) 1113 0 R (159) 1122 0 R (16) 102 0 R (160) 1129 0 R (161) 1133 0 R] /Limits [(157) (161)] >> endobj 3442 0 obj << /Names [(162) 1139 0 R (163) 1143 0 R (164) 1148 0 R (165) 1152 0 R (166) 1158 0 R (167) 1162 0 R] /Limits [(162) (167)] >> endobj 3443 0 obj << /Names [(168) 1167 0 R (169) 1171 0 R (17) 110 0 R (170) 1178 0 R (171) 1183 0 R (172) 1187 0 R] /Limits [(168) (172)] >> endobj 3444 0 obj << /Names [(173) 1191 0 R (174) 1196 0 R (175) 1201 0 R (176) 1205 0 R (177) 1209 0 R (178) 1213 0 R] /Limits [(173) (178)] >> endobj 3445 0 obj << /Names [(179) 1217 0 R (18) 115 0 R (180) 1222 0 R (181) 1226 0 R (182) 1231 0 R (183) 1236 0 R] /Limits [(179) (183)] >> endobj 3446 0 obj << /Names [(184) 1240 0 R (185) 1245 0 R (186) 1250 0 R (187) 1254 0 R (188) 1259 0 R (189) 1263 0 R] /Limits [(184) (189)] >> endobj 3447 0 obj << /Names [(19) 120 0 R (190) 1268 0 R (191) 1273 0 R (192) 1278 0 R (193) 1379 0 R (194) 1466 0 R] /Limits [(19) (194)] >> endobj 3448 0 obj << /Names [(195) 1502 0 R (196) 1506 0 R (197) 1613 0 R (198) 1717 0 R (199) 1830 0 R (2) 26 0 R] /Limits [(195) (2)] >> endobj 3449 0 obj << /Names [(20) 125 0 R (200) 1926 0 R (201) 1995 0 R (202) 1999 0 R (203) 2025 0 R (204) 2031 0 R] /Limits [(20) (204)] >> endobj 3450 0 obj << /Names [(21) 129 0 R (22) 133 0 R (23) 144 0 R (24) 159 0 R (25) 170 0 R (26) 178 0 R] /Limits [(21) (26)] >> endobj 3451 0 obj << /Names [(27) 183 0 R (28) 189 0 R (29) 194 0 R (3) 33 0 R (30) 200 0 R (31) 206 0 R] /Limits [(27) (31)] >> endobj 3452 0 obj << /Names [(32) 213 0 R (33) 222 0 R (34) 228 0 R (35) 234 0 R (36) 244 0 R (37) 248 0 R] /Limits [(32) (37)] >> endobj 3453 0 obj << /Names [(38) 258 0 R (39) 265 0 R (4) 39 0 R (40) 271 0 R (41) 279 0 R (42) 289 0 R] /Limits [(38) (42)] >> endobj 3454 0 obj << /Names [(43) 301 0 R (44) 312 0 R (45) 323 0 R (46) 335 0 R (47) 345 0 R (48) 356 0 R] /Limits [(43) (48)] >> endobj 3455 0 obj << /Names [(49) 370 0 R (5) 43 0 R (50) 382 0 R (51) 389 0 R (52) 397 0 R (53) 407 0 R] /Limits [(49) (53)] >> endobj 3456 0 obj << /Names [(54) 416 0 R (55) 424 0 R (56) 433 0 R (57) 445 0 R (58) 454 0 R (59) 462 0 R] /Limits [(54) (59)] >> endobj 3457 0 obj << /Names [(6) 49 0 R (60) 468 0 R (61) 473 0 R (62) 477 0 R (63) 484 0 R (64) 496 0 R] /Limits [(6) (64)] >> endobj 3458 0 obj << /Names [(65) 509 0 R (66) 521 0 R (67) 531 0 R (68) 537 0 R (69) 542 0 R (7) 54 0 R] /Limits [(65) (7)] >> endobj 3459 0 obj << /Names [(70) 549 0 R (71) 557 0 R (72) 564 0 R (73) 569 0 R (74) 574 0 R (75) 578 0 R] /Limits [(70) (75)] >> endobj 3460 0 obj << /Names [(76) 582 0 R (77) 586 0 R (78) 592 0 R (79) 600 0 R (8) 60 0 R (80) 611 0 R] /Limits [(76) (80)] >> endobj 3461 0 obj << /Names [(81) 620 0 R (82) 632 0 R (83) 643 0 R (84) 652 0 R (85) 664 0 R (86) 674 0 R] /Limits [(81) (86)] >> endobj 3462 0 obj << /Names [(87) 688 0 R (88) 698 0 R (89) 712 0 R (9) 64 0 R (90) 721 0 R (91) 731 0 R] /Limits [(87) (91)] >> endobj 3463 0 obj << /Names [(92) 742 0 R (93) 752 0 R (94) 764 0 R (95) 770 0 R (96) 777 0 R (97) 785 0 R] /Limits [(92) (97)] >> endobj 3464 0 obj << /Names [(98) 791 0 R (99) 797 0 R (ACEs) 172 0 R (AbortAtLineMatching) 594 0 R (AbortClasses) 235 0 R (AccessedBefore) 135 0 R] /Limits [(98) (AccessedBefore)] >> endobj 3465 0 obj << /Names [(AllowConnectionsFrom) 1087 0 R (AllowMultipleConnectionsFrom) 1093 0 R (AllowRedefinitionOf) 267 0 R (AllowUsers) 1094 0 R (Append) 595 0 R (AppendIfNoLineMatching) 596 0 R] /Limits [(AllowConnectionsFrom) (AppendIfNoLineMatching)] >> endobj 3466 0 obj << /Names [(AppendIfNoSuchLine) 601 0 R (AppendIfNoSuchLinesFromFile) 602 0 R (AppendToLineIfNotContains) 603 0 R (Audit) 604 0 R (Auditing) 56 0 R (AutoCreate) 605 0 R] /Limits [(AppendIfNoSuchLine) (AutoCreate)] >> endobj 3467 0 obj << /Names [(AutoDefine) 272 0 R (AutoExecCommand) 1095 0 R (AutoExecInterval) 1096 0 R (AutomountDirectResources) 612 0 R (Backup in editfiles) 613 0 R (BeginGroupIfDefined) 614 0 R] /Limits [(AutoDefine) (BeginGroupIfDefined)] >> endobj 3468 0 obj << /Names [(BeginGroupIfFileExists) 616 0 R (BeginGroupIfFileIsNewer) 621 0 R (BeginGroupIfLineContaining) 622 0 R (BeginGroupIfLineMatching) 623 0 R (BeginGroupIfMatch) 624 0 R (BeginGroupIfNoLineContaining) 625 0 R] /Limits [(BeginGroupIfFileExists) (BeginGroupIfNoLineContaining)] >> endobj 3469 0 obj << /Names [(BeginGroupIfNoLineMatching) 626 0 R (BeginGroupIfNoMatch) 627 0 R (BeginGroupIfNoSuchLine) 628 0 R (BeginGroupIfNotDefined) 615 0 R (BinaryPaddingChar) 273 0 R (BindToInterface in cfagent) 274 0 R] /Limits [(BeginGroupIfNoLineMatching) (BindToInterface in cfagent)] >> endobj 3470 0 obj << /Names [(BindToInterface in cfservd) 1097 0 R (BreakIfLineMatches) 633 0 R (CatchAbort) 634 0 R (Cfagent Runtime Options) 69 0 R (Cfagent intro) 66 0 R (Cfagent reference) 65 0 R] /Limits [(BindToInterface in cfservd) (Cfagent reference)] >> endobj 3471 0 obj << /Names [(Cfengine classes) 121 0 R (Cfexecd reference) 1144 0 R (Cfkey) 44 0 R (Cfservd.conf and cfrun reference) 1076 0 R (Cfshow) 55 0 R (ChangedBefore) 136 0 R] /Limits [(Cfengine classes) (ChangedBefore)] >> endobj 3472 0 obj << /Names [(ChecksumDatabase in cfagent) 105 0 R (ChecksumDatabase in cfservd) 1098 0 R (ChecksumPurge) 280 0 R (ChecksumUpdates) 281 0 R (Checksums and change management) 798 0 R (ClassMatch) 137 0 R] /Limits [(ChecksumDatabase in cfagent) (ClassMatch)] >> endobj 3473 0 obj << /Names [(CommentLinesMatching) 635 0 R (CommentLinesStarting) 636 0 R (CommentNLines) 637 0 R (CommentToLineMatching) 639 0 R (Complete filter examples) 828 0 R (CompressCommand) 282 0 R] /Limits [(CommentLinesMatching) (CompressCommand)] >> endobj 3474 0 obj << /Names [(Concept Index) 1614 0 R (DFS ACLs) 184 0 R (Debugging with signals) 35 0 R (DefineClasses) 644 0 R (DefineInGroup) 645 0 R (DeleteLinesAfterThisMatching) 646 0 R] /Limits [(Concept Index) (DeleteLinesAfterThisMatching)] >> endobj 3475 0 obj << /Names [(DeleteLinesContaining) 647 0 R (DeleteLinesMatching) 653 0 R (DeleteLinesNotContaining) 655 0 R (DeleteLinesNotMatchingFileItems) 656 0 R (DeleteLinesNotStartingFileItems) 657 0 R (DeleteLinesStarting) 654 0 R] /Limits [(DeleteLinesContaining) (DeleteLinesStarting)] >> endobj 3476 0 obj << /Names [(DeleteNLines) 658 0 R (DeleteToLineMatching) 659 0 R (DenyBadClocks) 1104 0 R (DenyConnectionsFrom) 1105 0 R (Directory permissions) 793 0 R (DynamicAddresses) 1116 0 R] /Limits [(DeleteNLines) (DynamicAddresses)] >> endobj 3477 0 obj << /Names [(EditMode (binary)) 660 0 R (EditSplit) 665 0 R (Editfiles on Binary Files) 765 0 R (ElseDefineClasses) 667 0 R (EmptyEntireFilePlease) 666 0 R (EndGroup) 668 0 R] /Limits [(EditMode (binary)) (EndGroup)] >> endobj 3478 0 obj << /Names [(EndLoop) 669 0 R (Example configuration file) 1172 0 R (Examples setting classes) 164 0 R (ExpandVariables) 670 0 R (ExpireAfter) 325 0 R (ExpireAfter editfiles) 675 0 R] /Limits [(EndLoop) (ExpireAfter editfiles)] >> endobj 3479 0 obj << /Names [(FAQ Index) 2026 0 R (FileExists) 138 0 R (Filenames and paths) 29 0 R (Files linkchildren) 806 0 R (Filter) 676 0 R (Firewalls and NATs) 1134 0 R] /Limits [(FAQ Index) (Firewalls and NATs)] >> endobj 3480 0 obj << /Names [(FixEndOfLine) 677 0 R (ForEachLineIn) 678 0 R (FreeBSDInstallCommand) 327 0 R (FreeBSDRemoveCommand) 336 0 R (FullEncryption) 337 0 R (GotoLastLine) 680 0 R] /Limits [(FixEndOfLine) (GotoLastLine)] >> endobj 3481 0 obj << /Names [(GroupExists) 139 0 R (Hard classes) 27 0 R (Hard links) 878 0 R (HashCommentLinesContaining) 681 0 R (HashCommentLinesMatching) 682 0 R (HashCommentLinesStarting) 683 0 R] /Limits [(GroupExists) (HashCommentLinesStarting)] >> endobj 3482 0 obj << /Names [(HostRange) 140 0 R (HostnameKeys in cfagent) 346 0 R (IP address ranges) 1086 0 R (IPRange) 150 0 R (IfElapsed (editing)) 684 0 R (IfElapsed in cfagent) 347 0 R] /Limits [(HostRange) (IfElapsed in cfagent)] >> endobj 3483 0 obj << /Names [(IgnoreFriendRegex) 349 0 R (IgnoreInterfaceRegex) 350 0 R (IncrementPointer) 689 0 R (Inform) 357 0 R (Inform (editing)) 690 0 R (InsertFile) 691 0 R] /Limits [(IgnoreFriendRegex) (InsertFile)] >> endobj 3484 0 obj << /Names [(InsertLine) 692 0 R (Installation) 18 0 R (IsDefined) 145 0 R (IsDir) 146 0 R (IsGreaterThan) 162 0 R (IsLessThan) 163 0 R] /Limits [(InsertLine) (IsLessThan)] >> endobj 3485 0 obj << /Names [(IsLink) 147 0 R (IsNewerThan) 149 0 R (IsPlain) 148 0 R (Iteration over lists) 116 0 R (Link Children) 809 0 R (LocateLineMatching) 693 0 R] /Limits [(IsLink) (LocateLineMatching)] >> endobj 3486 0 obj << /Names [(LogAllConnections) 1108 0 R (LogDirectory) 372 0 R (LogEncryptedTransfers) 1109 0 R (LogTidyHomeFiles) 373 0 R (MaxConnections) 1114 0 R (Multiple Links) 888 0 R] /Limits [(LogAllConnections) (Multiple Links)] >> endobj 3487 0 obj << /Names [(NT ACLs) 185 0 R (Owner and group wildcards) 805 0 R (PercentCommentLinesContaining) 694 0 R (PercentCommentLinesMatching) 699 0 R (PercentCommentLinesStarting) 700 0 R (PortageInstallCommand) 398 0 R] /Limits [(NT ACLs) (PortageInstallCommand)] >> endobj 3488 0 obj << /Names [(Posix ACL Example) 195 0 R (PrepModule) 151 0 R (Prepend (editing)) 701 0 R (PrependIfNoLineMatching) 702 0 R (PrependIfNoSuchLine) 703 0 R (Problem solving) 1153 0 R] /Limits [(Posix ACL Example) (Problem solving)] >> endobj 3489 0 obj << /Names [(RPMcommand) 402 0 R (Recurse (editing)) 704 0 R (Recursion) 780 0 R (Reference introduction) 17 0 R (Regcmp) 152 0 R (Relative and absolute links) 900 0 R] /Limits [(RPMcommand) (Relative and absolute links)] >> endobj 3490 0 obj << /Names [(ReplaceAll With) 706 0 R (ReplaceFirst) 713 0 R (ReplaceLineWith) 705 0 R (ReplaceLinesMatchingField) 714 0 R (Repository) 715 0 R (ResetSearch) 716 0 R] /Limits [(ReplaceAll With) (ResetSearch)] >> endobj 3491 0 obj << /Names [(ReturnsZero) 153 0 R (ReturnsZeroShell) 154 0 R (RunScript) 722 0 R (RunScriptIfLineMatching) 723 0 R (RunScriptIfNoLineMatching) 724 0 R (SetCommentEnd) 726 0 R] /Limits [(ReturnsZero) (SetCommentEnd)] >> endobj 3492 0 obj << /Names [(SetCommentStart) 725 0 R (SetLine) 727 0 R (SetScript) 732 0 R (Setting classes with special functions) 134 0 R (Setting variables with functions) 84 0 R (Single links) 867 0 R] /Limits [(SetCommentStart) (Single links)] >> endobj 3493 0 obj << /Names [(SkipIdentify) 426 0 R (SkipVerify) 1124 0 R (SlashCommentLinesContaining) 733 0 R (SlashCommentLinesMatching) 734 0 R (SlashCommentLinesStarting) 735 0 R (Smtpserver) 427 0 R] /Limits [(SkipIdentify) (Smtpserver)] >> endobj 3494 0 obj << /Names [(Solaris ACLs) 179 0 R (Special variables) 103 0 R (SplayTime) 428 0 R (SplitOn) 736 0 R (Strcmp) 160 0 R (Syntax) 771 0 R] /Limits [(Solaris ACLs) (Syntax)] >> endobj 3495 0 obj << /Names [(SysLog) 737 0 R (Syslog) 438 0 R (SyslogFacility) 439 0 R (The file cfagent.conf) 67 0 R (TimeOut) 447 0 R (Too many open files) 538 0 R] /Limits [(SysLog) (Too many open files)] >> endobj 3496 0 obj << /Names [(TrustKeysFrom) 1115 0 R (Umask) 738 0 R (UnCommentLinesContaining) 743 0 R (UnCommentLinesMatching) 744 0 R (UnCommentToLineMatching) 746 0 R (UnCommentsNLines) 745 0 R] /Limits [(TrustKeysFrom) (UnCommentsNLines)] >> endobj 3497 0 obj << /Names [(UnsetAbort) 747 0 R (UseShell) 748 0 R (UserExists) 161 0 R (Variable Index) 1380 0 R (Variable expansion and contexts) 83 0 R (Verbose) 448 0 R] /Limits [(UnsetAbort) (Verbose)] >> endobj 3498 0 obj << /Names [(WarnIfFileMissing) 753 0 R (WarnIfLineContaining) 754 0 R (WarnIfLineMatching) 755 0 R (WarnIfLineStarting) 756 0 R (WarnIfNoLineContaining) 757 0 R (WarnIfNoLineMatching) 758 0 R] /Limits [(WarnIfFileMissing) (WarnIfNoLineMatching)] >> endobj 3499 0 obj << /Names [(WarnIfNoLineStarting) 759 0 R (WarnIfNoSuchLine) 760 0 R (Warnings) 455 0 R (Windows ACL Example) 190 0 R (Work directory) 22 0 R (access) 236 0 R] /Limits [(WarnIfNoLineStarting) (access)] >> endobj 3500 0 obj << /Names [(acl) 171 0 R (actionsequence) 237 0 R (addclasses) 260 0 R (addinstallable) 266 0 R (admit grant and deny) 1117 0 R (alerts) 201 0 R] /Limits [(acl) (alerts)] >> endobj 3501 0 obj << /Names [(binservers) 214 0 R (broadcast) 223 0 R (cf.freebsd) 1264 0 R (cf.groups) 1174 0 R (cf.linux) 1255 0 R (cf.main) 1179 0 R] /Limits [(binservers) (cf.main)] >> endobj 3502 0 obj << /Names [(cf.motd) 1227 0 R (cf.preconf bootstrap file) 1154 0 R (cf.site) 1197 0 R (cf.solaris) 1241 0 R (cf.users) 1232 0 R (cfagent.conf) 1173 0 R] /Limits [(cf.motd) (cfagent.conf)] >> endobj 3503 0 obj << /Names [(cfrc resource file) 362 0 R (cfrun) 1125 0 R (cfrunCommand) 1103 0 R (cfservd HostnameKeys) 1106 0 R (cfservd IfElapsed) 1107 0 R (cfservd control) 1085 0 R] /Limits [(cfrc resource file) (cfservd control)] >> endobj 3504 0 obj << /Names [(cfservd.conf) 1269 0 R (checkroot) 498 0 R (childlibpath) 290 0 R (classes) 469 0 R (control) 229 0 R (copy) 174 0 R] /Limits [(cfservd.conf) (copy)] >> endobj 3505 0 obj << /Names [(copy example) 532 0 R (copyaction) 485 0 R (copybackup) 489 0 R (copydefine) 526 0 R (copyexclude) 504 0 R (copyignore) 502 0 R] /Limits [(copy example) (copyignore)] >> endobj 3506 0 obj << /Names [(copyinclude) 503 0 R (copylinks) 291 0 R (copyrepository) 490 0 R (copytype) 510 0 R (copyxdev) 505 0 R (create) 808 0 R] /Limits [(copyinclude) (create)] >> endobj 3507 0 obj << /Names [(defaultcopytype) 292 0 R (defaultpkgmgr) 293 0 R (defaultroute) 543 0 R (deletenonownerfiles) 302 0 R (deletenonownermail) 304 0 R (deletenonuserfiles) 295 0 R] /Limits [(defaultcopytype) (deletenonuserfiles)] >> endobj 3508 0 obj << /Names [(deletenonusermail) 303 0 R (dest) 478 0 R (directories) 558 0 R (disable) 570 0 R (disks) 550 0 R (domain) 305 0 R] /Limits [(deletenonusermail) (domain)] >> endobj 3509 0 obj << /Names [(dpkginstallcommand) 306 0 R (dryrun) 307 0 R (editbinaryfilesize) 313 0 R (editfiles) 449 0 R (editfilesize) 314 0 R (emptyresolvconf) 315 0 R] /Limits [(dpkginstallcommand) (emptyresolvconf)] >> endobj 3510 0 obj << /Names [(encrypt) 516 0 R (encrypt=) 1123 0 R (exclamation) 316 0 R (excludecopy) 317 0 R (excludelinks) 324 0 R (failover) 513 0 R] /Limits [(encrypt) (failover)] >> endobj 3511 0 obj << /Names [(fileextension) 360 0 R (files) 173 0 R (filters) 814 0 R (findertype) 511 0 R (force) 486 0 R (forcedirs) 488 0 R] /Limits [(fileextension) (forcedirs)] >> endobj 3512 0 obj << /Names [(forceipv4) 487 0 R (groups) 261 0 R (hard links in copy) 533 0 R (home directive) 779 0 R (homepattern) 216 0 R (homeservers) 217 0 R] /Limits [(forceipv4) (homeservers)] >> endobj 3513 0 obj << /Names [(ignore) 851 0 R (import) 856 0 R (interfacename) 358 0 R (interfaces) 861 0 R (lastseen) 361 0 R (lastseenexpireafter) 207 0 R] /Limits [(ignore) (lastseenexpireafter)] >> endobj 3514 0 obj << /Names [(linkcopies) 371 0 R (links) 296 0 R (linktype) 524 0 R (localhost examples) 925 0 R (mailserver) 910 0 R (methods) 915 0 R] /Limits [(linkcopies) (methods)] >> endobj 3515 0 obj << /Names [(miscmounts) 943 0 R (moduledirectory) 251 0 R (mountables) 340 0 R (mountpattern) 383 0 R (netmask) 224 0 R (nfstype) 392 0 R] /Limits [(miscmounts) (nfstype)] >> endobj 3516 0 obj << /Names [(nonalphanumfiles) 391 0 R (oldserver) 514 0 R (packages) 297 0 R (processes) 957 0 R (purge) 527 0 R (recurse) 500 0 R] /Limits [(nonalphanumfiles) (recurse)] >> endobj 3517 0 obj << /Names [(remotehost examples) 942 0 R (rename) 1008 0 R (repchar) 399 0 R (repository) 400 0 R (required) 552 0 R (resolve) 1018 0 R] /Limits [(remotehost examples) (resolve)] >> endobj 3518 0 obj << /Names [(root=) 1118 0 R (rpminstallcommand) 403 0 R (schedule) 408 0 R (scli) 1023 0 R (secureinput) 409 0 R (sensiblecount) 410 0 R] /Limits [(root=) (sensiblecount)] >> endobj 3519 0 obj << /Names [(sensiblesize) 411 0 R (server) 512 0 R (shellcommands) 1024 0 R (showactions) 417 0 R (singlecopy) 418 0 R (site) 425 0 R] /Limits [(sensiblesize) (site)] >> endobj 3520 0 obj << /Names [(size) 523 0 R (split) 429 0 R (spooldirectories) 434 0 R (stealth) 497 0 R (strategies) 1044 0 R (suninstallcommand) 435 0 R] /Limits [(size) (suninstallcommand)] >> endobj 3521 0 obj << /Names [(suspiciousnames) 436 0 R (symlink) 501 0 R (sysadm) 437 0 R (tidy) 339 0 R (timestamps) 499 0 R (timezone) 446 0 R] /Limits [(suspiciousnames) (timezone)] >> endobj 3522 0 obj << /Names [(touch) 807 0 R (trustkey) 515 0 R (typecheck) 525 0 R (unmount) 1067 0 R (verify) 522 0 R (warnnonownerfiles) 457 0 R] /Limits [(touch) (warnnonownerfiles)] >> endobj 3523 0 obj << /Names [(warnnonownermail) 463 0 R (warnnonuserfiles) 456 0 R (warnnonusermail) 458 0 R] /Limits [(warnnonownermail) (warnnonusermail)] >> endobj 3524 0 obj << /Kids [3429 0 R 3430 0 R 3431 0 R 3432 0 R 3433 0 R 3434 0 R] /Limits [(-1) (123)] >> endobj 3525 0 obj << /Kids [3435 0 R 3436 0 R 3437 0 R 3438 0 R 3439 0 R 3440 0 R] /Limits [(124) (156)] >> endobj 3526 0 obj << /Kids [3441 0 R 3442 0 R 3443 0 R 3444 0 R 3445 0 R 3446 0 R] /Limits [(157) (189)] >> endobj 3527 0 obj << /Kids [3447 0 R 3448 0 R 3449 0 R 3450 0 R 3451 0 R 3452 0 R] /Limits [(19) (37)] >> endobj 3528 0 obj << /Kids [3453 0 R 3454 0 R 3455 0 R 3456 0 R 3457 0 R 3458 0 R] /Limits [(38) (7)] >> endobj 3529 0 obj << /Kids [3459 0 R 3460 0 R 3461 0 R 3462 0 R 3463 0 R 3464 0 R] /Limits [(70) (AccessedBefore)] >> endobj 3530 0 obj << /Kids [3465 0 R 3466 0 R 3467 0 R 3468 0 R 3469 0 R 3470 0 R] /Limits [(AllowConnectionsFrom) (Cfagent reference)] >> endobj 3531 0 obj << /Kids [3471 0 R 3472 0 R 3473 0 R 3474 0 R 3475 0 R 3476 0 R] /Limits [(Cfengine classes) (DynamicAddresses)] >> endobj 3532 0 obj << /Kids [3477 0 R 3478 0 R 3479 0 R 3480 0 R 3481 0 R 3482 0 R] /Limits [(EditMode (binary)) (IfElapsed in cfagent)] >> endobj 3533 0 obj << /Kids [3483 0 R 3484 0 R 3485 0 R 3486 0 R 3487 0 R 3488 0 R] /Limits [(IgnoreFriendRegex) (Problem solving)] >> endobj 3534 0 obj << /Kids [3489 0 R 3490 0 R 3491 0 R 3492 0 R 3493 0 R 3494 0 R] /Limits [(RPMcommand) (Syntax)] >> endobj 3535 0 obj << /Kids [3495 0 R 3496 0 R 3497 0 R 3498 0 R 3499 0 R 3500 0 R] /Limits [(SysLog) (alerts)] >> endobj 3536 0 obj << /Kids [3501 0 R 3502 0 R 3503 0 R 3504 0 R 3505 0 R 3506 0 R] /Limits [(binservers) (create)] >> endobj 3537 0 obj << /Kids [3507 0 R 3508 0 R 3509 0 R 3510 0 R 3511 0 R 3512 0 R] /Limits [(defaultcopytype) (homeservers)] >> endobj 3538 0 obj << /Kids [3513 0 R 3514 0 R 3515 0 R 3516 0 R 3517 0 R 3518 0 R] /Limits [(ignore) (sensiblecount)] >> endobj 3539 0 obj << /Kids [3519 0 R 3520 0 R 3521 0 R 3522 0 R 3523 0 R] /Limits [(sensiblesize) (warnnonusermail)] >> endobj 3540 0 obj << /Kids [3524 0 R 3525 0 R 3526 0 R 3527 0 R 3528 0 R 3529 0 R] /Limits [(-1) (AccessedBefore)] >> endobj 3541 0 obj << /Kids [3530 0 R 3531 0 R 3532 0 R 3533 0 R 3534 0 R 3535 0 R] /Limits [(AllowConnectionsFrom) (alerts)] >> endobj 3542 0 obj << /Kids [3536 0 R 3537 0 R 3538 0 R 3539 0 R] /Limits [(binservers) (warnnonusermail)] >> endobj 3543 0 obj << /Kids [3540 0 R 3541 0 R 3542 0 R] /Limits [(-1) (warnnonusermail)] >> endobj 3544 0 obj << /Dests 3543 0 R >> endobj 3545 0 obj << /Type /Catalog /Pages 3427 0 R /Outlines 3428 0 R /Names 3544 0 R /PageMode /UseOutlines >> endobj 3546 0 obj << /Producer (pdfTeX-1.40.3) /Creator (TeX) /CreationDate (D:20090411220151+02'00') /ModDate (D:20090411220151+02'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX using libpoppler, Version 3.141592-1.40.3-2.2 (Web2C 7.5.6) kpathsea version 3.5.6) >> endobj xref 0 3547 0000000000 65535 f 0000000509 00000 n 0000000405 00000 n 0000000015 00000 n 0000805867 00000 n 0000806452 00000 n 0000808190 00000 n 0000001073 00000 n 0000000969 00000 n 0000000588 00000 n 0000807175 00000 n 0000003948 00000 n 0000004101 00000 n 0000004508 00000 n 0000003815 00000 n 0000001153 00000 n 0000004296 00000 n 0000004347 00000 n 0000004398 00000 n 0000805723 00000 n 0000807609 00000 n 0000807900 00000 n 0000004453 00000 n 0000007436 00000 n 0000007168 00000 n 0000004624 00000 n 0000007275 00000 n 0000007326 00000 n 0000807319 00000 n 0000007381 00000 n 0000009185 00000 n 0000008972 00000 n 0000007564 00000 n 0000009079 00000 n 0000807028 00000 n 0000009130 00000 n 0000009657 00000 n 0000009499 00000 n 0000009301 00000 n 0000009606 00000 n 0000010931 00000 n 0000010721 00000 n 0000009726 00000 n 0000010829 00000 n 0000010880 00000 n 0000808298 00000 n 0000011392 00000 n 0000011233 00000 n 0000011035 00000 n 0000011341 00000 n 0000013921 00000 n 0000014161 00000 n 0000013794 00000 n 0000011461 00000 n 0000014059 00000 n 0000014110 00000 n 0000096033 00000 n 0000015349 00000 n 0000015190 00000 n 0000014277 00000 n 0000015298 00000 n 0000018001 00000 n 0000017626 00000 n 0000015442 00000 n 0000017734 00000 n 0000017785 00000 n 0000017836 00000 n 0000017891 00000 n 0000808044 00000 n 0000017946 00000 n 0000021034 00000 n 0000020875 00000 n 0000018130 00000 n 0000020983 00000 n 0000023721 00000 n 0000023562 00000 n 0000021127 00000 n 0000023670 00000 n 0000808409 00000 n 0000026141 00000 n 0000025877 00000 n 0000023826 00000 n 0000025985 00000 n 0000026036 00000 n 0000026087 00000 n 0000806883 00000 n 0000028230 00000 n 0000028071 00000 n 0000026269 00000 n 0000028179 00000 n 0000030493 00000 n 0000030334 00000 n 0000028335 00000 n 0000030442 00000 n 0000032438 00000 n 0000032279 00000 n 0000030598 00000 n 0000032387 00000 n 0000034970 00000 n 0000035386 00000 n 0000034833 00000 n 0000032543 00000 n 0000035276 00000 n 0000035329 00000 n 0000035123 00000 n 0000096259 00000 n 0000037880 00000 n 0000038086 00000 n 0000037748 00000 n 0000035502 00000 n 0000038033 00000 n 0000808521 00000 n 0000040135 00000 n 0000039913 00000 n 0000038192 00000 n 0000040025 00000 n 0000040078 00000 n 0000041869 00000 n 0000041647 00000 n 0000040265 00000 n 0000041759 00000 n 0000041812 00000 n 0000044771 00000 n 0000044606 00000 n 0000042010 00000 n 0000044718 00000 n 0000047730 00000 n 0000047565 00000 n 0000044889 00000 n 0000047677 00000 n 0000050487 00000 n 0000049923 00000 n 0000047848 00000 n 0000050035 00000 n 0000050088 00000 n 0000050145 00000 n 0000050202 00000 n 0000050259 00000 n 0000050316 00000 n 0000050373 00000 n 0000050430 00000 n 0000052909 00000 n 0000052178 00000 n 0000050616 00000 n 0000052290 00000 n 0000052343 00000 n 0000052396 00000 n 0000052453 00000 n 0000052510 00000 n 0000052567 00000 n 0000052624 00000 n 0000052681 00000 n 0000052738 00000 n 0000052795 00000 n 0000052852 00000 n 0000808639 00000 n 0000054833 00000 n 0000054387 00000 n 0000053026 00000 n 0000054499 00000 n 0000054552 00000 n 0000054605 00000 n 0000054662 00000 n 0000054719 00000 n 0000054776 00000 n 0000057569 00000 n 0000057705 00000 n 0000057997 00000 n 0000057429 00000 n 0000054938 00000 n 0000057835 00000 n 0000057888 00000 n 0000057941 00000 n 0000238491 00000 n 0000154819 00000 n 0000060916 00000 n 0000060694 00000 n 0000058151 00000 n 0000060806 00000 n 0000060859 00000 n 0000063371 00000 n 0000063092 00000 n 0000061045 00000 n 0000063204 00000 n 0000063257 00000 n 0000063314 00000 n 0000065960 00000 n 0000065738 00000 n 0000063500 00000 n 0000065850 00000 n 0000065903 00000 n 0000067110 00000 n 0000066888 00000 n 0000066077 00000 n 0000067000 00000 n 0000067053 00000 n 0000808757 00000 n 0000069091 00000 n 0000068869 00000 n 0000067203 00000 n 0000068981 00000 n 0000069034 00000 n 0000071537 00000 n 0000071734 00000 n 0000071405 00000 n 0000069208 00000 n 0000071681 00000 n 0000124623 00000 n 0000074094 00000 n 0000074369 00000 n 0000074617 00000 n 0000073946 00000 n 0000071828 00000 n 0000074507 00000 n 0000074560 00000 n 0000074232 00000 n 0000115344 00000 n 0000269740 00000 n 0000076148 00000 n 0000076392 00000 n 0000076016 00000 n 0000074734 00000 n 0000076286 00000 n 0000076339 00000 n 0000129240 00000 n 0000078623 00000 n 0000078405 00000 n 0000076497 00000 n 0000078517 00000 n 0000078570 00000 n 0000080812 00000 n 0000081199 00000 n 0000080680 00000 n 0000078777 00000 n 0000080975 00000 n 0000081028 00000 n 0000081085 00000 n 0000081142 00000 n 0000808875 00000 n 0000086786 00000 n 0000087138 00000 n 0000083692 00000 n 0000083527 00000 n 0000081340 00000 n 0000083639 00000 n 0000087474 00000 n 0000086630 00000 n 0000083798 00000 n 0000087421 00000 n 0000086962 00000 n 0000087280 00000 n 0000124847 00000 n 0000090461 00000 n 0000090798 00000 n 0000090930 00000 n 0000091185 00000 n 0000090305 00000 n 0000087580 00000 n 0000091075 00000 n 0000090632 00000 n 0000091128 00000 n 0000264637 00000 n 0000093792 00000 n 0000093514 00000 n 0000091339 00000 n 0000093626 00000 n 0000093679 00000 n 0000093735 00000 n 0000096315 00000 n 0000095868 00000 n 0000093934 00000 n 0000095980 00000 n 0000096089 00000 n 0000096145 00000 n 0000096202 00000 n 0000098326 00000 n 0000098685 00000 n 0000098194 00000 n 0000096420 00000 n 0000098461 00000 n 0000098514 00000 n 0000098571 00000 n 0000098628 00000 n 0000808993 00000 n 0000101347 00000 n 0000101483 00000 n 0000102086 00000 n 0000101199 00000 n 0000098790 00000 n 0000101752 00000 n 0000101805 00000 n 0000101858 00000 n 0000101915 00000 n 0000101972 00000 n 0000101618 00000 n 0000102029 00000 n 0000277065 00000 n 0000324895 00000 n 0000104811 00000 n 0000104305 00000 n 0000102215 00000 n 0000104417 00000 n 0000104470 00000 n 0000104527 00000 n 0000104584 00000 n 0000104641 00000 n 0000104698 00000 n 0000104755 00000 n 0000107394 00000 n 0000107867 00000 n 0000107262 00000 n 0000104940 00000 n 0000107529 00000 n 0000107582 00000 n 0000107639 00000 n 0000107696 00000 n 0000107753 00000 n 0000107810 00000 n 0000110577 00000 n 0000110713 00000 n 0000111279 00000 n 0000110429 00000 n 0000107996 00000 n 0000111064 00000 n 0000111117 00000 n 0000111170 00000 n 0000110889 00000 n 0000111223 00000 n 0000114471 00000 n 0000114642 00000 n 0000114776 00000 n 0000114909 00000 n 0000115401 00000 n 0000114307 00000 n 0000111433 00000 n 0000115181 00000 n 0000115234 00000 n 0000115287 00000 n 0000115045 00000 n 0000355672 00000 n 0000311754 00000 n 0000118005 00000 n 0000118633 00000 n 0000117865 00000 n 0000115555 00000 n 0000118356 00000 n 0000118409 00000 n 0000118462 00000 n 0000118181 00000 n 0000118519 00000 n 0000118576 00000 n 0000809111 00000 n 0000120847 00000 n 0000121407 00000 n 0000120707 00000 n 0000118775 00000 n 0000121131 00000 n 0000121184 00000 n 0000121237 00000 n 0000120991 00000 n 0000121294 00000 n 0000121351 00000 n 0000397614 00000 n 0000123801 00000 n 0000123938 00000 n 0000124073 00000 n 0000124218 00000 n 0000124904 00000 n 0000123637 00000 n 0000121536 00000 n 0000124570 00000 n 0000124680 00000 n 0000124737 00000 n 0000124794 00000 n 0000124395 00000 n 0000128420 00000 n 0000128585 00000 n 0000128720 00000 n 0000128853 00000 n 0000129297 00000 n 0000128256 00000 n 0000125045 00000 n 0000129134 00000 n 0000129187 00000 n 0000128994 00000 n 0000132683 00000 n 0000132989 00000 n 0000132551 00000 n 0000129438 00000 n 0000132823 00000 n 0000806595 00000 n 0000132876 00000 n 0000132932 00000 n 0000135265 00000 n 0000135972 00000 n 0000135125 00000 n 0000133142 00000 n 0000135640 00000 n 0000135693 00000 n 0000135746 00000 n 0000135803 00000 n 0000135453 00000 n 0000135859 00000 n 0000135916 00000 n 0000138516 00000 n 0000138123 00000 n 0000136101 00000 n 0000138235 00000 n 0000138288 00000 n 0000138345 00000 n 0000138402 00000 n 0000138459 00000 n 0000809229 00000 n 0000140877 00000 n 0000140598 00000 n 0000138633 00000 n 0000140710 00000 n 0000140763 00000 n 0000140820 00000 n 0000143615 00000 n 0000143793 00000 n 0000144277 00000 n 0000143475 00000 n 0000140994 00000 n 0000143939 00000 n 0000143992 00000 n 0000144049 00000 n 0000144106 00000 n 0000144163 00000 n 0000144220 00000 n 0000146884 00000 n 0000146381 00000 n 0000144406 00000 n 0000146493 00000 n 0000146546 00000 n 0000146599 00000 n 0000146656 00000 n 0000146713 00000 n 0000146770 00000 n 0000146827 00000 n 0000149036 00000 n 0000151486 00000 n 0000149400 00000 n 0000148904 00000 n 0000147013 00000 n 0000149176 00000 n 0000149229 00000 n 0000149286 00000 n 0000149343 00000 n 0000193921 00000 n 0000151618 00000 n 0000152035 00000 n 0000151346 00000 n 0000149529 00000 n 0000151755 00000 n 0000151808 00000 n 0000151865 00000 n 0000151922 00000 n 0000151979 00000 n 0000152839 00000 n 0000152621 00000 n 0000152164 00000 n 0000152733 00000 n 0000152786 00000 n 0000809347 00000 n 0000153477 00000 n 0000153259 00000 n 0000152920 00000 n 0000153371 00000 n 0000153424 00000 n 0000154872 00000 n 0000154654 00000 n 0000153570 00000 n 0000154766 00000 n 0000156722 00000 n 0000156501 00000 n 0000154989 00000 n 0000156613 00000 n 0000156666 00000 n 0000159845 00000 n 0000159980 00000 n 0000160510 00000 n 0000159705 00000 n 0000156853 00000 n 0000160116 00000 n 0000160169 00000 n 0000160226 00000 n 0000160283 00000 n 0000160340 00000 n 0000160397 00000 n 0000160454 00000 n 0000163526 00000 n 0000163667 00000 n 0000164373 00000 n 0000163386 00000 n 0000160604 00000 n 0000163808 00000 n 0000163861 00000 n 0000163918 00000 n 0000163975 00000 n 0000164032 00000 n 0000164089 00000 n 0000164146 00000 n 0000164203 00000 n 0000164260 00000 n 0000164317 00000 n 0000168018 00000 n 0000167454 00000 n 0000164467 00000 n 0000167566 00000 n 0000167619 00000 n 0000167676 00000 n 0000167733 00000 n 0000167790 00000 n 0000167847 00000 n 0000167904 00000 n 0000167961 00000 n 0000809465 00000 n 0000171374 00000 n 0000170867 00000 n 0000168100 00000 n 0000170979 00000 n 0000171032 00000 n 0000171089 00000 n 0000171146 00000 n 0000171203 00000 n 0000171260 00000 n 0000171317 00000 n 0000174414 00000 n 0000174135 00000 n 0000171480 00000 n 0000174247 00000 n 0000174300 00000 n 0000174357 00000 n 0000176653 00000 n 0000176431 00000 n 0000174531 00000 n 0000176543 00000 n 0000176596 00000 n 0000177930 00000 n 0000177712 00000 n 0000176746 00000 n 0000177824 00000 n 0000177877 00000 n 0000180583 00000 n 0000180721 00000 n 0000181094 00000 n 0000180435 00000 n 0000178047 00000 n 0000180988 00000 n 0000181041 00000 n 0000180855 00000 n 0000339757 00000 n 0000183351 00000 n 0000183592 00000 n 0000183219 00000 n 0000181236 00000 n 0000183482 00000 n 0000183535 00000 n 0000809583 00000 n 0000185087 00000 n 0000185276 00000 n 0000184955 00000 n 0000183722 00000 n 0000185223 00000 n 0000187492 00000 n 0000187734 00000 n 0000187360 00000 n 0000185370 00000 n 0000187628 00000 n 0000187681 00000 n 0000190526 00000 n 0000190361 00000 n 0000187876 00000 n 0000190473 00000 n 0000191938 00000 n 0000191773 00000 n 0000190632 00000 n 0000191885 00000 n 0000193974 00000 n 0000193756 00000 n 0000192044 00000 n 0000193868 00000 n 0000196758 00000 n 0000196593 00000 n 0000194104 00000 n 0000196705 00000 n 0000809701 00000 n 0000199640 00000 n 0000200206 00000 n 0000199500 00000 n 0000196864 00000 n 0000199983 00000 n 0000199814 00000 n 0000200036 00000 n 0000200092 00000 n 0000200149 00000 n 0000202523 00000 n 0000202073 00000 n 0000200360 00000 n 0000202185 00000 n 0000202238 00000 n 0000202295 00000 n 0000202352 00000 n 0000202409 00000 n 0000202466 00000 n 0000204993 00000 n 0000205134 00000 n 0000205613 00000 n 0000204853 00000 n 0000202640 00000 n 0000205275 00000 n 0000205328 00000 n 0000205385 00000 n 0000205442 00000 n 0000205499 00000 n 0000205556 00000 n 0000207427 00000 n 0000206811 00000 n 0000205730 00000 n 0000206923 00000 n 0000206976 00000 n 0000207029 00000 n 0000207086 00000 n 0000207143 00000 n 0000207199 00000 n 0000207256 00000 n 0000207313 00000 n 0000207370 00000 n 0000209879 00000 n 0000209372 00000 n 0000207544 00000 n 0000209484 00000 n 0000209537 00000 n 0000209594 00000 n 0000209651 00000 n 0000209708 00000 n 0000209765 00000 n 0000806307 00000 n 0000209822 00000 n 0000212283 00000 n 0000211890 00000 n 0000210009 00000 n 0000212002 00000 n 0000212055 00000 n 0000212112 00000 n 0000212169 00000 n 0000212226 00000 n 0000809819 00000 n 0000214372 00000 n 0000213756 00000 n 0000212400 00000 n 0000213868 00000 n 0000213921 00000 n 0000213974 00000 n 0000214031 00000 n 0000214088 00000 n 0000214145 00000 n 0000214202 00000 n 0000214259 00000 n 0000214316 00000 n 0000216254 00000 n 0000215747 00000 n 0000214490 00000 n 0000215859 00000 n 0000215912 00000 n 0000215969 00000 n 0000216026 00000 n 0000216083 00000 n 0000216140 00000 n 0000216197 00000 n 0000218389 00000 n 0000217715 00000 n 0000216359 00000 n 0000217827 00000 n 0000217880 00000 n 0000217933 00000 n 0000217990 00000 n 0000218047 00000 n 0000806011 00000 n 0000218104 00000 n 0000218161 00000 n 0000218218 00000 n 0000218275 00000 n 0000218332 00000 n 0000221128 00000 n 0000220625 00000 n 0000218520 00000 n 0000220737 00000 n 0000220790 00000 n 0000220843 00000 n 0000220900 00000 n 0000220957 00000 n 0000221014 00000 n 0000221071 00000 n 0000223185 00000 n 0000222566 00000 n 0000221259 00000 n 0000222678 00000 n 0000222731 00000 n 0000222788 00000 n 0000222845 00000 n 0000222902 00000 n 0000222959 00000 n 0000223016 00000 n 0000223072 00000 n 0000223128 00000 n 0000225998 00000 n 0000226139 00000 n 0000226570 00000 n 0000225858 00000 n 0000223302 00000 n 0000226289 00000 n 0000226342 00000 n 0000226399 00000 n 0000226456 00000 n 0000226513 00000 n 0000809937 00000 n 0000228872 00000 n 0000228369 00000 n 0000226699 00000 n 0000228481 00000 n 0000228534 00000 n 0000228587 00000 n 0000228644 00000 n 0000228701 00000 n 0000228758 00000 n 0000228815 00000 n 0000230906 00000 n 0000230342 00000 n 0000228989 00000 n 0000230454 00000 n 0000230507 00000 n 0000230564 00000 n 0000230621 00000 n 0000230678 00000 n 0000230735 00000 n 0000230792 00000 n 0000230849 00000 n 0000233068 00000 n 0000232565 00000 n 0000231023 00000 n 0000232677 00000 n 0000232730 00000 n 0000232783 00000 n 0000232840 00000 n 0000232897 00000 n 0000232954 00000 n 0000233011 00000 n 0000234737 00000 n 0000234122 00000 n 0000233185 00000 n 0000234234 00000 n 0000234287 00000 n 0000234340 00000 n 0000234397 00000 n 0000234454 00000 n 0000234509 00000 n 0000234566 00000 n 0000234623 00000 n 0000234680 00000 n 0000236556 00000 n 0000236338 00000 n 0000234842 00000 n 0000236450 00000 n 0000236503 00000 n 0000241895 00000 n 0000238601 00000 n 0000238326 00000 n 0000236673 00000 n 0000238438 00000 n 0000238544 00000 n 0000810055 00000 n 0000242176 00000 n 0000242369 00000 n 0000241747 00000 n 0000238743 00000 n 0000242316 00000 n 0000242036 00000 n 0000252174 00000 n 0000249590 00000 n 0000245586 00000 n 0000245779 00000 n 0000245454 00000 n 0000242475 00000 n 0000245726 00000 n 0000249110 00000 n 0000249254 00000 n 0000249704 00000 n 0000248962 00000 n 0000245897 00000 n 0000249537 00000 n 0000249396 00000 n 0000249647 00000 n 0000252231 00000 n 0000251952 00000 n 0000249809 00000 n 0000252064 00000 n 0000252117 00000 n 0000807754 00000 n 0000254286 00000 n 0000254706 00000 n 0000254154 00000 n 0000252362 00000 n 0000254425 00000 n 0000254478 00000 n 0000254535 00000 n 0000254592 00000 n 0000254649 00000 n 0000288007 00000 n 0000256558 00000 n 0000256340 00000 n 0000254823 00000 n 0000256452 00000 n 0000256505 00000 n 0000810173 00000 n 0000258797 00000 n 0000258632 00000 n 0000256663 00000 n 0000258744 00000 n 0000260493 00000 n 0000260328 00000 n 0000258891 00000 n 0000260440 00000 n 0000261881 00000 n 0000261663 00000 n 0000260587 00000 n 0000261775 00000 n 0000261828 00000 n 0000262457 00000 n 0000262292 00000 n 0000261986 00000 n 0000262404 00000 n 0000264690 00000 n 0000264472 00000 n 0000262539 00000 n 0000264584 00000 n 0000267073 00000 n 0000266908 00000 n 0000264807 00000 n 0000267020 00000 n 0000810291 00000 n 0000269546 00000 n 0000269793 00000 n 0000269414 00000 n 0000267167 00000 n 0000269687 00000 n 0000271720 00000 n 0000271502 00000 n 0000269910 00000 n 0000271614 00000 n 0000271667 00000 n 0000273143 00000 n 0000272925 00000 n 0000271850 00000 n 0000273037 00000 n 0000273090 00000 n 0000274438 00000 n 0000274220 00000 n 0000273248 00000 n 0000274332 00000 n 0000274385 00000 n 0000276876 00000 n 0000277175 00000 n 0000276744 00000 n 0000274568 00000 n 0000277012 00000 n 0000277118 00000 n 0000280249 00000 n 0000280522 00000 n 0000280662 00000 n 0000284051 00000 n 0000280849 00000 n 0000280093 00000 n 0000277329 00000 n 0000280796 00000 n 0000280386 00000 n 0000810409 00000 n 0000291894 00000 n 0000284193 00000 n 0000284473 00000 n 0000284610 00000 n 0000284992 00000 n 0000283879 00000 n 0000280979 00000 n 0000284882 00000 n 0000284333 00000 n 0000284747 00000 n 0000284935 00000 n 0000287813 00000 n 0000288064 00000 n 0000287681 00000 n 0000285109 00000 n 0000287954 00000 n 0000291521 00000 n 0000291951 00000 n 0000291381 00000 n 0000288169 00000 n 0000291784 00000 n 0000291653 00000 n 0000291837 00000 n 0000292725 00000 n 0000292560 00000 n 0000292068 00000 n 0000292672 00000 n 0000294206 00000 n 0000294459 00000 n 0000294074 00000 n 0000292795 00000 n 0000294353 00000 n 0000294406 00000 n 0000297258 00000 n 0000297040 00000 n 0000294576 00000 n 0000297152 00000 n 0000297205 00000 n 0000810527 00000 n 0000299382 00000 n 0000299217 00000 n 0000297400 00000 n 0000299329 00000 n 0000300769 00000 n 0000300547 00000 n 0000299476 00000 n 0000300659 00000 n 0000300712 00000 n 0000301934 00000 n 0000301769 00000 n 0000300874 00000 n 0000301881 00000 n 0000303155 00000 n 0000302990 00000 n 0000302016 00000 n 0000303102 00000 n 0000305899 00000 n 0000305734 00000 n 0000303237 00000 n 0000305846 00000 n 0000308666 00000 n 0000308391 00000 n 0000306018 00000 n 0000308503 00000 n 0000308556 00000 n 0000308609 00000 n 0000810645 00000 n 0000309987 00000 n 0000309822 00000 n 0000308795 00000 n 0000309934 00000 n 0000311807 00000 n 0000311589 00000 n 0000310106 00000 n 0000311701 00000 n 0000314234 00000 n 0000314016 00000 n 0000311948 00000 n 0000314128 00000 n 0000314181 00000 n 0000316794 00000 n 0000316629 00000 n 0000314376 00000 n 0000316741 00000 n 0000319711 00000 n 0000319546 00000 n 0000316912 00000 n 0000319658 00000 n 0000321622 00000 n 0000321457 00000 n 0000319817 00000 n 0000321569 00000 n 0000810763 00000 n 0000322779 00000 n 0000322969 00000 n 0000322647 00000 n 0000321728 00000 n 0000322916 00000 n 0000324948 00000 n 0000324730 00000 n 0000323063 00000 n 0000324842 00000 n 0000328117 00000 n 0000327952 00000 n 0000325102 00000 n 0000328064 00000 n 0000330742 00000 n 0000331222 00000 n 0000330602 00000 n 0000328223 00000 n 0000331169 00000 n 0000330956 00000 n 0000333349 00000 n 0000333184 00000 n 0000331328 00000 n 0000333296 00000 n 0000335960 00000 n 0000335795 00000 n 0000333443 00000 n 0000335907 00000 n 0000810881 00000 n 0000338119 00000 n 0000337950 00000 n 0000336078 00000 n 0000338064 00000 n 0000338740 00000 n 0000338989 00000 n 0000338604 00000 n 0000338213 00000 n 0000338879 00000 n 0000338934 00000 n 0000339569 00000 n 0000339811 00000 n 0000339433 00000 n 0000339071 00000 n 0000339702 00000 n 0000341812 00000 n 0000341587 00000 n 0000339893 00000 n 0000341702 00000 n 0000341757 00000 n 0000344726 00000 n 0000344442 00000 n 0000341918 00000 n 0000344557 00000 n 0000344612 00000 n 0000344667 00000 n 0000347154 00000 n 0000346983 00000 n 0000344869 00000 n 0000347099 00000 n 0000811004 00000 n 0000349546 00000 n 0000349375 00000 n 0000347298 00000 n 0000349491 00000 n 0000351424 00000 n 0000351773 00000 n 0000351278 00000 n 0000349665 00000 n 0000351718 00000 n 0000351572 00000 n 0000353370 00000 n 0000353144 00000 n 0000351880 00000 n 0000353260 00000 n 0000353315 00000 n 0000355726 00000 n 0000355501 00000 n 0000353476 00000 n 0000355617 00000 n 0000359156 00000 n 0000359352 00000 n 0000359019 00000 n 0000355869 00000 n 0000359297 00000 n 0000362093 00000 n 0000361922 00000 n 0000359471 00000 n 0000362038 00000 n 0000811129 00000 n 0000362999 00000 n 0000362828 00000 n 0000362212 00000 n 0000362944 00000 n 0000364874 00000 n 0000364648 00000 n 0000363082 00000 n 0000364764 00000 n 0000364819 00000 n 0000365390 00000 n 0000365219 00000 n 0000365017 00000 n 0000365335 00000 n 0000366704 00000 n 0000366478 00000 n 0000365461 00000 n 0000366594 00000 n 0000366649 00000 n 0000368147 00000 n 0000367976 00000 n 0000366798 00000 n 0000368092 00000 n 0000370317 00000 n 0000369969 00000 n 0000368255 00000 n 0000370085 00000 n 0000370140 00000 n 0000370199 00000 n 0000370258 00000 n 0000811254 00000 n 0000373468 00000 n 0000372947 00000 n 0000370423 00000 n 0000373063 00000 n 0000373118 00000 n 0000373173 00000 n 0000373232 00000 n 0000373291 00000 n 0000373350 00000 n 0000373409 00000 n 0000376449 00000 n 0000375865 00000 n 0000373574 00000 n 0000375981 00000 n 0000376036 00000 n 0000376095 00000 n 0000376154 00000 n 0000376213 00000 n 0000376272 00000 n 0000376331 00000 n 0000376390 00000 n 0000379682 00000 n 0000379220 00000 n 0000376555 00000 n 0000379336 00000 n 0000379391 00000 n 0000379446 00000 n 0000379505 00000 n 0000379564 00000 n 0000379623 00000 n 0000382801 00000 n 0000382453 00000 n 0000379826 00000 n 0000382569 00000 n 0000382624 00000 n 0000382683 00000 n 0000382742 00000 n 0000385864 00000 n 0000385693 00000 n 0000382946 00000 n 0000385809 00000 n 0000388533 00000 n 0000388303 00000 n 0000385984 00000 n 0000388419 00000 n 0000388474 00000 n 0000811379 00000 n 0000389024 00000 n 0000388853 00000 n 0000388651 00000 n 0000388969 00000 n 0000391830 00000 n 0000391604 00000 n 0000389095 00000 n 0000391720 00000 n 0000391775 00000 n 0000393069 00000 n 0000392898 00000 n 0000391960 00000 n 0000393014 00000 n 0000394917 00000 n 0000394632 00000 n 0000393140 00000 n 0000394748 00000 n 0000394803 00000 n 0000394858 00000 n 0000397672 00000 n 0000397443 00000 n 0000395023 00000 n 0000397559 00000 n 0000398797 00000 n 0000398626 00000 n 0000397790 00000 n 0000398742 00000 n 0000811504 00000 n 0000399253 00000 n 0000399082 00000 n 0000398880 00000 n 0000399198 00000 n 0000400535 00000 n 0000400192 00000 n 0000399324 00000 n 0000400308 00000 n 0000400363 00000 n 0000400418 00000 n 0000400476 00000 n 0000401687 00000 n 0000401457 00000 n 0000400629 00000 n 0000401573 00000 n 0000401628 00000 n 0000402924 00000 n 0000402753 00000 n 0000401781 00000 n 0000402869 00000 n 0000403758 00000 n 0000403587 00000 n 0000403007 00000 n 0000403703 00000 n 0000404747 00000 n 0000404576 00000 n 0000403841 00000 n 0000404692 00000 n 0000811629 00000 n 0000405796 00000 n 0000405566 00000 n 0000404830 00000 n 0000405682 00000 n 0000405737 00000 n 0000406856 00000 n 0000406685 00000 n 0000405890 00000 n 0000406801 00000 n 0000408025 00000 n 0000407854 00000 n 0000406939 00000 n 0000407970 00000 n 0000409369 00000 n 0000409198 00000 n 0000408108 00000 n 0000409314 00000 n 0000410460 00000 n 0000410289 00000 n 0000409452 00000 n 0000410405 00000 n 0000411491 00000 n 0000411320 00000 n 0000410543 00000 n 0000411436 00000 n 0000811754 00000 n 0000412683 00000 n 0000412512 00000 n 0000411574 00000 n 0000412628 00000 n 0000413888 00000 n 0000413658 00000 n 0000412766 00000 n 0000413774 00000 n 0000413829 00000 n 0000415266 00000 n 0000415037 00000 n 0000413982 00000 n 0000415153 00000 n 0000415208 00000 n 0000416454 00000 n 0000416283 00000 n 0000415360 00000 n 0000416399 00000 n 0000417573 00000 n 0000417347 00000 n 0000416537 00000 n 0000417463 00000 n 0000417518 00000 n 0000418737 00000 n 0000418566 00000 n 0000417667 00000 n 0000418682 00000 n 0000811879 00000 n 0000419797 00000 n 0000419626 00000 n 0000418820 00000 n 0000419742 00000 n 0000420956 00000 n 0000420726 00000 n 0000419880 00000 n 0000420842 00000 n 0000420897 00000 n 0000421965 00000 n 0000421794 00000 n 0000421050 00000 n 0000421910 00000 n 0000423136 00000 n 0000422906 00000 n 0000422048 00000 n 0000423022 00000 n 0000423077 00000 n 0000424286 00000 n 0000424056 00000 n 0000423230 00000 n 0000424172 00000 n 0000424227 00000 n 0000425102 00000 n 0000424931 00000 n 0000424380 00000 n 0000425047 00000 n 0000812004 00000 n 0000425558 00000 n 0000425387 00000 n 0000425185 00000 n 0000425503 00000 n 0000430147 00000 n 0000430281 00000 n 0000430415 00000 n 0000430549 00000 n 0000430683 00000 n 0000430817 00000 n 0000430951 00000 n 0000431085 00000 n 0000431219 00000 n 0000431353 00000 n 0000431487 00000 n 0000431621 00000 n 0000431755 00000 n 0000431889 00000 n 0000432023 00000 n 0000432157 00000 n 0000432290 00000 n 0000432423 00000 n 0000432556 00000 n 0000432689 00000 n 0000432822 00000 n 0000432955 00000 n 0000433088 00000 n 0000433222 00000 n 0000433355 00000 n 0000433489 00000 n 0000433624 00000 n 0000433758 00000 n 0000433892 00000 n 0000434026 00000 n 0000434161 00000 n 0000434296 00000 n 0000434430 00000 n 0000434564 00000 n 0000434699 00000 n 0000434834 00000 n 0000434965 00000 n 0000435097 00000 n 0000435230 00000 n 0000435361 00000 n 0000435489 00000 n 0000435619 00000 n 0000435749 00000 n 0000435880 00000 n 0000436010 00000 n 0000436140 00000 n 0000436270 00000 n 0000436400 00000 n 0000436531 00000 n 0000436661 00000 n 0000436792 00000 n 0000436921 00000 n 0000437051 00000 n 0000437183 00000 n 0000437313 00000 n 0000437448 00000 n 0000437579 00000 n 0000437709 00000 n 0000437839 00000 n 0000437970 00000 n 0000438101 00000 n 0000438235 00000 n 0000438365 00000 n 0000438495 00000 n 0000438626 00000 n 0000438756 00000 n 0000438886 00000 n 0000439016 00000 n 0000439145 00000 n 0000439275 00000 n 0000439405 00000 n 0000439536 00000 n 0000439666 00000 n 0000439795 00000 n 0000439926 00000 n 0000440056 00000 n 0000440190 00000 n 0000440320 00000 n 0000440452 00000 n 0000440580 00000 n 0000445888 00000 n 0000446022 00000 n 0000446156 00000 n 0000446290 00000 n 0000446424 00000 n 0000446558 00000 n 0000446693 00000 n 0000446827 00000 n 0000446961 00000 n 0000447095 00000 n 0000447229 00000 n 0000447363 00000 n 0000447497 00000 n 0000447631 00000 n 0000447765 00000 n 0000447900 00000 n 0000448034 00000 n 0000440818 00000 n 0000429299 00000 n 0000425629 00000 n 0000440708 00000 n 0000440763 00000 n 0000807464 00000 n 0000806738 00000 n 0000448168 00000 n 0000448302 00000 n 0000448436 00000 n 0000448570 00000 n 0000448705 00000 n 0000448839 00000 n 0000448974 00000 n 0000449108 00000 n 0000449243 00000 n 0000449377 00000 n 0000449512 00000 n 0000449646 00000 n 0000449781 00000 n 0000449915 00000 n 0000450048 00000 n 0000450178 00000 n 0000450311 00000 n 0000450443 00000 n 0000450577 00000 n 0000450711 00000 n 0000450844 00000 n 0000450978 00000 n 0000451112 00000 n 0000451244 00000 n 0000451376 00000 n 0000451507 00000 n 0000451639 00000 n 0000451769 00000 n 0000451901 00000 n 0000452031 00000 n 0000452162 00000 n 0000452292 00000 n 0000452422 00000 n 0000452553 00000 n 0000452683 00000 n 0000452813 00000 n 0000452943 00000 n 0000453077 00000 n 0000453207 00000 n 0000453336 00000 n 0000453466 00000 n 0000453594 00000 n 0000453724 00000 n 0000453858 00000 n 0000453988 00000 n 0000454120 00000 n 0000454248 00000 n 0000454379 00000 n 0000454510 00000 n 0000454640 00000 n 0000454770 00000 n 0000454899 00000 n 0000455029 00000 n 0000455159 00000 n 0000455289 00000 n 0000455420 00000 n 0000455551 00000 n 0000455681 00000 n 0000455810 00000 n 0000455943 00000 n 0000456074 00000 n 0000456205 00000 n 0000456337 00000 n 0000456467 00000 n 0000456597 00000 n 0000456727 00000 n 0000456856 00000 n 0000456989 00000 n 0000457120 00000 n 0000457250 00000 n 0000457380 00000 n 0000457508 00000 n 0000460370 00000 n 0000460504 00000 n 0000460638 00000 n 0000460773 00000 n 0000460907 00000 n 0000461040 00000 n 0000461174 00000 n 0000461308 00000 n 0000457691 00000 n 0000444959 00000 n 0000440953 00000 n 0000457636 00000 n 0000461442 00000 n 0000461576 00000 n 0000461710 00000 n 0000461845 00000 n 0000461979 00000 n 0000462113 00000 n 0000462247 00000 n 0000462382 00000 n 0000462517 00000 n 0000462652 00000 n 0000462785 00000 n 0000462918 00000 n 0000463051 00000 n 0000463185 00000 n 0000463319 00000 n 0000463453 00000 n 0000463587 00000 n 0000463721 00000 n 0000463856 00000 n 0000463989 00000 n 0000464120 00000 n 0000464250 00000 n 0000464380 00000 n 0000464510 00000 n 0000464643 00000 n 0000464774 00000 n 0000464904 00000 n 0000465037 00000 n 0000465168 00000 n 0000465299 00000 n 0000465430 00000 n 0000465560 00000 n 0000465745 00000 n 0000459882 00000 n 0000457812 00000 n 0000465690 00000 n 0000466239 00000 n 0000466068 00000 n 0000465866 00000 n 0000466184 00000 n 0000472167 00000 n 0000472301 00000 n 0000472436 00000 n 0000472570 00000 n 0000472704 00000 n 0000472839 00000 n 0000472974 00000 n 0000473109 00000 n 0000473244 00000 n 0000473378 00000 n 0000473513 00000 n 0000473647 00000 n 0000473782 00000 n 0000473917 00000 n 0000474052 00000 n 0000474185 00000 n 0000474320 00000 n 0000474454 00000 n 0000474587 00000 n 0000474722 00000 n 0000474855 00000 n 0000474989 00000 n 0000475124 00000 n 0000475258 00000 n 0000475393 00000 n 0000475526 00000 n 0000475660 00000 n 0000475794 00000 n 0000475928 00000 n 0000476062 00000 n 0000476196 00000 n 0000476331 00000 n 0000476465 00000 n 0000476599 00000 n 0000476733 00000 n 0000476865 00000 n 0000476997 00000 n 0000477128 00000 n 0000477258 00000 n 0000477388 00000 n 0000477518 00000 n 0000477648 00000 n 0000477782 00000 n 0000477912 00000 n 0000478043 00000 n 0000478173 00000 n 0000478301 00000 n 0000478430 00000 n 0000478560 00000 n 0000478690 00000 n 0000478820 00000 n 0000478950 00000 n 0000479080 00000 n 0000479210 00000 n 0000479340 00000 n 0000479469 00000 n 0000479599 00000 n 0000479734 00000 n 0000479865 00000 n 0000479995 00000 n 0000480128 00000 n 0000480259 00000 n 0000480392 00000 n 0000480523 00000 n 0000480654 00000 n 0000480784 00000 n 0000480915 00000 n 0000481045 00000 n 0000481175 00000 n 0000481306 00000 n 0000481436 00000 n 0000481566 00000 n 0000481697 00000 n 0000481828 00000 n 0000481959 00000 n 0000482094 00000 n 0000482225 00000 n 0000482356 00000 n 0000482489 00000 n 0000482620 00000 n 0000482750 00000 n 0000482879 00000 n 0000483010 00000 n 0000483141 00000 n 0000483270 00000 n 0000483401 00000 n 0000483531 00000 n 0000483662 00000 n 0000483792 00000 n 0000483921 00000 n 0000491208 00000 n 0000491342 00000 n 0000491476 00000 n 0000491610 00000 n 0000491744 00000 n 0000491878 00000 n 0000492013 00000 n 0000492147 00000 n 0000492281 00000 n 0000492416 00000 n 0000492550 00000 n 0000492684 00000 n 0000492818 00000 n 0000484157 00000 n 0000471229 00000 n 0000466310 00000 n 0000484047 00000 n 0000484102 00000 n 0000812129 00000 n 0000492953 00000 n 0000493087 00000 n 0000493221 00000 n 0000493355 00000 n 0000493489 00000 n 0000493624 00000 n 0000493758 00000 n 0000493890 00000 n 0000494025 00000 n 0000494159 00000 n 0000494294 00000 n 0000494429 00000 n 0000494563 00000 n 0000494697 00000 n 0000494829 00000 n 0000494963 00000 n 0000495097 00000 n 0000495232 00000 n 0000495366 00000 n 0000495500 00000 n 0000495635 00000 n 0000495770 00000 n 0000495905 00000 n 0000496037 00000 n 0000496171 00000 n 0000496305 00000 n 0000496440 00000 n 0000496575 00000 n 0000496710 00000 n 0000496844 00000 n 0000496978 00000 n 0000497112 00000 n 0000497247 00000 n 0000497381 00000 n 0000497515 00000 n 0000497648 00000 n 0000497783 00000 n 0000497918 00000 n 0000498052 00000 n 0000498187 00000 n 0000498322 00000 n 0000498457 00000 n 0000498592 00000 n 0000498726 00000 n 0000498858 00000 n 0000498989 00000 n 0000499122 00000 n 0000499253 00000 n 0000499384 00000 n 0000499515 00000 n 0000499645 00000 n 0000499775 00000 n 0000499905 00000 n 0000500035 00000 n 0000500165 00000 n 0000500295 00000 n 0000500424 00000 n 0000500555 00000 n 0000500685 00000 n 0000500815 00000 n 0000500944 00000 n 0000501074 00000 n 0000501204 00000 n 0000501335 00000 n 0000501464 00000 n 0000501595 00000 n 0000501726 00000 n 0000501857 00000 n 0000501987 00000 n 0000502116 00000 n 0000502247 00000 n 0000502377 00000 n 0000502507 00000 n 0000502637 00000 n 0000502767 00000 n 0000502896 00000 n 0000503026 00000 n 0000503156 00000 n 0000503286 00000 n 0000503415 00000 n 0000503545 00000 n 0000503675 00000 n 0000503806 00000 n 0000503936 00000 n 0000504066 00000 n 0000504197 00000 n 0000504328 00000 n 0000504458 00000 n 0000504588 00000 n 0000504718 00000 n 0000504848 00000 n 0000504979 00000 n 0000505109 00000 n 0000505238 00000 n 0000505367 00000 n 0000505495 00000 n 0000512100 00000 n 0000512235 00000 n 0000505676 00000 n 0000490099 00000 n 0000484292 00000 n 0000505621 00000 n 0000512370 00000 n 0000512505 00000 n 0000512639 00000 n 0000512773 00000 n 0000512908 00000 n 0000513043 00000 n 0000513177 00000 n 0000513311 00000 n 0000513446 00000 n 0000513580 00000 n 0000513712 00000 n 0000513844 00000 n 0000513977 00000 n 0000514111 00000 n 0000514245 00000 n 0000514380 00000 n 0000514514 00000 n 0000514649 00000 n 0000514781 00000 n 0000514915 00000 n 0000515050 00000 n 0000515185 00000 n 0000515320 00000 n 0000515455 00000 n 0000515590 00000 n 0000515723 00000 n 0000515858 00000 n 0000515992 00000 n 0000516125 00000 n 0000516259 00000 n 0000516393 00000 n 0000516527 00000 n 0000516660 00000 n 0000516794 00000 n 0000516929 00000 n 0000517062 00000 n 0000517196 00000 n 0000517331 00000 n 0000517466 00000 n 0000517599 00000 n 0000517732 00000 n 0000517866 00000 n 0000517999 00000 n 0000518133 00000 n 0000518265 00000 n 0000518396 00000 n 0000518530 00000 n 0000518660 00000 n 0000518790 00000 n 0000518920 00000 n 0000519055 00000 n 0000519186 00000 n 0000519321 00000 n 0000519452 00000 n 0000519583 00000 n 0000519712 00000 n 0000519845 00000 n 0000519976 00000 n 0000520107 00000 n 0000520238 00000 n 0000520369 00000 n 0000520500 00000 n 0000520631 00000 n 0000520764 00000 n 0000520895 00000 n 0000521026 00000 n 0000521156 00000 n 0000521286 00000 n 0000521416 00000 n 0000521547 00000 n 0000521678 00000 n 0000521808 00000 n 0000521939 00000 n 0000522069 00000 n 0000522200 00000 n 0000522330 00000 n 0000522459 00000 n 0000522589 00000 n 0000522720 00000 n 0000522850 00000 n 0000522984 00000 n 0000523114 00000 n 0000523245 00000 n 0000523376 00000 n 0000523507 00000 n 0000523641 00000 n 0000523771 00000 n 0000523901 00000 n 0000524031 00000 n 0000524161 00000 n 0000524291 00000 n 0000524426 00000 n 0000524557 00000 n 0000524687 00000 n 0000524818 00000 n 0000524949 00000 n 0000525078 00000 n 0000525205 00000 n 0000532263 00000 n 0000532396 00000 n 0000532530 00000 n 0000532662 00000 n 0000532797 00000 n 0000532932 00000 n 0000533067 00000 n 0000533201 00000 n 0000533335 00000 n 0000533469 00000 n 0000533604 00000 n 0000525387 00000 n 0000511072 00000 n 0000505797 00000 n 0000525332 00000 n 0000533739 00000 n 0000533874 00000 n 0000534009 00000 n 0000534143 00000 n 0000534277 00000 n 0000534411 00000 n 0000534545 00000 n 0000534680 00000 n 0000534814 00000 n 0000534949 00000 n 0000535083 00000 n 0000535217 00000 n 0000535351 00000 n 0000535485 00000 n 0000535619 00000 n 0000535752 00000 n 0000535885 00000 n 0000536020 00000 n 0000536154 00000 n 0000536288 00000 n 0000536422 00000 n 0000536556 00000 n 0000536690 00000 n 0000536825 00000 n 0000536959 00000 n 0000537093 00000 n 0000537227 00000 n 0000537361 00000 n 0000537496 00000 n 0000537630 00000 n 0000537764 00000 n 0000537899 00000 n 0000538032 00000 n 0000538167 00000 n 0000538300 00000 n 0000538435 00000 n 0000538570 00000 n 0000538705 00000 n 0000538839 00000 n 0000538971 00000 n 0000539101 00000 n 0000539230 00000 n 0000539360 00000 n 0000539489 00000 n 0000539619 00000 n 0000539749 00000 n 0000539879 00000 n 0000540009 00000 n 0000540139 00000 n 0000540269 00000 n 0000540399 00000 n 0000540529 00000 n 0000540660 00000 n 0000540791 00000 n 0000540922 00000 n 0000541052 00000 n 0000541182 00000 n 0000541312 00000 n 0000541442 00000 n 0000541573 00000 n 0000541704 00000 n 0000541835 00000 n 0000541965 00000 n 0000542095 00000 n 0000542226 00000 n 0000542357 00000 n 0000542485 00000 n 0000542614 00000 n 0000542743 00000 n 0000542874 00000 n 0000543004 00000 n 0000543134 00000 n 0000543265 00000 n 0000543395 00000 n 0000543525 00000 n 0000543655 00000 n 0000543786 00000 n 0000543916 00000 n 0000544047 00000 n 0000544178 00000 n 0000544308 00000 n 0000544439 00000 n 0000544569 00000 n 0000544698 00000 n 0000544828 00000 n 0000544958 00000 n 0000545087 00000 n 0000545217 00000 n 0000545348 00000 n 0000545479 00000 n 0000545608 00000 n 0000550510 00000 n 0000545791 00000 n 0000531217 00000 n 0000525508 00000 n 0000545736 00000 n 0000550645 00000 n 0000550779 00000 n 0000550913 00000 n 0000551047 00000 n 0000551181 00000 n 0000551316 00000 n 0000551450 00000 n 0000551584 00000 n 0000551719 00000 n 0000551854 00000 n 0000551988 00000 n 0000552122 00000 n 0000552256 00000 n 0000552390 00000 n 0000552524 00000 n 0000552659 00000 n 0000552793 00000 n 0000552928 00000 n 0000553063 00000 n 0000553197 00000 n 0000553329 00000 n 0000553463 00000 n 0000553598 00000 n 0000553733 00000 n 0000553868 00000 n 0000554002 00000 n 0000554136 00000 n 0000554270 00000 n 0000554404 00000 n 0000554539 00000 n 0000554673 00000 n 0000554808 00000 n 0000554943 00000 n 0000555078 00000 n 0000555213 00000 n 0000555347 00000 n 0000555482 00000 n 0000555613 00000 n 0000555743 00000 n 0000555877 00000 n 0000556007 00000 n 0000556137 00000 n 0000556268 00000 n 0000556398 00000 n 0000556529 00000 n 0000556663 00000 n 0000556798 00000 n 0000556929 00000 n 0000557059 00000 n 0000557190 00000 n 0000557320 00000 n 0000557448 00000 n 0000557577 00000 n 0000557707 00000 n 0000557837 00000 n 0000557967 00000 n 0000558097 00000 n 0000558228 00000 n 0000558356 00000 n 0000558486 00000 n 0000558616 00000 n 0000558750 00000 n 0000558883 00000 n 0000559014 00000 n 0000559144 00000 n 0000559329 00000 n 0000549788 00000 n 0000545912 00000 n 0000559274 00000 n 0000559823 00000 n 0000559652 00000 n 0000559450 00000 n 0000559768 00000 n 0000562065 00000 n 0000562200 00000 n 0000562334 00000 n 0000562469 00000 n 0000562603 00000 n 0000562738 00000 n 0000562872 00000 n 0000563006 00000 n 0000563141 00000 n 0000563276 00000 n 0000563411 00000 n 0000563545 00000 n 0000563678 00000 n 0000563813 00000 n 0000563947 00000 n 0000564081 00000 n 0000564211 00000 n 0000564341 00000 n 0000564472 00000 n 0000564602 00000 n 0000564732 00000 n 0000564862 00000 n 0000565102 00000 n 0000561739 00000 n 0000559894 00000 n 0000564992 00000 n 0000565047 00000 n 0000812254 00000 n 0000565584 00000 n 0000565413 00000 n 0000565211 00000 n 0000565529 00000 n 0000568489 00000 n 0000568617 00000 n 0000568745 00000 n 0000568874 00000 n 0000569003 00000 n 0000569132 00000 n 0000569261 00000 n 0000569389 00000 n 0000569517 00000 n 0000569644 00000 n 0000569772 00000 n 0000569901 00000 n 0000570030 00000 n 0000570160 00000 n 0000570290 00000 n 0000570420 00000 n 0000570550 00000 n 0000570680 00000 n 0000570810 00000 n 0000570940 00000 n 0000571069 00000 n 0000571199 00000 n 0000571329 00000 n 0000571459 00000 n 0000571588 00000 n 0000571718 00000 n 0000571847 00000 n 0000571977 00000 n 0000572107 00000 n 0000572237 00000 n 0000572367 00000 n 0000572497 00000 n 0000572625 00000 n 0000572754 00000 n 0000572883 00000 n 0000573013 00000 n 0000573143 00000 n 0000573273 00000 n 0000573402 00000 n 0000576927 00000 n 0000577057 00000 n 0000573584 00000 n 0000568010 00000 n 0000565655 00000 n 0000573529 00000 n 0000806159 00000 n 0000577187 00000 n 0000577317 00000 n 0000577446 00000 n 0000577576 00000 n 0000577705 00000 n 0000577835 00000 n 0000577965 00000 n 0000578095 00000 n 0000578225 00000 n 0000578355 00000 n 0000578484 00000 n 0000578614 00000 n 0000578744 00000 n 0000578874 00000 n 0000579004 00000 n 0000579134 00000 n 0000579264 00000 n 0000579394 00000 n 0000579523 00000 n 0000579653 00000 n 0000579783 00000 n 0000579913 00000 n 0000580042 00000 n 0000580170 00000 n 0000580299 00000 n 0000580429 00000 n 0000580559 00000 n 0000580689 00000 n 0000580819 00000 n 0000580949 00000 n 0000581079 00000 n 0000581209 00000 n 0000581339 00000 n 0000581468 00000 n 0000581598 00000 n 0000581728 00000 n 0000581858 00000 n 0000581987 00000 n 0000582117 00000 n 0000582247 00000 n 0000582377 00000 n 0000582507 00000 n 0000582637 00000 n 0000582767 00000 n 0000582897 00000 n 0000583027 00000 n 0000586474 00000 n 0000583210 00000 n 0000576367 00000 n 0000573692 00000 n 0000583155 00000 n 0000586604 00000 n 0000586734 00000 n 0000586864 00000 n 0000586994 00000 n 0000587123 00000 n 0000587252 00000 n 0000587382 00000 n 0000587512 00000 n 0000587642 00000 n 0000587771 00000 n 0000587901 00000 n 0000588031 00000 n 0000588161 00000 n 0000588291 00000 n 0000588421 00000 n 0000588551 00000 n 0000588681 00000 n 0000588811 00000 n 0000588940 00000 n 0000589069 00000 n 0000589199 00000 n 0000589329 00000 n 0000589459 00000 n 0000589589 00000 n 0000589719 00000 n 0000589848 00000 n 0000589978 00000 n 0000590108 00000 n 0000590238 00000 n 0000590368 00000 n 0000590498 00000 n 0000590628 00000 n 0000590758 00000 n 0000590888 00000 n 0000591016 00000 n 0000591146 00000 n 0000591276 00000 n 0000591406 00000 n 0000591536 00000 n 0000591666 00000 n 0000591795 00000 n 0000591925 00000 n 0000592055 00000 n 0000592185 00000 n 0000592315 00000 n 0000592445 00000 n 0000592575 00000 n 0000596009 00000 n 0000592758 00000 n 0000585914 00000 n 0000583293 00000 n 0000592703 00000 n 0000596139 00000 n 0000596269 00000 n 0000596399 00000 n 0000596529 00000 n 0000596658 00000 n 0000596787 00000 n 0000596917 00000 n 0000597047 00000 n 0000597177 00000 n 0000597306 00000 n 0000597436 00000 n 0000597566 00000 n 0000597696 00000 n 0000597826 00000 n 0000597956 00000 n 0000598086 00000 n 0000598216 00000 n 0000598346 00000 n 0000598476 00000 n 0000598605 00000 n 0000598735 00000 n 0000598865 00000 n 0000598995 00000 n 0000599124 00000 n 0000599252 00000 n 0000599382 00000 n 0000599512 00000 n 0000599642 00000 n 0000599772 00000 n 0000599902 00000 n 0000600032 00000 n 0000600162 00000 n 0000600291 00000 n 0000600421 00000 n 0000600550 00000 n 0000600680 00000 n 0000600810 00000 n 0000600940 00000 n 0000601070 00000 n 0000601200 00000 n 0000601330 00000 n 0000601460 00000 n 0000601590 00000 n 0000601720 00000 n 0000601850 00000 n 0000601980 00000 n 0000602110 00000 n 0000605492 00000 n 0000602293 00000 n 0000595449 00000 n 0000592841 00000 n 0000602238 00000 n 0000605622 00000 n 0000605752 00000 n 0000605882 00000 n 0000606012 00000 n 0000606141 00000 n 0000606270 00000 n 0000606400 00000 n 0000606530 00000 n 0000606660 00000 n 0000606790 00000 n 0000606920 00000 n 0000607050 00000 n 0000607180 00000 n 0000607310 00000 n 0000607440 00000 n 0000607570 00000 n 0000607700 00000 n 0000607829 00000 n 0000607959 00000 n 0000608089 00000 n 0000608219 00000 n 0000608349 00000 n 0000608479 00000 n 0000608608 00000 n 0000608736 00000 n 0000608865 00000 n 0000608995 00000 n 0000609125 00000 n 0000609251 00000 n 0000609381 00000 n 0000609511 00000 n 0000609641 00000 n 0000609770 00000 n 0000609900 00000 n 0000610029 00000 n 0000610159 00000 n 0000610289 00000 n 0000610419 00000 n 0000610548 00000 n 0000610677 00000 n 0000610807 00000 n 0000610937 00000 n 0000611067 00000 n 0000611197 00000 n 0000611327 00000 n 0000611457 00000 n 0000611587 00000 n 0000615201 00000 n 0000611769 00000 n 0000604932 00000 n 0000602376 00000 n 0000611714 00000 n 0000812379 00000 n 0000615331 00000 n 0000615461 00000 n 0000615591 00000 n 0000615721 00000 n 0000615850 00000 n 0000615979 00000 n 0000616109 00000 n 0000616239 00000 n 0000616369 00000 n 0000616498 00000 n 0000616628 00000 n 0000616758 00000 n 0000616888 00000 n 0000617018 00000 n 0000617148 00000 n 0000617278 00000 n 0000617408 00000 n 0000617538 00000 n 0000617669 00000 n 0000617799 00000 n 0000617930 00000 n 0000618061 00000 n 0000618192 00000 n 0000618322 00000 n 0000618453 00000 n 0000618583 00000 n 0000618714 00000 n 0000618845 00000 n 0000618976 00000 n 0000619107 00000 n 0000619238 00000 n 0000619369 00000 n 0000619500 00000 n 0000619631 00000 n 0000619761 00000 n 0000619892 00000 n 0000620023 00000 n 0000620154 00000 n 0000620284 00000 n 0000620415 00000 n 0000620545 00000 n 0000620675 00000 n 0000620806 00000 n 0000620937 00000 n 0000621068 00000 n 0000621199 00000 n 0000621330 00000 n 0000624799 00000 n 0000621514 00000 n 0000614641 00000 n 0000611864 00000 n 0000621459 00000 n 0000624930 00000 n 0000625061 00000 n 0000625192 00000 n 0000625323 00000 n 0000625454 00000 n 0000625585 00000 n 0000625715 00000 n 0000625845 00000 n 0000625976 00000 n 0000626107 00000 n 0000626238 00000 n 0000626369 00000 n 0000626499 00000 n 0000626629 00000 n 0000626760 00000 n 0000626891 00000 n 0000627022 00000 n 0000627153 00000 n 0000627284 00000 n 0000627415 00000 n 0000627545 00000 n 0000627676 00000 n 0000627807 00000 n 0000627938 00000 n 0000628069 00000 n 0000628200 00000 n 0000628330 00000 n 0000628460 00000 n 0000628590 00000 n 0000628720 00000 n 0000628851 00000 n 0000628982 00000 n 0000629113 00000 n 0000629243 00000 n 0000629374 00000 n 0000629505 00000 n 0000629636 00000 n 0000629767 00000 n 0000629898 00000 n 0000630029 00000 n 0000630160 00000 n 0000630290 00000 n 0000630420 00000 n 0000631297 00000 n 0000630604 00000 n 0000624275 00000 n 0000621609 00000 n 0000630549 00000 n 0000631424 00000 n 0000631555 00000 n 0000631741 00000 n 0000631142 00000 n 0000630724 00000 n 0000631686 00000 n 0000631837 00000 n 0000845717 00000 n 0000631898 00000 n 0000631951 00000 n 0000845633 00000 n 0000632002 00000 n 0000632035 00000 n 0000845534 00000 n 0000632088 00000 n 0000632123 00000 n 0000845435 00000 n 0000632174 00000 n 0000632216 00000 n 0000845336 00000 n 0000632274 00000 n 0000632314 00000 n 0000845252 00000 n 0000632375 00000 n 0000632418 00000 n 0000845153 00000 n 0000632462 00000 n 0000632498 00000 n 0000845054 00000 n 0000632543 00000 n 0000632580 00000 n 0000844913 00000 n 0000632636 00000 n 0000632674 00000 n 0000844829 00000 n 0000632726 00000 n 0000632760 00000 n 0000844730 00000 n 0000632820 00000 n 0000632862 00000 n 0000844631 00000 n 0000632924 00000 n 0000632968 00000 n 0000844491 00000 n 0000633038 00000 n 0000633090 00000 n 0000844407 00000 n 0000633161 00000 n 0000633214 00000 n 0000844308 00000 n 0000633270 00000 n 0000633308 00000 n 0000844224 00000 n 0000633367 00000 n 0000633408 00000 n 0000844083 00000 n 0000633463 00000 n 0000633500 00000 n 0000843999 00000 n 0000633577 00000 n 0000633636 00000 n 0000843900 00000 n 0000633689 00000 n 0000633724 00000 n 0000843801 00000 n 0000633776 00000 n 0000633810 00000 n 0000843702 00000 n 0000633859 00000 n 0000633890 00000 n 0000843603 00000 n 0000633939 00000 n 0000633970 00000 n 0000843504 00000 n 0000634020 00000 n 0000634052 00000 n 0000843405 00000 n 0000634100 00000 n 0000634130 00000 n 0000843306 00000 n 0000634178 00000 n 0000634208 00000 n 0000843207 00000 n 0000634252 00000 n 0000634278 00000 n 0000843108 00000 n 0000634323 00000 n 0000634350 00000 n 0000843009 00000 n 0000634396 00000 n 0000634424 00000 n 0000842910 00000 n 0000634474 00000 n 0000634506 00000 n 0000842811 00000 n 0000634552 00000 n 0000634580 00000 n 0000842712 00000 n 0000634629 00000 n 0000634660 00000 n 0000842613 00000 n 0000634705 00000 n 0000634732 00000 n 0000842514 00000 n 0000634782 00000 n 0000634814 00000 n 0000842415 00000 n 0000634869 00000 n 0000634906 00000 n 0000842316 00000 n 0000634951 00000 n 0000634978 00000 n 0000842217 00000 n 0000635027 00000 n 0000635058 00000 n 0000842118 00000 n 0000635110 00000 n 0000635144 00000 n 0000842019 00000 n 0000635193 00000 n 0000635224 00000 n 0000841935 00000 n 0000635287 00000 n 0000635332 00000 n 0000841795 00000 n 0000635374 00000 n 0000635398 00000 n 0000841711 00000 n 0000635441 00000 n 0000635484 00000 n 0000841612 00000 n 0000635535 00000 n 0000635568 00000 n 0000841513 00000 n 0000635615 00000 n 0000635644 00000 n 0000841414 00000 n 0000635690 00000 n 0000635718 00000 n 0000841315 00000 n 0000635776 00000 n 0000635816 00000 n 0000841231 00000 n 0000635872 00000 n 0000635910 00000 n 0000841132 00000 n 0000635955 00000 n 0000635982 00000 n 0000841033 00000 n 0000636031 00000 n 0000636062 00000 n 0000840934 00000 n 0000636110 00000 n 0000636140 00000 n 0000840793 00000 n 0000636186 00000 n 0000636214 00000 n 0000840709 00000 n 0000636265 00000 n 0000636298 00000 n 0000840610 00000 n 0000636343 00000 n 0000636370 00000 n 0000840511 00000 n 0000636423 00000 n 0000636458 00000 n 0000840412 00000 n 0000636507 00000 n 0000636538 00000 n 0000840313 00000 n 0000636591 00000 n 0000636626 00000 n 0000840214 00000 n 0000636684 00000 n 0000636724 00000 n 0000840115 00000 n 0000636771 00000 n 0000636800 00000 n 0000840016 00000 n 0000636849 00000 n 0000636880 00000 n 0000839917 00000 n 0000636936 00000 n 0000636974 00000 n 0000839818 00000 n 0000637039 00000 n 0000637086 00000 n 0000839719 00000 n 0000637152 00000 n 0000637200 00000 n 0000839620 00000 n 0000637252 00000 n 0000637286 00000 n 0000839521 00000 n 0000637340 00000 n 0000637376 00000 n 0000839422 00000 n 0000637430 00000 n 0000637466 00000 n 0000839323 00000 n 0000637517 00000 n 0000637550 00000 n 0000839224 00000 n 0000637598 00000 n 0000637628 00000 n 0000839125 00000 n 0000637682 00000 n 0000637718 00000 n 0000839026 00000 n 0000637770 00000 n 0000637804 00000 n 0000838927 00000 n 0000637861 00000 n 0000637900 00000 n 0000838828 00000 n 0000637958 00000 n 0000637998 00000 n 0000838729 00000 n 0000638054 00000 n 0000638092 00000 n 0000838630 00000 n 0000638149 00000 n 0000638188 00000 n 0000838531 00000 n 0000638233 00000 n 0000638260 00000 n 0000838432 00000 n 0000638317 00000 n 0000638356 00000 n 0000838333 00000 n 0000638401 00000 n 0000638428 00000 n 0000838234 00000 n 0000638485 00000 n 0000638524 00000 n 0000838135 00000 n 0000638575 00000 n 0000638608 00000 n 0000838036 00000 n 0000638662 00000 n 0000638698 00000 n 0000837937 00000 n 0000638748 00000 n 0000638780 00000 n 0000837838 00000 n 0000638830 00000 n 0000638862 00000 n 0000837739 00000 n 0000638913 00000 n 0000638945 00000 n 0000837640 00000 n 0000638995 00000 n 0000639027 00000 n 0000837541 00000 n 0000639087 00000 n 0000639129 00000 n 0000837442 00000 n 0000639188 00000 n 0000639229 00000 n 0000837343 00000 n 0000639282 00000 n 0000639317 00000 n 0000837244 00000 n 0000639367 00000 n 0000639399 00000 n 0000837145 00000 n 0000639461 00000 n 0000639505 00000 n 0000837046 00000 n 0000639564 00000 n 0000639605 00000 n 0000836947 00000 n 0000639661 00000 n 0000639699 00000 n 0000836848 00000 n 0000639758 00000 n 0000639799 00000 n 0000836749 00000 n 0000639844 00000 n 0000639871 00000 n 0000836650 00000 n 0000639923 00000 n 0000639957 00000 n 0000836551 00000 n 0000640009 00000 n 0000640044 00000 n 0000836452 00000 n 0000640091 00000 n 0000640120 00000 n 0000836353 00000 n 0000640178 00000 n 0000640218 00000 n 0000836254 00000 n 0000640267 00000 n 0000640298 00000 n 0000836155 00000 n 0000640349 00000 n 0000640382 00000 n 0000836056 00000 n 0000640437 00000 n 0000640474 00000 n 0000835957 00000 n 0000640528 00000 n 0000640564 00000 n 0000835858 00000 n 0000640615 00000 n 0000640648 00000 n 0000835759 00000 n 0000640694 00000 n 0000640722 00000 n 0000835660 00000 n 0000640777 00000 n 0000640814 00000 n 0000835561 00000 n 0000640860 00000 n 0000640888 00000 n 0000835462 00000 n 0000640948 00000 n 0000640990 00000 n 0000835363 00000 n 0000641036 00000 n 0000641064 00000 n 0000835264 00000 n 0000641113 00000 n 0000641144 00000 n 0000835165 00000 n 0000641193 00000 n 0000641224 00000 n 0000835066 00000 n 0000641280 00000 n 0000641318 00000 n 0000834967 00000 n 0000641365 00000 n 0000641394 00000 n 0000834868 00000 n 0000641444 00000 n 0000641476 00000 n 0000834769 00000 n 0000641528 00000 n 0000641562 00000 n 0000834670 00000 n 0000641613 00000 n 0000641646 00000 n 0000834571 00000 n 0000641696 00000 n 0000641728 00000 n 0000834472 00000 n 0000641777 00000 n 0000641808 00000 n 0000834373 00000 n 0000641851 00000 n 0000641884 00000 n 0000834274 00000 n 0000641935 00000 n 0000641968 00000 n 0000834175 00000 n 0000642017 00000 n 0000642048 00000 n 0000834076 00000 n 0000642096 00000 n 0000642126 00000 n 0000833977 00000 n 0000642170 00000 n 0000642196 00000 n 0000833878 00000 n 0000642251 00000 n 0000642288 00000 n 0000833779 00000 n 0000642344 00000 n 0000642382 00000 n 0000833680 00000 n 0000642436 00000 n 0000642472 00000 n 0000833581 00000 n 0000642517 00000 n 0000642544 00000 n 0000833482 00000 n 0000642589 00000 n 0000642616 00000 n 0000833383 00000 n 0000642669 00000 n 0000642704 00000 n 0000833284 00000 n 0000642751 00000 n 0000642780 00000 n 0000833185 00000 n 0000642826 00000 n 0000642854 00000 n 0000833086 00000 n 0000642900 00000 n 0000642928 00000 n 0000832987 00000 n 0000642975 00000 n 0000643004 00000 n 0000832888 00000 n 0000643059 00000 n 0000643096 00000 n 0000832789 00000 n 0000643152 00000 n 0000643190 00000 n 0000832690 00000 n 0000643244 00000 n 0000643280 00000 n 0000832606 00000 n 0000643335 00000 n 0000643372 00000 n 0000832507 00000 n 0000643418 00000 n 0000643446 00000 n 0000832367 00000 n 0000643489 00000 n 0000643514 00000 n 0000832283 00000 n 0000643565 00000 n 0000643598 00000 n 0000832184 00000 n 0000643655 00000 n 0000643697 00000 n 0000832100 00000 n 0000643755 00000 n 0000643795 00000 n 0000832001 00000 n 0000643846 00000 n 0000643879 00000 n 0000831902 00000 n 0000643923 00000 n 0000643949 00000 n 0000831803 00000 n 0000643999 00000 n 0000644031 00000 n 0000831704 00000 n 0000644077 00000 n 0000644105 00000 n 0000831563 00000 n 0000644153 00000 n 0000644183 00000 n 0000831479 00000 n 0000644241 00000 n 0000644281 00000 n 0000831380 00000 n 0000644326 00000 n 0000644353 00000 n 0000831281 00000 n 0000644414 00000 n 0000644457 00000 n 0000831182 00000 n 0000644514 00000 n 0000644553 00000 n 0000831083 00000 n 0000644619 00000 n 0000644667 00000 n 0000830984 00000 n 0000644731 00000 n 0000644777 00000 n 0000830885 00000 n 0000644821 00000 n 0000644860 00000 n 0000830786 00000 n 0000644909 00000 n 0000644940 00000 n 0000830687 00000 n 0000645003 00000 n 0000645048 00000 n 0000830588 00000 n 0000645106 00000 n 0000645146 00000 n 0000830489 00000 n 0000645204 00000 n 0000645244 00000 n 0000830390 00000 n 0000645305 00000 n 0000645348 00000 n 0000830291 00000 n 0000645409 00000 n 0000645452 00000 n 0000830192 00000 n 0000645514 00000 n 0000645558 00000 n 0000830093 00000 n 0000645623 00000 n 0000645670 00000 n 0000829994 00000 n 0000645733 00000 n 0000645778 00000 n 0000829895 00000 n 0000645834 00000 n 0000645872 00000 n 0000829796 00000 n 0000645939 00000 n 0000645988 00000 n 0000829697 00000 n 0000646053 00000 n 0000646100 00000 n 0000829598 00000 n 0000646158 00000 n 0000646198 00000 n 0000829499 00000 n 0000646259 00000 n 0000646302 00000 n 0000829400 00000 n 0000646359 00000 n 0000646398 00000 n 0000829301 00000 n 0000646447 00000 n 0000646478 00000 n 0000829202 00000 n 0000646537 00000 n 0000646578 00000 n 0000829103 00000 n 0000646637 00000 n 0000646678 00000 n 0000829004 00000 n 0000646730 00000 n 0000646764 00000 n 0000828905 00000 n 0000646824 00000 n 0000646866 00000 n 0000828806 00000 n 0000646918 00000 n 0000646952 00000 n 0000828707 00000 n 0000647004 00000 n 0000647038 00000 n 0000828608 00000 n 0000647105 00000 n 0000647154 00000 n 0000828509 00000 n 0000647214 00000 n 0000647281 00000 n 0000828410 00000 n 0000647339 00000 n 0000647402 00000 n 0000828311 00000 n 0000647460 00000 n 0000647523 00000 n 0000828212 00000 n 0000647586 00000 n 0000647640 00000 n 0000828113 00000 n 0000647710 00000 n 0000647762 00000 n 0000828014 00000 n 0000647832 00000 n 0000647884 00000 n 0000827915 00000 n 0000647935 00000 n 0000647968 00000 n 0000827816 00000 n 0000648027 00000 n 0000648068 00000 n 0000827717 00000 n 0000648124 00000 n 0000648172 00000 n 0000827618 00000 n 0000648220 00000 n 0000648250 00000 n 0000827519 00000 n 0000648310 00000 n 0000648352 00000 n 0000827420 00000 n 0000648408 00000 n 0000648446 00000 n 0000827321 00000 n 0000648493 00000 n 0000648522 00000 n 0000827222 00000 n 0000648568 00000 n 0000648596 00000 n 0000827123 00000 n 0000648650 00000 n 0000648686 00000 n 0000827024 00000 n 0000648746 00000 n 0000648788 00000 n 0000826925 00000 n 0000648833 00000 n 0000648860 00000 n 0000826826 00000 n 0000648911 00000 n 0000648944 00000 n 0000826727 00000 n 0000648996 00000 n 0000649046 00000 n 0000826628 00000 n 0000649097 00000 n 0000649130 00000 n 0000826529 00000 n 0000649195 00000 n 0000649242 00000 n 0000826430 00000 n 0000649305 00000 n 0000649350 00000 n 0000826331 00000 n 0000649413 00000 n 0000649458 00000 n 0000826232 00000 n 0000649516 00000 n 0000649546 00000 n 0000826133 00000 n 0000649601 00000 n 0000649652 00000 n 0000826034 00000 n 0000649707 00000 n 0000649744 00000 n 0000825935 00000 n 0000649793 00000 n 0000649824 00000 n 0000825836 00000 n 0000649873 00000 n 0000649904 00000 n 0000825737 00000 n 0000649961 00000 n 0000650000 00000 n 0000825638 00000 n 0000650068 00000 n 0000650118 00000 n 0000825539 00000 n 0000650184 00000 n 0000650232 00000 n 0000825440 00000 n 0000650298 00000 n 0000650346 00000 n 0000825341 00000 n 0000650402 00000 n 0000650430 00000 n 0000825242 00000 n 0000650492 00000 n 0000650536 00000 n 0000825143 00000 n 0000650594 00000 n 0000650634 00000 n 0000825044 00000 n 0000650690 00000 n 0000650718 00000 n 0000824945 00000 n 0000650772 00000 n 0000650808 00000 n 0000824846 00000 n 0000650862 00000 n 0000650898 00000 n 0000824747 00000 n 0000650949 00000 n 0000650987 00000 n 0000824648 00000 n 0000651051 00000 n 0000651097 00000 n 0000824549 00000 n 0000651146 00000 n 0000651187 00000 n 0000824450 00000 n 0000651237 00000 n 0000651269 00000 n 0000824351 00000 n 0000651317 00000 n 0000651347 00000 n 0000824252 00000 n 0000651409 00000 n 0000651453 00000 n 0000824153 00000 n 0000651517 00000 n 0000651563 00000 n 0000824054 00000 n 0000651617 00000 n 0000651653 00000 n 0000823955 00000 n 0000651705 00000 n 0000651739 00000 n 0000823856 00000 n 0000651785 00000 n 0000651813 00000 n 0000823757 00000 n 0000651861 00000 n 0000651891 00000 n 0000823658 00000 n 0000651957 00000 n 0000652005 00000 n 0000823559 00000 n 0000652069 00000 n 0000652115 00000 n 0000823460 00000 n 0000652179 00000 n 0000652225 00000 n 0000823361 00000 n 0000652271 00000 n 0000652299 00000 n 0000823262 00000 n 0000652344 00000 n 0000652381 00000 n 0000823163 00000 n 0000652425 00000 n 0000652451 00000 n 0000823064 00000 n 0000652514 00000 n 0000652559 00000 n 0000822965 00000 n 0000652620 00000 n 0000652663 00000 n 0000822866 00000 n 0000652718 00000 n 0000652754 00000 n 0000822767 00000 n 0000652816 00000 n 0000652860 00000 n 0000822668 00000 n 0000652909 00000 n 0000652940 00000 n 0000822569 00000 n 0000652987 00000 n 0000653016 00000 n 0000822470 00000 n 0000653072 00000 n 0000653110 00000 n 0000822371 00000 n 0000653169 00000 n 0000653210 00000 n 0000822272 00000 n 0000653267 00000 n 0000653306 00000 n 0000822173 00000 n 0000653363 00000 n 0000653402 00000 n 0000822074 00000 n 0000653463 00000 n 0000653506 00000 n 0000821975 00000 n 0000653565 00000 n 0000653606 00000 n 0000821876 00000 n 0000653665 00000 n 0000653706 00000 n 0000821792 00000 n 0000653761 00000 n 0000653798 00000 n 0000821693 00000 n 0000653862 00000 n 0000653908 00000 n 0000821553 00000 n 0000653952 00000 n 0000653978 00000 n 0000821469 00000 n 0000654023 00000 n 0000654050 00000 n 0000821370 00000 n 0000654098 00000 n 0000654128 00000 n 0000821271 00000 n 0000654188 00000 n 0000654230 00000 n 0000821172 00000 n 0000654300 00000 n 0000654352 00000 n 0000821073 00000 n 0000654405 00000 n 0000654440 00000 n 0000820974 00000 n 0000654504 00000 n 0000654550 00000 n 0000820875 00000 n 0000654607 00000 n 0000654646 00000 n 0000820776 00000 n 0000654690 00000 n 0000654716 00000 n 0000820692 00000 n 0000654761 00000 n 0000654788 00000 n 0000820552 00000 n 0000654834 00000 n 0000654862 00000 n 0000820483 00000 n 0000654925 00000 n 0000654970 00000 n 0000820384 00000 n 0000655015 00000 n 0000655050 00000 n 0000820285 00000 n 0000655100 00000 n 0000655132 00000 n 0000820186 00000 n 0000655177 00000 n 0000655204 00000 n 0000820087 00000 n 0000655249 00000 n 0000655276 00000 n 0000819988 00000 n 0000655325 00000 n 0000655356 00000 n 0000819848 00000 n 0000655400 00000 n 0000655426 00000 n 0000819764 00000 n 0000655477 00000 n 0000655510 00000 n 0000819665 00000 n 0000655563 00000 n 0000655598 00000 n 0000819566 00000 n 0000655650 00000 n 0000655684 00000 n 0000819467 00000 n 0000655750 00000 n 0000655798 00000 n 0000819383 00000 n 0000655847 00000 n 0000655878 00000 n 0000819284 00000 n 0000655927 00000 n 0000655958 00000 n 0000819144 00000 n 0000656004 00000 n 0000656032 00000 n 0000819060 00000 n 0000656089 00000 n 0000656128 00000 n 0000818976 00000 n 0000656186 00000 n 0000656227 00000 n 0000818877 00000 n 0000656276 00000 n 0000656307 00000 n 0000818778 00000 n 0000656356 00000 n 0000656387 00000 n 0000818679 00000 n 0000656435 00000 n 0000656465 00000 n 0000818580 00000 n 0000656512 00000 n 0000656541 00000 n 0000818481 00000 n 0000656586 00000 n 0000656613 00000 n 0000818382 00000 n 0000656660 00000 n 0000656689 00000 n 0000818283 00000 n 0000656735 00000 n 0000656763 00000 n 0000818184 00000 n 0000656806 00000 n 0000656831 00000 n 0000818085 00000 n 0000656883 00000 n 0000656917 00000 n 0000817986 00000 n 0000656966 00000 n 0000656997 00000 n 0000817887 00000 n 0000657040 00000 n 0000657065 00000 n 0000817803 00000 n 0000657111 00000 n 0000657139 00000 n 0000817663 00000 n 0000657210 00000 n 0000657258 00000 n 0000817537 00000 n 0000657312 00000 n 0000657348 00000 n 0000817453 00000 n 0000657404 00000 n 0000657442 00000 n 0000817354 00000 n 0000657501 00000 n 0000657542 00000 n 0000817255 00000 n 0000657609 00000 n 0000657658 00000 n 0000817156 00000 n 0000657707 00000 n 0000657738 00000 n 0000817057 00000 n 0000657792 00000 n 0000657828 00000 n 0000816958 00000 n 0000657883 00000 n 0000657920 00000 n 0000816859 00000 n 0000657985 00000 n 0000658032 00000 n 0000816760 00000 n 0000658098 00000 n 0000658146 00000 n 0000816661 00000 n 0000658197 00000 n 0000658230 00000 n 0000816562 00000 n 0000658282 00000 n 0000658316 00000 n 0000816463 00000 n 0000658374 00000 n 0000658414 00000 n 0000816364 00000 n 0000658473 00000 n 0000658517 00000 n 0000816265 00000 n 0000658573 00000 n 0000658614 00000 n 0000816166 00000 n 0000658670 00000 n 0000658708 00000 n 0000816067 00000 n 0000658768 00000 n 0000658810 00000 n 0000815968 00000 n 0000658863 00000 n 0000658898 00000 n 0000815869 00000 n 0000658950 00000 n 0000658984 00000 n 0000815785 00000 n 0000659039 00000 n 0000659076 00000 n 0000815645 00000 n 0000659135 00000 n 0000659177 00000 n 0000815561 00000 n 0000659221 00000 n 0000659247 00000 n 0000815462 00000 n 0000659294 00000 n 0000659327 00000 n 0000815378 00000 n 0000659376 00000 n 0000659407 00000 n 0000815279 00000 n 0000659451 00000 n 0000659477 00000 n 0000815195 00000 n 0000659534 00000 n 0000659573 00000 n 0000815096 00000 n 0000659629 00000 n 0000659667 00000 n 0000814956 00000 n 0000659721 00000 n 0000659757 00000 n 0000814872 00000 n 0000659821 00000 n 0000659867 00000 n 0000814788 00000 n 0000659924 00000 n 0000659963 00000 n 0000814647 00000 n 0000660028 00000 n 0000660076 00000 n 0000814563 00000 n 0000660127 00000 n 0000660160 00000 n 0000814464 00000 n 0000660208 00000 n 0000660238 00000 n 0000814365 00000 n 0000660284 00000 n 0000660312 00000 n 0000814266 00000 n 0000660358 00000 n 0000660386 00000 n 0000814167 00000 n 0000660432 00000 n 0000660460 00000 n 0000814068 00000 n 0000660507 00000 n 0000660536 00000 n 0000813969 00000 n 0000660585 00000 n 0000660616 00000 n 0000813870 00000 n 0000660663 00000 n 0000660692 00000 n 0000813771 00000 n 0000660741 00000 n 0000660784 00000 n 0000813687 00000 n 0000660835 00000 n 0000660877 00000 n 0000813588 00000 n 0000660930 00000 n 0000660965 00000 n 0000813489 00000 n 0000661017 00000 n 0000661051 00000 n 0000813405 00000 n 0000661099 00000 n 0000661129 00000 n 0000661155 00000 n 0000661815 00000 n 0000661841 00000 n 0000662335 00000 n 0000662935 00000 n 0000662961 00000 n 0000662987 00000 n 0000663601 00000 n 0000663641 00000 n 0000663985 00000 n 0000664655 00000 n 0000665051 00000 n 0000665447 00000 n 0000666079 00000 n 0000666692 00000 n 0000667337 00000 n 0000667979 00000 n 0000675464 00000 n 0000675774 00000 n 0000687796 00000 n 0000688208 00000 n 0000692097 00000 n 0000692355 00000 n 0000693980 00000 n 0000694212 00000 n 0000695999 00000 n 0000696223 00000 n 0000714103 00000 n 0000714706 00000 n 0000716393 00000 n 0000716615 00000 n 0000730185 00000 n 0000730647 00000 n 0000738053 00000 n 0000738346 00000 n 0000748031 00000 n 0000748431 00000 n 0000750384 00000 n 0000750676 00000 n 0000764425 00000 n 0000764832 00000 n 0000766460 00000 n 0000766688 00000 n 0000782734 00000 n 0000783351 00000 n 0000787247 00000 n 0000787513 00000 n 0000802990 00000 n 0000803624 00000 n 0000805491 00000 n 0000812486 00000 n 0000812602 00000 n 0000812722 00000 n 0000812842 00000 n 0000812962 00000 n 0000813088 00000 n 0000813214 00000 n 0000813324 00000 n 0000845842 00000 n 0000845979 00000 n 0000846112 00000 n 0000846251 00000 n 0000846388 00000 n 0000846527 00000 n 0000846664 00000 n 0000846803 00000 n 0000846939 00000 n 0000847077 00000 n 0000847222 00000 n 0000847364 00000 n 0000847509 00000 n 0000847652 00000 n 0000847797 00000 n 0000847940 00000 n 0000848085 00000 n 0000848228 00000 n 0000848373 00000 n 0000848515 00000 n 0000848654 00000 n 0000848796 00000 n 0000848927 00000 n 0000849056 00000 n 0000849187 00000 n 0000849316 00000 n 0000849447 00000 n 0000849576 00000 n 0000849707 00000 n 0000849835 00000 n 0000849963 00000 n 0000850094 00000 n 0000850223 00000 n 0000850354 00000 n 0000850483 00000 n 0000850614 00000 n 0000850798 00000 n 0000851063 00000 n 0000851298 00000 n 0000851547 00000 n 0000851852 00000 n 0000852151 00000 n 0000852414 00000 n 0000852647 00000 n 0000852923 00000 n 0000853186 00000 n 0000853439 00000 n 0000853739 00000 n 0000853986 00000 n 0000854223 00000 n 0000854471 00000 n 0000854694 00000 n 0000854925 00000 n 0000855181 00000 n 0000855421 00000 n 0000855648 00000 n 0000855841 00000 n 0000856055 00000 n 0000856298 00000 n 0000856577 00000 n 0000856826 00000 n 0000857068 00000 n 0000857297 00000 n 0000857533 00000 n 0000857787 00000 n 0000858034 00000 n 0000858224 00000 n 0000858436 00000 n 0000858684 00000 n 0000858896 00000 n 0000859163 00000 n 0000859386 00000 n 0000859578 00000 n 0000859767 00000 n 0000859976 00000 n 0000860216 00000 n 0000860399 00000 n 0000860599 00000 n 0000860787 00000 n 0000861030 00000 n 0000861218 00000 n 0000861444 00000 n 0000861632 00000 n 0000861818 00000 n 0000862022 00000 n 0000862224 00000 n 0000862414 00000 n 0000862607 00000 n 0000862799 00000 n 0000862999 00000 n 0000863192 00000 n 0000863380 00000 n 0000863576 00000 n 0000863764 00000 n 0000863954 00000 n 0000864114 00000 n 0000864221 00000 n 0000864329 00000 n 0000864437 00000 n 0000864543 00000 n 0000864648 00000 n 0000864766 00000 n 0000864905 00000 n 0000865039 00000 n 0000865178 00000 n 0000865312 00000 n 0000865430 00000 n 0000865544 00000 n 0000865662 00000 n 0000865790 00000 n 0000865911 00000 n 0000866031 00000 n 0000866149 00000 n 0000866277 00000 n 0000866386 00000 n 0000866478 00000 n 0000866518 00000 n 0000866631 00000 n trailer << /Size 3547 /Root 3545 0 R /Info 3546 0 R /ID [<17B5A925448150F0E8B05AC45347653D> <17B5A925448150F0E8B05AC45347653D>] >> startxref 866904 %%EOF cfengine-2.2.10/doc/texinfo.tex0000644000175000001440000066463510202127306013247 00000000000000% texinfo.tex -- TeX macros to handle Texinfo files. % % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % \def\texinfoversion{2004-04-07.08} % % Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995, % 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software % Foundation, Inc. % % This texinfo.tex file 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, or (at % your option) any later version. % % This texinfo.tex file 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 texinfo.tex file; see the file COPYING. If not, write % to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, % Boston, MA 02111-1307, USA. % % As a special exception, when this file is read by TeX when processing % a Texinfo source document, you may use the result without % restriction. (This has been our intent since Texinfo was invented.) % % Please try the latest version of texinfo.tex before submitting bug % reports; you can get the latest version from: % http://www.gnu.org/software/texinfo/ (the Texinfo home page), or % ftp://tug.org/tex/texinfo.tex % (and all CTAN mirrors, see http://www.ctan.org). % The texinfo.tex in any given distribution could well be out % of date, so if that's what you're using, please check. % % Send bug reports to bug-texinfo@gnu.org. Please include including a % complete document in each bug report with which we can reproduce the % problem. Patches are, of course, greatly appreciated. % % To process a Texinfo manual with TeX, it's most reliable to use the % texi2dvi shell script that comes with the distribution. For a simple % manual foo.texi, however, you can get away with this: % tex foo.texi % texindex foo.?? % tex foo.texi % tex foo.texi % dvips foo.dvi -o # or whatever; this makes foo.ps. % The extra TeX runs get the cross-reference information correct. % Sometimes one run after texindex suffices, and sometimes you need more % than two; texi2dvi does it as many times as necessary. % % It is possible to adapt texinfo.tex for other languages, to some % extent. You can get the existing language-specific files from the % full Texinfo distribution. % % The GNU Texinfo home page is http://www.gnu.org/software/texinfo. \message{Loading texinfo [version \texinfoversion]:} % If in a .fmt file, print the version number % and turn on active characters that we couldn't do earlier because % they might have appeared in the input file name. \everyjob{\message{[Texinfo version \texinfoversion]}% \catcode`+=\active \catcode`\_=\active} \message{Basics,} \chardef\other=12 % We never want plain's \outer definition of \+ in Texinfo. % For @tex, we can use \tabalign. \let\+ = \relax % Save some plain tex macros whose names we will redefine. \let\ptexb=\b \let\ptexbullet=\bullet \let\ptexc=\c \let\ptexcomma=\, \let\ptexdot=\. \let\ptexdots=\dots \let\ptexend=\end \let\ptexequiv=\equiv \let\ptexexclam=\! \let\ptexfootnote=\footnote \let\ptexgtr=> \let\ptexhat=^ \let\ptexi=\i \let\ptexindent=\indent \let\ptexnoindent=\noindent \let\ptexinsert=\insert \let\ptexlbrace=\{ \let\ptexless=< \let\ptexplus=+ \let\ptexrbrace=\} \let\ptexslash=\/ \let\ptexstar=\* \let\ptext=\t % If this character appears in an error message or help string, it % starts a new line in the output. \newlinechar = `^^J % Use TeX 3.0's \inputlineno to get the line number, for better error % messages, but if we're using an old version of TeX, don't do anything. % \ifx\inputlineno\thisisundefined \let\linenumber = \empty % Pre-3.0. \else \def\linenumber{l.\the\inputlineno:\space} \fi % Set up fixed words for English if not already set. \ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi \ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi \ifx\putwordfile\undefined \gdef\putwordfile{file}\fi \ifx\putwordin\undefined \gdef\putwordin{in}\fi \ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi \ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi \ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi \ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi \ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi \ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi \ifx\putwordof\undefined \gdef\putwordof{of}\fi \ifx\putwordon\undefined \gdef\putwordon{on}\fi \ifx\putwordpage\undefined \gdef\putwordpage{page}\fi \ifx\putwordsection\undefined \gdef\putwordsection{section}\fi \ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi \ifx\putwordsee\undefined \gdef\putwordsee{see}\fi \ifx\putwordSee\undefined \gdef\putwordSee{See}\fi \ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi \ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi % \ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi \ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi \ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi \ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi \ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi \ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi \ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi \ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi \ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi \ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi \ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi \ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi % \ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi \ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi \ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi \ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi \ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi % In some macros, we cannot use the `\? notation---the left quote is % in some cases the escape char. \chardef\colonChar = `\: \chardef\commaChar = `\, \chardef\dotChar = `\. \chardef\exclamChar= `\! \chardef\questChar = `\? \chardef\semiChar = `\; \chardef\underChar = `\_ \chardef\spaceChar = `\ % \chardef\spacecat = 10 \def\spaceisspace{\catcode\spaceChar=\spacecat} % Ignore a token. % \def\gobble#1{} % The following is used inside several \edef's. \def\makecsname#1{\expandafter\noexpand\csname#1\endcsname} % Hyphenation fixes. \hyphenation{ Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script ap-pen-dix bit-map bit-maps data-base data-bases eshell fall-ing half-way long-est man-u-script man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces spell-ing spell-ings stand-alone strong-est time-stamp time-stamps which-ever white-space wide-spread wrap-around } % Margin to add to right of even pages, to left of odd pages. \newdimen\bindingoffset \newdimen\normaloffset \newdimen\pagewidth \newdimen\pageheight % For a final copy, take out the rectangles % that mark overfull boxes (in case you have decided % that the text looks ok even though it passes the margin). % \def\finalout{\overfullrule=0pt} % @| inserts a changebar to the left of the current line. It should % surround any changed text. This approach does *not* work if the % change spans more than two lines of output. To handle that, we would % have adopt a much more difficult approach (putting marks into the main % vertical list for the beginning and end of each change). % \def\|{% % \vadjust can only be used in horizontal mode. \leavevmode % % Append this vertical mode material after the current line in the output. \vadjust{% % We want to insert a rule with the height and depth of the current % leading; that is exactly what \strutbox is supposed to record. \vskip-\baselineskip % % \vadjust-items are inserted at the left edge of the type. So % the \llap here moves out into the left-hand margin. \llap{% % % For a thicker or thinner bar, change the `1pt'. \vrule height\baselineskip width1pt % % This is the space between the bar and the text. \hskip 12pt }% }% } % Sometimes it is convenient to have everything in the transcript file % and nothing on the terminal. We don't just call \tracingall here, % since that produces some useless output on the terminal. We also make % some effort to order the tracing commands to reduce output in the log % file; cf. trace.sty in LaTeX. % \def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}% \def\loggingall{% \tracingstats2 \tracingpages1 \tracinglostchars2 % 2 gives us more in etex \tracingparagraphs1 \tracingoutput1 \tracingmacros2 \tracingrestores1 \showboxbreadth\maxdimen \showboxdepth\maxdimen \ifx\eTeXversion\undefined\else % etex gives us more logging \tracingscantokens1 \tracingifs1 \tracinggroups1 \tracingnesting2 \tracingassigns1 \fi \tracingcommands3 % 3 gives us more in etex \errorcontextlines16 }% % add check for \lastpenalty to plain's definitions. If the last thing % we did was a \nobreak, we don't want to insert more space. % \def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount \removelastskip\penalty-50\smallskip\fi\fi} \def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount \removelastskip\penalty-100\medskip\fi\fi} \def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount \removelastskip\penalty-200\bigskip\fi\fi} % For @cropmarks command. % Do @cropmarks to get crop marks. % \newif\ifcropmarks \let\cropmarks = \cropmarkstrue % % Dimensions to add cropmarks at corners. % Added by P. A. MacKay, 12 Nov. 1986 % \newdimen\outerhsize \newdimen\outervsize % set by the paper size routines \newdimen\cornerlong \cornerlong=1pc \newdimen\cornerthick \cornerthick=.3pt \newdimen\topandbottommargin \topandbottommargin=.75in % Main output routine. \chardef\PAGE = 255 \output = {\onepageout{\pagecontents\PAGE}} \newbox\headlinebox \newbox\footlinebox % \onepageout takes a vbox as an argument. Note that \pagecontents % does insertions, but you have to call it yourself. \def\onepageout#1{% \ifcropmarks \hoffset=0pt \else \hoffset=\normaloffset \fi % \ifodd\pageno \advance\hoffset by \bindingoffset \else \advance\hoffset by -\bindingoffset\fi % % Do this outside of the \shipout so @code etc. will be expanded in % the headline as they should be, not taken literally (outputting ''code). \setbox\headlinebox = \vbox{\let\hsize=\pagewidth \makeheadline}% \setbox\footlinebox = \vbox{\let\hsize=\pagewidth \makefootline}% % {% % Have to do this stuff outside the \shipout because we want it to % take effect in \write's, yet the group defined by the \vbox ends % before the \shipout runs. % \escapechar = `\\ % use backslash in output files. \indexdummies % don't expand commands in the output. \normalturnoffactive % \ in index entries must not stay \, e.g., if % the page break happens to be in the middle of an example. \shipout\vbox{% % Do this early so pdf references go to the beginning of the page. \ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi % \ifcropmarks \vbox to \outervsize\bgroup \hsize = \outerhsize \vskip-\topandbottommargin \vtop to0pt{% \line{\ewtop\hfil\ewtop}% \nointerlineskip \line{% \vbox{\moveleft\cornerthick\nstop}% \hfill \vbox{\moveright\cornerthick\nstop}% }% \vss}% \vskip\topandbottommargin \line\bgroup \hfil % center the page within the outer (page) hsize. \ifodd\pageno\hskip\bindingoffset\fi \vbox\bgroup \fi % \unvbox\headlinebox \pagebody{#1}% \ifdim\ht\footlinebox > 0pt % Only leave this space if the footline is nonempty. % (We lessened \vsize for it in \oddfootingxxx.) % The \baselineskip=24pt in plain's \makefootline has no effect. \vskip 2\baselineskip \unvbox\footlinebox \fi % \ifcropmarks \egroup % end of \vbox\bgroup \hfil\egroup % end of (centering) \line\bgroup \vskip\topandbottommargin plus1fill minus1fill \boxmaxdepth = \cornerthick \vbox to0pt{\vss \line{% \vbox{\moveleft\cornerthick\nsbot}% \hfill \vbox{\moveright\cornerthick\nsbot}% }% \nointerlineskip \line{\ewbot\hfil\ewbot}% }% \egroup % \vbox from first cropmarks clause \fi }% end of \shipout\vbox }% end of group with \normalturnoffactive \advancepageno \ifnum\outputpenalty>-20000 \else\dosupereject\fi } \newinsert\margin \dimen\margin=\maxdimen \def\pagebody#1{\vbox to\pageheight{\boxmaxdepth=\maxdepth #1}} {\catcode`\@ =11 \gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi % marginal hacks, juha@viisa.uucp (Juha Takala) \ifvoid\margin\else % marginal info is present \rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi \dimen@=\dp#1 \unvbox#1 \ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi \ifr@ggedbottom \kern-\dimen@ \vfil \fi} } % Here are the rules for the cropmarks. Note that they are % offset so that the space between them is truly \outerhsize or \outervsize % (P. A. MacKay, 12 November, 1986) % \def\ewtop{\vrule height\cornerthick depth0pt width\cornerlong} \def\nstop{\vbox {\hrule height\cornerthick depth\cornerlong width\cornerthick}} \def\ewbot{\vrule height0pt depth\cornerthick width\cornerlong} \def\nsbot{\vbox {\hrule height\cornerlong depth\cornerthick width\cornerthick}} % Parse an argument, then pass it to #1. The argument is the rest of % the input line (except we remove a trailing comment). #1 should be a % macro which expects an ordinary undelimited TeX argument. % \def\parsearg{\parseargusing{}} \def\parseargusing#1#2{% \def\next{#2}% \begingroup \obeylines \spaceisspace #1% \parseargline\empty% Insert the \empty token, see \finishparsearg below. } {\obeylines % \gdef\parseargline#1^^M{% \endgroup % End of the group started in \parsearg. \argremovecomment #1\comment\ArgTerm% }% } % First remove any @comment, then any @c comment. \def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm} \def\argremovec#1\c#2\ArgTerm{\argcheckspaces#1\^^M\ArgTerm} % Each occurence of `\^^M' or `\^^M' is replaced by a single space. % % \argremovec might leave us with trailing space, e.g., % @end itemize @c foo % This space token undergoes the same procedure and is eventually removed % by \finishparsearg. % \def\argcheckspaces#1\^^M{\argcheckspacesX#1\^^M \^^M} \def\argcheckspacesX#1 \^^M{\argcheckspacesY#1\^^M} \def\argcheckspacesY#1\^^M#2\^^M#3\ArgTerm{% \def\temp{#3}% \ifx\temp\empty % We cannot use \next here, as it holds the macro to run; % thus we reuse \temp. \let\temp\finishparsearg \else \let\temp\argcheckspaces \fi % Put the space token in: \temp#1 #3\ArgTerm } % If a _delimited_ argument is enclosed in braces, they get stripped; so % to get _exactly_ the rest of the line, we had to prevent such situation. % We prepended an \empty token at the very beginning and we expand it now, % just before passing the control to \next. % (Similarily, we have to think about #3 of \argcheckspacesY above: it is % either the null string, or it ends with \^^M---thus there is no danger % that a pair of braces would be stripped. % % But first, we have to remove the trailing space token. % \def\finishparsearg#1 \ArgTerm{\expandafter\next\expandafter{#1}} % \parseargdef\foo{...} % is roughly equivalent to % \def\foo{\parsearg\Xfoo} % \def\Xfoo#1{...} % % Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my % favourite TeX trick. --kasal, 16nov03 \def\parseargdef#1{% \expandafter \doparseargdef \csname\string#1\endcsname #1% } \def\doparseargdef#1#2{% \def#2{\parsearg#1}% \def#1##1% } % Several utility definitions with active space: { \obeyspaces \gdef\obeyedspace{ } % Make each space character in the input produce a normal interword % space in the output. Don't allow a line break at this space, as this % is used only in environments like @example, where each line of input % should produce a line of output anyway. % \gdef\sepspaces{\obeyspaces\let =\tie} % If an index command is used in an @example environment, any spaces % therein should become regular spaces in the raw index file, not the % expansion of \tie (\leavevmode \penalty \@M \ ). \gdef\unsepspaces{\let =\space} } \def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next} % Define the framework for environments in texinfo.tex. It's used like this: % % \envdef\foo{...} % \def\Efoo{...} % % It's the responsibility of \envdef to insert \begingroup before the % actual body; @end closes the group after calling \Efoo. \envdef also % defines \thisenv, so the current environment is known; @end checks % whether the environment name matches. The \checkenv macro can also be % used to check whether the current environment is the one expected. % % Non-false conditionals (@iftex, @ifset) don't fit into this, so they % are not treated as enviroments; they don't open a group. (The % implementation of @end takes care not to call \endgroup in this % special case.) % At runtime, environments start with this: \def\startenvironment#1{\begingroup\def\thisenv{#1}} % initialize \let\thisenv\empty % ... but they get defined via ``\envdef\foo{...}'': \long\def\envdef#1#2{\def#1{\startenvironment#1#2}} \def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}} % Check whether we're in the right environment: \def\checkenv#1{% \def\temp{#1}% \ifx\thisenv\temp \else \badenverr \fi } % Evironment mismatch, #1 expected: \def\badenverr{% \errhelp = \EMsimple \errmessage{This command can appear only \inenvironment\temp, not \inenvironment\thisenv}% } \def\inenvironment#1{% \ifx#1\empty out of any environment% \else in environment \expandafter\string#1% \fi } % @end foo executes the definition of \Efoo. % But first, it executes a specialized version of \checkenv % \parseargdef\end{% \if 1\csname iscond.#1\endcsname \else % The general wording of \badenverr may not be ideal, but... --kasal, 06nov03 \expandafter\checkenv\csname#1\endcsname \csname E#1\endcsname \endgroup \fi } \newhelp\EMsimple{Press RETURN to continue.} %% Simple single-character @ commands % @@ prints an @ % Kludge this until the fonts are right (grr). \def\@{{\tt\char64}} % This is turned off because it was never documented % and you can use @w{...} around a quote to suppress ligatures. %% Define @` and @' to be the same as ` and ' %% but suppressing ligatures. %\def\`{{`}} %\def\'{{'}} % Used to generate quoted braces. \def\mylbrace {{\tt\char123}} \def\myrbrace {{\tt\char125}} \let\{=\mylbrace \let\}=\myrbrace \begingroup % Definitions to produce \{ and \} commands for indices, % and @{ and @} for the aux file. \catcode`\{ = \other \catcode`\} = \other \catcode`\[ = 1 \catcode`\] = 2 \catcode`\! = 0 \catcode`\\ = \other !gdef!lbracecmd[\{]% !gdef!rbracecmd[\}]% !gdef!lbraceatcmd[@{]% !gdef!rbraceatcmd[@}]% !endgroup % @comma{} to avoid , parsing problems. \let\comma = , % Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent % Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H. \let\, = \c \let\dotaccent = \. \def\ringaccent#1{{\accent23 #1}} \let\tieaccent = \t \let\ubaraccent = \b \let\udotaccent = \d % Other special characters: @questiondown @exclamdown @ordf @ordm % Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss. \def\questiondown{?`} \def\exclamdown{!`} \def\ordf{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{a}}} \def\ordm{\leavevmode\raise1ex\hbox{\selectfonts\lllsize \underbar{o}}} % Dotless i and dotless j, used for accents. \def\imacro{i} \def\jmacro{j} \def\dotless#1{% \def\temp{#1}% \ifx\temp\imacro \ptexi \else\ifx\temp\jmacro \j \else \errmessage{@dotless can be used only with i or j}% \fi\fi } % The \TeX{} logo, as in plain, but resetting the spacing so that a % period following counts as ending a sentence. (Idea found in latex.) % \edef\TeX{\TeX \spacefactor=3000 } % @LaTeX{} logo. Not quite the same results as the definition in % latex.ltx, since we use a different font for the raised A; it's most % convenient for us to use an explicitly smaller font, rather than using % the \scriptstyle font (since we don't reset \scriptstyle and % \scriptscriptstyle). % \def\LaTeX{% L\kern-.36em {\setbox0=\hbox{T}% \vbox to \ht0{\hbox{\selectfonts\lllsize A}\vss}}% \kern-.15em \TeX } % Be sure we're in horizontal mode when doing a tie, since we make space % equivalent to this in @example-like environments. Otherwise, a space % at the beginning of a line will start with \penalty -- and % since \penalty is valid in vertical mode, we'd end up putting the % penalty on the vertical list instead of in the new paragraph. {\catcode`@ = 11 % Avoid using \@M directly, because that causes trouble % if the definition is written into an index file. \global\let\tiepenalty = \@M \gdef\tie{\leavevmode\penalty\tiepenalty\ } } % @: forces normal size whitespace following. \def\:{\spacefactor=1000 } % @* forces a line break. \def\*{\hfil\break\hbox{}\ignorespaces} % @/ allows a line break. \let\/=\allowbreak % @. is an end-of-sentence period. \def\.{.\spacefactor=3000 } % @! is an end-of-sentence bang. \def\!{!\spacefactor=3000 } % @? is an end-of-sentence query. \def\?{?\spacefactor=3000 } % @w prevents a word break. Without the \leavevmode, @w at the % beginning of a paragraph, when TeX is still in vertical mode, would % produce a whole line of output instead of starting the paragraph. \def\w#1{\leavevmode\hbox{#1}} % @group ... @end group forces ... to be all on one page, by enclosing % it in a TeX vbox. We use \vtop instead of \vbox to construct the box % to keep its height that of a normal line. According to the rules for % \topskip (p.114 of the TeXbook), the glue inserted is % max (\topskip - \ht (first item), 0). If that height is large, % therefore, no glue is inserted, and the space between the headline and % the text is small, which looks bad. % % Another complication is that the group might be very large. This can % cause the glue on the previous page to be unduly stretched, because it % does not have much material. In this case, it's better to add an % explicit \vfill so that the extra space is at the bottom. The % threshold for doing this is if the group is more than \vfilllimit % percent of a page (\vfilllimit can be changed inside of @tex). % \newbox\groupbox \def\vfilllimit{0.7} % \envdef\group{% \ifnum\catcode`\^^M=\active \else \errhelp = \groupinvalidhelp \errmessage{@group invalid in context where filling is enabled}% \fi \startsavinginserts % \setbox\groupbox = \vtop\bgroup % Do @comment since we are called inside an environment such as % @example, where each end-of-line in the input causes an % end-of-line in the output. We don't want the end-of-line after % the `@group' to put extra space in the output. Since @group % should appear on a line by itself (according to the Texinfo % manual), we don't worry about eating any user text. \comment } % % The \vtop produces a box with normal height and large depth; thus, TeX puts % \baselineskip glue before it, and (when the next line of text is done) % \lineskip glue after it. Thus, space below is not quite equal to space % above. But it's pretty close. \def\Egroup{% % To get correct interline space between the last line of the group % and the first line afterwards, we have to propagate \prevdepth. \endgraf % Not \par, as it may have been set to \lisppar. \global\dimen1 = \prevdepth \egroup % End the \vtop. % \dimen0 is the vertical size of the group's box. \dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox % \dimen2 is how much space is left on the page (more or less). \dimen2 = \pageheight \advance\dimen2 by -\pagetotal % if the group doesn't fit on the current page, and it's a big big % group, force a page break. \ifdim \dimen0 > \dimen2 \ifdim \pagetotal < \vfilllimit\pageheight \page \fi \fi \box\groupbox \prevdepth = \dimen1 \checkinserts } % % TeX puts in an \escapechar (i.e., `@') at the beginning of the help % message, so this ends up printing `@group can only ...'. % \newhelp\groupinvalidhelp{% group can only be used in environments such as @example,^^J% where each line of input produces a line of output.} % @need space-in-mils % forces a page break if there is not space-in-mils remaining. \newdimen\mil \mil=0.001in % Old definition--didn't work. %\parseargdef\need{\par % %% This method tries to make TeX break the page naturally %% if the depth of the box does not fit. %{\baselineskip=0pt% %\vtop to #1\mil{\vfil}\kern -#1\mil\nobreak %\prevdepth=-1000pt %}} \parseargdef\need{% % Ensure vertical mode, so we don't make a big box in the middle of a % paragraph. \par % % If the @need value is less than one line space, it's useless. \dimen0 = #1\mil \dimen2 = \ht\strutbox \advance\dimen2 by \dp\strutbox \ifdim\dimen0 > \dimen2 % % Do a \strut just to make the height of this box be normal, so the % normal leading is inserted relative to the preceding line. % And a page break here is fine. \vtop to #1\mil{\strut\vfil}% % % TeX does not even consider page breaks if a penalty added to the % main vertical list is 10000 or more. But in order to see if the % empty box we just added fits on the page, we must make it consider % page breaks. On the other hand, we don't want to actually break the % page after the empty box. So we use a penalty of 9999. % % There is an extremely small chance that TeX will actually break the % page at this \penalty, if there are no other feasible breakpoints in % sight. (If the user is using lots of big @group commands, which % almost-but-not-quite fill up a page, TeX will have a hard time doing % good page breaking, for example.) However, I could not construct an % example where a page broke at this \penalty; if it happens in a real % document, then we can reconsider our strategy. \penalty9999 % % Back up by the size of the box, whether we did a page break or not. \kern -#1\mil % % Do not allow a page break right after this kern. \nobreak \fi } % @br forces paragraph break (and is undocumented). \let\br = \par % @page forces the start of a new page. % \def\page{\par\vfill\supereject} % @exdent text.... % outputs text on separate line in roman font, starting at standard page margin % This records the amount of indent in the innermost environment. % That's how much \exdent should take out. \newskip\exdentamount % This defn is used inside fill environments such as @defun. \parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break} % This defn is used inside nofill environments such as @example. \parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount \leftline{\hskip\leftskip{\rm#1}}}} % @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current % paragraph. For more general purposes, use the \margin insertion % class. WHICH is `l' or `r'. % \newskip\inmarginspacing \inmarginspacing=1cm \def\strutdepth{\dp\strutbox} % \def\doinmargin#1#2{\strut\vadjust{% \nobreak \kern-\strutdepth \vtop to \strutdepth{% \baselineskip=\strutdepth \vss % if you have multiple lines of stuff to put here, you'll need to % make the vbox yourself of the appropriate size. \ifx#1l% \llap{\ignorespaces #2\hskip\inmarginspacing}% \else \rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}% \fi \null }% }} \def\inleftmargin{\doinmargin l} \def\inrightmargin{\doinmargin r} % % @inmargin{TEXT [, RIGHT-TEXT]} % (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right; % else use TEXT for both). % \def\inmargin#1{\parseinmargin #1,,\finish} \def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing. \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0 > 0pt \def\lefttext{#1}% have both texts \def\righttext{#2}% \else \def\lefttext{#1}% have only one text \def\righttext{#1}% \fi % \ifodd\pageno \def\temp{\inrightmargin\righttext}% odd page -> outside is right margin \else \def\temp{\inleftmargin\lefttext}% \fi \temp } % @include file insert text of that file as input. % \def\include{\parseargusing\filenamecatcodes\includezzz} \def\includezzz#1{% \pushthisfilestack \def\thisfile{#1}% {% \makevalueexpandable \def\temp{\input #1 }% \expandafter }\temp \popthisfilestack } \def\filenamecatcodes{% \catcode`\\=\other \catcode`~=\other \catcode`^=\other \catcode`_=\other \catcode`|=\other \catcode`<=\other \catcode`>=\other \catcode`+=\other \catcode`-=\other } \def\pushthisfilestack{% \expandafter\pushthisfilestackX\popthisfilestack\StackTerm } \def\pushthisfilestackX{% \expandafter\pushthisfilestackY\thisfile\StackTerm } \def\pushthisfilestackY #1\StackTerm #2\StackTerm {% \gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}% } \def\popthisfilestack{\errthisfilestackempty} \def\errthisfilestackempty{\errmessage{Internal error: the stack of filenames is empty.}} \def\thisfile{} % @center line % outputs that line, centered. % \parseargdef\center{% \ifhmode \let\next\centerH \else \let\next\centerV \fi \next{\hfil \ignorespaces#1\unskip \hfil}% } \def\centerH#1{% {% \hfil\break \advance\hsize by -\leftskip \advance\hsize by -\rightskip \line{#1}% \break }% } \def\centerV#1{\line{\kern\leftskip #1\kern\rightskip}} % @sp n outputs n lines of vertical space \parseargdef\sp{\vskip #1\baselineskip} % @comment ...line which is ignored... % @c is the same as @comment % @ignore ... @end ignore is another way to write a comment \def\comment{\begingroup \catcode`\^^M=\other% \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other% \commentxxx} {\catcode`\^^M=\other \gdef\commentxxx#1^^M{\endgroup}} \let\c=\comment % @paragraphindent NCHARS % We'll use ems for NCHARS, close enough. % NCHARS can also be the word `asis' or `none'. % We cannot feasibly implement @paragraphindent asis, though. % \def\asisword{asis} % no translation, these are keywords \def\noneword{none} % \parseargdef\paragraphindent{% \def\temp{#1}% \ifx\temp\asisword \else \ifx\temp\noneword \defaultparindent = 0pt \else \defaultparindent = #1em \fi \fi \parindent = \defaultparindent } % @exampleindent NCHARS % We'll use ems for NCHARS like @paragraphindent. % It seems @exampleindent asis isn't necessary, but % I preserve it to make it similar to @paragraphindent. \parseargdef\exampleindent{% \def\temp{#1}% \ifx\temp\asisword \else \ifx\temp\noneword \lispnarrowing = 0pt \else \lispnarrowing = #1em \fi \fi } % @firstparagraphindent WORD % If WORD is `none', then suppress indentation of the first paragraph % after a section heading. If WORD is `insert', then do indent at such % paragraphs. % % The paragraph indentation is suppressed or not by calling % \suppressfirstparagraphindent, which the sectioning commands do. % We switch the definition of this back and forth according to WORD. % By default, we suppress indentation. % \def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent} \def\insertword{insert} % \parseargdef\firstparagraphindent{% \def\temp{#1}% \ifx\temp\noneword \let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent \else\ifx\temp\insertword \let\suppressfirstparagraphindent = \relax \else \errhelp = \EMsimple \errmessage{Unknown @firstparagraphindent option `\temp'}% \fi\fi } % Here is how we actually suppress indentation. Redefine \everypar to % \kern backwards by \parindent, and then reset itself to empty. % % We also make \indent itself not actually do anything until the next % paragraph. % \gdef\dosuppressfirstparagraphindent{% \gdef\indent{% \restorefirstparagraphindent \indent }% \gdef\noindent{% \restorefirstparagraphindent \noindent }% \global\everypar = {% \kern -\parindent \restorefirstparagraphindent }% } \gdef\restorefirstparagraphindent{% \global \let \indent = \ptexindent \global \let \noindent = \ptexnoindent \global \everypar = {}% } % @asis just yields its argument. Used with @table, for example. % \def\asis#1{#1} % @math outputs its argument in math mode. % % One complication: _ usually means subscripts, but it could also mean % an actual _ character, as in @math{@var{some_variable} + 1}. So make % _ active, and distinguish by seeing if the current family is \slfam, % which is what @var uses. { \catcode\underChar = \active \gdef\mathunderscore{% \catcode\underChar=\active \def_{\ifnum\fam=\slfam \_\else\sb\fi}% } } % Another complication: we want \\ (and @\) to output a \ character. % FYI, plain.tex uses \\ as a temporary control sequence (why?), but % this is not advertised and we don't care. Texinfo does not % otherwise define @\. % % The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\. \def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi} % \def\math{% \tex \mathunderscore \let\\ = \mathbackslash \mathactive $\finishmath } \def\finishmath#1{#1$\endgroup} % Close the group opened by \tex. % Some active characters (such as <) are spaced differently in math. % We have to reset their definitions in case the @math was an argument % to a command which sets the catcodes (such as @item or @section). % { \catcode`^ = \active \catcode`< = \active \catcode`> = \active \catcode`+ = \active \gdef\mathactive{% \let^ = \ptexhat \let< = \ptexless \let> = \ptexgtr \let+ = \ptexplus } } % @bullet and @minus need the same treatment as @math, just above. \def\bullet{$\ptexbullet$} \def\minus{$-$} % @dots{} outputs an ellipsis using the current font. % We do .5em per period so that it has the same spacing in a typewriter % font as three actual period characters. % \def\dots{% \leavevmode \hbox to 1.5em{% \hskip 0pt plus 0.25fil .\hfil.\hfil.% \hskip 0pt plus 0.5fil }% } % @enddots{} is an end-of-sentence ellipsis. % \def\enddots{% \dots \spacefactor=3000 } % @comma{} is so commas can be inserted into text without messing up % Texinfo's parsing. % \let\comma = , % @refill is a no-op. \let\refill=\relax % If working on a large document in chapters, it is convenient to % be able to disable indexing, cross-referencing, and contents, for test runs. % This is done with @novalidate (before @setfilename). % \newif\iflinks \linkstrue % by default we want the aux files. \let\novalidate = \linksfalse % @setfilename is done at the beginning of every texinfo file. % So open here the files we need to have open while reading the input. % This makes it possible to make a .fmt file for texinfo. \def\setfilename{% \fixbackslash % Turn off hack to swallow `\input texinfo'. \iflinks \tryauxfile % Open the new aux file. TeX will close it automatically at exit. \immediate\openout\auxfile=\jobname.aux \fi % \openindices needs to do some work in any case. \openindices \let\setfilename=\comment % Ignore extra @setfilename cmds. % % If texinfo.cnf is present on the system, read it. % Useful for site-wide @afourpaper, etc. \openin 1 texinfo.cnf \ifeof 1 \else \input texinfo.cnf \fi \closein 1 % \comment % Ignore the actual filename. } % Called from \setfilename. % \def\openindices{% \newindex{cp}% \newcodeindex{fn}% \newcodeindex{vr}% \newcodeindex{tp}% \newcodeindex{ky}% \newcodeindex{pg}% } % @bye. \outer\def\bye{\pagealignmacro\tracingstats=1\ptexend} \message{pdf,} % adobe `portable' document format \newcount\tempnum \newcount\lnkcount \newtoks\filename \newcount\filenamelength \newcount\pgn \newtoks\toksA \newtoks\toksB \newtoks\toksC \newtoks\toksD \newbox\boxA \newcount\countA \newif\ifpdf \newif\ifpdfmakepagedest % when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1 % can be set). So we test for \relax and 0 as well as \undefined, % borrowed from ifpdf.sty. \ifx\pdfoutput\undefined \else \ifx\pdfoutput\relax \else \ifcase\pdfoutput \else \pdftrue \fi \fi \fi % \ifpdf \input pdfcolor \pdfcatalog{/PageMode /UseOutlines}% \def\dopdfimage#1#2#3{% \def\imagewidth{#2}% \def\imageheight{#3}% % without \immediate, pdftex seg faults when the same image is % included twice. (Version 3.14159-pre-1.0-unofficial-20010704.) \ifnum\pdftexversion < 14 \immediate\pdfimage \else \immediate\pdfximage \fi \ifx\empty\imagewidth\else width \imagewidth \fi \ifx\empty\imageheight\else height \imageheight \fi \ifnum\pdftexversion<13 #1.pdf% \else {#1.pdf}% \fi \ifnum\pdftexversion < 14 \else \pdfrefximage \pdflastximage \fi} \def\pdfmkdest#1{{% % We have to set dummies so commands such as @code in a section title % aren't expanded. \atdummies \normalturnoffactive \pdfdest name{#1} xyz% }} \def\pdfmkpgn#1{#1} \let\linkcolor = \Blue % was Cyan, but that seems light? \def\endlink{\Black\pdfendlink} % Adding outlines to PDF; macros for calculating structure of outlines % come from Petr Olsak \def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0% \else \csname#1\endcsname \fi} \def\advancenumber#1{\tempnum=\expnumber{#1}\relax \advance\tempnum by 1 \expandafter\xdef\csname#1\endcsname{\the\tempnum}} % % #1 is the section text. #2 is the pdf expression for the number % of subentries (or empty, for subsubsections). #3 is the node % text, which might be empty if this toc entry had no % corresponding node. #4 is the page number. % \def\dopdfoutline#1#2#3#4{% % Generate a link to the node text if that exists; else, use the % page number. We could generate a destination for the section % text in the case where a section has no node, but it doesn't % seem worthwhile, since most documents are normally structured. \def\pdfoutlinedest{#3}% \ifx\pdfoutlinedest\empty \def\pdfoutlinedest{#4}\fi % \pdfoutline goto name{\pdfmkpgn{\pdfoutlinedest}}#2{#1}% } % \def\pdfmakeoutlines{% \begingroup % Thanh's hack / proper braces in bookmarks \edef\mylbrace{\iftrue \string{\else}\fi}\let\{=\mylbrace \edef\myrbrace{\iffalse{\else\string}\fi}\let\}=\myrbrace % % Read toc silently, to get counts of subentries for \pdfoutline. \def\numchapentry##1##2##3##4{% \def\thischapnum{##2}% \let\thissecnum\empty \let\thissubsecnum\empty }% \def\numsecentry##1##2##3##4{% \advancenumber{chap\thischapnum}% \def\thissecnum{##2}% \let\thissubsecnum\empty }% \def\numsubsecentry##1##2##3##4{% \advancenumber{sec\thissecnum}% \def\thissubsecnum{##2}% }% \def\numsubsubsecentry##1##2##3##4{% \advancenumber{subsec\thissubsecnum}% }% \let\thischapnum\empty \let\thissecnum\empty \let\thissubsecnum\empty % % use \def rather than \let here because we redefine \chapentry et % al. a second time, below. \def\appentry{\numchapentry}% \def\appsecentry{\numsecentry}% \def\appsubsecentry{\numsubsecentry}% \def\appsubsubsecentry{\numsubsubsecentry}% \def\unnchapentry{\numchapentry}% \def\unnsecentry{\numsecentry}% \def\unnsubsecentry{\numsubsecentry}% \def\unnsubsubsecentry{\numsubsubsecentry}% \input \jobname.toc % % Read toc second time, this time actually producing the outlines. % The `-' means take the \expnumber as the absolute number of % subentries, which we calculated on our first read of the .toc above. % % We use the node names as the destinations. \def\numchapentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}% \def\numsecentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}% \def\numsubsecentry##1##2##3##4{% \dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}% \def\numsubsubsecentry##1##2##3##4{% count is always zero \dopdfoutline{##1}{}{##3}{##4}}% % % PDF outlines are displayed using system fonts, instead of % document fonts. Therefore we cannot use special characters, % since the encoding is unknown. For example, the eogonek from % Latin 2 (0xea) gets translated to a | character. Info from % Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100. % % xx to do this right, we have to translate 8-bit characters to % their "best" equivalent, based on the @documentencoding. Right % now, I guess we'll just let the pdf reader have its way. \indexnofonts \turnoffactive \input \jobname.toc \endgroup } % \def\makelinks #1,{% \def\params{#1}\def\E{END}% \ifx\params\E \let\nextmakelinks=\relax \else \let\nextmakelinks=\makelinks \ifnum\lnkcount>0,\fi \picknum{#1}% \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{\the\pgn}}% \linkcolor #1% \advance\lnkcount by 1% \endlink \fi \nextmakelinks } \def\picknum#1{\expandafter\pn#1} \def\pn#1{% \def\p{#1}% \ifx\p\lbrace \let\nextpn=\ppn \else \let\nextpn=\ppnn \def\first{#1} \fi \nextpn } \def\ppn#1{\pgn=#1\gobble} \def\ppnn{\pgn=\first} \def\pdfmklnk#1{\lnkcount=0\makelinks #1,END,} \def\skipspaces#1{\def\PP{#1}\def\D{|}% \ifx\PP\D\let\nextsp\relax \else\let\nextsp\skipspaces \ifx\p\space\else\addtokens{\filename}{\PP}% \advance\filenamelength by 1 \fi \fi \nextsp} \def\getfilename#1{\filenamelength=0\expandafter\skipspaces#1|\relax} \ifnum\pdftexversion < 14 \let \startlink \pdfannotlink \else \let \startlink \pdfstartlink \fi \def\pdfurl#1{% \begingroup \normalturnoffactive\def\@{@}% \makevalueexpandable \leavevmode\Red \startlink attr{/Border [0 0 0]}% user{/Subtype /Link /A << /S /URI /URI (#1) >>}% \endgroup} \def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}} \def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks} \def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks} \def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}} \def\maketoks{% \expandafter\poptoks\the\toksA|ENDTOKS|\relax \ifx\first0\adn0 \else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3 \else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6 \else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9 \else \ifnum0=\countA\else\makelink\fi \ifx\first.\let\next=\done\else \let\next=\maketoks \addtokens{\toksB}{\the\toksD} \ifx\first,\addtokens{\toksB}{\space}\fi \fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \next} \def\makelink{\addtokens{\toksB}% {\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0} \def\pdflink#1{% \startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}} \linkcolor #1\endlink} \def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} \else \let\pdfmkdest = \gobble \let\pdfurl = \gobble \let\endlink = \relax \let\linkcolor = \relax \let\pdfmakeoutlines = \relax \fi % \ifx\pdfoutput \message{fonts,} % Change the current font style to #1, remembering it in \curfontstyle. % For now, we do not accumulate font styles: @b{@i{foo}} prints foo in % italics, not bold italics. % \def\setfontstyle#1{% \def\curfontstyle{#1}% not as a control sequence, because we are \edef'd. \csname ten#1\endcsname % change the current font } % Select #1 fonts with the current style. % \def\selectfonts#1{\csname #1fonts\endcsname \csname\curfontstyle\endcsname} \def\rm{\fam=0 \setfontstyle{rm}} \def\it{\fam=\itfam \setfontstyle{it}} \def\sl{\fam=\slfam \setfontstyle{sl}} \def\bf{\fam=\bffam \setfontstyle{bf}} \def\tt{\fam=\ttfam \setfontstyle{tt}} % Texinfo sort of supports the sans serif font style, which plain TeX does not. % So we set up a \sf. \newfam\sffam \def\sf{\fam=\sffam \setfontstyle{sf}} \let\li = \sf % Sometimes we call it \li, not \sf. % We don't need math for this font style. \def\ttsl{\setfontstyle{ttsl}} % Default leading. \newdimen\textleading \textleading = 13.2pt % Set the baselineskip to #1, and the lineskip and strut size % correspondingly. There is no deep meaning behind these magic numbers % used as factors; they just match (closely enough) what Knuth defined. % \def\lineskipfactor{.08333} \def\strutheightpercent{.70833} \def\strutdepthpercent {.29167} % \def\setleading#1{% \normalbaselineskip = #1\relax \normallineskip = \lineskipfactor\normalbaselineskip \normalbaselines \setbox\strutbox =\hbox{% \vrule width0pt height\strutheightpercent\baselineskip depth \strutdepthpercent \baselineskip }% } % Set the font macro #1 to the font named #2, adding on the % specified font prefix (normally `cm'). % #3 is the font's design size, #4 is a scale factor \def\setfont#1#2#3#4{\font#1=\fontprefix#2#3 scaled #4} % Use cm as the default font prefix. % To specify the font prefix, you must define \fontprefix % before you read in texinfo.tex. \ifx\fontprefix\undefined \def\fontprefix{cm} \fi % Support font families that don't use the same naming scheme as CM. \def\rmshape{r} \def\rmbshape{bx} %where the normal face is bold \def\bfshape{b} \def\bxshape{bx} \def\ttshape{tt} \def\ttbshape{tt} \def\ttslshape{sltt} \def\itshape{ti} \def\itbshape{bxti} \def\slshape{sl} \def\slbshape{bxsl} \def\sfshape{ss} \def\sfbshape{ss} \def\scshape{csc} \def\scbshape{csc} % Text fonts (11.2pt, magstep1). \newcount\mainmagstep \ifx\bigger\relax % not really supported. \mainmagstep=\magstep1 \setfont\textrm\rmshape{12}{1000} \setfont\texttt\ttshape{12}{1000} \else \mainmagstep=\magstephalf \setfont\textrm\rmshape{10}{\mainmagstep} \setfont\texttt\ttshape{10}{\mainmagstep} \fi \setfont\textbf\bfshape{10}{\mainmagstep} \setfont\textit\itshape{10}{\mainmagstep} \setfont\textsl\slshape{10}{\mainmagstep} \setfont\textsf\sfshape{10}{\mainmagstep} \setfont\textsc\scshape{10}{\mainmagstep} \setfont\textttsl\ttslshape{10}{\mainmagstep} \font\texti=cmmi10 scaled \mainmagstep \font\textsy=cmsy10 scaled \mainmagstep % A few fonts for @defun names and args. \setfont\defbf\bfshape{10}{\magstep1} \setfont\deftt\ttshape{10}{\magstep1} \setfont\defttsl\ttslshape{10}{\magstep1} \def\df{\let\tentt=\deftt \let\tenbf = \defbf \let\tenttsl=\defttsl \bf} % Fonts for indices, footnotes, small examples (9pt). \setfont\smallrm\rmshape{9}{1000} \setfont\smalltt\ttshape{9}{1000} \setfont\smallbf\bfshape{10}{900} \setfont\smallit\itshape{9}{1000} \setfont\smallsl\slshape{9}{1000} \setfont\smallsf\sfshape{9}{1000} \setfont\smallsc\scshape{10}{900} \setfont\smallttsl\ttslshape{10}{900} \font\smalli=cmmi9 \font\smallsy=cmsy9 % Fonts for small examples (8pt). \setfont\smallerrm\rmshape{8}{1000} \setfont\smallertt\ttshape{8}{1000} \setfont\smallerbf\bfshape{10}{800} \setfont\smallerit\itshape{8}{1000} \setfont\smallersl\slshape{8}{1000} \setfont\smallersf\sfshape{8}{1000} \setfont\smallersc\scshape{10}{800} \setfont\smallerttsl\ttslshape{10}{800} \font\smalleri=cmmi8 \font\smallersy=cmsy8 % Fonts for title page (20.4pt): \setfont\titlerm\rmbshape{12}{\magstep3} \setfont\titleit\itbshape{10}{\magstep4} \setfont\titlesl\slbshape{10}{\magstep4} \setfont\titlett\ttbshape{12}{\magstep3} \setfont\titlettsl\ttslshape{10}{\magstep4} \setfont\titlesf\sfbshape{17}{\magstep1} \let\titlebf=\titlerm \setfont\titlesc\scbshape{10}{\magstep4} \font\titlei=cmmi12 scaled \magstep3 \font\titlesy=cmsy10 scaled \magstep4 \def\authorrm{\secrm} \def\authortt{\sectt} % Chapter (and unnumbered) fonts (17.28pt). \setfont\chaprm\rmbshape{12}{\magstep2} \setfont\chapit\itbshape{10}{\magstep3} \setfont\chapsl\slbshape{10}{\magstep3} \setfont\chaptt\ttbshape{12}{\magstep2} \setfont\chapttsl\ttslshape{10}{\magstep3} \setfont\chapsf\sfbshape{17}{1000} \let\chapbf=\chaprm \setfont\chapsc\scbshape{10}{\magstep3} \font\chapi=cmmi12 scaled \magstep2 \font\chapsy=cmsy10 scaled \magstep3 % Section fonts (14.4pt). \setfont\secrm\rmbshape{12}{\magstep1} \setfont\secit\itbshape{10}{\magstep2} \setfont\secsl\slbshape{10}{\magstep2} \setfont\sectt\ttbshape{12}{\magstep1} \setfont\secttsl\ttslshape{10}{\magstep2} \setfont\secsf\sfbshape{12}{\magstep1} \let\secbf\secrm \setfont\secsc\scbshape{10}{\magstep2} \font\seci=cmmi12 scaled \magstep1 \font\secsy=cmsy10 scaled \magstep2 % Subsection fonts (13.15pt). \setfont\ssecrm\rmbshape{12}{\magstephalf} \setfont\ssecit\itbshape{10}{1315} \setfont\ssecsl\slbshape{10}{1315} \setfont\ssectt\ttbshape{12}{\magstephalf} \setfont\ssecttsl\ttslshape{10}{1315} \setfont\ssecsf\sfbshape{12}{\magstephalf} \let\ssecbf\ssecrm \setfont\ssecsc\scbshape{10}{1315} \font\sseci=cmmi12 scaled \magstephalf \font\ssecsy=cmsy10 scaled 1315 % Reduced fonts for @acro in text (10pt). \setfont\reducedrm\rmshape{10}{1000} \setfont\reducedtt\ttshape{10}{1000} \setfont\reducedbf\bfshape{10}{1000} \setfont\reducedit\itshape{10}{1000} \setfont\reducedsl\slshape{10}{1000} \setfont\reducedsf\sfshape{10}{1000} \setfont\reducedsc\scshape{10}{1000} \setfont\reducedttsl\ttslshape{10}{1000} \font\reducedi=cmmi10 \font\reducedsy=cmsy10 % In order for the font changes to affect most math symbols and letters, % we have to define the \textfont of the standard families. Since % texinfo doesn't allow for producing subscripts and superscripts except % in the main text, we don't bother to reset \scriptfont and % \scriptscriptfont (which would also require loading a lot more fonts). % \def\resetmathfonts{% \textfont0=\tenrm \textfont1=\teni \textfont2=\tensy \textfont\itfam=\tenit \textfont\slfam=\tensl \textfont\bffam=\tenbf \textfont\ttfam=\tentt \textfont\sffam=\tensf } % The font-changing commands redefine the meanings of \tenSTYLE, instead % of just \STYLE. We do this because \STYLE needs to also set the % current \fam for math mode. Our \STYLE (e.g., \rm) commands hardwire % \tenSTYLE to set the current font. % % Each font-changing command also sets the names \lsize (one size lower) % and \lllsize (three sizes lower). These relative commands are used in % the LaTeX logo and acronyms. % % This all needs generalizing, badly. % \def\textfonts{% \let\tenrm=\textrm \let\tenit=\textit \let\tensl=\textsl \let\tenbf=\textbf \let\tentt=\texttt \let\smallcaps=\textsc \let\tensf=\textsf \let\teni=\texti \let\tensy=\textsy \let\tenttsl=\textttsl \def\lsize{reduced}\def\lllsize{smaller}% \resetmathfonts \setleading{\textleading}} \def\titlefonts{% \let\tenrm=\titlerm \let\tenit=\titleit \let\tensl=\titlesl \let\tenbf=\titlebf \let\tentt=\titlett \let\smallcaps=\titlesc \let\tensf=\titlesf \let\teni=\titlei \let\tensy=\titlesy \let\tenttsl=\titlettsl \def\lsize{chap}\def\lllsize{subsec}% \resetmathfonts \setleading{25pt}} \def\titlefont#1{{\titlefonts\rm #1}} \def\chapfonts{% \let\tenrm=\chaprm \let\tenit=\chapit \let\tensl=\chapsl \let\tenbf=\chapbf \let\tentt=\chaptt \let\smallcaps=\chapsc \let\tensf=\chapsf \let\teni=\chapi \let\tensy=\chapsy \let\tenttsl=\chapttsl \def\lsize{sec}\def\lllsize{text}% \resetmathfonts \setleading{19pt}} \def\secfonts{% \let\tenrm=\secrm \let\tenit=\secit \let\tensl=\secsl \let\tenbf=\secbf \let\tentt=\sectt \let\smallcaps=\secsc \let\tensf=\secsf \let\teni=\seci \let\tensy=\secsy \let\tenttsl=\secttsl \def\lsize{subsec}\def\lllsize{reduced}% \resetmathfonts \setleading{16pt}} \def\subsecfonts{% \let\tenrm=\ssecrm \let\tenit=\ssecit \let\tensl=\ssecsl \let\tenbf=\ssecbf \let\tentt=\ssectt \let\smallcaps=\ssecsc \let\tensf=\ssecsf \let\teni=\sseci \let\tensy=\ssecsy \let\tenttsl=\ssecttsl \def\lsize{text}\def\lllsize{small}% \resetmathfonts \setleading{15pt}} \let\subsubsecfonts = \subsecfonts \def\reducedfonts{% \let\tenrm=\reducedrm \let\tenit=\reducedit \let\tensl=\reducedsl \let\tenbf=\reducedbf \let\tentt=\reducedtt \let\reducedcaps=\reducedsc \let\tensf=\reducedsf \let\teni=\reducedi \let\tensy=\reducedsy \let\tenttsl=\reducedttsl \def\lsize{small}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallfonts{% \let\tenrm=\smallrm \let\tenit=\smallit \let\tensl=\smallsl \let\tenbf=\smallbf \let\tentt=\smalltt \let\smallcaps=\smallsc \let\tensf=\smallsf \let\teni=\smalli \let\tensy=\smallsy \let\tenttsl=\smallttsl \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{10.5pt}} \def\smallerfonts{% \let\tenrm=\smallerrm \let\tenit=\smallerit \let\tensl=\smallersl \let\tenbf=\smallerbf \let\tentt=\smallertt \let\smallcaps=\smallersc \let\tensf=\smallersf \let\teni=\smalleri \let\tensy=\smallersy \let\tenttsl=\smallerttsl \def\lsize{smaller}\def\lllsize{smaller}% \resetmathfonts \setleading{9.5pt}} % Set the fonts to use with the @small... environments. \let\smallexamplefonts = \smallfonts % About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample % can fit this many characters: % 8.5x11=86 smallbook=72 a4=90 a5=69 % If we use \scriptfonts (8pt), then we can fit this many characters: % 8.5x11=90+ smallbook=80 a4=90+ a5=77 % For me, subjectively, the few extra characters that fit aren't worth % the additional smallness of 8pt. So I'm making the default 9pt. % % By the way, for comparison, here's what fits with @example (10pt): % 8.5x11=71 smallbook=60 a4=75 a5=58 % % I wish the USA used A4 paper. % --karl, 24jan03. % Set up the default fonts, so we can use them for creating boxes. % \textfonts \rm % Define these so they can be easily changed for other fonts. \def\angleleft{$\langle$} \def\angleright{$\rangle$} % Count depth in font-changes, for error checks \newcount\fontdepth \fontdepth=0 % Fonts for short table of contents. \setfont\shortcontrm\rmshape{12}{1000} \setfont\shortcontbf\bfshape{10}{\magstep1} % no cmb12 \setfont\shortcontsl\slshape{12}{1000} \setfont\shortconttt\ttshape{12}{1000} %% Add scribe-like font environments, plus @l for inline lisp (usually sans %% serif) and @ii for TeX italic % \smartitalic{ARG} outputs arg in italics, followed by an italic correction % unless the following character is such as not to need one. \def\smartitalicx{\ifx\next,\else\ifx\next-\else\ifx\next.\else \ptexslash\fi\fi\fi} \def\smartslanted#1{{\ifusingtt\ttsl\sl #1}\futurelet\next\smartitalicx} \def\smartitalic#1{{\ifusingtt\ttsl\it #1}\futurelet\next\smartitalicx} % like \smartslanted except unconditionally uses \ttsl. % @var is set to this for defun arguments. \def\ttslanted#1{{\ttsl #1}\futurelet\next\smartitalicx} % like \smartslanted except unconditionally use \sl. We never want % ttsl for book titles, do we? \def\cite#1{{\sl #1}\futurelet\next\smartitalicx} \let\i=\smartitalic \let\var=\smartslanted \let\dfn=\smartslanted \let\emph=\smartitalic \def\b#1{{\bf #1}} \let\strong=\b % We can't just use \exhyphenpenalty, because that only has effect at % the end of a paragraph. Restore normal hyphenation at the end of the % group within which \nohyphenation is presumably called. % \def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation} \def\restorehyphenation{\hyphenchar\font = `- } % Set sfcode to normal for the chars that usually have another value. % Can't use plain's \frenchspacing because it uses the `\x notation, and % sometimes \x has an active definition that messes things up. % \catcode`@=11 \def\frenchspacing{% \sfcode\dotChar =\@m \sfcode\questChar=\@m \sfcode\exclamChar=\@m \sfcode\colonChar=\@m \sfcode\semiChar =\@m \sfcode\commaChar =\@m } \catcode`@=\other \def\t#1{% {\tt \rawbackslash \frenchspacing #1}% \null } \def\samp#1{`\tclose{#1}'\null} \setfont\keyrm\rmshape{8}{1000} \font\keysy=cmsy9 \def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{% \vbox{\hrule\kern-0.4pt \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}% \kern-0.4pt\hrule}% \kern-.06em\raise0.4pt\hbox{\angleright}}}} % The old definition, with no lozenge: %\def\key #1{{\ttsl \nohyphenation \uppercase{#1}}\null} \def\ctrl #1{{\tt \rawbackslash \hat}#1} % @file, @option are the same as @samp. \let\file=\samp \let\option=\samp % @code is a modification of @t, % which makes spaces the same size as normal in the surrounding text. \def\tclose#1{% {% % Change normal interword space to be same as for the current font. \spaceskip = \fontdimen2\font % % Switch to typewriter. \tt % % But `\ ' produces the large typewriter interword space. \def\ {{\spaceskip = 0pt{} }}% % % Turn off hyphenation. \nohyphenation % \rawbackslash \frenchspacing #1% }% \null } % We *must* turn on hyphenation at `-' and `_' in @code. % Otherwise, it is too hard to avoid overfull hboxes % in the Emacs manual, the Library manual, etc. % Unfortunately, TeX uses one parameter (\hyphenchar) to control % both hyphenation at - and hyphenation within words. % We must therefore turn them both off (\tclose does that) % and arrange explicitly to hyphenate at a dash. % -- rms. { \catcode`\-=\active \catcode`\_=\active % \global\def\code{\begingroup \catcode`\-=\active \let-\codedash \catcode`\_=\active \let_\codeunder \codex } } \def\realdash{-} \def\codedash{-\discretionary{}{}{}} \def\codeunder{% % this is all so @math{@code{var_name}+1} can work. In math mode, _ % is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.) % will therefore expand the active definition of _, which is us % (inside @code that is), therefore an endless loop. \ifusingtt{\ifmmode \mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_. \else\normalunderscore \fi \discretionary{}{}{}}% {\_}% } \def\codex #1{\tclose{#1}\endgroup} % @kbd is like @code, except that if the argument is just one @key command, % then @kbd has no effect. % @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always), % `example' (@kbd uses ttsl only inside of @example and friends), % or `code' (@kbd uses normal tty font always). \parseargdef\kbdinputstyle{% \def\arg{#1}% \ifx\arg\worddistinct \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}% \else\ifx\arg\wordexample \gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}% \else\ifx\arg\wordcode \gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}% \else \errhelp = \EMsimple \errmessage{Unknown @kbdinputstyle option `\arg'}% \fi\fi\fi } \def\worddistinct{distinct} \def\wordexample{example} \def\wordcode{code} % Default is `distinct.' \kbdinputstyle distinct \def\xkey{\key} \def\kbdfoo#1#2#3\par{\def\one{#1}\def\three{#3}\def\threex{??}% \ifx\one\xkey\ifx\threex\three \key{#2}% \else{\tclose{\kbdfont\look}}\fi \else{\tclose{\kbdfont\look}}\fi} % For @indicateurl, @env, @command quotes seem unnecessary, so use \code. \let\indicateurl=\code \let\env=\code \let\command=\code % @uref (abbreviation for `urlref') takes an optional (comma-separated) % second argument specifying the text to display and an optional third % arg as text to display instead of (rather than in addition to) the url % itself. First (mandatory) arg is the url. Perhaps eventually put in % a hypertex \special here. % \def\uref#1{\douref #1,,,\finish} \def\douref#1,#2,#3,#4\finish{\begingroup \unsepspaces \pdfurl{#1}% \setbox0 = \hbox{\ignorespaces #3}% \ifdim\wd0 > 0pt \unhbox0 % third arg given, show only that \else \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0 > 0pt \ifpdf \unhbox0 % PDF: 2nd arg given, show only it \else \unhbox0\ (\code{#1})% DVI: 2nd arg given, show both it and url \fi \else \code{#1}% only url given, so show it \fi \fi \endlink \endgroup} % @url synonym for @uref, since that's how everyone uses it. % \let\url=\uref % rms does not like angle brackets --karl, 17may97. % So now @email is just like @uref, unless we are pdf. % %\def\email#1{\angleleft{\tt #1}\angleright} \ifpdf \def\email#1{\doemail#1,,\finish} \def\doemail#1,#2,#3\finish{\begingroup \unsepspaces \pdfurl{mailto:#1}% \setbox0 = \hbox{\ignorespaces #2}% \ifdim\wd0>0pt\unhbox0\else\code{#1}\fi \endlink \endgroup} \else \let\email=\uref \fi % Check if we are currently using a typewriter font. Since all the % Computer Modern typewriter fonts have zero interword stretch (and % shrink), and it is reasonable to expect all typewriter fonts to have % this property, we can check that font parameter. % \def\ifmonospace{\ifdim\fontdimen3\font=0pt } % Typeset a dimension, e.g., `in' or `pt'. The only reason for the % argument is to make the input look right: @dmn{pt} instead of @dmn{}pt. % \def\dmn#1{\thinspace #1} \def\kbd#1{\def\look{#1}\expandafter\kbdfoo\look??\par} % @l was never documented to mean ``switch to the Lisp font'', % and it is not used as such in any manual I can find. We need it for % Polish suppressed-l. --karl, 22sep96. %\def\l#1{{\li #1}\null} % Explicit font changes: @r, @sc, undocumented @ii. \def\r#1{{\rm #1}} % roman font \def\sc#1{{\smallcaps#1}} % smallcaps font \def\ii#1{{\it #1}} % italic font \def\acronym#1{\doacronym #1,,\finish} \def\doacronym#1,#2,#3\finish{% {\selectfonts\lsize #1}% \def\temp{#2}% \ifx\temp\empty \else \space ({\unsepspaces \ignorespaces \temp \unskip})% \fi } % @pounds{} is a sterling sign, which is in the CM italic font. % \def\pounds{{\it\$}} % @registeredsymbol - R in a circle. The font for the R should really % be smaller yet, but lllsize is the best we can do for now. % Adapted from the plain.tex definition of \copyright. % \def\registeredsymbol{% $^{{\ooalign{\hfil\raise.07ex\hbox{\selectfonts\lllsize R}% \hfil\crcr\Orb}}% }$% } \message{page headings,} \newskip\titlepagetopglue \titlepagetopglue = 1.5in \newskip\titlepagebottomglue \titlepagebottomglue = 2pc % First the title page. Must do @settitle before @titlepage. \newif\ifseenauthor \newif\iffinishedtitlepage % Do an implicit @contents or @shortcontents after @end titlepage if the % user says @setcontentsaftertitlepage or @setshortcontentsaftertitlepage. % \newif\ifsetcontentsaftertitlepage \let\setcontentsaftertitlepage = \setcontentsaftertitlepagetrue \newif\ifsetshortcontentsaftertitlepage \let\setshortcontentsaftertitlepage = \setshortcontentsaftertitlepagetrue \parseargdef\shorttitlepage{\begingroup\hbox{}\vskip 1.5in \chaprm \centerline{#1}% \endgroup\page\hbox{}\page} \envdef\titlepage{% % Open one extra group, as we want to close it in the middle of \Etitlepage. \begingroup \parindent=0pt \textfonts % Leave some space at the very top of the page. \vglue\titlepagetopglue % No rule at page bottom unless we print one at the top with @title. \finishedtitlepagetrue % % Most title ``pages'' are actually two pages long, with space % at the top of the second. We don't want the ragged left on the second. \let\oldpage = \page \def\page{% \iffinishedtitlepage\else \finishtitlepage \fi \let\page = \oldpage \page \null }% } \def\Etitlepage{% \iffinishedtitlepage\else \finishtitlepage \fi % It is important to do the page break before ending the group, % because the headline and footline are only empty inside the group. % If we use the new definition of \page, we always get a blank page % after the title page, which we certainly don't want. \oldpage \endgroup % % Need this before the \...aftertitlepage checks so that if they are % in effect the toc pages will come out with page numbers. \HEADINGSon % % If they want short, they certainly want long too. \ifsetshortcontentsaftertitlepage \shortcontents \contents \global\let\shortcontents = \relax \global\let\contents = \relax \fi % \ifsetcontentsaftertitlepage \contents \global\let\contents = \relax \global\let\shortcontents = \relax \fi } \def\finishtitlepage{% \vskip4pt \hrule height 2pt width \hsize \vskip\titlepagebottomglue \finishedtitlepagetrue } %%% Macros to be used within @titlepage: \let\subtitlerm=\tenrm \def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines} \def\authorfont{\authorrm \normalbaselineskip = 16pt \normalbaselines \let\tt=\authortt} \parseargdef\title{% \checkenv\titlepage \leftline{\titlefonts\rm #1} % print a rule at the page bottom also. \finishedtitlepagefalse \vskip4pt \hrule height 4pt width \hsize \vskip4pt } \parseargdef\subtitle{% \checkenv\titlepage {\subtitlefont \rightline{#1}}% } % @author should come last, but may come many times. % It can also be used inside @quotation. % \parseargdef\author{% \def\temp{\quotation}% \ifx\thisenv\temp \def\quotationauthor{#1}% printed in \Equotation. \else \checkenv\titlepage \ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi {\authorfont \leftline{#1}}% \fi } %%% Set up page headings and footings. \let\thispage=\folio \newtoks\evenheadline % headline on even pages \newtoks\oddheadline % headline on odd pages \newtoks\evenfootline % footline on even pages \newtoks\oddfootline % footline on odd pages % Now make TeX use those variables \headline={{\textfonts\rm \ifodd\pageno \the\oddheadline \else \the\evenheadline \fi}} \footline={{\textfonts\rm \ifodd\pageno \the\oddfootline \else \the\evenfootline \fi}\HEADINGShook} \let\HEADINGShook=\relax % Commands to set those variables. % For example, this is what @headings on does % @evenheading @thistitle|@thispage|@thischapter % @oddheading @thischapter|@thispage|@thistitle % @evenfooting @thisfile|| % @oddfooting ||@thisfile \def\evenheading{\parsearg\evenheadingxxx} \def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish} \def\evenheadingyyy #1\|#2\|#3\|#4\finish{% \global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \def\oddheading{\parsearg\oddheadingxxx} \def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish} \def\oddheadingyyy #1\|#2\|#3\|#4\finish{% \global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}% \def\evenfooting{\parsearg\evenfootingxxx} \def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish} \def\evenfootingyyy #1\|#2\|#3\|#4\finish{% \global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}} \def\oddfooting{\parsearg\oddfootingxxx} \def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish} \def\oddfootingyyy #1\|#2\|#3\|#4\finish{% \global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}% % % Leave some space for the footline. Hopefully ok to assume % @evenfooting will not be used by itself. \global\advance\pageheight by -\baselineskip \global\advance\vsize by -\baselineskip } \parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}} % @headings double turns headings on for double-sided printing. % @headings single turns headings on for single-sided printing. % @headings off turns them off. % @headings on same as @headings double, retained for compatibility. % @headings after turns on double-sided headings after this page. % @headings doubleafter turns on double-sided headings after this page. % @headings singleafter turns on single-sided headings after this page. % By default, they are off at the start of a document, % and turned `on' after @end titlepage. \def\headings #1 {\csname HEADINGS#1\endcsname} \def\HEADINGSoff{% \global\evenheadline={\hfil} \global\evenfootline={\hfil} \global\oddheadline={\hfil} \global\oddfootline={\hfil}} \HEADINGSoff % When we turn headings on, set the page number to 1. % For double-sided printing, put current file name in lower left corner, % chapter name on inside top of right hand pages, document % title on inside top of left hand pages, and page numbers on outside top % edge of all pages. \def\HEADINGSdouble{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \let\contentsalignmacro = \chappager % For single-sided printing, chapter title goes across top left of page, % page number on top right. \def\HEADINGSsingle{% \global\pageno=1 \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\thischapter\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chappager } \def\HEADINGSon{\HEADINGSdouble} \def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex} \let\HEADINGSdoubleafter=\HEADINGSafter \def\HEADINGSdoublex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\folio\hfil\thistitle}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chapoddpage } \def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsinglex} \def\HEADINGSsinglex{% \global\evenfootline={\hfil} \global\oddfootline={\hfil} \global\evenheadline={\line{\thischapter\hfil\folio}} \global\oddheadline={\line{\thischapter\hfil\folio}} \global\let\contentsalignmacro = \chappager } % Subroutines used in generating headings % This produces Day Month Year style of output. % Only define if not already defined, in case a txi-??.tex file has set % up a different format (e.g., txi-cs.tex does this). \ifx\today\undefined \def\today{% \number\day\space \ifcase\month \or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr \or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug \or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec \fi \space\number\year} \fi % @settitle line... specifies the title of the document, for headings. % It generates no output of its own. \def\thistitle{\putwordNoTitle} \def\settitle{\parsearg{\gdef\thistitle}} \message{tables,} % Tables -- @table, @ftable, @vtable, @item(x). % default indentation of table text \newdimen\tableindent \tableindent=.8in % default indentation of @itemize and @enumerate text \newdimen\itemindent \itemindent=.3in % margin between end of table item and start of table text. \newdimen\itemmargin \itemmargin=.1in % used internally for \itemindent minus \itemmargin \newdimen\itemmax % Note @table, @ftable, and @vtable define @item, @itemx, etc., with % these defs. % They also define \itemindex % to index the item name in whatever manner is desired (perhaps none). \newif\ifitemxneedsnegativevskip \def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi} \def\internalBitem{\smallbreak \parsearg\itemzzz} \def\internalBitemx{\itemxpar \parsearg\itemzzz} \def\itemzzz #1{\begingroup % \advance\hsize by -\rightskip \advance\hsize by -\tableindent \setbox0=\hbox{\itemindicate{#1}}% \itemindex{#1}% \nobreak % This prevents a break before @itemx. % % If the item text does not fit in the space we have, put it on a line % by itself, and do not allow a page break either before or after that % line. We do not start a paragraph here because then if the next % command is, e.g., @kindex, the whatsit would get put into the % horizontal list on a line by itself, resulting in extra blank space. \ifdim \wd0>\itemmax % % Make this a paragraph so we get the \parskip glue and wrapping, % but leave it ragged-right. \begingroup \advance\leftskip by-\tableindent \advance\hsize by\tableindent \advance\rightskip by0pt plus1fil \leavevmode\unhbox0\par \endgroup % % We're going to be starting a paragraph, but we don't want the % \parskip glue -- logically it's part of the @item we just started. \nobreak \vskip-\parskip % % Stop a page break at the \parskip glue coming up. (Unfortunately % we can't prevent a possible page break at the following % \baselineskip glue.) However, if what follows is an environment % such as @example, there will be no \parskip glue; then % the negative vskip we just would cause the example and the item to % crash together. So we use this bizarre value of 10001 as a signal % to \aboveenvbreak to insert \parskip glue after all. % (Possibly there are other commands that could be followed by % @example which need the same treatment, but not section titles; or % maybe section titles are the only special case and they should be % penalty 10001...) \penalty 10001 \endgroup \itemxneedsnegativevskipfalse \else % The item text fits into the space. Start a paragraph, so that the % following text (if any) will end up on the same line. \noindent % Do this with kerns and \unhbox so that if there is a footnote in % the item text, it can migrate to the main vertical list and % eventually be printed. \nobreak\kern-\tableindent \dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0 \unhbox0 \nobreak\kern\dimen0 \endgroup \itemxneedsnegativevskiptrue \fi } \def\item{\errmessage{@item while not in a list environment}} \def\itemx{\errmessage{@itemx while not in a list environment}} % @table, @ftable, @vtable. \envdef\table{% \let\itemindex\gobble \tablex } \envdef\ftable{% \def\itemindex ##1{\doind {fn}{\code{##1}}}% \tablex } \envdef\vtable{% \def\itemindex ##1{\doind {vr}{\code{##1}}}% \tablex } \def\tablex#1{% \def\itemindicate{#1}% \parsearg\tabley } \def\tabley#1{% {% \makevalueexpandable \edef\temp{\noexpand\tablez #1\space\space\space}% \expandafter }\temp \endtablez } \def\tablez #1 #2 #3 #4\endtablez{% \aboveenvbreak \ifnum 0#1>0 \advance \leftskip by #1\mil \fi \ifnum 0#2>0 \tableindent=#2\mil \fi \ifnum 0#3>0 \advance \rightskip by #3\mil \fi \itemmax=\tableindent \advance \itemmax by -\itemmargin \advance \leftskip by \tableindent \exdentamount=\tableindent \parindent = 0pt \parskip = \smallskipamount \ifdim \parskip=0pt \parskip=2pt \fi \let\item = \internalBitem \let\itemx = \internalBitemx } \def\Etable{\endgraf\afterenvbreak} \let\Eftable\Etable \let\Evtable\Etable \let\Eitemize\Etable \let\Eenumerate\Etable % This is the counter used by @enumerate, which is really @itemize \newcount \itemno \envdef\itemize{\parsearg\doitemize} \def\doitemize#1{% \aboveenvbreak \itemmax=\itemindent \advance\itemmax by -\itemmargin \advance\leftskip by \itemindent \exdentamount=\itemindent \parindent=0pt \parskip=\smallskipamount \ifdim\parskip=0pt \parskip=2pt \fi \def\itemcontents{#1}% % @itemize with no arg is equivalent to @itemize @bullet. \ifx\itemcontents\empty\def\itemcontents{\bullet}\fi \let\item=\itemizeitem } % Definition of @item while inside @itemize and @enumerate. % \def\itemizeitem{% \advance\itemno by 1 % for enumerations {\let\par=\endgraf \smallbreak}% reasonable place to break {% % If the document has an @itemize directly after a section title, a % \nobreak will be last on the list, and \sectionheading will have % done a \vskip-\parskip. In that case, we don't want to zero % parskip, or the item text will crash with the heading. On the % other hand, when there is normal text preceding the item (as there % usually is), we do want to zero parskip, or there would be too much % space. In that case, we won't have a \nobreak before. At least % that's the theory. \ifnum\lastpenalty<10000 \parskip=0in \fi \noindent \hbox to 0pt{\hss \itemcontents \kern\itemmargin}% \vadjust{\penalty 1200}}% not good to break after first line of item. \flushcr } % \splitoff TOKENS\endmark defines \first to be the first token in % TOKENS, and \rest to be the remainder. % \def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}% % Allow an optional argument of an uppercase letter, lowercase letter, % or number, to specify the first label in the enumerated list. No % argument is the same as `1'. % \envparseargdef\enumerate{\enumeratey #1 \endenumeratey} \def\enumeratey #1 #2\endenumeratey{% % If we were given no argument, pretend we were given `1'. \def\thearg{#1}% \ifx\thearg\empty \def\thearg{1}\fi % % Detect if the argument is a single token. If so, it might be a % letter. Otherwise, the only valid thing it can be is a number. % (We will always have one token, because of the test we just made. % This is a good thing, since \splitoff doesn't work given nothing at % all -- the first parameter is undelimited.) \expandafter\splitoff\thearg\endmark \ifx\rest\empty % Only one token in the argument. It could still be anything. % A ``lowercase letter'' is one whose \lccode is nonzero. % An ``uppercase letter'' is one whose \lccode is both nonzero, and % not equal to itself. % Otherwise, we assume it's a number. % % We need the \relax at the end of the \ifnum lines to stop TeX from % continuing to look for a . % \ifnum\lccode\expandafter`\thearg=0\relax \numericenumerate % a number (we hope) \else % It's a letter. \ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax \lowercaseenumerate % lowercase letter \else \uppercaseenumerate % uppercase letter \fi \fi \else % Multiple tokens in the argument. We hope it's a number. \numericenumerate \fi } % An @enumerate whose labels are integers. The starting integer is % given in \thearg. % \def\numericenumerate{% \itemno = \thearg \startenumeration{\the\itemno}% } % The starting (lowercase) letter is in \thearg. \def\lowercaseenumerate{% \itemno = \expandafter`\thearg \startenumeration{% % Be sure we're not beyond the end of the alphabet. \ifnum\itemno=0 \errmessage{No more lowercase letters in @enumerate; get a bigger alphabet}% \fi \char\lccode\itemno }% } % The starting (uppercase) letter is in \thearg. \def\uppercaseenumerate{% \itemno = \expandafter`\thearg \startenumeration{% % Be sure we're not beyond the end of the alphabet. \ifnum\itemno=0 \errmessage{No more uppercase letters in @enumerate; get a bigger alphabet} \fi \char\uccode\itemno }% } % Call \doitemize, adding a period to the first argument and supplying the % common last two arguments. Also subtract one from the initial value in % \itemno, since @item increments \itemno. % \def\startenumeration#1{% \advance\itemno by -1 \doitemize{#1.}\flushcr } % @alphaenumerate and @capsenumerate are abbreviations for giving an arg % to @enumerate. % \def\alphaenumerate{\enumerate{a}} \def\capsenumerate{\enumerate{A}} \def\Ealphaenumerate{\Eenumerate} \def\Ecapsenumerate{\Eenumerate} % @multitable macros % Amy Hendrickson, 8/18/94, 3/6/96 % % @multitable ... @end multitable will make as many columns as desired. % Contents of each column will wrap at width given in preamble. Width % can be specified either with sample text given in a template line, % or in percent of \hsize, the current width of text on page. % Table can continue over pages but will only break between lines. % To make preamble: % % Either define widths of columns in terms of percent of \hsize: % @multitable @columnfractions .25 .3 .45 % @item ... % % Numbers following @columnfractions are the percent of the total % current hsize to be used for each column. You may use as many % columns as desired. % Or use a template: % @multitable {Column 1 template} {Column 2 template} {Column 3 template} % @item ... % using the widest term desired in each column. % Each new table line starts with @item, each subsequent new column % starts with @tab. Empty columns may be produced by supplying @tab's % with nothing between them for as many times as empty columns are needed, % ie, @tab@tab@tab will produce two empty columns. % @item, @tab do not need to be on their own lines, but it will not hurt % if they are. % Sample multitable: % @multitable {Column 1 template} {Column 2 template} {Column 3 template} % @item first col stuff @tab second col stuff @tab third col % @item % first col stuff % @tab % second col stuff % @tab % third col % @item first col stuff @tab second col stuff % @tab Many paragraphs of text may be used in any column. % % They will wrap at the width determined by the template. % @item@tab@tab This will be in third column. % @end multitable % Default dimensions may be reset by user. % @multitableparskip is vertical space between paragraphs in table. % @multitableparindent is paragraph indent in table. % @multitablecolmargin is horizontal space to be left between columns. % @multitablelinespace is space to leave between table items, baseline % to baseline. % 0pt means it depends on current normal line spacing. % \newskip\multitableparskip \newskip\multitableparindent \newdimen\multitablecolspace \newskip\multitablelinespace \multitableparskip=0pt \multitableparindent=6pt \multitablecolspace=12pt \multitablelinespace=0pt % Macros used to set up halign preamble: % \let\endsetuptable\relax \def\xendsetuptable{\endsetuptable} \let\columnfractions\relax \def\xcolumnfractions{\columnfractions} \newif\ifsetpercent % #1 is the @columnfraction, usually a decimal number like .5, but might % be just 1. We just use it, whatever it is. % \def\pickupwholefraction#1 {% \global\advance\colcount by 1 \expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}% \setuptable } \newcount\colcount \def\setuptable#1{% \def\firstarg{#1}% \ifx\firstarg\xendsetuptable \let\go = \relax \else \ifx\firstarg\xcolumnfractions \global\setpercenttrue \else \ifsetpercent \let\go\pickupwholefraction \else \global\advance\colcount by 1 \setbox0=\hbox{#1\unskip\space}% Add a normal word space as a % separator; typically that is always in the input, anyway. \expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}% \fi \fi \ifx\go\pickupwholefraction % Put the argument back for the \pickupwholefraction call, so % we'll always have a period there to be parsed. \def\go{\pickupwholefraction#1}% \else \let\go = \setuptable \fi% \fi \go } % multitable-only commands. % % @headitem starts a heading row, which we typeset in bold. % Assignments have to be global since we are inside the implicit group % of an alignment entry. Note that \everycr resets \everytab. \def\headitem{\checkenv\multitable \crcr \global\everytab={\bf}\the\everytab}% % % A \tab used to include \hskip1sp. But then the space in a template % line is not enough. That is bad. So let's go back to just `&' until % we encounter the problem it was intended to solve again. % --karl, nathan@acm.org, 20apr99. \def\tab{\checkenv\multitable &\the\everytab}% % @multitable ... @end multitable definitions: % \newtoks\everytab % insert after every tab. % \envdef\multitable{% \vskip\parskip \startsavinginserts % % @item within a multitable starts a normal row. \let\item\crcr % \tolerance=9500 \hbadness=9500 \setmultitablespacing \parskip=\multitableparskip \parindent=\multitableparindent \overfullrule=0pt \global\colcount=0 % \everycr = {% \noalign{% \global\everytab={}% \global\colcount=0 % Reset the column counter. % Check for saved footnotes, etc. \checkinserts % Keeps underfull box messages off when table breaks over pages. %\filbreak % Maybe so, but it also creates really weird page breaks when the % table breaks over pages. Wouldn't \vfil be better? Wait until the % problem manifests itself, so it can be fixed for real --karl. }% }% % \parsearg\domultitable } \def\domultitable#1{% % To parse everything between @multitable and @item: \setuptable#1 \endsetuptable % % This preamble sets up a generic column definition, which will % be used as many times as user calls for columns. % \vtop will set a single line and will also let text wrap and % continue for many paragraphs if desired. \halign\bgroup &% \global\advance\colcount by 1 \multistrut \vtop{% % Use the current \colcount to find the correct column width: \hsize=\expandafter\csname col\the\colcount\endcsname % % In order to keep entries from bumping into each other % we will add a \leftskip of \multitablecolspace to all columns after % the first one. % % If a template has been used, we will add \multitablecolspace % to the width of each template entry. % % If the user has set preamble in terms of percent of \hsize we will % use that dimension as the width of the column, and the \leftskip % will keep entries from bumping into each other. Table will start at % left margin and final column will justify at right margin. % % Make sure we don't inherit \rightskip from the outer environment. \rightskip=0pt \ifnum\colcount=1 % The first column will be indented with the surrounding text. \advance\hsize by\leftskip \else \ifsetpercent \else % If user has not set preamble in terms of percent of \hsize % we will advance \hsize by \multitablecolspace. \advance\hsize by \multitablecolspace \fi % In either case we will make \leftskip=\multitablecolspace: \leftskip=\multitablecolspace \fi % Ignoring space at the beginning and end avoids an occasional spurious % blank line, when TeX decides to break the line at the space before the % box from the multistrut, so the strut ends up on a line by itself. % For example: % @multitable @columnfractions .11 .89 % @item @code{#} % @tab Legal holiday which is valid in major parts of the whole country. % Is automatically provided with highlighting sequences respectively % marking characters. \noindent\ignorespaces##\unskip\multistrut }\cr } \def\Emultitable{% \crcr \egroup % end the \halign \global\setpercentfalse } \def\setmultitablespacing{% test to see if user has set \multitablelinespace. % If so, do nothing. If not, give it an appropriate dimension based on % current baselineskip. \ifdim\multitablelinespace=0pt \setbox0=\vbox{X}\global\multitablelinespace=\the\baselineskip \global\advance\multitablelinespace by-\ht0 %% strut to put in table in case some entry doesn't have descenders, %% to keep lines equally spaced \let\multistrut = \strut \else %% FIXME: what is \box0 supposed to be? \gdef\multistrut{\vrule height\multitablelinespace depth\dp0 width0pt\relax} \fi %% Test to see if parskip is larger than space between lines of %% table. If not, do nothing. %% If so, set to same dimension as multitablelinespace. \ifdim\multitableparskip>\multitablelinespace \global\multitableparskip=\multitablelinespace \global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller %% than skip between lines in the table. \fi% \ifdim\multitableparskip=0pt \global\multitableparskip=\multitablelinespace \global\advance\multitableparskip-7pt %% to keep parskip somewhat smaller %% than skip between lines in the table. \fi} \message{conditionals,} % @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, % @ifnotxml always succeed. They currently do nothing; we don't % attempt to check whether the conditionals are properly nested. But we % have to remember that they are conditionals, so that @end doesn't % attempt to close an environment group. % \def\makecond#1{% \expandafter\let\csname #1\endcsname = \relax \expandafter\let\csname iscond.#1\endcsname = 1 } \makecond{iftex} \makecond{ifnotdocbook} \makecond{ifnothtml} \makecond{ifnotinfo} \makecond{ifnotplaintext} \makecond{ifnotxml} % Ignore @ignore, @ifhtml, @ifinfo, and the like. % \def\direntry{\doignore{direntry}} \def\documentdescription{\doignore{documentdescription}} \def\docbook{\doignore{docbook}} \def\html{\doignore{html}} \def\ifdocbook{\doignore{ifdocbook}} \def\ifhtml{\doignore{ifhtml}} \def\ifinfo{\doignore{ifinfo}} \def\ifnottex{\doignore{ifnottex}} \def\ifplaintext{\doignore{ifplaintext}} \def\ifxml{\doignore{ifxml}} \def\ignore{\doignore{ignore}} \def\menu{\doignore{menu}} \def\xml{\doignore{xml}} % Ignore text until a line `@end #1', keeping track of nested conditionals. % % A count to remember the depth of nesting. \newcount\doignorecount \def\doignore#1{\begingroup % Scan in ``verbatim'' mode: \catcode`\@ = \other \catcode`\{ = \other \catcode`\} = \other % % Make sure that spaces turn into tokens that match what \doignoretext wants. \spaceisspace % % Count number of #1's that we've seen. \doignorecount = 0 % % Swallow text until we reach the matching `@end #1'. \dodoignore {#1}% } { \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source. \obeylines % % \gdef\dodoignore#1{% % #1 contains the string `ifinfo'. % % Define a command to find the next `@end #1', which must be on a line % by itself. \long\def\doignoretext##1^^M@end #1{\doignoretextyyy##1^^M@#1\_STOP_}% % And this command to find another #1 command, at the beginning of a % line. (Otherwise, we would consider a line `@c @ifset', for % example, to count as an @ifset for nesting.) \long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}% % % And now expand that command. \obeylines % \doignoretext ^^M% }% } \def\doignoreyyy#1{% \def\temp{#1}% \ifx\temp\empty % Nothing found. \let\next\doignoretextzzz \else % Found a nested condition, ... \advance\doignorecount by 1 \let\next\doignoretextyyy % ..., look for another. % If we're here, #1 ends with ^^M\ifinfo (for example). \fi \next #1% the token \_STOP_ is present just after this macro. } % We have to swallow the remaining "\_STOP_". % \def\doignoretextzzz#1{% \ifnum\doignorecount = 0 % We have just found the outermost @end. \let\next\enddoignore \else % Still inside a nested condition. \advance\doignorecount by -1 \let\next\doignoretext % Look for the next @end. \fi \next } % Finish off ignored text. \def\enddoignore{\endgroup\ignorespaces} % @set VAR sets the variable VAR to an empty value. % @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE. % % Since we want to separate VAR from REST-OF-LINE (which might be % empty), we can't just use \parsearg; we have to insert a space of our % own to delimit the rest of the line, and then take it out again if we % didn't need it. % We rely on the fact that \parsearg sets \catcode`\ =10. % \parseargdef\set{\setyyy#1 \endsetyyy} \def\setyyy#1 #2\endsetyyy{% {% \makevalueexpandable \def\temp{#2}% \edef\next{\gdef\makecsname{SET#1}}% \ifx\temp\empty \next{}% \else \setzzz#2\endsetzzz \fi }% } % Remove the trailing space \setxxx inserted. \def\setzzz#1 \endsetzzz{\next{#1}} % @clear VAR clears (i.e., unsets) the variable VAR. % \parseargdef\clear{% {% \makevalueexpandable \global\expandafter\let\csname SET#1\endcsname=\relax }% } % @value{foo} gets the text saved in variable foo. \def\value{\begingroup\makevalueexpandable\valuexxx} \def\valuexxx#1{\expandablevalue{#1}\endgroup} { \catcode`\- = \active \catcode`\_ = \active % \gdef\makevalueexpandable{% \let\value = \expandablevalue % We don't want these characters active, ... \catcode`\-=\other \catcode`\_=\other % ..., but we might end up with active ones in the argument if % we're called from @code, as @code{@value{foo-bar_}}, though. % So \let them to their normal equivalents. \let-\realdash \let_\normalunderscore } } % We have this subroutine so that we can handle at least some @value's % properly in indexes (we call \makevalueexpandable in \indexdummies). % The command has to be fully expandable (if the variable is set), since % the result winds up in the index file. This means that if the % variable's value contains other Texinfo commands, it's almost certain % it will fail (although perhaps we could fix that with sufficient work % to do a one-level expansion on the result, instead of complete). % \def\expandablevalue#1{% \expandafter\ifx\csname SET#1\endcsname\relax {[No value for ``#1'']}% \message{Variable `#1', used in @value, is not set.}% \else \csname SET#1\endcsname \fi } % @ifset VAR ... @end ifset reads the `...' iff VAR has been defined % with @set. % % To get special treatment of `@end ifset,' call \makeond and the redefine. % \makecond{ifset} \def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}} \def\doifset#1#2{% {% \makevalueexpandable \let\next=\empty \expandafter\ifx\csname SET#2\endcsname\relax #1% If not set, redefine \next. \fi \expandafter }\next } \def\ifsetfail{\doignore{ifset}} % @ifclear VAR ... @end ifclear reads the `...' iff VAR has never been % defined with @set, or has been undefined with @clear. % % The `\else' inside the `\doifset' parameter is a trick to reuse the % above code: if the variable is not set, do nothing, if it is set, % then redefine \next to \ifclearfail. % \makecond{ifclear} \def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}} \def\ifclearfail{\doignore{ifclear}} % @dircategory CATEGORY -- specify a category of the dir file % which this file should belong to. Ignore this in TeX. \let\dircategory=\comment % @defininfoenclose. \let\definfoenclose=\comment \message{indexing,} % Index generation facilities % Define \newwrite to be identical to plain tex's \newwrite % except not \outer, so it can be used within \newindex. {\catcode`\@=11 \gdef\newwrite{\alloc@7\write\chardef\sixt@@n}} % \newindex {foo} defines an index named foo. % It automatically defines \fooindex such that % \fooindex ...rest of line... puts an entry in the index foo. % It also defines \fooindfile to be the number of the output channel for % the file that accumulates this index. The file's extension is foo. % The name of an index should be no more than 2 characters long % for the sake of vms. % \def\newindex#1{% \iflinks \expandafter\newwrite \csname#1indfile\endcsname \openout \csname#1indfile\endcsname \jobname.#1 % Open the file \fi \expandafter\xdef\csname#1index\endcsname{% % Define @#1index \noexpand\doindex{#1}} } % @defindex foo == \newindex{foo} % \def\defindex{\parsearg\newindex} % Define @defcodeindex, like @defindex except put all entries in @code. % \def\defcodeindex{\parsearg\newcodeindex} % \def\newcodeindex#1{% \iflinks \expandafter\newwrite \csname#1indfile\endcsname \openout \csname#1indfile\endcsname \jobname.#1 \fi \expandafter\xdef\csname#1index\endcsname{% \noexpand\docodeindex{#1}}% } % @synindex foo bar makes index foo feed into index bar. % Do this instead of @defindex foo if you don't want it as a separate index. % % @syncodeindex foo bar similar, but put all entries made for index foo % inside @code. % \def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}} \def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}} % #1 is \doindex or \docodeindex, #2 the index getting redefined (foo), % #3 the target index (bar). \def\dosynindex#1#2#3{% % Only do \closeout if we haven't already done it, else we'll end up % closing the target index. \expandafter \ifx\csname donesynindex#2\endcsname \undefined % The \closeout helps reduce unnecessary open files; the limit on the % Acorn RISC OS is a mere 16 files. \expandafter\closeout\csname#2indfile\endcsname \expandafter\let\csname\donesynindex#2\endcsname = 1 \fi % redefine \fooindfile: \expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname \expandafter\let\csname#2indfile\endcsname=\temp % redefine \fooindex: \expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}% } % Define \doindex, the driver for all \fooindex macros. % Argument #1 is generated by the calling \fooindex macro, % and it is "foo", the name of the index. % \doindex just uses \parsearg; it calls \doind for the actual work. % This is because \doind is more useful to call from other macros. % There is also \dosubind {index}{topic}{subtopic} % which makes an entry in a two-level index such as the operation index. \def\doindex#1{\edef\indexname{#1}\parsearg\singleindexer} \def\singleindexer #1{\doind{\indexname}{#1}} % like the previous two, but they put @code around the argument. \def\docodeindex#1{\edef\indexname{#1}\parsearg\singlecodeindexer} \def\singlecodeindexer #1{\doind{\indexname}{\code{#1}}} % Take care of Texinfo commands that can appear in an index entry. % Since there are some commands we want to expand, and others we don't, % we have to laboriously prevent expansion for those that we don't. % \def\indexdummies{% \def\@{@}% change to @@ when we switch to @ as escape char in index files. \def\ {\realbackslash\space }% % Need these in case \tex is in effect and \{ is a \delimiter again. % But can't use \lbracecmd and \rbracecmd because texindex assumes % braces and backslashes are used only as delimiters. \let\{ = \mylbrace \let\} = \myrbrace % % \definedummyword defines \#1 as \realbackslash #1\space, thus % effectively preventing its expansion. This is used only for control % words, not control letters, because the \space would be incorrect % for control characters, but is needed to separate the control word % from whatever follows. % % For control letters, we have \definedummyletter, which omits the % space. % % These can be used both for control words that take an argument and % those that do not. If it is followed by {arg} in the input, then % that will dutifully get written to the index (or wherever). % \def\definedummyword##1{% \expandafter\def\csname ##1\endcsname{\realbackslash ##1\space}% }% \def\definedummyletter##1{% \expandafter\def\csname ##1\endcsname{\realbackslash ##1}% }% % % Do the redefinitions. \commondummies } % For the aux file, @ is the escape character. So we want to redefine % everything using @ instead of \realbackslash. When everything uses % @, this will be simpler. % \def\atdummies{% \def\@{@@}% \def\ {@ }% \let\{ = \lbraceatcmd \let\} = \rbraceatcmd % % (See comments in \indexdummies.) \def\definedummyword##1{% \expandafter\def\csname ##1\endcsname{@##1\space}% }% \def\definedummyletter##1{% \expandafter\def\csname ##1\endcsname{@##1}% }% % % Do the redefinitions. \commondummies } % Called from \indexdummies and \atdummies. \definedummyword and % \definedummyletter must be defined first. % \def\commondummies{% % \normalturnoffactive % \commondummiesnofonts % \definedummyletter{_}% % % Non-English letters. \definedummyword{AA}% \definedummyword{AE}% \definedummyword{L}% \definedummyword{OE}% \definedummyword{O}% \definedummyword{aa}% \definedummyword{ae}% \definedummyword{l}% \definedummyword{oe}% \definedummyword{o}% \definedummyword{ss}% \definedummyword{exclamdown}% \definedummyword{questiondown}% \definedummyword{ordf}% \definedummyword{ordm}% % % Although these internal commands shouldn't show up, sometimes they do. \definedummyword{bf}% \definedummyword{gtr}% \definedummyword{hat}% \definedummyword{less}% \definedummyword{sf}% \definedummyword{sl}% \definedummyword{tclose}% \definedummyword{tt}% % \definedummyword{LaTeX}% \definedummyword{TeX}% % % Assorted special characters. \definedummyword{bullet}% \definedummyword{copyright}% \definedummyword{registeredsymbol}% \definedummyword{dots}% \definedummyword{enddots}% \definedummyword{equiv}% \definedummyword{error}% \definedummyword{expansion}% \definedummyword{minus}% \definedummyword{pounds}% \definedummyword{point}% \definedummyword{print}% \definedummyword{result}% % % Handle some cases of @value -- where it does not contain any % (non-fully-expandable) commands. \makevalueexpandable % % Normal spaces, not active ones. \unsepspaces % % No macro expansion. \turnoffmacros } % \commondummiesnofonts: common to \commondummies and \indexnofonts. % % Better have this without active chars. { \catcode`\~=\other \gdef\commondummiesnofonts{% % Control letters and accents. \definedummyletter{!}% \definedummyletter{"}% \definedummyletter{'}% \definedummyletter{*}% \definedummyletter{,}% \definedummyletter{.}% \definedummyletter{/}% \definedummyletter{:}% \definedummyletter{=}% \definedummyletter{?}% \definedummyletter{^}% \definedummyletter{`}% \definedummyletter{~}% \definedummyword{u}% \definedummyword{v}% \definedummyword{H}% \definedummyword{dotaccent}% \definedummyword{ringaccent}% \definedummyword{tieaccent}% \definedummyword{ubaraccent}% \definedummyword{udotaccent}% \definedummyword{dotless}% % % Texinfo font commands. \definedummyword{b}% \definedummyword{i}% \definedummyword{r}% \definedummyword{sc}% \definedummyword{t}% % % Commands that take arguments. \definedummyword{acronym}% \definedummyword{cite}% \definedummyword{code}% \definedummyword{command}% \definedummyword{dfn}% \definedummyword{emph}% \definedummyword{env}% \definedummyword{file}% \definedummyword{kbd}% \definedummyword{key}% \definedummyword{math}% \definedummyword{option}% \definedummyword{samp}% \definedummyword{strong}% \definedummyword{tie}% \definedummyword{uref}% \definedummyword{url}% \definedummyword{var}% \definedummyword{verb}% \definedummyword{w}% } } % \indexnofonts is used when outputting the strings to sort the index % by, and when constructing control sequence names. It eliminates all % control sequences and just writes whatever the best ASCII sort string % would be for a given command (usually its argument). % \def\indexnofonts{% \def\definedummyword##1{% \expandafter\let\csname ##1\endcsname\asis }% % We can just ignore the accent commands and other control letters. \def\definedummyletter##1{% \expandafter\def\csname ##1\endcsname{}% }% % \commondummiesnofonts % % Don't no-op \tt, since it isn't a user-level command % and is used in the definitions of the active chars like <, >, |, etc. % Likewise with the other plain tex font commands. %\let\tt=\asis % \def\ { }% \def\@{@}% % how to handle braces? \def\_{\normalunderscore}% % % Non-English letters. \def\AA{AA}% \def\AE{AE}% \def\L{L}% \def\OE{OE}% \def\O{O}% \def\aa{aa}% \def\ae{ae}% \def\l{l}% \def\oe{oe}% \def\o{o}% \def\ss{ss}% \def\exclamdown{!}% \def\questiondown{?}% \def\ordf{a}% \def\ordm{o}% % \def\LaTeX{LaTeX}% \def\TeX{TeX}% % % Assorted special characters. % (The following {} will end up in the sort string, but that's ok.) \def\bullet{bullet}% \def\copyright{copyright}% \def\registeredsymbol{R}% \def\dots{...}% \def\enddots{...}% \def\equiv{==}% \def\error{error}% \def\expansion{==>}% \def\minus{-}% \def\pounds{pounds}% \def\point{.}% \def\print{-|}% \def\result{=>}% } \let\indexbackslash=0 %overridden during \printindex. \let\SETmarginindex=\relax % put index entries in margin (undocumented)? % Most index entries go through here, but \dosubind is the general case. % #1 is the index name, #2 is the entry text. \def\doind#1#2{\dosubind{#1}{#2}{}} % Workhorse for all \fooindexes. % #1 is name of index, #2 is stuff to put there, #3 is subentry -- % empty if called from \doind, as we usually are (the main exception % is with most defuns, which call us directly). % \def\dosubind#1#2#3{% \iflinks {% % Store the main index entry text (including the third arg). \toks0 = {#2}% % If third arg is present, precede it with a space. \def\thirdarg{#3}% \ifx\thirdarg\empty \else \toks0 = \expandafter{\the\toks0 \space #3}% \fi % \edef\writeto{\csname#1indfile\endcsname}% % \ifvmode \dosubindsanitize \else \dosubindwrite \fi }% \fi } % Write the entry in \toks0 to the index file: % \def\dosubindwrite{% % Put the index entry in the margin if desired. \ifx\SETmarginindex\relax\else \insert\margin{\hbox{\vrule height8pt depth3pt width0pt \the\toks0}}% \fi % % Remember, we are within a group. \indexdummies % Must do this here, since \bf, etc expand at this stage \escapechar=`\\ \def\backslashcurfont{\indexbackslash}% \indexbackslash isn't defined now % so it will be output as is; and it will print as backslash. % % Process the index entry with all font commands turned off, to % get the string to sort by. {\indexnofonts \edef\temp{\the\toks0}% need full expansion \xdef\indexsorttmp{\temp}% }% % % Set up the complete index entry, with both the sort key and % the original text, including any font commands. We write % three arguments to \entry to the .?? file (four in the % subentry case), texindex reduces to two when writing the .??s % sorted result. \edef\temp{% \write\writeto{% \string\entry{\indexsorttmp}{\noexpand\folio}{\the\toks0}}% }% \temp } % Take care of unwanted page breaks: % % If a skip is the last thing on the list now, preserve it % by backing up by \lastskip, doing the \write, then inserting % the skip again. Otherwise, the whatsit generated by the % \write will make \lastskip zero. The result is that sequences % like this: % @end defun % @tindex whatever % @defun ... % will have extra space inserted, because the \medbreak in the % start of the @defun won't see the skip inserted by the @end of % the previous defun. % % But don't do any of this if we're not in vertical mode. We % don't want to do a \vskip and prematurely end a paragraph. % % Avoid page breaks due to these extra skips, too. % % But wait, there is a catch there: % We'll have to check whether \lastskip is zero skip. \ifdim is not % sufficient for this purpose, as it ignores stretch and shrink parts % of the skip. The only way seems to be to check the textual % representation of the skip. % % The following is almost like \def\zeroskipmacro{0.0pt} except that % the ``p'' and ``t'' characters have catcode \other, not 11 (letter). % \edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname} % % ..., ready, GO: % \def\dosubindsanitize{% % \lastskip and \lastpenalty cannot both be nonzero simultaneously. \skip0 = \lastskip \edef\lastskipmacro{\the\lastskip}% \count255 = \lastpenalty % % If \lastskip is nonzero, that means the last item was a % skip. And since a skip is discardable, that means this % -\skip0 glue we're inserting is preceded by a % non-discardable item, therefore it is not a potential % breakpoint, therefore no \nobreak needed. \ifx\lastskipmacro\zeroskipmacro \else \vskip-\skip0 \fi % \dosubindwrite % \ifx\lastskipmacro\zeroskipmacro % if \lastskip was zero, perhaps the last item was a % penalty, and perhaps it was >=10000, e.g., a \nobreak. % In that case, we want to re-insert the penalty; since we % just inserted a non-discardable item, any following glue % (such as a \parskip) would be a breakpoint. For example: % @deffn deffn-whatever % @vindex index-whatever % Description. % would allow a break between the index-whatever whatsit % and the "Description." paragraph. \ifnum\count255>9999 \nobreak \fi \else % On the other hand, if we had a nonzero \lastskip, % this make-up glue would be preceded by a non-discardable item % (the whatsit from the \write), so we must insert a \nobreak. \nobreak\vskip\skip0 \fi } % The index entry written in the file actually looks like % \entry {sortstring}{page}{topic} % or % \entry {sortstring}{page}{topic}{subtopic} % The texindex program reads in these files and writes files % containing these kinds of lines: % \initial {c} % before the first topic whose initial is c % \entry {topic}{pagelist} % for a topic that is used without subtopics % \primary {topic} % for the beginning of a topic that is used with subtopics % \secondary {subtopic}{pagelist} % for each subtopic. % Define the user-accessible indexing commands % @findex, @vindex, @kindex, @cindex. \def\findex {\fnindex} \def\kindex {\kyindex} \def\cindex {\cpindex} \def\vindex {\vrindex} \def\tindex {\tpindex} \def\pindex {\pgindex} \def\cindexsub {\begingroup\obeylines\cindexsub} {\obeylines % \gdef\cindexsub "#1" #2^^M{\endgroup % \dosubind{cp}{#2}{#1}}} % Define the macros used in formatting output of the sorted index material. % @printindex causes a particular index (the ??s file) to get printed. % It does not print any chapter heading (usually an @unnumbered). % \parseargdef\printindex{\begingroup \dobreak \chapheadingskip{10000}% % \smallfonts \rm \tolerance = 9500 \everypar = {}% don't want the \kern\-parindent from indentation suppression. % % See if the index file exists and is nonempty. % Change catcode of @ here so that if the index file contains % \initial {@} % as its first line, TeX doesn't complain about mismatched braces % (because it thinks @} is a control sequence). \catcode`\@ = 11 \openin 1 \jobname.#1s \ifeof 1 % \enddoublecolumns gets confused if there is no text in the index, % and it loses the chapter title and the aux file entries for the % index. The easiest way to prevent this problem is to make sure % there is some text. \putwordIndexNonexistent \else % % If the index file exists but is empty, then \openin leaves \ifeof % false. We have to make TeX try to read something from the file, so % it can discover if there is anything in it. \read 1 to \temp \ifeof 1 \putwordIndexIsEmpty \else % Index files are almost Texinfo source, but we use \ as the escape % character. It would be better to use @, but that's too big a change % to make right now. \def\indexbackslash{\backslashcurfont}% \catcode`\\ = 0 \escapechar = `\\ \begindoublecolumns \input \jobname.#1s \enddoublecolumns \fi \fi \closein 1 \endgroup} % These macros are used by the sorted index file itself. % Change them to control the appearance of the index. \def\initial#1{{% % Some minor font changes for the special characters. \let\tentt=\sectt \let\tt=\sectt \let\sf=\sectt % % Remove any glue we may have, we'll be inserting our own. \removelastskip % % We like breaks before the index initials, so insert a bonus. \penalty -300 % % Typeset the initial. Making this add up to a whole number of % baselineskips increases the chance of the dots lining up from column % to column. It still won't often be perfect, because of the stretch % we need before each entry, but it's better. % % No shrink because it confuses \balancecolumns. \vskip 1.67\baselineskip plus .5\baselineskip \leftline{\secbf #1}% \vskip .33\baselineskip plus .1\baselineskip % % Do our best not to break after the initial. \nobreak }} % \entry typesets a paragraph consisting of the text (#1), dot leaders, and % then page number (#2) flushed to the right margin. It is used for index % and table of contents entries. The paragraph is indented by \leftskip. % % A straightforward implementation would start like this: % \def\entry#1#2{... % But this frozes the catcodes in the argument, and can cause problems to % @code, which sets - active. This problem was fixed by a kludge--- % ``-'' was active throughout whole index, but this isn't really right. % % The right solution is to prevent \entry from swallowing the whole text. % --kasal, 21nov03 \def\entry{% \begingroup % % Start a new paragraph if necessary, so our assignments below can't % affect previous text. \par % % Do not fill out the last line with white space. \parfillskip = 0in % % No extra space above this paragraph. \parskip = 0in % % Do not prefer a separate line ending with a hyphen to fewer lines. \finalhyphendemerits = 0 % % \hangindent is only relevant when the entry text and page number % don't both fit on one line. In that case, bob suggests starting the % dots pretty far over on the line. Unfortunately, a large % indentation looks wrong when the entry text itself is broken across % lines. So we use a small indentation and put up with long leaders. % % \hangafter is reset to 1 (which is the value we want) at the start % of each paragraph, so we need not do anything with that. \hangindent = 2em % % When the entry text needs to be broken, just fill out the first line % with blank space. \rightskip = 0pt plus1fil % % A bit of stretch before each entry for the benefit of balancing % columns. \vskip 0pt plus1pt % % Swallow the left brace of the text (first parameter): \afterassignment\doentry \let\temp = } \def\doentry{% \bgroup % Instead of the swallowed brace. \noindent \aftergroup\finishentry % And now comes the text of the entry. } \def\finishentry#1{% % #1 is the page number. % % The following is kludged to not output a line of dots in the index if % there are no page numbers. The next person who breaks this will be % cursed by a Unix daemon. \def\tempa{{\rm }}% \def\tempb{#1}% \edef\tempc{\tempa}% \edef\tempd{\tempb}% \ifx\tempc\tempd \ % \else % % If we must, put the page number on a line of its own, and fill out % this line with blank space. (The \hfil is overwhelmed with the % fill leaders glue in \indexdotfill if the page number does fit.) \hfil\penalty50 \null\nobreak\indexdotfill % Have leaders before the page number. % % The `\ ' here is removed by the implicit \unskip that TeX does as % part of (the primitive) \par. Without it, a spurious underfull % \hbox ensues. \ifpdf \pdfgettoks#1.% \ \the\toksA \else \ #1% \fi \fi \par \endgroup } % Like \dotfill except takes at least 1 em. \def\indexdotfill{\cleaders \hbox{$\mathsurround=0pt \mkern1.5mu ${\it .}$ \mkern1.5mu$}\hskip 1em plus 1fill} \def\primary #1{\line{#1\hfil}} \newskip\secondaryindent \secondaryindent=0.5cm \def\secondary#1#2{{% \parfillskip=0in \parskip=0in \hangindent=1in \hangafter=1 \noindent\hskip\secondaryindent\hbox{#1}\indexdotfill \ifpdf \pdfgettoks#2.\ \the\toksA % The page number ends the paragraph. \else #2 \fi \par }} % Define two-column mode, which we use to typeset indexes. % Adapted from the TeXbook, page 416, which is to say, % the manmac.tex format used to print the TeXbook itself. \catcode`\@=11 \newbox\partialpage \newdimen\doublecolumnhsize \def\begindoublecolumns{\begingroup % ended by \enddoublecolumns % Grab any single-column material above us. \output = {% % % Here is a possibility not foreseen in manmac: if we accumulate a % whole lot of material, we might end up calling this \output % routine twice in a row (see the doublecol-lose test, which is % essentially a couple of indexes with @setchapternewpage off). In % that case we just ship out what is in \partialpage with the normal % output routine. Generally, \partialpage will be empty when this % runs and this will be a no-op. See the indexspread.tex test case. \ifvoid\partialpage \else \onepageout{\pagecontents\partialpage}% \fi % \global\setbox\partialpage = \vbox{% % Unvbox the main output page. \unvbox\PAGE \kern-\topskip \kern\baselineskip }% }% \eject % run that output routine to set \partialpage % % Use the double-column output routine for subsequent pages. \output = {\doublecolumnout}% % % Change the page size parameters. We could do this once outside this % routine, in each of @smallbook, @afourpaper, and the default 8.5x11 % format, but then we repeat the same computation. Repeating a couple % of assignments once per index is clearly meaningless for the % execution time, so we may as well do it in one place. % % First we halve the line length, less a little for the gutter between % the columns. We compute the gutter based on the line length, so it % changes automatically with the paper format. The magic constant % below is chosen so that the gutter has the same value (well, +-<1pt) % as it did when we hard-coded it. % % We put the result in a separate register, \doublecolumhsize, so we % can restore it in \pagesofar, after \hsize itself has (potentially) % been clobbered. % \doublecolumnhsize = \hsize \advance\doublecolumnhsize by -.04154\hsize \divide\doublecolumnhsize by 2 \hsize = \doublecolumnhsize % % Double the \vsize as well. (We don't need a separate register here, % since nobody clobbers \vsize.) \vsize = 2\vsize } % The double-column output routine for all double-column pages except % the last. % \def\doublecolumnout{% \splittopskip=\topskip \splitmaxdepth=\maxdepth % Get the available space for the double columns -- the normal % (undoubled) page height minus any material left over from the % previous page. \dimen@ = \vsize \divide\dimen@ by 2 \advance\dimen@ by -\ht\partialpage % % box0 will be the left-hand column, box2 the right. \setbox0=\vsplit255 to\dimen@ \setbox2=\vsplit255 to\dimen@ \onepageout\pagesofar \unvbox255 \penalty\outputpenalty } % % Re-output the contents of the output page -- any previous material, % followed by the two boxes we just split, in box0 and box2. \def\pagesofar{% \unvbox\partialpage % \hsize = \doublecolumnhsize \wd0=\hsize \wd2=\hsize \hbox to\pagewidth{\box0\hfil\box2}% } % % All done with double columns. \def\enddoublecolumns{% \output = {% % Split the last of the double-column material. Leave it on the % current page, no automatic page break. \balancecolumns % % If we end up splitting too much material for the current page, % though, there will be another page break right after this \output % invocation ends. Having called \balancecolumns once, we do not % want to call it again. Therefore, reset \output to its normal % definition right away. (We hope \balancecolumns will never be % called on to balance too much material, but if it is, this makes % the output somewhat more palatable.) \global\output = {\onepageout{\pagecontents\PAGE}}% }% \eject \endgroup % started in \begindoublecolumns % % \pagegoal was set to the doubled \vsize above, since we restarted % the current page. We're now back to normal single-column % typesetting, so reset \pagegoal to the normal \vsize (after the % \endgroup where \vsize got restored). \pagegoal = \vsize } % % Called at the end of the double column material. \def\balancecolumns{% \setbox0 = \vbox{\unvbox255}% like \box255 but more efficient, see p.120. \dimen@ = \ht0 \advance\dimen@ by \topskip \advance\dimen@ by-\baselineskip \divide\dimen@ by 2 % target to split to %debug\message{final 2-column material height=\the\ht0, target=\the\dimen@.}% \splittopskip = \topskip % Loop until we get a decent breakpoint. {% \vbadness = 10000 \loop \global\setbox3 = \copy0 \global\setbox1 = \vsplit3 to \dimen@ \ifdim\ht3>\dimen@ \global\advance\dimen@ by 1pt \repeat }% %debug\message{split to \the\dimen@, column heights: \the\ht1, \the\ht3.}% \setbox0=\vbox to\dimen@{\unvbox1}% \setbox2=\vbox to\dimen@{\unvbox3}% % \pagesofar } \catcode`\@ = \other \message{sectioning,} % Chapters, sections, etc. % \unnumberedno is an oxymoron, of course. But we count the unnumbered % sections so that we can refer to them unambiguously in the pdf % outlines by their "section number". We avoid collisions with chapter % numbers by starting them at 10000. (If a document ever has 10000 % chapters, we're in trouble anyway, I'm sure.) \newcount\unnumberedno \unnumberedno = 10000 \newcount\chapno \newcount\secno \secno=0 \newcount\subsecno \subsecno=0 \newcount\subsubsecno \subsubsecno=0 % This counter is funny since it counts through charcodes of letters A, B, ... \newcount\appendixno \appendixno = `\@ % % \def\appendixletter{\char\the\appendixno} % We do the following ugly conditional instead of the above simple % construct for the sake of pdftex, which needs the actual % letter in the expansion, not just typeset. % \def\appendixletter{% \ifnum\appendixno=`A A% \else\ifnum\appendixno=`B B% \else\ifnum\appendixno=`C C% \else\ifnum\appendixno=`D D% \else\ifnum\appendixno=`E E% \else\ifnum\appendixno=`F F% \else\ifnum\appendixno=`G G% \else\ifnum\appendixno=`H H% \else\ifnum\appendixno=`I I% \else\ifnum\appendixno=`J J% \else\ifnum\appendixno=`K K% \else\ifnum\appendixno=`L L% \else\ifnum\appendixno=`M M% \else\ifnum\appendixno=`N N% \else\ifnum\appendixno=`O O% \else\ifnum\appendixno=`P P% \else\ifnum\appendixno=`Q Q% \else\ifnum\appendixno=`R R% \else\ifnum\appendixno=`S S% \else\ifnum\appendixno=`T T% \else\ifnum\appendixno=`U U% \else\ifnum\appendixno=`V V% \else\ifnum\appendixno=`W W% \else\ifnum\appendixno=`X X% \else\ifnum\appendixno=`Y Y% \else\ifnum\appendixno=`Z Z% % The \the is necessary, despite appearances, because \appendixletter is % expanded while writing the .toc file. \char\appendixno is not % expandable, thus it is written literally, thus all appendixes come out % with the same letter (or @) in the toc without it. \else\char\the\appendixno \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} % Each @chapter defines this as the name of the chapter. % page headings and footings can use it. @section does likewise. % However, they are not reliable, because we don't use marks. \def\thischapter{} \def\thissection{} \newcount\absseclevel % used to calculate proper heading level \newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count % @raisesections: treat @section as chapter, @subsection as section, etc. \def\raisesections{\global\advance\secbase by -1} \let\up=\raisesections % original BFox name % @lowersections: treat @chapter as section, @section as subsection, etc. \def\lowersections{\global\advance\secbase by 1} \let\down=\lowersections % original BFox name % we only have subsub. \chardef\maxseclevel = 3 % % A numbered section within an unnumbered changes to unnumbered too. % To achive this, remember the "biggest" unnum. sec. we are currently in: \chardef\unmlevel = \maxseclevel % % Trace whether the current chapter is an appendix or not: % \chapheadtype is "N" or "A", unnumbered chapters are ignored. \def\chapheadtype{N} % Choose a heading macro % #1 is heading type % #2 is heading level % #3 is text for heading \def\genhead#1#2#3{% % Compute the abs. sec. level: \absseclevel=#2 \advance\absseclevel by \secbase % Make sure \absseclevel doesn't fall outside the range: \ifnum \absseclevel < 0 \absseclevel = 0 \else \ifnum \absseclevel > 3 \absseclevel = 3 \fi \fi % The heading type: \def\headtype{#1}% \if \headtype U% \ifnum \absseclevel < \unmlevel \chardef\unmlevel = \absseclevel \fi \else % Check for appendix sections: \ifnum \absseclevel = 0 \edef\chapheadtype{\headtype}% \else \if \headtype A\if \chapheadtype N% \errmessage{@appendix... within a non-appendix chapter}% \fi\fi \fi % Check for numbered within unnumbered: \ifnum \absseclevel > \unmlevel \def\headtype{U}% \else \chardef\unmlevel = 3 \fi \fi % Now print the heading: \if \headtype U% \ifcase\absseclevel \unnumberedzzz{#3}% \or \unnumberedseczzz{#3}% \or \unnumberedsubseczzz{#3}% \or \unnumberedsubsubseczzz{#3}% \fi \else \if \headtype A% \ifcase\absseclevel \appendixzzz{#3}% \or \appendixsectionzzz{#3}% \or \appendixsubseczzz{#3}% \or \appendixsubsubseczzz{#3}% \fi \else \ifcase\absseclevel \chapterzzz{#3}% \or \seczzz{#3}% \or \numberedsubseczzz{#3}% \or \numberedsubsubseczzz{#3}% \fi \fi \fi \suppressfirstparagraphindent } % an interface: \def\numhead{\genhead N} \def\apphead{\genhead A} \def\unnmhead{\genhead U} % @chapter, @appendix, @unnumbered. Increment top-level counter, reset % all lower-level sectioning counters to zero. % % Also set \chaplevelprefix, which we prepend to @float sequence numbers % (e.g., figures), q.v. By default (before any chapter), that is empty. \let\chaplevelprefix = \empty % \outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz \def\chapterzzz#1{% % section resetting is \global in case the chapter is in a group, such % as an @include file. \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\chapno by 1 % % Used for \float. \gdef\chaplevelprefix{\the\chapno.}% \resetallfloatnos % \message{\putwordChapter\space \the\chapno}% % % Write the actual heading. \chapmacro{#1}{Ynumbered}{\the\chapno}% % % So @section and the like are numbered underneath this chapter. \global\let\section = \numberedsec \global\let\subsection = \numberedsubsec \global\let\subsubsection = \numberedsubsubsec } \outer\parseargdef\appendix{\apphead0{#1}} % normally apphead0 calls appendixzzz \def\appendixzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\appendixno by 1 \gdef\chaplevelprefix{\appendixletter.}% \resetallfloatnos % \def\appendixnum{\putwordAppendix\space \appendixletter}% \message{\appendixnum}% % \chapmacro{#1}{Yappendix}{\appendixletter}% % \global\let\section = \appendixsec \global\let\subsection = \appendixsubsec \global\let\subsubsection = \appendixsubsubsec } \outer\parseargdef\unnumbered{\unnmhead0{#1}} % normally unnmhead0 calls unnumberedzzz \def\unnumberedzzz#1{% \global\secno=0 \global\subsecno=0 \global\subsubsecno=0 \global\advance\unnumberedno by 1 % % Since an unnumbered has no number, no prefix for figures. \global\let\chaplevelprefix = \empty \resetallfloatnos % % This used to be simply \message{#1}, but TeX fully expands the % argument to \message. Therefore, if #1 contained @-commands, TeX % expanded them. For example, in `@unnumbered The @cite{Book}', TeX % expanded @cite (which turns out to cause errors because \cite is meant % to be executed, not expanded). % % Anyway, we don't want the fully-expanded definition of @cite to appear % as a result of the \message, we just want `@cite' itself. We use % \the to achieve this: TeX expands \the only once, % simply yielding the contents of . (We also do this for % the toc entries.) \toks0 = {#1}% \message{(\the\toks0)}% % \chapmacro{#1}{Ynothing}{\the\unnumberedno}% % \global\let\section = \unnumberedsec \global\let\subsection = \unnumberedsubsec \global\let\subsubsection = \unnumberedsubsubsec } % @centerchap is like @unnumbered, but the heading is centered. \outer\parseargdef\centerchap{% % Well, we could do the following in a group, but that would break % an assumption that \chapmacro is called at the outermost level. % Thus we are safer this way: --kasal, 24feb04 \let\centerparametersmaybe = \centerparameters \unnmhead0{#1}% \let\centerparametersmaybe = \relax } % @top is like @unnumbered. \let\top\unnumbered % Sections. \outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz \def\seczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}% } \outer\parseargdef\appendixsection{\apphead1{#1}} % normally calls appendixsectionzzz \def\appendixsectionzzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}% } \let\appendixsec\appendixsection \outer\parseargdef\unnumberedsec{\unnmhead1{#1}} % normally calls unnumberedseczzz \def\unnumberedseczzz#1{% \global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1 \sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno.\the\secno}% } % Subsections. \outer\parseargdef\numberedsubsec{\numhead2{#1}} % normally calls numberedsubseczzz \def\numberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}% } \outer\parseargdef\appendixsubsec{\apphead2{#1}} % normally calls appendixsubseczzz \def\appendixsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno}% } \outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}} %normally calls unnumberedsubseczzz \def\unnumberedsubseczzz#1{% \global\subsubsecno=0 \global\advance\subsecno by 1 \sectionheading{#1}{subsec}{Ynothing}% {\the\unnumberedno.\the\secno.\the\subsecno}% } % Subsubsections. \outer\parseargdef\numberedsubsubsec{\numhead3{#1}} % normally numberedsubsubseczzz \def\numberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynumbered}% {\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}% } \outer\parseargdef\appendixsubsubsec{\apphead3{#1}} % normally appendixsubsubseczzz \def\appendixsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Yappendix}% {\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}% } \outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}} %normally unnumberedsubsubseczzz \def\unnumberedsubsubseczzz#1{% \global\advance\subsubsecno by 1 \sectionheading{#1}{subsubsec}{Ynothing}% {\the\unnumberedno.\the\secno.\the\subsecno.\the\subsubsecno}% } % These macros control what the section commands do, according % to what kind of chapter we are in (ordinary, appendix, or unnumbered). % Define them by default for a numbered chapter. \let\section = \numberedsec \let\subsection = \numberedsubsec \let\subsubsection = \numberedsubsubsec % Define @majorheading, @heading and @subheading % NOTE on use of \vbox for chapter headings, section headings, and such: % 1) We use \vbox rather than the earlier \line to permit % overlong headings to fold. % 2) \hyphenpenalty is set to 10000 because hyphenation in a % heading is obnoxious; this forbids it. % 3) Likewise, headings look best if no \parindent is used, and % if justification is not attempted. Hence \raggedright. \def\majorheading{% {\advance\chapheadingskip by 10pt \chapbreak }% \parsearg\chapheadingzzz } \def\chapheading{\chapbreak \parsearg\chapheadingzzz} \def\chapheadingzzz#1{% {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt\raggedright \rm #1\hfill}}% \bigskip \par\penalty 200\relax \suppressfirstparagraphindent } % @heading, @subheading, @subsubheading. \parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{} \suppressfirstparagraphindent} \parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{} \suppressfirstparagraphindent} \parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{} \suppressfirstparagraphindent} % These macros generate a chapter, section, etc. heading only % (including whitespace, linebreaking, etc. around it), % given all the information in convenient, parsed form. %%% Args are the skip and penalty (usually negative) \def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi} %%% Define plain chapter starts, and page on/off switching for it % Parameter controlling skip before chapter headings (if needed) \newskip\chapheadingskip \def\chapbreak{\dobreak \chapheadingskip {-4000}} \def\chappager{\par\vfill\supereject} \def\chapoddpage{\chappager \ifodd\pageno \else \hbox to 0pt{} \chappager\fi} \def\setchapternewpage #1 {\csname CHAPPAG#1\endcsname} \def\CHAPPAGoff{% \global\let\contentsalignmacro = \chappager \global\let\pchapsepmacro=\chapbreak \global\let\pagealignmacro=\chappager} \def\CHAPPAGon{% \global\let\contentsalignmacro = \chappager \global\let\pchapsepmacro=\chappager \global\let\pagealignmacro=\chappager \global\def\HEADINGSon{\HEADINGSsingle}} \def\CHAPPAGodd{% \global\let\contentsalignmacro = \chapoddpage \global\let\pchapsepmacro=\chapoddpage \global\let\pagealignmacro=\chapoddpage \global\def\HEADINGSon{\HEADINGSdouble}} \CHAPPAGon % Chapter opening. % % #1 is the text, #2 is the section type (Ynumbered, Ynothing, % Yappendix, Yomitfromtoc), #3 the chapter number. % % To test against our argument. \def\Ynothingkeyword{Ynothing} \def\Yomitfromtockeyword{Yomitfromtoc} \def\Yappendixkeyword{Yappendix} % \def\chapmacro#1#2#3{% \pchapsepmacro {% \chapfonts \rm % % Have to define \thissection before calling \donoderef, because the % xref code eventually uses it. On the other hand, it has to be called % after \pchapsepmacro, or the headline will change too soon. \gdef\thissection{#1}% \gdef\thischaptername{#1}% % % Only insert the separating space if we have a chapter/appendix % number, and don't print the unnumbered ``number''. \def\temptype{#2}% \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unnchap}% \def\thischapter{#1}% \else\ifx\temptype\Yomitfromtockeyword \setbox0 = \hbox{}% contents like unnumbered, but no toc entry \def\toctype{omit}% \xdef\thischapter{}% \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{\putwordAppendix{} #3\enspace}% \def\toctype{app}% % We don't substitute the actual chapter name into \thischapter % because we don't want its macros evaluated now. And we don't % use \thissection because that changes with each section. % \xdef\thischapter{\putwordAppendix{} \appendixletter: \noexpand\thischaptername}% \else \setbox0 = \hbox{#3\enspace}% \def\toctype{numchap}% \xdef\thischapter{\putwordChapter{} \the\chapno: \noexpand\thischaptername}% \fi\fi\fi % % Write the toc entry for this chapter. Must come before the % \donoderef, because we include the current node name in the toc % entry, and \donoderef resets it to empty. \writetocentry{\toctype}{#1}{#3}% % % For pdftex, we have to write out the node definition (aka, make % the pdfdest) after any page break, but before the actual text has % been typeset. If the destination for the pdf outline is after the % text, then jumping from the outline may wind up with the text not % being visible, for instance under high magnification. \donoderef{#2}% % % Typeset the actual heading. \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright \hangindent=\wd0 \centerparametersmaybe \unhbox0 #1\par}% }% \nobreak\bigskip % no page break after a chapter title \nobreak } % @centerchap -- centered and unnumbered. \let\centerparametersmaybe = \relax \def\centerparameters{% \advance\rightskip by 3\rightskip \leftskip = \rightskip \parfillskip = 0pt } % I don't think this chapter style is supported any more, so I'm not % updating it with the new noderef stuff. We'll see. --karl, 11aug03. % \def\setchapterstyle #1 {\csname CHAPF#1\endcsname} % \def\unnchfopen #1{% \chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt\raggedright \rm #1\hfill}}\bigskip \par\nobreak } \def\chfopen #1#2{\chapoddpage {\chapfonts \vbox to 3in{\vfil \hbox to\hsize{\hfil #2} \hbox to\hsize{\hfil #1} \vfil}}% \par\penalty 5000 % } \def\centerchfopen #1{% \chapoddpage {\chapfonts \vbox{\hyphenpenalty=10000\tolerance=5000 \parindent=0pt \hfill {\rm #1}\hfill}}\bigskip \par\nobreak } \def\CHAPFopen{% \global\let\chapmacro=\chfopen \global\let\centerchapmacro=\centerchfopen} % Section titles. These macros combine the section number parts and % call the generic \sectionheading to do the printing. % \newskip\secheadingskip \def\secheadingbreak{\dobreak \secheadingskip{-1000}} % Subsection titles. \newskip\subsecheadingskip \def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}} % Subsubsection titles. \def\subsubsecheadingskip{\subsecheadingskip} \def\subsubsecheadingbreak{\subsecheadingbreak} % Print any size, any type, section title. % % #1 is the text, #2 is the section level (sec/subsec/subsubsec), #3 is % the section type for xrefs (Ynumbered, Ynothing, Yappendix), #4 is the % section number. % \def\sectionheading#1#2#3#4{% {% % Switch to the right set of fonts. \csname #2fonts\endcsname \rm % % Insert space above the heading. \csname #2headingbreak\endcsname % % Only insert the space after the number if we have a section number. \def\sectionlevel{#2}% \def\temptype{#3}% % \ifx\temptype\Ynothingkeyword \setbox0 = \hbox{}% \def\toctype{unn}% \gdef\thissection{#1}% \else\ifx\temptype\Yomitfromtockeyword % for @headings -- no section number, don't include in toc, % and don't redefine \thissection. \setbox0 = \hbox{}% \def\toctype{omit}% \let\sectionlevel=\empty \else\ifx\temptype\Yappendixkeyword \setbox0 = \hbox{#4\enspace}% \def\toctype{app}% \gdef\thissection{#1}% \else \setbox0 = \hbox{#4\enspace}% \def\toctype{num}% \gdef\thissection{#1}% \fi\fi\fi % % Write the toc entry (before \donoderef). See comments in \chfplain. \writetocentry{\toctype\sectionlevel}{#1}{#4}% % % Write the node reference (= pdf destination for pdftex). % Again, see comments in \chfplain. \donoderef{#3}% % % Output the actual section heading. \vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \raggedright \hangindent=\wd0 % zero if no section number \unhbox0 #1}% }% % Add extra space after the heading -- half of whatever came above it. % Don't allow stretch, though. \kern .5 \csname #2headingskip\endcsname % % Do not let the kern be a potential breakpoint, as it would be if it % was followed by glue. \nobreak % % We'll almost certainly start a paragraph next, so don't let that % glue accumulate. (Not a breakpoint because it's preceded by a % discardable item.) \vskip-\parskip % % This \nobreak is purely so the last item on the list is a \penalty % of 10000. This is so other code, for instance \parsebodycommon, can % check for and avoid allowing breakpoints. Otherwise, it would % insert a valid breakpoint between: % @section sec-whatever % @deffn def-whatever \nobreak } \message{toc,} % Table of contents. \newwrite\tocfile % Write an entry to the toc file, opening it if necessary. % Called from @chapter, etc. % % Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno} % We append the current node name (if any) and page number as additional % arguments for the \{chap,sec,...}entry macros which will eventually % read this. The node name is used in the pdf outlines as the % destination to jump to. % % We open the .toc file for writing here instead of at @setfilename (or % any other fixed time) so that @contents can be anywhere in the document. % But if #1 is `omit', then we don't do anything. This is used for the % table of contents chapter openings themselves. % \newif\iftocfileopened \def\omitkeyword{omit}% % \def\writetocentry#1#2#3{% \edef\writetoctype{#1}% \ifx\writetoctype\omitkeyword \else \iftocfileopened\else \immediate\openout\tocfile = \jobname.toc \global\tocfileopenedtrue \fi % \iflinks \toks0 = {#2}% \toks2 = \expandafter{\lastnode}% \edef\temp{\write\tocfile{\realbackslash #1entry{\the\toks0}{#3}% {\the\toks2}{\noexpand\folio}}}% \temp \fi \fi % % Tell \shipout to create a pdf destination on each page, if we're % writing pdf. These are used in the table of contents. We can't % just write one on every page because the title pages are numbered % 1 and 2 (the page numbers aren't printed), and so are the first % two pages of the document. Thus, we'd have two destinations named % `1', and two named `2'. \ifpdf \global\pdfmakepagedesttrue \fi } \newskip\contentsrightmargin \contentsrightmargin=1in \newcount\savepageno \newcount\lastnegativepageno \lastnegativepageno = -1 % Prepare to read what we've written to \tocfile. % \def\startcontents#1{% % If @setchapternewpage on, and @headings double, the contents should % start on an odd page, unlike chapters. Thus, we maintain % \contentsalignmacro in parallel with \pagealignmacro. % From: Torbjorn Granlund \contentsalignmacro \immediate\closeout\tocfile % % Don't need to put `Contents' or `Short Contents' in the headline. % It is abundantly clear what they are. \def\thischapter{}% \chapmacro{#1}{Yomitfromtoc}{}% % \savepageno = \pageno \begingroup % Set up to handle contents files properly. \catcode`\\=0 \catcode`\{=1 \catcode`\}=2 \catcode`\@=11 % We can't do this, because then an actual ^ in a section % title fails, e.g., @chapter ^ -- exponentiation. --karl, 9jul97. %\catcode`\^=7 % to see ^^e4 as \"a etc. juha@piuha.ydi.vtt.fi \raggedbottom % Worry more about breakpoints than the bottom. \advance\hsize by -\contentsrightmargin % Don't use the full line length. % % Roman numerals for page numbers. \ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi } % Normal (long) toc. \def\contents{% \startcontents{\putwordTOC}% \openin 1 \jobname.toc \ifeof 1 \else \input \jobname.toc \fi \vfill \eject \contentsalignmacro % in case @setchapternewpage odd is in effect \ifeof 1 \else \pdfmakeoutlines \fi \closein 1 \endgroup \lastnegativepageno = \pageno \global\pageno = \savepageno } % And just the chapters. \def\summarycontents{% \startcontents{\putwordShortTOC}% % \let\numchapentry = \shortchapentry \let\appentry = \shortchapentry \let\unnchapentry = \shortunnchapentry % We want a true roman here for the page numbers. \secfonts \let\rm=\shortcontrm \let\bf=\shortcontbf \let\sl=\shortcontsl \let\tt=\shortconttt \rm \hyphenpenalty = 10000 \advance\baselineskip by 1pt % Open it up a little. \def\numsecentry##1##2##3##4{} \let\appsecentry = \numsecentry \let\unnsecentry = \numsecentry \let\numsubsecentry = \numsecentry \let\appsubsecentry = \numsecentry \let\unnsubsecentry = \numsecentry \let\numsubsubsecentry = \numsecentry \let\appsubsubsecentry = \numsecentry \let\unnsubsubsecentry = \numsecentry \openin 1 \jobname.toc \ifeof 1 \else \input \jobname.toc \fi \closein 1 \vfill \eject \contentsalignmacro % in case @setchapternewpage odd is in effect \endgroup \lastnegativepageno = \pageno \global\pageno = \savepageno } \let\shortcontents = \summarycontents % Typeset the label for a chapter or appendix for the short contents. % The arg is, e.g., `A' for an appendix, or `3' for a chapter. % \def\shortchaplabel#1{% % This space should be enough, since a single number is .5em, and the % widest letter (M) is 1em, at least in the Computer Modern fonts. % But use \hss just in case. % (This space doesn't include the extra space that gets added after % the label; that gets put in by \shortchapentry above.) % % We'd like to right-justify chapter numbers, but that looks strange % with appendix letters. And right-justifying numbers and % left-justifying letters looks strange when there is less than 10 % chapters. Have to read the whole toc once to know how many chapters % there are before deciding ... \hbox to 1em{#1\hss}% } % These macros generate individual entries in the table of contents. % The first argument is the chapter or section name. % The last argument is the page number. % The arguments in between are the chapter number, section number, ... % Chapters, in the main contents. \def\numchapentry#1#2#3#4{\dochapentry{#2\labelspace#1}{#4}} % % Chapters, in the short toc. % See comments in \dochapentry re vbox and related settings. \def\shortchapentry#1#2#3#4{% \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}% } % Appendices, in the main contents. % Need the word Appendix, and a fixed-size box. % \def\appendixbox#1{% % We use M since it's probably the widest letter. \setbox0 = \hbox{\putwordAppendix{} M}% \hbox to \wd0{\putwordAppendix{} #1\hss}} % \def\appentry#1#2#3#4{\dochapentry{\appendixbox{#2}\labelspace#1}{#4}} % Unnumbered chapters. \def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}} \def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}} % Sections. \def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}} \let\appsecentry=\numsecentry \def\unnsecentry#1#2#3#4{\dosecentry{#1}{#4}} % Subsections. \def\numsubsecentry#1#2#3#4{\dosubsecentry{#2\labelspace#1}{#4}} \let\appsubsecentry=\numsubsecentry \def\unnsubsecentry#1#2#3#4{\dosubsecentry{#1}{#4}} % And subsubsections. \def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#2\labelspace#1}{#4}} \let\appsubsubsecentry=\numsubsubsecentry \def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#4}} % This parameter controls the indentation of the various levels. % Same as \defaultparindent. \newdimen\tocindent \tocindent = 15pt % Now for the actual typesetting. In all these, #1 is the text and #2 is the % page number. % % If the toc has to be broken over pages, we want it to be at chapters % if at all possible; hence the \penalty. \def\dochapentry#1#2{% \penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip \begingroup \chapentryfonts \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup \nobreak\vskip .25\baselineskip plus.1\baselineskip } \def\dosecentry#1#2{\begingroup \secentryfonts \leftskip=\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsecentry#1#2{\begingroup \subsecentryfonts \leftskip=2\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} \def\dosubsubsecentry#1#2{\begingroup \subsubsecentryfonts \leftskip=3\tocindent \tocentry{#1}{\dopageno\bgroup#2\egroup}% \endgroup} % We use the same \entry macro as for the index entries. \let\tocentry = \entry % Space between chapter (or whatever) number and the title. \def\labelspace{\hskip1em \relax} \def\dopageno#1{{\rm #1}} \def\doshortpageno#1{{\rm #1}} \def\chapentryfonts{\secfonts \rm} \def\secentryfonts{\textfonts} \def\subsecentryfonts{\textfonts} \def\subsubsecentryfonts{\textfonts} \message{environments,} % @foo ... @end foo. % @point{}, @result{}, @expansion{}, @print{}, @equiv{}. % % Since these characters are used in examples, it should be an even number of % \tt widths. Each \tt character is 1en, so two makes it 1em. % \def\point{$\star$} \def\result{\leavevmode\raise.15ex\hbox to 1em{\hfil$\Rightarrow$\hfil}} \def\expansion{\leavevmode\raise.1ex\hbox to 1em{\hfil$\mapsto$\hfil}} \def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}} \def\equiv{\leavevmode\lower.1ex\hbox to 1em{\hfil$\ptexequiv$\hfil}} % The @error{} command. % Adapted from the TeXbook's \boxit. % \newbox\errorbox % {\tentt \global\dimen0 = 3em}% Width of the box. \dimen2 = .55pt % Thickness of rules % The text. (`r' is open on the right, `e' somewhat less so on the left.) \setbox0 = \hbox{\kern-.75pt \tensf error\kern-1.5pt} % \setbox\errorbox=\hbox to \dimen0{\hfil \hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right. \advance\hsize by -2\dimen2 % Rules. \vbox{% \hrule height\dimen2 \hbox{\vrule width\dimen2 \kern3pt % Space to left of text. \vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below. \kern3pt\vrule width\dimen2}% Space to right. \hrule height\dimen2} \hfil} % \def\error{\leavevmode\lower.7ex\copy\errorbox} % @tex ... @end tex escapes into raw Tex temporarily. % One exception: @ is still an escape character, so that @end tex works. % But \@ or @@ will get a plain tex @ character. \envdef\tex{% \catcode `\\=0 \catcode `\{=1 \catcode `\}=2 \catcode `\$=3 \catcode `\&=4 \catcode `\#=6 \catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie \catcode `\%=14 \catcode `\+=\other \catcode `\"=\other \catcode `\|=\other \catcode `\<=\other \catcode `\>=\other \escapechar=`\\ % \let\b=\ptexb \let\bullet=\ptexbullet \let\c=\ptexc \let\,=\ptexcomma \let\.=\ptexdot \let\dots=\ptexdots \let\equiv=\ptexequiv \let\!=\ptexexclam \let\i=\ptexi \let\indent=\ptexindent \let\noindent=\ptexnoindent \let\{=\ptexlbrace \let\+=\tabalign \let\}=\ptexrbrace \let\/=\ptexslash \let\*=\ptexstar \let\t=\ptext % \def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}% \def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}% \def\@{@}% } % There is no need to define \Etex. % Define @lisp ... @end lisp. % @lisp environment forms a group so it can rebind things, % including the definition of @end lisp (which normally is erroneous). % Amount to narrow the margins by for @lisp. \newskip\lispnarrowing \lispnarrowing=0.4in % This is the definition that ^^M gets inside @lisp, @example, and other % such environments. \null is better than a space, since it doesn't % have any width. \def\lisppar{\null\endgraf} % This space is always present above and below environments. \newskip\envskipamount \envskipamount = 0pt % Make spacing and below environment symmetrical. We use \parskip here % to help in doing that, since in @example-like environments \parskip % is reset to zero; thus the \afterenvbreak inserts no space -- but the % start of the next paragraph will insert \parskip. % \def\aboveenvbreak{{% % =10000 instead of <10000 because of a special case in \itemzzz, q.v. \ifnum \lastpenalty=10000 \else \advance\envskipamount by \parskip \endgraf \ifdim\lastskip<\envskipamount \removelastskip % it's not a good place to break if the last penalty was \nobreak % or better ... \ifnum\lastpenalty<10000 \penalty-50 \fi \vskip\envskipamount \fi \fi }} \let\afterenvbreak = \aboveenvbreak % \nonarrowing is a flag. If "set", @lisp etc don't narrow margins. \let\nonarrowing=\relax % @cartouche ... @end cartouche: draw rectangle w/rounded corners around % environment contents. \font\circle=lcircle10 \newdimen\circthick \newdimen\cartouter\newdimen\cartinner \newskip\normbskip\newskip\normpskip\newskip\normlskip \circthick=\fontdimen8\circle % \def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth \def\ctr{{\hskip 6pt\circle\char'010}} \def\cbl{{\circle\char'012\hskip -6pt}} \def\cbr{{\hskip 6pt\circle\char'011}} \def\carttop{\hbox to \cartouter{\hskip\lskip \ctl\leaders\hrule height\circthick\hfil\ctr \hskip\rskip}} \def\cartbot{\hbox to \cartouter{\hskip\lskip \cbl\leaders\hrule height\circthick\hfil\cbr \hskip\rskip}} % \newskip\lskip\newskip\rskip \envdef\cartouche{% \ifhmode\par\fi % can't be in the midst of a paragraph. \startsavinginserts \lskip=\leftskip \rskip=\rightskip \leftskip=0pt\rightskip=0pt % we want these *outside*. \cartinner=\hsize \advance\cartinner by-\lskip \advance\cartinner by-\rskip \cartouter=\hsize \advance\cartouter by 18.4pt % allow for 3pt kerns on either % side, and for 6pt waste from % each corner char, and rule thickness \normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip % Flag to tell @lisp, etc., not to narrow margin. \let\nonarrowing=\comment \vbox\bgroup \baselineskip=0pt\parskip=0pt\lineskip=0pt \carttop \hbox\bgroup \hskip\lskip \vrule\kern3pt \vbox\bgroup \kern3pt \hsize=\cartinner \baselineskip=\normbskip \lineskip=\normlskip \parskip=\normpskip \vskip -\parskip \comment % For explanation, see the end of \def\group. } \def\Ecartouche{% \ifhmode\par\fi \kern3pt \egroup \kern3pt\vrule \hskip\rskip \egroup \cartbot \egroup \checkinserts } % This macro is called at the beginning of all the @example variants, % inside a group. \def\nonfillstart{% \aboveenvbreak \hfuzz = 12pt % Don't be fussy \sepspaces % Make spaces be word-separators rather than space tokens. \let\par = \lisppar % don't ignore blank lines \obeylines % each line of input is a line of output \parskip = 0pt \parindent = 0pt \emergencystretch = 0pt % don't try to avoid overfull boxes % @cartouche defines \nonarrowing to inhibit narrowing % at next level down. \ifx\nonarrowing\relax \advance \leftskip by \lispnarrowing \exdentamount=\lispnarrowing \fi \let\exdent=\nofillexdent } % If you want all examples etc. small: @set dispenvsize small. % If you want even small examples the full size: @set dispenvsize nosmall. % This affects the following displayed environments: % @example, @display, @format, @lisp % \def\smallword{small} \def\nosmallword{nosmall} \let\SETdispenvsize\relax \def\setnormaldispenv{% \ifx\SETdispenvsize\smallword \smallexamplefonts \rm \fi } \def\setsmalldispenv{% \ifx\SETdispenvsize\nosmallword \else \smallexamplefonts \rm \fi } % We often define two environments, @foo and @smallfoo. % Let's do it by one command: \def\makedispenv #1#2{ \expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2} \expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2} \expandafter\let\csname E#1\endcsname \afterenvbreak \expandafter\let\csname Esmall#1\endcsname \afterenvbreak } % Define two synonyms: \def\maketwodispenvs #1#2#3{ \makedispenv{#1}{#3} \makedispenv{#2}{#3} } % @lisp: indented, narrowed, typewriter font; @example: same as @lisp. % % @smallexample and @smalllisp: use smaller fonts. % Originally contributed by Pavel@xerox. % \maketwodispenvs {lisp}{example}{% \nonfillstart \tt \let\kbdfont = \kbdexamplefont % Allow @kbd to do something special. \gobble % eat return } % @display/@smalldisplay: same as @lisp except keep current font. % \makedispenv {display}{% \nonfillstart \gobble } % @format/@smallformat: same as @display except don't narrow margins. % \makedispenv{format}{% \let\nonarrowing = t% \nonfillstart \gobble } % @flushleft: same as @format, but doesn't obey \SETdispenvsize. \envdef\flushleft{% \let\nonarrowing = t% \nonfillstart \gobble } \let\Eflushleft = \afterenvbreak % @flushright. % \envdef\flushright{% \let\nonarrowing = t% \nonfillstart \advance\leftskip by 0pt plus 1fill \gobble } \let\Eflushright = \afterenvbreak % @quotation does normal linebreaking (hence we can't use \nonfillstart) % and narrows the margins. We keep \parskip nonzero in general, since % we're doing normal filling. So, when using \aboveenvbreak and % \afterenvbreak, temporarily make \parskip 0. % \envdef\quotation{% {\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip \parindent=0pt % % @cartouche defines \nonarrowing to inhibit narrowing at next level down. \ifx\nonarrowing\relax \advance\leftskip by \lispnarrowing \advance\rightskip by \lispnarrowing \exdentamount = \lispnarrowing \let\nonarrowing = \relax \fi \parsearg\quotationlabel } % We have retained a nonzero parskip for the environment, since we're % doing normal filling. % \def\Equotation{% \par \ifx\quotationauthor\undefined\else % indent a bit. \leftline{\kern 2\leftskip \sl ---\quotationauthor}% \fi {\parskip=0pt \afterenvbreak}% } % If we're given an argument, typeset it in bold with a colon after. \def\quotationlabel#1{% \def\temp{#1}% \ifx\temp\empty \else {\bf #1: }% \fi } % LaTeX-like @verbatim...@end verbatim and @verb{...} % If we want to allow any as delimiter, % we need the curly braces so that makeinfo sees the @verb command, eg: % `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org % % [Knuth]: Donald Ervin Knuth, 1996. The TeXbook. % % [Knuth] p.344; only we need to do the other characters Texinfo sets % active too. Otherwise, they get lost as the first character on a % verbatim line. \def\dospecials{% \do\ \do\\\do\{\do\}\do\$\do\&% \do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~% \do\<\do\>\do\|\do\@\do+\do\"% } % % [Knuth] p. 380 \def\uncatcodespecials{% \def\do##1{\catcode`##1=\other}\dospecials} % % [Knuth] pp. 380,381,391 % Disable Spanish ligatures ?` and !` of \tt font \begingroup \catcode`\`=\active\gdef`{\relax\lq} \endgroup % % Setup for the @verb command. % % Eight spaces for a tab \begingroup \catcode`\^^I=\active \gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }} \endgroup % \def\setupverb{% \tt % easiest (and conventionally used) font for verbatim \def\par{\leavevmode\endgraf}% \catcode`\`=\active \tabeightspaces % Respect line breaks, % print special symbols as themselves, and % make each space count % must do in this order: \obeylines \uncatcodespecials \sepspaces } % Setup for the @verbatim environment % % Real tab expansion \newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount % \def\starttabbox{\setbox0=\hbox\bgroup} \begingroup \catcode`\^^I=\active \gdef\tabexpand{% \catcode`\^^I=\active \def^^I{\leavevmode\egroup \dimen0=\wd0 % the width so far, or since the previous tab \divide\dimen0 by\tabw \multiply\dimen0 by\tabw % compute previous multiple of \tabw \advance\dimen0 by\tabw % advance to next multiple of \tabw \wd0=\dimen0 \box0 \starttabbox }% } \endgroup \def\setupverbatim{% \nonfillstart \advance\leftskip by -\defbodyindent % Easiest (and conventionally used) font for verbatim \tt \def\par{\leavevmode\egroup\box0\endgraf}% \catcode`\`=\active \tabexpand % Respect line breaks, % print special symbols as themselves, and % make each space count % must do in this order: \obeylines \uncatcodespecials \sepspaces \everypar{\starttabbox}% } % Do the @verb magic: verbatim text is quoted by unique % delimiter characters. Before first delimiter expect a % right brace, after last delimiter expect closing brace: % % \def\doverb'{'#1'}'{#1} % % [Knuth] p. 382; only eat outer {} \begingroup \catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other \gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next] \endgroup % \def\verb{\begingroup\setupverb\doverb} % % % Do the @verbatim magic: define the macro \doverbatim so that % the (first) argument ends when '@end verbatim' is reached, ie: % % \def\doverbatim#1@end verbatim{#1} % % For Texinfo it's a lot easier than for LaTeX, % because texinfo's \verbatim doesn't stop at '\end{verbatim}': % we need not redefine '\', '{' and '}'. % % Inspired by LaTeX's verbatim command set [latex.ltx] % \begingroup \catcode`\ =\active \obeylines % % ignore everything up to the first ^^M, that's the newline at the end % of the @verbatim input line itself. Otherwise we get an extra blank % line in the output. \xdef\doverbatim#1^^M#2@end verbatim{#2\noexpand\end\gobble verbatim}% % We really want {...\end verbatim} in the body of the macro, but % without the active space; thus we have to use \xdef and \gobble. \endgroup % \envdef\verbatim{% \setupverbatim\doverbatim } \let\Everbatim = \afterenvbreak % @verbatiminclude FILE - insert text of file in verbatim environment. % \def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude} % \def\doverbatiminclude#1{% {% \makevalueexpandable \setupverbatim \input #1 \afterenvbreak }% } % @copying ... @end copying. % Save the text away for @insertcopying later. Many commands won't be % allowed in this context, but that's ok. % % We save the uninterpreted tokens, rather than creating a box. % Saving the text in a box would be much easier, but then all the % typesetting commands (@smallbook, font changes, etc.) have to be done % beforehand -- and a) we want @copying to be done first in the source % file; b) letting users define the frontmatter in as flexible order as % possible is very desirable. % \def\copying{\begingroup % Define a command to swallow text until we reach `@end copying'. % \ is the escape char in this texinfo.tex file, so it is the % delimiter for the command; @ will be the escape char when we read % it, but that doesn't matter. \long\def\docopying##1\end copying{\gdef\copyingtext{##1}\enddocopying}% % % We must preserve ^^M's in the input file; see \insertcopying below. \catcode`\^^M = \active \docopying } % What we do to finish off the copying text. % \def\enddocopying{\endgroup\ignorespaces} % @insertcopying. Here we must play games with ^^M's. On the one hand, % we need them to delimit commands such as `@end quotation', so they % must be active. On the other hand, we certainly don't want every % end-of-line to be a \par, as would happen with the normal active % definition of ^^M. On the third hand, two ^^M's in a row should still % generate a \par. % % Our approach is to make ^^M insert a space and a penalty1 normally; % then it can also check if \lastpenalty=1. If it does, then manually % do \par. % % This messes up the normal definitions of @c[omment], so we redefine % it. Similarly for @ignore. (These commands are used in the gcc % manual for man page generation.) % % Seems pretty fragile, most line-oriented commands will presumably % fail, but for the limited use of getting the copying text (which % should be quite simple) inserted, we can hope it's ok. % {\catcode`\^^M=\active % \gdef\insertcopying{\begingroup % \parindent = 0pt % looks wrong on title page \def^^M{% \ifnum \lastpenalty=1 % \par % \else % \space \penalty 1 % \fi % }% % % Fix @c[omment] for catcode 13 ^^M's. \def\c##1^^M{\ignorespaces}% \let\comment = \c % % % Don't bother jumping through all the hoops that \doignore does, it % would be very hard since the catcodes are already set. \long\def\ignore##1\end ignore{\ignorespaces}% % \copyingtext % \endgroup}% } \message{defuns,} % @defun etc. \newskip\defbodyindent \defbodyindent=.4in \newskip\defargsindent \defargsindent=50pt \newskip\deflastargmargin \deflastargmargin=18pt % Start the processing of @deffn: \def\startdefun{% \ifnum\lastpenalty<10000 \medbreak \else % If there are two @def commands in a row, we'll have a \nobreak, % which is there to keep the function description together with its % header. But if there's nothing but headers, we need to allow a % break somewhere. Check for penalty 10002 (inserted by % \defargscommonending) instead of 10000, since the sectioning % commands insert a \penalty10000, and we don't want to allow a break % between a section heading and a defun. \ifnum\lastpenalty=10002 \penalty2000 \fi % % Similarly, after a section heading, do not allow a break. % But do insert the glue. \medskip % preceded by discardable penalty, so not a breakpoint \fi % \parindent=0in \advance\leftskip by \defbodyindent \exdentamount=\defbodyindent } \def\dodefunx#1{% % First, check whether we are in the right environment: \checkenv#1% % % As above, allow line break if we have multiple x headers in a row. % It's not a great place, though. \ifnum\lastpenalty=10002 \penalty3000 \fi % % And now, it's time to reuse the body of the original defun: \expandafter\gobbledefun#1% } \def\gobbledefun#1\startdefun{} % \printdefunline \deffnheader{text} % \def\printdefunline#1#2{% \begingroup % call \deffnheader: #1#2 \endheader % common ending: \interlinepenalty = 10000 \advance\rightskip by 0pt plus 1fil \endgraf \nobreak\vskip -\parskip \penalty 10002 % signal to \startdefun and \dodefunx % Some of the @defun-type tags do not enable magic parentheses, % rendering the following check redundant. But we don't optimize. \checkparencounts \endgroup } \def\Edefun{\endgraf\medbreak} % \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; % the only thing remainnig is to define \deffnheader. % \def\makedefun#1{% \expandafter\let\csname E#1\endcsname = \Edefun \edef\temp{\noexpand\domakedefun \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% \temp } % \domakedefun \deffn \deffnx \deffnheader % % Define \deffn and \deffnx, without parameters. % \deffnheader has to be defined explicitly. % \def\domakedefun#1#2#3{% \envdef#1{% \startdefun \parseargusing\activeparens{\printdefunline#3}% }% \def#2{\dodefunx#1}% \def#3% } %%% Untyped functions: % @deffn category name args \makedefun{deffn}{\deffngeneral{}} % @deffn category class name args \makedefun{defop}#1 {\defopon{#1\ \putwordon}} % \defopon {category on}class name args \def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } % \deffngeneral {subind}category name args % \def\deffngeneral#1#2 #3 #4\endheader{% % Remember that \dosubind{fn}{foo}{} is equivalent to \doind{fn}{foo}. \dosubind{fn}{\code{#3}}{#1}% \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% } %%% Typed functions: % @deftypefn category type name args \makedefun{deftypefn}{\deftypefngeneral{}} % @deftypeop category class type name args \makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} % \deftypeopon {category on}class type name args \def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } % \deftypefngeneral {subind}category type name args % \def\deftypefngeneral#1#2 #3 #4 #5\endheader{% \dosubind{fn}{\code{#4}}{#1}% \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } %%% Typed variables: % @deftypevr category type var args \makedefun{deftypevr}{\deftypecvgeneral{}} % @deftypecv category class type var args \makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} % \deftypecvof {category of}class type var args \def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } % \deftypecvgeneral {subind}category type var args % \def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% \dosubind{vr}{\code{#4}}{#1}% \defname{#2}{#3}{#4}\defunargs{#5\unskip}% } %%% Untyped variables: % @defvr category var args \makedefun{defvr}#1 {\deftypevrheader{#1} {} } % @defcv category class var args \makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} % \defcvof {category of}class var args \def\defcvof#1#2 {\deftypecvof{#1}#2 {} } %%% Type: % @deftp category name args \makedefun{deftp}#1 #2 #3\endheader{% \doind{tp}{\code{#2}}% \defname{#1}{}{#2}\defunargs{#3\unskip}% } % Remaining @defun-like shortcuts: \makedefun{defun}{\deffnheader{\putwordDeffunc} } \makedefun{defmac}{\deffnheader{\putwordDefmac} } \makedefun{defspec}{\deffnheader{\putwordDefspec} } \makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} } \makedefun{defvar}{\defvrheader{\putwordDefvar} } \makedefun{defopt}{\defvrheader{\putwordDefopt} } \makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } \makedefun{defmethod}{\defopon\putwordMethodon} \makedefun{deftypemethod}{\deftypeopon\putwordMethodon} \makedefun{defivar}{\defcvof\putwordInstanceVariableof} \makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} % \defname, which formats the name of the @def (not the args). % #1 is the category, such as "Function". % #2 is the return type, if any. % #3 is the function name. % % We are followed by (but not passed) the arguments, if any. % \def\defname#1#2#3{% % Get the values of \leftskip and \rightskip as they were outside the @def... \advance\leftskip by -\defbodyindent % % How we'll format the type name. Putting it in brackets helps % distinguish it from the body text that may end up on the next line % just below it. \def\temp{#1}% \setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi} % % Figure out line sizes for the paragraph shape. % The first line needs space for \box0; but if \rightskip is nonzero, % we need only space for the part of \box0 which exceeds it: \dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip % The continuations: \dimen2=\hsize \advance\dimen2 by -\defargsindent % (plain.tex says that \dimen1 should be used only as global.) \parshape 2 0in \dimen0 \defargsindent \dimen2 % % Put the type name to the right margin. \noindent \hbox to 0pt{% \hfil\box0 \kern-\hsize % \hsize has to be shortened this way: \kern\leftskip % Intentionally do not respect \rightskip, since we need the space. }% % % Allow all lines to be underfull without complaint: \tolerance=10000 \hbadness=10000 \exdentamount=\defbodyindent {% % defun fonts. We use typewriter by default (used to be bold) because: % . we're printing identifiers, they should be in tt in principle. % . in languages with many accents, such as Czech or French, it's % common to leave accents off identifiers. The result looks ok in % tt, but exceedingly strange in rm. % . we don't want -- and --- to be treated as ligatures. % . this still does not fix the ?` and !` ligatures, but so far no % one has made identifiers using them :). \df \tt \def\temp{#2}% return value type \ifx\temp\empty\else \tclose{\temp} \fi #3% output function name }% {\rm\enskip}% hskip 0.5 em of \tenrm % \boldbrax % arguments will be output next, if any. } % Print arguments in slanted roman (not ttsl), inconsistently with using % tt for the name. This is because literal text is sometimes needed in % the argument list (groff manual), and ttsl and tt are not very % distinguishable. Prevent hyphenation at `-' chars. % \def\defunargs#1{% % use sl by default (not ttsl), % tt for the names. \df \sl \hyphenchar\font=0 % % On the other hand, if an argument has two dashes (for instance), we % want a way to get ttsl. Let's try @var for that. \let\var=\ttslanted #1% \sl\hyphenchar\font=45 } % We want ()&[] to print specially on the defun line. % \def\activeparens{% \catcode`\(=\active \catcode`\)=\active \catcode`\[=\active \catcode`\]=\active \catcode`\&=\active } % Make control sequences which act like normal parenthesis chars. \let\lparen = ( \let\rparen = ) % Be sure that we always have a definition for `(', etc. For example, % if the fn name has parens in it, \boldbrax will not be in effect yet, % so TeX would otherwise complain about undefined control sequence. { \activeparens \global\let(=\lparen \global\let)=\rparen \global\let[=\lbrack \global\let]=\rbrack \global\let& = \& \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} \gdef\magicamp{\let&=\amprm} } \newcount\parencount % If we encounter &foo, then turn on ()-hacking afterwards \newif\ifampseen \def\amprm#1 {\ampseentrue{\bf\ }} \def\parenfont{% \ifampseen % At the first level, print parens in roman, % otherwise use the default font. \ifnum \parencount=1 \rm \fi \else % The \sf parens (in \boldbrax) actually are a little bolder than % the contained text. This is especially needed for [ and ] . \sf \fi } \def\infirstlevel#1{% \ifampseen \ifnum\parencount=1 #1% \fi \fi } \def\bfafterword#1 {#1 \bf} \def\opnr{% \global\advance\parencount by 1 {\parenfont(}% \infirstlevel \bfafterword } \def\clnr{% {\parenfont)}% \infirstlevel \sl \global\advance\parencount by -1 } \newcount\brackcount \def\lbrb{% \global\advance\brackcount by 1 {\bf[}% } \def\rbrb{% {\bf]}% \global\advance\brackcount by -1 } \def\checkparencounts{% \ifnum\parencount=0 \else \badparencount \fi \ifnum\brackcount=0 \else \badbrackcount \fi } \def\badparencount{% \errmessage{Unbalanced parentheses in @def}% \global\parencount=0 } \def\badbrackcount{% \errmessage{Unbalanced square braces in @def}% \global\brackcount=0 } \message{macros,} % @macro. % To do this right we need a feature of e-TeX, \scantokens, % which we arrange to emulate with a temporary file in ordinary TeX. \ifx\eTeXversion\undefined \newwrite\macscribble \def\scantokens#1{% \toks0={#1\endinput}% \immediate\openout\macscribble=\jobname.tmp \immediate\write\macscribble{\the\toks0}% \immediate\closeout\macscribble \input \jobname.tmp } \fi \def\scanmacro#1{% \begingroup \newlinechar`\^^M \let\xeatspaces\eatspaces % Undo catcode changes of \startcontents and \doprintindex \catcode`\@=0 \catcode`\\=\other \escapechar=`\@ % ... and \example \spaceisspace % % Append \endinput to make sure that TeX does not see the ending newline. % % I've verified that it is necessary both for e-TeX and for ordinary TeX % --kasal, 29nov03 \scantokens{#1\endinput}% \endgroup } \newcount\paramno % Count of parameters \newtoks\macname % Macro name \newif\ifrecursive % Is it recursive? \def\macrolist{} % List of all defined macros in the form % \do\macro1\do\macro2... % Utility routines. % This does \let #1 = #2, except with \csnames. \def\cslet#1#2{% \expandafter\expandafter \expandafter\let \expandafter\expandafter \csname#1\endcsname \csname#2\endcsname} % Trim leading and trailing spaces off a string. % Concepts from aro-bend problem 15 (see CTAN). {\catcode`\@=11 \gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }} \gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@} \gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @} \def\unbrace#1{#1} \unbrace{\gdef\trim@@@ #1 } #2@{#1} } % Trim a single trailing ^^M off a string. {\catcode`\^^M=\other \catcode`\Q=3% \gdef\eatcr #1{\eatcra #1Q^^MQ}% \gdef\eatcra#1^^MQ{\eatcrb#1Q}% \gdef\eatcrb#1Q#2Q{#1}% } % Macro bodies are absorbed as an argument in a context where % all characters are catcode 10, 11 or 12, except \ which is active % (as in normal texinfo). It is necessary to change the definition of \. % It's necessary to have hard CRs when the macro is executed. This is % done by making ^^M (\endlinechar) catcode 12 when reading the macro % body, and then making it the \newlinechar in \scanmacro. \def\macrobodyctxt{% \catcode`\~=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\+=\other \catcode`\{=\other \catcode`\}=\other \catcode`\@=\other \catcode`\^^M=\other \usembodybackslash} \def\macroargctxt{% \catcode`\~=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\+=\other \catcode`\@=\other \catcode`\\=\other} % \mbodybackslash is the definition of \ in @macro bodies. % It maps \foo\ => \csname macarg.foo\endcsname => #N % where N is the macro parameter number. % We define \csname macarg.\endcsname to be \realbackslash, so % \\ in macro replacement text gets you a backslash. {\catcode`@=0 @catcode`@\=@active @gdef@usembodybackslash{@let\=@mbodybackslash} @gdef@mbodybackslash#1\{@csname macarg.#1@endcsname} } \expandafter\def\csname macarg.\endcsname{\realbackslash} \def\macro{\recursivefalse\parsearg\macroxxx} \def\rmacro{\recursivetrue\parsearg\macroxxx} \def\macroxxx#1{% \getargs{#1}% now \macname is the macname and \argl the arglist \ifx\argl\empty % no arguments \paramno=0% \else \expandafter\parsemargdef \argl;% \fi \if1\csname ismacro.\the\macname\endcsname \message{Warning: redefining \the\macname}% \else \expandafter\ifx\csname \the\macname\endcsname \relax \else \errmessage{Macro name \the\macname\space already defined}\fi \global\cslet{macsave.\the\macname}{\the\macname}% \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% % Add the macroname to \macrolist \toks0 = \expandafter{\macrolist\do}% \xdef\macrolist{\the\toks0 \expandafter\noexpand\csname\the\macname\endcsname}% \fi \begingroup \macrobodyctxt \ifrecursive \expandafter\parsermacbody \else \expandafter\parsemacbody \fi} \parseargdef\unmacro{% \if1\csname ismacro.#1\endcsname \global\cslet{#1}{macsave.#1}% \global\expandafter\let \csname ismacro.#1\endcsname=0% % Remove the macro name from \macrolist: \begingroup \expandafter\let\csname#1\endcsname \relax \let\do\unmacrodo \xdef\macrolist{\macrolist}% \endgroup \else \errmessage{Macro #1 not defined}% \fi } % Called by \do from \dounmacro on each macro. The idea is to omit any % macro definitions that have been changed to \relax. % \def\unmacrodo#1{% \ifx#1\relax % remove this \else \noexpand\do \noexpand #1% \fi } % This makes use of the obscure feature that if the last token of a % is #, then the preceding argument is delimited by % an opening brace, and that opening brace is not consumed. \def\getargs#1{\getargsxxx#1{}} \def\getargsxxx#1#{\getmacname #1 \relax\getmacargs} \def\getmacname #1 #2\relax{\macname={#1}} \def\getmacargs#1{\def\argl{#1}} % Parse the optional {params} list. Set up \paramno and \paramlist % so \defmacro knows what to do. Define \macarg.blah for each blah % in the params list, to be ##N where N is the position in that list. % That gets used by \mbodybackslash (above). % We need to get `macro parameter char #' into several definitions. % The technique used is stolen from LaTeX: let \hash be something % unexpandable, insert that wherever you need a #, and then redefine % it to # just before using the token list produced. % % The same technique is used to protect \eatspaces till just before % the macro is used. \def\parsemargdef#1;{\paramno=0\def\paramlist{}% \let\hash\relax\let\xeatspaces\relax\parsemargdefxxx#1,;,} \def\parsemargdefxxx#1,{% \if#1;\let\next=\relax \else \let\next=\parsemargdefxxx \advance\paramno by 1% \expandafter\edef\csname macarg.\eatspaces{#1}\endcsname {\xeatspaces{\hash\the\paramno}}% \edef\paramlist{\paramlist\hash\the\paramno,}% \fi\next} % These two commands read recursive and nonrecursive macro bodies. % (They're different since rec and nonrec macros end differently.) \long\def\parsemacbody#1@end macro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% \long\def\parsermacbody#1@end rmacro% {\xdef\temp{\eatcr{#1}}\endgroup\defmacro}% % This defines the macro itself. There are six cases: recursive and % nonrecursive macros of zero, one, and many arguments. % Much magic with \expandafter here. % \xdef is used so that macro definitions will survive the file % they're defined in; @include reads the file inside a group. \def\defmacro{% \let\hash=##% convert placeholders to macro parameter chars \ifrecursive \ifcase\paramno % 0 \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\scanmacro{\temp}}% \or % 1 \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\braceorline \expandafter\noexpand\csname\the\macname xxx\endcsname}% \expandafter\xdef\csname\the\macname xxx\endcsname##1{% \egroup\noexpand\scanmacro{\temp}}% \else % many \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\csname\the\macname xx\endcsname}% \expandafter\xdef\csname\the\macname xx\endcsname##1{% \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% \expandafter\expandafter \expandafter\xdef \expandafter\expandafter \csname\the\macname xxx\endcsname \paramlist{\egroup\noexpand\scanmacro{\temp}}% \fi \else \ifcase\paramno % 0 \expandafter\xdef\csname\the\macname\endcsname{% \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \or % 1 \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \noexpand\braceorline \expandafter\noexpand\csname\the\macname xxx\endcsname}% \expandafter\xdef\csname\the\macname xxx\endcsname##1{% \egroup \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \else % many \expandafter\xdef\csname\the\macname\endcsname{% \bgroup\noexpand\macroargctxt \expandafter\noexpand\csname\the\macname xx\endcsname}% \expandafter\xdef\csname\the\macname xx\endcsname##1{% \expandafter\noexpand\csname\the\macname xxx\endcsname ##1,}% \expandafter\expandafter \expandafter\xdef \expandafter\expandafter \csname\the\macname xxx\endcsname \paramlist{% \egroup \noexpand\norecurse{\the\macname}% \noexpand\scanmacro{\temp}\egroup}% \fi \fi} \def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}} % \braceorline decides whether the next nonwhitespace character is a % {. If so it reads up to the closing }, if not, it reads the whole % line. Whatever was read is then fed to the next control sequence % as an argument (by \parsebrace or \parsearg) \def\braceorline#1{\let\next=#1\futurelet\nchar\braceorlinexxx} \def\braceorlinexxx{% \ifx\nchar\bgroup\else \expandafter\parsearg \fi \next} % We mant to disable all macros during \shipout so that they are not % expanded by \write. \def\turnoffmacros{\begingroup \def\do##1{\let\noexpand##1=\relax}% \edef\next{\macrolist}\expandafter\endgroup\next} % @alias. % We need some trickery to remove the optional spaces around the equal % sign. Just make them active and then expand them all to nothing. \def\alias{\parseargusing\obeyspaces\aliasxxx} \def\aliasxxx #1{\aliasyyy#1\relax} \def\aliasyyy #1=#2\relax{% {% \expandafter\let\obeyedspace=\empty \xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}% }% \next } \message{cross references,} \newwrite\auxfile \newif\ifhavexrefs % True if xref values are known. \newif\ifwarnedxrefs % True if we warned once that they aren't known. % @inforef is relatively simple. \def\inforef #1{\inforefzzz #1,,,,**} \def\inforefzzz #1,#2,#3,#4**{\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}}, node \samp{\ignorespaces#1{}}} % @node's only job in TeX is to define \lastnode, which is used in % cross-references. The @node line might or might not have commas, and % might or might not have spaces before the first comma, like: % @node foo , bar , ... % We don't want such trailing spaces in the node name. % \parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse} % % also remove a trailing comma, in case of something like this: % @node Help-Cross, , , Cross-refs \def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse} \def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}} \let\nwnode=\node \let\lastnode=\empty % Write a cross-reference definition for the current node. #1 is the % type (Ynumbered, Yappendix, Ynothing). % \def\donoderef#1{% \ifx\lastnode\empty\else \setref{\lastnode}{#1}% \global\let\lastnode=\empty \fi } % @anchor{NAME} -- define xref target at arbitrary point. % \newcount\savesfregister % \def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi} \def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi} \def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces} % \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an % anchor), which consists of three parts: % 1) NAME-title - the current sectioning name taken from \thissection, % or the anchor name. % 2) NAME-snt - section number and type, passed as the SNT arg, or % empty for anchors. % 3) NAME-pg - the page number. % % This is called from \donoderef, \anchor, and \dofloat. In the case of % floats, there is an additional part, which is not written here: % 4) NAME-lof - the text as it should appear in a @listoffloats. % \def\setref#1#2{% \pdfmkdest{#1}% \iflinks {% \atdummies % preserve commands, but don't expand them \turnoffactive \otherbackslash \edef\writexrdef##1##2{% \write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef ##1}{##2}}% these are parameters of \writexrdef }% \toks0 = \expandafter{\thissection}% \immediate \writexrdef{title}{\the\toks0 }% \immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc. \writexrdef{pg}{\folio}% will be written later, during \shipout }% \fi } % @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is % the node name, #2 the name of the Info cross-reference, #3 the printed % node name, #4 the name of the Info file, #5 the name of the printed % manual. All but the node name can be omitted. % \def\pxref#1{\putwordsee{} \xrefX[#1,,,,,,,]} \def\xref#1{\putwordSee{} \xrefX[#1,,,,,,,]} \def\ref#1{\xrefX[#1,,,,,,,]} \def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup \unsepspaces \def\printedmanual{\ignorespaces #5}% \def\printedrefname{\ignorespaces #3}% \setbox1=\hbox{\printedmanual\unskip}% \setbox0=\hbox{\printedrefname\unskip}% \ifdim \wd0 = 0pt % No printed node name was explicitly given. \expandafter\ifx\csname SETxref-automatic-section-title\endcsname\relax % Use the node name inside the square brackets. \def\printedrefname{\ignorespaces #1}% \else % Use the actual chapter/section title appear inside % the square brackets. Use the real section title if we have it. \ifdim \wd1 > 0pt % It is in another manual, so we don't have it. \def\printedrefname{\ignorespaces #1}% \else \ifhavexrefs % We know the real title if we have the xref values. \def\printedrefname{\refx{#1-title}{}}% \else % Otherwise just copy the Info node name. \def\printedrefname{\ignorespaces #1}% \fi% \fi \fi \fi % % Make link in pdf output. \ifpdf \leavevmode \getfilename{#4}% {\turnoffactive \otherbackslash \ifnum\filenamelength>0 \startlink attr{/Border [0 0 0]}% goto file{\the\filename.pdf} name{#1}% \else \startlink attr{/Border [0 0 0]}% goto name{\pdfmkpgn{#1}}% \fi }% \linkcolor \fi % % Float references are printed completely differently: "Figure 1.2" % instead of "[somenode], p.3". We distinguish them by the % LABEL-title being set to a magic string. {% % Have to otherify everything special to allow the \csname to % include an _ in the xref name, etc. \indexnofonts \turnoffactive \otherbackslash \expandafter\global\expandafter\let\expandafter\Xthisreftitle \csname XR#1-title\endcsname }% \iffloat\Xthisreftitle % If the user specified the print name (third arg) to the ref, % print it instead of our usual "Figure 1.2". \ifdim\wd0 = 0pt \refx{#1-snt}% \else \printedrefname \fi % % if the user also gave the printed manual name (fifth arg), append % "in MANUALNAME". \ifdim \wd1 > 0pt \space \putwordin{} \cite{\printedmanual}% \fi \else % node/anchor (non-float) references. % % If we use \unhbox0 and \unhbox1 to print the node names, TeX does not % insert empty discretionaries after hyphens, which means that it will % not find a line break at a hyphen in a node names. Since some manuals % are best written with fairly long node names, containing hyphens, this % is a loss. Therefore, we give the text of the node name again, so it % is as if TeX is seeing it for the first time. \ifdim \wd1 > 0pt \putwordsection{} ``\printedrefname'' \putwordin{} \cite{\printedmanual}% \else % _ (for example) has to be the character _ for the purposes of the % control sequence corresponding to the node, but it has to expand % into the usual \leavevmode...\vrule stuff for purposes of % printing. So we \turnoffactive for the \refx-snt, back on for the % printing, back off for the \refx-pg. {\turnoffactive \otherbackslash % Only output a following space if the -snt ref is nonempty; for % @unnumbered and @anchor, it won't be. \setbox2 = \hbox{\ignorespaces \refx{#1-snt}{}}% \ifdim \wd2 > 0pt \refx{#1-snt}\space\fi }% % output the `[mynode]' via a macro so it can be overridden. \xrefprintnodename\printedrefname % % But we always want a comma and a space: ,\space % % output the `page 3'. \turnoffactive \otherbackslash \putwordpage\tie\refx{#1-pg}{}% \fi \fi \endlink \endgroup} % This macro is called from \xrefX for the `[nodename]' part of xref % output. It's a separate macro only so it can be changed more easily, % since square brackets don't work well in some documents. Particularly % one that Bob is working on :). % \def\xrefprintnodename#1{[#1]} % Things referred to by \setref. % \def\Ynothing{} \def\Yomitfromtoc{} \def\Ynumbered{% \ifnum\secno=0 \putwordChapter@tie \the\chapno \else \ifnum\subsecno=0 \putwordSection@tie \the\chapno.\the\secno \else \ifnum\subsubsecno=0 \putwordSection@tie \the\chapno.\the\secno.\the\subsecno \else \putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno \fi\fi\fi } \def\Yappendix{% \ifnum\secno=0 \putwordAppendix@tie @char\the\appendixno{}% \else \ifnum\subsecno=0 \putwordSection@tie @char\the\appendixno.\the\secno \else \ifnum\subsubsecno=0 \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno \else \putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno \fi\fi\fi } % Define \refx{NAME}{SUFFIX} to reference a cross-reference string named NAME. % If its value is nonempty, SUFFIX is output afterward. % \def\refx#1#2{% {% \indexnofonts \otherbackslash \expandafter\global\expandafter\let\expandafter\thisrefX \csname XR#1\endcsname }% \ifx\thisrefX\relax % If not defined, say something at least. \angleleft un\-de\-fined\angleright \iflinks \ifhavexrefs \message{\linenumber Undefined cross reference `#1'.}% \else \ifwarnedxrefs\else \global\warnedxrefstrue \message{Cross reference values unknown; you must run TeX again.}% \fi \fi \fi \else % It's defined, so just use it. \thisrefX \fi #2% Output the suffix in any case. } % This is the macro invoked by entries in the aux file. Usually it's % just a \def (we prepend XR to the control sequence name to avoid % collisions). But if this is a float type, we have more work to do. % \def\xrdef#1#2{% \expandafter\gdef\csname XR#1\endcsname{#2}% remember this xref value. % % Was that xref control sequence that we just defined for a float? \expandafter\iffloat\csname XR#1\endcsname % it was a float, and we have the (safe) float type in \iffloattype. \expandafter\let\expandafter\floatlist \csname floatlist\iffloattype\endcsname % % Is this the first time we've seen this float type? \expandafter\ifx\floatlist\relax \toks0 = {\do}% yes, so just \do \else % had it before, so preserve previous elements in list. \toks0 = \expandafter{\floatlist\do}% \fi % % Remember this xref in the control sequence \floatlistFLOATTYPE, % for later use in \listoffloats. \expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0{#1}}% \fi } % Read the last existing aux file, if any. No error if none exists. % \def\tryauxfile{% \openin 1 \jobname.aux \ifeof 1 \else \readauxfile \global\havexrefstrue \fi \closein 1 } \def\readauxfile{\begingroup \catcode`\^^@=\other \catcode`\^^A=\other \catcode`\^^B=\other \catcode`\^^C=\other \catcode`\^^D=\other \catcode`\^^E=\other \catcode`\^^F=\other \catcode`\^^G=\other \catcode`\^^H=\other \catcode`\^^K=\other \catcode`\^^L=\other \catcode`\^^N=\other \catcode`\^^P=\other \catcode`\^^Q=\other \catcode`\^^R=\other \catcode`\^^S=\other \catcode`\^^T=\other \catcode`\^^U=\other \catcode`\^^V=\other \catcode`\^^W=\other \catcode`\^^X=\other \catcode`\^^Z=\other \catcode`\^^[=\other \catcode`\^^\=\other \catcode`\^^]=\other \catcode`\^^^=\other \catcode`\^^_=\other % It was suggested to set the catcode of ^ to 7, which would allow ^^e4 etc. % in xref tags, i.e., node names. But since ^^e4 notation isn't % supported in the main text, it doesn't seem desirable. Furthermore, % that is not enough: for node names that actually contain a ^ % character, we would end up writing a line like this: 'xrdef {'hat % b-title}{'hat b} and \xrdef does a \csname...\endcsname on the first % argument, and \hat is not an expandable control sequence. It could % all be worked out, but why? Either we support ^^ or we don't. % % The other change necessary for this was to define \auxhat: % \def\auxhat{\def^{'hat }}% extra space so ok if followed by letter % and then to call \auxhat in \setq. % \catcode`\^=\other % % Special characters. Should be turned off anyway, but... \catcode`\~=\other \catcode`\[=\other \catcode`\]=\other \catcode`\"=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\$=\other \catcode`\#=\other \catcode`\&=\other \catcode`\%=\other \catcode`+=\other % avoid \+ for paranoia even though we've turned it off % % This is to support \ in node names and titles, since the \ % characters end up in a \csname. It's easier than % leaving it active and making its active definition an actual \ % character. What I don't understand is why it works in the *value* % of the xrdef. Seems like it should be a catcode12 \, and that % should not typeset properly. But it works, so I'm moving on for % now. --karl, 15jan04. \catcode`\\=\other % % Make the characters 128-255 be printing characters. {% \count 1=128 \def\loop{% \catcode\count 1=\other \advance\count 1 by 1 \ifnum \count 1<256 \loop \fi }% }% % % @ is our escape character in .aux files, and we need braces. \catcode`\{=1 \catcode`\}=2 \catcode`\@=0 % \input \jobname.aux \endgroup} \message{insertions,} % including footnotes. \newcount \footnoteno % The trailing space in the following definition for supereject is % vital for proper filling; pages come out unaligned when you do a % pagealignmacro call if that space before the closing brace is % removed. (Generally, numeric constants should always be followed by a % space to prevent strange expansion errors.) \def\supereject{\par\penalty -20000\footnoteno =0 } % @footnotestyle is meaningful for info output only. \let\footnotestyle=\comment {\catcode `\@=11 % % Auto-number footnotes. Otherwise like plain. \gdef\footnote{% \let\indent=\ptexindent \let\noindent=\ptexnoindent \global\advance\footnoteno by \@ne \edef\thisfootno{$^{\the\footnoteno}$}% % % In case the footnote comes at the end of a sentence, preserve the % extra spacing after we do the footnote number. \let\@sf\empty \ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi % % Remove inadvertent blank space before typesetting the footnote number. \unskip \thisfootno\@sf \dofootnote }% % Don't bother with the trickery in plain.tex to not require the % footnote text as a parameter. Our footnotes don't need to be so general. % % Oh yes, they do; otherwise, @ifset (and anything else that uses % \parseargline) fails inside footnotes because the tokens are fixed when % the footnote is read. --karl, 16nov96. % \gdef\dofootnote{% \insert\footins\bgroup % We want to typeset this text as a normal paragraph, even if the % footnote reference occurs in (for example) a display environment. % So reset some parameters. \hsize=\pagewidth \interlinepenalty\interfootnotelinepenalty \splittopskip\ht\strutbox % top baseline for broken footnotes \splitmaxdepth\dp\strutbox \floatingpenalty\@MM \leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip \parindent\defaultparindent % \smallfonts \rm % % Because we use hanging indentation in footnotes, a @noindent appears % to exdent this text, so make it be a no-op. makeinfo does not use % hanging indentation so @noindent can still be needed within footnote % text after an @example or the like (not that this is good style). \let\noindent = \relax % % Hang the footnote text off the number. Use \everypar in case the % footnote extends for more than one paragraph. \everypar = {\hang}% \textindent{\thisfootno}% % % Don't crash into the line above the footnote text. Since this % expands into a box, it must come within the paragraph, lest it % provide a place where TeX can split the footnote. \footstrut \futurelet\next\fo@t } }%end \catcode `\@=11 % In case a @footnote appears in a vbox, save the footnote text and create % the real \insert just after the vbox finished. Otherwise, the insertion % would be lost. % Similarily, if a @footnote appears inside an alignment, save the footnote % text to a box and make the \insert when a row of the table is finished. % And the same can be done for other insert classes. --kasal, 16nov03. % Replace the \insert primitive by a cheating macro. % Deeper inside, just make sure that the saved insertions are not spilled % out prematurely. % \def\startsavinginserts{% \ifx \insert\ptexinsert \let\insert\saveinsert \else \let\checkinserts\relax \fi } % This \insert replacement works for both \insert\footins{foo} and % \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}. % \def\saveinsert#1{% \edef\next{\noexpand\savetobox \makeSAVEname#1}% \afterassignment\next % swallow the left brace \let\temp = } \def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}} \def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1} \def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi} \def\placesaveins#1{% \ptexinsert \csname\expandafter\gobblesave\string#1\endcsname {\box#1}% } % eat @SAVE -- beware, all of them have catcode \other: { \def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-) \gdef\gobblesave @SAVE{} } % initialization: \def\newsaveins #1{% \edef\next{\noexpand\newsaveinsX \makeSAVEname#1}% \next } \def\newsaveinsX #1{% \csname newbox\endcsname #1% \expandafter\def\expandafter\checkinserts\expandafter{\checkinserts \checksaveins #1}% } % initialize: \let\checkinserts\empty \newsaveins\footins \newsaveins\margin % @image. We use the macros from epsf.tex to support this. % If epsf.tex is not installed and @image is used, we complain. % % Check for and read epsf.tex up front. If we read it only at @image % time, we might be inside a group, and then its definitions would get % undone and the next image would fail. \openin 1 = epsf.tex \ifeof 1 \else % Do not bother showing banner with epsf.tex v2.7k (available in % doc/epsf.tex and on ctan). \def\epsfannounce{\toks0 = }% \input epsf.tex \fi \closein 1 % % We will only complain once about lack of epsf.tex. \newif\ifwarnednoepsf \newhelp\noepsfhelp{epsf.tex must be installed for images to work. It is also included in the Texinfo distribution, or you can get it from ftp://tug.org/tex/epsf.tex.} % \def\image#1{% \ifx\epsfbox\undefined \ifwarnednoepsf \else \errhelp = \noepsfhelp \errmessage{epsf.tex not found, images will be ignored}% \global\warnednoepsftrue \fi \else \imagexxx #1,,,,,\finish \fi } % % Arguments to @image: % #1 is (mandatory) image filename; we tack on .eps extension. % #2 is (optional) width, #3 is (optional) height. % #4 is (ignored optional) html alt text. % #5 is (ignored optional) extension. % #6 is just the usual extra ignored arg for parsing this stuff. \newif\ifimagevmode \def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup \catcode`\^^M = 5 % in case we're inside an example \normalturnoffactive % allow _ et al. in names % If the image is by itself, center it. \ifvmode \imagevmodetrue \nobreak\bigskip % Usually we'll have text after the image which will insert % \parskip glue, so insert it here too to equalize the space % above and below. \nobreak\vskip\parskip \nobreak \line\bgroup\hss \fi % % Output the image. \ifpdf \dopdfimage{#1}{#2}{#3}% \else % \epsfbox itself resets \epsf?size at each figure. \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi \setbox0 = \hbox{\ignorespaces #3}\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi \epsfbox{#1.eps}% \fi % \ifimagevmode \hss \egroup \bigbreak \fi % space after the image \endgroup} % @float FLOATTYPE,LOC ... @end float for displayed figures, tables, etc. % We don't actually implement floating yet, we just plop the float "here". % But it seemed the best name for the future. % \envparseargdef\float{\dofloat #1,,,\finish} % #1 is the optional FLOATTYPE, the text label for this float, typically % "Figure", "Table", "Example", etc. Can't contain commas. If omitted, % this float will not be numbered and cannot be referred to. % % #2 is the optional xref label. Also must be present for the float to % be referable. % % #3 is the optional positioning argument; for now, it is ignored. It % will somehow specify the positions allowed to float to (here, top, bottom). % % We keep a separate counter for each FLOATTYPE, which we reset at each % chapter-level command. \let\resetallfloatnos=\empty % \def\dofloat#1,#2,#3,#4\finish{% \let\thiscaption=\empty \let\thisshortcaption=\empty % % don't lose footnotes inside @float. \startsavinginserts % % We can't be used inside a paragraph. \par % \vtop\bgroup \def\floattype{#1}% \def\floatlabel{#2}% \def\floatloc{#3}% we do nothing with this yet. % \ifx\floattype\empty \let\safefloattype=\empty \else {% % the floattype might have accents or other special characters, % but we need to use it in a control sequence name. \indexnofonts \turnoffactive \xdef\safefloattype{\floattype}% }% \fi % % If label is given but no type, we handle that as the empty type. \ifx\floatlabel\empty \else % We want each FLOATTYPE to be numbered separately (Figure 1, % Table 1, Figure 2, ...). (And if no label, no number.) % \expandafter\getfloatno\csname\safefloattype floatno\endcsname \global\advance\floatno by 1 % {% % This magic value for \thissection is output by \setref as the % XREFLABEL-title value. \xrefX uses it to distinguish float % labels (which have a completely different output format) from % node and anchor labels. And \xrdef uses it to construct the % lists of floats. % \edef\thissection{\floatmagic=\safefloattype}% \setref{\floatlabel}{Yfloat}% }% \fi % % start with \parskip glue, I guess. \vskip\parskip % % Don't suppress indentation if a float happens to start a section. \restorefirstparagraphindent } % we have these possibilities: % @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap % @float Foo,lbl & no caption: Foo 1.1 % @float Foo & @caption{Cap}: Foo: Cap % @float Foo & no caption: Foo % @float ,lbl & Caption{Cap}: 1.1: Cap % @float ,lbl & no caption: 1.1 % @float & @caption{Cap}: Cap % @float & no caption: % \def\Efloat{% \let\floatident = \empty % % In all cases, if we have a float type, it comes first. \ifx\floattype\empty \else \def\floatident{\floattype}\fi % % If we have an xref label, the number comes next. \ifx\floatlabel\empty \else \ifx\floattype\empty \else % if also had float type, need tie first. \appendtomacro\floatident{\tie}% \fi % the number. \appendtomacro\floatident{\chaplevelprefix\the\floatno}% \fi % % Start the printed caption with what we've constructed in % \floatident, but keep it separate; we need \floatident again. \let\captionline = \floatident % \ifx\thiscaption\empty \else \ifx\floatident\empty \else \appendtomacro\captionline{: }% had ident, so need a colon between \fi % % caption text. \appendtomacro\captionline\thiscaption \fi % % If we have anything to print, print it, with space before. % Eventually this needs to become an \insert. \ifx\captionline\empty \else \vskip.5\parskip \captionline \fi % % If have an xref label, write the list of floats info. Do this % after the caption, to avoid chance of it being a breakpoint. \ifx\floatlabel\empty \else % Write the text that goes in the lof to the aux file as % \floatlabel-lof. Besides \floatident, we include the short % caption if specified, else the full caption if specified, else nothing. {% \atdummies \turnoffactive \otherbackslash \immediate\write\auxfile{@xrdef{\floatlabel-lof}{% \floatident \ifx\thisshortcaption\empty \ifx\thiscaption\empty \else : \thiscaption \fi \else : \thisshortcaption \fi }}% }% \fi % % Space below caption, if we printed anything. \ifx\printedsomething\empty \else \vskip\parskip \fi \egroup % end of \vtop \checkinserts } % Append the tokens #2 to the definition of macro #1, not expanding either. % \newtoks\appendtomacroAtoks \newtoks\appendtomacroBtoks \def\appendtomacro#1#2{% \appendtomacroAtoks = \expandafter{#1}% \appendtomacroBtoks = {#2}% \edef#1{\the\appendtomacroAtoks \the\appendtomacroBtoks}% } % @caption, @shortcaption are easy. % \long\def\caption#1{\checkenv\float \def\thiscaption{#1}} \def\shortcaption#1{\checkenv\float \def\thisshortcaption{#1}} % The parameter is the control sequence identifying the counter we are % going to use. Create it if it doesn't exist and assign it to \floatno. \def\getfloatno#1{% \ifx#1\relax % Haven't seen this figure type before. \csname newcount\endcsname #1% % % Remember to reset this floatno at the next chap. \expandafter\gdef\expandafter\resetallfloatnos \expandafter{\resetallfloatnos #1=0 }% \fi \let\floatno#1% } % \setref calls this to get the XREFLABEL-snt value. We want an @xref % to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we % first read the @float command. % \def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}% % Magic string used for the XREFLABEL-title value, so \xrefX can % distinguish floats from other xref types. \def\floatmagic{!!float!!} % #1 is the control sequence we are passed; we expand into a conditional % which is true if #1 represents a float ref. That is, the magic % \thissection value which we \setref above. % \def\iffloat#1{\expandafter\doiffloat#1==\finish} % % #1 is (maybe) the \floatmagic string. If so, #2 will be the % (safe) float type for this float. We set \iffloattype to #2. % \def\doiffloat#1=#2=#3\finish{% \def\temp{#1}% \def\iffloattype{#2}% \ifx\temp\floatmagic } % @listoffloats FLOATTYPE - print a list of floats like a table of contents. % \parseargdef\listoffloats{% \def\floattype{#1}% floattype {% % the floattype might have accents or other special characters, % but we need to use it in a control sequence name. \indexnofonts \turnoffactive \xdef\safefloattype{\floattype}% }% % % \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE. \expandafter\ifx\csname floatlist\safefloattype\endcsname \relax \ifhavexrefs % if the user said @listoffloats foo but never @float foo. \message{\linenumber No `\safefloattype' floats to list.}% \fi \else \begingroup \leftskip=\tocindent % indent these entries like a toc \let\do=\listoffloatsdo \csname floatlist\safefloattype\endcsname \endgroup \fi } % This is called on each entry in a list of floats. We're passed the % xref label, in the form LABEL-title, which is how we save it in the % aux file. We strip off the -title and look up \XRLABEL-lof, which % has the text we're supposed to typeset here. % % Figures without xref labels will not be included in the list (since % they won't appear in the aux file). % \def\listoffloatsdo#1{\listoffloatsdoentry#1\finish} \def\listoffloatsdoentry#1-title\finish{{% % Can't fully expand XR#1-lof because it can contain anything. Just % pass the control sequence. On the other hand, XR#1-pg is just the % page number, and we want to fully expand that so we can get a link % in pdf output. \toksA = \expandafter{\csname XR#1-lof\endcsname}% % % use the same \entry macro we use to generate the TOC and index. \edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}% \writeentry }} \message{localization,} % and i18n. % @documentlanguage is usually given very early, just after % @setfilename. If done too late, it may not override everything % properly. Single argument is the language abbreviation. % It would be nice if we could set up a hyphenation file here. % \parseargdef\documentlanguage{% \tex % read txi-??.tex file in plain TeX. % Read the file if it exists. \openin 1 txi-#1.tex \ifeof 1 \errhelp = \nolanghelp \errmessage{Cannot read language file txi-#1.tex}% \else \input txi-#1.tex \fi \closein 1 \endgroup } \newhelp\nolanghelp{The given language definition file cannot be found or is empty. Maybe you need to install it? In the current directory should work if nowhere else does.} % @documentencoding should change something in TeX eventually, most % likely, but for now just recognize it. \let\documentencoding = \comment % Page size parameters. % \newdimen\defaultparindent \defaultparindent = 15pt \chapheadingskip = 15pt plus 4pt minus 2pt \secheadingskip = 12pt plus 3pt minus 2pt \subsecheadingskip = 9pt plus 2pt minus 2pt % Prevent underfull vbox error messages. \vbadness = 10000 % Don't be so finicky about underfull hboxes, either. \hbadness = 2000 % Following George Bush, just get rid of widows and orphans. \widowpenalty=10000 \clubpenalty=10000 % Use TeX 3.0's \emergencystretch to help line breaking, but if we're % using an old version of TeX, don't do anything. We want the amount of % stretch added to depend on the line length, hence the dependence on % \hsize. We call this whenever the paper size is set. % \def\setemergencystretch{% \ifx\emergencystretch\thisisundefined % Allow us to assign to \emergencystretch anyway. \def\emergencystretch{\dimen0}% \else \emergencystretch = .15\hsize \fi } % Parameters in order: 1) textheight; 2) textwidth; 3) voffset; % 4) hoffset; 5) binding offset; 6) topskip; 7) physical page height; 8) % physical page width. % % We also call \setleading{\textleading}, so the caller should define % \textleading. The caller should also set \parskip. % \def\internalpagesizes#1#2#3#4#5#6#7#8{% \voffset = #3\relax \topskip = #6\relax \splittopskip = \topskip % \vsize = #1\relax \advance\vsize by \topskip \outervsize = \vsize \advance\outervsize by 2\topandbottommargin \pageheight = \vsize % \hsize = #2\relax \outerhsize = \hsize \advance\outerhsize by 0.5in \pagewidth = \hsize % \normaloffset = #4\relax \bindingoffset = #5\relax % \ifpdf \pdfpageheight #7\relax \pdfpagewidth #8\relax \fi % \setleading{\textleading} % \parindent = \defaultparindent \setemergencystretch } % @letterpaper (the default). \def\letterpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt \textleading = 13.2pt % % If page is nothing but text, make it come out even. \internalpagesizes{46\baselineskip}{6in}% {\voffset}{.25in}% {\bindingoffset}{36pt}% {11in}{8.5in}% }} % Use @smallbook to reset parameters for 7x9.5 (or so) format. \def\smallbook{{\globaldefs = 1 \parskip = 2pt plus 1pt \textleading = 12pt % \internalpagesizes{7.5in}{5in}% {\voffset}{.25in}% {\bindingoffset}{16pt}% {9.25in}{7in}% % \lispnarrowing = 0.3in \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = .5cm }} % Use @afourpaper to print on European A4 paper. \def\afourpaper{{\globaldefs = 1 \parskip = 3pt plus 2pt minus 1pt \textleading = 13.2pt % % Double-side printing via postscript on Laserjet 4050 % prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm. % To change the settings for a different printer or situation, adjust % \normaloffset until the front-side and back-side texts align. Then % do the same for \bindingoffset. You can set these for testing in % your texinfo source file like this: % @tex % \global\normaloffset = -6mm % \global\bindingoffset = 10mm % @end tex \internalpagesizes{51\baselineskip}{160mm} {\voffset}{\hoffset}% {\bindingoffset}{44pt}% {297mm}{210mm}% % \tolerance = 700 \hfuzz = 1pt \contentsrightmargin = 0pt \defbodyindent = 5mm }} % Use @afivepaper to print on European A5 paper. % From romildo@urano.iceb.ufop.br, 2 July 2000. % He also recommends making @example and @lisp be small. \def\afivepaper{{\globaldefs = 1 \parskip = 2pt plus 1pt minus 0.1pt \textleading = 12.5pt % \internalpagesizes{160mm}{120mm}% {\voffset}{\hoffset}% {\bindingoffset}{8pt}% {210mm}{148mm}% % \lispnarrowing = 0.2in \tolerance = 800 \hfuzz = 1.2pt \contentsrightmargin = 0pt \defbodyindent = 2mm \tableindent = 12mm }} % A specific text layout, 24x15cm overall, intended for A4 paper. \def\afourlatex{{\globaldefs = 1 \afourpaper \internalpagesizes{237mm}{150mm}% {\voffset}{4.6mm}% {\bindingoffset}{7mm}% {297mm}{210mm}% % % Must explicitly reset to 0 because we call \afourpaper. \globaldefs = 0 }} % Use @afourwide to print on A4 paper in landscape format. \def\afourwide{{\globaldefs = 1 \afourpaper \internalpagesizes{241mm}{165mm}% {\voffset}{-2.95mm}% {\bindingoffset}{7mm}% {297mm}{210mm}% \globaldefs = 0 }} % @pagesizes TEXTHEIGHT[,TEXTWIDTH] % Perhaps we should allow setting the margins, \topskip, \parskip, % and/or leading, also. Or perhaps we should compute them somehow. % \parseargdef\pagesizes{\pagesizesyyy #1,,\finish} \def\pagesizesyyy#1,#2,#3\finish{{% \setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi \globaldefs = 1 % \parskip = 3pt plus 2pt minus 1pt \setleading{\textleading}% % \dimen0 = #1 \advance\dimen0 by \voffset % \dimen2 = \hsize \advance\dimen2 by \normaloffset % \internalpagesizes{#1}{\hsize}% {\voffset}{\normaloffset}% {\bindingoffset}{44pt}% {\dimen0}{\dimen2}% }} % Set default to letter. % \letterpaper \message{and turning on texinfo input format.} % Define macros to output various characters with catcode for normal text. \catcode`\"=\other \catcode`\~=\other \catcode`\^=\other \catcode`\_=\other \catcode`\|=\other \catcode`\<=\other \catcode`\>=\other \catcode`\+=\other \catcode`\$=\other \def\normaldoublequote{"} \def\normaltilde{~} \def\normalcaret{^} \def\normalunderscore{_} \def\normalverticalbar{|} \def\normalless{<} \def\normalgreater{>} \def\normalplus{+} \def\normaldollar{$}%$ font-lock fix % This macro is used to make a character print one way in \tt % (where it can probably be output as-is), and another way in other fonts, % where something hairier probably needs to be done. % % #1 is what to print if we are indeed using \tt; #2 is what to print % otherwise. Since all the Computer Modern typewriter fonts have zero % interword stretch (and shrink), and it is reasonable to expect all % typewriter fonts to have this, we can check that font parameter. % \def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi} % Same as above, but check for italic font. Actually this also catches % non-italic slanted fonts since it is impossible to distinguish them from % italic fonts. But since this is only used by $ and it uses \sl anyway % this is not a problem. \def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi} % Turn off all special characters except @ % (and those which the user can use as if they were ordinary). % Most of these we simply print from the \tt font, but for some, we can % use math or other variants that look better in normal text. \catcode`\"=\active \def\activedoublequote{{\tt\char34}} \let"=\activedoublequote \catcode`\~=\active \def~{{\tt\char126}} \chardef\hat=`\^ \catcode`\^=\active \def^{{\tt \hat}} \catcode`\_=\active \def_{\ifusingtt\normalunderscore\_} % Subroutine for the previous macro. \def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em } \catcode`\|=\active \def|{{\tt\char124}} \chardef \less=`\< \catcode`\<=\active \def<{{\tt \less}} \chardef \gtr=`\> \catcode`\>=\active \def>{{\tt \gtr}} \catcode`\+=\active \def+{{\tt \char 43}} \catcode`\$=\active \def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix % If a .fmt file is being used, characters that might appear in a file % name cannot be active until we have parsed the command line. % So turn them off again, and have \everyjob (or @setfilename) turn them on. % \otherifyactive is called near the end of this file. \def\otherifyactive{\catcode`+=\other \catcode`\_=\other} \catcode`\@=0 % \backslashcurfont outputs one backslash character in current font, % as in \char`\\. \global\chardef\backslashcurfont=`\\ \global\let\rawbackslashxx=\backslashcurfont % let existing .??s files work % \rawbackslash defines an active \ to do \backslashcurfont. % \otherbackslash defines an active \ to be a literal `\' character with % catcode other. {\catcode`\\=\active @gdef@rawbackslash{@let\=@backslashcurfont} @gdef@otherbackslash{@let\=@realbackslash} } % \realbackslash is an actual character `\' with catcode other. {\catcode`\\=\other @gdef@realbackslash{\}} % \normalbackslash outputs one backslash in fixed width font. \def\normalbackslash{{\tt\backslashcurfont}} \catcode`\\=\active % Used sometimes to turn off (effectively) the active characters % even after parsing them. @def@turnoffactive{% @let"=@normaldoublequote @let\=@realbackslash @let~=@normaltilde @let^=@normalcaret @let_=@normalunderscore @let|=@normalverticalbar @let<=@normalless @let>=@normalgreater @let+=@normalplus @let$=@normaldollar %$ font-lock fix @unsepspaces } % Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of % the literal character `\'. (Thus, \ is not expandable when this is in % effect.) % @def@normalturnoffactive{@turnoffactive @let\=@normalbackslash} % Make _ and + \other characters, temporarily. % This is canceled by @fixbackslash. @otherifyactive % If a .fmt file is being used, we don't want the `\input texinfo' to show up. % That is what \eatinput is for; after that, the `\' should revert to printing % a backslash. % @gdef@eatinput input texinfo{@fixbackslash} @global@let\ = @eatinput % On the other hand, perhaps the file did not have a `\input texinfo'. Then % the first `\{ in the file would cause an error. This macro tries to fix % that, assuming it is called before the first `\' could plausibly occur. % Also back turn on active characters that might appear in the input % file name, in case not using a pre-dumped format. % @gdef@fixbackslash{% @ifx\@eatinput @let\ = @normalbackslash @fi @catcode`+=@active @catcode`@_=@active } % Say @foo, not \foo, in error messages. @escapechar = `@@ % These look ok in all fonts, so just make them not special. @catcode`@& = @other @catcode`@# = @other @catcode`@% = @other @c Local variables: @c eval: (add-hook 'write-file-hooks 'time-stamp) @c page-delimiter: "^\\\\message" @c time-stamp-start: "def\\\\texinfoversion{" @c time-stamp-format: "%:y-%02m-%02d.%02H" @c time-stamp-end: "}" @c End: @c vim:sw=2: @ignore arch-tag: e1b36e32-c96e-4135-a41a-0b2efa2ea115 @end ignore cfengine-2.2.10/doc/cfengine-Tutorial.pdf0000644000175000001440000177741711170173462015140 00000000000000%PDF-1.4 %ÐÔÅØ 3 0 obj << /Length 311 /Filter /FlateDecode >> stream xÚ}PAjÃ0¼û:ÊP©Z­lKׄäPhKÁ=•‚#×jå$¥¿¯d%%”tØe5³3;@Dx@Œ "7J“æ#§é.ƒS§P†zõ‹Å?7È,lg•œù‹:»_W’HÁËB¤n£vQ¯´&õ–¼ÑekÇ®mΰ*èQ¦Ú¸±±Ÿû)¯²U}ý­|e¸p–Ž‚Ÿ°Þ[Òf/Iµ‚a ªbibO Ô\ª¤¼ÚöûÞA‘J.9ˆÔ·ÎÇFÑc.5µ~ú ¦æ³@qT¥ŒLVI© «À$Çߥ‹ßÙi>(xfP„fE7ÍaØçô'Á]›êjÇú~ìîÒäy\ê^Çþ)Ñá%wé†Ávö„rþ;GI7 q-PÈð2PàÆà9Ð_µþƒ$ endstream endobj 2 0 obj << /Type /Page /Contents 3 0 R /Resources 1 0 R /MediaBox [0 0 612 792] /Parent 6 0 R >> endobj 1 0 obj << /Font << /F72 4 0 R /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 9 0 obj << /Length 308 /Filter /FlateDecode >> stream xÚmP»nÃ0 Üý¥A ©‡kR§hfòÖvpl%1ÇìèßW²<$@¡AGòxG ø‡¤’)% “¦O`Éž\VÒÿÿ–¸‘’ð‡îu•¬¶ ‚( @R‚> endobj 7 0 obj << /Font << /F51 5 0 R /F60 10 0 R >> /ProcSet [ /PDF /Text ] >> endobj 13 0 obj << /Length 2723 /Filter /FlateDecode >> stream xÚ¥ÛŽä8õ}¾¢5/›’¨Pv®µ< eÒÂìD#„$܉»b&—"qº»X>žss*ÕÑ̵Աís¿¸ÔÝþÔÝñpW$I|LË»ª{wè§wJF{@د0~wÿî×ÈÔ:ÄÇÃQÝÝ?®¸¯ïþýؘ³·ãnŸ$I¤¾ßíÓ4‹><ítÙñÉÙçÝ^‡C¤vÿ¸ÿã»ßß/—eZÄxCN¡ïTk•¥BN^¦±JR&GíöY®£»½Šžv‰DÀÝÀIºæXÕy|ÌrÞùS<äEä7ñ¨3ýlÚµ O—ÉÛŽÇ¿Èe±AÜeùê`ySI¬2f­3Uãz<;+£çÆU ƒôfLÌ{Ó ÜÛ-,‚ó/†õ}ÌbE¤q’æ:ˆµˆÓ X4òWÔHc<S¤,¨"‹ªGÛŸ˜4˜™¾æÁs3Ⱥéy€¥ó¿eªWÊTÇXé`•×sánV‹f9i<˜çÐòôqy0YïA„<™w*:Ë6" q=¶‡ï‚X­ô¤EO(&KTô“8ýä&/d á>q0²µÒó€3¡½åk§ï…õä5ëeœ‰l{4'ÁßTVÄ9l!Ôzv[3û¡ºaF“ÉýxPé e0á׃iÛÇCví¿g7ÚÆ*Þ¢nO¾¢p¯¬¿H]¸E¥ä@îc‘ á¤XR‹Ö ÞÊZåÝÓ.Ë£¸ßUöJþpÆEÓ~ùöÅV_KþTít5¶ž[0D”LyV”<ŠTW4¦"b°„ÎöõWJY/d’²¾BÐÁ ÀL{á›këm$—¼•ÜäÇÂ`+‹(ǹÿJA>£ rta¹ÑUÑ*šœ`k'Ñ2ÚË•Ž(0‘€J™rÁÃÌÀÞZQ•¾ÑÊ!ŠÁAÏÿ/ƒöÅt!àAœŠÉ9 їîƶlYÁYjã̓™ìt5­&¸MËÑŽ°¿ÑØÈN£97Ÿeô&®ýÐW®mÍx R½Fc˜r4Æ tµßEg+ž¾Í>QÔ¸|I²B]G>"²"Å-gq¡~°C\—Ã0_.äÞíSçÙ+9Þ£NuqbqúO¡XßPœÄYHfKß õé!>Þw| %T<Cr+øBÍ£gç›a–Û} jð‹¥ŒI¢ó8€Ê»éW¨ŽÓNr;çUT»g€‘« O{ëépWoµ*£$µ½¥ é˜QF؈‚y'É5 ⾨5°Ãá8bÃÙWùSèN8|°§!:Æ›Ï Q´”ªCØþ#D[‚*Ñ=Z9†s M .x —]'[ê Š|¯,c¾ŠŠ†C2‡¢¥?I&§ºrÂxá­©okò9pÓ¾*í%® ýçC'¥$㾇Fç9D­IÖ(>'ëNgèG:É9oÂ|±[ž.bÇ ã@@­ñ²ßð'D‹÷Ðek.¡ [ªµ7‚—ÓF¢’5A8½Ú⊿µÅK(4(a1W0¾¦ _H†LÌŽk€×Éï®çŽ< ¦OÚÇ–åáPœÉca¼ä3œ\ù´5%Yè†Jù‚ÿ½u'Ô4æ‘‘¯ô¯³Ã’Yîð3Ž—Ò¿ðÇ:±8Wè¡[uÿ¡’€T¬¥`¸¶Bî·PÈýÓ,ØÖ¡Ì†Agķ䈥!Õ\p\ñíÓT±#!øÝ¡[üYòº.3aKK†B¯Z²x®nkF0'ƒ… cqoƒ`¦î7ƒòÖcåÁÇ=2æÕ%a‚]½]nô‚º¤o„ÖöÉ…üŒ[ pw¼ÂV™-þSoæ[.Škå…K/\dô:ÑV>+EÔÐ&¢„)¤zà/†B.A‹WñœŠ?Á¢¢¥ˆ$2̇Pôšp‘3Xð0š$ïW©cbháýfC‡òž–@½'ö<Æšƒ¸bNôÚÍe¡±=¥¦T„JTWëÆTKîè(oЉ–Uè5Ö顚âš)ɸpZCÂo³›šÏL(õDôœjŒq–A¦§Äj) ô­ ]@šÉŸ‹Àhf_ÕæaÇT"ŽJR(}'ØûžWVãûÀ‰q‘ ÜoÅÀåaÓâ,ïFž5n•*Íß8P¾_Òh@m:—LIÂg¤7çß”Ä_Ó $ú÷á+9Ž˜Lí âtÉõ™÷‡ƒ7l„ëö…Þ"ˆ“n3:Ï,´î ‚Ã#)¬ÖB‹EûÕFËÀR oÛ”)¶‚º4ytÛfB é!ïê ܃UªæhÚ×ûðþÃ(3ÓTcó)x+VQ³LíÜ’d@ƒÒz ·Ô®°¹óÒ} õXoç%ý´’r€ŸÎ½ØÍîF|ÔòÁ‡´ÃÕHË|e¤e¾Îã0[e0;/-V[í{Ûìæ(ªY A†ä¼%epi#CbGéôàþ çóÂs­Ç´©‘°õÚ!CÖZ7·$PJ[RÚ‰7T ¸Þ2D.¹&.-ȘkÆa4½úÙ<&^ ”QÈýøÑT^ˆÀ»ßºI?ôû¹wdÆ‹/æ…ü¢Q ¯¾ÈÏdô˜9ÝüÂÕü)(ú× ¿i5פÊÁ_²2¨öþ¼(7œÁn‹?µ!ôCk…ñg4+?¬”Ë/jøv޶Ùü?ÓP)TÌ`Ñ5Hbø Ž”£V kî†Ä© )T,X†Hï·ì£÷A:K­T^:Sôªø%„çØ ä`[··ISPa=!¿¢þ¤à endstream endobj 12 0 obj << /Type /Page /Contents 13 0 R /Resources 11 0 R /MediaBox [0 0 612 792] /Parent 6 0 R >> endobj 14 0 obj << /D [12 0 R /XYZ 90 720 null] >> endobj 15 0 obj << /D [12 0 R /XYZ 90 720 null] >> endobj 17 0 obj << /D [12 0 R /XYZ 90 632.528 null] >> endobj 11 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F54 16 0 R /F53 18 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 22 0 obj << /Length 3359 /Filter /FlateDecode >> stream xÚ…ZK“㶾ﯘÛrªvdñMUN^Ç©rI*ÛI%©Z IÈP¤ÂÇÎNÊ?>ýu7HH£KÝ@£Ñhô Šï¶ô‹ïvÛ»2M7»¬º«Oï¶ }~kë<#>>¾ûæy|o7»í.¾{܇$›»DÉýCºÝ»è»½í®³ÔO³è3ài=ÞWi4OýàL{ÿ¯Ç?¾ûþqY-O’ß`#~›Ÿ¢Ê6qš ?cO çYT÷§sëj3Ù€426æn°¦1O­•‘ÓÑL‚étnÏ» ÀË}REfèf7)|œü²LžŽöU`[–Äü×S?ØÍýC¾Í£?Ó¨r ý=Äé&Εëzpç •±¬jyê[Só¨Ýw-Ö(·ÔÑ“Æø:Nöä)—éÓñ>ލG:“¨—žú6lk?ßç¹ò:} pEäçIWÜ+yw8ò™&Â>n+–}\×ÐÖ³$~  M%1Ö ôŒ­ðDÚomNVukÍ M9´úYA ÞIšcßΓƒ(ÙXEÃÚæ‚¬Òéå;X§'îFi‡¾u{;¦vc,†mœuž ÉWiÅ»îÀzEínãLÚ%i£ˆ×¸ŽFžäÎçüJ|xøÄx0_F~2Æ­Hç4‚`%)I÷Ø“´d@©ZB€ÎN*¢ž77Tñ#Ž…¢±Ø€°‹¾‘Og_¤Ñšî0›ƒýp!LBø}£]ëyPóèš¶•¤Š/³Ç ;NJ剝޴çqá¢nÍ8Úe¥|«llGÇ׺ÿ’lnœß§ñÅM"Çoj3Ú÷$Ž —Få ‘ŠU®5z­ôû³?“8‚¢Üã:Ž‚“ë@“݉T $?ßëùâQbw\ë&Ýæ:Ñ]¨²7¥(¢G?þ0˜f»y½¡ANÇžlç¯%Y]VÓ4ÕÃ@‹„n¤5@jq4ß­Ešà:?ÁJãLÃ@²’iÔÏ+ujµñ¢7qFv9#¾ªMºÝ _ßÒ"Ùߘ°_BÁÑêÎv5wZ/޽y´©TãjÑ´~ø‹ƒÖ E~"ëý*=C#‹½ŠFÛî; ¯¬:ÀN81i6½¢qóFÞÌò›õ*°åÏ2OW:™I³4:šËã&YŽÅKcE—2^QG{ ž ã‘EÑâTÓòý‹ÜéJQæ¤N¹ñ_Ȧ‰(èúI—=*+C`µ=ëÆ[-ðÓßÒ-Hå™Ñ&GF“ÌßA4åÀhi(ÂC–%Ñß¡½, BËIavgY‰ _x#¥®B qFºð“Òú´ês±òýžWŒ£_”±”/X»¹ ØädX¥é.Á¿•ތڳx3æÃßcjiLP®Úù~Œç¥òþ”ïœGM1ªÎཱི…\ö*þ©Ç}Ô¥4–àåÕ=³v_YoƹļG&Ó6«ó¨"µø­“½bãqË…D½‚é.ýıï è^;-^dX|[¾%‹zôë[>røÁN™ðê+àå*³“<«Çw{õX¼ó[Ø«ê?ˆ½ZØg›eÔz©à¨µ®“¦7•º, º¥0õ_7`l|37Øyë«¡‹cÆWLkF”O2Á@3†Ó|²£–2¾jj<0ç¹óæò!0µºê¢:ûã¿W9jüô§þvÃb©Ä~ä0A\ý,Ÿ52¬”LZl·ÊHA…QuWÜ7âƒZoùÚÐ×›Œsz>U¹Džh§¬¨¢PTGõ»è/§ÝІdÚ;•“R‚LAIÁoä[¦Äú:=D:MGÑ.©éäd·#Ù“’0?ìßœ k°BéÍöÅy%"æGåÎÓ2$nœ$œüpãò®…²„S`¤ót¹°šUôšq<»ó’gHƒ‚äÖ±°©#±9Ov¯ò‰¤¦Dˆ¥ËÅ<ù•èCy“v\w…mí#dÊò0»:«ï:;r÷9‚%³…ñyI ÍH …äEj'»MBà6ˆÁËÄÇ4ú«¥]Õ‘àë}D²U$ÞeJ¾~#Xcô–”„íϽô–X¸×{§|]l9 ‹« ôö¬Øyå¥X‘XÝ䘂ÏxǺøj¼¨c-^’ÙAs¢Ò(UµÂÀû«Ÿï.TUwÍ müŠ”žFê›É4âlu€“îгájæZ”Þ‡•Ìzñ:MPõO|­l6Q2YN³"Q­Jã…Ñx“ÈÉþ(™x‰ë• 43¾ÖÌÝ&N´`Á ˆ²òR•¯²£v ;±I’¨0J¦'#f,*X°gì{WúC!ü¿gV'?7öÞ&½-?sœx£@ýÂê)ºÙã-“¨6›‹ìOÒ2HB ¶8µfï““|ÒÃI€¡¢)£eI`ôì×'çs?2B"š"ª‘ºØ‹µŸÜAúûyº4ô!ô[¹´š4En’hþš,f1àv}»Ÿ`þ§ó@šaSˆÔ³f|Õé½|?AU¾¼G§ð±?#Öø¸ÎBTÅÉ+{_ŸŽRÆ£…G½µ‹Áˆµ²4'ª fqÆ®>¦¤™ã?´ ô<*à3£IÇç~¼Ô„„†_Œå`€`° @`èÿzωâ(ˆ i"0Û€ýùšUX‘S²† ‰0ˆ~# _áx‰À’ÀµX*aÔXj<”ÞÝ·†E@iðÆ¢¡ /)áLà£ÀÖb uäÔ1I‚Ç„ ±þEz”Þ5ß‘-Y¼¡Ÿ%Šÿ>ažø¬>²oS¹øåõ]²A¿3) !K¡dW¿®dñ¥¸Âø¥¨ñ«Ši/Æv›R¢N %ê¹éWï0nl犑LÊ2a¿qIá@— 1¤0¡·^óL6~„ë½10ª„[ìf–û"HNG ш&£ìA—SRŠë쌕…^¾OáŒÕÌÛ[ ž$©ØYá³&ˆÍa+«-ua+vt1ä2‘D?Å=V¹%dšÏȹQK¢t‰ QÁHÞy‰3º=æ ÂA#X“#Ó½ŸNé%œêÀ Œí›’q|D&E}A¶ŽVM©%¥@ì•MêN]½DêhŽRšÛÉY_ŒzBbéZdØz’èÛvä|L*.¥ò@Yšë~Í*”øÞ¸K½4B­Rk¿»T8½±7µ'qÜ€x'}?Ã]Iа2ÅZ¦§/gLŒdÒ’ìgù8+±Õ2yG2”šK’ㄹ3ñNõž1žé/oÕ”¥[K =ò3N"e`–ú2:zŒÕje|ñX>Њ‹À±èfh\±Îñ£”¦®ÄÇ?*y§‚ÕåŒ ¡KÍø©ä–¯;‘¡TA¬ÊC®Mî¿8? Dù¡V\C“ G1ªFé¢ÀÓð*³CGƒ¾QUOÈc{ÕnÛž¥è!-7Oý‰“ UžÌÈñÙ–<Æ|S묤L»qOZl—àzÇõL|m×' „¨'QÃÕµ‚•’¾Ÿ4 M.òš*Ù”qêó·ßl(o6¶­ƒ¯^¹âM‘æ~Æ{!®Õrfôè››ï‹${Q‚E±s-I†B=Ii’1wu,U)&g(µµ­–‚½†0-ÿ§œâ£í""Ï+åzg˜‘ÏhÏf0ž›ÁÖýÐ|õÕ¸HäÁs”/aQãlôUÒ‹r°# ¼.¡¹n³Ы_¤+µ¸» °WϽ¿[Su^Šùæ¡™ nm”’Âߪþ_aÿçŠ7uD”3´)f8 Ó‚<õÔ(TNÿ–PB’Ž…uÌ 'ö“ÿŠá&ÿ_Z…7µ¥¨Š­`JÚ0ÊñòÍ ¦ Þ;ûÙ-er€û¡?-“W]«4ÄGÿo—ÿ W`ˆ endstream endobj 21 0 obj << /Type /Page /Contents 22 0 R /Resources 20 0 R /MediaBox [0 0 612 792] /Parent 6 0 R >> endobj 23 0 obj << /D [21 0 R /XYZ 90 720 null] >> endobj 24 0 obj << /D [21 0 R /XYZ 90 406.624 null] >> endobj 20 0 obj << /Font << /F51 5 0 R /F54 16 0 R /F72 4 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 27 0 obj << /Length 2988 /Filter /FlateDecode >> stream xÚY[Ûº~ϯXôee`íèFInŠf“EsŠî šEóÐW¢maeÊ¥ìqÑß¹Q’wurü r8¼Ìpæ›:º á]m뽉¤µ†õŒãÝÛ·w*ºŠÂÍ6ÜFW»ùÕÕ¿‚Ûƒ>õ¦[­“$ ¢?®Öiª‚Ÿ¿¯â"0Ý÷Ú<¯Öñv†A²ú÷ÃOo><Œ›©8þÓ Ço' SM¯²"ÝDIÊgz8صˆ‚º2š[ø Ì¡¶«(¨˜VîŒÝ×Öó:þö-wô ÊAèà ¾yÐZîʺ;O$ñY;£eZ»“hW—Ütg×›£pVÇÚÖ®ït_ÃÒ ¢«uÄ"­£d)–H[<ó6N]‹}ɘ ùÓh»ô^ˆµåïóö„C¸Û@xb)ØÑºÔ–g¥“N+–­ýFé~£ùí÷>Ê.N&žúú¨› Ü}{’"”óG,€ijT÷Æ¡¥ÀöxEI’Ö˜ŠI»¶cRÓöÂ…GBJÌ 7&çp™ ‚3³è¦!<×vÏ”3vÛAf¶²R·×¶þ¯¹`éüzZ5ÕvOLÔeÙvÕ¸(¬³ ÕW0¹²ÑÎ÷? îVEt-¨( ÉJðã`Æpû•^p¤x†¯¡ I8ŽF ÒÄÈè€'âIZ\[[™wb{/ëÝ™'Zï™;g•ä‡Éc¸È?”åt‡vhÐ3å=‰;“0F†ÿÇ6X䘜,Ëà–š†é`–[`„N–›î{^)³õ2±ëÎLk‡~\‹µOJÔ«»Yº0’QwVî5 ØæRÚë—‘jº®í·µcŽºçþžqÁ¸ nðö.¯Àa“4‹`¿¸Ø¨mÂûE›dµVYü ¡!ɳඵ¥9%Ód•ÎÁ »ÝD±@ëçöˆ&¡Ä”÷®w<­XE×kÛóXíÜ@Þ…mËli6" Nô¦tĈ³Ow…%1 ×Á4'á¯ûÃLôdÂñ½è ˆ\¢o"þö•Éçþvwèz±Ñ™=ž±6^AÑKå›ÌãüÏtÔmÌú/ëg hù;¾O —xíÝéB¬_—îrâ;Ä—Ï€Žïy>Ÿ>{ BûŸüa¥:f¬ßY÷ãÎÜpõÛÃê-Fžõ"ŠL”ˆÒ];ìØÉ¹áäÃQÛ5„”J?¢?“ù¥ç–èàgªàaU€Qó\]ÉŠš?c6‡›–VR¼Å`{„옪îá›\S<¿&°‰øˆá­éË·'€ÈçjéF³‘ñúý Žjj¹I$‰"… €ªvOÜš½ Žcƒë¹G'¦Öâ!£<ÚÄQ|qÎëõãÒ1U¾‰óøåQa ¢~º þ~ç“วSS—dëN(` ÛãmºQQziºq$qüO“$"wã1 ™±÷ÅD¢‘5`k²†4Mƒ/ð£ÀòHˆ˜t1+6òŠ'À€¶Äãqãˆïœì1ß,b,N‹&„ð*óî‡Ø²ç±ãS:B·*ã8â–鉿RV$-kµ‡Fl»Á¤,žÌ€X;ü;]áf5bë 9â£dœï)1p¢Pþ±$j;b54^±¤j°…–ƒv„ÁؼEó …‘,GYq-ÝŽ}{D+Û/Ýh ýrΫ)Ý7Õ@° 4:[ž{lÏgˆˆªµ×B?\ž+—¼3Ç\VWÜšÔ Ý‚n¢KÉ)bÇÅ8‹¢nÎ6I^˜Ï’^ÚÏVžSGý„g0ËbÎ]¸À ‘äÆß)XØN0ã­u]ûÄGx[²³Dt „qÙ^»'a†l¦ú¢ƒöÜAYÂÒ Û?¦V|9²ŠàMâ³SJ2®Æb(Ûdá÷¹ðøRÛŠ“©D$4£m…ér#ÃΛj^9e¾K5hKjrÆ+µÎF•­‡.äª÷öu-篃M­mè ¹wØ,¹ ´?^È‘ûã¨Çé>4$€@둊TYŽfVx•=…—0…Ó%Ý“SêG¼áX%¾æO§Ç¦J}žÎKûÄ—öébÆõ\ã'œ»ÃXÕÊäd,û©PDÂ+oà­U¨wô/òÈŽ×þ˜vÐÕÅq„•ôÐ,øÿ™²• Ãà þ/ÐvMµþBÿÝŒ4óèóÁáž7)†ÀT×1Œ„s¸Ä±é 5 yKPP»Ô ?Î×áw lµòìO‚q&“ÿ#¤œÙ¾Ô×âƒÅ<:‚úC\ÇígH¥1ÔGü~€¤éìØ+ێ߀ڎ*@¤™ã©ö³ü¿ H¬ŸÎÕ½€1Ò«*YLdP²{g¬Ä¨;Â1v` Y›%qè%GÅA‹å6#ÿ×PÅ×Q\E|¨hæäjö¨Ãe˜â?`=y´TñdA—²Jà;ÑqÏnÌöTì  Š3 Ú„ª¤ü冿„áÜidÆÃzáy`¯òbzA nŽ5ŒäqL¥Œ›ØømdëÅË‹ÑÕÌóbÜÇc7ÌywäÛî¿Ç²ºÀê:NþÄø‰bÖù6”7Wà ÀäŸRT8÷þÅŸy ŒXÇ('ž—$£ð>Ã:øW1RçjdãÿÃþ?ÉÖ6Æ endstream endobj 26 0 obj << /Type /Page /Contents 27 0 R /Resources 25 0 R /MediaBox [0 0 612 792] /Parent 6 0 R >> endobj 28 0 obj << /D [26 0 R /XYZ 90 720 null] >> endobj 29 0 obj << /D [26 0 R /XYZ 90 603.607 null] >> endobj 30 0 obj << /D [26 0 R /XYZ 90 559.108 null] >> endobj 31 0 obj << /D [26 0 R /XYZ 90 371.108 null] >> endobj 32 0 obj << /D [26 0 R /XYZ 90 175.413 null] >> endobj 25 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F54 16 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 36 0 obj << /Length 3427 /Filter /FlateDecode >> stream xÚZëoä¶ÿ~…ûédÀ«“(êÕ~JÓ¸¹8 ’Gk¹^ÅZi+i}qûÏw^¤¨µ®yÀ€ÅLjÎ g~3Üô&¿ô¦NnÊ,‹k]Ý4§7‰Œ>½I¥µ‚]@ñ÷û7ï¾ÍÓ›4‰ë¤Noîá÷û›#}»Ë’¤¨£¯¶l{ ýLGÏ ŸYt[eÑeÆÖt·?ßÿóÍ7÷þk¹R¿ÁRü?i¢aVß•ŽÓL3S÷Gd#Í£ó8ÜîT5všxäó-t‡ñIºØ}áö§Ÿ’Twvz™f{šÞÆ·;UÑW<ÎñH+K ´çTGg3ÎíܽŒøiø±o§'¦Ûíó­*#yí¿B>.Ë nv)ol—fqšó¾.};³\iqóþ6xaèLgÓXžÿ|lÜÚ‘gÓóø‰CˆLƒr±{¦ñ¢ÀY°í;!þÔ mZ¤ÞÞ>·}ËdŸaPŒ “©2VeŠ$ÖßÁï¦ádç#,*/¬4Y%qZ¥ŽÄORÈjÝ.Íã²T¢^4ª9™§[·#Í|g×Ê¢ ÀŸoó"2mgܦæßæ£yè8LóÄÍ|i¸È¸Áï<›……½<çãhÝÔõÒ?N1ï´HÂîò¸®kÙSÊ{–Ë-©¤*.òÜIå_ F]T°¾ÅFMÜrK†*14B Å‘ó‘T;¡úºžk†¾·ÍŒÊ§~¡ãqáÎ ;øó¥C¾TÆuåÕk=ßæ)ñ¼µ‰,íi=ó¨&hêv—F¢-äFL‘ ì(Q…œ‘–ÙïÑŠv™®¢Å¨¨;ʃ4É @ƒíۛƚê4ÖyéÕÎÍ;ØlgÚÚOQÅ¥*SÝ骯C.?l»ŽšeôáÛ<öù(\9"ÐÅ€û$D‡P³h’Ž&K@¥x2ôZ¼7´>üM¿w‡_,²ú·ó¶ Š]ýIÌÒD8€Û`–¦+¯ì!ÞL˦Öo_;Öt±Aœö6H½f´h*f–— —é„êLNnhyŒüxé´ãÙ‚UH¼ÉZ®½9‰`ÛÞe/éNÌ0Šœýi7ó†Ó½r¤eã¹ Üز󲞈$tQ™“ÊÈ$Ƶ2jHÝk¯÷;”®þ¸Ò0ÒÌ+]¯•®Eº²=x.JÞ^v£¾õJßz­Xÿ¾~e4z”64[—B]óž6Ì$褫O'I40µDøD Hùk0ð‹y2Ða{§Ä™=L{Þ9Ip>BBŽ´ÂD¿e²¡J·whìÍl¸eFšÀ|í¶šYôÛ!sWf¼!¤ï Dûá"]âž$À-½AÖguü–U¢pÂtRiµ0àÄØÛýÝÖ^VLN×È‹aÛ+7!Î1ÆØPÅœ©bŒË*ð‡™¢:6»Ž.HW)c(²“åæU¢Þ²í¹‹x‹t>·nUÃ+³„Á[Íp²Žò5ÁáfHõÌϦg²³`Å­}}06t~ÂúeÛ¹µò¨ŸÛ-%©Üç`Ý'JŠ¡@Óö+OË¢!ˆÔ£étŽkÈÓqœ&|þp[iÏB3\º½¬ÛMÃÖn/¨UW ¥\Ûþ:ïì¾e‹UuLÓvŠáA†ñÙˆ`Jä Њq|_FŽ–›˜@eE ˜g8_B:‰“Úƒ^‘-áeIÆeùà([1£|[ 'Ž’›dÃXyYÄE¶Îø$í9fíd_@8yçuþ'vƒ+zü”Õ >ý0üáýGn òØÀˆuK)·ØïãH ñrÞþrg‰G‰(;¬cªKÌÉtäS Ãý0sãqà9qê¢ØÑ‹$zà!w$X¼¸éê bŽW8`?\Àç» ÃOL…ê‚8&&d|Ï`Ž’»É‚ˆ™Ñ¹ &~Jò$‡)»5Ÿûú#ù Ñàr;cüÄîy´4!lŽÇ¸×öí©ý¼Àˆ†éTáú> xªÓìÚñj‰à8å|"pÚîåõ^<ÖNÛËÂâð$ÇÛÌb÷Öýâ8Š”åOÓÓ™À(¥UÛwûÄ6ižAú‡oâCE§˜÷“ôa¦ÀÃ>‚¾tUŽòâ‚GB>ø1ÚÓ0[÷¹—¡ín8­¶ñŒ¯Z§œ¦ŽfO5ʼ Ö£ ,L<ކBœÊ£®ŽŸ¸&°•”%$>ßòo§Y*RGvËTîtC±L‘1ìy‚± 4fÉ0y¾Œ‚&+ûùÒî SžŒ+±wâ;•ÔqVè _Ž–¿òÉ!¸%õHõá ÿ¶½;X­‚«sÇó­½.0©JSž¦ÇHc äE“A‘ÉQí²BÓõb|&!!`81ÈŸYüñƱpÓ¤¶ŸïÖÞ@GEvͶ.Qv*d{£6æ¨~ƒíëňmÉÀ³€š ¥ì «dEOGšÆY¬/ªè%dJMv|¾Í 4„ñ°B–'ÿøðØ–qâQ)!ˆ-%:Ž€¹ …z >pÀiº”€¨%ˆçÑ$.¤i/<iÔˆÕ¬‰ †^^8ÊW$"Øq ÃXÁS€¤ï¿~ÜJ쾤*Ý2WŒ moxþ¬Î²pK–åN×:¿…½Íˆ]×? wšó9¾\bd~C¸9ÖÚTˆAðƒX 3kh†ú47ð“ñVHÌáëdG®úáø‰ÓÿáX%Eœ*ÏFZ«XW1 €z³ˆ¢¨ vUïÓ*ë¬^Kó+¨w(ïzP©¨"àÏ}ª…bŠÎ]ˆQ»yØ ½7Ã8ú´D"/F FæÅ;. ›%Έ %™P ˜[™]"2—w^§œh gÓ¯RÚT_%ÌÃ)Ãà@‰¾uyþb·Øw‡ŽVBbñ“£ý÷ä±_»Ú“9Kͳ·ë_ðû% B)² ….€rSì6à)9∶B'+óõ°1òó4B!GX5Icù=~²2€šò¡ÒçC<+rÙ£Y®b•W’#SeB»@'¶e¢i\þo¡`ÓåÚ@¿1¤B ”ÚˆVa5ÆŸz)ø •ï(©û¡‘²›2¼cø!e) $¿KIÏ òlåÉÿ4â¥á2Ìùœá ©reQF=£cnnO[»¤Ž€ª—‹ ÄØ3?ùn¡&ÿI}>¸U€` k!ë—)àôÀ -\’®8ØŸŽ1žgæhäá壎|žH+­ãRHÉg6üööUF¼¤%T†í Ýs l¶Ì¦N!ÎayË-R€ôånRf¼q@G†Ps¤øõœáäÇEe&Ø­\¯ˆ¹0¼”k:Á7»ZÇEqU[ç{+íÊcÓÔr•†ä«iXá´Yä¤ ¥†ÂoºÅŒURdÇ3îI“Ø<¸<ôhÃèrüJGr1÷±%×D€ Åíù{9¾ JõÚ©¼¶o¯ ¼ ÷GVLK®Qùä™ÂRe¾‚Û´­:,»ä þí)ŽR·Ì)ÓŽ¤xÙŽ1p”ÀÄr)|zC‡ŽDZ;m'((ŒÜq©{ÂÓSš6B÷ m /$møIòÝ•°‡ q£Õ•Eà&6¬wŽØcçˆ-ÇŒ_¬ kY8àv‰m` Cüа¼ªëº‚(¹@Uæt5§J‡Ë@VØ!ìÏí+¡DÇIYÿásŸ‡( 7—Žâ,wob¾@a!网`g}KòÈ".ñ;‚§Ãߘ¥5ëtsãqRµrúªƒ8â)!p0òÔ›G¦µLÙsS`a¥V)ö+nHˆ|­=;ëß_¶Rgž7AjÊ6¨wºô ´””ù¼ƒÜ°ÐÚÏãÅ—ìË$p½¾RZÔ,´/)È–IpySH\‚A—~Q¡³AE´ôwae¹/†n9 ЏX÷¡¬ŸÆ×V²iÓóq¸Ì«»h‰n¯o¢Ù‚$›âà$&ÛÔË*úËV*˜¼ÎsοCI }‹¿èàK€œ'D”¨¶>œ)ò¥ÿÉÄïH!¾x^Ý"¹BßàZ™ñ„”Ó0Ý‹õ·@îµe-w#FQã}u•ôp™„®k6 >B2^¿#wMfåµiÃFÂ6=o£&Û¢%´M·®óâ˜5Ì„”,ad´'KFÒ’‘‡y¡·¬&û¨(½¡Ü‡¾á/ݪhl$1鳌ê•妮Æû7.èH±—5½chºtó—‚ Ú–mݯ(ü1¦µbñ(£•š$Aò³ «¿óqKò>¼õŠEm¤&.Qa)üqÃéDù´§Æö|$÷8KÁ;¼´Å9˜^æp'½V1Î ¸@¦“⣷Ÿ¹qæ}=ÑÝù6å«åØüöþ{)W ‹ç¶Ûú©“ªDz÷ÚôÓÌ5o<B°x2ë¶ò`€ƒG$à¢1£=\¤y ¢ô9‘÷‰1zD(&–xjA%C?­Úõݬ«jýS$Ý  endstream endobj 35 0 obj << /Type /Page /Contents 36 0 R /Resources 34 0 R /MediaBox [0 0 612 792] /Parent 6 0 R /Annots [ 33 0 R ] >> endobj 33 0 obj << /Type /Annot /Border [0 0 0] /Rect [284.727 400.047 473.152 410.956] /Subtype /Link /A << /S /GoTo /D (Emulating rdist) >> >> endobj 37 0 obj << /D [35 0 R /XYZ 90 720 null] >> endobj 38 0 obj << /D [35 0 R /XYZ 90 391.816 null] >> endobj 39 0 obj << /D [35 0 R /XYZ 90 164.883 null] >> endobj 34 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F60 10 0 R /F54 16 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 43 0 obj << /Length 2720 /Filter /FlateDecode >> stream xÚµÙnä¸ñ}¾Ây50-‹º•·ìdl€Ý 0F€ `i‰ÝÍ´ŽŽŽé1O]Ôa·1Y`,²X,ë.¶º àOÝÁ]E~çweó.èù’Ñö+ŒïßÝ?$êN~êîñ°&ñXÝýÓûxÒ—Ñô»}Ežúãnlj÷óç]˜{¦ÿlÍu·‹"¼d÷¯Ç¿¾ûþq>, ïpƒ_g'Íc_E1³c[à$Hóx¦É×g js Ôú6НÓkÀB{)bHË#ø'Ï<™Fˆ¼V7†a]‹Ä@ýñZý* |•ÅpÑ~î¦^Ð6V¦~VäkxFÓø»}¦ÞãÉ,‡ÚJ;8þd. r¥ûâ´±Çò;òô‰Å¸¹ Ã:ú_=“ ö*Ký" ·òèP*»#þÔóŒyäññLÉ’SØ×À¶ÃÓ²å4‚’­á·®ÿZ‰r¹+€~ T\›éh6'¸^7Õ¯—µÑ}-t–ÛÁÄYRåÖDk@§çã;w,Ùkcnte8VôFWú©¦ˆp<‘ø®½Ýb´œˆm×7º\PÙàÓ)*† ÃQ é@bÁ'Û\DªËÒVà™ ¥qzJð;Á®Ë‘]—À·Ð>Œ½àÀ‚8Õ#ƒm Ñ ‰CïÐõ 1_4ò@àýRyFlÁ1¼2…‹ ]ÔÃ$EáX9=ëã|‘bŽCa«muÿÌ3‘Ð>V¹÷Ãaã # î¹r”6.¤J= Çaš;Æ‚r‚óDˆÕ^l3¤¹Ñ¾bjít ·<Çs3gm0eãE]父àÉTè¡Aá}<è£Ðf|ŒD,;À¾Ù*^GâE ›®µ#yP.·ÂÁËø÷á†Åαs8Ù Fû4eÓ‰ÒÀÆLO映l wlKÃkD¼8[*F‡Ð äTGvµ"Ô­l\.ËW;œdî„çY‰¤)ZdônIöº?ø$›–¡ZB•ó@‡Q“IÇ9rÄÌRÒ°®aø¼Ë#Ïçh 1 N Üb´…óÃØ3 ò#?HCïGÚ~&޲īm{nl¼Bæ§.«ÿÜ¢L3ÉÈ™ËȨ,ˆ7-ÁY°vµ˜ÿpñ¤ñ¢ŸçㆎáÍ’m‰Lj¶1@ý¼K°f°Z‚Â(Rg.y3͆±ÔûîˆæÏ<¾?9G€8ñwü€gƒÃU<ìœIÂÁÄ6`±ë Œ`J-Á6¶Ö=ƒc‹Õm;ÁÕ5랺`]OÆá-póEx)G9²»e^x"»ÅÌ«I`®yf ha'>×ÛÀT?ðìðjk@UÝ[Wž„g‡…ä9Xš†‰œ¶]=¡.yáöUX±iå Ö†'$ñTB |}v%dp¡™b²ZÌô¡(zAÎrÏ!h9ŽÐò­Œ,úN8èÚ )ŠV,iP0hÑ¿an,‹h.¥À­™? S‰'žÄÛ]<›À®ŽK·k¯Ð/¢b©ªš§& Ú–Ÿr£8ø-ÿN•$‰ÛêKJ, €Jö 4‘"8qõ5]!9˜ÂSˆƒ­XÖÝv6Ü€ÒÂ/)ŒgÀ7âH$æL¡ 3ׇ]Îå.,)=#ô˜Œ<†/e!NÙÕ6œne‘Ÿi«F[4×,Ä{ ²S¯Åj³¥Àñ¯"Öp£è•â|–ë½Ë{G×/·4Q(³©Ûñž‰“]Áw)ý`‚ÆšE$˜-–æÏ±îžô×Ùç»ÃÄW¡zQ$hŽËY>0³‘ºËý"Mc*ãs?'Ù!Þðëý4ô÷uWêú/ùòÆïo]y/tV¥"±X@Ì“Æõ™§Ä`x@ñ?Œ uÈ«Šf­¡êHê·³èø+Ѻ¸xa yÑ£RÙÑ4k÷ SÙ R¥TÊ­8àÉIWó†Ám [1š%äpdܺaU̱ ‡œ•i(æÝ¦> Å'uº1w¬®ˆ£ý+òšžRÛƒmc€í z­M%G4¬ccå“ðYӆǒZ³®+@1¢Sr ¦b¨ó?3ˆÙ<£—# Ñ³Ù®SÀo?µÈ=ô7ÿ@³$WGÊ-é¬uL£áÌĨº²6ÚJx›.üíjáq®^*ìz²3‹ wh”·]ÜCeˆƒRH„©<$«wDjN´ uí‘Þñ£Ւ°Å!´üÔ3Ia(‚M¡³ âÆº“adÛZÖú[·{UèD«¦Ƶ†Dˆé2Jùq`w˜fhß /O©k#¸DÅÊ•[ÈÄVN¹”¶s±„§*i¨"ƒ)Õ¼1[6–+S~m“¯Ã_žÌá|´IAÅ^ѰÄ9O…M€ˆ×¤Ða~<˜öh)2Çï<š‘—ìHÄsi2²j…¾²ó–ŠÄ¸J= fn ¸ ̈†¼ÔÑVl‘ˆ-–€RÄÅí¬\j]š·»÷mÛ†,pÄ>Ç#éýxºÜ7”ôßU½³“ÆÞGN÷+ÔÞ'.¥Cµ.ÙÂÄ{šØ«ËéÕ¾N1BsS Õîðv«¿8SE䟸ŸÞ uÞำë7´t%ÛBQÚNà §áôV=ãZ-ÙaÓC%ì'\"™aEîmžºD–Úd)s¶Nq‹±h®'Ð 6¡HJϱ[õ˜±ÅièzÌÜÏâÈõ˜1w˜»ßè  Ùq¡U¼ÑaPäë29gÝ*.+é=AÍýñRW2æÑ®g+WS$;€A >žb+#@êsl»H«)W®8³ xõ,‚ Ç ~[RN^xáúW¶’fs.È`úŸ‰Èùæ{ÌÔ4ôLDö*ª½·.õE?Y$µW$È4X ʳ8Ùº.ØBvKæ*ôÓ¥êÿH‰9÷ήýȱÏmÔ‰¸ÄÊÖ%îš.œ¼äp/ç"q¨~ ßWÖ½Š˜/ãÒ\¯»¨™½%}­n3£I’WKTÛÿÁlø[˜ýq tk fiÛ:F”£<‹'Æ?8©–õTIfHY.îMvAƧóQË ®pF£êÀÒÚê[ßö-ó¡_-6ÉŠãÊúWŽÍ†ÍßÖæ(ýmY¤jú%Hë_Y™ÚŒGÅËÿžÚ³CœM/âz°´ü›–øM=ó/qK¦–;¾­_ð#VÝ¢vfìªqW4Ý$¯ÂÎ@œhzø´¹¿qýnF"çßrÛK¿ÚFòÓ:@#ɶçþ•"ækÿ¾—è¤rêêÚ –âþ—©Ê‰^g»v{ù ¢tï$ö2¾t€ád\l_å+àµÿ‡jØN endstream endobj 42 0 obj << /Type /Page /Contents 43 0 R /Resources 41 0 R /MediaBox [0 0 612 792] /Parent 48 0 R >> endobj 44 0 obj << /D [42 0 R /XYZ 90 720 null] >> endobj 45 0 obj << /D [42 0 R /XYZ 90 550.573 null] >> endobj 47 0 obj << /D [42 0 R /XYZ 90 256.957 null] >> endobj 41 0 obj << /Font << /F51 5 0 R /F54 16 0 R /F72 4 0 R /F52 19 0 R /F31 46 0 R /F60 10 0 R >> /ProcSet [ /PDF /Text ] >> endobj 51 0 obj << /Length 712 /Filter /FlateDecode >> stream xÚ•TA¯Ó0 ¾ïW”[*½ö%m×µ'è!àÄaòÚt oM¦4eLâÇcÇÙØÞ›„Pqûóg×¶H8|"iy²*˼­š¤ <.“º©rQVÄé+ öœ»(òz¹è`õ†v;9MÙ£œ€¹`=){ÕéI[C·É»¹ó³S9¡^3È"l&j Ðþ…ÏΦYѰNM…¥‘5*“+æC¼$«Á§ü6E,û›‚ߜĒõÏšQggRºÙÐ €hðÉ¿N³ªlÙ—´©Îv4äíæT°(kOrŠg´u6‚þ°w(µÌ:Ò\ï°–Òú-¤©Í†,ŒR}4ö–ìC;)RöÖDé7½ê!:Z¿(ÅK”ò¥(ø«›g~zºÊ"&ƯÒl ýõƒ5ü¢/à2㔡ZÎÎÑíC+Á²¥I¹³f©ÚÀô]áEÓØØúôj”ÇJ‚‘{"åà숤ÛÐÇçËÁR z ±Sç-pwëÁßÀ>æ-JØÈMÂVAKµQOô²ƒ{œþ·H­öTiéU£” ™¼·Ñn«v{RÙ!.•âr©”EWµ8m•0¥7vXÍy÷HÓßCÁoÁá+Ïhƒú¥ºþ`Ås”¢a~Úïï-ž+ endstream endobj 50 0 obj << /Type /Page /Contents 51 0 R /Resources 49 0 R /MediaBox [0 0 612 792] /Parent 48 0 R >> endobj 52 0 obj << /D [50 0 R /XYZ 90 720 null] >> endobj 49 0 obj << /Font << /F51 5 0 R /F60 10 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 55 0 obj << /Length 2751 /Filter /FlateDecode >> stream xÚµÛŽã¶õ}¿bŠ<¬ ¬µIÝH6HŠ}ËA‘(Ç¢mudi*Ê;;E>¾çF]<Ú´RøAäá!yî:½Kà—ÞUÉ]¡u\™òîpy“ôñM*£= ì¾óþ›,½K“¸Jªôîþ¸<â¾¾û)úêlŸF7ìöZëH}ØíÉ¢¿¸qlºýh‡ÑÕ»½*”©¢b÷÷ûïÞ|}?]š)õ_¨BŒWdê.-b•fFÈÊK§Ú0Yj·Ïrµ ¤È&Bà~Þnbmr…Ûm]ÅIvÇ)ïÿq·O£³ñ½ìtõW>í‚“«yv¶8ý¸Ó*r i:þZþŽöä:D’OCì…©Y˨I«8U"â?Á†TE¤å¸K#8‡ÝN•t®õÝÏIjN×ÁŽMß1!-R“êèØ ´ YÇñÁ¶­«ùâIjéIªÔq 1!aYâc 2=n9^^Æ…Êö[¡÷þìø ß µ€xI:Sq–¯ ùâlô¯-ÈäƒÚÒUìΊ‹‚Ñx1_ðµñ<Å϶yܱJØæÿi×é]Wyn˜Ó¸¼Û+…ÛÂT}Õ_.ÈsÏSÀ0DT–HßCßÒ‰wUlR³^·2÷¯«ëŽOü’??'Y£¶éýLY<ËÃÄBï³W½@ÀCöäïû«º¡ª½.!øãylra™4¥“<¢ñÉ‚º N üƒM­G=|äPDð•‘{Á¥],Û½À‘çæÈK;€ßÛá…xæm¼‚|2à8ô†mš',€¾&ƒû¯JÁ°œÌ’¤ WlÛ½Š™Ìþ×äh²¸LË¥ÉE]Y¶öª—Ï×.ï@ÄM·°L ‡$y_8þ£­·½§s!Ž–&йVøV<Á ÒÑu'9Ó@(I#Šbóy²$Ìßdb%Y‚Ë[|¦*γ,ðù¢+M‘PW*òOö â¾×np˜I#E®\©9ráöáJ †uî™a`NÎy>»Á±Á ™Cl!÷†5ºBãFÖàäsmëUÆLCÊìÜÑO2ÒÙŠUOqBÄøY®ó±Ös¢³Ç©‚{²ƒ¤¤³óίóÅâ¤oê@»ãÕO±jʈpŽwC¼¥´½¨â7¨ *!£ÌÚ—)q"U†_OUŠQ`ºî“¬=Ÿ›tq! 6§QódJ:€ ôQ$™€ÆªÓ’r7XÈ § ç%B_.H>'Û¾åjç*HB¢ÏKÀEI^ ýp¨‚2ÁF1y¬Ã!s1“ gÕæà.¶4®ub ‘¨t$dòņLžšRªÔ뫉™É‘"AWÉ•ëro2VÁÐXþc…!UÏð…:]SrW\±Ì4UIÚ”“·±+ åh‚ç÷ü¹¢‡Ñ"ÚÀìeÂ%¨gÈì©0©ûîíÈ×](ŽÙnË5§âò•’©ºô“£IÑKzöwhõl:QŒ<  ],§1öÐlæ9S‹õ»ÅssŒãrnpa«ïB¤3¦BE¥æà—&¸úd¤#Å-C§_¢ÃÙJ£Bda@ò¨? „Êš—¬äã©–¥È–p›¿Uâ•àpådqˆy£'eÜ•:}ˆïÐñÅ&Ͱt’€Ó»®Œ®Eñ#|®Npvæ(Ê4üJQ¿.©Rì­ò² Ý6•sxú¤7£ƒâªƒD«Üú ŸÙíûä\Îq÷¿ö 3Ÿ¼‹,6 v²^¦ØÎÀð‚Ö°ˆ |M92QÑ7Û·ˆIu뼜}ý¡fNó~l²h8¸§–kÐLK7AU¦¤~ •É&²´¼7ÂêPžÈÊ2ÖêÆµÙ|û&Ô´ªÈùý®È¨*}‡ëE„O ¸4‘‰)?¿6OÖˋ؋âJ*«:§d\œm gdø´|áùsƒuß*?ø¾½‚q¾lÕXºBŠú×÷!ôL:¦´Þ(Eùð>+o\¡$Yæ Kì ü2ÀÏ¥  ÚùÝxO¸M·<•‹ zC-Íéú™¶œŸ‘¶U²eR Y·–eeRfs¡„`¤:„/{ ¦B£&^MzÃ+m°2zžFǾmÝ ÷¶øµü¡ý×EoF6¼ BÞíèîžA¡¬$.²8Ó7|±5L]Fßâ11fg‚ÉóÐÐ{&E"FÐì츄M¥",ƒw\¾?\ êþ_ •‹!©®(ŸÖÇMF. Slü¶Kd1_~PcÛ×É$5ƒû9´o/j`|>¤g Àfâèñ•ò“m%:‰+‰ôYIé“BÐKa3™ÿ «»:ì¤z@ÄÅëÞ›û­¼Q`ÛàTÍx^û9Kð¸e„þEz`îÑ­¦HžAп¬^¼Ù.6â·‚8™Ío ¿¿Õæ›Û*g+Ô„š¥ªâjýGÌ=iP°¯—‹š»wSëR ÙebÀ4\®SYy[îgz*–©ùÃg q¨Csó›*ñþ2©pÕ‰’²1_埼æø2=Øv§ðZ¿e½ôøwíôüµU endstream endobj 54 0 obj << /Type /Page /Contents 55 0 R /Resources 53 0 R /MediaBox [0 0 612 792] /Parent 48 0 R >> endobj 56 0 obj << /D [54 0 R /XYZ 90 720 null] >> endobj 57 0 obj << /D [54 0 R /XYZ 90 720 null] >> endobj 58 0 obj << /D [54 0 R /XYZ 90 657.663 null] >> endobj 53 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 19 0 R /F31 46 0 R /F60 10 0 R /F54 16 0 R /F58 59 0 R /F55 60 0 R >> /ProcSet [ /PDF /Text ] >> endobj 63 0 obj << /Length 2119 /Filter /FlateDecode >> stream xÚ¥ÛnëÆñý|…€>„F,î…·$@{ÐéCσ ô¡ е¸²S¤ËKlý}æ¶%3±ƒBœÍîÎ}Vmø©M™lrcâÒ›ÝñS"اOJ -0l»ÿôù§TmT—I©6÷û¥ˆûjó器ٚ$ÉÊèëÞ·uëamlô«Æ¯‰îo Mc××®¹ùåþŸþ~?ï–jýÎqãÍy²äâ<ÓMVØXËgúO¢rÜìúìJÇYš‚hâúk GT&r»±î¶Ñàÿ7ùvç™òr¨w7:¼}Ó îöîÑ·H—¬³¢*ÜcÇßç`Úùa¸Eðwø¯¦‰<ɿ꣮­ð>pò­2±JùuË:^–]_ùžÁñàO ‡nj*¶Í"ÄP|¦<Â;«h|ÓVÛ t•Á~E¬Š’7üg8¬5:jüøÝ€ ‚mêö‰AÇćÕ#Ãî.ÝM€Ôá,HEÓà÷SÃ$2áÀýÈ uÇçÆ3œ÷±wG¦ÔC|þQDßZÙ‹ñwSû펯¡,ø‡½©àir×5®¯("Ë£á4ŒþˆfÉ3P©ïQAY:d†ªîÁª]âåÅÃô…‡fùìbŸÀF+ލ5‚ë;ˆ7Ç É¬°ÞƒcÊѦçgÖ!˜‡QäRÀ|¶%,Ó°†Üc˜f¯‚c6Fyú<±–t’Çia/ÜkÇc³ä¼ .Ø^°-Uô0ŒÅÂïÐ…¯ÍÚ´Ý2ZT‹àª uªã<ïϪ’óÀ~Ž—m'‡“uÃn ó±…2øg׻ы6ò4βôÒiÎæ‡Œ†ê5øúùÀ‹—òr޲,êÄ155hG“JÀ¦ÎÌâû¾ë¡>@Jaü¾ïŽŒyÜ0l I¨nyqâ-™w<¸‘Ñ«z5p©RåÒk±tMM÷x•»bíXUòo¡¯T…éjk´¨Fk6"¯Ñ¹Ö&Ñ=…â@”†ÿÃ+á½µ‰ê=£HË~;Vü¡c࣌X()Ì¡!×>±$Ö½P•Mbcf%tTÔ,Ä!(¾ñkZKUœ%*ü!ä(ÑŠKS^„Ö²Z˜$Ú±C$ËÌœDý$ØN¾|SL?º„:ŒBÞ_“a1ÌYÃß îàEÒ¬D€[O9Å„ÐEá/XNÜBí„Þc_CmcL$;âî’åñO¿Îš+–xG ¤ŽëOðZCõ‚êWÛHÑzôãÀ\—) uTfþrÆgÉ”lÈQÉÇlô/ YÏTÑ5T;}8ƒ÷]Ópi‚ ~aCµ#Ë,Ex;ä[+7úË t)iôµ;};Æq®­Á;´ ©´û®!‰›2¶Ê ]KÀp·07(ñþ`­bu‡·DDe‹Ük)m¡äáw÷¦Ö~a*Ü#5ù%™òí·ý‘¿Ÿ§¡Ù‚ì™Ä6»¸¼dúó!¹ò‚®Ì¥ðnØËÖK¢zWØu¸m35DA×'ÿ§Lb5x´£Æ ÁEk„˃[¸'aªnzhÞu µl»ýHÅK“‹céÂìÕN×4¾ZKºÔ±Éç,»k´T«w0y¬ç*GS6;É Âf}"v’Rtgh¸eh…ÐONSJ´iAUëÝ­Ž C¯ 0E`š…L-_‰@ INRI¿ïú#òïùËñ쒔ɫå$±¤/ãU/Kßr€NT®¹»ÁM™ÆIÈ„†ÔKA®¢Ÿ…zB{SM„)9÷P²°k„ÚÒ`s"ó¥Ìúuµ±AÙÜf|ÿýêX¡b{+¨^¥ÒÉâÉë{•uhÅñž¡ å\ε•Þ¢ Z†‘rÕÇ¢B,Öñ2ZTÆÛÖ2 #ÚBö^½¢Òb)ÿÀmࡦÛF_—Ûr÷Ó?ɲ©ÃÅ,U‰Ò63_KÐ!P·|¼1‡Ê Û˜Ï©ìýÞðvMR—ÎrÌÿ!Gϰ_ÍVƒãB—ÆóãŽ> endobj 64 0 obj << /D [62 0 R /XYZ 90 720 null] >> endobj 61 0 obj << /Font << /F51 5 0 R /F60 10 0 R /F52 19 0 R /F54 16 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 67 0 obj << /Length 2403 /Filter /FlateDecode >> stream xÚÅYMÏܸ ¾çW °‡õ,2Þ±%Èa[t‹í¡ØÃ ôШbkf„׳–œÙ·¿¾¤Hùcâ zhd,š’(êáCÒIgø›ªó¡"®dy¨»wg–¾¾Køé §•Æ^Þýøs–’s\«äðrY/ñÒþýñ¦îNÇ“"J?ORfÑŸµs¦¿’Ð:5:ÝOi‘Ê*ªŽÿ|ùË»?½Ì›fiú «Pã ³Dr(ã*Ï%Z•ˆ4®Òä—2N„$Ó~tÝýxJÎÙ9º+Fö8ÂbY¤®úcA£®§Ñꦿ aÏÇ=IZø”æqžä´ðߎ¥ˆ45+£›:¦eôù˜AÒ(yà ŠTÓàÑQ®HÒë_Mßh¸¤Ñu«FåÌГ ó#Õ“¨ÕøØ°‰éÚÄ4/ãT€§¼mÎ4oöNîËEÔ7S£™7² Ñ­vÚÒ®ÿ8'²Õ6>žÊôýÒ“Š»i\öpç$.óòpJDœd´œþ]uw´Qd2RŸà®Ëh`Ç”‘·ý=¾¬À/$\ÃÈ3Úf¼hp G¿l LOóÐ/h \ŸÆ7þkß=EœË,܃bÇ=iŠAë{Z¼T —pØ)œ†C6#CtÁ9ÌžØÌ]s©y9ßÃ{¶dq‘–‹)Þë2´ìô„^)È‹„äZô:0Ï#º ­{’«ºÖÖjžwFÒꆑ'º›êIfñ8šeQ£ÐoLÊè寓¬Vãì™õºà"Ë:ËM ѶÖ}cýÙÎÛSQDڸūpÓàÖ7ôÄ*`%¼ç·þyêð_>/F–ç ‰ä0á{'HE‚9À`~ÁðDŠBÀ•¿¯rµ) üÚ ânÆ’¨ðŽ4GþÁc5×[7YÇ+áz&õa Qžmð™¥1Ðç:Ìwa ü7ë ›õÁg5Q ­þmÒ}­ñ*ó,ú…Ã{È¥U§•ØÞN3ôß;Ë‚–OÄ%€ä¦mé‰ïƒô̵ 5°§¬’诃3µ&5ÕÚž€aýQ_ÕØh,M÷—UØ·Š.p¢eÖ^¸‰ ¢_Á%­é_í.=ž‚ææ´õÐòáƒ\0Rv6ʳXTò›, Q¼2‡9q&’Ù£ñà…Ñ\èn¾¿l¹?VÑmkiÖdìÀ¡ îb%ðx%¾‰¨<.Š4h‘ ¼ßòâN9P\•oÄÃÜ×yö ü†G!•W¢úöÍ ‹|ö<…5d}f6çmâ+$m†ò©›J•qªÝ4ò°öT(èx¬$•äÊÑI$Ežh2-nºóV¤Q=àuš£Þ%2S¤hëÑÜ]L¿A ™§¢¬Ò"®’ŠÎ¬€œF¿úì3\Gê0š³Õyvü†´[ÅIZ>±D“ºNæßú)Þî£þl0ÔÒ ¬7=²–§C(º«ƒ.©SVs$+ÒtžVï¦VÌõJ4O¶ß_úÏ›3œö2øp.#{£bŒêг/ÂÄMï­ùä}ZÁMHL"gœœYU 5õŒX…ê·ÆàÙGmØ©|Ú ÈÝG7<.ØÎ Þ|&˜Dè0dÁ©?©O”g–d«ny½ maû¯%½Ÿú°Lc>›fò7ágúeN[Š\Œ ±ìw÷àëè­¯èÀêW˰"…Dz‚ÖÌiÕ› 5¾Þ^nŠû¸„>¥Ð¤ùš‡NîíÎØÞ´+Ëd® öÖ< b¬§Rh/ˆí[em²³^ZÅi9sà‡Ý!²$-˜ÒÂ|m½,?ôÛ qh«ŒK±cTúÿ3ê™–OyY舊¯\Ç–jrPy0ÕóR^Ï÷ª´J—¡m×ëY×ê‘jÂf#Rkèl|„˜) m°s‡énßÓ9XÜ8´óèþÆ7Lý°¥ƒê'Óo2-I‚`˜z±©A#D5Ü@Ξ7Ý}]XmTS+ÆpÀ¡ý¬yÔ苚Z°lr³h©]ÃvÆÖ~˧íh·‹igM*¼x€™~Þô· –mxè“ì¼Å“ðÈޠ€j¨ƒž#hmB ¼‚={‡Õqk€|ëaÿë6›i8]X“YD«þÅ+v²<ÇgøZ {Ðf„ãÅ:*KàRÔœl@×§sø­/º¿RоŒCGrEûF“ü”¹à¯hx½n§¾!>ýÀÜYbÝàH†4I…xÐZŠw*B|4wz °Tdú³dϯLåVàl<0N<ÙÎm-H—dƒ Õt^Äè—"bë7E£¾øû ÑÎ[ÀňÉTæÑO~=ˆ`H¦ØòŽ*‹Üæ&=C½à(Ö“«~»B>nóT¦%ѯ™ê8< nš{E¤S jH$æ}Å»tZõÛæ”‹dÖì°f 3 ¿¢jP®Xì‰Þž…Ü¿UÏ€ãf’\—›l§` ôÅh]Ȱ½^÷ÀëÂ`çûŒÏÙv „u4Ê4_5)8BC$„÷êS Ó% ïpé9 ƒÔÉ–¤þK Ðm(˜oX=_&æ<ŒãõÝb ›’±)ùSe5WÍk€:‚C" îw]Ùz,ˆŽëo4Âo£Ô!´%ˆ6þˆðqì‹+)b˜§æ)tn;® ͹Ÿb‰}âÄU‹S󧺱1½rú Ù΢ñkrX +œ†èbï ±ù¢†ÑÀè¾(F¿b6 Žk°>^ ,òu¨þì[™‘ŠtHZwü¸ÙCòyO¾âV%9sV¨B[té%uAoôÊGÑ9ôBøvÕ+®Þ+zKq&C/£GŸ!àÕº·ù á»ÃS»#áø\`@ @û G>¾!š§gŠ+šßúÏ„øà{4Ø»ªõvÚÔC!âFS;_HìÎnÃt½±Ú²Ëï«–€ã#,|Œ?WÆ }†#™i4¿õ±¿wL„«YÁÀ‚‘ÙÇ!¤%”0íûï4¹ç ÔÅÿׄ_œŽŸ$Ù¶ÇMóªœI°ÜÜ9Wè}êŠ÷jq¨Ûý™ó ~÷¿ÿƒâ¿;µÕwáÿPþ>¯Š endstream endobj 66 0 obj << /Type /Page /Contents 67 0 R /Resources 65 0 R /MediaBox [0 0 612 792] /Parent 48 0 R >> endobj 68 0 obj << /D [66 0 R /XYZ 90 720 null] >> endobj 69 0 obj << /D [66 0 R /XYZ 90 532.203 null] >> endobj 65 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F52 19 0 R /F55 60 0 R /F72 4 0 R /F58 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 72 0 obj << /Length 696 /Filter /FlateDecode >> stream xÚÍVMs›0½ûW0“‹9 j%"3¹´“zö­í€œ0” H›ßÂØJÜ´iR|0H»Ooß~d4H9'™AѬè´úmÓ]„ÑÌâýfõîc P’Ñ ‚Ív±)ƒÏk aIJ8ÉÖ¶ª½®ZFœ‹õ³ÿ|½ %_½6U^‡_7ŸV—›ýq1c'øX‹#BI²$–€$2H¤ À…£t¢_¼¾ü™7·µrzëþ»Þ E?e¹à†&’ß| ¦Å¿¾BAvà µÄ¨Fðk£‡ÛîÜn¡ÎrÆÃ`²†™58ã…V™!øhvá"ýBcêF¹ØÞöFw}%ÜÝ1´Èˆ½9!$DubjÑÁƒŽ›€éRÑ8û¿ˆ?BÕº]›¶LÀÙ‹\¾B(tÛ]?Z DŠ:ï:OÐL8wAŸŸ»P¦ÕÅ]ÕÛFTäâAŸî)% ì ›ûÑñT&ç"ãáY¶¹ÔM^µ87€>÷øÉÕ“oN娾hô]’I©\ê’}¥ÛN}T[L³ãb4Έ±ŒãÊÄA:¨6o|êÑCzÄ7ŠfAÍkbbÞè¡íoó¾W¦Ýñ~ªŸ$%”‰½²£·®Z_/ÅŒHm9n¶ £õ iL8¤;èU]¹);çÓä}qSµ×îÉ"»»²2ª°¯åkÀ’‰)Óe"ãX&¼,«¶ëóºÎ¯jõ[Âa%ð}©oµvsè*7¾¾ÈHÊ…G:†ó)å•R–cgcXK^‰6¾¿_kÐÙ$vÊÜ)Óý‹awÇ •MûPFtI%,©_a¼)s$›û?âŽC³v.oÄݘ3?IfsÉvæiÑÙ‹ŸÃÕ•ýИBÕéÁêIñ9.ÙKw“ýxþ^¸¸& endstream endobj 71 0 obj << /Type /Page /Contents 72 0 R /Resources 70 0 R /MediaBox [0 0 612 792] /Parent 48 0 R >> endobj 73 0 obj << /D [71 0 R /XYZ 90 720 null] >> endobj 70 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F58 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 76 0 obj << /Length 1523 /Filter /FlateDecode >> stream xÚ½XKÛ6¾ï¯0Cd`͈Ô{/R¤AzÈ¥zh ”–h›]Y2HyÝí¯ï ‡”-¯6AÑ"É£ápæ›gèå‹þóE/Š$aUZ.êÃ]ì¹wÜS+X]I|Xß½û1ã ³*®øb½½V±n¿F?ìåqPf¹J’$ËUšfÑ'5 ºÛÓÒ ªY®D^¤UÄùò÷õOw×£ÕLˆoÀB‰¸¾(Y•ç)Ââ¼då"/SÆ“”éñ7ÃZ'Êka V€[°:麕֒ìD±HYVdÃI=Ì©%iDtW·§F-tmu«ðºÀJ^z›â{ؼQºÊsV%Õb•p–”Á›ÿüoÉçd< éÆô²©¥ÍAÅRžþ‹p¤_ fŒFß©95X>e„ÞP°zCëßÊô–ÈwéY¬Êœ•q1EÛ¨­<µƒéOƒúE†Šýáyµ;Ï%9+€ÿ¿“ì³aû鈡±êÊ Ò1îOÄ<ÈÆ+’žQ”¨Êóµ?î‰ÄÄ5@ïJ(ãH3øRè x’Ç"¨´ÏTò/j›£OWñVÆ`Ï©«AíA•®鞸»~@¢šÖî`&qC=9Ôæ™Ø˜AŒ(/¢/¡¶‘/Û–äCAÒï*†ø9Þ8ü8urÓª©MsêˆJò~RL¡Õ¹”8‹FÉ-½‹ÊrÔèözZŒ(ú}îZ˜“$(i¯îQ5]:÷y[c J5† àœ®rÏû>²j8‰¼x;s6T< Y œÙTjñåNÀæÑøÐSš‰9ì]…õ¨ÿ@aûÆUÖµn¼´«ÂyX…› ¢@w Ä]ÿxtã.ìWªòýÖ“UÞààÖý‘ÑŒŸT×"õªP‡È|΀»Ñ4:°Bà*Y£Â=qC©¥qíE_fÎÙ½¿ ¨y °};ŠÈ/ƯÅe{è]x†™ëBñSS¹L øP†’y æÞ>Szt­ÖP%˜†¾°Lé¬öó5K¯ÇLJ¼Zý«Ã,3HZ«åF·zxž€)¼ÊñÀÕ(NX 2n ˜×qœ‘Á,.ÇYÌ8MãŸñƒ+]ºn…AE ÒÛצnÁòðð§Ëg—š‰óèPLÐ –Šötüª‘||_¾%íµìHõ^bPŸB+…­ƒ+dC]E°åá”%Î@ZxâkëN.nßµ1äXÈ®ÅÂá~°Cs¤G îöW>©õƺv]:­»½›kØx-5ñ™)þœÂžeÅä9Öd̘šòøä}ýáã§Ï_ˆ¼‰ï˯k¡Ë†”­>úGâe@øMÓŒ®äV‡ yO<éøwÈøK‰¸}ЀÓþu z;Z2þ¨ L?œ|ŽvSΣ¹:AwE8=Às/ý®4ä~.Þ7îOô³c&FÿN ubè¦ÖYšÆzXÐpÜÃòõ  мvûo8é}ì»·ô~‹ã éÏž² óñp:O¸ŒÄŸ§ð#a£¶áŽÓ¯ƒ¼Å3‰I°ë05,üâq Y| endstream endobj 75 0 obj << /Type /Page /Contents 76 0 R /Resources 74 0 R /MediaBox [0 0 612 792] /Parent 80 0 R >> endobj 77 0 obj << /D [75 0 R /XYZ 90 720 null] >> endobj 78 0 obj << /D [75 0 R /XYZ 90 377.617 null] >> endobj 79 0 obj << /D [75 0 R /XYZ 90 221.053 null] >> endobj 74 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F58 59 0 R /F72 4 0 R /F54 16 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 83 0 obj << /Length 809 /Filter /FlateDecode >> stream xÚÍVM›0½çW ¥²C I¥¨êç¡UÛÃFê¡­VŽ1‰°)6éæÒß^còÙÔK“f<óÞóÌ(À ä8ËÀ™G‘¿œ-TŒóv?Æòd€wñf=š~ˆ,³ÎÎS¬Sç» Â‰.ãdé¾Í0ÝŠ'^ÍÜCØ<#w=YDn-XE`>ù¹þ8z¿îÊÅaø ž&¢(ÎÂ_&ɬÁÀÂ_8Ébæƒh¦!›:ò¼'aÏóNZO( ÉÔÊ…Ë_*ßÌŸsãÚ‘ Œrü«ÆIv ˆw5‘Øb÷‡´µ…XyÔ– é±ó?Öo>a\š¨áÚâ¤(s¬mHÓ6åRaœ²ªâ,@Híïó)Âðã›2«´Qá‚ |Få¼.°éÚ½Tg¾íÚisǸ˜¦Ä$nYŠÉ^@.puU^ÒÍȶ®`#µAÄòÜcµà¯ìe-”,'èØÔ—½lâPüXsß&Q¿e4ДZÖbèÞ§:,#9æSÉûYÏA>¥â=+º; L – ~  ¬aëm[™ß¬Ú«K˜Íåñ>l™pŠº‰µÊ`°¡ì4͘ç*á€5¯¦9C0Ÿòéξ—t_1ÈquÀ§f’xÓ b÷ekÒ Õ_•ö,#=þ÷Ïœ²ô6Ç Wýî ^W¸›‘ÖlÇê‡özѰìj´,SÔ,”a§¡T3£ %«ÔæQ?åUÊÎÃM{¯rsð·yîàÁXíTI0ËÕy âhmZ…ý­µ ¶!í>”m§–¯!l"Òº"t«íw_ï S! ÚóáeáYn¨S/þ0òã(¹l“MW]®½N“(Üs±R!fÖ_»š” Jü„—Xª¡™ dÁR¼šE+q,ñJÝÄÑv?¢¼–‡ïüœ‹'þ<åßÙ¼z05ÏÓ~=MWG²'ÜåÞPâ  nÕJ Á €’g7¨¢+Žmˆ7² êr•Á\6逘h‡e¯Ô…Cø‡F’ô:îÿä€1º…ƒŽ»‰CóÏî/ ÷µn endstream endobj 82 0 obj << /Type /Page /Contents 83 0 R /Resources 81 0 R /MediaBox [0 0 612 792] /Parent 80 0 R >> endobj 84 0 obj << /D [82 0 R /XYZ 90 720 null] >> endobj 81 0 obj << /Font << /F51 5 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 87 0 obj << /Length 1109 /Filter /FlateDecode >> stream xÚ­Vßs£6~Ï_A¯)¾ 2 vfòЦÉõ:s}©ßz}AM1BÄñß]$9Æv’¶WûA‹´úö‡v?‰z!ü©· ½,ŽÉ*YzysÚÙÇ+j¥‚#Ÿ×Wó‡õhHVáŠzëòb]xúwë4W³ Žc?º™I²ð?q­E»5“½fJóbDi–¬|ÏþZÿvu¿>X]DÑ;n¡Æ™_1õ–d•¦ ºeK²L2/]&„ƉñmÃòÇ¡»-YÝs4 `„’¤fYï;~›W<ì‡f\h’`‚"££Þ÷ßü›Qq.ŒØÔú Šý͸Åd§'–'^S7 ùXøw%æya>z-ï,Ý ÚÈ¢5£®„]-„â9hïÉ…ŒXè/ì‘[ÜAYigÇB¶?ZðÍ jkèÌXŠÚ¹ÁZ»–WÒÁÉÖ¹¨¬°³3;©Šþ»Ëá§Í&懯á"„=ˆtn‚¶¦;¦¡$ÛÛÖ“-¿ÍÌùN’L'Çû¦í ù¿ÿý_I†®`š¿pfpþEIí…eDPÆ^'$ÍŒrDb¡4òÿÀFÂLÇZí¹z*H.ÛÒ MûMf$u­ðòœ,¨iÆfEQK3ö\¡qT¼‘ È”K¯•Ø@ZH R*Ù˜ef&rÞ΢¥¯«¦z®®abIý=~ÉÁ¬îDmõZŽÄ0ñƒ´SÕKJcB6¥6rHCšŒ†DÎÍú‡#naáWà·„¢,³bfȤDª-y£^žF}%÷rÚðÃÈM)Î ¶©ù¥hæ ëá¸ÇwÖ\´æÍ“Daè$GŽ\jª7wÀNtl×qÕˆ¾îÉæ2ÎÁÔfLöYÿ7uát endstream endobj 86 0 obj << /Type /Page /Contents 87 0 R /Resources 85 0 R /MediaBox [0 0 612 792] /Parent 80 0 R >> endobj 88 0 obj << /D [86 0 R /XYZ 90 720 null] >> endobj 89 0 obj << /D [86 0 R /XYZ 90 476.115 null] >> endobj 85 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 92 0 obj << /Length 1981 /Filter /FlateDecode >> stream xÚµÙŽã6ò}¾Â@Œ<ˆÙI] 4‚l`dóÒ@$‹µDÛÚV‹ZÝã<äÛ·R¶Üê\@쫊Åb±.*Ú„ð6y¸I•¹Î6åã›ÐaÞDÚÃî‚ãŸwon¾‰£MŠ<Ì£ÍÝþRÄ]µù)ˆôv'ó8Ƀ/÷¦=Ô­Ùî”ÒÁ“ÄQwÛLÓhûºh¶ÿ¾ûöÍ×wóv±”¿£r¼PHE›LäI¢QŸHI‘Ëh“dZDJ³R7OES:}nîë&ÅÁ´ãv…q¼æcñØ5FØþ€Zmv,1;’8ó‰ûXÌ O[G‚Æqðõ¿¾b Ü¦ªDiÛý‚ÿ·d\lzóM*á„"ëãaw2Ùf§´PaÌìR(¡`·D?Àé‚£éñÒ8¶0³SSñô=Ý420ßÏa¤3|Î.ouKEâíúK—`ÂÁ‰–:gQˆt¢{C8JcaLƒU,FÐÌ Tðùv§£”ýÄòJ¸”¢­qKO[c§~±Åg0KO[S©nm÷Õ'²#ÕìhZ\?:פÓ*9Ë’ÊYPcm[ÜÝyo{ª4Q`‘##»©ïèœvÀã™álÔ$¼4*8¯Ža«DDaÊ{¬tÍþ‘IƒbÄõ†Z¸«–‹«5ø…¿ê›ièo[Í œc4ý¾¥Ï9­n!‡5—‘.` ·¬*iùK;Úa|+Öœ¸b!eîü3ù“þ©À@¥ «¾h ˆ+F.¢ ƒ)΃šù,s<kv*žÎ¡gVœ(¤¤œpV4ã .©0¾u;£C{- <ðþSÏQ-ÖîðîˆÞ'¥ xTΧñá~â°ËóÅ©µïí#CB!¦8ÏdP6µ3SŸë¦aJeýÜ6¶¨Óšg8Q!w&D^ÄΰvÌ:–|ؾ28h†ÎU³0zÅUS%d–ÿ¾Š:%©$«k±ZdŽ¥ÿBåƒ÷dÁ<(ʯKAÖò#ü1òž´щžÉt¦e f ºh„ç,“Co§vKžEbù|Ý &(ôƒj*½#äKßX5>¡ÜQõV ý RSÿÀ³¯êÞ””䡚¢}âȹ3Ryô¥/ôFê•Þt%ïG¦yI¾ª~u²‹q¹[kûÇ¢iN+u€Â†KN*òwä¬-–úiÃæ££Tõô|hb{v-€Üõ¹(Cñ~Ä’ÂÉž\ærg J×LŒ®ƒäÌIÈJÈ­F ´qj™Eƒúz€DЖÆz¾utùªÜt阵N×wÓ±ˆ³Ì/œº ¬6÷¡×Û$ÐCçùe‚X> ÃG )­—Dó_{Ï¥KÛ¡¡O5ˆàDèQDK ŽžÈ¥±|:Â2u•Oõ34ìÜMöãî'ènF D®Êrí¦Äé»#¬v|«˜¿ÙÕJPnv V:å"ôMøw>.¸S ½¯|4Ð/1Õ“ÐÝ4{:ÍH‘näYÝ:fž¦+zrdœ½tdd…Pjýbržû àÖþù’k½4ìY•*UÒ‚ësÊb “à~0vR ÍÔÿ¦ºw肇jÎ)4}®Ç#Cƒ"ìŸyô’ph'áúê–DóÑ”æU/Å©i%~¨ûSYp°î^ÉÜŒëzHô5õ0ûÂq6–Ü ÂaØSX/aI$2ÿåø@Eš¢4כ͵UåËÂLTr‚KöÒöh\tÊ^„œb&v4D¬0Kè=»šo-;öj• …„G§?ê9Æ|éÒñE(5<Çšì^IEÓ03w5²¾»&Y”DZŸ0•¹@ŒòHh/ëáô0œÐ^ܯƒƒQËÓÖŽ Œ3.âqôÙˆgç˜ ûsãH.K)rwD<¡VóSðô¤JÏO*Ä]?©@E|€@O[¸]|ûú2:]Ö«G_˜ØRSÇ#ÔÄŠ_ 6»Ž Žu[Zü~A•z!©àk–<¦s뛤Ë'­Ù;¦£2[‰°ÖíH˜¤çgøJ¼âÕ®ÅY|áïR‰,M—ŸHøû O®¢¥ÓgéºÛ¢ñé-½YûNÃA÷ŸrOyÒ}ã¹eÙ- ýÁ6Õ¯ŠÖ>Î> endobj 93 0 obj << /D [91 0 R /XYZ 90 720 null] >> endobj 94 0 obj << /D [91 0 R /XYZ 90 602.009 null] >> endobj 90 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F72 4 0 R /F60 10 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 97 0 obj << /Length 2236 /Filter /FlateDecode >> stream xÚXë#9ÿ¾E¤CºÎiÓÛïÇIó[ÝÁ"ˆ„‡À“8‰•îvÎvÏL@âo§^ÇLÏ‚Ðj6vU¹\.WýªÜé"é¢MužÇmÑ,6ý‡D¨Ç©ŒV °º‘øaýáÓOeºH“¸MÚt±ÞݪXo>Ô)h·\åyeß/WEQF¿Ñ!˜aÏD” z»\eU]´QZ.ÿ¶þ݇×—]Ë,û/f¡Ä»òtÑÄmUhVZdqžW‹ªÎc؆mûÕÏI™ôʃ}ïívì´Jº\Uy’D[íÉ<[w܇¼O"‡6.Ò¼ŠËö‡óUÊJ݃vÄNî°R?ÔI2Ç ç“~x4ƒrç;6sõ˦añwqçÃÜò‹À¿¿Æýæ»9®×îI;>èÉvfs>XÈo- nôá¨Ï0ÐÈÿôSs㼨2ôó*mš¸)êÅ*o㦕=²¸X®Ê*‹þ¸\¥Ñ);¨euuí´ £ŸÒÌ ü»Ù©½–yÞè>ÎЮ6N³)ÌX:k@zU”E´µPu¤ýðí ¥(óH‘Ø9(‘3p£ž¹gdÚ‘Ê™jDG°ñrÕ$EôçìF¤›yäF¡*žo^›urvïàèªç¹¹Þg§¥ø Öh§¹$©¢Áò¯Ãi\¢Ch:™c#´Ÿ“´¶Bô¶×rÌ<)/2à™&ÒÑOhÙ´K°wl^óìì°‡3y} L#×^× Vôn”ƒð%°tî\âzÎ{µÁ`ÀX€#¡®üzÈ}fªBioõ¦Sáe(XXVD7¤Eÿ2êa£cNÖС{ê8ÅXE{¾ì@òöqÒ™#¹å#N[PmÇýA&w‚5ð W¼BÈx¬Þñ^ãpº~ä((­7Á€ï!<»ó´„*vP“GàôœzØw»^ï &x9Dܳ &):öêrî›{ }cÿ‹èކÞØ¾WÖ‰´°)u=O0¼Ö¼€/¨Nï´C¯ó´ç+U‡ˆ‚Ô&ìö¢¹ñ&.¤À@Tµœ+˜(H¥s݆” gUýC@"»‰,“«É®žæ€$Mã¢,'™oY›u_×ZVõEë àóÑz=§Ž\o”³?b,4”•H}6]Ç#?žN8¾¸'$Z;3±ù¶q¤ø`tìÅ%x™YUDÏWL™ö2ž·Ö`vsœ$e\åÍ} |Ö.(L²¬M£gÜ^¹%k³¨‡\…èôÌV·<â¸<99ÃáK%“:N÷()¡E'ƒËÓ/kÛˆufl:®žvãŸÑëÝØ±ÈV?Žû½A8+³ÝûðÌ5ŠÁª’Ü‚^Õ÷ŽBIEëš®äȤÎÏ#J#XMà+´ÉzŠnä°³GGéZJ0àî0ðp`h‹ ‹>r1œÈ²º‚›ëñ^ÞÏpÕk̶"¾à™Ð nKižµ²MÆÁ‡:Ì%ÂèpG&Á–x7$u`çz´ú#ÓXC ZSÙÉZ*;ÂDqجW‚ʸ·³=/‘Ø3áä<Þx®†xˆy1Kv‚}˃ <áäù{¾&¤drejÀðÄ99“D)°‘{f†(ë0¼Oï«9< i—bŠœ½b™ÁÒ¬ÅRyK5-Ü ¬‘³šRîW@†‰r#qÑT\E~±Ò2 ¼@ÖÆÁÙîûYÄJâ$m'I¯§zÚ0ž¼2j@§¡.&à;Œ»2÷O`ç²§©2Õݬnx5Åq–€•muÝOËÒÑõØi?µš <$¿ôÐÀƒ•öá4:v=@ …XýVO+ͤJ:…ƒu‡t%/Ò¡za›J4ñÖÝ«"ƒ^ì†üËó·®]´q‘x®¸Ín$oWi YýŽÊJ*¤<Ò/ª?­Û_Xsmø CO ¼U“•e<ý%ï(š¦øA©7š~ÿ㚟§Á­¢Ûƒõv í†w”}êÏ|üO, Å'¼£tê)ú¦>nR+Pžâ£ïö,´ÓÌ7hÇëA³ ´|ÃʈÅCà‰Íè¯Ãõî ¾ê«3ÐóÊ¿Ñ8ÝÒÛûƒ*m»'Ü®®ßÑsðoÞ‘à#ˆÐ &Ô”Â#“ó{*/_A/p¸óAÃ8Ô :Fh7 Û!hEÚ7Q’qÉ\)æÊËlǸ”ÿýBÊ„MóÍ$è®þ—µ¸h•†­†(ªûnæ6n½±¼aÛ—ð¸º|n2j7šó <3ÿ\Àš(GÃ/Tž sæ«P/øA§Jy-¶teÉ`-°‰ÂØŠ`³LíÈABC·(ºÌþ+} ×<Ù¡J¯Öó”êüž &°IØ­x¬@0Ys1~Ð]'Ãë£éì#‰Ê_ð…­¸°™0½W+9ü­d§w²š X$–z³å±÷ï=[òª½?OËu¿j®|gö‡K÷‰/DöGK»à1ÿ×®kU#¥ØS/*í°Cýôz«n_²Àëi—zÚEºß6Ra2ÇÈ2)©ÒÒÇs´>H‘UƒæzÑÛËkÝË{_=H¼>ga²±ÒQáê©È+QÃJy¼•ª³ü=‘‚ŒïƯ¾ä€É/YòâÆ“ï¿~ЦˆE×M-â6{GÎèÕV¬Æëþ YÀ"\ÆÁ]ß„_H°…<Œ,á äé=ÊɃ 7Vè÷Óg«éƒá&®H ‡ª²¸l/÷º(¼Æ£:³ä‚rJ ýÚC\Vu%éW¤éôÑÆ³ JˆÆAwiñ“R©çòmÏ ä ø)8‘ _¦Ž:ˆv+ùbü‚íÆ endstream endobj 96 0 obj << /Type /Page /Contents 97 0 R /Resources 95 0 R /MediaBox [0 0 612 792] /Parent 80 0 R >> endobj 98 0 obj << /D [96 0 R /XYZ 90 720 null] >> endobj 99 0 obj << /D [96 0 R /XYZ 90 566.037 null] >> endobj 95 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F72 4 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 102 0 obj << /Length 2334 /Filter /FlateDecode >> stream xÚ•YÙŠÉ}×W´Ìd:;÷Åo3Âbd°1¸ýd&TÕî\Ê‘Ý*ðÇûn‘KMº"n¬w;÷D*~ˆà_üPGeš†uV=»‘H_?ÄÒz„ «??xúœÇqÖQ?<ŸÖ[<7ÿââð˜ÔyQŸNº1½><¦i¼%ø›χ* &7ŒFµ‡=ÿéßçãò$ùÎ}pÆ÷/TTY§_èŸQœõ ž×A7Lý!©§EÐûjÃì_ËÞMÛrë+¨R¨@?ß.­ud¥éeí”iyJ«LŽƒñATÁiy¬ðàw^ÔÎ5·ÝY9ß2–'7šnmœz4(ÿ§aœ³Jí@^qz ç)wÖ#·­›.¦á¶ê¥azØ/×ßÌ×Vƒ¶E\±¶0ô~HÊ`˜Z™‰*—¤r^y:âßó2 ¦pÎgN«m4·Ëv“™:ÙôÕø[ §n1+÷vÈ‹@AxÀ]-ÇŽ8vÄ,š{ï ³ÞN˜ Ã]6>4Øï¥ø¸lµNwèÿ,Ë‚Ÿè^°ÛpâI Çhå°+›IT†!]>Î ³‡Ç$ÓL"î…{3ý lœ§Á×ÑàÅó+wíqT¶cÃð6²ÀNã bG1Š4âmð÷â[Ç“zÑÇ"P=¯o» ÌMc/{›3RˆcÕ]Zé`„ ^µ'œz=Hü—y ð'Û˜º»0Ê·# ÿ žä4K.ãð2ªN†ñʸðf¿Öð™˜>U~Ê#«eR׌ú®ï"ï9wB˵°"Æ„. ÄO<ýŠ;‚ïv‚mê=ZG‰’”E`ÜG¼Nµø¥y9‹¹“²œïÈ=40N²¯æ"’ó8L°‚Äti”ŽÚÊzôèfˆ€LD¤¾€”iyÞæ.Îp]¦ÜSQQ’Äåbi Ì0òc?­ÙT0Ç8¡¹¥ ô 0[F3L“Äxÿž—±g`^¯¿91j¨ # Ù³À ªÞ¾“ ý£Œüg3êÙØ#È¥löyßè‹;S">}.LÆ4+¬°2ÍÃ2JyiæIð¥?¤1` üñ†€‘Œ¡ãͶ%¯Q‡q"%îÓ:ÿð%ü•o· èšöFä iæúU¼ûŸ¬,ë¹<¾ò1¯~™á] ³ÄŽ ’,·}’µ>IVYbÚó`Ýï± z[8oÿ¤Ó(¾;‹:'ƒˆ‚íîJíõêä;«O›•,{“ßþÿ»ÇY·—=bUy±Uú™ò¯âj0RvV ggE€içñGŠà$ãJh¾±n]3H¿¥lžç_ŸèP ¹CÛ×倸醶Êa¥¼ ÊLüi¹cì2Š;Êú aE^·B\(ójTL ¸Ñ #YÎ’7¡g¹D?Þ…}ÿÞ¹}­;ÐÚ[ËS•…¶¼~°öC?΀7”õúç;¡- È¦úè]žÌ§^{®É<’;!óÌäÁg¡×¶£ä¦‚AÍ"ˆá¦á·2õ(Šàwœ¼A¡³5p¥¦ÕüÃèÖ«Žq2“j^¯üY­•ý§Ûî^úÝå)Kä^~æâìý×Ú!„ìN!b¹Ù3r¥ñNþ,O,¤Œ¬`šz[CâKG’ØR»dŠPÅ4~¨Âº(²…)ÆUXäò¸ýáwO“ŸÚá¨Ú'ûÕôO·dÎÃT’Bôúa_H+þ|&$üp› uw§ß”î¡õop&Ç€gïþ ÏIe!E.ß]ªlåg蜕0öy‘éÁlm»ÂSœw\¾nAÞ‘~_‘­xvw f 3J±5íž®pލšK§dG–€8­·Ñô3Á|AÙDmü)ƒ3”|=²hõœ­ œÃìÓ?S«bM“ ÁVœÇ„¹XÅ&öæP¤S™jàK÷u¾ÊfßVÚLrÏí•Òw!*KÃ"›êxî†f—$a²Ùœي̯²Í®Þ?­„‡­`l“zYðïÉJF. s©}™“YмþsþkB-Î,Á—IµvT\ª @¤ä<Þ¼×*©â^Zs4H˜ø•éëgÛÞ¯?ám²šà0äƒå§1¡*ÈýIh£<åZÃüé2‚`{3–ü·]EŸ4ý¼Ê9ü™5ò¦“ãÅǸöK«0Ïóï2°¤Èoí*Õö„ÈÜ)>cŠ[Î;‚ 9T™ vLž()êtì0n¯ŒÖ#:4N‘Ýqv«••æúÛN½ª18FïxlœTgZ£ÆÍ›² G‘(!`eä"̇pÜ;)ÜùŒò,^¿ZuÒ?rÛ›³<Ã_«í&³%mžD•ò ZK’œØ¥¼x×k þN™ÔÅׄ+F[P*G>ØAo«[ùBÂÜ¿JR`l†þ¿þN8|¡ endstream endobj 101 0 obj << /Type /Page /Contents 102 0 R /Resources 100 0 R /MediaBox [0 0 612 792] /Parent 80 0 R >> endobj 103 0 obj << /D [101 0 R /XYZ 90 720 null] >> endobj 104 0 obj << /D [101 0 R /XYZ 90 562.002 null] >> endobj 105 0 obj << /D [101 0 R /XYZ 90 79.203 null] >> endobj 100 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 19 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 109 0 obj << /Length 2443 /Filter /FlateDecode >> stream xÚioä¶õûþ w`5…GI í&í¶ h ôCli Ç£ZÇT‡½óïû.Êš‰/ }ùøH¾û ºŠàSWEt•q~U6o">¼Q2ÚÂvñõí››‰ºRQXD…ººÝ/¸Ý]ý|s°ÇÑõ›­1&Ðï7Û8N‚¿¹q¬Ú{£íG·ÛlušÅE ²Í/·ß½ùëí|k¢õ+d!ƯèÊô•ŠC§ÚÓEa”%L—ÓÍ6IuðÏÍVSÛ2=Y”{„¸ö¾jB’à?€ôm]»1:ëÓ¦0Á5/7][]/$mwÈ•ÎôÂTtñ­½#ngÔrï>»’Ð/¹·¡ÒïÿG[M±J‚ÓFçA7ñÄöaqáÄÓi ›p7G@slh{6oªêGqð„`Ûâ#¯Uò;þ÷S˃ÚÙAÖº™*€ê&jº©÷gT÷$°%eB% NÃèš!DúâàöP ¢Èþ×U vÛÏ9TîéEÛAèpN»]µQɦãÁñ`ßÕu‡xO•_«YψÕ]`÷@‚Gœê DÃèáX`îí£ý© µìêöžâÑg̪%·ïYñF]åa‘¦1êÔžnƱMtm"°UøßÍ4ô7uWÚúf¸«ÚoZ´¸ý¸jb@Qž¤`jQ¨ŒáÛDòI eèÚnº?à8e)l˜Ðîv°#C½1œ- á÷ndè8cûÐz…%h‹ãq”{׺ÞRLÀ¥Y¯t‘§î?ÝÝ5Iv ^^€¬ÎäËë"†Ý¨BÇ“ü”B Œ«–ÿÿÑè¥hrƒÖè´›GÛßxÎn˜ÔaM¢ $©3å÷½#kVÁ·rZåXuí5ÛSµgðì˂òB\Ø,­u8h‚`$é0É“s¬riÂÈxZ˽¹aÙµû5ÖÒ<Ìt6svÍÁ›]– šv×Tm5Œ ÃN"¿‚a}dìr­jÒ3n“|05íOŒ@¾„k³­ pËD¬ùÏ6Öa‘d † h¦Æ¾«ß{W53Ø›ñ8¸þ£úÊù÷s”ˆ×!‡é.tŸms¬]Øõ÷3ŠâÑïù7T£ãÑ÷·xðt¨ÊK`‚£­dÜ=‡‡(ŒÓ9:€ 1#®ÓÓ?üùbT’ÍÔ Ý<›‚Ì3ðEJwó%/¤ˆA& “B¢óGñ§LÜ&5UkÇ³Ç 8§­'7ð|ŠÇÈp†ÓW¸‹ã¼Á@k¶†"¡… ¢‚Šƒ:ùèZÎñ®c…Œ'´+FAuü§…ƒçŒ·1ŠèXñ.øó®8Ȫä:T°f—y1{ÇPj³³ð‰Ç¾»ïmÃ& vÖ5]˰†ÓÍN(@?U#dÑQˆeÚ¢uÚTc“úK×C¾RaœÌqí žÝQº¨e8^Ñ…^N3i D ÐYÉ2•Ï<9d×GTÛE>[®<¸ã\þpßwS»c˜õƒ¡vî8%€—cÅ&4J„ ÙÖ§¥YÂÞ²ìú¥Šç(@± 9“k·›jˆ¬ z7P£ O£c|¾_äM«¬+HG\j€H²ÜœYûÁÖû-jo-AO’DÙy=w–ŒŠênIH"b ßÿ:8ÉÃÅJIdYÖU‚àù¡¨ßí$=ÙMGI<”ÿ´š Kr '©äWÉg¶-?3Ñ'“,RÐj>TœeRgŠ~èF±7.ÉiT52¤¥(+,qJ‹Qjà%ÛψgÝAP2l®C™žxIβÐD¹7#¹,Ƀ²¶ÃàV+»$ƒnl.ì°‹Ê¢àGç.›ÕL4W4¦Á­°…shqѰz¬ím¥™¾<ŒîþÑ•(f3 8k&'.,󧯧ªÞq ˜`>Q‰û\QÎŽ=ó­=ß¿ [9$*0^H£Kþtç)F§aªÕ ¹ÇÚ.ÐVø»<Œ¨ÆxTÁ‡36HH× EX½ 3RW ¨q€ÉÁfàEï0¸:LÀwZ:ß,BÙ2¨µ.Ò\¹ox$õ*Œ `Á‹p¸ï;Yîç˜ÜI“xàiÙShÁ­˜ÇpÀ×¼÷âd¨vnËÍÍÇØÁß<Ç kæŽå I«qœ×,ÞÍ ÕµïÐŒw2³°Zv|‰ÜE&u^ªwäze9õ!]é­óvQ.þù™OnØk;|/ÁNy©æM"¢[¹ynÕΞ…xN9ùÍË €j\½_‹¾¾¿]F_¨ÂJ‡ÖÎñ7³(;¿o‘¼ÇÝ[öü› ‡¸·+m6á.‹øçs°¯ÀƒpëkçîjŸž‡IjÎ+rŽŸ^µ×,JÊ{^x³¬Åä¨ùò]”Y¾‘n¼:ęپk¡Rð ›W%,Iæíââ«/–3b|DÏßŽï°æL!K6R¥õãü´…pªýÓxu °²a`|Ÿsd‘‘{w?ÕPµÙžçîó[+òžår%¬p”r¶ÆcGyâÛF ó³Ç㩘o!ž¨À½üÄq´qŒ­+ߌ/: c"‰BËeâÁöçÙá`¢øýníÜd–½zp¾Èéxh‰D«4Ôé…̹!е ¤ÿæ*Öó»FiɜŠFwÄ×aÙIá×»=Æ^‚±Iäh8ZÐŠØ Å@å5’} ³$Ô§±CÁ¤Ïû 죹RÁõÊc+? ¯ :ÿÄ|QƒkÂLÍuûs\ÑŽñ^ô’ýyJÑÐÎ ^@ ü[2)¡ìH]þS˹@û»Öˆ×T–\4|Ìz;œ$Ð7©3 0ød¤/‰¤ë’¦£Ô\IEavn"vXísLhŠË÷D"ےԿ`¡ñé7„¯5ăh¶íª½xŒ;Ò#õ™ ã€^k~çë¹ÿ·S­R endstream endobj 108 0 obj << /Type /Page /Contents 109 0 R /Resources 107 0 R /MediaBox [0 0 612 792] /Parent 112 0 R /Annots [ 106 0 R 111 0 R ] >> endobj 106 0 obj << /Type /Annot /Border [0 0 0] /Rect [468.686 337.65 522 347.347] /Subtype /Link /A << /S /GoTo /D (Building flexible time classes) >> >> endobj 111 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 323.893 283.171 334.803] /Subtype /Link /A << /S /GoTo /D (Building flexible time classes) >> >> endobj 110 0 obj << /D [108 0 R /XYZ 90 720 null] >> endobj 107 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 46 0 R /F52 19 0 R /F54 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 119 0 obj << /Length 3344 /Filter /FlateDecode >> stream xÚ­ZYÜÆ~ׯX$â.»Ù¼üÄRŒ(Ab¯a²€´f8;ÄrÈ1Ýì¿O]ÝÓœåÚJ`ûš>ª«¾úªzÕMÿÔM•ÜiW¦¼ÙÞ$ÒúðFIi ¶ÁˆoïÞÜ~—©•ÄUR©›»C8ÅÝþæS¤ÊÍVWY^Eïuwßtõf›¦&zÔøM£»M™FóÔm7Ÿïþöæ/w~¹LëߨŽx±¡Bß(§&ײ¡¼4±J oHÇÅf›å:zÿÝÇ¿ÿc³UÑÝýÛ)²¨î6©Š›¡ïN\ž¸ãq?±06ú¥­q«×GÙ¨*VZNþÓ±îêÇ.£z”Y´ÃÕ0G… ,]æQÛã7êF{èåG–??'Ê´2¶™¤kt£-wü2×ãÔôÝ7›­ÑIÔHït”ò$=Õò³N¾_ƾ'iuý8>K¦£ð´t¼4VŸçNóWÆÿKOÇf‡‡>rõ «†ƒÒŠè0ô'îú·Q‡BT&‹•Á ¦en×Å….܈·“6Ì×ÎC?ØWÐn-EPP‚û†Ë÷z-rÍb›8dÉ%ùõØÚQZÞÞ¾{0Š$,Û TjÓ0“Ì&’ðÀ!º,;ÒríÌE¶¤ýñ¸r„[Ü9ã)¾oÉ:®ò=Ãà Qš ÖNb¶ÐJÆ (¦z°mûŒŽ'†Ó˜”õúk^´ùð¼Ø§*>ÈškG°ãÚùG¸üV,vÓ"N¼ Ư```ü«Sê4Nr¯Õ_…©0¥\2LºÄ™¡¶{1£ƒ‚ó¼ao 5yžCÀa‚ ²Ã~9 Áˆˆ?“ï²,OÀŽì±BŸ`¢ûÚ³.àÂËžˆÏ ÄF°á—™ƒÒÇÏéöòdHfK®άXU1ç™×°ï‰<ªô2Â%nž¹zdÏ ƒÝðË\+ÔFK}QTi}[Kë“‹«dÝ¡Sšè¸PK¹È¹˜ÝjÆTïf;¬Ñ¥aI'`¯ÈLMýàˆi}‡ÔE @¥nàjâ„pê r‘nÔ6¶âX®'c?p´ç a÷”ñçÓ£?ÆEaé£|ùs@­E›ÝÖ”24ôCèûüNÐʹ¬^KÁºQÛ`ØÊ±¯'[·fÉÜr¢‹LÑ÷Gs×±DÊ2”H‰IÅMj’>®uÜÊ5‹9¬rø‡Ãš‰[žЊŒÌ›¿àp™—ÂM+“i.šßʯꖻzúL`€- V 8Ȇƒ¡ªÐ— b’Ü´ïi?#ר¤¡p´2”LZžl#}œŸËB!á@·ˆ…I8e†óø…Ü<»M¦A”@4§z·‚ªÿÿ@N@éh>¯ÇÐqR–—z¬‡Çý*7JcSùŒÉÚaò"Øf¹î¢,€òYµ`@п³2Ù!•`kœ\:õS^Ê7SÅrj²¸¨K™//Þ;qàF«PíæÈÛXš‘~V©9Ï™¯‘È¢Wå‰ïVåžÄiáó ¯¶»¯G^/—DÌ]faàjÅÈÅ' –Wp‹¯97h{µæþ–S9mÈ•p€Ígþ^®*«aG^ÅEV]ƯçÜIN˜×'b lw»~ÀÔÛµìë_”sm ÅJ:JÇFWK9Ûv‚Å$œ2>î9foëSß]±âáBá‘^ívõ(Ô{ Èá’Ã<¸´ÇPŸÐ&ûéE* ;gbkp†Uçš,Qûý^öl½ø´‘Û¬wŒ„ª‚¨ÆÁAâö,¿¢D<ÀîêÑÿV:ù³cM@½þcQ~Øt{@Ü ¡¥ŒØÄÊ¥áŽÙÍiÜW\¬÷w—SˆÃ#~ž'€?â÷Íh÷¶›ØЛòS9Q–é&3Ç!°…¹ÅîxíLv|Í;sÊî¦òJ¿6]kå}ñeÛ¦J½ç¯8›‚M,U¯¼VUYœ\2éd,1O²†À:®ªðvpZÆ/0É <élj÷,[â+P%Þ‹…“8PªÜuâV9Áý>÷ @Ä“¤«!"z=>òt A™Dý#wañeiܵ{[BÿeŒ"Øå’oH¥±øÅ@âX3žFnƒ¨£åŸ€òÝÄ•à…'ˆu_}¨íþ"Š2¢DŒ¿ ɲœ!–Ë.@‡û#˜óøYN&¬W(^0,ÐøJ…'\a%2è7x5•qHó0Pƒò­á~\êJpS–ËКœ+ä«òÌì¼-ž:|Öá×nù -‘4‚£çƒjƒp%¤§{:|úù<†ë•÷ÕºZäYðÛNÍxx^S0yÿiÙçú÷«ë?8¡üN=úÄû¨œÕ endstream endobj 118 0 obj << /Type /Page /Contents 119 0 R /Resources 117 0 R /MediaBox [0 0 612 792] /Parent 112 0 R /Annots [ 114 0 R 123 0 R 115 0 R 124 0 R 116 0 R ] >> endobj 114 0 obj << /Type /Annot /Border [0 0 0] /Rect [273.541 313.321 522 324.23] /Subtype /Link /A << /S /GoTo /D (Using cfengine as a front-end for cron) >> >> endobj 123 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 300.776 147.964 309.928] /Subtype /Link /A << /S /GoTo /D (Using cfengine as a front-end for cron) >> >> endobj 115 0 obj << /Type /Annot /Border [0 0 0] /Rect [470.013 229.71 522 239.406] /Subtype /Link /A << /S /GoTo /D (Configuring cfservd) >> >> endobj 124 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 215.953 255.543 226.862] /Subtype /Link /A << /S /GoTo /D (Configuring cfservd) >> >> endobj 116 0 obj << /Type /Annot /Border [0 0 0] /Rect [173.132 102.777 425.91 113.686] /Subtype /Link /A << /S /GoTo /D (Deadlocks and runaway loops) >> >> endobj 120 0 obj << /D [118 0 R /XYZ 90 720 null] >> endobj 121 0 obj << /D [118 0 R /XYZ 90 720 null] >> endobj 122 0 obj << /D [118 0 R /XYZ 90 403.952 null] >> endobj 117 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 19 0 R /F60 10 0 R /F54 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 130 0 obj << /Length 280 /Filter /FlateDecode >> stream xÚ…‘Ínƒ0„ï<…¶Tˆÿ¸ÇVm¥ž‘zh{pÀQiÕ·ï:KPn’±?fgׂpø1œTJFפ=f|¡‡L,»ù•â¡É6Ï¥ ‚†Aš¯k‹¦#ïôÑÛSt#Ë•RTÞ³\ë’¾¸û°G8E;F×±\n+m¨0ì³yÍžšµj)åXIq;×¶Ö…Ps½y ~)é“f> endobj 131 0 obj << /D [129 0 R /XYZ 90 720 null] >> endobj 128 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 134 0 obj << /Length 123 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h #M]#KS3K ç´Ô¼ô̼TM]cc2#m¬¢ia¬QZ’_”™˜£âÅå·ÎÔÈ»{“b%Ç endstream endobj 133 0 obj << /Type /Page /Contents 134 0 R /Resources 132 0 R /MediaBox [0 0 612 792] /Parent 112 0 R >> endobj 135 0 obj << /D [133 0 R /XYZ 90 720 null] >> endobj 132 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 138 0 obj << /Length 2776 /Filter /FlateDecode >> stream xÚ­YYä¶~ß_1y²Ø–E‘ºö%X/’ÀA6/žÀ0âáJìneº¥ŽïœŸºHI3š6‚~b±Xüêb«»~ê®Jî ­ãÊ”wõõM"£o”´@pXQ|óðæë?fêN%q•Têîá¸fñÐÜý=úp¶·É ÷­u¤ß݌ɢýàxÄ6?Ýgyd»Ú58b¢º‡ömïiZ*¥êþ~ó‡‡ E–¦¿ &R¼³HïT§*3"g^šXiÃrêûC–§ÑÇûƒŠXºÂt0è¥+²E:‰YšX›ºîÔv.¾?äU}g‘åSÛ˜l:ò áV†’dx8: œŽH§é‡V䳓k¾òDGWg»‘›Â9I£vâ‘Äz7v_ÉÈÕ>"'ó®nG8€0˜G”’Õš®ÕšæUlÒ "AÚãžî•Š `Ahâ8ÞãTÅØÐj·Ç)M±ùk8¹Ëèv9±N´§°Ó0×Órd¼XTõA›*N -gúϨ*¾> †kï|àæÅv§ÙžAÐmú·ÐÈTô 1OBÞ]dam¸<¡íý¼íäKq»=ò—s? ù0wÈæa#!¹ ýi°×=Ì ªti¢¶ã/±ÅÆh¯Òb¼QÓŽ*p'5¥Ã~;îrdgU=ÜÃHÏ+æ®qÃ8Ù®áþgÂ"ób{È á ªÒ°¾½Z†?ÉÓ“ ïù¦óÐϧ3@¹Jà:࣢K‹ZÁ4;š¸\xŠ„ÇÔÜ(“Ï=áeöóÀ£c;¡•DßzYÊ^Æž)ؤ°+ñæ„Ý [\ØÀúGº9öÃ"#Ò¬ K“HzcÜ<Öy ëŒR“jð¸é¥rL vÿùÜÖxÂ3w?±õ_zN'ŠÜNðýB£î¯·™ôNÝÆÝì0]ÅËà5%ås¦€Bnüé¯ûú/-‘Î_xÈ{GðŒçø4Nn› –<ßìgÑÙ¢®?…tmîÚ†ïgy¯Ï®¢ß$Z l~L”9̓° £ãÍ[1ÒXÃS·õ|±2Ì6G»ÀIF䄯‹3bxdZ`ƾçùñêà5´ØÔ#;Èp“»¸Éñ„€8T§Á̱ð¼¹hZ6I× Óp9\]dÂîÖ›óÿÜ? 8œ6¸«mÙ¡íö½Ù/7 ݦ§ÀƒÍ-Ñ/ôÏ<Ò‹¸ö«BŽ€ÓAŸLËG F$Œw®e-{Qy١Ų$;t½ìÐ{p^ÒdQÃsÂ쓤ضãcX1›ÆøÃÞƒ&ˆM¤ƒˆòK¨—Tç¹(ƒƒ¨^²Û0Ô^â4z™Î!‰¤÷$mÑèj—ðýc’%—ö190N#8MÃC Íμ\9ó28sš_`]²Ú36NY`_ÈÝ5TŒ¥¼?àNÿi蘠״ƒ«'H`„¾ÊAOÎq8B„V«Ô'jÁCè~³ÎùäYC@ÒVH%Xȳ£gÝóܪ¦~-?X¿Pp´4Å*ó2¦[Í’õÓ!—|ñ¹ø!oiؾÝÈ’ IFßåš›'ZYÓwÂè$+~–ù••ÍäAŒd½Ø`>;´¤p±³±R7yô•x³„RJ'€`•@ïä:¨¼jî óÅ É ®#@ ! „tMO·˜`À[ÛäBׄ ¥CoC.^ vúù¶ûªÑŸ|!Z¡ ƒjà¶ùe„¶…ÑÔN>Vᨭë~h³•X|……m/«ZJë«l•dA‡_÷xÉ™’8äEÆTå+u£4$=4n–k€½DýÕ„£ä¢œL´Ãç âgŸØXñÎ'1*’Œh•Êc7\šˆøz*ó~/"+±° ï-‹ËÍJøè\Û"ˆg¡ÿ ¤ô\ C¯°É‰­æ(«7°À'¹ kˆ\"ž¬…£˜l+ w±ûTRPHVÿhSRþ€-N…p„„…ïžýÃp(‡tà`ÑNP¼ð³Œºø´ûzš"Nux-Ÿ/ÓÐ~ÙMM¬óð‚ývW— Å8wæ•÷Ä"IÃ{ùT£;…zœS<3KÎ'AG«,VyúÜwI‚o`Ÿ“Ô'vô¹ÀŽ!–UlÊ ô3¤WÔzlˆ¯>ƒnžAã½{‡¸©4¥»y¬Á4~õÕW%UÆs÷ïÙ^("¸FJÖ* ¢’g“Šb'v7¯†Uòf]ñÓOU®Þ›±àR¡–$ìÑÃãÌÉ"4W’ì¸Þ¦¿R ºñ–è¦×»â%X¢ê£=Ƀšøe(Ðk;¹q›Ër¿>7ô÷-¢H륢E^¹V÷o¾šÍ½s°"Íè†CãPKÿ·“ÃíÆ•P†ñÿ–Nœ\C/OÛ ƒZøÕÁ=r!Övº³ëžMƒ©Å¥ ècß5öé7û‡> endobj 139 0 obj << /D [137 0 R /XYZ 90 720 null] >> endobj 140 0 obj << /D [137 0 R /XYZ 90 720 null] >> endobj 141 0 obj << /D [137 0 R /XYZ 90 655.075 null] >> endobj 136 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 19 0 R /F54 16 0 R /F58 59 0 R /F31 46 0 R /F60 10 0 R >> /ProcSet [ /PDF /Text ] >> endobj 144 0 obj << /Length 2651 /Filter /FlateDecode >> stream xÚ¥ZKoÜF¾ûWh/k ÐpÉ~ðá[v½Á&@bØ«‹±YÈœaDxHNš¤”üãSÕUMr$Ž5R ›Åêêîz|UÕ£ø"‚¿ø".R)Ã\e›úMÄÔ¯ob­€a5ãøçõ›ü¨ã‹8 ó(/®·s×åÅÿ!.W"×IükkšÛª1—+)Up/ð)ƒëËLCßÚªØ]þÿúç7ÿ¾—ÓB<³äx²¡$:ÚPõE’©0–Š6õ[§¸ØãÍÇ"L´ю뇆¶x×–6Ýn‰Òß”ťȂ}ý-ÒQÕ<âØ¶¶æ¥ÄÑR: S‘ùµþc£hiGBÀpäºZ’”„I’ÎäÄ'åä“··0 —Š(L¢d’(äóáì1 ;VÿJ$:”˜)NBÉ—àÐ&¨wèMG®.ã ¡á¨`o9Ó¿:CÿI*1_ꄲ0‘ɳHf‚–öXÐù‘J?/ò;&È@õ [àe!à5«ûK‘¬Ôz4 ½ãkôÆÞ_ê$€@öÔçM5†Š:i*!’PécSÝD‹Q:ÌâìEÖŠôM#ëEÓú&:C*ÚlÑd*’a&“×D Ûì÷¡°=)ôc_ƒRàb"•^ôǘÕðQ\‘´ÒSÔÒÎR9‡¯“§±šöå -TP¬×ÖÜWEoJ$ÀÙªÚЧ‡ª¿£‘Ó‰±ôÂÞ¬€.q°‡<¾©ÐÙIÈLY»±øŽŸæ`[5Gô›‹`¬¢pŽÅ‹Nªç’„¼YÖï#I°½$0ý&<©i {:ÿ ~…)/¥”'Ÿ&ĺ%(¸û^œƒ3žÌŠ9 òxò÷Å!žâÎM’\Tjzª,ŒÒü/ áóçûN0Eé%~.pÇÃI³ÆçÃØfmOÊz5Œ½7S¯!\΂±Oó)õ¼ÆÝ.íöúÎÓ0¡ë³ó|qY©B™¨ó•ýÙŠh¹È:–tZ)q¦_í†|øÂ®«Þ¢ÉÝëл* BWã° "¥ëmÕÜBØ(E@Öã2D ­Ùkšß‚2{±ûÎöiG¯°é5š,‹¢ ÚÃVEYZÓuDj³`Ó›iž;lÁ´£¿lúêß 1Q!˜¾-6,Ûû~îý‚§|DŠ4Œ³B«ý½º‰sqÆÍ¢³(|¦À€Ü‚ yeÃì'’—ä&´éù^8É»òÃEýGjúÄ'asyf †fJ1Å\.ƒM[ï5Ú¡;•LÝh+Vü,èÑ™ßv¡œsR«z¿s4l0Ãâ|Óù%š†œ0F›—Ķö©ÆeÛ3okéùe_ѶÌ[bqyûP£¬]önwNAÓ§Ž-€~A®cûjCEª‚‰1SGŠPÑÁØ‘¶ 8æOñŽt+ã è&ˆqª¾ÁÅ ¥ªÇ ­Qœ–ÂnhTøKÛ”Åá› Xºæ‚5 ߆„èßÚnûîÝ’ñV~ A½¢·‘RÉ‘J&‘ph¸ ×;!©oéù¥·*ÇÕ–žÅnGƒ– .nGSV÷U9»Ù^da™«3ûÂÂR»O‡%®ü±ç6äAtqóc× à“WC¬éHÈä£él…ÇÜ€mòîª Î¸£×m»Û91‹yNCY;ÅêÕxãN·l‹z5Îà“CÓЙÁ‹ k+pdçR«0žæ´”ã*–¤õXðAb싺žHc„;ÎŽŸÍr±$B=†6»Þ9U¢’bí,ÏÞ,Ç×Òj¨²lL§è¿‹-iª±p)šÒ ØñÊd~@*-ÿv¹J2üÔMvziJ-ª3 6D,ñž‚‡Ô§Ȥa™¥Ážâ2#½,˜;w<®qMI‚5+…€fÂuE‹“1ê.]ÖD<Òù‚òÔ#åÅbTqk—ê©Æ Y’%3ðì%²†3&Há™8y(@¦<=6ÚKbÞ&¡þP1­-;´Gü´{àï†=i±ÅÖÕYbØ‚#´¬f€›Övï.W:Mƒ~}OÒÈã€íç+¢<تï oíË’T‡rŠpI zžœßNk‘2",4“£`_\IÎêÑog-aGåXúä@Š‚t¥óˆÒ•mkâÞL—¬ðÆé®˜$‚ãÐõð¹ ~"Ô‘4àH Þìv†éÅ ÊÒðpùxJ…zj[þ~î ‹ŽŸôèMK%_íÁ4‡rY{ÛÖeèÄpâ-ë˹j 2Òìò8J*6M׼퉲qˆŽ£»ƒÿ^ê±øt‚·ã’ãι#ÑÎ]â:–ë*𠫤…¼èlåF÷µÚó]ç, r-²ÞÍWúèk1 6Em\ù­]×Ë´ ‰åÖ°ã¶‚‹}ƲӥPà±\wtí®°U÷­À9§\É‘çlùg/ÀóJÃæ†JÅz ÀŒîž¦^–¨}Ñõ®àDŸHUð¡aºó `gäBÚx=*4˦n 9lI)Ýnç¬ð@ò,SªÃôT‡Iƪ (ƒNíÃ'|ê¹W.;vK0Ÿ«0S#v_kØëbºN§ûîºT´xB•úµ5k6a‡\©ï>=Q(ÎT|uîɘYmÕ‚{ù*^=ñb`#d†OÎQ½dªÚ¡Ã+æY$=°$×PÌv4³¾ôí­ñIšãêÖ©=vø™ñOR•ŒÒv G6bq„$0˜á,‚K /æùð‰+ºÏpj'×éQ6q}½ïX !@Úwѯǽ»Þ%ƒ»ò?•xë6tIÐÜ,™;Wn݃Ù*¾˜×ãýÞ¶·¶¨kÚ|칊[Ó¹•Òà³ë’ú¸)¿È"¼YÎ÷€9Ð(êÙDýfùVc> endobj 145 0 obj << /D [143 0 R /XYZ 90 720 null] >> endobj 142 0 obj << /Font << /F51 5 0 R /F60 10 0 R /F52 19 0 R /F31 46 0 R /F54 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 148 0 obj << /Length 2587 /Filter /FlateDecode >> stream xÚ­YYܸ~÷¯?Yu+"E]ó¶qÖÁˆd'OI`k$ö´0:::f¦üøÔEIÝÖÄ»A`ÀMKd_9ê&€ê& n’0ô3“ÞÍ›@¨o”ŒöÀ°_qüþîÍï>FêF~dêæî°Þ⮼ù»÷ᘟFÛïöazáínoLäý¹ë-SòòiÅ^Þ¶DŠñŠƧqØíµN•òt¸ûçÝŸÞüt7Kiý1‘ã;rªÀÀª¹‰Sã«Ð°°?‚AêÕÝCUä5NïÓç;¦v')õlŸ]Ϥc>0Ó=/Ù–éyY’:0;æÈëºÛéÄ{æéyüÝ´æï_Šz*-O ÛyÕ2û gÕ?e 9½ƇÀFºÙ+Vj¯B_E¬S&ñ69Œ`‡È¾T÷µÌŸQ”ÿ;ïÒÐóÁEiäÝey1†qÆ€Áµ1€Tí”7¸#¢ —1©¿ø'oK7‰Á+zí•P)? Ñ$û?Ó¥ë”o"ãxà,Å;~ÝÚ˜ƒ(uÌo·ö‹üD'Žãèÿm1«Ö#†è{˜F7‚mÈÜ¡ ü s+ÞàБ§Sï¹j8ÈíKÞœÈÜßÏìùº”pܼ S¦;çâ绽ò^Àº 7˜|é6ÖFûi’9}š3î´¥vhü0ß­°¤7©ŸÅ±A޽F­HÁ0È$ Š±êZfW-ì:óuª/6„-Œ%‘Öb¢·,ÔíÖ™*õS ¿fþ¢kŒ› %öq Á‚„‘ŸeNBŒ1@8VMUç}M Î3*ó†Ž×V†7fÃ#] 4 ]båé4Ø~_ZÌÀÖÊ }76Ý„~’èÅ kÎ 0†²9äß ‹Y³$~”ÅŽPbql{U-Ǿ#*ñù­"ösÈEÞ5ì^ÎU€?÷Õh7 ašýCK_ØÙÿÕ!¦þ·{>VêyD%c¯·yIÙy_‚Rv7Q~üôæbô ³ €7àM†[Xž˜6YHEÞ2S^cãH ¬w´ñ}Õr1ƒÆ#+¸©ÏõÙ; ÌÁÄÁÜñ–ƨ“Õù0¨ï:ëßo7¶Ë|á¬6Ò›¦O•+gút3¾ÅÚã7ÀÉNJØI!h]çA¨Š5 мgð¥RK$Õ{^r&a{ûÝÝ×v£³éÕžÆÓ>¹d®Õ«°úXµD®B“t–‡~¯#ªèðÓâSƒ"ÜK¨0_w`†Þ`=‘X%SHKø3.îà#([` éQ¸ráQ|vN½Õ3•»¸¾ê¦a£‘¨[5 |B¢½á<Œ¶Á1Ôžs £'„Œb B‚hä¯3TvüËV†/[K*i”¥%1`yÚ«µ"ŸÈ—@±ùìJ˜Òè±å1l%Ñó19{¯C)†27<¯„½h"íõSÛBp@ -“,C-Ñ¡²Œ=ñç§Sßú*…е–YÐÏHÖAÖž+*cÖ³U_'{J˜\説 ¤ñü³0Èi6 …Màý2VZ9Š”WæhƳìr¸Zå¡|}d ‡´† ²n7%^ª3kËtr-EØ keIèMmm‡M'-66[.=ÙøÒžÛ>T­¤õ¡ïÉùitq'Ù?œòÂ’ ŒClsf.×­d;œy»’P„.‹ßT}õ EOÃÔšeÊðxš^VCÈ$_¾ëÀ-Õ ³n8Ȩ‚­Íj솠 ÌbãIQI|‹ý†¢ÞCoíýPʬµã2éN¶]f02_™ïyè†Ké^ÒØ ŽKxtõ%rGóÉ­}!…NË®ó>uÕΆ(í}•·2)úü,é­^¾ O2ûcû7}ºÛ¬4I]³¾D㟙K0‹kqBá„ ±8 hÀ¨¡1µë•%œ–u aü²¬D ä¬è›ã|¤Š!/&#’$’{¦‚ý¹{Ebÿø©é*”‘€—ŸªÒnæ†Ü ¾½_FÚ•,H ë¦×A2Èv¸¥‚˜£Q(¹‹mÞȈo|ˆxP¥sB\`$pp8‡ƒoŠCäŠVh¿ïv)ä$/”[:aÒîu :ë8šÝĺ£CºG^©«Ç!"ͨ˜!×ÊÒ0c!†‹%þ€ú1¤œð`eX¯„úõ”÷ƒÝwm}Þ3Pô\‚ —xÇ,MGØ\nbE˜úZn¾b‰Íâ?Øvä˜ÞŸä÷i3¶çïã9¹È):™‹‡†bÇÅC'K¡  Äê©–÷9@m–Ö·‘+.†!xéÎs^Ò¾áC„GWÛY &çeI¸ž×¼àòmãsåx€Énø}1›WüÈWé|ÇZýË+›3Í}+ï‡8Ülí¸¾mìûqolõš€i„C÷/¸§Ú\¶¿æ3b‘bŸuÐïÓ”ûähÿ5å5å5]ZÄ÷cŒø ›Mâ瞉˜¹ƒ0ÊÞâp|ŠÅ¿k,ÓèÔ†eÏ_Ýø™ e¨ta‚Œ`“ᆜp°t©œŒ0¤¬E~иê™Fè ÒÆA•oýí§¦È—˜˜° |ïÛÍkz !4?õÔVD;U€â·¡8ôÓ8½4DÙ5ô¦g2s¥Pj”ÏÀZwGjaAй«j!°s³ÈA4Òš|”î™,œá-ñ¡ƒË÷±¶ JaE ±*ot„ëJÓ4‚ä#>¢OtÀ  Wä#×ÂÐy‡«2S*©Ç™´ÿ”T4a§¯>€  ¡Õy…Ñh~¸f«„ͶE7ñÞ¶ü­j@4^×ÎÅÐ$ot- AÉáCæ…:†îøË5?Ãþï`ec.ïkhfo;œ‡Íj@%Oˆk#‡¿0r—— @Ø$=ƒ°<Óê HϘ‰÷D|fWÐuí»‘iGð'iÀ‘"J"?J“Dh¤kµ»ôaŽÈZo·ž¦tšøY8ßå?}¾ûéÕäêtu†›II·S ócwÞ&Z±Ì6b½fØ“-/ôæW1„-äÙ™ç”FÜqK'1óGtORñ²…`BЄf‚¾¢7µŽQrþqùÃ3V}´j3¹¯Ý­éjû9Éaüu0¿¯gR[Œ5” E(žY?HŒt;ß[\¼ uõ B> endobj 149 0 obj << /D [147 0 R /XYZ 90 720 null] >> endobj 146 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F58 59 0 R /F31 46 0 R /F54 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 153 0 obj << /Length 1996 /Filter /FlateDecode >> stream xÚ½ÛŽä8õ}¾¢´ HI[©8qn#4, »<b[ðÀ"áN¹º¢Î¥ˆ“î)‰çÜœNº3ÌŽP|||ìsñ¹9jÁ§ve´Ë“$,u±«Úw‘`ß)@pXPüæîÝñw©Ú©(,£RíîÎË#îN»¿±Þâ2ÍÊà›³íêÎîI¢ƒ§Ç$¸ÛI0ýP›fÿ»?¼ûönf—ÆñgäAŠÏ ”:T‰fþ‰\€(^%a”À‰D²`¿ºÕa* Ê_’**¸»XÞóá¿eíú+h]v0 ¯Ý×ÝÉ1Øöƒlë‡Ë>΃±¹ âb:†þô—%ØTªtUeåéOTâß[Ò§aç áµ*KàÃ"×ÎK ²=£`Ö<îQ72r¥XÈLrB‡‰Îbdr(Â<Íw‡8 3¯$„ÛN³8øë¾Lw}ß —< ÜtïÆzœÆºï¶dŽHq‹;ýíbÑ>pÔ åê'ž2h¦‚û©nNu÷Àèé*˼XõÝ‘ÒHìh 1$ ÀõÈ„d ˜?‘îÃMNsö<5 =÷`°’°¹÷ùeØÂ'>íÓÔ+îøbQ³$T .iöý(£b¡L*òNå¤à‰r¤ÉfàÙ[µ`C-ãh‡Ö1Ø ×·–!¾ÛO@ÄlñkÀ©„ ²”ãE_ÄâvpØ{b9ö†nÖ¸š<n¿1 ¯Ar:pdïr €ÆÁtî ×Ú!!#«–ÞEö eQ9ymRƬë’ô:ôƒiybº“‰!yÂJârã„kØ“Ï÷n­«F2¥jyAi$lSµ6ªPÖ@™X¯ÙÐtqo—å<”óveãË9¤"ŒîæFÛBÖÒe|èzà=ðÊ3ž`h+3o1¸rã8ùxظ7º—¢À¬42T½$ñ¢x£ Äv» xWÓ[3NƒuŸï‹,ö{ÛAíÉZS ýÁ;"p]V)± ³uñÛ´z µä•Õã\saÀµ³9˜Qm\9Õƒ­(úh™nñt;ðíÐ*Æ&¢ž!¬^áàãÕZxSבFH0^(3m¸¥d$ \8ð²(ÒÀ~4íËNÐëq4<¸ÕÝ"f©1cHˆ"%56z„8Qa‘—þ:N}kêͺ›ä¡†Â.toùˆÁ„×Á>Õý$8°îâ³2„L³¶Àå©‚<÷Çé€n™E옞Êu@‹¦iz¤~v<_4˜,!92¸ÈʸKŽ»µ˜¹”õ ¯u¦ªQ¸Jþbä`¯ k*¬19D9e£(p!ÉA™ût¤¦£ýH• J0ù> endobj 154 0 obj << /D [152 0 R /XYZ 90 720 null] >> endobj 155 0 obj << /D [152 0 R /XYZ 90 651.036 null] >> endobj 151 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F72 4 0 R /F60 10 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 159 0 obj << /Length 1888 /Filter /FlateDecode >> stream xÚ¥XmoÜ6 þÞ_qèÔÄ®%¿臬h‡]?4Á€¡-PåN—3j[7YNlûï#Eɵ/Î’uÓ´DQȇԱU lUÅ«"I¢*-W›öIì´_ž0'…0 œŒøéâÉó×[±8ªâŠ­.vSÛÕ‡àå^ŒÔë0I’ 9]‡iš¿*-I#¶×ë,D·‘[Ô¤ÁF|0ý:ä¼d,àÙúÓÅ/O^]Œ^dœ?à&ŽxÀO§ð5]åe±$%g_—I p$-‚èHM¯HªÛ¸UJR€ó|dOï;­Z’Ì^’ ¿ÊÍ`j匩3J~/›Æ­§ÚVt[z¹\ó2¸%ù åǘ¥_ëîj6&„ˆÍ*d´—%Ëh+d*-xpS›=IÖ§´H‚´®ôg0|L Zèº2ÃŽsý¨h–9 .öuOË´Òì0XÂy@xexÀ‚lƒ(Œô£:z^£sR÷2Tpš=nHËC#6~šG eáàà•uð`äænè6x í(a«2ªò<Å %eÄà—äQ‘4âÐhÕœZ“iT,! ´ì÷ÖfY š- v×Q†Fº•›º7öìpØ z|Œ³˜¤§e+>¿¬»çMO/aótÊffçtòæÿ9ð Ö/û¡1¨;òÁ.>sã8”ەBžG¼¬hE Lð^šž›2T”4º† —¤¯Ÿ“ÏhŒQî¹wßÕ`ƒ!¥Í¡o“ÀFÒ˜> ÀXšøcPFööìWc¶dQÉM«ÖT0GÓš`b Ø« }ôAä6'€ÆRè[>–Qç´Â{pNµo:‹²›UNgeEÄ î³J,΢‚Ùy²hd:ârÉFUcêÞ{¦à8cù<~–Ô®në‘¶»A·p]yü.-YJ³†ÿ–r¤ì&³]JÛ‘Ñ"ŽIîPt´6Ö%rÇo;ô¤º`=eQ’%B‘'Àį,§Ëþ(F;ÑJ€ž×18ÁËt¼Ûï$P{©Mÿ/ÁîP=Î*›ºÆ ¢°^@ëµ­g®øÊ¯¢=4òtÿx€YÈ“(«ª{ø¯œÓϵ[œßC+³xOxr—JŽÍ›L¾ƒ©„£Pu0à,)Oæœõ‚å<ÀÉ+›ßVÐr'µ¶‡ oö0àiYž²vœ²å&ƒ§Fu–ÛŠx"µ¤ó$å ¦†°¬?U5Slí”ÝÒÖ|´ëÖºÅjp«Ñ8þ0ËØØ¼Ü×P?ÇÁÐK(˜@Ø)ÝöK9R>Ř#?"ìþîÃ6ϧ4Á·Ôc|3ù§·÷÷¢±dÒe¤ÄÞe_D\Mí¶w©¡9èI¶±σð¸ïeï?" ,h4£,Íæ9~I§ÿ+—v(`Š£”ÚƒFè\‚J€V“zk{¶C_[±Ñ O8æyr]kÕµc4à ùžP£œ5Õ­::´SM£,ÁÚ ªÞЦ†²åÒlº³»emºp¿HÅñœXΚæe#z„ráÔM–<ÃgA£l8ƒÔ]{™.óá˜Ùp$éóbôpîd¤ø—¯ÏÞ¾}ùöìüüÕù‹ zÅNíƒGQ´äƒËqþ3Z™ïY`Õ)·¢&0{,‹bhfûsÕ° ÚèÛi—\O…`ÒMbÃÞx’4ÚøÒˆ‡êL]ÕÔwÎPÝbÒ§i¼ñUÂOo,ç8J!Ý;÷`èm88#j´íXßí•Ç:í=ê7º>øREdß[AæIMÔ’¤c‹¶ÙÉîªîä3?÷JC`-ñ`Ùw͓Лý½‘ûž×Î ¯=aYPl¥ucáN‘Ô7펴6t 1ƒ½Ðh Í¿ìáU´¢¹‚î ºÂUî<3dŒXqS{'$ßÓÙ- zµ²ôÞ–Y¶˜0€aFƒi¼S]è¢hlîv¡PJgH^ÚŽãZêÇ%.Zæ€áN@áÅÈ^°@·4ú¸SNëØÕÛÀIöˆÃ> endobj 156 0 obj << /Type /Annot /Border [0 0 0] /Rect [342.915 158.294 518.97 169.203] /Subtype /Link /A << /S /GoTo /D (NFS resources) >> >> endobj 160 0 obj << /D [158 0 R /XYZ 90 720 null] >> endobj 157 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F31 46 0 R /F58 59 0 R /F54 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 165 0 obj << /Length 2426 /Filter /FlateDecode >> stream xÚ­YëÛ¸ÿž¿Â8ˆ ÄŠÞýÐË]‹; I{Ù(r•h[^JÚ]ß_ßyQ–½Ú®q8,°¤†ÃáüÍ‹öWüù«Ü[¥aèæQ¶*šWžP¿½ò¥·†ÍŒãû›Woÿû+ßss/÷W7Û¹ˆ›rõÙ ’õ&Èã$wÞou»«Z½Þ„aäÜ؆ÎÍ: qèL¥êõ—›Ÿ_ýx3-Á ú ÇS…‚ …’,rý0b…¶ªëáˆk]ê§nr‰íf¯YAæ_©sdBg¸í«Aö¢z¦”úWÏZ]ògÕr[t-NLW3áW/öz­Ob€à»¢Ñ™òRiã§nšÉnïö]?\§~ž8Û±®Ü½U]¡†¤`ž’?|ø´ö·ßÿ´ÞøÎ‡ Êð8.ÔªF$u[n+º?ö8i€9;Í›õ&òça_ë söÌVµE=–º?ÍÝAϺ>ì€ô-»FÙó’%gû€ât]¿xF9K»þ„@øl—°$í¨ƒnT··䆎Û¶jwlÓíŒj®Õ°:¨²4ºïŸU“g¦kGN‹16ÚT˜ ŸixUGÊ`¹+b´iõÀ»(ñ1dùù$˜TŒÆhžèA’ÝöÂåbÙ×nþïêÑ:ƒ—öïÏ ò¸ÇªáC@BjOÿß‚§˜æÄÝa[L+Ñ'ƒ3Epâg¿ïƺä¾ÌçU× e蕼ØÐ‰Ìn£+<,þj7gÇ"§r~†!žxË-£:`BƒÐlb/‚MV=“ %Œ£ïI–ÃDýXÀV÷¸ ‘Swªä^9 uÅvl- ¸©º–=íå-öÕ4 ìXœ\;¸§Qá$Qía¯U^³ ¡HjoÕNVnż fPfÐ¥•]ê6ô¦#‚@0IJ“Ð[…¾˜ î~ÇpK£Ø_%®bl몗Z^ FÀüñ _òg½ïÌÀŽbkãma¥$îþ'tµÊ{r® kEž‹=a_ÖÝO’Ë`ðqãð£·Õãµ–„'D„ƒŽn$ˆ|¸C7t'{@êØ[^ñ‘WíN8ÔÈ0]R¿Zû{÷@†ÆôÈìÕÑF–.½fÛ ÒØö]£‡=+zp=`Š™óQ72½Á TAtÚí)þ2õ¡ê÷âðRu+DÚRñHp2DµÒ¼n¤ïî›­’)Š›ck¨­Í/x„ÓÖC/Ag>‘ÔD"úâw&ª|1ŸXÌÙ(´;މr©ÛÚòȈ: Å¥dq%“ªao7ÅÁ…K¸ˆŠ©‡ÚEÑ)ÎÌ3šìQß•¨}ÚJêÞ0`C¦’$â5ÌÜÀ`í0¾qHøbçÏÜ Iqï» cdg¨ÚÙ»ïfÖvnJyìf´ÎÌü¢ï÷Ê\•7DŒ#ʨb ˜$ñI€š‘˜8ÆFÖ8`--šl {·’_ÎX±RË4£ùúºÞ‚Ræ#! H!pÒƒ‹á™0 ‘àõ ²Tdãu÷LØÙ5üqPˆ ì^t[×TÛ²±dÉåYàZhc-RŒMxBVA——Oœ¯K×F‘¤“W|»x5n¤–ãµÝç×x›0ÊÝ<ÏÎ qÊÚUhw… ºQœN¨úªŒ\€C…À‹¨±Á™LtºªR,„“;¶’% –™G ½”5ÏÅ—Ä›‡#Õ–6¹Åýy÷“¿§8ÚÏÊÎ"å’Ááƒî®£gâxÙ'Gt¨«ë3ò 4Q•Ú`^[€Ê5%ar¬“çë¥z0¶Ä¢Õg¥!ï"ÿc pìUÙ\½ÑYÙaì…TrõSª¾X•pâ(û,!mƒƒ0 |µšU£ëZ}ý¥H:{òàV«+š>­—œz®LÇEÅñïÌ‹‚$oœïï_çL_tF¿¯Ußëë ­Ÿèœ=Q¡gÛ^2Ôqûµk_s¯˜=lxh82\n Y(gèõ¬Áí¸ð2¸Z%”qÚśŔë‘”?J®Oð{JQºªdC {EWƒÙ`F~=Kç“–U[¿ŒR,ð¤ÀùxG)ईFöè4c2Ÿ=OÆtí+ÇQ_‰¡y¤ìL±1,¡¦¢ˆÂôÒq`¾EŽǾ‘œÃÀ_½dP>UE.°P#K£ç#jë[IäLDv‘8€{YŒN(€´S ŽpÂî*fË_*ûmo7*ذ– sºÝ‹w5?ó]ß W~ž¹i”ãÃipö¶f¹63¶…¿Ka¤ $RöÝIìDÜ|þ[ÝÝR`ƒÑókQ·ÿ‰vH:(¬()Ì/5³Ø!cœ©´ð*h¹^ÐüR˜¸:µ©@=”d.؈w ñŽ|“;€@` r»øìj˜Zåì>°µ~’¿ä•»PAcE]ýFõÌHÀÄ.B[Â7¨Á_òôÄÕ‚çü#ó ÐÈA©•uY>+ërÏ–u3ÅTÉ ;¼‹§… 9¬lÚ?À÷,«ÄËÌ¡¬Œ.8UEI8±Ë9HæMÂà('IÊìÆfö–‰ã…¶ßëºænÑ5àZJÜyœ=ûlðß±¬Šªû)³9ª ©?ÀPVPŽÅôØÎ²%»wû6Ê“KH!rànlŽ7ÅÉj˃r…òxXÛõ ð= z !èClƒ6 D-l.w¡îâ½aåhän²€`õ“CôŒC„ÿç/Þª„18ªðÕq6«(H܈"q½úôêŸl&ç ÆAæ†i²ò!‘Î@š]×[XÂzž¯|?vÿïªÞ dfA<_4ŽÎ¼Š‹¢m†¡'¼æ‡7?¾ÃR'¶5àüvCÝr¯™^¬c|S Qk&Þϼ;N¡A™ÐvS $ª^Ƚn!«¯î5>i' ½*}“%?†¹UðB½°Qø–#\,9?ró(:³ûâÆ¯Ž“7㧦w-wNK1ËÃTî™aàˆFR¹f{r;x‘qÿ¾ë9ÇDò¼ÜõÒ‚çaœAüQ0¼Xw±Üz5t£sÂÄMý|–0>½Ø×]yõÊ/’(  åE؃Œ\›{û$Lc­t¦R ?fOgùôt–ËÓYŽ›R ö-4bºWî!œe O±dC>¿Áq¥$¾ËþŒÂ/ ' üTï&¶ endstream endobj 164 0 obj << /Type /Page /Contents 165 0 R /Resources 163 0 R /MediaBox [0 0 612 792] /Parent 150 0 R /Annots [ 162 0 R ] >> endobj 162 0 obj << /Type /Annot /Border [0 0 0] /Rect [181.103 196.022 385.531 206.931] /Subtype /Link /A << /S /GoTo /D (Global configurations) >> >> endobj 166 0 obj << /D [164 0 R /XYZ 90 720 null] >> endobj 163 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F31 46 0 R /F112 167 0 R /F54 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 171 0 obj << /Length 1711 /Filter /FlateDecode >> stream xÚ­XmoÛ6þž_á"5#ê]: Zl¶›;`X‡Ž‘蘨$jÝÄ{ùï»ãQŠäÚM—ù`‘:’ïž{î¾ðá/r‘†!Ë£lQÔg¾›}wÆÝÓ V‹¯×g—¯b¾à>Ëýœ/Ö›éërñ›÷ÍV´FvËU†^xµ\EQìý ;I3¢|¿ŒO4…,q&ò Ï­é—« È8÷‚tùûúû³—ëEÀD‹q8“,b<ŒgÑá1‡·‰S–À–Öâå]+š²'ÜFZ³]rO:ä¢ë”¸‘«Nš]×a± 2o+:Q€˜;c†deYñ”E±S^Wî´‘‚$hXêÝuå¼<Ýlv6k†ýÎÑ d9Ëa–0Å“®*ñ8'ýqìè„3ðaݳ£³4È‹‹ãÎãAÄ¢(Ÿû¯Ú<Ås•jäj#‰$Ã7~ì¿nÔÈÆYê ½† ˆ-ùƒQwnžº‘·ˆû ¤{2ãzÕÜ≮ eq4îwq*îé`q"ì¹Ï²4œ;°o‹OÆd®ÛjÏtœÃ+º‹}nE!(8u½Unq!Zy?ž³ÝõH|¢ C¯­`õd#·\5ôûÆçQ%Qà L>X2în$Mñ©ì1âús·x”Îytìä_—pM½sK„>ð@ÊräÎVÍ žîÄ ˆ‹FÒÞ š²~ë¯èN‰?½Sº†˜…~@Àé±ëó€%€Ó9à;<7…;7xÖž¥êdatç† vœ$좙³˜ç£t¡\«¦—Ý{ÙaÂ’,óG¡ú„ŽEZÙãµq«[),R÷R´m§[Xf†UîBiiÃÀà t,⮸i{a#ï £ üj ÜÓNλÁ L¸CŽN’ÈÂfPIƒùk$­ªyGQYä,âP$¸dà ûͽäË”eŸE‰ƒqi]Õ+#ÑK—ÏþÞêÞü{9 @ÄÞêKúíu-7ª’ǰŠ2æçZ‘„ÿ›ØyŒX¹r*Þ›HhýDJÿ³<¡d9ãY0ìÛoeUº®mŠcB¬•Cá2 ò~’ÙI ‚¯ ÞNT“ 2‹ øÝ·aY¢†izÅ}˜ây˜D³waŠXê§î¥‹Òù%ùR[Mq°A3ª–éÆަÿ¡k\ UMŒû}/ÊMÏGM›Ðàâà€ó¡UÁDÿÅùÑÂlqRØ]ÝZ"R 3VèÔ5:öêZUÊ Ží‡j=¢b#›(›ýI­tòÚîè¢Õоø¢›¹!_·*% {3rªèô´ì³ªÙÚêîr˽á<YVåQâîSíð28Æ tk”nz —Aãöƒ…1:d{n1T\ôúÈ=Ka»dëNÝè®v¨³)j.Ftö±Œ c–cµza¹ôÞEã”®&ÙÍÇ9óýƒ¦ðt×}l#?¡bùé}pq0‰• †!&'²È`Àӻ¦D²Ùà#2–¯z?Ò\wR…Nî‡ÓHyð¹í“¥­zhg9¡Œ‚íÈ]p¸ÍÝy«à„Í}†àQ®)¤Zv øw¢F„-ì]É«#ê€[st 0އc1®œ¾Ã·~eM•£ß5è Ð#ö½zÿ¶Eçrüý`Déé5dÉ[’Ú·||Éé…êÔÝc¶ æÛ~\LÜ¿•öË4p‘ƒ! ‡hÎU7”ØÍ—£¥«ß¬ApŸäqÂâx\RÊ–ºJj×àX«2pàíVQwOCûÉÄÚ Ñp ‡ü‡†¡Ó‚n'‡lÉAzÒ`N+jt#ðøF øœEZF¹Ë˜»^œ¥®§q{ü½Ñ$ÀÖʽ“6E 3±„µ÷Êeg·nKËO[Vp$ʲ“½„w¶“4ìwÊPeGûÞÈzÖJ»AIRn3äÁfx8Èqš¼éô®íçŸvø¹¯{ÄfØcÒëm6Ïšv»ïUÑ[†ÇiìQõ<ÁïZtïžo:t÷ÇR¦ØÊ¯Šežš©mZéBT`ñU©¡’7¤M²Øö “´ùŠ6Ô…(Ì=ûí[ ‡T9WBQv‚ 9C³Hžº óìø? °ÝÎÆÆi%ŽFnu~ü¨´»i”7[kì¨ËÓ uaÖQQhšþzTn˜Ö;CóeêQ·ƒS÷´DÃͽå4ná¡\;~º~02ºgä¤= ½Û:BÝ ÅPjƾÿEö€j A endstream endobj 170 0 obj << /Type /Page /Contents 171 0 R /Resources 169 0 R /MediaBox [0 0 612 792] /Parent 150 0 R >> endobj 172 0 obj << /D [170 0 R /XYZ 90 720 null] >> endobj 169 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F60 10 0 R /F31 46 0 R /F58 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 175 0 obj << /Length 2006 /Filter /FlateDecode >> stream xÚµX[¯Ü4~ï¯XUHÍJ'iî—#ñ@ •@ñpP… Ÿ¬w×j/vÒsöß3ãg³— }ˆ=¶ÇßÜÇ›¬bø%«&^UY5y½jû1S?¼Hx†p±ãÍË×ïŠd•ÄQ7Éêa»dñ°Yý¤õ:L›¢l‚·[9ìÔ ×a–åÁÇ¿Yð°®³`µQ¢[ÿöðÝ‹oæëŠ4ý <¸ã P•®’<Êò2e@eGI– ,ÊÖaQ¦ÁOÃFþ'9"J‚ À©ÖV€yì¤E<—ò’&JRï=Âñ4m‚q/Fõ¢5:ü¸.Š'·ð´Wí:­ƒ=M…á£ÓŒd³\Éâ`ÐÌS>ìòëÌPoéû¹Jc•ˆD%1ð;ZV~„29!²()H†oáPÖ¦SÒà¤\²´wë0O’s˜xÀ‹¸N–O>áI=u¼é'Z3òЉVÎK°r¤áAô‡qA¶£Qðß1Á—(Þþ#ÁìÎåJ‚%Å™,DýDÏ4µâ :1Js‡c4¦ôG‹Ò[‘(ÑŽŽç:½p™õ4„vz´£§Qn˜ŸÚÒ%_T˜çÁF“¦ì-Qœ#`¼ÈgeÇ”‘Á»uÚP@©ÁŽbhåym–¬ê¨)Ë6­£zþyCüZ=ŒFw÷î®&Ê“ÖÁË!žÜºhGÔ–üc’À&-‚/éók\Ä4²{Ùu­î{Сßñcüýñ£0Ÿ`ór”vdެ\G¾àÞ€y†€„É£*®Î/ùúQ ¯e»×Äò ¼Û!rÌ/h)_ÞŠý0©£¢Ì€y¥kÒH;u£%ë¨áþ†úÁuQ^€ò~¯íxO¾y–í4Î °­QVÌ…×Kþ¥³#ÅQ^&·îý$Û{oa?8£x¦±4F³-oï\^ÇQÂ~G(¯h< òä [ˆˆ¿E‡Þ©Ay7ÿ¡.®íé ³°çÃ^±1E×éuZO<_æKA7jZ:%9˜,³$LõB؇@+ŽtjÎ{°ÚSÔo&àÈóú¸ÉÑï«(©2_Är,bYð5è•®£¤TAÛ kÀÊg7ôâüC>·òàâûoT¸SÙN›8ÀXCôÓ ZÈ—–¨OjÜÓHVvXsêŬPL“»7õÒZ±ó‡1•ã×åFlµé锫^x+‰„ijÚû½ä#b±|+k²Y4^–gà"•j0š'c`ÉÄti7mf˜Ö±â§ÊùŠ9ŒÞÑÓUŸ[+*1Ý‘x\ßëͬÐVr’Ty ¾&±„à,ù7$°’‹tGaÇT]…s KÒßYwä#•aZk]yêI~ZÐLw~â$>Ò–ZÏ‚ï¡=Ø„®@ZIÛ¶S‡r;ªc˜£ø°¦ˆ@ºEÜ’nT½¼ã`sŽêìÑqhŒÎÎ8b¾0:¢O¡T8Ù"p¥y71<MNí±<‘"9(·´~Ö½~WÆËH€ ž€¸ˆªŠ£´SÝ š$Ê¢ù(fæ„+z±÷Ï% (b(Ý$:¯­Ñý…t\ìˆÚ} yÈxþvH¢'ìy³À+L<&(ŒI XèÈÓ[–ι^-÷Ml¹l.æM°¦ÍÆÙ÷k"IWy»Œ,ÞŽŽEôíMÛ³ªùJÒ!¦+Å®%èc²J°§azÛisÄ÷Éÿ§ã´\è&¨ã `œdƒº¶ôØãšI ·§PABï90¼yäÆÒn§MXi…1G"éiä³ÃÌÃ=!–û¡eÊ|V¹öhGÙ¿²ÞC„»›Œ@nÿŸîþIlùZ„ãÉJ^¬ºizŸ¸ªÉ«°¥kó¸$ od+&—Ólm@0#èd>Xš & úpR?Òl¯v{uœî;ÌŠ)¾ ¨h_q¹‚½& Ðw|ÓÖ=®lå_Ã[9fæciÜ–uÀ.¨ØSz„ꥄr*eO ôüu4öÛ Zx?ÄP=ª±%+ûf§ùM“rqGânäë¡É†Þ®e­4£P¼íÙ §uá\ÑÍ-ÿ³p龋>)&ùðËsíη­ÀG#‡ÁÞX^ÜØÝßGNø9·X^V\Ç™ lŸ#€"ÐÚ@é/´ÌEØs®->õºùSP^e4á²ÊˆÏuPØ¢ÙÌ¢b{?x¤$u=·™QBÿ–¼ëNåÛýe³ù‰>²ŠJÿ¿ËϘH]?R&Ô¤ÀöôŒ#{…à’kþàËŒ¡-Ô‘4Yþ¡;™krÊH=oùgÞFMÐ&w¨ý2ØË²Óú;,u¨ˆ“•qëX5eEsør‡Ùsž-K*c\ !гw=ì•Ï¢?t®Mtv:°—Xæ5‡ ŒOÚD΂ˆsw Ê—ʊܽ¤9±ª¡í¦¼eÊ,‹ª,óå{4(_ŒyÎ¥gi>«kÎó'›Íg¼¦Äaí¯òï«æ÷<΢/lú(Æ{⺹ºèö^b7Ñ`cý£î.þ˸z6¦uT5Íyñzp¶ &ÃM§eŠë5«Ò§Ñò/²ª\.Ü¥éK¯Ol[Ýô”ó`ò;¼à¹O6¾pÛWç,ÎøÎÍW¥ÁWíü¼ôáëÚ‰•†ÿœý+È» endstream endobj 174 0 obj << /Type /Page /Contents 175 0 R /Resources 173 0 R /MediaBox [0 0 612 792] /Parent 150 0 R >> endobj 176 0 obj << /D [174 0 R /XYZ 90 720 null] >> endobj 177 0 obj << /D [174 0 R /XYZ 90 720 null] >> endobj 178 0 obj << /D [174 0 R /XYZ 90 408.016 null] >> endobj 179 0 obj << /D [174 0 R /XYZ 90 177.979 null] >> endobj 173 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 46 0 R /F60 10 0 R /F54 16 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 182 0 obj << /Length 2466 /Filter /FlateDecode >> stream xÚ­YYä¶~ß_Ñð‹5À¶†¤H ä!kÄH ÄFà‚À6b¶ÄžV¬–zuììø×§R-õh7“ èñ(²ŠÅª¯ªØr'à'w…ØeI:ß•ç7ÂþöFúÖö Š÷oî¿5r'E\ˆBîŽË-ªÝOÑ7'{]·O’$JÞÝíµ6Ñ_»Þñˆ­>Þ™4²mé*ÑQÙAû2w{¥r)#UÜýòðÝ›?=ÌR¥þƒ˜HñBÎDîò¸HSbJ™Çù.Í’8Í4KjÛç¸nËfªÜ»wÈŽ–/–d"NE±ÛÃau*ýšr¬»vðÔ+Eì‹"ÖH¯Ò8ÓŠéŸê¦ƒ¥"j»þl›æ™{ød‘ãNiû¾Fu`§›Æ·8iMi§Á>ÝùE¦ˆN;ïT¶©ÜÏBê6béÔR:eT, Љå½u ­âB™@8vWygFc'£Éw¦¡n·8filò$ld«ªlì0¸MÝ™,V™ ´1’ìöZÁ]d ÿ$–Æëÿý4¢ÕdQ}äoy´®E-„‰¿yD2¶~Ì­ŸrÃØ×åȘEçŽNWÁ 8”ŒÞ2Y ý–›O'씨ñÓ¦vuëB¾F½Iœ¥ùL8°ƒóÒ£¾ñ{´Íà¼áÖé¸ÖÅ}šY€Å2›X«j<¹!8[-ëUjð ´i þÆ´?vÈK¢Í"ž±-ƒ=áõR6äÆð|F2¶‰®ÙRˆTÅë¢s¹´7d1Ûv@ ý¯Æy9ŸQ€nâyV 4‚R¨cÑó°Ñ¡©Hq•?81uàjKÜìĪ”y2]«}-¾¶yýp©éë›èù°1¯ÈÑ,ñsv µº>è„»{89ÄN¢ éžH<@m„g¿'š<ÍÌÇã•§ÚÒ°qumèT]»ôa¢0 Š" kGÏv¦}´£7Å4¥NëÉFHîÏÿØtÆBœX ˆ”jW«”ÔŠ½—*6™ß 2 Ñáà ÿõŸe;cL¬`?ý"vL~·qRä»'"=ï’"‹S… ›ÝoþÆbÍÕÛ$Ki7!ÕÌXl0† RÅÎÈ,Â|‰±Ø% 0®Xò½u@èNaLj£ÞŒ2Ñþ{þ. l-ŠŽºúåYë#¦ ³,Ÿµ ¾ ~çñ,täÃRRŸjê-÷•H"v"l_ú瘹A@/ÀŽŽ*S``~¡ca¼]xÆ ¬"UÕ܇ÉABB ñ…+Hgiâ ím‚ôP3œP(Àtxü‹²>ú™K±SkrJ\ˆŠ?V;ºÆ•!#÷ nšçÕ²a:P€¤ù£ŸBt§Nn- ÂXÐ51Ú'¹ál¾|QÐXkp7"úÇ]žp„Šª KȲòô(q}UqÄ6ØA³µgÇkF¿K×ºÐØ–du ¯T{¾Þåeë«H0Ã˜Ê x¤êFîÿºiõi`—®2°IÚÒÜ¿æÍèH$ÉÅöxôäícT_Aê6šGiéZ¥<­_¤9½È|úÛ5<Ûµ`¡3€¬µã¸ªh&!¸zÇŽöëØOîkn{']àÀ–S.|xÖ6ú 9¤b&HÝzôIÖ8Zµ®Š¹ìù³ ¾_{¡¬ßË}²çKã|Ù±ªTÑ”Ôk7oêö·!F ÝÙÍæ±(L†“kš²;Ÿm Ú&_=ºf½ì€ÎÜE Þ’ 6Ð}úaäy+ÞÚ†å2ÖW¹a¬WÆ$b#Ô2Öª˜=õÎ@ú‰ù` €©Ž9nãnF ÈÔœ_ÁE5.…X@«n‡Ñ’ÏhIp²å "܆Xh‹Fê+»ÀÁ}rå4¢½‚õÌšµ½>œ,š’õYJE&¨a¬Æ®¹* 7ÖׄMC`COõx «}6´)“@ÔŸ¹žul+âDΔ\ÅâÞsÝŠpP/©ÒòЬ©½ à^r¯@™\ÍèphhÁ½Œîì£&†H0LðWh4àfôº`œ©š¹·+4a½xíÙÓl.ÑÀŸ6÷KOf¼\úÛÖ–Øe>ûåñx˜e`2±à\!#gݧÅùÜ"Ú5xj›y$ËzöÀ~lAÇÚè›°ö]“Þ× @r¾Lû‰û¦¦âîõIDËE‚S9x"ò˜îÎõÈ#¥ëG[·~º>»} 2)âá˜÷™·Â²‡PÑÜà%UðR«uõÌ›!Á(’è„fBC¤råØõµÃxV(ýÐóŒO‹ú“½ ¼ŠÄ†P³ï»¶þÝñäõÅ2ƒ*’e¹†ssáI>‡#°ïFr|½þÎkÿµþ-0${è+¬.7rLñ2¹L8¹\šÇ›Z~K™š)¤Ug~ òö%PàSÅnáKv)®}¬[¿âZôãFõã õ2r—SÖv1BÞ$OWÄôиåôüÊáG0~!ëÆÒ‹ÃÀ]r&PÈv¨75’}™Ô–.dƒ¤ømÝL}È«äôÐï}-€ØÆO´^ƒÏ0çËXìŠ+=eÙ×—Ñç²ß€}ÕU˜BÁ^&ÉÇ®i:zWàÌñš¤lä(P£eÅM)òØwÓexÞ˜$>É*0 ¥‚~tÿ,K.aÿÀŸŸ…ÜúêþP·÷¼…Z÷Èßûièï§òp_–_ÑÖ&už¯“ŸÏ.nºÒ6÷íDËaÈS¾úýöûn¤œ#gnà*EàËïBý@€‹b±¦ †L˜¤®–Œäç¹ÒR—L!œãtÈ¡·@<?+Òù‘õ >©5µtùò„L¬—Ø6u€²ÁiŸ¤ \úæ‘ï|35è¸ †ù0XñßO®uáÉR wòæ ×`Jäðï€Ä(Ηa¨/6&úà/OÔ~Âú=|½3M=ø}:Ïp|«¯Áù—[0¸Lå²tøSk+~J‡³óa–îr˜«cð“:”ÎIuðxlT)>,w!’|˜:*R°ÝùŠ»w ò=Ç=a*¿…>A5†;Ó%Ø 54ñâ\lUƒ4cÏ ×¡¨Þ­M”΢ Zµ¹fÅ1ÚﻩoOáÝJÈÔŽ~A äØcwÁ!,ÑÛ J.+¿þw×{Þˆ‡—{¢åøW¨.N̸ endstream endobj 181 0 obj << /Type /Page /Contents 182 0 R /Resources 180 0 R /MediaBox [0 0 612 792] /Parent 186 0 R >> endobj 183 0 obj << /D [181 0 R /XYZ 90 720 null] >> endobj 184 0 obj << /D [181 0 R /XYZ 90 482.018 null] >> endobj 185 0 obj << /D [181 0 R /XYZ 90 257.59 null] >> endobj 180 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F58 59 0 R /F52 19 0 R /F112 167 0 R /F72 4 0 R /F54 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 189 0 obj << /Length 2682 /Filter /FlateDecode >> stream xÚÙŽÛÈñÝ_1Ø—¥‡Ý¼øaãÄHIv± Ù ¡É–D˜‡Ò$=Öß§.’M™ã5ôÐÕ«ºªë–zà§òà! C?²‡²}ÈêÇ7J #8:'þðüæé}¬TàçA®žO.Šçêá_^Ž:“Ü{w2ݹîÌᆑ÷Iãzχ,ô¦±·uÑþýüã›?=/äb­ã>xâ·/”d‘¯Âˆ/d>×ã¯A¬|ìÓÍÐAy†á²)†Á~Ù–½ÆœF†.EŸT<êJô§»/W}îZ ¤3O¾…uÇ¢/µ+‹A¾ù/ÊXÑ.+a”û*Ή‘KñÉü§,åà†ç(ð’ƒß¯ì¾ÔMÃD?À³dÀ/|ýp ³Ü×ÈS…H€¾ídüÃ1ï/ÈQ G”}Û]ÅkÆÉvO bòÆ“~–©ò,®„Þ§C òh&ÁƒR(:†µ½œ©7Á§-xÓtƢŀƒd¢AU‹µw6ãÀ«e…«<2æ„)ëcÏãªÈ±¸º ®UÒ2ÞÇ™`U‡kQ 1â£ižM]eìæb¥±cÁ‚è^@œ—KßT{6_ž@"K Q(ËŽå¢8i‹J äGÀzee#¿®y+~.öÝ#¿b^´9;1ñºEç…¹÷ÌÑ Ï4 Ùô‹Ìoè»úi{ÒšbÜuÖÕ­+ZtÈ …—ؽòPÏŽ7®¶?Û¢xör©KܼÌ_3 ÍdŽÔ ªzÓÓ”3¯°,?Õ¶_8ä yW3MǪîÔŒ ³k'`ãd'°|-ìÈg7A#ÈÅálA 3qùæ)×T>ä'~ ÏšÒ@<ìm»ç·ÀMë]Hî§™¸Êœ O{+dzW½:ñÜ€×Úó%Ç$ög¼Ù?Ñpɦþ(O†3x‚AÀáÒOMÅ0è²±üâzq‡r®2@ß9I1”1Ï„ ¥4˜5È.V<̓( O¦®1ð\g×ÉgÚOòÅϳœv™sô£éVƒï_RgÅ N Ô¼­¥p-S.®Äð9NðƒÙsâÄÑmœNÃýiGç3k)¢1/O $ƒÄvsÍŒBX-ªªîàþMS|hvYÎ_eKι¯"ùy*ñ*[ãUÌñ꟯l-.BÕµ™Î”%Ü’ƒðª©ù¦Ø…9«ÎòY9Øýy}áIkXlEWè'tFOð`F¾^NªžÇ®"­¬¦Ò|AŸ|xC‚èíxçSm娩·›#v×±÷¾äy²¾?¾^’8Hã€]=/–â‚ Jš±û•SûÄW”“/$$}W2Cè%q…ÙÁ­EˆêÄ߉·<«À»¶z~•z?óë}éÛYbø”Çø I@UQ˜pDÀqi)e¯°°ºwœlß2„ªLa2‘䃲¹€¼  ¶8(7ŒœøÅœŒ5¯T-4SÑ`¶ Œå:F×)e]BO—ˆ†º?ŒòQ®üÊyS‰Å.­ˆ¬+ÃgIq7_0–Ôƒ˜>¡]MŸ>°Bcì%{ÞU"Ì…>ƒ!ŽSôƒq%Åói`û›5×zθ¼7BñEÆ’JT4<âÿ´ÌùIñFöª“<Âê$Ï'õoë •ÑFž5µa€<«¢4I¦D9q¥U޽½ÉÔÉ_”ròC%—øDk®(± +:Ïü,Xzm×\éìÅ•Àl+T¦lܺÈs?‰Ó­YùÙ_ ·¤7âÒIZP,ãU4gK´µ_`F¹ßsñûWó¥%*¶7>º[/§þÊæ÷%%ùÞDá6¼úÕ-œ)N|jj p`VOðâ ʾa‚„´'M¶ZøÎ-$tªÅÂê;ÊÇ2ŸM9Q¨I‰6‹ ¦µ4/$Qf‚¨¤¨GxÖ,„%ºör‹^ŽHgDcÊcg:½KAc-Ò¡+ûz™„‘4ͨ6ÓØ?BB ¦§ép¥ã‘I&ŽŸ¥L="ØpìES/¬bàR Œt‹b±5\AeDå†×ûW0ù92ñðNª°»”ã8q›ywn‚ÏH-N‰Á‡N“(w&v h×#/KÝJ{7Búp8µÆéêЩ$÷„ûVÊ›Æy«c¿m<«Z²{Îøp»e§à…][Œtèëhiöün϶b?ÕŽmqgGrÑM‚^ŸIÞ±t±6¤z´’ÕÇ5’*ǵ8I6--œbÂá<É++­´ŸFKcèøÇ=f”Ú4¤‹§ÓåÙzòÜz•kºf(·MEØ´MÂ&&¿rAç~.UÁñ5a§Ž#Cd[Á.=ç4‰îZ–³´ÃTq ãÚhH¹ï‚ãæa‚=’÷aéÁÀz°Š=Oîs•‡~ºxóãß¿QêØˆSﯢЀ $;W/jÖßW©bk1[ȾýY’X¬ðâÆÚá©-JÛ"[û™J¶ýü~§´¨©4k~蜦ϜôWتmždD/ ;6qj~D•nºH[¯j¨³úVÐÜ@¸ƒ@,j[‰ í¸t'/ƒ2q›—…JRßÑ*˜`*\T ëQèýÙX9ÊÿÆ`ôå¹´_A¼zØPRªC.7êAþ¾¶²ñü¬ášQ½Ú½ÇÄïŽbè­ÿɶé;WlyP‘$II¨ÀÛ%`nXÚ‡¼ÜUátbÖMÇr?Rغ=Ôz?Q;ÆP½å­Œ!i|ó}Æ'þhXN©™OÂ,|n ´/ã'dQÔ„ü(‘ïNuãΆdcííº­?#ßəžçÒƒ©Z ýÝæËYL×ÛÂ…¹#xµ2ñÍ®ïûó_›ÿÙ endstream endobj 188 0 obj << /Type /Page /Contents 189 0 R /Resources 187 0 R /MediaBox [0 0 612 792] /Parent 186 0 R >> endobj 190 0 obj << /D [188 0 R /XYZ 90 720 null] >> endobj 191 0 obj << /D [188 0 R /XYZ 90 619.643 null] >> endobj 192 0 obj << /D [188 0 R /XYZ 90 452.574 null] >> endobj 187 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F72 4 0 R /F58 59 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 195 0 obj << /Length 1626 /Filter /FlateDecode >> stream xÚ¥XmoÛ6þž_á¥&o-Š”%¥(°.M mö¡Æöa0E¢mmz1ô’,(úßwÇ;Érª.–|y:wÏ=xG£ö`Ò<)Ò"iÛñuòq,\M›¸~(üPÑ&7ug÷uätû¤ÃQ#±Qfæƒ'uµ”NÞåuÅÒmÝ ‹ ­-kx‚z_°v_÷EF/“¢­Iz Ð1'¶MFÓ¼bí–OáOO¡´Þc;¤™sG‡ÏQcÑ®TB‚º}•o!çž?oiDÏ5œÊ"$€‡%x~·„Cš*7:±t×^àÜü´¹¾$½”×=û£§þÈØ¾¯‡Ê¾íæÜ¥ ­Ì@2'l´­7˜ ÃÎÞÚÈ̉tX¡oój7.*ùTÕÑŒ †ï{B©è4é6Ùññ@Ý·¥€yÚõM‚xŽÒÀAà[S´¸§¯ÀlMCí$)ƒ'÷yQ{Jâ|WAt3µ(óWGJ÷KBˆ7yÇêtvŠ~gO‚6ºÖ[Aa<©,ˆ"ž ÊÊgÄ?ûjÕ·Íê6¯VÓ6À#y½æ£?›Úê*kÄöeùÀûO5§«c¡¥†ÐBB¡ü§ŠºãJ­·ôLëòÐw6ªþ()S€ŽÕO‰¦,gõG 31¸¶ÌÖìLt" µä+âX¸P2axzüs194yÕ‘OçßN™èüÅœú§YZ:Šq7KKÌ}ïŽ4‚èñ ÅÕÞ p0@j¨s@|SW%H¥3bÞNÒäÌ (Ú6uIVN‚ù-ãqмÏãf×—¬Ù"î¥çüeKoÙpB±¬ÅZs-Ñi³ë¡zéŽi÷¦( ãeRñ“ÕĆíÖ#€¼íþ‹ØûïÈ} ü)êìn&Ý×dæâ›Ù,Âq£`}šÅ«“jdú–¦”ÆÀ. ­– k$=ÉÊ]n“<µH÷5%˜$xÅñ„u»&)Ùê>±Ö‚Áý Û¸ËûwõL29àukµ×`ZìxÒ5”b: ¶uQÔ¸Í=Ñ0ˆ&äåÿá«)±LËðµIëÌîf“u}óóÇ«7¯Þ¾½zûêýûë÷Ÿ>@QËsšèïào”I³Ñм;2ÏùåùóóÏ Ÿ#}¼˜sï~Ÿcr†õéËvŸo;O¶Äå#1ù}™€HvÁk?^¤ŸN\–/ž¢«‹”9Ÿµ5Ý£Ðü æR€õ$.Hxj1¬Žà§¢/“´©Y%gB‹n…%ØbPÕ}—DÇ@ÒNÛÁi~»–æx™<_SÎ l,T-‚ˆ½~9s›hzáp5Üq‰UIifl¡€Ê_²­½™hä‰0~Ä"¿ì!&nì«¡ayÜ®•ÐÑØ^ ®Na5ÛÂñýãùNh$†–‚{ jL¤ÝR[Ó ø|Ǫ‹€Ñó}gh~Ò+ºL(khÂÁýéõ0¶‘ÅÃ2RСÂý¤ " Q!I…}Ú·Ð?¦ãY‘ãÍ„#„„}ß7 ã ¶°¢ŒzDé &al»o«‹ÂPWvÃ…«dÂŒ¿Ï6ìÂ{Ýàh•nM÷YAÛÞ™Õ„tfÒ$C)"9æék¾"CØB ¥¡y±—O¨E¤±q“ƒ”öZ9[¡v ¸ ‡Hqðc­ÅjjMZ¬ÕØ%ÕÃü…Çj®Œ¬ùûÒn¥½ÉVÚSØùfiÒdsá‘|žÄá»ùÒëðÉ0/àNc3;õ-æÅJ”@+Ù¯5”% 4±qÀ¨€Í ÷-½ÉáÃÊ$¼±d×ÒE×®B2"XCÁPƒ'p8vÿÄFÄS#?Mp’88úؾҳ!Y‹@œSWóäX7–eóÝ~è>£à9ÿ(8Lº Ò¤8ÛÃçGÚõÃÏ·ö0|ÊJ'…]:•ËáW‚¿ŠKš endstream endobj 194 0 obj << /Type /Page /Contents 195 0 R /Resources 193 0 R /MediaBox [0 0 612 792] /Parent 186 0 R >> endobj 196 0 obj << /D [194 0 R /XYZ 90 720 null] >> endobj 197 0 obj << /D [194 0 R /XYZ 90 124.998 null] >> endobj 193 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F52 19 0 R /F54 16 0 R /F58 59 0 R /F72 4 0 R /F93 198 0 R >> /ProcSet [ /PDF /Text ] >> endobj 201 0 obj << /Length 2196 /Filter /FlateDecode >> stream xÚ•XYä¶~ß_ÑoVÛ\‘º Û‰õƒÄ$@œŽÄž&FGCRϸóëS—®Y­×Á£b±X,Öñ±ØúŸ>á!‹"UÄù¡lÞ…Â}~§…:Ài%ñÃû?%ú CU„…><œ×*ªÃ¿ƒÈO¦HÒ"øñìÚ'ߺã)ŠâàÅà7 ŽyÜÆ®÷¶>þçáçw{˜·KŒùŠ=(ñ™A‘>äªHÓíÑ&WFLJ4‹TšÅl”mï?ân`}¾FÙ8>œà¤C)V—Á¦±ŠâÔ :È'tz”H¶¨ôxJRüÕ=Þžà„O >K‚Ñ_w#Ëu¡ Ƽüûã)Ž“à6¸ó­fzì}y4YðÌÃWr!RÕ²ý€ß4;»Ú7¾µ£•£WÔÄá]Å3S~ÐàîL—(v±í²8É÷¼ ‡=n]ÕÚÆ)ðA‘¿ú¶ÄˆA¬â¯ã£ç)O@hÉ£|É#àû‘Y Ì›¶¬»µ•ë‡Ñ¶OxY‡1eI°‰YÝ™9C׸=ë/Ý0¾ç¦]¡Ð_=¥/pß\ë»Ì>µ]Ø©½'ëæå³Ñ ­=ê ͽ+»§ÖÿýÇqðB %$*ýÝÂnNª| ±Q…Ñdxš¥lxs'‡Í¨°­óyEª¢TV”¶åÙ@P®aÐ1=ùô 7þõÿ›À ²SÊPRY:é¤yOo\¨,š%[pv”AÝÁz¦;r&SÒp•f0[¹ßB·tZÒ>nÀHqZaSFÁ—SN-äpjE©õV=擨_²\%¡‘¬c«%Ã’lÉ0 —°À€Ó­ÂÂÒiðpÙõšŽ2•,‰3N¿ì9L' ÀJDº+Ö>oÁù„­‡nÇ¥Š©Q¦Å `¶8j¼a9¸r$c“à·0 'óÿ Z9CÑ;IðG©P›m96ìÌ›­A‹þCN'΀¿Gýe A×ÁÀ \ÂQ# EÚÕ‹?AàâÑ$#‚ŒÑl!•i/øÏµP gdQÂ`™ý‡LûX;fót§Ýeò&­–M1©ˆÇÃkß=õ¶Y«™ç h+¾5Âé†|‹nÂ~°y¸PRGáz o|7±%Ÿ¶¸³âk ‡²r2éÚSÊ££;ù^(Þ{už&*ò)Á§œ_(ôZ‘\)™ ú©òà+KÏ£+lÊîRœa¤>l¸)½=È}¿xbùîÖ¶4L›Bú.žWJÍ!Øtcì©Ä$Á_øƒÂTcûg¦ú‘Ffõ> B±ãžëÞí•=PãÕnà’¶q!ç G”:ðí¡ÏÞòn­08lD/‰jš˜¡$°ð)Ϙt¿—î:2ÍÇã…Õ^~ö|Wv€¿¿Þ¹±|¹1Ìâ¹j8üÀX‡Ü$ð€;©÷|és³\ßb·P:áû3³—Ž—d¸K‚ÞBS:÷±ÏG© n<áyO~{$ÉÓ²÷×+CœÞ°04ìÑÈëÕÒÜÒõ£õ-Oˆ ‘Oûê5ÀÑd=MqCâÐP‘‡ÜËë ©qYYðb’+P^v³ƒã££wŒ¦îýKX"=Ã@ Ávåm”N‚÷ŒfÐârä.è…²j~éFèsNI˜r(R EÆ¡€¥F 8bËØ“âÂ>‰¥Ìxñ˜!i2õòŸ]E¦¢h†òŒÛ©¬È¨4,&±9óq yÀ¬vϦÝÉhlMùh©26²­Ç~›`h*/¶Î|õ#&¹Ž§HÅÓª)‡{¦|%†fB0Yc7ýfiy†/®RTÐÀ¡ºYË÷®éF¡±aÁä‰rKß@ðï“4 ~µåÕ1H…Å|€ðóúÒnÙtxãl;°¼¼ ˆr< LýÅ ÒÏwgè+fJGë.v¹¥™C="|©Uq¥è'§„Sc ÂEš9/3ŸxÙ5 ÙÛ|ƒ+-¾žnpµ¤K»Ûã`Ó•ô¶ÓɹÓù'úÃ×Uiûj˜Á‹:žÊÃcìú;±Yý3ÏÐOtˆÓ‰Ç#¸˜Û6Ç.À°x~…Ÿ}½¿e)£³å±¾ëBcÀÑs{0újÿIŸ©¸Ð“ÔŒâhçÔÞËhqÙ|ž‘¿¯?]98Äŵ,æ—ÑÔ¹’Ô3¿Œanîb³Teá›êF»¶t÷…íWïX;\ÀZè›*"XPQÁß©ƒUŽ’¾£×cCñ>¢ '„g–8;;Þzçú,æú)Vw °÷ð¡aYàõÒÕ¢ê©ïn×½"§º(òÙ©üòmYdâËŒ®o.µ_’Í ùÆȹÈEŽ4:‚IÊgÐÁ=)0ήžtLi‰ÿ¯Ì›;V á¶fß™Ô40çâ·U°y•Uå1÷ø¿Ú~£%3Kñ~ñÿžoÈùR\W& W•¹é; èXãmãùá6ô¾ýðí¦»”©ÇÚ”}ü©ý_ü Iº½{w…¦j¾KMdø';#½526=üÆky¡Â庄s¡·þ›²bÇ0#ÎçêǘÞÚ´#5G¸ç*³¨ ¦éU…¢ÌüºŸÌt,f¹[êÖ诔,…dû4ÈAÇ€$ݦùë6#6†’ŒÞ|²G³= f :†Sˆ þ@äz;:Ñ"PkYe+±.¸^f1.k­~R°TÛN­ÎV©é'êÿ4Øøó endstream endobj 200 0 obj << /Type /Page /Contents 201 0 R /Resources 199 0 R /MediaBox [0 0 612 792] /Parent 186 0 R >> endobj 202 0 obj << /D [200 0 R /XYZ 90 720 null] >> endobj 203 0 obj << /D [200 0 R /XYZ 90 610.94 null] >> endobj 204 0 obj << /D [200 0 R /XYZ 90 448.161 null] >> endobj 205 0 obj << /D [200 0 R /XYZ 90 220.528 null] >> endobj 199 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F58 59 0 R /F52 19 0 R /F72 4 0 R /F54 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 208 0 obj << /Length 2858 /Filter /FlateDecode >> stream xÚ½Zm‹ä¸þ¾¿bòéÜÇ´×’_ä^XB²°ãà2B.­™6ë¶Û}3ýïSo’í÷Îìr Ó’\’JõòT•´ê&‚êfݘ8wI~SÞE2úå’Ö¶3Š¿Þ½{ÿ)U7* wÑNÝÜ=Ì—¸«nþüm_GÛo¶qñ‡Í6IÒà§®·lµøé4“ é>tK^·¸ß P¤aª@ …ÄÑ1†[Ö~ݲ΋²ìú €ÇŸêqÏ­ao›†‰~TÒØípºÆzü­ê`Q°&s<.,Ql±¹ð¹Ã¡h+&Ä¥:\óI¨ºÅ^@€ÇÎ’ CQ4gžE&¹œ 6òX·ÄYFîµb«ñN…;å,ñXŒ`!íšÅn…r! VOýr $*BÍ­l“æaf¼§Žuu^ÛC›0Î=3%Ø?-)gáÛ¶ð¨ø;°mY?œyDŽ1pï‰ìfÔHíLšÇ>[µ‘h‡¶²ýª¬"Æ€nÂßCsWŽا¢#+@ãdJ‰ŽÂ$Oé9 û¾;=î…ŽfÌ$qÌX™Ž¨‚¿OûZ—º"¨3÷&£€¹~gû\ê–L7[AF eNj)D15Ž=ÃAÉÈ50ôDša†A [tr±Mž ¬à~wâà‘3’(žq½ºP d™iB×Jµ`ñûúÈß×bU«BÚªä+–S”üarºŠÃY˜&é÷ˆi†g‰£…(n‹k\;}¦ÀÔ}ú²;~ëé8œÝ÷ú(Ã÷I(f&pFˆö" ЄñGç¾ëŽ…°õÅß,08i1P)Vãv–Qú#³mUW}+MÃÈd/Ŧ3/6Øn›±éU±é¹Ø€=ü" ü™(Ìl:œ~€h´#ý2oC ôÖ.eîœU˜Qdеš•&Úää÷=`ÇH¢ŒÃNmØöx8p¿–ßq_Œ<?óe8ظçlQ(;NH/Ö¹ü ¢ˆóç‡Ñ¶¼ÖEÖ¸C¡çPºI›3ÈC,F[­a|-y<Ç71Y3Ûu/æék¢ u³¯š/TœIðï äéÈ$e%<™ì©ösLj¯Ed–ÿ®‘Æ>—Í©òÎZÚ~,\mÔB±Q †IRQÛ%ê“!ÖŠP‘&/ˆ¶•µ”ë ŸñÖ-çk r¶Ì#×:,Äo;Ž~M¤T—c^žýÅA};EN1!Ÿ¥ã‚%S±žƒ\Ýå±×"3ûxW·‹ƒums^Ú´v\ Õ×γrØWoàÿ›C¼ø+œî$^sák-|‘"P½sPäp^@-†qIVçÂPU¸q (3å”.·U®è‡ ãtÄÈå,¥lJ¸Ž[6½-üþ¾ª7\ÕØ}ö«ÈAü²² Ä%Òaqf/…•¤©SàU®tð3fÌH‹ŒãgH–muÜ™‡ ^éû^ÝÍqÛM E}.=|—2#*6 ãAw$k[9ø©=¢œòL²+hüã° šrœPÌ¥‘SŒ“,»S#d>ê`gŠ:Ø«ŠöÑBeƲ͠@ø„ňÛpZ/Â8Êïvat8³\Šgîƒc­@ß²vºšŠ¦á.õYubÃÈùÎŹÖØœ{s—qôiwV¸°ÁˆG "êgY§–…eŸòt“¶2­nùwÜË‚ƒÁN'á¼Gã#,yQÐ?|K%ý¦íóh”å`XeSp% :æ+ jJÚ”Mw_4«÷—i¤ß•L¸‹}ÊçE«„åÈ› ¤R:¸›R_H n™¼©Û/Â9ÇäMH(‹Ðh‚1› _Pä™0/r½e–Rfå%3n4X' Ú'ãø]Œ$E®@Ș „úÌ.Ä„‡B.h±ƒE>|û­f[Pék¾_e‰×{½u«tÓsOƒ8ü‹ü KÃ$5KU|\ÓE…Ó™uêîün¶I”BMc76!pæïÙFö$¾rlù«x wXIÐãàöÀ¿œê.¿*Nvq°²EÃ-¹jÆõ9²Ð,«ÀÛK8 8èÚEj]:6›s+9—+Öâï‹$ Ìû"Á¾}F·’ 8ºØíº;N›¨)ƒ)Ïû²òš+‚mGz÷–‹Y~(×S—‹é·–¿YìoïÈ'«0¡4PQ¢nܵ+ëE‚¤Ó-9õ¡ò„@…ï<É›>:2^Ï\\¶{]|¡’ñÌ1¬¯†+媚#ÿº»ìÀ¯’צ•^&Éo]޳ÌaYhJ€üó ä`áóªâ¡=["»îøjîùPrM¦'µÝ±±r+¬•²,á¢!ÊCÈDIæ©ÉgföÁÙµ‚ütµ…¨äýièß7]Y4ïïÑ!ÐA#“¦Üv‚ú1DÇN#?>ÔÏrþâu!Ñ´þ¬Ï¸ áÏôdü³‘q'ÁN~q‹iæ$vp3…Vèj#cfרÆÝÐhu‡ztoCfög.«:@ç+#/V¼åZMH¸Å——†¼!D©½§{ÝK²íTÊ8$òþA`ý<ÎsrSok«o•Údan¦Àq\…eB•{Gøß._&Jd\<¹’¶`ž*2¸Rþsö„Ã'„4|\±2Qh&ÇxÅǵöHö…|ÏãîsÈ‚½.j…¿!ÐŽ)ÎJ¤–ªšTµyq;(?ê’Ëü„UA_s‘2Íb…Ž/ò•Y€OzüŽ—»`•ŸßÃàô¾…=TÁÕBåqM¸ú½ ß:@‡¯½´ÏWñ¯ÂÎR2z7o]…ÃŒO±_>éÑý$òÑ]£g $ #ÒqF;Ogæ FŠy|H1ƒ€í??ðËî´)=3»¼ÀÄs©Î^ ø$Áì}Ùe®ùå[ N$O—9“/›¹/›x^ÒS5=üò#w·šìø›p•LK’ÅÁ£ÜA·<>ÝD¦*®l`¸h†Ž[ž?vø6ŸÊ½ƒØ_Øs©,ü¼ŒýT.e|°dÖøŸJþÉ÷þé endstream endobj 207 0 obj << /Type /Page /Contents 208 0 R /Resources 206 0 R /MediaBox [0 0 612 792] /Parent 186 0 R >> endobj 209 0 obj << /D [207 0 R /XYZ 90 720 null] >> endobj 210 0 obj << /D [207 0 R /XYZ 90 600.388 null] >> endobj 206 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F72 4 0 R /F60 10 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 213 0 obj << /Length 2380 /Filter /FlateDecode >> stream xÚXÝoã¸ß¿"Ø—U‰"ŠÔ‡·Ø‡öz‹Û¢èÃm€>´Ž‘i›ˆ,¹+ú¿w¾(Ë^¥{“ÃÑp8œùÍ ÕUêj•]UZ§+S_5ûw™Pß)ÝÃíŒãO÷ïî>êJeé*[©«ûÍ\Äýúê‰6×·ùª(WÉ×m}ç®oµ6ÉSŽ¿:¹¿®ur ýàm{ý¯û¿¼ûé~Ú®ÈóïèƒßW¨¬Mª´a…ü¶ëwÛú1 *±#ÿ>_çuâÚöœz°!¸¡“™{iÚãÚ­å v¨3l™Ï·ÌUžÖf*ÒŽòÑ'a­ç¬¦HkUGNÙLÏŽaTª Óë[cLò¥cEú°sÃìý°of¾‡€Ô«[eiFS:U ³-}dñßëÈ×Óãä‰,2 ~-—æ¯UÒEy) Tlo@^™®PSøew^›ä•t9âD' B%¨ È@yÈ`ù'›øúálmí×€{¼òªíÖLöãŽG¡ç¥08˜äã¯Èû½ì8ð7q º :]ñÝU£êÕ¤zçàÆÉzÓiÑzrZÜ_Ãe4¤M›4e²{9´¾Aˆ åî\ƒû=2iƒ'Æ/ÂÎ ×d42Ñòψvt;€mÍ\‡ìÏRÕÉçk8bÜÀ½Øý¡u覚ôÞM[UptÐìÌAÜËäô:ùuÉãNamòÎøäªJUG¦,2­¯³` ¯ç»a®É“‹]üØŠBt;4¢éó›Ð|ûaç»-O[ÿH¢™Ƭ­VWuº*KƒÊÞj•V`¼rÉUo<¨ú1ú½Êr8€-ßÇá®íÛÞ= ëy‘ì?e¥1<öÁh ¢Ø&@(}ÚøÛ¶K6s¤«ª¢_=îo}p²dÝwÐi@Ö{6O‚ÛÙ'=ÿ:Ø¿…C<|àÙ³oרà)j¿ÿ>ÂV#¡JîwnNÅq‰¶§ý«i Æÿ5­‡C¿ò¥P\ÓîäbN1Ô½ßîÈÃy­ëƒÐm PÚ]|<j"ÌH_:#„SĆð6´}¾fˆZˆµJU©&Ð_û@î²t«…I«²Š¬¤5äÈd|å0¶/8/? ø™À©kÐÔCØhÒ{ÐÇ;¸ÿ™‰À☻ïD8†ÉÈ4BL Ùõš-¤eÙ‹×Ê“Rx¾ÆºNë*?¿Æ1Øî7»@9pƒÛâIÕ…I8‚`%«Îè?wa¸ þŽˆ-æŽ#fN˜+KMÜë§—ËCk—¹¾P-ÀLïÓ÷ßg¹àa–_\sFá)ÏÎ#Ç¡µû#† šÝ{žý˦̸¨ÉÙÈpI¦Ì¦tZ õ*-¹æJUK|EÕàþtNPIdÃ/+ퟮ5¹ ’Šy<>Ó‚[FrÔ ¼=¯çðŒØÑYè;6®[3ìÂܳŸö²*iÝŽdJV$H‹ûécËLÛ¶Ì⯰EŽ¡¼ó&3 ØnëdãQdtg©M¬ê;($†" ~||ÒCÌœ]4@î ¯a%Ó; cA¢Æ Áz±~sS³ê†2ç8¸·èëñÀ G=ŠZ ˆBÃY0›H—zÐ|(<:á¤Ê•GàN¸š†SpQ…4Ö´˜òôë™EØ×\\še|Ý£ 8õPõ,ÀDÿ«%VUo”’ž."NÞ¹ÐÜì8>¯—œ²œêhU‰O)|w>žPR+¸‡žJÛ-³Xþ«A6¼föî*ÊX»Öaâ&ЭàNÀ]ëGܺ95;À/©¹—2\AŽG;óEØ×”(j¼€ú‰wÓθÆÚ[qT ÖgfSÂ9ÜÆ¢¾mà¹l¼£Tøä)Ý£Œ \gAÊIa’Ós26ʷȵéÛ–ª³gž/ßxv™ê»G”•„>&+дǙM‘Äx„€½‹É5;6~†E ¬éØe) RûÞÆb+V©ôÔ‰…Á>±6KI¹€J+r6¶cÑSUƒ“ÑQ¨—ßáèDYßIƒ…•ZynèÇ8ò¤ê†ß3”BúÓ:–Z…*’Ÿ©ÿz&óH†ŽUjÆï¢L¶®ÃúI¨'ìQãNjwñó·v%t,¢ Eœ›·Ià×ß¶~ÃuÞ‘‘s8ŽRm2ÊH)~#'Œ™•¥ÐË„‘—{b©9‡®8]º¥‚4%Ì©YÃIÓBnå—1Å@¦œîK%gÈsÎ{•|ç¨ÍâK/*H¿Å9Tÿ¸±[É, l}iþF¦1x«|‰TLƒØRÇøHí¼â"Ûù©ð…i´9|(™LÈšc* $Rl–x€*Zô±2‚dѯ—Šx— Î CG™6‰ÆÐµñ9‚“(jé§YÎL|ž‘ ç™ìÓz÷$éXÅì¦ùH@jÉøø†ÃÓÓYŸñaጜǧŽQ`äÂÛó4KuìW‹L𓍴L!l ÕÛ)Û5¬ªrrP‡ZQdW Y¬RèÌ ÞZƒ³šê÷âW±šž’È –Ÿ OÈž¨¥'zP–Û f[Ê‹Ó=T*¶wð ÷\@’€7N ßæbÔçc[i!T™¥ª^]¤=ª• Áä-`Àâ;Bƒ×/œQ‚ †”…©Ô6Ðùó"+Á¨$þò“‡‚v²ó{ÿ›»yàׇqô¾ ³MÉKÌäb0’E=8FkŠÑÅSšÎYÄêJê©Ó§bLÏ€ÈMìU±`O g•¤sTI8/Vm7½ BKw> endobj 214 0 obj << /D [212 0 R /XYZ 90 720 null] >> endobj 215 0 obj << /D [212 0 R /XYZ 90 358.202 null] >> endobj 216 0 obj << /D [212 0 R /XYZ 90 125.301 null] >> endobj 211 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F58 59 0 R /F31 46 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 220 0 obj << /Length 2382 /Filter /FlateDecode >> stream xÚXëã¶ÿ~ÅâP`åb­)ê (®EMÐ$hnÛ/I€r%z-¬Ž$ŸÏ-’¿½ó¢,ï*½¢ð‡Ãápø›¥n"ø©›"ºÉâ8,L~S¶o"á>¿QBmA`»øÓÛû÷‰ºQQXD…ºyØ-UÜ{.ùÓñ¨rp›;È8u÷$É’0Ë´xD±q´—.tÐX´G*8ØqdZ†ÿ(´æ z´?æTWç5gè4Œ /´;våT÷xÞÄÀ«–­ü? bwlØB0™?í{ž¤ƒÛ}+vO=‹²üRcŠÇ–ÿNȳ£˜¤jÑæº²?²z üyµ :wâqß9&°rÌv4ºay¢Åí“€c&l38[áñ à ™õ$bx»R%²<•æe g˜‘WRÅ {$Tµu;Qñ3î(ï ‚òûoh3R( â„;sÊY9Ð"#Ñ©¸ˆ þptq çTbn?lWñÌSíŽ$ï"9#O4”%¤7òŒ–&¸¾,òˆ»#]Nƒã 0­î5ôî?ÚáÞ뚉õ­³29ÐsµÅÈ0†mÂä6'HxœKcNâõÛG?Mõ À¶lÃ2ä„w†ê ™16©Æ·~kˆª03çÐKRü Ëıçbœ™À _ÍHè€JøbQiB¹]4 ã7èÛ®oÄÈŒU@`é8GNÌTPþg1†T‹14 dÂåÐ]^½õ«¤Ì^²âÞ€–ºOS—$·ÕÖÊZéhI¡¥”ð2\ÞorðU@*ødÛƒïÊbuOSC}Eæàù$T&•ÊÖwÓÐ7_ÐþEhdo >Ö³ %Â8ÑIðþÃÜÁÔÛö\²'ßÎSŠ ÁR“fM®ª'ª.¿¹×¿YËïp‡¿|÷Í—¨î¾=ã"ZbÂŒ€³Púîpp]õÕîÛþñÜÿ•nuÜræA’žÜ'|òß-›+š\&c~YƒÜ6†6‡ÌÎÂΓÍxq€«Ýá-ÙJ$DãD•üÕö­lDƒr¦_¤ /:˹¥£æ ¸”±Î-jàî¼ox[íZ6àw JÓ…2 ¥Û5;L#:å @¶uÒÙGi½ô5"žútøæâ"°|…ù®yt¿hA"Ï73‚´ <1³àï]S?Ke½R>úW½) {TèL£¢Eª§Pª¦q^L-|‘°ã0ˆ^7p¤K—nü¯dÜ«ž‹CsöM¸4ôä1¢¸Yã`Îc,®‰VèÚÁ÷þÒœw=«*H ÓÔ˜Ò“€Ý;ñ›Œ:Ÿ¹‘w­hDØ"kÆ étT9Q²_‹eÉ q¬èQ ïI_àÅ÷qÇFf¼,$O·¦âµR»>NªÕÅ,½èèqX-@ÂÒ`DR¡óà–¤.'žG$φ­¦©ããŒ'¨âÃÝü•H>£Œu/T‡Q˜Iïó¯jèÛY4_ˆ½ãÉ…7b6ÖŠB7–VÒ13È·¾úlâüÙ›¿^m¿óÅÅ~T±yËN!¦?=ñ™Gö¸—ÕùUNÔq¨³ë”ø-£$GgÓ«:_¢%ÊGHŒâ(Ô æx?; 5vŒ# r¶Èå¢Ý - 0FÌ`ÙœÁD¾–¬ìãïèÅËïz&-BHW*ÍÂ$ÖøÝKs‹O{"´]H­|Ý{¡ŠóÁÑË—·¿ùw¯è[Àñ‡ ¤äèÒ²áÕÓ5ü$h:À«Pàh^žEÇE¨M u è\ýÆwJ/µ]ˆ­œæ¥2éü×{tÑH=z>÷è1÷èßÓ½=| a“î>!’äˆù÷_ûuéù¿÷tZ€\ÍK‰AøBâÑÇlSµLûW5ÑZNô]çï Ç)+e[`ûª> endobj 217 0 obj << /Type /Annot /Border [0 0 0] /Rect [469.36 165.411 522 175.108] /Subtype /Link /A << /S /GoTo /D (Variable substitution) >> >> endobj 223 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 151.654 239.243 162.563] /Subtype /Link /A << /S /GoTo /D (Variable substitution) >> >> endobj 221 0 obj << /D [219 0 R /XYZ 90 720 null] >> endobj 222 0 obj << /D [219 0 R /XYZ 90 532.171 null] >> endobj 224 0 obj << /D [219 0 R /XYZ 90 137.846 null] >> endobj 218 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F72 4 0 R /F31 46 0 R /F58 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 228 0 obj << /Length 2680 /Filter /FlateDecode >> stream xÚÅkoܸñ{~…Û/Ѧ^V¤HJ Špé®rRý¨¬¥m5»’#i'iÿ{çA=­wC›!9K g†ófäYåYžÅQ$Rœå»'¡‡¾"ýl Ö£?^<ùãÏFžÉP¤a*Ï.®Æ(.6go‚È®Ö*56 ^\¹òº(ÝjE:ø¨pŒ‚‹Uû¶ª‹l»zwñ·'?]ôÇ¥ wâùe<®e$¤aʯèü¨?¤ø6”ÆÝ—ŶXÉ ÅÏ?¯ü$¡Ç’Ĥ¥F+Æùë«‹Ÿžƒl :ž4·+#ø'Ç[!`AK…aÿô§¨é)‘ÐÒítÀ³%JŒˆUÜíxÊȲró ¬*IuŸüp,Ò}ClxÌEÉ#]1C,m<;›ŠÇ²jyr“}tsÙd;?Ûæ¬,Êë†.k-ÓTXû;“LH†*b’ îez½‡«b]8êýÄúô;ÏÙD…eh…“Ž7ÁÇ¥RÄQwþ´¿WH^”Z8[OŽðTuSì²6Gµ¹áeUn?óÎŒ ð·õ8›¶†X„Âàg4ܪæ]tÒ]¶»Å³hº­%ÀÚ\öØcûtS°©yéuÚ9^^‘µ¶Yä*-ánx%Ûõ ©Ù2¬ðcÆÃ‚L<È„×a´$ä¿&¤¡Õ}ǼqL:¸O`[MlÚ³X´Û^¡—-7äœðj”f¥ÃIÝ;XŒ©Åõ²ÚT¨8í4&ï\ï‚ri#™Œì‘~B:ªývÃKI—^IÆ$ï  ëe— …OíÏøýëÑ;A%B'æx\èd•%£^À¶Ö!­I&Žöa¤/¾A –ÂÈoG¦ý°¡%™Eã=G‹lQb€*²ÇäÚôÑD&x÷‹jgÇ:hõÌ‹Xˆ™^WìTWpɱ f×®t5~À¶ÒxW&%05ŒÁ¿„è¹›6+s‡—)•W»0Yôra2µ‘ðP Šz°‘g‹®W afd€®gÑ5|^F¶þ™íŒ˜Œ˜ ØE lÈŸ6w^ˆNÀFg~fv”µXâì@®¨ƒ±fW P:G·õûØÓX;½:Xœ"¹ÀÌ3íÎÚÙw¥»ó ©Œ–Ò)ªÈRÎáqBäÀèk=¬]W˜¥,RQ!ó÷|Â}BÇœb¦æxûü"yÿä"„ÑkãϹªê…âŽó@¥íò«sdWòì¶®Z—3Ѱ¼ì<6Ì›{.@^{z(ín›e7®Dªz=~ƒŠünI“•*‰Fy ña_õd|ÕâYæÏŸˆƒŒKAö§B»”ö²I*ø´1c[;do³ÝUG‰0aú“¾Žµ ¯Œì?‹hÎFî7øuþ0¢7Huwc«GÀ,›YÇé¡VKj„ìû_Í2E±‰KÎõ0ˆôéCAîü æË¸Ýð0¶ò(mv§±Iݳ#4}ìî&ÉôÖZ¥Ëœ% ï¸÷Ö_íù"k˜p‡éømNàŒ‹XÃå¨=£¨FZo]Ö´ ²'ì2®ü&~þã 49Û¾.i€öq64”å÷ýÿ~\'¨ÙV×üF‚¤¼z½P'w¿=íÂ×mDüèÉ Ö¼ÅnQóáÍRj7᎚VKe¬àlº]’Ô& þâP™J2kÒ @¹5†²sï½zlü~…ßÖŽ'Ø A,½ÊL±qµÛøÝ oÊxÙ=ÿÑ™ƒ0«ÄW¯Ýf(e2zÄó¯ ”.™øÀK•2š>½ÉÖ_–[Éø ã)7&‰š½bÄñ½6LL 'Ù `O•×nÒÀ ~üòµ.9ô­B!eïå²Ë|s”Û_$Ú·ç¸W’‚W’³d|JµàEhD¾è­r[7xü²BÝÐ /¡#%àÏÀ¯Q?W]¾ßÂÃvÅï¦^üämñ'¤ÓÍð5øâ¼àˆÜ]în[´»çHßði#˜žfŸ›©™¦S“bÓ@оd7ŠÐÂà ¿öÛíàªy—Ûã‹×”^IŒò'÷}ᘠLl—Í©¥Ž&ßx’­ìÄd&HéÄg4XÅ`<ÏzÁÒ¡âv8N–]Ÿ:ì?yþîh´ïµü!8Èiû´­ñµŽn –oÏߢkiœGäÖ¶B¹|Boã…òm6”ß’öö·>âÒ|f !‡™=GÎË(•RxÅÁ;•vË©¾ï–Öé%ÎQ/iôkN×R=è%a«¸åpŽ×£(g(ÐD÷_©þ ácW endstream endobj 227 0 obj << /Type /Page /Contents 228 0 R /Resources 226 0 R /MediaBox [0 0 612 792] /Parent 225 0 R >> endobj 229 0 obj << /D [227 0 R /XYZ 90 720 null] >> endobj 226 0 obj << /Font << /F51 5 0 R /F54 16 0 R /F52 19 0 R /F58 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 232 0 obj << /Length 1828 /Filter /FlateDecode >> stream xÚ­XëoÛF ÿž¿Â@TÆ*E§·ìCº­k´+:ïËÒ=Ëg[«ž$çñß<òd)UfgDô‰Gòøãë$f.ü‰YêÎbßwÒ ™eå™Ë«_ÏS60؎׋³ó7¡˜ ×IÝTÌ롈Åjveý¸•»N5sÛ÷}Ë¿˜ÛAZïëFÑŠ\ÝÎÃÈ’U¦V¸XY ô®kç¶ç%BX~<¿^üzöó¢·"ô¼#f"Çq;£$p„_P 0yC&ßq}¨®n˜#ráahxмí¦äx (†ëšYFö„NìņãåÜNÁ?©Ï®*¾BaIzh%šª×ôÌæ^lme#3ð43ßmsXN¬-ïE‡#ñá·žÕÕ´°GÇ–¢ÅRv´K­œ¹§‰•;Š©þK¬ðÇže&|Çñ̆§éÄÊ6²ê%Ü»mÝrä½î¶¼€t´\;ŒÄ&ŽÞ: §/W“@ÅŽH<Ô²m'‘J$M ÛÅõË)¬´,qK›š:Qê± ØÖ~:Ö9Àµn½‚âs à+ZÜ·yµ1ÞR¼·ÓNßf‰¥ì"_6²y˜'åLÆeß‘9²¨öådì¡—ù4—Ån+I«x_ª"‰´0Ð7—ÔòŽ)­ØCȼ¤Ãu¤õ‘sNÔº,dõõ¨V’ßîdÆî­›R¾µ˜'¾uùú˜N©ªkŠUBÃCuM]ôgPµ"b]7¥Þzj.íw»ã!LT›˜ªÍêÐ,6ð4µ÷'å0‡úVÝË•ÊòÒœ›6ëwæì%i¯©! :Þœã½ãvãSˆ,&›Ÿ—8‘ &ÏMSëK½ßqaèê:¢()æðÿräQÓkãhÙÕMËÀ/œ(zî8ð&¼©y`4o=‰Âx€ÃŠ L­×RgðW»QkÕ¨*SV æ2>5tßúåÃ&ò7êžÖVµ“ARr­éòºB@Œ#‚𹎸9eê `ù^z1zºt²é†ð}í…e“'ãgZôݵ¨÷žªøÒ`âæß #¡oÍ‘•·ô”ôX«;$`¾—å®Pwv"<ë“*Õ r‚ë-ÝVvDµuÉR³º,¡±ì‚À¬¿²ŽºéØ÷…ä5u¿kTÛØÚvwõI2y(ª²èãûü/f‰“FQÀõ&†´=ß =Þuóæ¹dä– –ÑôRmòªêâHB”¶‰¼é¡\ÖEo˜ë‘Qquóâ Â'µTu÷?ª»´ÿ¼v¾ÌܱFùŒã3õSw3êNøó0Í‚ØqcŸu“êu]àÀµbÙ,ª3{eËd]±¼šÊ:’Ùx0!ÙÇ"O7¼8tX‚0pÂ8%u~{#Ïz×a¥ä ©s_@‡ºZ ^Û©"ÎKáñ7†ß·ª€–D®¹G( ³ f ÔZzI—`x‡Î7 ÐKáJý@ë+¾°­ˆÉ- é¿êœ<Ž|‡Ö¦Å>V­ïå°²‚äÈ 䯾ÒѦ‰lÀo²S•.øÃé'è†fhÌhS‚tyÞ÷i:˜Ê'‹¯¡ BV™Ûíñúëà÷š€®-нèòi/ßÊq î¶9OÁ¹™¶d3Òñ²z‰«Å[3Ö…¡êbrn>L2x¹†Zºì«—‹·?œïÛæ|™Wš(j°ìð³jêˆèò$ YœGâÞa ÙŒßThh¿E÷«*çNLïtçO'z"Å|!¼Þ·¼ !¢î~˜ÃÐ2Þ“­a(¦;æÉ)kÌ0ŒKõÁÒ†¡ÇàK ¤e£O4‹¨MN»[óåaÔæ¡¡ÁÀÞÑš¾iÉÁ,g`¿krÎe=Íì½"zõÍ€ÞŽ†öÀ2³¬, }¢»±ºŸå&oñRi"¯„d¤6»šÊ*m!´ul̺ÙTÁœa°Lå)êm@´TP$àoó¦®JÆ’"¡õƒXÏy¸Ce{p€ñ ¬4P8áŒØx#ß ftR”Á6s¥¨tÒ”ñUñ0üN6ø¤ ·vTÿ¡È\5µßïñ:¢½va>¡þ(øÓ endstream endobj 231 0 obj << /Type /Page /Contents 232 0 R /Resources 230 0 R /MediaBox [0 0 612 792] /Parent 225 0 R >> endobj 233 0 obj << /D [231 0 R /XYZ 90 720 null] >> endobj 234 0 obj << /D [231 0 R /XYZ 90 224.677 null] >> endobj 230 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F58 59 0 R /F31 46 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 237 0 obj << /Length 1728 /Filter /FlateDecode >> stream xÚ½XëÜD ÿ~Å š…K.“w*RAT…¨‚ýF‘:›Ìn†ËcI²÷à¯Ç{rÉ5G‹ÕI7/í±ý³þÄ&÷7izy”mŠæÂçÝ› Á3ÜÅw»‹«×±ØßËý\lv‡9‹]¹ùÍ ³­äq’;ßT{Ô­Úºa9·Ž¡³Ûf¡s»^Ëzûûî§‹v“¸8>¢R| Pâ/Êà0Þ$Yä‰0"¥Þù"EaO•—Ä1°6Tº%ÇŠu~?v/h Dª.iÑh”DÕlƒÌ9×£>ÕŠjÝÞ0I±u…3ê­pºö’TXªë²®ˆ½\dÿMßCß5Ÿ qÑPç«ã¨?ƒr¥îU~ø¸~£.ÿ­nùÿ®ÛDŒ§µ>«ñô±ízõ9D² †JÕ5í]ÓȶôÇÆMàR2/ɺº«4ZÃÑ„ÕI²®h fîÞ1 rÛ©sH´@ˆo¡“;=V4{‹9âþÛ½qk}ƒ÷©·ºïÚ†æ#ÜnãÄ‘UöäØÒ̘¬ó(zäµ ÷ü„ãæG D€¤ƒÂ©E[Ôs=‚ø~.á$Žl=xc.—vî*¸¢ ¼\«J{šºˆZ`„á(‰ºÖÃHt>KÚ»£Qc¬¬B=ìgÊ]ݵ9JD#CO€ãÍ3ï´qjŽ·\ÐOÑBª—#J•q×­±yO;r¤|wÒµuYîP£Š·u‘8?w#s+{çugf ù"[myœ®ð„,ZŸyið÷xî£}Œ!¬çÔIÂS:´MA6èöˆÓÄ\'‹jA¥¿žj=®a*N,,Õ—ƒŒ4É¿01Á±Ùw5m ª ³¡.ÆásòSß{ÙÐâûƒâ“_ÔAõª-;5 ¼8NùѤNCñx–5ÜÞ“óg¹ñ5 -ŠÐQ÷²zu‰+P¤£].\0“&P§?aSLöº•&QŠp– aaà6§œÃ˜¥®¢–&5\ŒJ‘ÉG°DGÖj%²ém ¤]rò„*bÜ‹RÉò±8œU—i6D?.2§PÃÀ\0RMüÂ⎂ٖ†»CአôIa´™—æ9d˜Ð³ ƒá¥yAîE ¸@|¸”ÔõçÙ8ع¦ãf¬:N©Dò± »ÌÙÄÖÜxVèxyF@>ß|KãW(ïí«Ý›dŒòŸåû%qzÓÔál*.ÛÎmäXT´2S5Ø£±BWÙÌ<´Ðñ$GHUíõ’•<ªë¹…®qÅñ¢<†™ˆœ ñ”=üгÕô£*^4•ÉÄhLICu£§¤YÒÅJÏ+|Ž7Å—¦K†È³ íøFNp°YÃØ›`Æù“x^vO4R÷'ÄÚ™bñÌË[äÏ©´Ù6¨V+ …‹W5:ʽ»žƒï1íc‡¬•»E‘äêJì,JQfkv‚)^FYµÅðÀ79Ã#™¤á$ îšä0ëiÂÇâðr³`… ;'Äl¶Z°€À¯ypR½Xë‹a“¿„Jó@oYgÑÈþ†¦½.nG{Yºå¹TO9»k>âtqj@ÓŽWU×(qe`OÚŽ ¼}í‡AÞbh[À‰5¬¸Q`˜€eóî0S[shÁ=™ œÇ™i·LjÅ䚉Ë®dv'’¿¶ÜÞ¯Uú0ò=?œŠøìéÆÊ+¯É ÖýÌ^xqɰ `;Ìåg] ˆ[‘Fž\— / “IœÅ@Éßv«"ÌtEˆ‘Õ¾ßϼLL=Ï n왾ª=ÃÎt(>´ê¦Å0Ÿº{Ê.Øbù>õ2þÔµÂÔòxÖ‰ã–éüyç ‹¶ØòãÂtl0"þa¿6me‹ k0TTx6¶}†óÉ™%«FB!%CÎ,L_‹‡džk:L9˜LQ ͇ ep“©#l@ e¡¥çy%O•üKRšÇ/k2‘n¹K6L0¥ ´Ù@Sễ ³T]"0]‹¹ËW& â¢Q²…ô5v­fðBož…{2¯ÖX+ÖnOÝXwèHÝÆîèîVLó)W•ž<Ð *…'Œeæº*îH¢Â/?ËsP#ks  *Lº.ݵ§,NàfËß/°ZÅF{Y:a[ˆ5,¤žÈÄ âÏóƒÏå4˜²A­÷ŸÀØ)(»‹~sPlªgøûÄ}ˆþ¬LBÃÕÓ‘Ÿ:³„g>ûcX è endstream endobj 236 0 obj << /Type /Page /Contents 237 0 R /Resources 235 0 R /MediaBox [0 0 612 792] /Parent 225 0 R >> endobj 238 0 obj << /D [236 0 R /XYZ 90 720 null] >> endobj 235 0 obj << /Font << /F51 5 0 R /F60 10 0 R /F52 19 0 R /F31 46 0 R /F55 60 0 R >> /ProcSet [ /PDF /Text ] >> endobj 241 0 obj << /Length 2628 /Filter /FlateDecode >> stream xÚYKã8¾÷¯¨=tÒ–ŸñÜfv{½‡½tÍa°³•­$BÙV`ٕο_¾d;©fP@Y¢(‰¢È¤¢žbøSOUüT¦é®ÊöOu÷)êë'%­-0lW¿>úòÏ\=©xWÅ•zz>¬—xnžþýý¤Ï£6Û4M£ìçÍ6ËòèÆÛcoû#“5Ž­{Ñ-¶³È_ýh:¦×®ÿ#VÙqôh]¿Ùª".²(­6ÿ{þ÷§¯Ï³xy’ü‰üÈñîeò¤Ê]¢òLPì³J3>@¶ÙæEr#r™“Èð™E†ö,2´ïEAïšLªÊÞæùd=Ìͳ¨Þ$e4k <{¾l¶0䦑û/“m–¸ü{™£5Â}p2ý<ãÌ5º£O¼2Ÿ§ÚÑ0áªqXVÊ£ë&ÙÃöåW)ÈÏâ›ÇF;¾¿~£"hªhDú…&¯;V*<Û¥Y‘EìwY"+êYãÿ2½‚rA0oÃbùô©@Ÿ‰ØÝ7¾L`׆N ÍÑñwò†ºGU_¹³\ 4í-i”µ ³ñ­°Oum¼?Lm{ÝìÓè3÷ U„7Ä<'ç~ÃæV„N¿"£PÏt¯F×ÔO£‹O7:V|¦YÿÛ4Ž#꽂ž©Á²ù™®ÜnLc˜ÄPb¸–º[ḜôÈ­Erè˜g:­©eT÷Íí¤‘qºx ^l »µóntbE¾ÜW‘®qúÉQÏ{“3Ö¬Šã§vô;ÀŽJE¿oöo C½1 ·h]øÂ‘ÁN¸-²Bk‘5Ck´-ãº]é…5À ·}õKkx ÖÇÍä¦wóË»“ÉE† Iø´€~wnÍhèV ?±7™7Äsç ž;å#ƒœ;Íy7 ¬, z`?â^(M ÔÖ“ Ñl9c­§Àç.6tƒânºe€v= žÍg¦œòë6ÌÔê9 \N¦g–ñd)Žž»ë%8þ²ÀaˆÆ #‹ÁBge°¦!˜Aˆ©² d.vY%(û5° ÖôänÀßÉH¡h”o´Êdo uÎ iq{a×u­­x«¼À«§ÑuA o nÈÞ];£ ðÍ™3; ÌÛ–Ž°Ï°BÚáŠZÎLÁ¿|,Z·™–E|Tç½e+*ö{3†;7ûÔ[¹c2ÊNk´öU$Äî‚<4WsŒ²3ÊËŽ€€ƒšeØÇh‚'k†G6lp›Y\1€` ¿8 «ÑÈIX 8žqAêLÍàç¥ð´¥Š¾»ÎŒ¶32 wïXS@¨[m»°8Þºl#2±—a ®àêÑŽƒÁ©IUD;sóþØÖŽb©IU²72O šm™ö±7»€†=ŠŠ\`“SÛðè DØi,l’t0D 8¤‰d+æÖšƒlcúF¥v¿ í— 5x„ ÷P|œÓ€æLA9Þ –ïÅOPa¸ÊÔáÙc`wàïl9 :k:+‡éα!á¦ŠŽœ´Â HƒçsË.7 R…S‹`Aà×Hìiݹur<æÎ›\üß )É«è7?‰4À·D•R8Ä”ƒ…,U€i¢±«pJ£#ª‚S#&,~E+Õœ/,¸Š©ÇŸœ‹• (°…P¬{&-A Çu#­7B AÀĶzøF¿S˜ê}˜1EBÔ¼%¬H÷'=rÑ J)KŠ×¶2c̸¨EOãÖÍO¶}ÝNÓXÿê?Î?âÏY’ÜÌ!džüÜIÓuq)]¿lÊJu–Üñ¯Tp Wp¿ù¹^îÍxÜtþK¥F®l¯Ø¡dØ€%×µ%m¹LÀ" x3¼Ùš¦(‚€ÿ|ûŽ®Ï£k9<öZ¹*ôäwéNÞÉÙ…;º…Ü ¹>òƒûÚ‹5²Iˆ¬¢l­¢"Ýå >cÐdÒæ&WÑGÍã]’&Ê /+·i¸ö$øžÜLºœ¬$=ÔÛl]X…cS¼ G(ÍK‹ýPNFn32ó Èmh¤ÌÓGA¨CÐûACHÓjéW7ŠC‡kÅ=Öut8èe±ü)AJhŠ5Rëm+¼õÁôGNOHŠ4¼Ì_gtïÃJì›wÂá–.{~q`LÃŽ«î¤7 S¢/¬|³ÉúfU îU¦áj¿˜±þÅCL|`e²+÷eàæ@'o~Nb–‹EPI<‚QòÃD(+±Ý¹i3­€°I÷›Äå..îjߢ¨ÉCüÿSÚ, lxfÞ~5ð™ÁòÓR2a@î5'ý©T40 Gdåepeã´4!„ÈGð .Ðiïž¿\‚à %AÂG°ƒG˜©K©ò†&F3†é7Є;`ò¢½ O}cä š?^^f·#±àh`¶%`Ï·^Ô2ɼz^ì"°Oòœ¨ Éæ2‰!K|`Ê A5 Ÿ†ÃŠ•8ðD.‡Ð`œÜ’"ñ¨\üøöŸé™kGȇÉI–:4¡³+5G&ÎN©Ù›02/&<¯¨Ü¢«U*T¬Ip’¾—”ûÚ7¾7‹òÈùöp¾™,@%7µtÁ³ñ€ãìâòÎY0zqM·º‡º!Ai93tØl °l72… \ž†4>uáåK7&IYU¬—Ë$IÂÙ·A ÇH©¸¥•ܳ²Y´VÐ]Yi{?‚õáƒÍ6Ë2NòÑjø=b±#ù‰`µØlo·l!|\üÌw’ª'¸‡¢ ×}ÈSö€K€¡EÊBtW\f˦™ª<&WÄ…ÔçÏìŽy’ÏÄä1}DÌ„(çNÀ.1òÞ }Ýú©Ï¶'*ÒÂD¯ú~1¼¦;’ƒLývy0»¬«98ã·PKM?¶¢0ïÅ ÇeÞ½½nE;Å® ?K|Õs« ð¼FÞ›\¼——ÞÓ`äØÐK×8X*ªÒ¸”\†BŸ,Á$fŸ¼°XYp0-Tèø3Åh€ÊÏkø‚,û» J·c(ûnLØDDêx‘éqÉ|ÖÇL»þÖÔ„ÌÛ.–xá§V~­‚ Õ\¨ÄVö8¿^bêÀOÜ_1xa‘’Žƒ[Ã(‰?pý>äG² endstream endobj 240 0 obj << /Type /Page /Contents 241 0 R /Resources 239 0 R /MediaBox [0 0 612 792] /Parent 225 0 R >> endobj 242 0 obj << /D [240 0 R /XYZ 90 720 null] >> endobj 168 0 obj << /D [240 0 R /XYZ 90 720 null] >> endobj 243 0 obj << /D [240 0 R /XYZ 90 629.348 null] >> endobj 244 0 obj << /D [240 0 R /XYZ 90 346.088 null] >> endobj 239 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F54 16 0 R /F52 19 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 247 0 obj << /Length 2872 /Filter /FlateDecode >> stream xÚ…Y[oãº~ß_‘·uzbE÷ËhOÑN_ ôä­-°ŒDÛDdÑ¥Äúã;7ê+]ˆÉ!9$‡Ão¾¡¢»þ¢»*¼+’$¨Òò®> Eúò%’Ò:ì=~{úòø=‹î¢0¨Â*º{:,U<5wÿÚ¥áý>®²¼Úýõ »£éôý>IÒÝkŒ¿Éîé¾Lvã`{£Úûÿ<ýýËßž¦é²8þÉz°ÇO…)´¦wy™Q’òªžNš§¢Ýá>Úm§ãÕÙ7wz8öv¼ˆØ8'5°d8éw–ÕªcÑ3l¸ØÉ6A#c,KÜ :lÏ2ÅõÖ¸a=ÿɺ¡Sgíç‡evh¥»}Ä»ÚGIe¼)÷î}ÆÙ£Ý¿Ã(mqX\Ä ÷å>.qIØô€•⥕Š*s4+izÔCý¨¯ÛNz¯lš—A¾÷×à~ŸÆ)Õ8ž¢¶çKÆô N2·:۱õ \Ç}R}‰éøwe1möÝj®z+{TüÓÚîèmREYŠQ"^5+ø²œ¬ Ugº#*EÚv‘EÙî÷AzµÎrdzV|ðÐl,yÇÝØ‘+#¬Ó¡?‰ZÚ7Íú¹ÔßGYQ„GíXÄ[D¡,UÜF^h§áz‹¦s¦AóTÅ®žnÖÞNºãR£ÑŽì™ëÞ­±LIƒ[…‡ö³†Ù¼5jR¢Ý›} *nì¥Ä–ÁÒj˜âöÌù†r…ÿÞeÞ`µ!Þ›-Š½Ù¢˜NÝ,)v¿w,º¨~0õتžëfà_\Qì+ŠpQˆÛ)¿Jÿ“¶W¹!4Ìòïx¡«Ü¨AÎØilsiERÛ‹Ñ2$üªyÉ[§µ¼Û. Óe΂¼*–U”+ **Á”[\ÍK§SÁé;{Ö.½=öêìüP<?’Åx@‘Äy¥±¿û¿lÁC”Yî{Æm¨ƒ,úüyS X#+ßǽ“õy£¶u¼`#p˜”!\ýèÆ¶¦. $D­˜vcúdêãt=Û¡ÿ¥)àQrÔòO}нîj©žá€ÀkFˆgˆÃY°ö"ÆsNÒÎ5hLXiûw®pëÝÃÖ†ÞÌpB£Rô–n>É@ÉØ;Ü$&@#Îa¼‹àÀéüaà\£åbg.œµ–ÓO(¸ o¼6¸ž-ƒ{D‡ * iˆ,‹ùN¾ä;ùêæ+ü¯ t°á} r^@34EV‰•¡À,´òܰäé-ÎÛžˆa¹“µÒ-C´E?˳™:ó<5›óÅÏ2,V ´OñóÔ¥ŸºÚ©aÀW DàiÇ5ø|É电4gÓÉéÕÀ‰L2s (+îÅ´¯Gæ)T’/ˆ1ï<¹ºòfF  ÓN = æóÍlÖù˜r>¡j[‹nñæ~e$N"€û*ÏSb ¸Ið·#Ò5+]«bô}hBr¼¥5 ²"óðþ믪Yå¢ –¬jcž4(Â)¨]\ŠO&H}§³mô· M°­,)–½~ªÊ"¨±%Â$ðj|bIñ!³\GÐåÎú®JFãrñ÷Ò£©}&Éoß8íìÝ ž8(õé5äû’¸ª­X"ÈöùCØ÷{o`xúª€íê‡/OJ¨#ó~·ÅèT÷.tMÈÓ`!Í¥õqtý㟟qóYœ1ñR¿ô×»c0£o½E'ÇZÿÍt.‚™¾Ìa‹=äQP€ˆÉƒ,uy“àXùÈK ¬žŸ{Ài6$ ð-ÆãTÉ®kÇV?<  è6²¢VòRšÊ;!J;Q³ôB¸\ÜK~£þôÆÉ°rtȃx_44 %ýÀ¦7Ó6µÂ„k¸c`’á6¤G¾ÊL_)ð€Z IÒ†¡Ëp{¢s_1Ê‚m~|ò YdéJõX?¦˜>€¬c†¬û·wÞÜÄÍ(0`$凗Ïý%É¡8m»V#XI„3baù$ÃD¥ü°ŸÜ<Ä’l'žUÌŸŒäkUœ$óÇ,ßãªE%F_GTr{ÐÓKË2ã£G@«ËõµþG'1˜ Dƒ3Ó€9¦o‘˜œ2ð^„S˜‰[AΓ™e,¼zúL‡³Ñ†Ô[-ÿrJ JŽzð¦Õrë`jM0÷jæïM7ßà ûqRøÞ~äÚzNí#~7+ |ýAŸõU¡³§ô=ÌÆ²ª4Nø…‰ÅôÌÌ  5Jó¥õĦQB"N<ëCÑtdXY G¦–Ø~xø$ùï5ßz#X V”€}â¹³P ê Ñ(2gM¢|2=! VͰ%aÒ|éw=@Ñ»@>Xļ5Z6¶£Ï9yù17‘OÊÿï.Ó endstream endobj 246 0 obj << /Type /Page /Contents 247 0 R /Resources 245 0 R /MediaBox [0 0 612 792] /Parent 225 0 R >> endobj 248 0 obj << /D [246 0 R /XYZ 90 720 null] >> endobj 249 0 obj << /D [246 0 R /XYZ 90 575.737 null] >> endobj 245 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F72 4 0 R /F31 46 0 R /F58 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 252 0 obj << /Length 2919 /Filter /FlateDecode >> stream xÚ­YYܸ~÷¯è}²&qkDÝ2àŽ“…½€á$;€vX¶Äîæ¶Ž^3žŸº¨Våã!60¢Š%²ªXõU[mø¯6E°É¢È/â|S6Ï¡žž)ma»àøÇݳÛµQ_…ÚÜí—KÜU›_¼7G}M³¢È‹_Þlã8ñþi{hm{`²æÇ¡îvºÆqì Ãh¦—]ûk âÃÔëÑvíÍV¥A{±ºùíî§gÿº›ÅKÂðò#Ç·HóØWQÌ èö&̽LJ£éâG…ww“Ç^©„kp~§G~vÀQâûnW›æ¾ÞãM˜yÝÄS%,J܃™2 Sº3éš`áR°0ý4‰A’«¶íix5ÚêQ˜¯´H?S‰ãµ­îFy²š´6ƒ“£Äm}\j³âÈÒb³U‘‹Ðïö7Û°ÈE¿°(<~æ¨ê€-öú`È\#O=غfæÞ4NÜãÃ4±¬¬òØ …vðvªmÉ<¤¥,v"|p䙪crÛL8ó§ +<åU8ò©›‡lªø¡ÛŠã, ÏÐãı‡|õ¡ëíxløõgõÀ~0+·°Ie‡rƒ«Ç9ËΘbœ÷NÞuUÙË,ž ~‚aa& “™€:€ˆµpm^°Ö]k˜±Ñâ>ø¸!†êäó3Ù×”vÿ(û¯™õYlÉüÐ Mõhϵ¾;>€¹˜M€k•Àª?©|:v… ™C5R›Ü/Ò4æ°ös2u–‹È~éÜK…€[!D6@Mïl«ûÇc7Œ/Lá5ÓmÝ•º¾5us»Ã3JÂÄûëßø)sH_AŽm’ùAÁr™_¨¥Hx¨)XºÆAB¶B#æ°B*nŠÏß× L¨q:xz"ìŠPyà«\9þç²qÇû–]ß9ﮭȵqžäq130ï×ÅŠR?Uê‰X_ Ìf³ ÏáÀ‹HÁ[ ž¨ˆý$H¯£r¡ ­ ús@p4]{0 àÜ`LÌ•Æ-(ÂL™8}®Ö°K.V]â½Ã0Â1qŒãGÝ~D6þ —ÏÏš¡à&I<ÀíÁ}˳½9Lµî×`ñw°A”æ€=>}žæ‚ÖÈï» Žû®Æ£`‘€> ¦d‘ßä‘÷sêÝ[¦Ü“L½Õ@Á° DïkœÉ¼ýÔ‹‰€m¯K[ÛÑY(>Q‚æ]x–Y ýKºzŽÉÀåÔÒù<Ô‚³Ê;`²ôFÍY,@°5ÊÇdÌ"M7ñj¦ÂÁßíHkXæGí¦¾t.‰$ÊQðŒîçïû®çA£GÁî«/"Ƹ 1]½\;+ \£Ò™®Àê]½ SI®'<‡7g˜pí§ºæ%\8Ñ©£-p³$ämAW™¾›³{Û ë¨¯æÎ0¼Ö¸T‡o¤1>±Ü‘òþ˜ÚÓ.Ù^ŽzàùÀ×È‚¶E¨'¨–% †á\®K5õ\#àN,ˆò@vpðG¦’±Ü›ö`[Qd5Qþh ÓÐÛM¶®pyÓ™IN\ÌœP$0ƒF!™TÛ“TK8±ŽXŒY:×y·cs^ê0ÄáŒU/ ×WŒý8Ïæïuÿ¥EãÄÏU¾À< ½÷sU‡*P˜‹æ.Až2œuŽÈéɤa EzV\ÛÀÆØ{9#(uOá ÃýxÞ.òÇãQndlÏC(bN<ší–b5v%%ĉø¨¶4Õ (TÌwZóì=‚œðiô}r|7Ÿ4bö‹úc"à€'Ø r‰; Ôš§åÌ“ÁÒãÀï‹;ö–Q³æIÊ0ךq(õÙ)‚SIô]’^! ˜÷#b°ÙñKY[ ê`æ²…áá‚™j |Ÿ-ç:±Â¢[% 'ü·Bü‰¡MÂE÷ÕOh`ž>? uÇ_³$ÌŽuZ[~ÉÊT•ÀLczGž8Yˆ§@Í™ ž›T­®è°¨]CWL‡áœ‰ªÏb_ÝkîBIÆÀ¹e™òƒh® ‚1ß·¼°ssâ7)„I”7ÔE¼¸qhªÖ…²Û÷ !U©gÈjN_@.t¸Ç-–-˜iª©¤£')’à „3.øÝš Jä'_PŒmÊÅ2È™§¾ ®›ÑÕ#°è¼kݾˠq¶¬[³Ô3césöÎ3ÅSõÀ|Î'K<ˆ‚AH\¬“,»Uœk.°“a³*’sÞ “#÷yPJdHLü"*>+(ñ’m57C,1ÓajÁ1ôÞ¦²”á¡úç#å±fFx‡jÁÈH¡»˜Ÿ4÷D¸¾–¡"C¹´G tËnêeÊÔ*¤µX³ÔúQ ’¯^^ …ì„L‚ͦåW]–fàüR1…ê'´ÛJ³Ò’PÔ4z¨œúaÆnd½Ô`¤D¬¤Nš÷ëáUÚa°»ZDã0B˜³‡cý¸‚÷ç^C›\j©¨Ü•4Šï¤ÚCÌ%è|;FuÐ'ÄÅGgÕæåW;ÉŒ·Ãji¥k¿®ë·Pýlú{p¸¯ô’Gª¡ò¼á¬ÇŠ»WXX'^ÿʶ{n,ÁA^³ÚÐ⥗nýÈhf§‡Þy… ×­öú-ŽiàáÓ$î=ÿ¾“Å.qÃè¨/áÍ”Z,1—Û@.LºI’®,ΩpÎ,_sÑp.‘†ô¡ãc†r:K²ëSv?g¬]3¼– Ôyòk‘ªÆ¶ÐóRqÜF—ßnˆ÷ØM56TX;C1a„h>™¾´ÔßÂÔKO\]ã øDëÀàäz¨ÕË„~⪠Å¢°ÄW.²°§%dâ  I°hrâ"¢k4 Î7Ö8®í™G|õînæì×øW„Å6½¦zd"ÿP‰S“[ò‰ŒÔYî¼¶ï͘ͷi;ò§(¾(r‰GßýÒ÷çüS^l @Š?ãýò[°©€ ;øQ‘oˆ©£G ª7??ûÿÔ·l—ŠÄÏÓl“C¸¨ðª_ EUáPNA·”â;Èx«J™)Å}È9ãÈ“ÚèÕÔœ!êV*×*ÉÂsßB+±p~ t t-iáýàÔþ­ê¹— endstream endobj 251 0 obj << /Type /Page /Contents 252 0 R /Resources 250 0 R /MediaBox [0 0 612 792] /Parent 256 0 R >> endobj 253 0 obj << /D [251 0 R /XYZ 90 720 null] >> endobj 250 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F31 46 0 R /F4 254 0 R /F54 16 0 R /F2 255 0 R >> /ProcSet [ /PDF /Text ] >> endobj 259 0 obj << /Length 2333 /Filter /FlateDecode >> stream xÚ­Y[oä¶~ß_1}Z¹ØÑŠºÏ¾mÜm&@b (Ú¡%Î k]¦¢´îA{Ï’Æ–›´ ÉÃCòÜøCYí"øS»C´+’$<¤å®jßEB}z§¤·†ýŠã«‡w¿ÉÔNEá!:¨ÝÃq½ÅC½ûkÆwûøå‡àþhº“íÌÝ>IÒàKŒm<Ü•I0ý`us÷÷‡?¾ûúa>.‹ãŸ‘9~F ¥0›îò2 U’²T>›ä*Ë ÕO¶;q_sóãhëë{î»qУ9]qt®wqô“Lû©©¹úGýØ\yTõØýPÛV3ñÙŽgîÉ.u…ã§é"[ñÚÆVW4MˆFÙí+±WI¨2Öá/8¤I6 “&yÐõ#wjÓ<û‹Tz§‚Æ8Ož:Ú†‡ú8𻳒88k}ÁÙhÔO4êd!7‹€«ÀõÂ~Ö"ÍO,©=ú Ùð™ÎÜHšF¢£b%½^*g}aãàÙHø‰Ciiz0Ü'Ä…H>ÙBŸ´íà$ˆ¥³D¥®*[6cÓ{ËÇQ˜¨‚¥º?ê“p‰h¦¹8îŽ=·0TAߊ4æ_ãÍÏŶ4¡hƨ4ìÜ>“ ±‡^$âÀ ‘Ý âîÓ4“Ð¦Ý ŒmN?±r“3ƒ{ÿf‰©ËÕÎ vNdqÌ‹–Œ‘ÅÝ-j1B6ü´ÏUXiŸDaQˆKªg9œx—æ85r·¾ߘΙ›Ëøãi¶D×U?˜÷Ìqsy·ÏKAh¸°µeÀJ#veÖÎÇJ(Š¥7©nª¾ýîáëßÀâC|…GTPÝe pò.‹Ô‰Ï À6 GCqG îF™î™÷$5#œá)Ú¸ðW(¢2˜/ËÊàG¦^ ¬ñÐÁŽÂ©¹y¶M=ˇ0ždŸÌÖ%½Få9˜ßnY‚1OrEÑs ÖȪCË Ñ„=ôÁº'î!:0¤5zŠLtÛ^XùQ“¡€ä®n4-÷×Ãæ)g&ûks«\ÓPE3 2áyK›*¹œß1ÆA’æ1™'ÉâCî[.ÖIÃü‘ÇÁ= g¢˜¤Èf17. *ˆ—P%˜tÝÚÎR™d{Š ˜óÎq3‚¦FŽ3 æŸ$Ç£‘7ŒAÝ FøuŽ>¿ÛK¹:,@JrþàãÅõG†|à°n+%LnäGÔÌ©R°÷,¥ÎÜ—"†}ZMâ=À¶Fåíã4 ]sãÕàåÃeò¢‡ÑVS£³jˆÐP'‡¾e²ãŒ ½Òž憫ˊ ¾ÖL°Q;I (“ÜDÕô¡öŒ< ¬Œ2-Í HMIÂG*) beJ\=·5Ôˆe|†ZóŒ‚á‚ÉÉ‚#ù€ö%@Ï·¼TP…Íb8ˆ 4Ö3`„ ±a¨0ò¯_©\="g‘/ Ztž[0™×Üÿއßã‘ßý Ö¨uME +õKË?¸7¾üƒ®¨ =x°£ŒÊ£DöAùžtž/ßµ'*8‡a»„-âÆÁªXç+Ë}2û¶žƒñ•€ÏÄŒÈß™73úÚ²P60êGÞ6XäG¾‚žm |\×~ °j¸ú,(ï´ªnH¦<Í Ól‘²?OôÇ%9ÀpVȧ!\[ÿc¢‚^ŽÙˆ›9¨±fî$[Ï•¹™*|€r¹MaÈf/Ó@r?Îm žúh¥>çÑ÷0s‚bÞ—Ø)üK`rl¦uXûÂßß @!žhÍxƨ‚Kèïóè¦Gf·Ñ ò[ˆ®â0Ï2Ÿ=>cH”t·÷p5Û ¡ °²Œ°…Å&\'bã‘ û3Œ¡3¼^@Ç¢}Ï‘¡»“aâh[®0j´l¿”B0<©…·ßÀ9¨Sš7lê_WÂËýAo­=È}*©i²€-ÅËñ¿L.û,ωÎÈsƯÓþ5vž¦"’Ý¿ôá^<³‡27Žÿ«Ó‘è¦V¨$Jº.8‘ žèÁ…SÝPx깜MWš¦©Ï/‰Ä¯L}d¤>Œ$›yÝ2[/õåp¸áY¬Ó<’OÙßD„¶âdÇÔþ5Ûç¯<ò2#Kma”®à¢’u'Áò›^84ŸOËèçK¤Î'+° S½•7i0{¥Z‰± søÍÂäú³|,K–dá6¾xø´U÷/íØ¯s̯ ÷Ë­R\æ©xÉJJ-ñ}’æ)u0ZBÕöš yÙλlI´0wSû x¨ìe. E<“ x)¹£[Â'•íuèm$(´Wß”¯eCôÆØ{î Õ/¹Þåÿgw̾øé-Z쎤9#Ž œ§2 ôý‡içÄsf®Ñ1°ãHàCcž˜æ›3´ /æ×øjû3œlVâ ¸~û|[Qe.¹—^ÎY$Ÿp¢h~:ÂGÊ…†’/")"uS›#ýˆ¬ìçZûHy]­YOßîÌH…o´¼b©Tüu=ú½©¦ÁY~åãk$é–¤…#Dí ¤ð³X–gÑ‚:È#å]–‚k[ÿ6GòÎÏ5 VŸ~p_5ïÞX¬ª€>F =ÍÁDû-^ôÀØñÇ„+Qp\CߥÄÉÁzý1F×·õÏê-ø&RÎßÒøcÞjoiûi”ê©÷‡5ƒ³Ì$/˜Î_fíÁñ¾W’îÇþc#þËâ?YÖ…> endstream endobj 258 0 obj << /Type /Page /Contents 259 0 R /Resources 257 0 R /MediaBox [0 0 612 792] /Parent 256 0 R >> endobj 260 0 obj << /D [258 0 R /XYZ 90 720 null] >> endobj 261 0 obj << /D [258 0 R /XYZ 90 423.23 null] >> endobj 257 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F31 46 0 R /F58 59 0 R /F54 16 0 R /F72 4 0 R /F60 10 0 R >> /ProcSet [ /PDF /Text ] >> endobj 264 0 obj << /Length 3016 /Filter /FlateDecode >> stream xÚ•Zmã¶þ~¿bûédà¬H¢^ó-¹ö+ @ö€Mrm­-¬,9’|{äÇwž™¡^¼rsÅ~ 5$‡äpæ™oxÐ_xWw™1~çw»Ó›@©OoBímiÂv6ãûû7ß|H»0ð‹ ïîç,î÷wÿòÞíy(»ÍÖãÅßn¶qœx-ûêÐTÍAÈVšCÝ>ØýØë_ú¡< }×6¿a|¸tv¨Úf³ Ó ½Ølþ}ÿ÷7»—DÑŸœ3^] ‹îÂØ7qéÒ<öCËb?Ùl“4ò~¤=ÛØMèäèYâ»–:‘·+û¾ìq kÄÂÂ#'G{(›M”{É¢ˆ=[×í&ʼç^¾_0Ö^äch¥Ýx,w˜ø$¤Ç¶Ó9ÇR:å—Š„Öìô³}”–HËõˆDKŸkú‚òè‘ ¼ùMB¹Êp¬h‚I ÏvtñRú}ÙìåÁéã?úÆÑüsââÆ\v‰wE¢ˆº¹›õV7Â¥Mš¯36¡Ÿfã’ª)‡ý*çÜOMzÅy8NWøáÓÏz~˜wPÞ̳b™´{¹¯†ñޤQ•Ò_ÙÆA©Ëþ‹¬1%ãI–’„rš$á¾Iê]6P(è:^ÈŠ”{™y­FX°Ô̲:réËn\wèì©—¯çcÅF¢ÓíA:l$X8 ˜ ÊBôÍ>9Þd¢«êQÊúêó(FÇ€_ôyÊ?7¹aëeà²tºÒî×NmW*è=ð®íeoÕ=êUÌ•3óòDzÃÆg_îô-h’/ú°Ä°­;ZTø¬"d©ÙûGXvÙŠ•o±g†s1ŒíËZpÑŸ>ü²=µ—fC£òVYâ€Eù5 ÷cÛ³¨ %“î=Š+V:fuöˆ… ?“* ù/lˆ‚œÄœ½!žR¨ýϼtUÛ‡Ú‘É@ûþêdZ˜Í¬ÛîIgòcÑ´C %^S tDò²8\Åx=œKémS ™Ñ˜nº——ÊCÛU _Y˜{x”'’õgÛÕV°=buîµËgÄ ‚»ºtð/P$1~ÅŽí Kbzn2ó ‘øk¯¹u Wr­l…~TŒXôP5¶{“¯ÝÀ4GÀô4ó¾#q¨GG˜•`ò"Ÿl;ÔZiεek¡;>+ †^§Ký[é×íÍ i˜b*1Æ/sœÝrѰóà+üdwa´p‰÷lË$ϵCg°-/1®_„j¥™ÝŸúÜ_õ ažÞgNDß°T¾Æ-€# û&grQQŒYRkœ Ý9opîù‘¸wÈeׄ-°P Åx`–ïDšQøyV,5Í)QT$KV‰Ê7I&îÝÁüùXv¥Pwíé\©H)6i'#´]9¨döº|¬_¦¸¥qÏ}$¸›q|ß 3DMí }‘@Y··Äˆ¨s¾°¢Äá,KázÙ…Òèè¾ès]Ú¾” ƒ¢¢Ô¡–²ƒDö² Rš•fnBôéÔýõ`$!}*’™vtßÔ-¢¬ I2?ÊÌ<$Á¹$êÚÆaâi¾°™¾:aðpëÛgäf‹q÷›;_馚)‡]u&cŒ´a¨®=yLÍX@xVw‚~Ç<Š$«½›du\£ô“Η=àðûÅ! ˆòè©‘\Bç³Ï vrbø",¹§TèqÈ$Å%(:Áè)DøíR :œmÕ~5Ú’äÔiG±Ÿù/ø¡D ?á°8B…Å98 èœrˆÝíü'#Òtê“ÈÂàx¬òÔù©œyEö½ÔùPÕ:ü I »áØ‘l¶G‚QÕ§9¬Ú°g¯mwÐÕêщÇå8A¼,¢Ïë,®ŒÅEMW’À:AÜ ha×J D®é,F‚ì]P$·/­ô8î¡–_“‡ziÙþ©%åêtÕˆ2¼°q­Ž%–¢Þs5uDÙMýžã£®=Kv„·_áÐUÅ-ŠÁXñÁçÜËHÎ bsý˜ Jx„ySxÄ[Ì£!¦hèÛÕH†€#‹ó«èb ŒŸNÏÊå ASFK޽ðM-e2CwE0z>»e‹f~ÅDáܯd€b§œá­H)¤HÇ£·å”fÍ‹“!NñPÛ­²2~d’E€·Æ©ðã°¸!\èÊ¥­\z=Ñ DO⸓ÀOÓeDB°·ò¥ÌEJìCÕѨÄ8jÕìÅo+sHÿ"V",8ªgH4-i/µrPW<_/,Á¬ü¼aŸû"ŸŽ¡Ì…|J«ây Á.0~vDi*¦ §d;i„ÛÉ>è §Éõ4ô ãæ"GäÝs¢)dÝw­öBÚµ”w÷(x¼ƒõÒ½ì¨è& e.*ìäxмˆBGz |Çikö0[Psiªß.Jj쉣¼8ÖÀD× ®QG’p“ꡪ«AÞ9=Ô* ½äÉÄ­;Mb¶ZT Û&T—}ø ÆûNw.¿¸:S…Üz¿†ŠoãÌhúg(FÙºú½D,È=ÆÀí¨Eâé3vÍò_Kºú"câÓ3smƒ˜Yé~V Ѫ³`$ªÈ¸p(”'2]tå\ŒÙµRÃÛU‹÷SªIoéTF2¦ §?qÎvÌ…=1NÌ;É ¹f€ïYíŸ\ý@çȼ÷œ…ÉTâD OàæI÷Æ3ƒÜ6A’úf>3˜î¸Ü´Ã¦dhŽï±kOÒ“˜‰_%w YAâ@<4µâ¡©³xNCï£NÖZDŒÕ¡^°‘¡žè†ºµ½ í‰ÄÙ/Jjô€Ì€ÐAÙW+Pö|îÚsWY è^c¨qø¼q.ç%â^žŠƒ ®,UÚ{P­4†²—Ü(ŽAT*¤]mµg¤„Ö…ØàL”kE4"mT¦ðzR°J¼?dÝüÁ–0‹b™@Úæ­ÆZú€Š‡hçÂgZd þ•@ˆ"¥,)8®¥¼IêGŘ©\ê¡«¾¬†”Ä¡›7ßaÂìÛÛd¸c@òÃÏŸþ±ê¡S?ÎÓåšÀ˜‚Æ®k0÷’䚨˜8ËÄa ²•9бÕ\†ÈÐ\†3CüëZ¡Ç$~”Œ±\ÜÙ‘k 3\´Ú³–~DÒ˜pä~öû-k$ªs†ôõÌ;PˆÐ kÛx±d^I"øÿþ2hP~\•´ÀD©’ËŽ+§þv¬ÜvâJ馸¥Z"°Kë4oǹXÐ_¼&L)"zéM…Ï0Å"¢Ú§N¶º¦âØ>”ª ¦ËJ‡²±ñ\ãÝ©(Ûõ%déªöÒË"6tëõ Z›Åv И6šÜö6kŒIÒS,ž×·ÉɪWQ+¼ÒФÆòC gÝ|)£®Pªê“÷ýËÿJm³)µ$µýD DÃÁʘÝJÝ/2JgÌu¥N„3.϶„¯¯I}%-4âY:~6ZJ&~òÐÎÒ‡½¸'̵dœ2 ÿÄ™±†5V[ÎòyRm‚…e›p ÂXÃÆèI4dª h¨"»QŸ—>8$×Ð\Ôå:®Îgeö„Ò¤#ÿ0Xð†˜å¢HEJ)1ÚEñ-`׉–ãt¦¼µ˜¹årÏ¥½Àûø¨l6Ó,q>¯TßâÇGB W+ 2 UˆÔÈ»½“züX1¢);ÁcLbÓÕþì—!pHG­ü:„•jz Jšž•±¥‹ÃÀ¢ôU4 ý´ÈÿšÝËúó^å~‘]dÅpùÁhqƒÚùoøÜL¦{ªÇ17„ZO³AQ¿xáÝ •F /#ÌòQÆéE¸ª¡ØŒËU¹×wÿ5ð_¾0 endstream endobj 263 0 obj << /Type /Page /Contents 264 0 R /Resources 262 0 R /MediaBox [0 0 612 792] /Parent 256 0 R >> endobj 265 0 obj << /D [263 0 R /XYZ 90 720 null] >> endobj 266 0 obj << /D [263 0 R /XYZ 90 720 null] >> endobj 161 0 obj << /D [263 0 R /XYZ 90 582.316 null] >> endobj 267 0 obj << /D [263 0 R /XYZ 90 426.372 null] >> endobj 268 0 obj << /D [263 0 R /XYZ 90 149.112 null] >> endobj 262 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 19 0 R /F54 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 271 0 obj << /Length 3022 /Filter /FlateDecode >> stream xÚ­Ymܶþî_±@ XÜêDQ¯ 4)Ô퇠ðF‘°¬åÞ ÖJQòùòë;o¤¤=ãÁ~X¾ ‡œáp晑ÚEðS»2ÚåZ‡eRìêó«HF?¾RÒÚÁ~Añíý«»ïSµSQXF¥ÚÝ—,‚$¹ÙÇeš•Á?¦{h:s³×: >Åø¯ƒû›BÓØMÕÞürÿïWßÝûíÒ8þó ÅïHE Ì&»¬HB¥>Õ7°yY¶9_Zqw²æ8µLÓݨ :ßìUÐ@«{àQ[ßÄEp‚5¼¢±<>ždàØ·m4M÷¢”wßÃÂ2×QG)­ØiÉŒ™êJ&IºÛ/èÞy‹§›8ú‰;‡¾{-´ÍGÜØ¸á¹-ò.Z…iœïöJ‡*ev+Q² ÙÌ6Kƒ¯:î4N}"æn>ò¸¬x=KÝÝB/×¢bfÍ5(ºjºƒqäGöó#\O=6mËc¦«õ°uıçA¸42é‹òÃÝ$)ìÔ™ðf_(MÄÏ;óq^8k„JŠÌ¥ªG4œ­„ê`l=4ÀôA=;™Á­YíÅ’a«3¬ÏAT³Š…=iúiK´ËÐhÍMO#Ïñ„­<8÷ÝÔÈ:RÏ·7Úù&Á;|„†)ì©"Mk–ï|£qÂ0W¾ ­ &šÎ-«¦å1\ zB…æÁ#m©ƒ6xº¯þ¼¾5‘l}dvtÑàF̓±ãßøµdÑòµðìᱨ,Ô©<ûŸ#•o>¬8ÌÒö%ªw'#Rxå5ôÖuT<vÛrl`š´Æ>ÙÑœy¤ï˜xñ`äGAêJ´Ë+n¹ãJTùLUu‡ë-Sz0õ~CWèG¨Èžú©=°šªöÏBõ$óh^¹7/ñ¦ŒKÀ€T ÎÚVg!é ni{/:D}ÇIþGô}²' 3ç:üǦ3€v*Þ¥'?ýÇ“Xy42Ôˆö½5Œæ ‹;¹¬ÇS刹§®¶+äñg_ÁÿÐÄ9ž©ÃFùÌjpì\¹€‚½¶é>ÊÄqèϼÞò]˜C:Íy}Ã,^²,ÁGL<ûA&Ñ©+ ³Æ9Çc±Îµ ?ø^„—Âê0ÒNÔ»Éwm_3ܸVKš‡qîi_‡leu´ˆ5q)1‡±°oùAÉLÝŸ/MË7)G*¨U¶ŒHîÎÜaôÐ_ï·Oÿò0£àÔÛñÖŸÅö, 5ˆ¼ íÞhf¾0JgX=¸¡Á:ÛmjdyëÄPŒ&ÿ ³s):]ØÝÿÙ&ú†MNg' ÆW#!À;ðâPžØÐ7ÈX¦¡€UºˆKE¡g´çˆIvd¼²p:zdñ¾Ïý„x¥^†,•b…-­A‚@õ¶=‡7¢Â êOâgXûäs-_šñDÈv«0ƒ“–a"'ý®â€ÎÌÐßÂ1IY*ðnöb‹øjy/11QÈÓ7˜'ªŸOcçc“B!ãĨ†ÑJX× cy–%hqæe '4KX¿³Íhîð-ÜÕ}7šn´[ö´÷k³°PÉ"ø,dHÔqSˆŸ£4ºz}çâ¥ùÜØktR¦ÍB/J§f¬>´2øBø‚”¼P{u¿mî!z”±á —˜#.Áô@QèÓ´"Ÿ—Éìu°S ì[¨ÍK.'zÕ¶©- ^ÎÙ¸HK´#ÏUÜ/H6¤èÁã¤@‚¦žÎDÖs¡­I[HiÍ8]X Hãm;59²ç¯¬fàZx§YFÁ{<~ÁÇGož©X["V¹N26¶U.Uüuxrµ-‡xc¶ÁÎóRÁ«bÝ”ûÕÖ0xfä½í|`â‰s8ãu=€/Ǧ5tƒÿáò–ß$©]§zâÖ·¦33H釶°7-ã`Ý0™a…âŠÛÊÉéF1{¼H9†„µ`¸ë%dž)¸µÁ¹Ž fp Ý’ÖÇêa.?áÚž)–eèÚÉà ªxp0¼|md¯Fh¥Ò„tÓØ¸äD{ï¥ZhÙùLRŠÏŒÎM¯ 0Ï …$}š“.rb•mËEÍE“ÐRNš1Æõ¶‚¾øéÙVB” ä 'òö~ë¼1k%Qi˜æåº qr°Åž¥˜~üJαÜ*Øhmd aÀP^ǽ¤dôA·í†®€^¦|ê[iB„«Ë!Îws=DåE0ÇF›3 tít>WCó] XÐ:8w0'=ûŠÿVv™×U ût“Bš/˜ÈÛ­{deÊ]n6^(;ê6DŒ8sÔyßIép‘á]क़ùî’u”­ÝÝ–·ã•íŠ6|©ÃnDè}–†eQ¬CôJŠ„ç?„’ ÿŠmD¶ˆ¹‡èˆÑ£Ðª¯™–JÈ9y!.&“c€7“‘M€R­yb©F 8Ì$W\N1b#FŸM=‰¿[RpäáÁÁrt ¨X”/ú³2 uR¬B*º¤Í,S §Å]nÅmΞ åhÜ'Ø< µ¾6ú&ý´ª‰ É£ªåµ,UA‹é mÚ¹ä$ÖŠ ËøŠ@7îÊ]5x®9¹âÆ\MìºÏõ¿úïñ%{¸,úÿÓ/Ñîãð ÁË»G¢::CËkwo_ý—?Ø/¿…—iXdù®Ôa’ëÕ·ðxÊ0Êsü^D¥³²ÅxþØ€Eqï†â«ÏôÐ9J1ï Ü~H4RŠgpŽÀø{y®è ©^OíÿtØ¡O>ðÿ-$W®°/C?¾}s/¥û£+ê ÉT(+W…2Úï¸UMøÁ¶½×úÿù¹¬ endstream endobj 270 0 obj << /Type /Page /Contents 271 0 R /Resources 269 0 R /MediaBox [0 0 612 792] /Parent 256 0 R >> endobj 272 0 obj << /D [270 0 R /XYZ 90 720 null] >> endobj 269 0 obj << /Font << /F51 5 0 R /F4 254 0 R /F60 10 0 R /F52 19 0 R /F31 46 0 R /F2 255 0 R >> /ProcSet [ /PDF /Text ] >> endobj 276 0 obj << /Length 2072 /Filter /FlateDecode >> stream xڥˎãÈí>_áC€•qê!•4‡,6› 6¹ä0Óî«–«-¡mI‘äu äãCYz¸Õ˜‚ZU$‹E²ø´ÜÅð'wy¼³Z‹Üd»òò!fèëÉ«yúðéo‰ÜÉXäq.wO/KOÇÝ/ÑUѮߴ֑ù¼?“DuC}jêæDà‚>§sû\œqm¢á>ŒîBð²m~¥9]ûb¬ÛfiœšÈ$ûßžþñá§§I¼D©¯Èo°j'µˆAV ÍŒÚF¤BïIª¢Ÿáê¨ÝkÝ@2›DǾ2rm둾·=Ûþõ{ðÑ@`AiEª5±ÿgS:8•ëè¾W6j¯´©Š½Ê¢?ðŸG›èèÐ;NÔP÷´»6õ¿¯LØìeT\Ê:|{ÇYTµH}#ZÙD^¾'× ~$ük3S›èV [ú^Ú+‘¿?¤*‰ž*‡zzÅ´ ­W¬>:~×z 7ùjæÀ#HëeEí`Ý8‚óÙs=Œ´j_Ø3\OféB¼´=a\Q"¢b¯9_LGÁ¨í0 + ¸€‰a¤%‰¿\»Î›¦¸û“Kñ:íÐeéiÕÊ÷Sa”CxvÏuƒ²‚ïoxA’™É@zt -y÷g¢Ör—‰ôσ²FÄY¦žÄß²„VM†@G‹g¸oKÚÔ/mÑs׸ªUU{á¼p¬!kõ>…•cë5ÃÌQ{?…Õ3¿”ßLÎ쎔‡I&Ò\q"â ú™˜g10ïr­½k Àì~¤õ°^F’õ”VqMi«i7¸3 ãŠëØ^ ï”VÌé9xŸÍ—¡ú“¿ ÚHø)‹Î/QWÌž*OÐT*7l*mî´EÛ"AÛ0þVµálÉ1Á•i84EàòRžwÆj3t yÉLéÅèŠz‘͈LS¡äD=ÿ?öI ­YiLq’­Cý }|õ‹s‰ÔlvgÒL$Fcç@\4'ê° Ûè°™QíÃúÞÈ·Yв(òÎ_þÕ Rs ßDÜÒ%¹öÕlñß>Ò‰\€ÙêG½tn…I’¥^MW úŠ^Ì8oPÌçJ$R®ëõ›1/E&³å£¿_„×1ÿµ" ‘šAÅXÕà™ÿW‹ðÿ]1CYÝ …&Õ‘/îÞ\Šo¯Û7j'±è‚}!üzÈ(ìOqÍ 3"/Ój®Í¸õµÙÈ”ªB(öq±:=NH¸H[HÔ2_>Ÿrýö°zÂy>ËŽ“TàVQ¥žV,˜ .kÆQ¡À»…NB‘6©ýÖJ'—¥Î¨èdz+zŸTñÖ‘n­YŠkÓ8Ðz üâ´„8‚ð¨×z¨À w¤Ö—n¡ea ó&!õ”$ë2õçðïÀvçb„–ùB€U71,;mÍ&Â^8\ÎÚoÚo˜A†0æ-ªÖûÝößñ=•Ztí¸+‹Á}¤<ºLG5Õ(¹ò;@,“ÚÀ§çv)È¡`Qt]ßv}í+ pþ@qÑ1AdÜÑèD7y퇷5OέEèQAÿu&e†ŽÂëñÁ¾o“òHõÄûÚz<Ÿ‡VÓ¤é<šN¿tè‘+kÿV Wª±p½Ûôl΢è¼<]ÒfšEmÄèEC€‚>!œiç£yF†×s'é_,Íß¹“žÐ€% a1Zžóð¡s§í\V¾˜~é±@It9¸JŸ¥Á'S©ÂOPo´70”äȽ}Î-+@wŸÛi½?¦P’´ÄæÅ©ù Õ¤)ëîÌõAC‘SI¾jMÜ:Êÿ ùI¶óaóì;,ê`;YuÄ$”PÿãÏ{ƒÂûÐ?‘™¯¥êz(Õu‰T§?íþ„&µQ(pÈv¬ «9U¼iE×BkÖæ²Ñ…­«}! ¡^ñ؀٬¿â-R Áån®~v®êù‡<³œ÷D@þ¦]ј endstream endobj 275 0 obj << /Type /Page /Contents 276 0 R /Resources 274 0 R /MediaBox [0 0 612 792] /Parent 256 0 R /Annots [ 273 0 R ] >> endobj 273 0 obj << /Type /Annot /Border [0 0 0] /Rect [136.667 465.816 397.455 476.725] /Subtype /Link /A << /S /GoTo /D (Unique filesystem mountpoints) >> >> endobj 277 0 obj << /D [275 0 R /XYZ 90 720 null] >> endobj 278 0 obj << /D [275 0 R /XYZ 90 720 null] >> endobj 279 0 obj << /D [275 0 R /XYZ 90 266.322 null] >> endobj 274 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 19 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 282 0 obj << /Length 1990 /Filter /FlateDecode >> stream xÚ¥X[‹ã6~ß_‘‡Â8°q,Ë×…RhÙ–ÒB;Ї¶°[IÄ:vjÙ3èï¹Ùqf2ÛBKGGG:÷OQ«þÔªŒV¹Öa™«êø&ê§7JF`Ø,8¾½³ý>U+…eTªÕýn)â¾^ý$Ùz—iVßíl»w­]o´N‚Ç¿:¸_:‡®w¦YÿyÿÛ÷÷óqiÿË}ã_.¤¢V“UV$¡Ò ßê»nlêõ&‰ã`88ϣƢ©`è˜bøSuMã¼ëÚoÖ›\EÁ¯ãéZAç-s<­a&cÓË k§„pX+زÞÀ|ÎGëZ?À¿;ÙÚÖ/åÙ϶‹ÆYm+³Q:T)ëBâãv?ð¥pK ×?ArâtÜ„|èüÀ—×ÀùÁx‘ÈŸ?"•4ÖŸçˆ×ÇKÇyQ.¡ mO‡³w•ßNb·MW±w_8Gƒ>JO;Ñbx <«›Di˜ÇJôUÌÕt¤'ŠÜèL5˜ÕùO<ù›?n¯Ço¸–ç;SÉ ™ —\kú3½íÙr½°wý3îÖë8guý§·HÍß][Ù~0®mΗò¥­oï„§µ¶ái]«yìÆOAö"…ØÀÉ™'?}ÿ+–®ñàá´,ƒoGÙ¡£éÛvü=õÝCΤ ‡­ÌˆáŒ”jgööêpÈУؼ‘+ ½5ì¦çá]…çWDi„±_u+i6…†žNR1x’QÒ¸ýÁb°âüÔ;(Ãd `ã+÷-/ã‹o„Q`F˜‰GkZÏÌÃLt;þžÉå£l7’ey`™b$bY›×jÞÒio¹RàÀÒ“k„É4c8{¦Í§Rnã¾+kIÒ-æ*‘†E"—ø€Õ¢£êر½ñž&iˆK\¨`À¥G}…Üü÷äÚ½íïx¡7í´ Ll'ÙTixò²Ñqœ$IY`åb˜¢U¦½§ø]XîµòwUœ6qª»Ôº™yÆúeòÕuûR¡ÊÃ$ hg¥=žˆá—«i„Ó½,›¦k÷8”^€4h(²©Ûñ·¶d+›%ªIíXeaV>+ƒ—P÷o±S$ Féuk‰Ri-æí{¨PTµÓ8üÍUE 'X=q™€èÆ”Å1lµdi5æa.«ú5êûèj‹ƒšoYáˆtžö^é<¥z’hÒtçÉ“%Ù–gX:‡ù <Ð"Vó G; ×~ÂQTkpÑÃ@p"z0î¤> ,õ­Ѫ€‘NÊ‚eóðÀ‹l*.8äâ’`fKQa•EÂ2¼ýãIñ~èÇj_h‰¥A®"ìÆs¨BÃäâí_£m+{ë⌢x¾7µ2’N0ÅJÔ0éªÙ0Éðeô¥[Y¹¬t°¹\÷R~S¶¹ôxçqqíh– %ïhjûzQûÍAù¾¡ŠÖȆÆ2éÔ£î•}ËSî(0¨@ÜÂ%¦¶¬ba#Qig'gÈŠm»ôõLõîxjÚ¦2hjæÁ¬žN}­t9ïGQ“Ùlì›Ù”æ¡‘åÞúnì+ë_7ÅO?ß¿‡ð)Y(ˆ8¯ž/¶ÝÀ*È€ê!Á~TÛ ù›«;@#v;3‚$&lƒL ˜‚SÓ.¨ÏK‰9J¤²6ÉÄÚ¼hÊ€9> Y2½è½0¡¾afx’±ø˜b…ÊðFw¸Øš³yß¡2¹º–Îþ‡£¡L¿–gZGa¢Ô”7¶vÃÎj·R,MÃ4š1€P×\ +À HçÏr¡Æ8Ì1î¸s;ô¥ÎSÖ>Þlv€DÊrnvv¨¶àpÅÍfíù†w,¡›·7µË0ÉŠÿª|–ÌM€xžÍ¸Ç¿Øí©<ÑôÈÎMƒ˜CœôAöMY-@sŒó0Ÿ‹§š2Œó‡D˜Õ˜­Y56º8¿9S0 ©ü#óÁösA”=Äk½ë1ACV9ëè0Ç:Ô*–Gp˜…)¨‘ÅÁ{Ì¥ÏJ†h±¹ïÁæ(Nå7 (³4<¢¤Ìeà–™vCËœž¸?Úá%Â{õ "ž¦•I p8óŒ*˜0<ÄÅ?öS=SÓK˜E½ƒŠùÄLO\Ža™ë¬œBx%ghsi4>˜sQ¥ÁÓ"áÖsˆºP 8QÞ»9¡TÏ4jH#0uaˆfŽÓÒäMÃ¥Õ 6Â:½ëÎ\°,=–5ñƒ‰ÓÕN~ŒËb~²#C…Nf.ìLÓK¡s5“F7¸¡dÕï)»1 ›¡ÛÛ)OTÐK¨iµ*Â2ËÊÃ",(Ø25ÉèÚ¡ïšw$²TAu!Lb FOÁ Rˆ§¯!&ã”ÒœGcëgššo….ãÍ5ÔWÌ`d¹¹;„ûRÂòüg€DDI[Søƒ§&xÒ—÷X¼ŽŒ‰—w¤%×îº[û ˜ÒºÿÏB§GÜŒX®O›ÕÜL×_*KOflÿšÕ¶_0ºœ}èŽöËBã›gB6Kç_´àæw“«ë;¯­Ëââ*ÿOPþ(àÝöÑô[êºf‹[¦ÿùÁb endstream endobj 281 0 obj << /Type /Page /Contents 282 0 R /Resources 280 0 R /MediaBox [0 0 612 792] /Parent 256 0 R >> endobj 283 0 obj << /D [281 0 R /XYZ 90 720 null] >> endobj 284 0 obj << /D [281 0 R /XYZ 90 442.013 null] >> endobj 280 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F54 16 0 R /F72 4 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 287 0 obj << /Length 2118 /Filter /FlateDecode >> stream xÚËŽä¸í>_QÀÚ Ly¬‡_lÙd°lrI9d¬º¬ê2ÚŽeooùø"­²]îd zJ&)J|“‡þ‰C™r¥âR‡Sû!aèóÁ«#¿øðéK*"‰Ë¤‡‡ó’ÅCuø{ôÃżŒv¸?*¥"ýùþ¨uýÁºú©«»'úyjúGÓàZGîͶ%ø©ï~N„~š3Ö}wY’éHç÷ÿxøÓ‡?>„ë¥Rþ—û#ÅJЏÌ2÷¢ˆ‹C–«8Ë5‰ÐöS7šÇƺÏxâAèXH`&Ajàçi.¦ùüiêê_?]úÖ OºÅèLì‘ÈÉ–¢éO  ¤8îÖÔÝóÞeø¤O“˜HœFÇßÑï†÷ÖtG™ÇežûßLäÄë+è[É$/µ£•ýÍ´/ýˆ_*z½—yd s1÷²ˆ~ÅÿÒwÍ®¬4"úíåþ¸ :óþÞDíúùT&¹ñÎ7b*ØfZ¦?÷ßÖœðÀKPf©5üªX¤¬-zY —ü3ÍuÔõ:5Æáe ölÛ¬#”,-ûÏ©lß3UF_™Ûë¬X7½—¶žúééNe†' ÖxâYtô’•³68Ê@"ŒƒŠ+rfWdÑËÐ? ¦%(ªnpL‚îŒGGߦih ï%rðv‚Lôz©Y´gàcL3XS½´²¸³³}zi€Æ› §­™7r¼’íðï—Š¨"myE§rv<@Œ=AO>nòWA4)`–\pxƒ½>Ç– [ÀgÍÜ!D„Dd*X¾1WË—™^ø=}?¿`Ф—xÁuØõ';Þ9Î}ÎMÞi!é±Sx±``¬wJ€e!µ¼ÿµ/óîÚÅsN /ÏáHv‘4®YÔÙßFZ±v´ÈùdBº~!ývŽpµ›É†Ò†\¦ QȸÈxÍ–uwî÷RLšÅIH§º©˜»¡Ÿ¦v#‹aIÇòÅ7^‰ «Q}tËTÅ$Ó•®C8êDqŠÑ‰A-ÛŸpîÎSƒi ‘+K3°-(²#Ü£ÏdÄRjƒÚÜÑÌD,r9 mªÊ«Èíê'K•ΤsàãÆ=Ó©§³y²t' kz„Óz…<“Bz@’¯òz±è^¸‰ó…N² ¶7@ÚÚ9rš.»É¨¨Æ#ìÆƒÇàeÀ{#Ä"C!6äËy_¿“ó0B°ApÜ+ sñ v¤øÅ2;Á'UX\¿(=ÓDSéKUÈ@heÇÌ(i2=cû@ÏDõÅΗÈ~xæ ë"é÷·íd _2µde FePx/౦«æBF?b©×õª†- allè3(j o¯ ÄSzë1¥øÏº3ÃÑ`v4#30]E¿`/sÇŒ–Ñ¿ø2±ÝMœïp“µ÷­¥UUô4öCm½OA±ãœUPVØK=™Šó,]¥ߨíÅ„a¡ÄL;Ú¦qÄ}íŒxålXÜæ.ü~AvLÓÈÔ žÊIH¦qZf+_í¯&÷Šž³ôd7>‚@¶Gz%[»Á.d~hr¼¢ÀåÁD–øÓ-=‡Á2l+ `e)N¦#x(sø±È÷̉¹ov´_ö̤ …ü·é’o¬$ã²,gâ»80dûláeªnùÊ]¾ðnåÂï]jZ¾fýnß¼¹²Iý°ò*©ù¹ˆ|f“œ»çÈF*$gr¥<‰s-Þ¯gšªdâs޳Úš@”€[2§†ÅW•®B Cë\Ÿ‰´ëÇÂõ%TéDÏåSJJ_Ä.ï¶UM%î¦U徆8øÆkàÆK…Ësëƒ&ÂE¸· í-6•è¦ùáÁê ä1*é¹¼VUXŸ(ûä‚kÌ‹%0©à»~îÚs˜(ó"Õq'mó¹·GàÜÛƒ›†®7Þ€3R¾­ñ9µŸø»˜$<ßñzÏ7%H]¬=fQ $ò@!bò»ê3Œ×9j3­ßÁµÍLv›iÎCßÒj7ž¤ÎâòÚù-&Ô½.(åµaº#¶¨9+«îKgàþ'ѱ ê vûá'ê[£]-#]«M¤«Iß“ jDBÀ#Š\#Æ .y¶Pkžç® a9LvÀÆ(¢®ÁW¨È_BÑÜ™HnL€øi1FÁçkhŒpâipzOŠëhæÕ•e¨†•ïðH^¦ÔÝ”zX—•«àî€îÒOME”0°ïWúmMn1̸±f>c¼„iŒ‰¶£h™n¦.NKï—ž!) Þ)w*Ö7øÀÿäŸ>'õ”ÁöÝ™‹ÿ·žPh+«¢XOu?úðÕ`ɹÇ6À¹»/"WãK !øÙ†áu1ÔmtU¡¸õ/¸P"ëiì[3Ö'Î¥€ ¶X ï¾´üåË_ñ Ú è£«==Á|¨AÆo²ôsÃXåxósFÊ%®Õ‰=]º_íС—/ØÛG?® l7 Î eI† ÁÁ>eZnf®9°•Þ ÛqŠ‹^?—ý¹£=×JˆàÉ-Ÿ À|Ìyr3Ã~~Rð/X–Jãæ¥SâC'ÚIg\&¿Ûy“ü‚1I“èÏafݾk†]ÞAù…òÔwãÐ7ï?˜ºzÄ+ `ý=½Nþ ÇЪ}#,Cw_S+pE¬³Jô{â^{”ÿÄ ’‹©Úw9Lm»ûi;øCë‡s‘æéí~ #ýü—Ü2Zª„º„ëÛÒ~U \_Ûq{ššfOÒÕÓ̹z—ÀWõÝ8§ endstream endobj 286 0 obj << /Type /Page /Contents 287 0 R /Resources 285 0 R /MediaBox [0 0 612 792] /Parent 289 0 R >> endobj 288 0 obj << /D [286 0 R /XYZ 90 720 null] >> endobj 285 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 292 0 obj << /Length 1219 /Filter /FlateDecode >> stream xÚ­WÝã4ß¿¢Ò!]*]Òø#_+ˆ{¢o€D¶uÛh“x±ƒ÷¿3ãqÒ´›Ý{€Ý=3?Ï·S¶J៭ªtU‘T²\íº»4œ>Þ±@Å Ï$¾ÚÞm¾ÍØŠ¥I•Vlµ=Ì!¶ûÕÏ‘,×1¯²¼Š¾>¨þØôj !£Wm×¥ˆ§MS·ë_·?Ü}³®Ë8ÿ„=(ñÌ ÁVeRå¹D{˜,’TŠU^Ê„ IFuzè]Ýú (ûeN¬¶éíÕ9#Æ/iÆüyÌ ïåà5¬ħÚ9eú5˜•EŸÓj)Q›Ï¶SE»“¶Î²lÁ¤“îÔͲb{ør†—2M£7°VA«r»$™ùîý9=<Ù{/pÅÑxþ%FW'1þ,héR0Ñoöƒ/1šÞ*óA™¥MLþzæx™p¨…+Oßüç¿5ó ãÕó0aêȲ¥Xò«XÞßS4/±™2#X"J~ãë§;ôa}Ѽ¾Q|hiþí˜Gt±FººiIèå:ñÎÜok6öIëvƒJ¯@úÆ|hÕ+ÎÈ´ñ»Í°Ü7 ‚‹B3Ɇý¦Õ»º}Yß(ð™Âbîþ·Z{Vo|6½(tWµÌöy Á,â/ÆÙô7úñÖ©¾>^¼¹ò±äIZUž'" wÿ¨Ü[ Ã^¦‘ž`4ð"ÒVÑÉk^F6Ì1.ªÈKÔ“ÑGSwÄ×M³€ÔOÍN´ÕêžöC qÁÚ¥mW“0<6É:– ^º xJʰ€M­îvJY%%¬"a9å4>SLUDìÚÚÚ>IV$yVAB¨Ï~‚.OФ`r¬ûýÍ §Úì㯩X’r1jSÇ.Ý"d"òIà eƒ¿Mµm K/±;ÕŽNXãøòÉ3Ä}?½ sê ç)r¡Ø<ŠL+œXµ9c"Òhކû&È\Î91|\C0,ÆÍ¤ŽÌÀ󯀓y!¢÷Ú(BAòˆp¸¡éwŠ´|¨Iíò²Ž]>ó «’²þ#ë ¶gÜHxV˜„AuŸêèTõû¦?Ýô¤6Ä.‚jï` 4 8E£vúØ7Ñ’,C†Ã‹|Óh:@SIf߀~0VÑ5¤<÷â2R‡Æ*}|a»4d7%óZB1b-(£H’µ)&³ŠHÓÁ˜[¤¯ óp­ÕÉ8Ç©³²¤”!º[-KÕ;×`Ï#mÕïƒò‰*K¨WL?rB葞|ò¡öð1ç } U7¢Oi‚¨Ý`Œ"€6 6ý†z(hÙ+(<Tbþ¶Ô­Œ±$ÏÇ.ÜÀG׿N=,u, ^ðQöm‚Ïv™Eß;Â+z¢ì®îm8„DŽÖµ ¢´®Ã ëdzL™S{:¿ ùÃ'³àÏf_^‘8ÒzpHH˜Èµ£#,$\!¤áL»)Ejï=Gæ'ê@äú"q;az &.àÂø~ ÿ±×T† -KC,‡šÕƒ!‚&¾§jK„÷ V2²ˆß©t*¾)> endobj 293 0 obj << /D [291 0 R /XYZ 90 720 null] >> endobj 290 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 296 0 obj << /Length 3299 /Filter /FlateDecode >> stream xÚ•ÉŽÜÆõ®¯èCs5‡E²¸øæ8  ‘h‚lá°kº+b“m©Ñùø¼­¸ts¤†U¯^-o_ZjÁ?µ+£]ž$a™»úü&è§7JF{@Ø/0þøðæþV;…eTªÝÃÓòˆ‡ÃîçàÇSuL·O’$H¿¿Û§©þdœ=¶¶=2¸âϱé«Çià^Ü`Î ¯»ö—H¥Ç±¯Ûµw{•EY¤åݯyóç‡éy:Ž¿ñ~Äø6Y‘†*I™€á-€/‘’0JàDB8unPßߟ_œÌ=ÍîG%»VG«X‡eYúßyPßp¿r“ 5@¾vWüÿÜÞí5ðòý_:œîT`€•Á _^õ†WÚnàÁ¥7δwq ~yÁ«vû¸ÈB]ìö* •æ xœÕá`<:þn–eaRäþ}÷f¨ïŸÜP=n£ó0Îã™o„’î²°Ì“ÂËCÁßR—Œ“l“†iVîö ´õQÌ—á-¾5 ž‘`!åSÛáìY¨9Uƒ £m«þ…ÇÎôŸioÏsë®áJ®p–åUîÔ͹«@æ ^ÈìUüÒ‘O>yð ^]”ÁSW¥e´Í_‡:Qžgø xÁ¤:2¿oºLnK@>Q±ÒŸR%Á’Žwž+Ûð3˜ÀœÇ9ŽUƒ„"„Mo/àíHôQ˜À@`ÍRE˜ÅkÒ½F%*°¨¾I´¦6Î!ï‹”…˜?>UÇY_ ÄÔò¶¡·ÆÉ°ãÅs7θ Û0=McØýÈ–®­ /VÇʶ`8oyê:Q%ǰfÀ 5ÏDP´2’›Ã“À¡ ¢1’üÉ÷=Þ푟,ÛßÕžk&H ™Æt¤àN ‡âÜg`óà‹oUÄug3œèyq™¢þ,n”Šö;^$ý?šl§Þ­z'\D6 `¡ö8ÅhÊËÈ!•\ß Â ÓÊ`²[ØDLæ±xÛÝôÆ%"­gËæ–cÆf`UgµEQñ×ô}×o¨~·¼çÛ4à´Ç,%ÊÉntÃÁ•™.Ddolû‰A†Ò “z ÔsÄ=ÚÝ1À|¹LˆÓ‰Ÿï´†ðgÁ†«Ç†-,Ü å9¬,ójÿ‡_"¡3†ïfºj£B®XÇO€Kò¸¤wåðÞ훇*›8ûý­k’4„è¾pô[Ö„EªW/‡ØÇAäµçµYžú=«w£.õwŠßÀ40-%ó˜Ý´ÕÙø-:BHŒ×¼ õã8HÔˆâÀkN}3q[¦QñW"aT„…ÊY[ëàÀÅSÊšp`¾X‡~8+sг²Æ†¦ìØ5Èî¡óœ•áXøëS 5óÑÏ>lX®’9(rÊ×|pã£ì0²'û$®ÏY ɤ“2óÎM£^gGÃðîi‹Ÿ*‡4£ˆŸfdE˜ÇCÑBÄüh9ÌÂÍ›’KãPEúZvßÎcâh;Ò ‡‰ÿÄ·4J¬ÈVŽ˜¹ÊÐÎé ô˜óÂlåØ1åê*þ¹â´ÇÉyüaWD™uÇxìÓâãÙ OŸúîÌ£m­NSÐÿ‰ÈûÑõ¯sä*™¦Â ¥ÄNx¡BÈH¯t¨îíe`·LOLÒ)½Âí|iÌðµ<…ꎴíJËùDÒ‰ðíÇ–)ÏBfjð¹¢§/q ²€;Ë戛JÄjQÆ_0WZ@…zacn]ȉ©.Z[–§i©Q&9ƇǖDžOSÖšù¤*㤪g­¨=R-›re;È($¨›˜t*Ç( “yA5˜õýþ( ÊÂý=ÝÕ‹þ™çãVŒöY¯WÿDÂ>A|øör)­¯àWQœ‡œFå”FÁôŒŒNÔjl®»õŸÓ~\Ra|ÂƳ?^ò5ïÎx†aý¶F,ã0/Še•˜¾R%æWE"aÍ€$)”'œÁްN"(´b90ÌAR`¦ÿÀèÆ–ka7 ªqèÈ_`­`ú­ëQ e¨b¹œ ®D•óV&ËÆˆ-ùs¨Ì™Æ•ã:<¢ ÍÖrÎ2—…ioÈ<œ`ÕË´2]Æd„ ø~x÷‘ÑQŸÐ†²SHƒ÷ ­¤ÆXï‚"J€?‡ˆï¶&‰17%8˜†*º8øçÔ¤h¯ ï fÌ7¸ì-Iµ}£ãnß«X¸îmh0}.À09¥- JŒ0:¼R["’lÄ©±:]áOÙ3€À%HíÁ:%äìZA¦„φ,E@KŠSýð4ø÷È…Gë bƒ0®uLo…ãð7‹(ÅÝHI5]ôYrjœŸÙØ0“ ÐNÀÉùþi Y ÓSåx@ ÄxœðNQ“!VvŒ-ˆëŽª \ª¨tЮµÖUN_Â1Þ’7c_ÚÆÞ¢`‘8¦§_buÌí'ør¯BßxL€@>+n&^tŸt|%«yÕGºHH/(k -×o¯]ü$¶U7J¯˜œh¦}‚9öÿocîë©-­> endobj 297 0 obj << /D [295 0 R /XYZ 90 720 null] >> endobj 298 0 obj << /D [295 0 R /XYZ 90 429.619 null] >> endobj 294 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F4 254 0 R /F72 4 0 R /F2 255 0 R >> /ProcSet [ /PDF /Text ] >> endobj 301 0 obj << /Length 2951 /Filter /FlateDecode >> stream xÚÕÙŽä¶ñ}¿b—Õ Û‘¢®<pâ,àÎCvòÄA¬‘ØÝÄèhëØÉäëSII½j¯½‚ LSÅb±XU¬‹+î"ø'îŠè.‹ã°Pù]Õ¾‰,ôù°£ V¿{|óð>w" ‹¨wÇ5‰ÇúîoAÝd‘¤Eðû£îN¦Ó÷‡8VÁG‰¿qðxŸÇÁ<õƒ)›û¿?þñÍýv‰”Ÿá1>ÏPš«PÄŠ2ÝýA%2(ÝoUéqäq­;`#¼?ä‘ÏÚb{m?w÷2&=0ÐØ%Uß} uš]3¤éáÄyP•MóÊÞn¥Ë iœñ+†ô@E“%iÑ^£-ý®l0|q(>Æ÷ƒ³ÊõYã0ŠôT= ëÿhËÙfü­lD˜Æ©[ñö«d—´a&3‡Jtk3èjÚ£›Ê°( O—É?!ä ’$T °ƒHCŒõ ž>*‚‰Ä.¢ òö‚àq*'SñØ+Ãt'ÆY°ºÕpÃ×{™ýÌøµF‘:J%ÿ4fœxqdÈ“éÊáÕ"u5Î}kùõðwÑÃèΡÀîÔF-l4"uJ|Ñ· ™Ê§†&6µl*µAl²’µ >ˆ¥öTŽn qKÓz´³µ®ÌhúnÄÃÇ©eþŠ »¼´ÛÌsmWª¶®‰)säßêXž4Kœµfzˆs/´¼\†þyÒ ˜zþõú²à3‰FtT‘JàódXÀžûq‚»˜E™+nWk‹|Öƒƒ{çÀÍã4ZÓ™ÖüKóYˆ¡¹Å¿O¤¼Ø8òÓìJ"ÌgÉÀÔ pûLÀ®¥ýr6î¢ã'‰Ï]à—ή°+íþü1èf)\­:ܹö_JtqÙ£ÀÀŒãl‡Ä|æ[!ËìØ~-28b ¸h( mñ ¸›óB¸tá0Êa(»µÀp)Ð.8mPM*ªf´Ø$26Z é¬Žéè=]š²"âàØ› ËÄð@‡¼å‹ò"TRmÝüÃÓž+J²PfòÚÅõoÃ2Dçôà ƗÀýh4ë—áGƌѡ€mÌvιX„pÈîÌÆ½÷(¢¡oyµóeï6ĘVUڳΣeÆr¥><8k:Ø»¬ƒ¾,‰½ŸÄÉÕ½Ã)çmtÃßO÷ä(Ihi´Ú!!ÿ½ñÏ ÜlOÀÒ$qî[3‘[ÞQ›J3÷!¤®‘¿iÜÕšå5ün×€5ºˆ’éŽýMbÉg‰%b½wiEažúÈv$«ÔÊe5á{Ò]EѨHÉIvD…‰éfè6#‰ÒγÍu‡ûf•ÇŠV;ŒW1¿Àýž†²}·«R«'Ô©Ì–Nçñ†BeFÒ£éÚLGƒ‰ËžÜ@÷©p¨äù²Œ–à(÷Áǃn4ßEo½]­%Ì|ª„ãì½.à—ºëA¤ÌÃHä?;WJVŽ„”¦"Æq±ukÎgì'Riê&Rû*.dÙ´ê‹T|ÒkbÿþFÒ_¹¯¬oš¾&îÿ¬G°Êj_û".Âb¹­Uß¶”£à~èé¥d[ðê$Fzž¨çöâXÓ âÜ Ax-BñîèbOwÉD§­†ô¿HåVGUSŽãò*Š?¹°4qÄAT.î·‘ç Czþ*ù‡ÙÞ.^ÝS€²aö¦Òž ý²Û&`ìF€õW> Œ?m¹Œí¶ótØÉ <¿oGö5'žÆ€ò2þ÷üC¦îc/x'LHnú‡Hæÿ „3ò€Â1f‹ŸDE˜ý.J¢Q£QmpϾ`†sáÏÑœº²ÙåUå¼-çù²{ð,¹?ì)0¢KÉW6¾Ø\ò rfë‹xIµ5¾qê/X^d®ÎÈ–£â‰bu©[J’hÃ5ñ¤\üXì½ H“„×HªÝ;’ÌÂ8ñžÙ ˆè¢H}¦B»žû¹©™³ÎÝ5[-|ý(S©Ò0KÓá>›ý`+ÓuàfÖPæá®ƒ‘¿Ä÷e©u04¨.˜›É\ iL÷ÌHDz2™ ù©Œ „/äÒ`ÆtÖ³ÔWNr5ïŠ4\XŽ<…ÅVïЪr2–™^%Õ7cp,שp?ìF§8ŒS&S¿~^1t[1i4§²*˜/>mlr‚â±~©<‚1¾ ˆË¡¾áŽÀgçqú%úÜ\Að—ém•Ea©%,]^oܱ”ìû¡è†x1˜§y"žQ‰^ñÔÆAñì:{A¯L L¾N``“¾¶>œë`(²0—ùU© †ck‘$R+Â$KW- * ?ñ›`S/h’”+ÁG5è’ [@gnŠ`ì¾ã‡l#ÕÄ¥( €k‡IÅ|­Ë_\°ä¨0iKà+Òv%z ùisÅ”«÷ rîŠsX²_LÇBEï°Õß³É߸jÖD¥\œ‘ËZúŸe ‚FGî\‚gWÍ»†€Ÿùã[Û^(/ %Y¬ÑqgÍ)¯¯ª×åªÅµ+@Pcžðák?£„¨¤ ïÂæqxhúªl~B=Ìd9.¸ëA/‰7+eî 4Tœ…]RSD×Vâpû³r³¡7›£qòj‚f`¬åLA8ˆ7áÅ ¸Š)þöCMöª¶J•Hü#uùLÍSØ*åÉñRVvXõMÃÍ1н‚Äì/ìîin±Le»fH§äo>3´_µî5îèt‰˜©äÚ¶ók4±¬hkAŒÄ9ƒ8¬§˜~HŽ›.* ‚R/ìž,í¦áµ×t¡œf3õóÈßèƒ=}M®ùŸ;Ë.3Þ,«2€$.·Jwü ÷ÅÄudK\pl¦Q7GT…Á·pÂ)Û‚r©lÙ€›}8¢;(Y5r¥IªÑ{Ù°·îÕǰŸmmMÌ,.–ëÍ€°’§•Cøê‹5I à©N¿0èÔôO˜:!pÛ<$JpËÕ©,NørЯÞØmǺ^î×ï?„<²=æŒ[¸ÜÕ­×syrK¯Øâ}ò”X®³<ËÉõ†¾×ܲñšXÇÎüÕ¶á±Á8ôûŽàŠŽZض ŽÎéX¨…í°#‹X²GKß­¤³0Š|Uù«]w·~µøˆxµ‘íù* J gî9¿Þ}B!‘?}WÔZ!è}·`)o6ƒM?‰391pý¥a!äÖ¶u7š'—Yqþ¥–þ!ÛÅÒT½êŽ<ÇæŽ»Ü]*YWŠ^#N.|D^u?ðóˆJ—~/~ =¢íKØdqNC?ó"$ò[èiAOqÜô'×-S)Å|á(ƒ>Q?PúM‹;Š D°½Ðw7Ÿh‘ŒSz§Ã”GÆ7zEYÊ¥@z ¡½,1ß¼¥1A z¸É~ †ªXÊ4ûÏ&' Ù àŸ\iÜïÄ’§%F ‚?yŽÄŽÐ.°ÏŒxŽÚ)(jGØ^Ç@M÷tÊÏäÞSK¼ röAžä~qTÒ;Ã3ì‰y˜Ü7GžYúá©kƒ§l—øíì2—8 ã%ó7eJÙ²­/#r×6Y3’(ù‹˜×÷eÆÍM¼ÿ£)mNõLñL¥´r¶Ç@Vi_3è{R¶¯ï*¦Mƒ^ù¾áuý€ ¦ñ—|Xßmº öYaXp‰µ¦XÜåa‘BU‡=<RÐé2÷Dÿ`­._ãAa”/•÷¤whA‘‘§ÞÍÝ¢â(­û,¼^ÂöV‹P(l­F¡JÅÿ(¯ò6¯aîÝçƒ×Áê¹È;c°[[CãKµìCUëÕj_¦š†’§—ñ7?¢h©BkßuH ‘úõoùwWV³ø?"Ðü‹•_ˆ0É•òÿø—·ù·ÿÅåß% › endstream endobj 300 0 obj << /Type /Page /Contents 301 0 R /Resources 299 0 R /MediaBox [0 0 612 792] /Parent 289 0 R >> endobj 302 0 obj << /D [300 0 R /XYZ 90 720 null] >> endobj 299 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F60 10 0 R /F31 46 0 R /F58 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 305 0 obj << /Length 2326 /Filter /FlateDecode >> stream xÚ…koÜÆñ»ÅÕEažcR|?üMQlÔE“°Z¤h „"÷îáqäR²šä¿w^ËãI´ Cæììììì¼ç¢Mÿ¢MnŠ$ ª´Ü4Ç¡`} ä¿ øööÅÕû,ÚDaP…U´¹Ý-Yܶ›ÿx7‡údÕ°õ“$ñÒ·[?M3ï;5ê}¯û=£kþì;sWw§Þø8Zud|cúŸÃ(ÝOCmµé·~”‡yêeÑö¿·{ñîv/‹ã¯È_y@¦°›nò<Ê2æW¼×}ÝuÛ2ñÞlKî=nãÒ3¼§,½ñ`¦®E¸ðî¶>ì(Þ¨‘êÿ«AÙCm™ÒÕdÍÑL=Ò‘®Ùf42qo,ã;ýëö|5üÅ[ ‡<êOªeðAÛªiãGü,?J‚^LÏ-h´-W¹7 À˺o˜ú';æÄw±5Æ`ëçIì]_¼A΢Ù:Ŷek'>®Nƒ6ƒ¶ˆyîßÉÀÒ§G„—â7dð‘X¤/äj@\\ý†én²¼IšGà™æÉßêžwgSâ¼p7ÌX9‘ñîšÎONšä¬KqñØ3ÃÅXþ…jçXxª2ˆ…‡ƒîïj+_Ù¦Ã(@æWï‹xVNÒÇ£º¨)¶Ub€5Xp{&æ$o€ýVuê\Yˆ€*ÅfîŠ ÎiqX?è>á2òÂÍQ1¾nÁÝ!“ƒbÌ02‚Ô­’“:àKú½Cj¸×l±G禅X3Î ßÚ%n¦9€?ÛÌpꃇr¿Åícœ’[=J&íh‹ ¢]8)œÚ8Ü=ˆŠ4½àZ(w¦ë Þð0JñM¢MTyžbåŒË „ò›aœ²tè_;,´oé@§ @µå¿ag™yWÊ6W`+ÛØs8§!JiGÿZ‡rûw´êéÑÈÔÈâåN£ê_Ω´¬z?ƒ°ªà’"("‘/ލÈü˜Ò¸ÖÏW!žìÀjà -¯~¹9ûî+DIÄãwQˆ²F¨žÎ;fâcåÙÉ >Ìu/òD®Ý`Ž_ð Ê ª+>‡Öï:Àú•Ʊ¹…Ü)„°£D–ÔkìY.@c6- i7Vš>Ü:G·rË-8´ð´¨¢ÇÓ\‡¥¿K *+ÍÅG¶>µW¯¸h*žy‡–‹² ‰þõÕË‹&r®@»rŠTX€Æ€4µ6Oz˜Ý{»ûÓZ{´l¾¯ms87FÁk>¼^}Çzw'¢‹æè2~€G`û•U7ó°H,#FGt’(ZŒQì’“6®JO­bôÑôíù‡°’_]ìmè¼+3º±þJÖ”zÖ4jÄa®àT‚ßÌ@‚r?€ |ž‹ä<¾ãbœæA®àŽ¿ë-CQ1ñ`àËV”œ†ËZúJxÓïBx¥²N˜Øƒî‡‘›m= Õ½LÑHAaƒ8//Ã’ ôoƒÆq€~ ‰¸ƒ€ïü34ÀãAuj4Ó@#LÆ¿O Õ¹ýIØè,ƧLÆyd¦,ò³ ú¨þ³¦ŸªôþMégâ=® Su>&¿xÿ™Ú=Y endstream endobj 304 0 obj << /Type /Page /Contents 305 0 R /Resources 303 0 R /MediaBox [0 0 612 792] /Parent 289 0 R >> endobj 306 0 obj << /D [304 0 R /XYZ 90 720 null] >> endobj 307 0 obj << /D [304 0 R /XYZ 90 611.683 null] >> endobj 303 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 46 0 R /F52 19 0 R /F58 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 310 0 obj << /Length 2649 /Filter /FlateDecode >> stream xÚ­YÝÛ¸Ï_±w}ˆŒ®µú¶œ—"Ms@‡´Í.Ú‡^£%Ú&"‰®(íÆ×öï|Q–7 ’ŠVäpHçã7C:¾‰à/¾ÙF7›4 ·YySµ/"¡~|Kk ëÇ^ÜýÇ7qn£m|ó°Ÿ/ñPßü#È“Õ:ÙæÅ6x³×ÝÁtzµNÓ,xLð›«2 ÆÁöF5«>üøâíô]ž$_‘9¾.PQfaœf,®Í`ºH•GÁ~ P¨a„f¯™™á(").à@Rɤ²hb3âóÁ¬Âv…ekÏ7÷Ê“Ócm×O¦©+Õ×(d–ïöÕ¶“0~êÍf UÓø¦ ·E‘á¢i&18z’†E‘ðšÿÛ%9ÉqVîØWÞ H“øˆ?ŠÞíßÛû±:þDØŽÓ¾ÿïÏŽäÇw•$€WL<7:@ n5ÓG@ ï'ÓGaV|mO§Ý=rç/Þ½xûÁ/ÿtêM7è~qÁÿ.*zRJ¦ÞëÀi;„f‰ó$+Øÿ^2‘Åñ€"°j…®pÔä ½[àf½Cêœb^c;†Mœ¿ç,0Ûê`Ø«DT•ìE¹YA”Cæ‘FîX£c¼qaït… Ð àiÖùÐ?:åŽ^rwcU­ë){$½Ð»Fm`ò ‚2ÏÉÌ’tZÝZ/ùíÃQŸej/žk»FHŽ’æ%ºë 8¥t0ZÓrÖ6ë$}žŒ³J ÆvÂÉ’^’YžˆE B€õ†;)H õ£a{{n'ódU°qS?_>™`äÔkð§GT¨Ý”߈¢Z²”ààñ럖0’M²õiÝj ÇŠ$ø;ùóeÈq‡›Eb²[î\[ÐÓ—¦Yü¡Ü®úŽƒè$LTèŽ-ú%ùOo/ÝB9ÈË…ƒ®ÐVlg'Î&l^ºôZ9Ï&;ÏFÙ6˜Žx RÂ*uÀÅ£½“¹ÁàŒõ—«žZ¼ŒüGvQcÇžéTДÏw´#y´;;\­"Sl·„É#eä^Ƹ8£W6G¯4JÃ(ÝølN˜#,à\¼ 7›)í€ÂVs”›Ìóœp-Ý7‹«mÂ,™81ÿ—0—‘Øû±«$$ÓòX~ej´¯štYÊq‘¡UO½ÄôX‘:2o^h€–.ë ®ä³y°fß×ñÞd˜\ €ç8¦ˆQ(Z2ïFÖù¾íü.>½?Årt–"cw(r*Ô ÔL MÏMðáúº¶vÆQ¥y×™c¯ªÁ“ÔÔÒ~¾”äØþe¥•øbs^K¡U¯'E¼ —NñZÂŽ’Ö sJEW§†é¢ Ú €Ò5U—n àY„ÙFíY¨îmÓðeA–ɾ‹Yž<¸WìE4÷@¨j²ü*T›E_MÂ"Ͻ¯þíù)2‘Óç¶yªZØz-+^¡Ã·íþŽ<¯ônºUýJõ8÷Èe.ó+ "*Púú¬:‡Ö&k©†¡ªûÃ@סÁý’@YrëÝrm>_½ˆ‚YdúÎtR8,]B{°%ÞbY—èÿo½½¡ºª„ºŠ·PSò}î‚䨶m§rdjÀ çõÊä€D[ü/'ï¥Ù_äü ¹Ößp¶ßä´Kô1’­ˆ]Ĉ.aè2Pá'¼³üª{{ËÍžJnË©#)O’í, äщîúZ8M„¡Ky COñ¾#S¹6HПÅw+¼¶t€ë­ØˆOl ÅSâßîK¿]ß`vû™u§:Í|Ëõõì}‡[:ÿ¦ƒ,2ÄHº.`³ä*Ã"åßèò¥³¹”EJ÷¾¥^¸k!Kæê§¢FŸé&iç/|ñY |­´Ð¼týÚGu’•éÑG²h^žŠdùyÄ_Ë9þŒ¾¸È,¢d÷3œ›Áý±ë¹u‘o¯‡™"/7(ˆt7!3ۦƃÚN¼a“`–fxÝÓmu¦Û KCEGø“q€‡¬žO­ÿz³É/Îm¨=°Ô¬3Âÿ‚'¡oÃ8ÙÎ*¤€˜øµ-¿£%EÉ×4 Wºè΂ÄË¥G”P+ÛBÅÓ'+ñ%$#QpèᑳñõòDÔ3Õ?±àß Ô-æÒ‘;íô ,OÆ0p<+/OH”¨ÐàÔtæV-|\ÑâÔFw9 £é% _–¸LÌJïz#4°Uï|r£GÞÌÈtݰýG7HX,à ×ÍYRà%ƒcÿ²ô“n=ü~ÉÆy¸I¦‚ú%/çÎ-jqÇuIË£aqL† ïL_Ü9Žâ0Þ–~ñ;=TwP].Ô Òlc€‘ » Z[o’LÞ¥pÏV«Îy9ÐF¸¹hÔX§¯¥½x öÞ¿»ç OÒMH°5Sgm[öÞ-¾:nœ”sb‹š)Pcjn© ß°ÍÕÒ¤T&ûçwßáãZÜb2²¼ÿBPì tÏÜ#£øs°òÆŒÿE Sk…EÓÃéç¾ýd©aŸV“¢†yý’5Æ„iÆ}^ôîf EÙu*?Ì Â_I×?ËʺÑÃŒ5üÆ7:‘è•¿šÆø[Èüyî[-°ŒÂ¸ŒgÈD²tµÿ-íÅ3? endstream endobj 309 0 obj << /Type /Page /Contents 310 0 R /Resources 308 0 R /MediaBox [0 0 612 792] /Parent 289 0 R >> endobj 311 0 obj << /D [309 0 R /XYZ 90 720 null] >> endobj 312 0 obj << /D [309 0 R /XYZ 90 248.838 null] >> endobj 308 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F31 46 0 R /F54 16 0 R /F60 10 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 315 0 obj << /Length 2936 /Filter /FlateDecode >> stream xÚYYܸ~÷¯˜äÅ`[Iüà\€÷!²“A6Àr$v·0:zEµÇýïSÕêÙ‚Fdñ*‹¿ªVw ü©»*¹+Œ‰«´¼«û7‰HŸÞ()í ÃnÕã÷oÞý9Sw*‰«¤RwûõÍÝ¿£?íivÓýÎ¥ïïwišEt¾= íp`±åÏ¡m‡å4ò?»žåõ8üœ¨ôpžìÜŽÃýNåIžF™¹ÿÏÃoþô°¨—iýý±Ç÷7—i¬LÊøWNzÝÉĉ©Ã»Ïvz×ÞuãÁÃ××G×Ș›‰•Jã,Ͱ·1Øvú×ùHæIL„»ìœçJ×>Ýë2r2U¶žª41ldYÿ>Ë#ÐÁ6ý»‡«ÈÛ6”¨ÊX'EzpóÖîT—`éôÛ­y²¸ÐË4Ó8ÛyÙô­¡`ÏEþÍ©ª•-qË6Ø… â 0ôngò^¶ÅŸpmÏ/vÍŸg¨˜ŠÚC;ØÐ#ƒ—îïþ za»jpõ¬2·vl Wè›–%£ JŠ€Ò@›°Ážä´‡†Àe¤ vôó´·¸³ZÌ×ûE™ £]ñáí‹…XiTñw°k0œbË“€3Áã"k¸¾s¡K‹äÆ3-û½Ø+¶³å¡1ì…›{U•‰Í•Á^½ýü¾”Å¥*Öœ%ƒà„8 ¬D/¬ÂÊŒð”>v¢q*Ü\ñ·qäzx:¡Ë Ì»Àg‚ÀCL±Myë!€|.„¦ÈøY)‚Û̽Ø)‹öÎÎüvBŸÇ€ËPönžÅH! )D^0Lí _9IQ.—6Ê^à7a3/ט„ת̢Çó̫ڠäÌA5ÈŸQ»Ú\-ö“Ä™zEÀ"ìv¢¡+ûlx] ÷ÂÖ`pºÎÍíŽâűsëYH$¾gŒeh–°Âäj@Ó WÑþØú|liî#‹—‡ZÓ‘‡®g®‡Âþ¼°)ñ÷Öh8>¥#‹±“"ÇØ/ ªD¢’$D•7úb5ˆ^¿žxu a“#ë€S·×ÑL 5Ln$ó/æªGŽx¦±Ûb2';‘Î"0(í;L¶'w1ÌÊÁ\{0"ÇWþ=\BFŸ†ëÀÍKÀ~M |ã1¹¢«e†) ,z'ºv[K%*NSóâZÌ-Ä+³íO›Ix®“%€a6¹8¿87/B¹!ø¿@Do†3`šZ G±a¸Ú£Ùψ#s{êdÔj<Òl]‰‡`[øÂÌûsÇe^Iœ«…]3Ö{7À¥“Ƀ"×Ö0¥ðjñ¯ú70DXòALR q¤g“j´MPÍú‹ÑQØ$J„%z8%é3!ã¶s_Z?Ç SÆH §Šà,:®¤ Ólë´ÜŽåbd:‹>ðgElÊÕEçIuëd0t‡¯ä†F§å×Éf BAè§Õ-iÆEgøÓ±BI²iŒé$ -à ?\ÑR!Fëâ×Ç®a21 ¦¥“-PUD`šIðG³/\kWŒ¥ ˜IVýRC°Ê³‘'`û*ÿ»Kã*M·ø§'ÓìÒDü¤ ²è{~•±r…¾2(²ªÀɘ%:Ñç<´¿ž—Ov>â¡P¸Wa*,%Ç6J…ñn«z¡!ˆî(‘Ü¯ì Æ´ÃÒ¾…† ¶å lÑáCäe§É‰ïƒKÏmó2ÄÚœE®W áf•Ř‘Þ-f'´”Ì5Œ< ßÒ—IÖ‘-Rî„=pJ&Í5:&fØàN…|3Üž™ Žþ†ç}$O˜Ž7žŸx_OíiÞäçhª n äß?>JpÎôáØ:ø$:o)TˆDmÏ|bð»‚-ä÷ž¿üÒkL-ø%MGãùCÑmö¿·µ»2ü4²éÛð†â.FÜwóìm=3`¥‰YÓ¬2éO0= –k»™k¢ÅÈ5¦ÞP›[$#P°€2îÇî³Ü‚e´Žú‘9×Ð~éO2\åÐù5~sÖy£|—éM–.¡û…ÛNÑ\Ȥ“ŠqhèíØ)Œª­'ÅYoLÉ2É<àZóRñ™Œ©u›ðÍ¢´tvãb[¹èTá²*ŠÅY*ú‘, ¥å®·xƒjÎÖ?áçðÎ=ÈåǾ²˜L;ˆ”µÅâò¦cÌ‹S΀—²üt–!œ©¢YÄyã­ühòt³u€8X[O£ò4k£ÜNð”rÒ ‹’XÁLaÇ ¤™àVÑ΂(^Úä× ìŒ±šÜ\ÙÂÆv(ûI?iôKØé-¡Î™7êÀ8¡Pw !·=ZV¤«‰½ +T†r£*úØ‘®Ð|Ø…ÙìŒ|1ph_Öh8.ñ›*äº8÷´••$7 <7” +L/„Nù…Ðᘑk!MÓ‚vo¥'Þ…öp$kºs¸45Ü8ËÜì@ *‘giñL9.¬‹ƒiÁMÒ+xÃÆÉ0+øÜNãÐ_³’cƒíœ{É&/r[ØI~ùÄTëòã'Ê…òsoNÿêÈ}qõY²Æ†Ø‰m» ¾ùx~€²î8>²NãYFžý¦îü¥#,…/Gë%³à.üc dÑ›ˆ˜–ÿŠYDÒ:ƒRG)ï­Ÿwt»šÛ¡\ã䉗ж”à§ AF¹—,·h,úá±¾ö­_Ï@˜ä&óc.äŠy·¿8ð‰¹¿úӦΠùEË]×ÕcèÜøV·l¸¿G ×ëßÙðgìÿFx'8 endstream endobj 314 0 obj << /Type /Page /Contents 315 0 R /Resources 313 0 R /MediaBox [0 0 612 792] /Parent 318 0 R >> endobj 316 0 obj << /D [314 0 R /XYZ 90 720 null] >> endobj 317 0 obj << /D [314 0 R /XYZ 90 275.564 null] >> endobj 313 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F55 60 0 R /F31 46 0 R /F58 59 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 321 0 obj << /Length 2323 /Filter /FlateDecode >> stream xÚ•YëÛ¸ÿž¿Â=\Ä´H½¯¸Òà¸"- ì¦Åõî€reÚ"K†(í#}ç%YÞUšöÉáp8œçO^½ áO¯Šp•E‘*â|Už^…BýøJËl ›Ç_o_mLôJ‡ª ½ºÝÏEÜîV¿I¼Þ˜"I‹àÝÞ5‡ªqëMÅÁ½Á1 n×y }ÛU¶^ÿvû·W?ÜN×%Æ|Aäx¡P¤W¹*Ò4F}tœ©0ŽVi+ŬÔ7ÛÁwÛ»ªÙî«f·Î;Û»ÝÝ7¨Àóm°1© ³‚Ìß¾ìªsïùa¥m˜zÏa9[ïÝŽç÷ë$ ,<ø®vžIƒ¯šO›¶;)ØHë$9åªáÎ÷U?ôUÛ|Ëê^=×ä*_m´Q…”mÓwmMÌ` ¥ ØÍÀûÀt̰C€®©I‚ïÖ`Ò$ø5LBžmïm·-åµ[bM!ÀVqÊ¢îlùŒYuÌõRZ5lwöqË|ÏDm–”óGW×e{:Ùfçù …Šu,\ZüùG¼ƒ‚â@áù ›qÜóHÌ“ªt?ïû‹–{üvÐË!a"e2ޱòO ;ŽÂàim² xÑ8t9ÎúGÅ œITªÅÁ n¶ ji’À ÄõO’Œ¯ŽÂŒ_…é,ãÙ©,Ç\]©4äPˆZˆ|¶Ë˜#Ï/Ï2•ÙxŒ·Éµ™DŒÂXH‚[2’¡"›mÕx>ay£®|Ï4$R,: ¢SÑîãEL©†`®­¼‡BÆE‹¤A9³RÃú«ÝËâ5UÚHEùXi|ûþý»÷oon~¸ùNlÏÎÀͺ˜ìFjꥺX(“›‘íÛA±ÊÂìJŽù²¥ÔbйVIX\7 ñÀ³À[σR:ɵŸ«á¬l¸&Èí‹wÄ…“Ñ%åˆé’r$}L¹…øßHTs¿'>x¸Îdr/N¤zã€~Û3ö0žÿw)#t©ÌÄ£àͰx9^2ñ¼Ñ_¶(Öh•Eù$u•mãšû%á 81ž^öÉÄÁ¿®ŸˆÅæbã7X<“yMfÆ‘Ásâè×qª¯Ê09¹(0Ëðœë‚@aI÷U×6§I*n<‹' ”¹äi˜/[·HÕîó$[2Dšƒ'²™•Qìñ*Q‡£Üx­@áȃ‰·'™QxòËÓDÅØDç%ÃbaÏ ¸÷´—þ¶Ï³"øÐ@Ué‡Ê(…!†‹':nž|ïN,æ_<Ì„=:¹a×6¯{žz7òS—‚±®>ŽM VØæ2°:´9&!lpî‘ÖÍR³Yt6©k§Q«²ç‡vð„ BL|i”½›fÒw@9Þ9ìò°ÂË^)cÓö/ZñÞu¥»À9FÒç«vèþÀÑ‘D’–|‚CZ¥TêòD6 9U© Þ’é0¾Í’ ­w<©[¡`FÔœÏõ)Ž(‹pj1Ö@OC½¼QÏB`Lð®Ä"ã™ùAœŠ;âÔ¥n9LØõ;>b{aoY4{‘Þµ=ùiô*sàÉø*–Óìþ ÷èÊ¡w  ø VJõXF#%¦ À‰ä'B9.LÀº»3oYjô8î¶r„=@;Þ™t¥c];4ÂZnAXÛñÊS޽ÁE~­À B"#ùÂJÐ/äõ¯; ®ôî‰é^öû#:Böž˜&LÛvÌWd¡æ8;|¢d*Q•£ìœm‰%,ó3ÖR?¿Ý@Ænº˜Z6̪^N[fa×,ÂÄœÚÂCûF¤Âhlûªvj˜FP҉﵄Êr#‚C}%Ò|…H@^Ëâx€¹Ö0\’‡ Ú¬¥a¼Vœmap"sÄÀRâ€YÈ®’+œ(¡“Ó”ëݘ:ç®=töÄlžzÖØý5éP\e¼„:·'†j'¤Q¸#·Æqp‹âŽÐþµC„y›Ü ¤¨]Pc\>ßÚJ¶üy踞"„Œü2bÄç?4d¨ú«æc=¹þ¤çõC3ЧúáSužýÔ%iûgõK¸)~[¦Ê–Á÷²s÷Ûf@×áÒ|ÿ§/¶_~È™´H›14ø¶¦ ´Î•í¡©>9YRÝß1×%9a§Ú3Q\”ëod¤Hê#†DÖ‹K1It:àô`!>ŽÂ—Ó±(£Né£þó ù G_lUDÅïÌyuø´xE¦ô廈>ú®7s0©º»EÆàtžŸ{ Ìe`j¦ú«äæ3L¿h  ©\g‚i¢ ÓÆ4§ Y×ØÃ„kÞ®#¼{ÿ50æíôËHʘ/ ð':& D–=Û9ž¸GÄ}ücI*!‡ó,` êºSE%‡~AI£«º€Ý›ÅÕS¿ÁåÔ¸qÁhz¼ldÙ‰–uëE{¥Äçšzn¨'ÁÐø×ÁŽ—òš >À:ÏS, ÿ-Õ°|ú‰‰ £ì²süÉ > endobj 322 0 obj << /D [320 0 R /XYZ 90 720 null] >> endobj 323 0 obj << /D [320 0 R /XYZ 90 362.15 null] >> endobj 324 0 obj << /D [320 0 R /XYZ 90 164.45 null] >> endobj 319 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F60 10 0 R /F52 19 0 R /F58 59 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 327 0 obj << /Length 2692 /Filter /FlateDecode >> stream xÚ…kÛ¸ñ{~…~ˆ œ½ÅÞ&A¯(’» ô ”+ѶΒèŠr߯ï¼HÛ‰‚ÃÖp8‡ó䯫þâU­Ê4 ë¬Z5ëH°‡W±@ ØÜPüòüê͇<^ÅQXGu¼zÞÞ²xnWÿ÷ê8ëi½IÓ4È~^o²,ÞiÛíÆnÜ1Zñg×›Õ#œöbg=0¾1ãoQœíN“š;3®7qYçëÿ<ÿýÕûg/^ž$"?RüÉâ(ƒÙlUTY§Ÿây¯' ÒdUÐYüÖ$4 ÇuR§_Öø¥³Â„Ù2Ý´ŽXÊšÑòÜÖѼïÕ*dqFÂVô¬XߎT8*;‡ ÇªF±˜h6°w˜^„óX=Ϫ p‹ÇXÔÛjó97qÆ9Sñ!“`GNô ®dºàdЏTÕÌÝ„5O¨±åå|–Ãy 2©I(#R¬FñË8øyëFÆ­#ŠQ ZõÉúLpùduÆmÌ©w´Zµ<[á#9\̧Ó_míUâ´žøæŒíf_xŽŸVp*dfRÝ™I‡QVÃÄ›¶ºé…øÎ¦Ò(L2O G‚+ù E3jÞ¦5l>–wÍ,hÞLƒê{‘Ëj,b@M‘·OÛ2¿Q`Zn;äªï5Â6b·jÜ9'÷jvLï»¶Õ#ÃݸEqØq{ 0”[¦ Ìilõ¬›Y ÅK˜É:~ü5G>?„8ñŽY ß÷ÚÞݦˆŽÌ«Zd¬ÀÜ&Cv82ÐLÇW›§6p V½m›¤ +¶jFÒÙà«Å@.<äÑØšéµ0DÑ5ÈM8hYÙœ%”å­_ÏK–É*œ@–çÁÑôº’<#+Ñã|X²žBžþudŒ=v³[þÂæVP@Ó—5@ty LçFA85 µâÏnÒd v­V°aÕÁß´'[<Ï'Û£vë(x4}¯wöÊ"¸ë™±`¤&ÅÚÜ­1R®©ÆÐO'ïÖ:‰à]ÚG6X°7=oèF q>e¨®—‡7‡¨ßOVäÀع`odgq%C°1óÖxƒŒCž$Þ©HsçÎîe™á¹4¤$A‚ÓŽnÞ£o§ä/LºW¨¿³› ¢Î#A…í-÷*øèŒ –ôý›ÏK×5ê›3L‹—ç}× fÏCÍ9‚>îR š Gӛ݅q[Ì{fàÁ«NjÞ|||Bd tŸw[¨©ïô„ž›ÁçIéÌÉö—ëv Âÿsì¾¢-àqö¼v8/Y€w†à^  zNNï'ù[X¥€Iìd=š0$ÌÕ a¶ºB:ÜY xã2ÔÁÝÊZŒbŽM§ú[ƒ[=Ñ Iä\8Ê¢n¢ mbd|kø+q°þ+ (¹ËVYæyéRP³L»”¨’*,Ò‘½v¬ÁÏhã4xà¨Fû‘Þ¸w› `hY» Í<‡à(‚žÁá9z‚C3öEÒ,验øNï¯Ú¹ÉÉç§N’ˆ&ë¯ÄÃ×7EX¦%sxhÛ kŠ¥çP¯È<¢ðY&!ŒCÓýáL²à Æ1ãS ü»y¹åÄ5.|>zúõ_Ì»Ôvflc†¡›g …Ñ÷¥™þÉ s¯YÈrüß«kÆ`Ì Zí@ç²Èpìõ yŽs€Dö‘ ľ1¨pº&’Nv#¹)T T¯¦NØ$aáä±Kžª0žäV,AÞ–qWÑJ T {”yJÙ-K}vCr ¿(¦–"q™zt”öôI^Sä•Äj¤ø’®h¥9‰\31‰]Âb9= j쎧^I±•>¯†¼ì#Õs‘ "@öj"Ó”_-îÎò+ÅÊJÃߎ#8 ¨·–‡¯%¾b®“ Û~ǃoÜ'a ƒ[·…«$IA!Isïåwkð¨qÊeý ¸Î< blxGE$B:σëŽeïß¿¶~-”çJö(¸„¯³¯m¢°Á[¸rã2÷uÂÎmày‰ e.Y!º¨EBÀµ“¸_Vf|o’¦‘Æú”‹»5p誌‚÷ר4Fv哿8qýµ¯•½ÐβØ'°Å|?pLV€€þª°r@qH'EÀ·ì8pªIJ_4LCŒ ø¤J¯ 9D#侨`ü‚·Í½ÈCͶ ÷#M…€ ûÞÄîŠɹì"r¿ifïzÉICõÏE-åf×YZ3 D±ænû>×:ÊËm軀ã~ŸÝ+ÿJƒ>=³¦:¸p!…i”Ä]€hïê/v[}æ…(§­.âyæX»üÀÃQÞœ ¨gÕ‰¬Ÿž„ór€¾Wdý¼q›”Ô÷Œ¦î ¼BË ¿­¹:·Š;\aŽp÷ÍòOF‘|Ü9½áá ë]áˆcOLÏu;½Ü¸³E'¾ N$[sƒ #{:JóýY"íAâs,Æ_HXO'|cé/ž¬w­Àd™ðm¦Ò£n1«ˆƒR8¸Ý±‰¶ÏŽÑw‹OಎëзÜ_PYT!øw ï ¨›^úEêçÓ‘8e,lUû‡šIæ®LÅ/Þ[¶î5@f¼{ é‚ ÒkNâê|ÄÞío©„\,VîxQv<î»ÞXsÜßàÎÔÐ „¯ø…b…¢>€dCE.†VäþAâÚ”dL½Î —Ù()×Ð<Ÿ„óáÎ×ø‰C1 ¨¥qõПÔK/‘Uµmw}‘sÑÓ¿ßY~h½ÑÂ5ôÂ÷41¬lÂ÷Nò¿…ÞÀ×¢øœ y#Ù¨%9ðÁ7o4¹ÞÁYØ ënRòÀßKŠ<Èâ¾ó‡3ƒý™›Õ4^Ua]õ´iXåÅÍ(ÿâÕ…Y;ä&Oòàħñ&Ã|8©™ 2 ˨\m蘙hÌ8O¦' Wu˜Å™Ì'¢¶/æIÿ朗ÞÃ}6üù-Ê#‘‹/Œ9!Ü2“͈î‡[5½²æ¯ù=Á›¶›t)üò9U€Á`Zý¶È2ZUEa”drv)ÓΣžÞj:üÔÚ%ÝÐ{Å[zfù *…%ÕôoÿPÇå)TÐÛm÷õØcá³ga ûß^î1 C|Ü&èE÷æìþô# š endstream endobj 326 0 obj << /Type /Page /Contents 327 0 R /Resources 325 0 R /MediaBox [0 0 612 792] /Parent 318 0 R >> endobj 328 0 obj << /D [326 0 R /XYZ 90 720 null] >> endobj 325 0 obj << /Font << /F51 5 0 R /F58 59 0 R /F52 19 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 331 0 obj << /Length 1796 /Filter /FlateDecode >> stream xÚ¥koÛ6ð{…¨U Ô µ–ÓèÐ|li3!ÓqJoåAu0uDŒ|ŽüC̲^Dë0Ëk0Í(±9ô\¡?àž!K#–“õD.-‚a²¦´â9pÅÙ½jB[“’º 6j:¬™5N\9vínÒH*Z5ŠËÍE™nRGtW-ðƒwà©ÐÔ4!SQÜزàHüàæàUl…ߡϑ}·‚GJæ”±,ªX—µ·äMï¨Îž2ôdäFÄ­T¢1òMFOU|oÀL–Xµ¸r\¸ª{KZ_þå‘®'—N;9nç(Þ?Ç[³àúàåâÝÊVÌU$à4ƒ÷fKg||\› ´ˆ[`¼óäüy™ÎEÿ$i§¥wÏ'¾_rO¢,õ4R£Í}U ”ˆ¯6ÁÒ:†oûZ{†ÑFšz"ì¥6è_–?sxHe…¥AÓñ Z"q¸?‰ÝerZ¬3sf;µ|¿ãI4dMV8‚N›»½¸Ð¾’^¢€xVjøt¡Ž·ŸÅ÷b¼PKØ¿—KYbM “2ʲ’(/±”$ ¢ýz Cƒù‰-lzbÒeIà¡§ÈÀƒt¸c…ø¦7:`/@Ðt Îʃ? bþ娮‰ÑgÑ4Bí8†?(ª`ël9ïz¡SqØš l¥¬ƒ-G8a‚< Eá¥k±xe‰ÕjÔ%”›W¢á H}) ö6rvvVË2*«Ú—F¬cz±€fh½£²IƹtCù3ï9È€úÚ8ý=Ô"[ÐÒ˜EuZŸgÌn¤ ÄE—XDé@ÚŠ:‹4Ál§¶È‰ÖkrºÃîÝŒ-¦ýœÎƬÐn´¡N'¼6í&õÈì̾“ß=V¿þJì{Ž#-õXï5âÉ5Œ¬¼Ï`¹.pÒ=ž‚=ªx-v<Ð_„â=Á§½/ËVsëDÐ47 öÇÑ(©? ÕÍÖ¿•¿ Ì7}O›Ã9…¡eÄà4ì&ç!Á]1$Ùz¾¿’’²§ðC5=¸@37ÆÜÌ ôphŸ·ä¬§"êh›=Ôb“™+¥‚lPÍK&ªÊRÓÔշΠŒ²"ª+W…qfJ ºí¨+1N6µ¼î)<ƒæâʵ¦ÐHÛ]¦]̾N}Õr¸¦oG‰C’Ór? ³*øe ÷·à3_X€­¾ÆÎ ËÎEÌØt<Ýwæ°ùÁ2;Ò¥q qÍ[M[ OØÌÂN÷“(þâ ‹-zjíS 'Á µ“Ë\â(Ž´™F{á´ÞÊÞ³ÙÈ$¬ý&ömÁõ™êTËn) @—ýž‰íè‚+Í,)6¬ï e ³qî %~Pß×#Ç3R5û¬‹}╲4x'Ì3MˆÓ´@Gî,át¤Ï…Ì·q_%\íЋGç“o>ÄyüÝO?¾•½0^ÂÿG¡ÌÃðÞ/;y‹ÂÒÂø±8š°³Ñd&x>¡$ÿBy8€,(ÿa¹ï§Ì}+âæF ª`-1 p}™¬²gJiܹöYúEðûòÇM1ßv7ÂtŸùüËâ(>5ñgø%RçÁûÃÞ*á5sc¿×*Û0¡öA¬;œ:Œ£o€½õä‘nœu‘üœ §ý‚Vn´Ú„§™H·¼u<x³Þéóù×>ß·_œ.®v– ÌË2žŠ®³½âB…‹\øÑ¿G¡€Ë4ÿÏÀõîŽP ŸãkEǽùHsò1ü Ù¥ÂÐÿØóÏNÔp endstream endobj 330 0 obj << /Type /Page /Contents 331 0 R /Resources 329 0 R /MediaBox [0 0 612 792] /Parent 318 0 R >> endobj 332 0 obj << /D [330 0 R /XYZ 90 720 null] >> endobj 329 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F31 46 0 R /F54 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 335 0 obj << /Length 2073 /Filter /FlateDecode >> stream xÚXK㸾ϯ0C«ƒ‘"ŠÔ«˜Ìîb'Xä2}Ë.&l‰¶¹-K In·ä¿§ŠUzÙòì`àƒKd‘¬ÇWRlBø‰MnR)ƒ\e›âð.äÑçw‚)üÇ?ßýå§XlDäa.6ÛùåæßÞǽ~éM{ïK)=õpï+{?˜Îîj[ïhXÓß®jžt…´òºs×›Mýk(ÔîØêÞ6õ½/’0Q^œÞÿöøÏw?>ŽâÅQôò#Ç•Rl² O…ò y$6I¦!)Qš­>Vý—ƒîžü“Æ>è­’%KÓïMûОÞçÒ8¾¢ÍAƒqá‡íhXJÚ[½3õ}”y=Í´ÇúýÏœþø žð£9V%Í=ÝûQê£ãÌɲÐs”DiJ’;üσì£~b6{Ðí³cðã4½?™íÖ½}5­ÿ¶b·¨25­Id~m Ÿ´k›ã Óà¬ø[Ö8Ïܘc—¬ 8¸Í Ú^xV,yH®Öÿ*Ó*DÄ÷b$ÎiåçãË ø|Ü¡ûã˜<îè„h xI/‚ü^[ß ýÇ^k r¿Þ@pìîtGLO¶§‘mÓÒš…†þòFsY#‘ˆ@O'åïºhžº5¥¤ $àŽùîˉð†SúyÔ&öºcËzõ{Í‘`ƒ¦}ÔæÕ-k­ñ*ˆÓÄAZÄlr´´ VðeA¶@ÿÓQìé¢ú¢+«;1x0 ?f¦ß7åƒ~y1u¹æâmן_ÌC×TºµÝÍ8"KNÖ8þ· xJÿjz´„!Û)Uœ`È êSÒÀ€Ñ!0LI¬hš²ýk‡1€E]`Œ$÷Çn©®»áÝ£3"£#Ü>Þ¼eQ˜Ž·çÍÛ)4ÐOlWÛuÚ‘S%¶>ØÝ~H„ð¹×ŒÞ‘a×jÊ”N1À !ZÅò~X=*ƒòªœM¤Fl«[ØŽ³ ù7b[ŽØŽŒCM»?× Û‰Å*Z]à7A¾FA'[UJbˆ¶s„Y´Ävíœ{§Ö"¤$aÚÉž8ŠÁ§:dp²’¡÷³.y¶*Ò`ÍÃiÑ©Ô+Wí•ÆÙ`‡æÕ´$ØŠÉb$ùhZýD©mòì{<:›1f…YàÀ™HÊ0Eº4‘©ìÁÖÚaC Hhb$£nŒ1ŠôµýpÔ¥C$œŸéóعT;ìSß»´«DîINu&tÃT˜g|€¦Ÿ¶Äyâ´Œtk@ÚóJ°Œé~=T|—ß¡x:¶5Q« ÎÀFò»ÒõÐd ÊÐlÈë’‚ƒ2NáÛ-åä6F2i²²cp,¶[IÜ~š3?RA$WrjݰC×’¨Ì ^)Xœ@N§µ{F}& µ«O ÂÈÑ._;IÀé 3eTž92ðp(½Ç#åu =L¿¹˜Ëplø¯žª Èà¶„ŠSìÎó¸¢Ó¦4¯- |Ð}»À­X\佦~d¹tòoô/Q„äÀÐQPU;[ë0õºæà¨!-;ÙÏCu‚¦¿ã5ù‡Ÿ>¿§ –%GMËš‘(l„ö$ôæÃHƒ[¸»æì–fO³­æ±ÅkÎ/7 £ -ììë ±ºæhÄÓ¿¿€ú ¿tôupjœ/vüX¢…£ sÐZÖDgSÖýJH<'Ûï/îÝ™4Öok‡g$¡¢n)ɯCŽûÚõ¶EQºè[>a‚ʤ÷™z$´RO`À)[Cvv=| »»¾õ0ß¶mD‘*Èm[¸)4˜¢yœ©Êšaó¿¢g]ZîxL·L¸i²()9BÜÕÒùO£÷fv> endobj 336 0 obj << /D [334 0 R /XYZ 90 720 null] >> endobj 333 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 339 0 obj << /Length 1931 /Filter /FlateDecode >> stream xÚ•Xëoã6 ÿ~E€}˜s‹]¿cçÛívÜ0`®lÃMµ•DW?2Éiš ûßGŠ”ã´î(PÓIñ¥éD‹þ¢E.ÖI”i±¨ÚW!¯Þ¿Š˜òÁŸp|}ûêæ}-¢0(Ã2ZÜn§*nëÅÏ^V,ý¸ÌòÒ{»•ÝNuré'Iê=ÄøL¼Ûe‘xÇ¡×J4Ë_o¿}õîv<.‹ã±9ž”D‹"(óŠ|IÚ•¡§–¿•–5½í¥–ÁÒ/ÓJPìd·+¶QtlbÏ+- ³4g(Š4ˆ‹â“QF'VȱÝÍoðýíw†ÞjMC¯àpZÂhð®–m?HÐ^¤Þ –ò»;$¡¶ÄsF}ýÑ ÓÕYFwÐýN‹–w{d~ÀRóÂÆM`…Ã^^ Žq¡œŠ^M+Ò!…¡Å5z†/z6ªUƒTß±Q]%i|Xƒôb#„Ú†¼ZÃ%üƒ…m^¤!^Ä} 1n«ŽVûލ Ï3ž}€Ø&9ÛžÇÞgT täñư#%‰²:¢[$"0ö5Ñ”zi÷ªÛ±¤¸Gƒ¥¡Wk ‘¤;q2x5’sÉ*íÕYCŒðD :•p±”™NÖMý#÷î쵓Jžg`…,cÚ“4v•ƒëìÍvÀ‚Ä}ìÐ)rÀrŽwS™&ÞI {Ú£°`YÑa“‚#†±‘Étêp £œ*V»$£-°™„±GUßJ³¡Û…éIÄQjeRB+Ìý§þîóFû¾ï¿ÈÄqªTý"NZŸ+Pe[År»•Õ äÜ S¸ÄY[ÿGY‹ûêÿ-»™vˆ—‚`éÓU˜žüÝ<ˆ¸_¾Ç&Ý#•# ¶–±ìmàŠ›2hª”«HÜ;ÙëAô^L %ú®a>bÍZÑÕB×´þc§‰ºSƒ!ŽÙv’@ÇS×4µÙ§^Fë *â«þ‘ÙN›%92Ñöš.TlÄ8oLKj=t•až‘V, À”Ó w'a‹Ëš^¶ý±«‰‰ ,ñ¾yÿ1 jŒ÷Dãjî"$A®¡CÁ4­ÁVèûÍWàúÊçZže' ­œ$O{EІfBô%F)›p$´õÊŽsÞI«AZ:g¬dž_Â(;Ãl6Œ$Ú^†à¸È.Ê+ÀZ¨A÷ «|ayÁB¢–|rbhý0‹%„<ÝÅÄÒ†z©5wUÉW½Œ2ªƒæÖTéË2ï3ÜFZ¸@pZ¼%Q¥iÿ ô8kàV #Iƒî“»¢5ˆyÃguòDrŽOI3ƒös†Ú(”3ÖNý\FÖþÜÚO]2Jaj¾¾çv–K¢bꬡ-·RÛ™ ßlÿÑšJÞ!¸D3;áåPmyî®›ƒâ¹ÂL³ ˆ ǹšÓ–Ù8ù°9§+Ë‚0Š«-!´Ñ°ñÛ^Ûç¼›º†Y‹¼1̆’ÂŒÌËëB³'ž ‡-2l»¦' Ê–û™ù´$‡Õ‡%¤F4’®­[Cr—d Œ£“ÓÛ¶àŽaMÐh ,wWB©7Î:Ö¿KŽõ²Sæ"ð¼ÚÈ àȬ©JêNÖèJ˜á—Ü ÜCœsm9ép¹|ò¦ÝWT˜Roi@.@KC•>@!»LùÂB°¥l¹ßpìx…g”친–¾ÿøá'€ ä»EhYØŒ¬µ¸|ÝŒp¥Ö½`jZ!”bþ&_ÃUkò¥rŒc$'=š#Ä8¯$¡N¹vcE¦@6lÙËf@S+Ëь׳W"XÇÅp¼Ä§`‹°y³»âîNËeçRî‚Ù:¹òÖõª.7æ)¢¤$ohB„¹ò®‘-ÍŽnpw£n왳d{=ö6ÊXàJyx¶3¬ÄS÷É€#¯ý&|¥/ cábJú˜ÁÃ/Ý7kúØ•¬UÚðŒ¾\µ ¸žðc.êÉÇUìÁ@ã? ±Gè9^Õåô8üÈêñÇ ºô°/#~÷m¥X;G> endobj 340 0 obj << /D [338 0 R /XYZ 90 720 null] >> endobj 337 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 344 0 obj << /Length 2544 /Filter /FlateDecode >> stream xÚ­]oä¶ñý~Å}ˆ\xu"%R’ßr‡¤I (Î}(®‡T^q½êi¥ %c ?¾óE­v-'¸¢0` ‡ÃáÌp¾ÈU›þÔ¦L6yšÆeVlvÇ7‰`?¿Qm`» xwÿæí÷FmT—I©6÷û%‹ûzó1z¨N£ó7Û4M#sw³Í2ýchºGFíö®{l:Ç£jÀoU<Üû¾»ÑE4òÐu5Oï{a¸C‚­²e™E¦¼ùtÿ×7ßÝÏâ­ÿ@¤x¡P®7*µ2™(d‹,ViÆ ™›­±zV!7K`D*à—?¤BªH² ˆ'p5€à׆Kë2ÎŒØñoÄßäQ¿çoØõ›ÇÃè1dØ„ï(À4\3h«ap2;öB^;°8Œ›ýŠž…5˜8zFwjPêÈP%`ŒVøÿ+QY€IIœw#êˆJ©4V ))E¢$aɃw¤&ú©"póÄFU}lº´«ÆÞL?šîs«‘¡F¾Oè1ýÔÖ<|¸Ù3ǃ®Ù ÔìÃzA°+!TWîàªú%[ÿ?Nx7ÝšV Ê™Y^S±2E¡~E*G Ó' xCóк—+A&‚/XpdƒÁtâ¯È œ@Ûþ¡j…¬ïÐÂذ +žp1 ÏfÊÄp𙥂A?ruuv|v_½t_«â‚+á%®nÆ}G¼æéÆÄ¦(é¾Ú5-œ%Øá™·!iò„˜0ÆU;œ?ˆl ˜]°ƒ;U ¯kÁô)šÞ}ËtGÔ}ß!p`䘙²pg1 BÇ ” Ze« M¤êòð9ÌR{ŸàÕcs 3sà!ºgäì^4jö3¦© ¬=#ŽQçÁXB#)‘}ͨèž9´m Ÿ&zæá‹`¢éúeÞ}iŽ9ÖoÂBvœ =ùÚ"-½ÌO‡f>5$”Ô^5dR’ÑA–ÈÉôŸþ¨ óÌþë;`zÂ4uäñS3úidÒ¶§dýÒ“«.œ.ÔŠ4(.¼; PøP˜HZÌ÷-#–ÚÌ…ˆJ,K{_{. ”)Åc_¯ãÿŒõBúFŽ©'{j!†â5[nÅBhÍÔæ_cÍbÎA)±žíàü Üq82€ïhåÃïöS ™‹‡¾ÚXrpðèûé4›®žûmíØa7g™LB‘\Þ ,ïÏk±}áÕ|”'ôéÀ†ƒT €áô–¡‡P8ùþÑWÇ!æ$iÁ.v)ãB6¹ÇÖ6»Lˆñ*†$ùՌࢊÐÀº£p xÔ‘æ¡×ÀP$'\½{œÚÊËîäšk2è89:ŽpODøl!.\viD÷«ÛM#š^ç˜!nC«sˆæ‘'öÞý2-f¨Àóõ-5DÚFßÍ婯æ†ÒœÂ, ¯vàÞ'øä@_øO±\t‹–-¨[BZ'{MÕ,1W*’]|hÅSÈ÷t®/´Õ½ ‡NŽà®?\(nª±¦vŒ¦>•©¯šDr!sdÑ]Ø«‘5•zFˆ$uÄya§•Z@Å]sß<$Yî‰R\ÈC«*Y4§ü«vê‘äÜ' /áÊ&"@H^WNêˆô´T'ªÄiúa$ßʲèýE›’ÌmJ²lSÉÙp!ÑB°ig©ÏàøÁ;ÄÔÊÂa­ML!€òÒ†¼ùÚeHkÕKYÞÛíô”{hšæqž˜K“,oì5G'—|rIp-„êž9˰ëé–e‘ ®% µ‘’"ú&§jÈÅæÒ[¡LÈÖœ»¾¿¦VÇIb7YšPY‡ *X…&wØ@µ]­\̯™‘!>¸Ü@.§ ||75mÍ%3¡à3îW¸£Ü°«¢}Ðòd_,Þ}Jâ9ŸP3Pûa‡lr­¢²6.Ëb“A+—æ•kz Ú.ÈVT¼fFŸk.:©†’Ûa]EiNžoƒ€¤ÓÔ8SI+Œ^|pU-ؽ¬ÄÍË ÀrÙ¢ûÕk÷. ©Œ‹#Ïd—ýÚ=õØ©Pypì½@ÀxçÝÈM8äòc%›ZL¨ÃýËfÑ•åØ,fˆpiý{-*5Èeu±ŒÊ±zX Ì,‰ É<ç®`IW= 0wd<‰‰h&ãp…£³6½p§ss„íEå]Ÿ¯ãÒ+¥7e\Zmåí¤Œ!»Í-[üî—Ù©J—y±Ió".ò¨Ÿ’M sAãÜè‰((Áq¦q]»ùðæïìy—]Äin‰›…hû&+û&±*KH|päEù{û&cc 4‹mẠ-¾µü4•Æi‘Cd+’6ýÓ\’8³3rkÀõþ"o¿§Ú…ÞË×­ “[enÓä63¼øÏ¿óy; þmÛïªöíðÐto!8 W¨yrûýKÓ MnþWÛ\I™Xdõ|úu/J:þŸ¼àj_Å>ŠïŠYœf8³ÇtÍÔ[ÒZ®&Vü¾øaôÓnœüâ•‘º|JŒ!þ÷¯¼BŸ­tyÕhÂÌqcŒi Ñ«±_è8Kò9ôi××w´Eœë|ÿÈ·sŽº=kæ¦Ü;ª"»‘‡çF"î³ú¶Ù=3‚Z-ZnˆÒ¦—}:w›°€;tIªPæé¹v™Cæ YªɇPÂy 0ÃS3Îw­ø2 óÞµØ ›pçÙ±> R¼àPÌ(ë8uÒÒŒóögFµ“¦“Â;K¡ByQç²»öŽ ¹±>wòàph¸ËÄëwž@w.+¸H®Â™ÜñQÂ;™\¼Gøà}Íù=pjºËÃ&ÞÎëæ ÜÔ?^¦QEÊÀÄSWS;ž-»ãìò5æ¼ÃÆ 'Ù|w-²€ÚX@]-Òg!ð«––ÛN}+ ‹t ñ¬¸Æ_ äÙž¥gâ‹Ü­KH_óûèxnœÀ­›…|þƒO’ø§¦SÉÏÊüöÛ¬ÃÌülÌÝÝŠbþªAL$½çØê# Bz+tþÕ'ˆo_8=qøegþ §Æ–> endobj 341 0 obj << /Type /Annot /Border [0 0 0] /Rect [362.006 428.218 522 439.127] /Subtype /Link /A << /S /GoTo /D (Building flexible time classes) >> >> endobj 346 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 415.067 166.998 425.976] /Subtype /Link /A << /S /GoTo /D (Building flexible time classes) >> >> endobj 345 0 obj << /D [343 0 R /XYZ 90 720 null] >> endobj 125 0 obj << /D [343 0 R /XYZ 90 720 null] >> endobj 347 0 obj << /D [343 0 R /XYZ 90 291.996 null] >> endobj 342 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 19 0 R /F60 10 0 R /F112 167 0 R /F31 46 0 R /F58 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 351 0 obj << /Length 2249 /Filter /FlateDecode >> stream xÚÅË®ã¶u?_á ‹‘±"Rï t‘)fÐv (M€Ðm©£‡G´rÇýúžeùŽÚfWx!òððð¼V»~jWF»<ŽÃ2)vUÿ&èç7JV@8¬0Þ?¿ùácªv* ˨T»çÓšÄs½ûGEûƒ.Ó¬ þ|²Ã¹ìþÇIð»Æo<ï‹8˜¯ãÔšnÿëóßÞ|x^žKµþü Æ7 ÅjW„e–%ÈÊ‹0J‹]V$¡Šfê/S==í*ÍÓàû=Iƒ«k;g¿Ìv¨,OãċڴݗÓ<ðÂ\ùÛ·õО›+²¿Sð 2¥A%Zñs†H?Rþ~‰Òï‹×E&q 2Òýå&!>ˆ—ÄaŨ)â$Sa–+áCóñwXîñÚØé¥uôäNÇagÿg™~ø˜EkG;è8 ó"EfEá±U.o?¸¥Òa–¦žæû;_Û_À;‹`œ®ípfX?¨ž;ër4 ‡ƒ jÞŽ¯moyUái·Wq¸rÖ…bÅE¨²«Ã²,™`Þ~b-Ãy’‡ÅAçaž¥Lá¹qW^'þ‚?89lÝâE?zl êϪÖ{Ðà·üb²ö¬“v´É€ËkÃ`w5>6`GaÀêžn ªNæ¼Øïš«l„˜3½ƒÕ°Ù-4 ÎÝx4ŸVÅX’Š!Š~Ç„ýíuËØ=äbïQtÖÔ¸ÊÐ7R̯°ÝâcG;#8¡÷ãê†å)Ü †ƒ¸¾#jÀyÑ‘!8ÛÓ0|J ÌC=ÙZÞ¼«É &:⺹®íÕeC–µo ©#~QŒ Âo¼3|¸( @§iì{k;1ÈAz¨ѵ=úè ¬¡ì8»î&5¤v8%Vƹ«yËj]ócøslÏ‚1z PðZ6üCg ?:•Ä­BÔ§þŽº„ @‹Ë„់¿!9Ô™—a¹øˆ'?CØQ”…˜-˜|ª¯,Ã쩨mgV7Wa§þéyh¡œmY³‡Šk*ä½áDª‚šAI @œ`ÑÙ̧àìCÝHÁ°s»$A<@a€cÔ` t¨Á8‡vk˜€7;Êhø¤ð`\Ãaˆ°î =صéùl;A;™+òQD>ôÆLtm€y&>8² ®œ ñ€X†“YT=Ñ éïÄzó‘  D¨YÞl…BÏ&œ¯$Ø0¬ßÍEÞÊ›ã9(V#tíg®[NÙº§­Ú P”?ÖnéŸ~š¥ dGÄU+ â|©AY!ä›Ó;†¸Ñãšå–]# 3 ÔtþŠƒlƒ°®übx|¹{ú¶•Ö+Åí™|úuŸF+-Å«ï}k;Š·:ˆ$3]>¶_Å4˜E¢ \-Þ±øÃÄ„–àöÃýSêÇz‚xçU'EœÄáë:k/LÁœ®žèRÎé…«Üý œgð]ÎöpËgJD@/Üp÷ rHéëY JÇQøŒµA—Á‡UUäÞp–àq.I݇#”‡è|‚‚`¼ð–óEÉuöu ŒÆv²å ì U¢ xØ_½ÒwO¹U 1¼nQJêÛ6d(ó{Ò) ŸtÊB#ˆK7€"‹+lꀑÓm§ù:NQSP÷~dN>pã,ñï󩢦»fãàÙNs÷ª\²,_fÓ¡º+ ÖƒjûIz€F˜€}ív|6;_­¹Sȸ±aHP(ÁªÂcÆ %}¾Ñú—N¾CÀœ´ÏþY×@¿o§;3&‘êD 3°§Sð"õB Öq’UÕÍXÔIWI~ïºèu†‰ï%K~Æ Q¤¾÷ËȸÈÖ\ÈyçÛ¬W73.ürqŸ¥¼MœÝRúIYI|±ETð&=ª¾†oÆ–ÔÞ’Šçq\pÏKKWw6Ñ–Óßå…ÈÊÑ¢OŽB©X€ÍÞf?#SeÅ•Z{éÀV½iýì°´þÐ!’öxJ¥0 ÷ L>vŒ|œ¯|ø8õÐdÂÐǵñ$¸‰†SŽÑ±k}7+e¢ÄiSÁ8ᇟWÚ"FhˆçðÆÁ|À™Åú™“” QvªÍ„)ZIœsx¨ÀñËÏY¿IaÑë¢`)_æÿ×Íy^…Išxœ·Â… jÛdã0ÊÔBõ0Œ*©[ÔÓ8Я©_hüÛÑ 4tEÉëI-æIíýÜvõ2¥®Rûµåi+_Æ"XU0x»ÿ>·IóñÁ,©=ÕžBúª|"€Ú÷”¢„"8Ç©‰!PÝœÜo亻A2é…Õ¹< ¶ê3ßáv }KõHòÿØÁ5X\y¡‘Óú·Ñ³ü©ÒˆÝGtã§vìž¶L‹¤ò0ބ֧iù÷é?zÌׯ[„”s•{œ§§-C@+˜èåo,Nì0„Wó4Ýû–X²œ5fHã6> endobj 352 0 obj << /D [350 0 R /XYZ 90 720 null] >> endobj 353 0 obj << /D [350 0 R /XYZ 90 477.672 null] >> endobj 113 0 obj << /D [350 0 R /XYZ 90 168.604 null] >> endobj 349 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F58 59 0 R /F60 10 0 R /F72 4 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 356 0 obj << /Length 2771 /Filter /FlateDecode >> stream xÚ½Ùnä¸ñ}¾Â@V¦‘u ³›,&‹l‚ì8OÙ`BKl·ânÉбvùøÔ%J=–gŒ`ôCÉb‘¬»Jê*Ÿº*“«Ü˜¸L‹«êô&‘Ùû7J  ìVßÞ¼ùí÷V]©$.“R]Ýì×$nê«DßÜÃèûë1&²ï®wij£¿M{ÇSÕÞ·wMëyäüO#ÇÃ}ߵ׺ˆFú¶æå}'+DØ©¬,Ó(S×ÿ¼ùáÍoÂu­Ö_yb<PñÙƒ²"•IùA?víxÀ“Q¯ue t íÝ;Á¹àŽÎãâ¢÷÷<:‘Rœù-Áà€}À†ë$õ}+~“,ï¦Ñh¸af‚-€ƒ«Ý¦Í˜46™¹0D ¾mˆ:Îu ùqú"Éte†´v&IÌI?—È…ìT«BÏŸž^ºÜbû¯ñÔïᩉ]É ¤¾ ô#¨‰ à“Ä«NlR»œ²U¼i‘$,/’„HpÈz`ƒäÑó\7óžy?^g$£Vb™,fcEÝr?ÈÖZÎ~nA³úyWá¢u«Ç Ârlñ¢gÛb8ÉÛ@Fj“¹ÁÏ)˜¯VÃøݲiœ%Ùê ½}(‹ hßÈ Çj[Çtn èK«ÿÐoª˜ŠS›¾BÅŠ¯8§:à¼où†‡nê/Ö¸v(ÀÂD²Fü›Nw°Q¶VÇŽ\f…ĉ´ÝH‘r°ä§i6 LûÐ'É+äÇñ¶6X *˜6¯!¶íR°kP× ð#<ÿÿæB²öÐC<$;5d#Ó(‹N¸ÇCC¼?0Zµww Þ#ÂNò­atýèkŒ…`·-˜|´ \‚—¿,˜b¥óxˆçz—AF¶M9‹‹Åb°-_aMBñæÐ |üS™¤uéeFñÐw·î3¥¨ˆ €ËÛOG„!|ArŠÎLçEt; ÂÈ邜î§kñuo;!<ûTÄ >UwBv ™WÍøè[qevfùdÕ¤Mé“J^QÑ0Éø‹9Z²ŽyHÚ~z™ô¥3^”&¶Yzé=oL»S-¥NŠÆâ¸¬„yÌžñŸø‹Àâú`páú´¸>˜_»>$~áú`‚ëÌÏû‘LYNs½žÚcsOj†ƒ.Ðñÿ\{ñ£R¨Ú?s4ìQ°[¥ƒ¨–­²ÑQƒW0*"§…ÿ'ñLžÇãÁ ÆχˆJƒÇæxˆ´‘u]¶tüï†{¸%±^ê'™¸d…O¶ªÑaJ’¾ %^óÛ$’À¿ÿ…j…þÌCI0Ê2^ðùITÇ&骎MÐ%óÿH:U8:õ<¸eƒH'—à]Ž~¾Np¼*ÚÏ»^RÐf\OE $âm¸[wu!F—2…J¤ŸÝ}·TÅ=Š×äJ·â÷S…­¸ŠUesµÎ`;<4¤YˆÔñlíîb¯çùE¿qö„*g^%ÝP³‚SšLG¬¤º!¶G¾4U²ááø@m¥,MÔ{t™ˆð0õÄÉn-\&³`Ìj‹»¹ÜN©ÍP2wíáM8KÇó¼ˆàfMJŸõ~äM(y.ɇ†äŸ­û%Y¹ö8ìýžÚÒ ð¿„\®£l&Q¦IÇqEÙµ*ºÁôWˆÔò§Z7Ï¥pæéiðóºßrªibÖÕç]ßM[>u7#^ÔLýf€hÎ,ÙrÓ)ä–!ª¸Š[©6âë°µé»VQûOkàKC9#LqËOSKÿøò"Ó{oBòä`b®LôÁ÷3i´taÂÉ {vµ¶Œ“Ô\ê€rhþƒ$J‹¸Ì€Iœ,Ø‹3[\°¼’‚š8ú ¶ÛÀCŸÛ®=Ÿx@/`r„¤ Ø Q¯Ôš)üyj«Ãû¶¾ñî[¸àýÀ»~ÇXi3ô¡W:@Ëœ xjÖh¢.¯ùKsw?š=©$Ù¢«](dJÂj¢ð’/ PöÂäÅß….Ô¸˜©­{aý›-`¾€eMòå“þ6¡Wê?@v††§ìÆ9˜!-àÌOÍ2›~…˘r|<6çÉ §¨Ô h–W`º€v>õ™ùš"Ö¤N§(䟤 *%6Fg~ú®Œrô¨}€Å¡©ÉסÜJ €¦7wíÉsš Xdg g5à¦ÅÀ¨-ºÞýן¨Pï‡é8òypÈV§–6€ ê;()òùž°€÷Ä`×j8Ùìù?P,þPÌ)Šå€7 @~ ~S>;Pbž&jÙ&¬+믴Tð˜ [pâ’¹aÞeLHü*îF8“fŒ ø‚Þg0Œsº 2tÇ °Çú§†'Nó%‹ñ·–x hœª„–«•b/[õ³÷gù‚e7B×Ë 6 ºÒ¡3–‹®4\û®w'©0»~€-_ÂW3Š¢ðÏî¥nœ6¡ðŸ-ø¨¥ qó7¶íš ÀP·Ä¯¥ÙÍ_ÜØõR?‡¬õ3T!•k ™æž\‘pØÕylJñU6F›Ïtôݾ®`BlÉYÌð7T×0ðõt KÀkLÉQJÒ­»£ÌÊXiqH‹1cÅ :ÒG‡ÃœEë¥NÀ…Ê‘¾$Ó=îŽPdy—D¦ê›‡ñ÷˜Ì¦˜ rÂ,™¼$¼N¨Î9.Òá$œçîe#gˆ 4“³dý:Ï)6Ðl\òB°‡|‹PÈfÖ†ÆÝ̇ÔêèD5H(ðÀôæF •|·ì»#O`††ÿK=ƒÖûÞC ÿÓÔb–É,íÌDúww;0ÔqýÐÒŸÆ7js&úÐôÜ}ÛMw˜™”6vë©Ï\Øh„òü>\‰ºO¸¼Èq×6£'0D‚€ÿä{I´‹L˜Ò3uúü&Ítâ N†[8¹•d`ýÑlÓéã]ãù[÷uMôO endstream endobj 355 0 obj << /Type /Page /Contents 356 0 R /Resources 354 0 R /MediaBox [0 0 612 792] /Parent 348 0 R >> endobj 357 0 obj << /D [355 0 R /XYZ 90 720 null] >> endobj 358 0 obj << /D [355 0 R /XYZ 90 154.339 null] >> endobj 354 0 obj << /Font << /F51 5 0 R /F58 59 0 R /F52 19 0 R /F31 46 0 R /F72 4 0 R /F60 10 0 R >> /ProcSet [ /PDF /Text ] >> endobj 362 0 obj << /Length 627 /Filter /FlateDecode >> stream xÚ•TM›0½çWp4ÒB±NU[µªzÝܶ{p/X 82°Qþ}g<În’®´ª8x¾l¿™÷0O øxÒɶ,ó¶j=nŠ}ÞðheP]T|Ým>ý¨y‹¼-Zžìž.Øí“&Eš‰¶–-ûöd¦ÎN&Íʲb/×’íÒ¦dëâ¼UCú¸ûµù¾{½®â¦ô• fííxXBÓI&¸„&Ûœ‹¨Å7VÛ†õjF£…+(`‰13Àh‘½0LL . _cú9°Ñ€ ÷/v4nµÄ“,Œ&޽ÕxVOîÜ»uØ“ý‡8‰8:Í8³Q;”€ù„†xB®`-s$…ŽzŠ)E…6´ß|èϽ ƒS»q„ʽ’=y7RüàÍ‹u뫼›bÉì(´ôj!kr” ¿úü Ô8ÂPÿÆ,?(mR!Ù½1·¿7<Rˆ¼–5þº »¿ym.*ÞmÎ$P£éwB}È\ä%‰ãᥡFœîhÜ(å½z( ?=ÞQò º(5Yß‚/yו¼ìà÷é\õA·‡…^òó•U`i endstream endobj 361 0 obj << /Type /Page /Contents 362 0 R /Resources 360 0 R /MediaBox [0 0 612 792] /Parent 348 0 R /Annots [ 359 0 R ] >> endobj 359 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 619.838 315.546 630.747] /Subtype /Link /A << /S /GoTo /D (Spamming and security) >> >> endobj 363 0 obj << /D [361 0 R /XYZ 90 720 null] >> endobj 360 0 obj << /Font << /F51 5 0 R /F60 10 0 R >> /ProcSet [ /PDF /Text ] >> endobj 367 0 obj << /Length 2619 /Filter /FlateDecode >> stream xÚ•Y[oì¶~?¿Âo‘¬¢ u;o'Aƒ¶…¢h „–¸»ŒuÙŠ’ÿûÎ’vW†O`À"‡Cr8üæÂÙø!‚¿ø¡ŠŠ4 +U>ÔÝ—H¨/_bi€á°áøùéËO¿fñC…UTÅOÇíOÍÿƒ_Îú2™ññ¦i}<(•¿M²½aªînôfzLÊàí1)‚a|a¢3ã«­{<$QRdAž>þ÷éï_þò´H•%É'b#ÇÜEòagJäÎKÆ©b¹óÇC–' éã!ia–¶P$mƒ´ð¥…ÑEZñV5 »¤2ÞáéláPi’5xÑãêÑ>ÑËÀÓy`Ý@' Þ±=Ì2]÷Lu Qæ ´0¬ê†i¹@-—"7Enž6 ²%œµ•Y£é†IÆÿÅ èpD8ÜÎÖãàæp1ŸNO“®q1B¦ fgI:îMg#—žl/½ŒÂÀƒÀý•Õ5C(U&Ö¶l˜¬”<&ÀÄÙðV@ÈØœàkþ ô€U SØÏÓõ88'SÎÂqíaåfF¿¦©çI˜7v=¶¸ö]&ô»îØJ¼³{w“éÂ=ý‰g&/>6„çÙ¶“§ ³wî|$h¯2Ô‘…3õbBpCº‰¡ýÃwr_÷pÄØÌ²ÔãHŸL?íá(+ÂÜÃ艨@MCŠ?Í£‡@¥ÄXàRUopÃÂ<ô¤Á ¥c™t=ñ:#nñÙ*µ£' ’›®W«™ ¾pç>jð]0ŸŒ-¾ÿÍ W’‰0p¯(¦7Ã2 +æ™䯆M~#ÐÙ4¶ÓÞÌeTì8ûgíÀÌ*‹\ôgB36 hj‹+{F+Œ´:6$”Pû·]ŸQäa±z ºéä=î]w^†E²pÿz+@ï›x}ÒNx úÜ … p*H$ÃOT*XëêzN£^ÔM‰ jó]:5˜‚“X0mkX³«åæù”]£ ÈI—„_Ó¶2÷ (†`=]37Fç(0 ªcç69b«ýØ 7®õÒ|9åëóÛ Bd”šG+ÿ]Ä%˜AÛʺnÞ÷=kÔ`/‘o=G}Žè˜€aŒŸÛ†s±õº¡³$œd¾ÂA‚Â$ Œ=h  Pwë©›L» UFîÔŽ~+‰o÷XYÝYn– Gn]Fûj[s2”·D1E  ·âfÉXÙ¤J¦ð†Hè-ñ»IgiYË„"G€¼¾¡Ÿg'œÏ¬Ì»‹î:ØúûÍüMOõù; 0ºZoY²ˆ-¸ ’çc}—äfiFçQhhoøe°!òùY <ô²þ  Ér¾ÊÍš­9ÊäŒqˆ’{÷AäÂ× 8"~îb^ bÇ8šîÌDNŒ’0újÚépÜ œ‘`P,0À¥y535Õ€„úA† ¾ \ro’u¦ï±dEêŸÕ;.û&‡‡DŠ|åéDÏ«ýÚɬ•'Ø<6ØÒÊ“ˆãLÈoÁG–I‘èŸüPä~*Þ{ÅðÀú€U‘<`jøAÚêIæ †óµö…Ô±‡Ø$Ïáñ¿'{XM“ì³ùÇ lõûðÌ»K‚•] xº³X ¡Î8C®Ê0/ª+\uZ®]“Gøê¾Xz@›î'’DÄxü˜çoízEÐï´‡ù•æÁ¿Ë”õHãþÁ ëÖ LnÀ5R¡ æÆYËfâ½ÆÎ:gýΓpId¿CÜ5xÔZ¶\+s„ÁÉôÌ`e«ˆÐY|¹ Ôð#w–Ú²ìë‚G½ä/Û…t¿tÔ­?†a1Ä4½òÇ;¥¤è¶†”p é¯x9è‘HÇ¡'$×ܺZF€5¿Z–Uµ¬ækRÿ @2ˆB­ÏXòªnøA1 ŒÏ×f}åKµ˜¢6UÓBª¦êꩺ«š¦XAÚ3²OOÑ* óx±Fí65XµW?•Ý7/(àÛ>Ê`x‘r4nn—·)¼‰£òŸ¶_ž.ü®¹)ÆVX𻔈`v1¼á}_(­ªeiÍŸný¦c”P®¸föîò:FÎé¬e®š`kutÈAŽ®öÊÊ䨨 p+¥ð¯s©ÿ|£B¯¢`F•ÜqÒËIÀU4øKÍhúÚ0çM½¯¤z¬9ö¤zR%C?æwÈ£`‹~7ùÊAKyééJ-eºÜ?¬üÙ¶:ªª©Ímš&äྩÐÁøLoWliþüv™ÛönÃÍp•Où›¸bÄÄÂ…·ã4­1-÷ùe·•€Pú?xZÉAä2J¨·cbYêó(–†Y±ÚáÐup=˜Ö–‰d<”;”î™ü*ŽmÅjÍ¡¥È±¦Óà=®p‰NŸ S&$)W¥w‘ ‡Þ»‡²Ó8¾Î—·V.•¢f…r¹ÆJë$…”ŽLó¹±DŠJ¿Z®Ãà‰|Wške¹aÂÛ™ÃPâëLÉoÖýBVÖ‘ ¶™µÙÿ³¦l8!†Ü–¿|ÂU‚þ3ǶXŽi§ÝN“jjû­é‘å°¼÷éÏ. ç+ ñàщ¶'kãÊV–'çÊꌮ´‹]Ëï‰ÿ½Sœ endstream endobj 366 0 obj << /Type /Page /Contents 367 0 R /Resources 365 0 R /MediaBox [0 0 612 792] /Parent 348 0 R >> endobj 368 0 obj << /D [366 0 R /XYZ 90 720 null] >> endobj 369 0 obj << /D [366 0 R /XYZ 90 720 null] >> endobj 370 0 obj << /D [366 0 R /XYZ 90 614.386 null] >> endobj 371 0 obj << /D [366 0 R /XYZ 90 232.882 null] >> endobj 40 0 obj << /D [366 0 R /XYZ 90 207.108 null] >> endobj 365 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 374 0 obj << /Length 3138 /Filter /FlateDecode >> stream xÚ…ˎܸñ›5€[õ–6ÎÎ!ìÎ%H,Gbw £–zEÉãÎ×§^¤¤‹Zd‘,‹õ樇þÔC=IViùP_ÞE}y§¤u€ ‡ÕŒ?=½ûø×L=¨(¬¢J=<×(žš‡yúxˆ«,¯‚/GÓŸÚÞ<’$ ¾ÅøM‚§Ç2 æi[Ý=þ÷éïïþòä·ËâøèÁLP^¦¡JR&è<ØÉÂÞY´=~Ë`:·y}ŒË@ãÏ éúÐ< Ú‰Gk- †¾»1ȶ§§öt6×}à m_îǦA ]gjÁüŸH¥qdYæ¶&«Ç_Y0 á#œ^_{äpã ’Pe|Æ–Ž0Q•¼t‹g‰ã ^nFm{Áñ¹Óí®ðôð©‚ß®³=¿gÐH†YÍ£ ` :?3Ÿ¨}¥p¤¶?1ÄèÇÏŒ®îZãéWŽCÐç¾÷k€lnt¼cÍ2áO§øxë3$ÀÈÙwšG=µCÏ@[í•öŠƒSûMvHÜ ‰ÁˆéÕ}-}º)ø+ºî=·ùnÜ™ñÔEÐó†,÷ã8\–-vÎ1šË0‘>d5ã7DmÆ xnÏ·;C2)Ç@ ƒ2†D BµÐçã`Ãr¸È…ˆ f²" S·À^Ïî’'ßyÚ ß~„¤ðÒY¤YLÌ[©œYH]! «ô6…9YX¢ž?uv@D«gáÓ1FMW¢¾×q8úb¹×µ/ÄAÄ V ^[•«°ŒÐn0ç›pñ¼µH6Ý´×së…6ÀEcû<ÓA¹mè tCL€0  —E` G¶‡N—/BŒœ8ÄQæYºáWÃJ€d‰b¾gI bóûÜŽ†;?vN¦7#ë̤UXd¥gÀ0ìž?.Ãb9¿®kc-ãFžÓ†L½Ù M‚fK‚I³Î†ÇÛ%"C\¥}8²1Þ¡#Â…Œ÷Œ›ÙÍèQÝ~ÄÀ¤ˆá|j«`»D$a”8ÌÍT$"Bdê·=R*æI¾¢%U…Ð68¯òàëÄ@ô"øµ3 çõ¢~Dþ¥hðP¯{!·Øh0Ô‚eäë&Ú% þ…i˜y\6H*hºCÚNÌ‘* ó<ß2Ä›ì2 tÓ°=6©rQ±bAŸ4v9XUae‚ OMšzÜca™­µê=£v׉m2Û°ÿ œ‘õœ˜aûL*öŠSŒØJt‚e<9rGƒZ³=|ǹ¯ÌD¤j«aè/t‡®¤Àà#™ÐpWƒm°7øl˽-±°¨øŽàÔ;hé €W·¸ _óÝÔlL ãt—:õpËÑØ=¯¡-GNÞГ %bŽgK¾f°^îéaT„±Š½1°ç½[SE¨J?)6FU˜f[›M1œ¸öiAÏ$Éé¾Wl0¡OLÅ9»0Gö–$ï4©i6î-ØÖß\|³w̸(C•?ËÌò¹ñÞbƒ=ãX„eìM¨s¸B=\Qn®w¹KÀó€ÁY‹^-Jn_†Þ‚óÅ Ë+9\Ç¡CV ˆñ•µ†Íw}¹’Ê@gí›`EÛu(‰$‚Ú=‘²<ÛéuÎÂÂK{:»(Æ6>úš?WmíaO=ÿIöüsWDQó碙@3bt1pGÄyà¯.oòu$ê¡ «náÞEáý'k—UáÒYƒþnµdsH« 36õ(“FÊ< }úÍ=ïÖ³M‡¾ýŸièÌYðuÙãv‡—;©Æ#qË}ƒÒpœƒ N"Ìxqs\…mo„Üω¶W¼="ÅG$øD¦Ñ Ž5fB”=±2+s²\pÑ ¶{cË£$zfª¸³Jt†!Üóå˜ TK"•¢+âŒÜ§Ð æÈ –¶gåIì@î0ú@+’/b³C½yåþz©|T.Ȭ¾˜õ4”Á$ŠF¢êG).϶'-9x=È”‚k.¢œkb÷¬ÎÛg™„ÓߺŸWTü—ÞÜ„õ¶—Þ¥a’ûèÿ½Ðò³”srpªdU3g8ò„O«:I‘[`gŠuŽsÈØê@¼ îS)û`Ê 8´6¶dáhìi™…—NÁ*öXy•S^t‚—©FSRbU"‹¬Ùu q…Yµ¤…æ:ØvÆÛ÷ò(ŒcïÈ®7ÿÅÍh¨|ÂôÓifÝÁþêƒDC€®Œ‹²“ÍE;‹IÒ°Í©4HD±á.Û-3jàÞµÓ5ÊUG(W¥±¿¦³TO†y”å–¿ í©7²½C§‘íd_‡ÖQ »iZ”äݰ|U’ %•XÑ ®qoì7àœÿ¬P'Éj0Œz‘ÅC߃ÐV4K£m¸Ýö¡ü&.Õè Î4j¿²Ø’…ÞÑ»M¤Xkç,S{!=… '¨ÌªÖ‘KÅÇŒ†‡l QéÛ Ÿ-³švt%¤zrÈ唽´#7ÙAce,d#2~0B¶‚ЃxAøú¦Ÿ]  óØ\'d®ßz“·<†ƒ™q$Oª‡¹k¸)‚ƒóUò)É8,@õöè’«»š\êBÜz µFzó3¨ 0‘וÀ¾¬-Aš‹|£Èæ´ ‚ð†(Ò@šjîIcr CQde!•òì-3¸8œMº@(]U‹u†Îã’“¤ƒŽþ…ÛëXÆØó>¡±<¤.¯Ã†/…@Žg;c®¥yĉ¿D†ãÌ#Þ_šÜS#”w WÅÄöÝÉÑ`@xÿë\#â3¯Ôãaç€ÊÉS-•fHÕ/(ßzUAð¡@’Ò•ƒ{žZ)Ä—`RX=CµM€Ñ©*.> endobj 375 0 obj << /D [373 0 R /XYZ 90 720 null] >> endobj 376 0 obj << /D [373 0 R /XYZ 90 188.697 null] >> endobj 372 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F58 59 0 R /F31 46 0 R /F55 60 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 380 0 obj << /Length 2945 /Filter /FlateDecode >> stream xÚ½YYÜÆ~ׯ˜—@@Ãðh^~1$# cm Š÷’=3ŒxŒÙä®&¿>u5‡œ¥`;1¢…Àî꫺ú«sÂ]á®vYû…Êweû*êçW¡´0á°˜ñîáÕïÿ˜„»0ð‹ wÇåÕî£÷ÝY_F3ìq{é7ûƒR‰÷ÝÑt§º3LÕ]ÅÎŒû(÷ž÷QæõÃg&Z3<Õ¥±ûCDYâ¥ÉþÓß_ýáaæ*‰¢Ÿag¼à;w¹_¤©B¶Ã0÷ó]š+?ŒsÞ^Ͻ·‡Õ‰W‡©Ãƒá¾ùb]šÀÍ#8…– ¦íGsÀu ã ¹7®ÙGοð~®+ÓA“ÓÊ‹3`iÝY.ÉxöY“Àt$øŒ€°8¹™@yaL¯uÃôª¶„’t倖J’ž¢Ó#h“Ù ”Ó2hµº©ËºŸd`b¹ÑH}:Ëý±ûH|É‘ú±‘ˆ….*°õj­s$L…â] S!,d`¶°p‡ üÕÃYˆ`1e‰°Œ^«ï‹÷C’cÛ=%.ƒójë6“-ô–ÕGÅaš¾£5Íñ tRPÙ#9[¤ƒáÛ(h´¤ÔZˆ™fžÉä+·Ø LMÅÝ›Àqo8Îïù[õ_]•y›&œ…cÄÐç3“¤Ðp`¡y³šjöHäØ! àé.ºÑ)tœ"ÀS&IæýUNí;9‚u vÀ· ½fÿydépÆ3¾ùò&·‹¨H± V˜,K3R"ú9~ 0tt‹¦2x=ž@ˆŠÍ•)]omÍÂ’;Iö" Mó¥¶£œšÜ$waa!ŽÃÜ{7[/AÞ6x ¤s 8Ú­4CÇ#5li¹)€ h‚‡~Y(-.A†®Òîy ßÏYù`1l|ŒMER":IÛ6}* Ö¨(¼íE·-Hä5z@¦Ùž¿Ì8¶´ ʰ-0/uk„0Ïèܾ`Üàgîë ;+•&BßÙQó…€û\yðäqzï¹a!jViê'Bx Ž„èw÷bÆvàí&4Þ»À‰o?òcvß_àºE°ƒ€ }rî£rw9 5…â×OoxðBæ¶zÇaâ'*]Þ`#w³~æ÷›Ñ]ÄCt ïÀTrÇQ$;FØçùÊM“4òÞ Pyg)’ùzqè]·<7¢*óS—°íW0·Üº‹ûƒ92âAŸ Ö8Û-³¦ûl¬usÔc-q-)XĹ}kœ-†.YxØSsw©f*gK«^×-mpQ~G¡|œ²©Æo¡êžm9vñP¶†Ð)ýo‘ŠÚ¥~‘Å9E3Iâgi¶ACÀMû‡[²S¾‚Ld1‹¬nèý©ÎîH&&Î Sç4†¦ºqÄ­Å•±K–™åïé (6šš3ñÿi¡L¶²Ó?‚QL´…ð˾Æ7IÀQ1[H¸hH;_ܾHý8M–—¶.éZ]~f‰éù 2xHÐC?¡þUwL`ÌdyÂW6za&¶)&Z¦iÙ¤Ó[èÐ3SËcâ qÐX!¾XH0$kÜ´8{jÆš2ÇH¡y¯ñdH!Èh”5¥9Hé7ç3[BhßÒøœÓx$ÞR9Yùºã,’~‡}èÝÑú9I0CÓӅʶÛnº5gÐä oôâq!?ÊÃ|ù¸ñ/D6ÉP…~Læ"úp‡!œ‘Üp»v:îjþÌ‘N$Š9mÆDÉ&”‚óøbÇy0P"»:B9¥ƒñ­ó2^‚•Qb…zˆGîéå¡1¿|KÈBq•¢,’tGïË;ÈeÅCòŠoõ„ƒ`\»<:ŸfNâ9¶6ºú25&&ˆý“¹·ËuÀÖn`ea¥cŽ>èpä¤2Å^GJ¼ÜqÖ±á‰0à͹KÀsw&=Ÿk—‘c÷2ˆ•b&,Sµ³ÒØ9âÃCm Kì G+AæÜŠ{S'1OÀñ |ÀøŒšbè+!,Ö-Š~j™ÎÄU©hãF_¬Ûr+*Zb1’±ÝhJmWH*HmË ›i¨c¹PÞ;„s¸$›š?+)3i)OèÐáKö î IÊ@û’OP·W’íH¨í2Hrfw D›¸c[ÁX€Žtµ\cG»‘›Þªd¢ò§~³”—L“ÿ¦Ž÷<Ôå8êƤ¢¼Ù.Y).veRìRËŠ[ w–Õ®ÁœÀ¶KånŽU@Р TüÍÚ¶(ç#\Ès!HC*Ë0_ÊijUAÃÞóÙt®ò#kæJÞ³‚|rpH·ûAVP|nyœ= Ö¹fV7x¶”—Þ €ÜCæåCÞ£/Ã5s¼*žàdz§ÙRnÄÌÕc°"pL>XhÆT}û JŸé¯ÈÛ²d¤‹…‰Ó¹ &a`'‘R ‰_ϱnEÍr¨/nMéôQ£PW% p ƒ6<ŽFövuÖÔ«Œ­‘<þ ð•Îlˆ[7Î×uÆHIÚ•\o‰îê&ÍŠ„oOZÞü·®(Àú¹¹+oêÎ2‡ºùWpvvÖ-=Tͬ¦ŒÐ˳sÐlHy/Î7ùØÙ㣾mT’Óµ·F瘊ûÍ–®Oª6é-S)2vÏ\Š2²9CÚJ,Ӟџ C¨]0ѯ2wz€ÛÔ#²•@ÊÂJPŸS´"#Oˆ£ækÓÃ/ýB˜lh#kùŠ­ =.1àHoçㄦŸéÃu5G«Þml¹ñ¯þ‘"—\¢W ÝKi·< w!ƒ Ô”¡§S5?’~ZÖ°BÀq@•Ÿ‚]dÐ+?.òÝ3Mj!˜Sðmvï_ý«?«<;ñó4Ìg~¦ÔªÌ-~$-ü £\, ç„JªvÇJÒh Š©JóšÛ¶w….5{hý1Xàï_Hß_Çsß½–˜+"iغ¬‡r²ß¾Ì!ÂRî'I¶ªüï|ËÙÿ¦ãߘiüÉìlæÌx·,£þÖè?½s endstream endobj 379 0 obj << /Type /Page /Contents 380 0 R /Resources 378 0 R /MediaBox [0 0 612 792] /Parent 382 0 R /Annots [ 377 0 R ] >> endobj 377 0 obj << /Type /Annot /Border [0 0 0] /Rect [90 463.836 315.546 474.746] /Subtype /Link /A << /S /GoTo /D (Spamming and security) >> >> endobj 381 0 obj << /D [379 0 R /XYZ 90 720 null] >> endobj 364 0 obj << /D [379 0 R /XYZ 90 454.799 null] >> endobj 378 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F58 59 0 R /F52 19 0 R /F60 10 0 R /F72 4 0 R /F4 254 0 R /F2 255 0 R >> /ProcSet [ /PDF /Text ] >> endobj 385 0 obj << /Length 1827 /Filter /FlateDecode >> stream xÚµXYÛ6~ß_¡·Ê@ÄðÒU išé[Q¿I€*6m ÑáHrv÷ßw†3’¥]µÙÅkrø‘3œ‹3R„?ä2H¹Í‚]}#™úñFñ(@4Cüº½yþ:V’"—¹ ¶‡ùÛ}ð6L’M¤ó8É××ËÆm"cløY㯠·›Ì„—¡íÊ¢Ú¼ßþ~ój;±‹µþ‚<ˆø²@If…2–Nۉ¬IÂûÎÂöB“]ÑРŠŽ½ûŒ×hš®`Mž»î–…;×÷®ç-e½Ñix©8O…€TÈB…=Ž*Üð¶Ní… 'W3‡®èOes¤YÙ ÿ¡EÅÀ…#e„Šé®ØáÚ €2 [8¡›(I’ð%IåîÊ~ “0“f$yJ’£`=Ñ‹ŽEÕ·#”•@¢¸=‘][Óhèî'.oÚó/HEƒ¾¨Ýâj4†ßk`9Я߃¿FÀµ¬™öNÆòÖ‹Có]QUã¶²'ôߣ¶Ï0(jÕÀå'˜ÁvZŠmþ…~‡Æ§c´ šoèÜVÌùy¦íĪ9ö,õ¯loIœOfY¹ìDzٓӷú0H7”mCó’I0.ZðÆO×ìÜÏxöó׉œ{y‘–"5ÌîT)A—¡´Hâ„ó¨­g•Ôún^j$ØQë°t{*GgéWî 5t©ö„=¸þy´ €Î¸¯ö%ˆMäadWýÀ$æc94‘6ݹã©EOw­Ã–Õ6|ãM!!ÂÈ7dØ´L"c!·8§Ø¼£­D)Ž…· /äî%Ÿ0z—‡jyæÞ”ˆ`•  †ºª8÷“X躿¹C©a5h?:AOöV4­) €”ÝwÍø›4R™€Äôõ懻×ÅÝÌüq6^4õ…¹¿(YP ìÅÑÍ!ý‰=`dµ’WmÇ*nø´W6=¦J¯ì‚dâvåú^ÓZKJ‚ËÚ¦ìO¤¹>¹9`ÊÍGpJ4¨ßckŒFŸñyÙ’€Í¬]ÚŒ“­dÙJ&TZÎì™âbp>D&{A\*‘ÀÿDH•äSþÑYFù½hq‚™Yg9DUœ@B¾à¡¸äJLö´v¬Ú˜åªêž(±W6"}rôN½—ÇFCóÙsrÅ"‹®p‰Q1:ßhñ¯ ·X1¿Š±©—PY—tD| ùõ¤µtvÏgh{ɹÁüZ=FÒ¼½&Ÿ®+÷¼‹·'3Ú¸ïÙðEÅB¡Qù$ÿâà¶+‡ïq®sô¥)ŽTpV 4;´X ›MîqA¿X‰H“ §#PD)ä"Otâ#<ËEf±ÖF›)ÀÍX1}šJ¢<yš±LDH¨‰Þ¾—ÁÖà"ÂäYpë‘u`Á­Æ}UðçÍT;-ÙÆ:&MüiVÛ‰¯\á+…Ês8^¢$þ/¾P *ÿJÍØÂ ÷%Ög(™ŠXÂYP¶iPŒçÊ.Ìo ·K.¬Â¤'…M¦7/–“Í>ß,Þ^QJf+d3¦i, Ħ¼fã¨l"°›l!aÄèofòêî\vîÅa€}Ì®„W"F?¼¢z¬~´TœÆßªÿ¥Ù¡d¶Z&›,®ÿÕÓ™›ôyÚC¾j-` 6&4æÕ”ûUúÕMY°¹“΂塋ú‘‘e]ï:“ƒêŒ‚°#°¡â“z±î¡,²©ÂÊ:ÅæÅc:ç¿fx¸§Q-\9Þ:Vr8Þ—˜ë\Ç5;–Œˆ÷MûõK°JJÓÀz'ð§aÉôËal¡µË"ÍŒ]&Å> endobj 386 0 obj << /D [384 0 R /XYZ 90 720 null] >> endobj 383 0 obj << /Font << /F51 5 0 R /F60 10 0 R /F54 16 0 R /F112 167 0 R /F31 46 0 R /F58 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 389 0 obj << /Length 2953 /Filter /FlateDecode >> stream xÚˎܸñ›5€[«÷coŽwl‚ °ƒ²Ì‘Ø#f$±#JžŒùöÔ‹j©-Û‹>¨X,‹Åb½:¾‹àßÕÑ]™¦aUwÍð*ìÓ«X œ6úðê‡?çñ]…uTÇwÎ[Ú»ï:u™õtJÓ4(~¼?eY¼;ëñÑŒš±jlõ|ŸTÁó}Rvzb¤ÓÓ'ÓhwJ¢¤Ìƒ¢¼ÿׇ¿¼úùÃ*Už$ß)¾#we0›ÝUÆiÆÂ¿u(CœíÄÀÜi~⬿ÆQUjfcGÝ_Ùê^]œnyàÌØhÔÝÝ)泞â4Œs>*Ÿ¬¨ƒ^¹™!*¼?åy¼7ƒéÕÔ¿ÜWYðfË*0B%Çh´‚º O0O" mgzA_&KTp³ Ø##?’Zµ{ÍCP PÌFø«3€q10 þ hõª%…7ì{åIŠ$ðm™H»ñõƒ”øRPÝYü2Âm©öÍvi[vìßW­¤‡te“˜'Æ·nÐ{p2/!É$_Ë’°Èo„·{#hÓdªÞ¨½a€ñÏvza’GЉÓ<,¢ÔK|ÿ÷C¸^·‡,’°®kOüš·‘’( ž!Ærtÿ ’”ž‰Ï˜ËB;µfT,gŠ¡hr>W­+/—¼;]‹/ª¨‹äž®ˆÂ"N½¼§¿)ŽÃ,Ï·gBÎÓ7¸&Y˜T+ÓÓhO½mž"óì–·8Ïmqƒ…]f- `ܳ™½[&™0E¯–%/®y‹/ƒblÿa™ylÐpŸUZÞTÞŸ;=Ê[X+ 1¶½õ¡÷,å4ýɨCS«Ó0­3¯æŒõ|{¤¶, Â7× Íü˜ùú˜ØYH>ÀÊû/aïØD5½ÿJþ¬Ê€#̹“0C× u­¥<0K“ÀB±  €$+cÅ€—ž—L–.-wÔøßLx·.NÈÜq“„#KBïiX!žé¬›OŠM&Ô2wv2Ÿ;A¼ i6 SÛk.ä¨Î$ß„|b("@Ñ0ÏTQ~™»BþÄÏ;B|ËXšh*‚Еg9˜j…âê}(ÔâˆxDW°o…Õ“ï™ ½bªQ?ó<û¨~à8A‘'6©q’Ý¥dˆ—¤ëÊL·ÇÕ’$!eLª/ªzíò@q†¾XŸÈ—ñ5ç^.Œ0#Å.bêQmŠ´8xí˜×O{Ï ðwŽú)UðÞ§¸v¦§Gд43”‡NÄ›„¤Qô¨»ãµPåxÿ»&Ü_¶WÐãžw‘‚=ó×;¿þ”ciSÜx–…ë²Â×ePLnž5$|T=•äæ©cƒ¦7W·‘RZ\H{ÅMû9ß•2Í´Œê­˜Ñu²5k³ZTmœ?ûNËW»ØbËâµÅ1F4\!.kZ.3ã¹SXRQÞ(mRžÎ C盲 ñÝõxZ¶°Lø¨eÏ uáõËo"nÛ‚e¸ƒ'ª¼e,ô®ùd{Fðª}ë0,ÌD]>êCqùˆä„xËsºˆ™„[³R?ncYI][óRßáB`2ÝZJÖrpHÏ­p%»Ü.ØZæmoàQÑóË"Z¿2ó´>F}¡æ š xKˆ­_«eI«•GÑCˆr9lÀm6„:Ežš™ N÷lqŽ·àÒ&9NáJ,@Û’"Nzm!†±HâW~_9ǯŸÀõöƒ0p=Iàb!€®îS4ÀÝ]ÊÝgÉÚad/îD®@N ×wšÛfxÓ4Ãá¾öcÜ®FÄ´ÈÙä ¬¡É'þ`U´L Ö6Y]J÷„§ìÕiEÞFÿÈ}4NÝöE囤Áô¾7”e%·^áÛŠJ±ò¤çÅuµ×@á¿(-„5gæEq$B,äOtœ¬ 6f0)ù˜¬'ùB1È×OV $Áè%øÒ|2b @±¥×5pÈ]d„ž;³†SŽXÞ$%XpˆoÔ…ký›oGËí$á!h G#[Š;AŒ|‡Íë/ã«Ï Ûî[õ5¥V¥÷3R7ÐÌû“½üÈ¢æ¶Z"Î7ŽÀpÎ_}»R+§†ÙdŽGÒA䨠kz…£U YD¾J¦¥Ù`«'Í:‡/;ºN-ÀäL¸jeÚio·Ç Ä~5 nRÁ¨¢” *¯"3vM–` ¢ øJ®»QÒ4—’ è t”,¼–x‹‡ˆ¿¥wñU°{c×azà˜ÚÝ£#5n`ÚµâpûwJÅÉ:î¥Ü“ûFœ÷¨QXq"ÒåÁØ(Çf{ž5æ×¸sêîÅúWxc¼âÏÞÖêzÛ½òÿÖûƒà* ÖÑÜŽõO¾xð‡åîºdÓÎg `Na ”ž½Ü®@Î ®íF\îÿÅ‹÷'4w„¥Ì|Ë@þŒ¶œn_:ÿÏ ,°Ð<¸7C}K2Mü8ç0Œ-ôËs½Gsc¬ü»˜‘ÍÊûÄÁÆáp‹˜?ø%³p~eçý?sɾý‰+7»Lä$åoêÿI6, endstream endobj 388 0 obj << /Type /Page /Contents 389 0 R /Resources 387 0 R /MediaBox [0 0 612 792] /Parent 382 0 R >> endobj 390 0 obj << /D [388 0 R /XYZ 90 720 null] >> endobj 391 0 obj << /D [388 0 R /XYZ 90 367.443 null] >> endobj 127 0 obj << /D [388 0 R /XYZ 90 217.817 null] >> endobj 387 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 394 0 obj << /Length 2277 /Filter /FlateDecode >> stream xÚXmkä8þ>¿"ì}ÒËïØ³Ã,—ãX6ËrÜœÒV§EÜvc©'“[ö¿o½Évwœ8i©T*•êå©’ÕUêªI®ª,‹›¼¾ÚÞ$B}|£d´†Í‚ㇻ7ï~,Ô•Jâ&iÔÕÝn)⮽úwTÖ×›´)Ê&ú¸3ýƒíÍõ&ËòèsŠ¿Ytw]gÑÉ£ÕÝõîþñæÓÝt\‘¦ßÐ9¾­PYç±ÊrVè8 QmsÆ]or•EO¶ëxÔž÷ÀTE†'ÎëÑ›–'º—Áó5ˆN—"œ=»gï5ò|Æ"ê ÇÚy˜ªˆ¥‘æ¥Îzß ÛÇŸå·_oJ°Òo{Ó£‰àê•Ūà ù=š4I£ß•_«htžçÛ~€pžFãOcïnpÄ=0ËV¯Ý£ãáÓÞnqϧj–îÌvÀ›#1H®X2¸³!‘ 2.=‘4Ù“9’ŒÆ-Ë+)¾Ó©ïÀ=ÈÓÌfÆÉ¹A‘âŒçj ¢ÀÿéÒÿJ©8«K8$ßî>uúèøØËX)ò¸lòÀЦgÑÃŽ “­œRq‘«°óÓ—£͇7ãÚ1e«¼yyŒø÷fÀçyÚD·=“ÀÜfÔÝ &SÙݹiЂ@¨âª:·ã“uèÇ¢ Ùø;Ûo°-“ #î;sp<ëì£X—¶í-ÅK©f? Ýí‡S'ûÙÇ0h­Ó÷Ý´S eJÊaÄ<Ùö¼p0DÛëÞº“îñ˜g9Åx¼«Aï #ˆG ”VƒÀ ŽQÆ ‰-ŠbTX‘ƒ¬’¢‚„ÝQŒWIt¤ œ³÷²£&^ÃŽ9Z£[ºMnCËz´&Èb{þíùþ ¬EÁñ‘× •¦å­·NÀãE‘/aK&¡8²2žå½9=Sá‚äüéZË$" ©ä0 zs© ®ü»Ž“é “ð1¥“ÝKd@~Ýóàžsy’b `l|ÌØë®¹;D¨áÀ7dÛAs ðÅ'­ T¼#+u°o¯aÅ-š"M‚©`¤;FYºŽc@N§·†'¯AEšBP!1?›ñûµ γ¸¨_ ¹N  „P  &ü³0-)ê÷<ú/\*ä†îöƒóoEÁ!ì?ÏV úÞ`íÒ㳸¾,â¦,ÎÒ㥣³Š‚ÎP´9D—Š/d7®•€&è Mn“•+v=Z‚$íXàZ2Àò2N`ºE‘€pÕ–÷…-ü§Þ£:p®>ŠܵOýš»Í³=yªÜIu^ãòÕå_4&³|`ÂïI‘lwèÓ–é—œ%sº:žz¬·4ºŸ¬ŽEȉ϶]ØbƒbRœ«nÌóèþä×nÄé™5¢I–Õ¨ Àc˜€§QHÐÚ”’Ì@çkÛ;^Õ¼0šÃà'¦)ú€aÇÙtL­nÇTÊ@Ãð(“)<–âêYÜÊU8à¸2dX®vV·iMN|ÂÈÑÖól‡¥–NÁè@°p8`¯-=Qûq~X¨ò„Ì,Çý/ôš ¯|XÀ~0¬³ý6˜oÇ„ú¹]©E„ ΔxÒE¼L+G !„lØk7c Ø¿è¸Ë„ê¸|¨‰[c,• àðqŽ-hž4ãÂl…3\/×Ç•©ð­ø—홡:Õ¤ŽicÆÈ*ÅòšåeŠ™`K§¥X ê-¸2>NAÍ÷¨Š(äå$%‹€Ú ¥Œë¦™¤ÄŠåÜöЖw]È ÃEúBÜ9p'S©äʯ4V iÏòxÂÞ(«IMZ ïea8p ÉIxçÏ}pIQ‚QoŒHñràh¬Ã‘fšDæèyÊù@zÌmAš¤à¡$ÎKñn%<°ÚËc óhè °Sš–;yŒe’TùܳÁØ=ƒn^Ÿ!'‡šµR9S«têß¿}‡v³[#³³YsˆJ`ÜLÍð[æÉÔU E­Ì‘ ŽðlRxÇ•dÝdR` ŸÜ L(Yœ:V\_5?Û¾^Ø>4¦Ïè’á$ÒN&¥ÎÑÿ¥e ¿êó[™Öz4µ{OÁÑĹ‚®0[ÀK™8þ€ìI‹ !oWI%¼LŽGÓ··»Ÿ†_NÛý?I3ÜüÝ+ÆÿŽ;‘´ Ë?Wý’>~áyu‘’ªæw7›E] ‘• rƒÐ°û¿ap›3è’JJPBC¨¸jE2%ªáÒ‡¸F~?Nµ¸¨ïSÓÃl”k º>‡Z†Yµ­t×Óq™pìÄoúüoì”_ØX8œÝƒ3îc×Àâ+@¹‘sÐ3òLú‰kMƒè¨ýê+žÚÍÔEzžÇy:½É$„ÄÍM%NjìE˜ú² jêðµƒ` ¦OÐjH ;†í¼»….lD‘ægË\€ _(ä˦)â:½xQq[«ûÓbˆ)@IŠ¥djI3?ŽUx¶%/: %M~‚ÍÕç¡ *×9†¥À²3ü ¦aý“)B“èï¿þ,ÇÛxpñ˜.§äͱulðá]üZ^DVáô²š/ ñT/æbƒw¯Uä*.Ãç9~‹×EíäÎzQ{ë’a¹®¦öw„ä¤ì®«O3iR·èÀZ¾Rʲ š–ü"ˆ_UJS5Gò[üT—ä‹[po «|ãœß<¸3Ä[ÇsF¶°H6ü$qy¼˜2|¹ ~»‘~6¶Æ­åäýæìÁvz´šÕ›³(E/4Ó0>Ø/•48Ü,ž¨¹¼G'¶lúâR…OB‚§_û4œöøì¡OžÏ<Ò#V8ˆr4}.SjüÀ"ðTÀg]“­‡‘ªTÜÌA„¯Tÿõ ªæˆ§ïÌ0X•ŸeqÙ4ÿg”žÝNÊ’…+h€þÕ#_Ö fE±Y^ø2.¡ 8bùÙå}øšÿ¨˜Q) endstream endobj 393 0 obj << /Type /Page /Contents 394 0 R /Resources 392 0 R /MediaBox [0 0 612 792] /Parent 382 0 R >> endobj 395 0 obj << /D [393 0 R /XYZ 90 720 null] >> endobj 126 0 obj << /D [393 0 R /XYZ 90 497.615 null] >> endobj 396 0 obj << /D [393 0 R /XYZ 90 466.93 null] >> endobj 397 0 obj << /D [393 0 R /XYZ 90 167.619 null] >> endobj 392 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F72 4 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 400 0 obj << /Length 1031 /Filter /FlateDecode >> stream xÚVKã6 ¾Ï¯È­6P{,K~íq]´=, 4{(ÚÕØÊØ˜Ø ,yÿ¾¤(9N6‹E‹DQ´ô‘üH†í2ø±]“í*ÎÓFÔ»v¼Ë¼öùŽy)ƒdcñqwÿ©`;–¥MÖ°Ýþ°½bßíþŒzy²jŽÎyT~ˆ!Šèá ¦§aR¤•SG¤lœ×ÑkœW‘žŸIiÔü2´ÊÄIžåU•Mü÷þ×»Ÿö+ª"Ï¿-¾Â]f¸k8,ve-RÆaÿ+c>ví#ËÓ²(àjgõQÛ Ú‹#"åE-F‘¶=JcH[EVÓz”àP©#íÕ„žÛyPæGД෷´½´tã;šè…Ô£ÄÝ;mÖ·l¯ÈÖÈ1<¯'Äõ´ÌÒzÚ"EßÀ‹„ñ”ä âË›¿"@úH yôB¯5$âm¸z`3íÎY¬1‹)¤Ò¸ïÿUX%.½TE/h®¦AM­¢ó×~hQÙÓÖ8‡É̬ïV. xsµ€yy¼rŽ‘wú@œå@îÁ:LO¨ œBHÁ¤ F\Í>1dâœ). ”xV$5KK^ýÁ«gÁkrV¡äL¡P´¯¨ÅxüÜç„6NXäóçá:!ÿÅÙô%®Èy>`€3ßâÌ›,-X€>|úåóo_ö¿ßrIiͪ`y;D\@•ÕµQù_bôG\s"&ÈC9ÑÉz™¥\°ðùâdn=ë´¬›`‡½èVP\/Æ“ží÷/Â"ÂR‡ZpIÎÄ&ÉpæÚÌJ>“¸œh½°b¹B ø =×Mà)œÚ½Ø-ø9ÖAŠ2-óËjXû®»h~¹¦„Î9E«Çѵ 0š•o©?!)—áxâJϰã`¬§o(6 }J8EQî’œÇÁø¬­¢ÀøV—‚b¦×æ ›aº:ýçV®/¡…¯Ih8Aºâu¸•²²N«|eøÛ‘ÜiZ'À)ì…(;ò71»(ÀŠm“¤s_sÉY“ÖYs™š~Óì fy$[½!ó…ëJg€ÙD¡fÕZíG‰`Mô¸X> endobj 401 0 obj << /D [399 0 R /XYZ 90 720 null] >> endobj 398 0 obj << /Font << /F51 5 0 R /F60 10 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 404 0 obj << /Length 1416 /Filter /FlateDecode >> stream xÚ½WmoÛ6þž_!t_d bH‘ÔK~XÓfh±+j Ú~P,:&"‰ž^’ØßI9V­®NZ "úx¼{øÜñxd…?ä4H9'¹È‚U}F½ôæŒùQ ÑÆ‹åÙù¥d£$§9 –ëCË2ø¦tŹLòðb­škݨEĹocüòp¹Èx8ô¦ÕEµø¼|söj¹w'ãø;xPãcq“<‰“ã$M¹ô‰2>:ú{o)—$O3«™ƒ&˜úø™%̽ (áyÜYÍ:qBDŒëªàÃÙû9—2ÎO“#¿tÆ/%,Ï–'°šý—_HÆÍø¡_΂ &Âî4#4—A’3’ÐÄy]™¦oMõ =C¨²Cu"˜¢bÛqÚUÑuªsÊÛHq–«÷ÌÚ "& K¼‰ØM•¦.t³€ÈÈð¹û|¢’Îø—Œ¤M¾|÷!rk£¦¨Õ „4!\ŠQŒ2Øf\~µ“u;4¦®‹¦<cGOf0e‚¤<}t«Voûóµ®Ô·0Õ"õŸì]°EÄÀQø‹“¼L¯Ê‘3ØGšOY{[|¹0M£V½6Mw {„ïR_t=ÔnE3ÔWªuc³vßµio”g¢,T^Ž·3b;â8’d,›rüzýª*¶*OÁ›À£{f{]«B]ëfègÎF[ÎD[Ä$–锾—ªÙ½(ʋʬnNcoçuQusÑsßgè&T‘)¿V•¹;âekêS 0–’Nµ÷òúà Î1#cŠcT)%’²cf*†:((ˆ{šSõv¨z½­Ôc°A.æPhÌTˆ)a¿›k€÷ÀÃÈ('2a“|:ïÛA=Í\]øp£·ªV¯w§À€¸ñ¼@eNR6Ùuk†m÷½{ÄÃþ •}±QkÝhÇä1„hæÒõÖ´ý‰ž.¡6ûõÆ}Ýúe­Á—]øû\·Esªû_˜9É’t á|Æ”'º¿Vðþ‰L•º…œ4íÎÚB•lŠæNWåªhËî|cº¯¬YÎ9œmùUxK¨ÿǞ㟶gö=C{Dz}ïÐÓ?ŸAÃ)æû‚ö*ÝÍe’àDн9Õ¬ÚÝvÖ"‡Ú.÷G +¹iŽ»@l%”ÛǶG/ƒ¾2…žhì<ãov¼¨™sñ“:Þ¯ý2ÏÉä‰ ZÀõqI8Ë}©S _ 4ì7vÀÂV­U äz9´r‹8 x'ØihiÜD©\£æª5J°ëA0ÕùÕªRµiØwd NÃåÆÏPQùñ :·bÄÂGzôÓ4,œè¯öØco81ÐúCõ}¤»JÀk,BÛÚuµR]ç~ëvT¨ S–†áÛÈ nº.ÐÑÎýp[‹ÞF9É!+8pêj# K…{mÔeoR†· ™„<î*w„ Þnþ mô Õ7îý¶Ã1bÃGÜþpÖz7q€>u#.œòHoñŸj4Ø«à»Á.Þ('h>JÕºŸÈýo/uÑ#òÈ>$XâÉ¿´$Bs†‹îts Ûe#q0˜¤â‚ä=ÅDA¬*v²ÀOÚº`ˆ ¿…×­âw¬^z¿Ü `qñ²bñççofS±ò9#R—à˜-™€vÜÉàâEfÛZw;(-ZÈdåÆxÃÙ=cënͯ„Ÿ$¼/º£“ÆÏW`¤rãn¸²Ž¦{´ž”3SÀ³>šd_+½^Uö¹`S8(€öÉàM²ð<œœ°ß½m+|%އ%Ý®F©€O+®tƒÏk²õªñVçÊ~nl.z礼‚‡q’û\‡5fÇ}Œ°¨þ ”K¨ endstream endobj 403 0 obj << /Type /Page /Contents 404 0 R /Resources 402 0 R /MediaBox [0 0 612 792] /Parent 382 0 R >> endobj 405 0 obj << /D [403 0 R /XYZ 90 720 null] >> endobj 402 0 obj << /Font << /F51 5 0 R /F112 167 0 R /F31 46 0 R /F58 59 0 R >> /ProcSet [ /PDF /Text ] >> endobj 408 0 obj << /Length 1293 /Filter /FlateDecode >> stream xÚ­WKÛ6¾ï¯0Ò‹IJ¨—ízH]$=êЦZ¢lb%R•¨Ýøßg†3Rlï h³{àpÈy3¢Å,‚1ÛD³U’„›t=+š«ˆ¹wW‚©\XœÜøm{µ¼ÍÄLDá&ÚˆÙ¶:U±-g7Ù:ÕÍI’ùõ|‘¦YpS)³×FWš’£Ü<^óxØîŽ˜½êîu¡úù"ŽâU¬ÄüŸíW¿o'¯²8~Åm¼ñºßù: E’’ßF)ôj%gií[pa¨BDZȺ>ÒA© ºÍ;Y€³ý¹h­Í³tÅG‡¹ ‚ä¢@vŠNÚZjC$ªUÿvkìqtRT˜ö°´ä›0–/U¶®-eR©Xˆ$XêNÎvGNó±Á´ï@$¿Ö²ÓÉóÓ2íõ=*UtcŠN|¼Àc¿‰éƒu4¨é Z²¥}öœO7pIGžpN‘wP½ }"…"¦É*ÌÇZÝÎ×I0P=Ò(øwµ¯‘W™Šà`{gdãíÂy°CÍG;Ê ý(á}N±Jš…(¤𛯂1Q1]œÔ .$ª3'ž` Ó#ña,¦8°"‚â(†®#,¡V±‚Â6„ ½#°Ê–ò¦Lé½–O®Õõ5Ê¢’¹ *Ûí•§óI¤TèžïDRðØ0†úÆžl‚÷Ü"'õâ \ÒikÐÅU€MÒéU#ñÅèoDUƒ)ü]Pퟶ£HcèÅt{¥à7æzwdg"tˆåÎÚx½7ñfóES½¥utÌñ^—c(Õ‘8,’÷تãƒ<(°WAj­<í4Ò{*gœˆ0ʳóz¢Ëؼ)$¼÷âÑ͆r‘Fш$1Û¸Ng8ð­9 Öð¤'\ÉFºpºý(=¶#¾‘eÍ#³rCg<@x‡vŽ£"ÍwÆ:…gÕæÿÂÞ³˜Ù¬‚FrÓ⺉ˆ]—…ìÊž¶)®ì’¾^Þ¨á€Ý¥ˆØQ¦wÒŠù+âû Yu¶!JÒÒÊÎéb¨%ë L_LZ}$TÇ$ÍJòäRßdÓÖ|ÈuñØKÄ ð–穇l®³ü\ç/ÿåoJs¦9ë9㉑ ¶,ØúB!5®’–éá7ÖTzOt¥)€Ç ŸbþŸbè̘í;;´ýµ?Ú„©Hù8¦ãϲïÊ~¢¢“¿Ò‚ÍN”Q߆~b ê»SE?ÍaöRæ:[?öX¼^”÷}?4ÚpÂon?~úüeûçy™JUil½—*qæOÕ æÆ6ŸQOæèÍò^vË‚ŸWË6°‘{eÜ›‹Ì]Ä´Ü!ÆŸÔ»únY[˜çËvØÁë!ôb1⟌Y6ÚÁóQdðä$ß`ƒzÀ×8à=Ìýh@ÊMm±ï¤qTE±×ðy€ïZ˜¬ã³Š}²N’’1øÀœfQéu±Q~øx;Šª@á Á¨Î-<Œ¡Œš`Þuã]^;Õ€øÊñžÜ瀋çÚêY@LÏãÓTÿèÄëØÏ.Ô*W,[q¨ô¼ õ´íkËö¸§ºn]{bìôc?M•†ž÷ê<_•kß=.‘9Z£žu ¢ˆêç2øvü‡> endobj 409 0 obj << /D [407 0 R /XYZ 90 720 null] >> endobj 406 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 413 0 obj << /Length 1246 /Filter /FlateDecode >> stream xÚVÝÛ6 ¿¿"ÀÌÅú°ßãn-p{h,}¶sl%ÖêX™dß!ÿýHQNâ]ŠëIÑüü‘1_¤ðÇeº(¤d¥Ú,êãC¥_x¤V °ºÑøaû°þñOY™–|±ÝßšØ6‹ß’B,W¢Ìò2yÚëþ`z½\I©’§L¶ËLÆÁ:SuË?¶?=¼ß^ÜeBüG<¨ñ& ÉVæ¹Âx¸,X.ÊE^H–Š‚ªúóã#z[pÅ8ÚœáöÛ§Ïþ¼ýe]ïÝØ3ßÕ’)®¢&'Íï™Yk¬ï,ëmÐZ)ÁdžÍ-~óþséÜa£!òkà|îf­‡zíµ{1µö¤µa9WÚYw¸¶,“ÅÜÛº³uÕ­÷Ã)èÌTÄTSeúüZ½ª¼gµ=¢6àBÝâb¥r¶IámèGšG?mß òMòüHg½ÇøbŒ§³·C4)nMrž1h{J¶Ü©fG;öCsÏ}V0QˆI÷Ø-xRÕËL$ðà‰öÑWàl?¸pvó@vg:O¹êt_u´„Î4 M†c  Ë¨Ò|ˆ,s $ãô£µLE;Y–@%Ç£&áÐVQJ~=‰»³éDšžîý¸CŸq˜˜FºÆÑ¢WÀª›BºúR‰=i´±·ŽÄUˆÿ¦: óæxêΤ¸»úÀG5zM€„óÞcìvgP!- ¼tVt4ò’šbë1¨4¿) [®”’ɯË"OìH¯øÖŽÝ2%ö`^¢iðMDÌëH²¬†–8lH|Å’G*nŒ¬–«k"éÏÇ ’Îô_<‹p“3h*ØH°,xθºÅº*Šä6"!¹ªÆa]ñÄ_Cuàzp>˜p±øñ5 Y;´Öц‹DÔqÄAGToäg? 1ñh±r:¾Ðm`=ðv¶ ðG ºbý:YæTC8wÁ¿ E#„­r)`ÑCŽ-D¯Ñ+Þ†©*1úȶૠO º0åÑGΡ‰®Œí}kNÑ ~à¥ý—ƒNç+¶ÂÇùöœ¾,C Í´‡×Z °rÄ€!1úI„E˜]9}´C¤c“8E3Só‚ŠC£–¡ýüÒ]Ž=ùªÃWƒ~këN.æP—Ð*©â„€ ³¡Yu˜à1R6ý¶\Ð+ËÙªø^@Œ²§ËÚÆaÆ…µ‚óatE78ØHh=ŠH&Áϵ®ÌÛŽQ{o;Èbx¥5(boEWä""qfßù²˜ÂÚ)aÍlÅ*³$X äwpä ²—páÊl*nF(¥Êf×ÍtØ®pÂŽÖ¸›ÏÔ•°ÁÃu£ÝÜæÕºÚŸ™„aíþö¦e4û$Kgc»mˆ¾ºè¸†‘õºb Q²×Õ0â0íž´ëÊGÉ©rCøiA†0‰ =®¼„Žô`é:¤@þ\œ4âkXé ‘7•ž›_Ùªi n„PqÅo`£@ ¢.Ú ÷‚k& FÅ€ðnZžGã½ ã¢u.kÅÐ${ ­ `D¤‰oWÄ7±Û np»AÿqäA Ì?ƒßÝKM³C€¦Jþ¼÷$êòa³ާ{ÉIë;6}iÿœÌ { endstream endobj 412 0 obj << /Type /Page /Contents 413 0 R /Resources 411 0 R /MediaBox [0 0 612 792] /Parent 410 0 R >> endobj 414 0 obj << /D [412 0 R /XYZ 90 720 null] >> endobj 411 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F54 16 0 R /F52 19 0 R /F53 18 0 R >> /ProcSet [ /PDF /Text ] >> endobj 417 0 obj << /Length 3406 /Filter /FlateDecode >> stream xÚ…Z[ë¶~?¿bߢ ²Ž$ëÚ—"9h€hQ´[ä¡)®DÛÌÊ’«ËÙ³E~|gæJ²­Ó`D‡äpî3Þè!¤¿è¡ òý~W&ÅCuþ*ôõC¤£'BxZa|ÿüáÛÒè! weXFχõÏõÿ‚'smÿø´ßïƒüOI’ÿ°ÕÔ»ñ1.‚w¬˜¶Æ :ØöèZûø'QL[öÿ~þó‡?=ÏD¤qü;T2Æ™yüå»8J%3+’]´O@fþø”f1öø n qyªÄÑ`&ŽHº}8q&ÎvEžé»»óeÂÓ,üƒs9“ nÀ×¼ÐK‹ ›FÌ/}7Újtí‘çy0ž,j3Ý"äКa~zL äóâš…¥´Ú<º~‡¡“»*gF×)Xypê†qØñÃø%Ñ~Ñóä%ß÷ÎþFéûc±¾!ì8Vªâ0xå í;&o<éúzÀÔôŠd&Âoyqt•Ü-Çìé±äWëÃPíqű¨ÔgÓqc? ãŽ5) žy_øÔÖ¶Fàцª;?m=Hå’D·raˆ¼Áò˜x¢ ^ c¬õU<~0‚§½ïm#/Nî2 ’¶"£7¾ÒSdÅ4 , ¹çe `|ÙÆkÛr•ežQ båïÔcЮîëú×Ç(̘Ôx0À3…€ý²ðá]—œ^ñvrŸzò;ºA÷(Ñ<¬ŒbóãóÀêÝ<Øš„˜ù,DÖžf¸z$Þˆ« ¹jŸ»èMÇ—¿ÁkŒ'±'½:x’šM³iÍÑžUÕ݈jéÈ¥±ŸoœÐ4L$’w ØÏÐÞ¤­<ØÁþÙ£$;2¢ØÛ¾KÂRÊ.‚Kù‰=ÊÉðÅy³'Oâoïü‚;‰Ê]«ýAXÄ2ÈáS-.†f¬šüU-Ä®áë'â—¼˜4ÊX:3;È6v}}9Aàd­`ƒ7û50~ÃÇð…6+U"q­ž ]¤Á‰<(¬Å©fK¥YØ+•ø Ë4†ôh¹µ0ÎÓsçÆ“Ñ}€¡êí[Íîf…oÔ2DÁÕ3Á¡ïκ.VA8É‚x7è iï8üö2ó|:³Ï¾×ÝQeO¶LRè–ǨZ€‡ÐÒÃYES˜Î~±X\oPÆÚ›N ë©­iysã 0ØsÎqg˜ÄYäêûù¦î°8 ¥)½öRZe¨-Ì„áô9ó¾i Ò¡Qí(ždÕÔŒ˜ÝÅUìÐ÷”\ÓB,“MùBÜúÆuå¹xŒ«fßw.ŠÓ`õhhÔÆɉ»u\%$232Ú¿2¯K:…„Þ0…%,P\–`%[ Ò¼zé•b¹ »ÐëÔ€ù¨÷a´çA'"x½ì/†]Iðk§˜/ìþ‚¸T@{&%¹×ȳ©9º¤1X&ƒ¾ˆ;4Ðý³óŠQ\ƒ¨§#JÀ€$åpÞ‰§¬§JqÓÐîŽôŽ"ŒüÎ_Hú ™£0¾i¾"¤ ˜šZ¯èš9ø®‰û=Í$:^{¦[ó}¶¸ÎdRðâ¨]±I%©xÒ„| bdù]¼Œa¾òÔ; (^ÕÑèWïEXÛÆŽ¶ÖÉ÷@2 3¢ë)³ë(ôZVoV\±ñ’Ú™fº°ÂÆðŽÂnÌ8ìϾ,\Öq‚ʹ#ñ[BÃ$c’;©QªjDó¿v=\ÊÑ=u¤·r"6´š¬ XãpcÚÙØ)…³· ñâ{e£]‡®gË, 8œ² ­KïÕ_0y!õaƒ¤§±âsv§ˆ¥Z©îºÀΆÁ‘˜Y’P4´@O}7O@7€±ÖI„kiÙ™xÎUf’üEvÛkò¾vyþÇE)-. ìe‚ƒ$Óz„‘í[x5Ò Ìã}®­ºž…ã€lïZ&ýHþ ÞA§žqI¡´wãÈBàÝ J'Zrz WIë•8,AÛm¾mñÛ)Ë •jΘŠ9ðN ãB±½ÑÚ…×Å£±¢÷º6zÝÔãÛv-ûº„XþÂ%]æô²Þþg"Ë©1s×$ø[GWi†·áñÜç”Rr‡¼0 >¹£k¼$éܤ‚¦¦úõ.ð”û•IB÷¤»¢ÌnÓ4ÊõÎ7ÖR$WùØRÜÌya2¿§²šªhåit]•,¦ùðÞ"½Ÿ»ið¢~²Jþ Iþey]t èMï°ù‘Oó+Wú¡E•aä8‡'¯ò·ëSC}+¾À ú¸jéGxÙ•Wy ¹â“ÆëÛNšÔ„[ï ¯ê“yw¨Ù(_ëÉ!»e¶µçuØO¢‚"±Šô)¦põÒ[ƒ+Ø£3„Ÿ§ÉM²Â“¹ø28NÞÄòr­Þð¬FšB'xTol&©ÓžP(†)›U%¯l;äÚ´G$!D“Çëí¹-`Kúz"gŸnñšÏé…÷ÿÎ1S£èn¹Dç\«da ö’ÚmHh¾!.Ö‰ž´JömôÍÉ GäXL5¸ËCmaä>šx÷á$y¦Ñ¬å5vÓIŽB }GL•óÒ‰Ø?³tú´á"–É¢ù\5“¯"%Ï窼ÝzÛ=›SydËÍ¡O‹ïHó¥4" wl‘f§ˆ{i~-±BáÑÂÍÎ<-–ÞE+, ˆ¥â¸ƒK6ɾkÀgvÞyJ‚—Fž§´ú«ie:›¥<ó$É!bhü‘b–åÄ8(½ÙŽˆ[fô“„Kè1Ÿ-’…àØ»¶&Uˆ3x8†!8',É!ÎY†øN^:=O,Ã÷ß@ªíßËIVù5[¥Ñœ­dYÐØ³:Kì4@fZ±ÑÂ¥™ Pš»óWº·“BI À\ AÕ‘ôäSŒ§½S+ Ê¥¦k_9Å}3KCØáÔn8ö„ÝH€¡îD½Yñuh<'l#±Æ§„ Ѽ‹`”¼}{òÐÑ4j`ºã¨gM-yÆž½0%Ñ\ °=Ѻœ+þì¶ œ©hŠÐ~dÐnê0½ ç%«ùfCor¿˜‚6L¶æ,M«.Kœ¬Š4šhƒsî"‰'ˆ‚G@¢u-L[I¦²ý‹‘r/þ!4V‡”Ü[ù†(¤`KtOdsÛ…!«úœ§”t!½V#fØÙ5 |žù3ÕæºK£gK×3I¤ÌÌ—~(Š”I,½šã«h¹'­˜Ç–/Ž IÎV V SsŸ×ç íÜ¢W{Ë_ ùΦšOðg|æD–Û}ÂÈO®—Œ]êôUë0ñéèpuÀ(‘aÆñ¿ï<|A€’_ú&ÍÈu³‚SÕViÒRC,ÑþØ^XËuå'W£a©Ùá Iâö'* _¨ð%ýá̼p“£«r€÷+t.§øxŸÖ©±šj¹8£*¢]% M†,?Î4©“U|ؤz{Ò¦«(ƒ“«u(Ž>‹–>ÙœB&’®ÅQðw3Š’‹F ÏT´ú¥ìà|×grCqz¤ZÆ~9 >ysÚ“Í/?[í©nEë'‰VmÕD:5À¢£9ÙæÈ;:˜˜‰ê93ê6`£JÐ`Š–d8÷J£›ŸMÔ?ê/Iè›™¾µ¯[‡ù´ U¢´ëtóK‚ô¦âàãòðRq‰&à՟Ĕ٪žõ?C•ÙmïLK^X€ÌØò/Utû®öþÞ†r\N&Ìq3ŽyA„ê,¸ÖpM¡Q~ýr•|ð ÒW¬[Ù>øNñ¾€†ÅÚUïT ¬Ïü_ý´À¢ûRù+µGùACÿ'çÇ1žæ endstream endobj 416 0 obj << /Type /Page /Contents 417 0 R /Resources 415 0 R /MediaBox [0 0 612 792] /Parent 410 0 R >> endobj 418 0 obj << /D [416 0 R /XYZ 90 720 null] >> endobj 419 0 obj << /D [416 0 R /XYZ 90 720 null] >> endobj 420 0 obj << /D [416 0 R /XYZ 90 591.065 null] >> endobj 415 0 obj << /Font << /F51 5 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 423 0 obj << /Length 3098 /Filter /FlateDecode >> stream xÚZÛŽãÆ}߯˜<-ÇðȼŠTòØ 8Ïc,‚8€{¨ÖˆŠ”»É]¿>Uuª›”F »«««ou9UÚì.¥ÙÝ.½«‹b³+›»öô!UêˇL[Äð°âøîñÃ7?TÙ]–nvé.»{<¬E<îïþÔåýC¾«¶»ä;o¢ ÿåöèáA”jÜÀñBd^F|>ün“åŠ@¾³¨N•ÓöÉ#UbMBåkçþ8Hð$ÊÙg=‚(±x~„‰BA–¨H¨5Æ'yöŽ‚!ÇÛÝŽ]keç™Çqî÷`0=K¢eŽÉÁˆqÆ2Øþ–«ÙîZEŽžúä©èîËçÙ?Snñ04x帉®¶™%:ÝÍÀXLÓ:%ž×ÖA‘XqʆHTfÔ/bá½8?Ý4ÆGĤ2±¿v»? ~Üæžý6«•pTE£PÿÁ$ŽÎ¬·Må°u¥Ë÷©{>ŠCBלaò™´ Z´ŠÇ÷ Ýû›{‡Ég‚í^ÑÂ"ð¾Ô$ìˈï|Œr+ìbÇ]Úý()ª ³µ´%&S×´­=ëBq+³·‚¯Þ:xééÖa¦c7¼àÕwägè’³€IîB<ÓYk‰ºÖèx^ø/÷[ZåÛÞìïSø" èupг^@Û¦¯³mwîD H®è,QŸgR4å"éëç¶òž6zÃ@úî³'¯Óåe¹ó2@gÑS`Ç-:´Œ{&4Äyê éÐàáFÔ?ümG¾êßÑùm¶^Ð@˜Ä³) èN:áyE Á÷wž& `QJvÃsË8²Æ”K)€W™S@}ýüD»˜æIÇÁ?s®€ÖLèˆ6H÷õÿyé"zé,YàÌŸûâï¡Àµ+QþjÔ&äEi™îr iyŸÜ§1h-P°f(â ZT d¥ò ±|YnÄW’Ç­Ú“îG.KÆõ8×ïÃ(’ýö ÇËDyynœLܲ@¢&z„Öˆé2Ÿ¯ŽH׃z +ʪ‘]WÊ¡•UìG‘£¯V0(,ƒ}ÿ$_ÝéˆÞi±_¿ͨ PSîì…<y-ÒÇ-%0?!_N74 ó|2(ؾ›LĪ̦«éÃ0«Ñõ×93ƒõ#/Kw‚®'¿%ÿí _p2¬°É¯¢ü°H“<ðw°‚3Òc¦-¹"Xvfçä­8="‚4^Þ+´·MߦRn£Í‡Š«CB£áï Ká¤e îå6ÄâR«?ÜX-zFÀÀÜîf@”dÉ*0ÿ‘µ?Û*´ÞÅwó>äsmà@ ya£¦v,o›&òB™¦j¥j îˆät3Xà©x-ëØí ƒêËu›¸.T “ð+§ Õê¾ñ¶(1µâS5!n;…ý\›>\d„Zwš•¢êA”Ö0jzÁ<ºŒéûuí\ÂIªìu¨VK>ËëÂ%sö¬Þ ÖÇkA \µ_Ô­fu‹|H&gWØbÉ&æ‚N}^“+:).*ÛC#ÑiÒa³ßxTÍ…²X(M¹¨‹ ‰sM®›åp¸ºÜ@ÇõüŠR OG¼å¿Õcþýþ¡®Ò ”…cË‚•ÁY¥yÊ ·|£?§U†©„[Ôý•é³ï> endobj 424 0 obj << /D [422 0 R /XYZ 90 720 null] >> endobj 425 0 obj << /D [422 0 R /XYZ 90 542.321 null] >> endobj 426 0 obj << /D [422 0 R /XYZ 90 412.557 null] >> endobj 421 0 obj << /Font << /F51 5 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 429 0 obj << /Length 3166 /Filter /FlateDecode >> stream xÚ…Zmܶþî_qߢ rk½®vû¥p‚p&E}EP4ªÓrwKâF”|¾ßyf†’ö¬K`àDÉ!9œ—gfÜÅô/¹;Äwe–mùþ®nßÄJýô&ÑÖ=M¸_ÌøþáÍÛ÷Er—ÄÛC|HîNKÇ»ÿD?\ªë`úÍ}–eQù—Í}žÑGS½6é>z–‘ª;J£>™îl;³¹Oó$¥%Åæ¿{óãÃtˆ"Mÿ䔘ñ'ÇLâœFó»Ý>ß&Y.g}çi×#_Û¶8âȧ¡¾öƒi¿£ƒÆÉò 4ôd›FZæ3Öeñ„Žë?Iï×8Éà «3*ù\«~°UÓŸmïºVÚÄrwŸÈ5î“l›r ’+­)¢¶úÄ'ñÒ5UîEzçuZ¿I":Rù+ÊÈuÞ>6FO®—†˜M¹ Íyê¤ã‡j0[zÓ,>(?«ûuÄ×…=Lc+=6\§“ +ÁRJE¸»ý$œ7Žõ®‰\¶7­è°YžG­.Žïp‚©1s¢ï£º,ÝOFqµ,Ï¢~þç÷ïî½lÖ(/÷¸¹/vÑoA8õ “{óûhü ,*/Të¡ù.òÄó¼Ùç‘Rìg\c!§²ˆÞAQxÑ L:cŽ~índ–íYù;}|[ ©v×Ɉè’'ùÒ4i°xË…xeM=<=KCˆG\=²z•x'ýàzs”v£SDIy?]̪UBµÐƒjá®Å>úpº¹—\k¸ðÅŠ, _9/5êÊÈ–VB9šAõ–AÑ\´ÄæÐ꜒ù™•[cNJ»kOj{ ìM`iõÛÚóEÕ•9UçþKîjíÅ:qbl-Y–‹î™Þ«œ3}¢på,ÿÚØ Bå,hùR[lùö}™Þ‘Õ“n¥pdt‚t¿ÍóLNPns(n=lÈmô£dÑ­÷ñÛ$=È¢‡‹éað»CTIcOÞ£Uæžm¯­Ù³Ð¤ùr“,[lêbé´W/Tömô­]{Ùûƒ‰Ç­Ø…zè9wö`¯ëê~¬É ê.NÇîHª"ÊdZ0K2(Û}šÁ ʃè5,]FH q˜Úy0ò¤R¥²Ø«H¨qmªÚvg™­»ô2Ä!ÕJ‹ýÚˆ,©9®mÒRtÌ—kã,<ýŠB=.Cä0ˆ}R¥ò|4éRMÞÎ%sã¬Ç4¥u½Õt«Ó¨–Œ™âdòYz O,ËȰöÝMñf·-b}ƒ÷›}&Þ4Žé:é [q\FâôŸeè§÷¥Á²7½‡ÐØ0è;zºÙ7b/®5÷GÛ“áºÞ"aK4´ÙŒhj/ΉýuÁEùv73cöþÕàùt±!LfÅP7v“( PÏÎ%Ç"ý+âCô‘N+cÕQæWumê²½’ztíV†Å½åxq¶:´Ûêze…ÃÂå qŽdÖGPÂ7Šºid|*‹¥ÌæøYxáŒôq„¬þºT]w[¦‘7ì©F2#†s‹Ð•èÝBά›5] ÔPì2¸=ˆDh§›òùWîÅ6”Ç»¨jž°+è³ÚˆÇAã~ü­’ÅŠš9$£“'ÕÄ4ÈVù³ GãZyÖWõÐG¡Â/7&pRbÅÒ¨÷oE‰ªîlVv;VCµâËž,‰šÍ04-Ët+?;N "6ÜBô;‡È£8:5ßZ!ü1±¡É`=™ät·uö‹Ìj5Ú°Õ9羚AzóNÔý5.âudæH3öCº41sííg;älÔ±B#B†u¹šªx9 g6ÜÏ Ð <4u`°ÊBX¥9t®:¯ìw–~/FJÔÚ5  (!õ½;͈jšuê]+-2'ÝƒŽøÉ˱Y%ñí>žîÔej€ë:2æäš‡Ð2ÏáX­Yqa*y=9J½Øü¨ÁiþY^dbYq|¤›ªg#¦Q{’%z °ï•Ÿª¨PÅ… ,pV¹"5£x/Õ…ÆœÍZl'ïi¼¼& –Á=6  HöÑSò…aŽ4ýØ*/=6@|Ïné!…6vͼ¹Þ˜–6ÞÝ090†à?íá"ƾ‡}ò¹Bˆ\±“EÀ,€î å$’£îŒk©Ã¡š¾æË@úfø}vÈäõ¡P쩤ÅâÛË|Œ”¹íª^I„“Éà[éøqŠ…˜íåû–濽®f,AóŠ y¬·Šö‰$Ï —{N.S˜«%Ì‹.&Wg5tòÙ€Øt~ìtÞa%÷S”œô+i6wðdA®3k^XìU³t¡@Òè/Ù|кÁ÷ Æp:ïC]`¸ÜäùМ’ñ[(4\(1!ño zµÈ0ÑC=I§ÑšÀ-Þã*ÙaÆ™3I1ÖüòUt©cÄÇK“6ã8£˜ÉÉW‘ç>úĹ~ý¹½"hAm›$ º%JÓå\ t‚•NxÿðÝqö‘BP ®¨MÁ£zâu­3 "êž÷“{Æ£ï“èƒN¤\QgF>‡¥Y”‡…ª–š1o3h ÅãUG•óœî^ÞäGW> ]Üö~XQ*Í7ø8f:]àuˆæ4ŽÝ΂2»â$¸u¢jiG¨Áe¦ÁצAC1ªºrÅ›2°&ÛgãïGdÂÇ!Ë 5᜞õžn¥iê/;š«ù‹6jþ>V=é62«õRŹÍ—iݱiâd[¨eiô¦ƒ½žçͪŸxJ¸€ã3œCK’~z:•hS¦ŸJ_߯pÉ’:ï* ý„\øܾۗCy<áüÄ™;½Z™Zèvs°»²ŸJ©½¥\;SÊlKi¼RðOáÏH®í‚ ØìÄö„ìI‹k#u‡Xã ‘%Íe›Iãè%’žÂ¥$04uXÞ%Hˆ/¡[¿È×®ùº4.—ᇦ{xùºAå119H ý~¿ÑÍÒ “ÉTz’¨¡ æA>Šëkw3ýPqÕ…= ñçç ž±TØ%‹`ÓFi›ñÀ¨Ã‹úàD¾ü(AÝZÍðäªÞ:¡Wºn~/_T‰•?Pºd”i¼¼ü]ûf¡pe⟓ެRŠ…’BÒ aV"i3e”. OQúè¹Ö°;Í…ÍÌh·´o ƒ‰bžtÞîElyµfHáƒ41ßg¯j¦q;Gýª1i’ŠÕБP ÀŒÅy.˜™x{4çðƒ^H´ÐfÃ+€ÂgÙE!Yƪmµ”·ÖÃZò$Ÿ~*@»ê´Š†ßEzÒ5¦ØíwšPcZkªÎË$uV —wàîÑ ó*™ãéþ©öØP zy§Ê6âe»5Dð L:Š ‚)ÁøUa®ë „ûK‡fªX0ÿ²B$ÿ”% (‘tI±z äÒ#)BüÉ…_”´ÚsÝLy𢺳ޭ%D&ÄÁ……e¨›UÃm)ôè¶á??üf¸ôÔ endstream endobj 428 0 obj << /Type /Page /Contents 429 0 R /Resources 427 0 R /MediaBox [0 0 612 792] /Parent 410 0 R >> endobj 430 0 obj << /D [428 0 R /XYZ 90 720 null] >> endobj 431 0 obj << /D [428 0 R /XYZ 90 603.757 null] >> endobj 432 0 obj << /D [428 0 R /XYZ 90 286.463 null] >> endobj 427 0 obj << /Font << /F51 5 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 435 0 obj << /Length 2503 /Filter /FlateDecode >> stream xÚ…YÝã¶¿¿Âo§b¾lKäášæãŠ (zÛ‡¢ ®D[ÊJ¢KR·k |狲ì,°$‡Ãá gø›¡œnøK7U²9äy\å¦Þ%B}~—Jo ÛÇ_ß}øa—nÒ$®’*Ý<—"›Í¿£Ãþa›U»}}wÔã©õÃ6Ï‹èk†m=>”y4yc;Õ?üöø·wß?ÎÛí²ìOôAŽ?Q(M ˜-6û²ˆÓ¼`­[mA‘âEÃ6kå뇬ŒZ¦úÖL§6~Ø–ûtasŽÌó"̓Éé†ç½aÊ™§íÑØ)VÆ‹”_“´è¥ï­ÝQ[Ú.‹>x ›mÊlÓõì-a¾†[–F/àcŸO¶Ê> n4 û¡U˜Ãöv²)›® “~¡„°­ØÒçÁü"IÀ5J*KYhö½ãþŠøR<-¨íÐÙä7œóÜB ŽÆÏ|kÝQÖÏ[©ºž¬ª…LZC;Ï£AÑ/#Ä,}i˜Cž+öó y¨Ü3)ØðNZl÷ù!¢ô“UsšQ–¡"ØŽ` öBÕxÒ<Q—œ¾¢°Õ½"±mwvÿõ|Þp§ÁuÖÈ S:D¢àO- Àb·v† G€žEBM1ÒèÄdºöCç=`&žeÖÀ4ãÜÛÀ1–K¶ A“: ®SLKæd»÷ÁâG¾€I$×Vn;Óøö%ˈÅ´#$}À³ ’ûHD)cà1AÄ©7OªáfD¸9i)H<’AÐÑ’Dâ@¼R:ÌÖr9\Q­é’f[¬›ÎyÛ=M|àˆ­ÁS{aÂKË€ÚòpÐj [å¹G°ÄÝõd,Qmú"”—úY«é¡´fàžúH„@sÑaåšæX }L³Ÿ¬ô‚ÆHd¡wÅAä@û&B i™h€vrO…jHšPîŽu@QJÐÆsa³rÝ(¾0j[©œä·‘D>BŠ?2 jÈ€–à =+ã=¨<¡>ßA±ùÝZz[I£bUœfÕâVd°$f@§‘Ði¨5¶NÃuœ+¤ /°­µä}ðÙ1ùFô"¬ýž};Š>û‰D¨%ö Eqƒâ¬~ÁYª,H­¶Ó}ƒÚ¾ª«÷«<`x5y5“ @GªïœÝyb=l0ÁH œúæ¸ÚH „KìàjÇÅÃÛóCŠíÜ3œÊjΟdU6KÜ®EÐEÊe‘B¹EÑŽ”k<]çÁa°ÍËK*KpâEn-åR åiå:„0b…Cq#Â>Ÿ™Æí鿣AÕ.ú‡‚(·< ×q\O? -¢D[&¡<ª"ýêõèº9ý©á-ëiâšNâ>´^sñ |ò4) iÑÍ–GŠ›£~ [((P¨n*“›{ŽÌ\–­„”ªýDPw’äS¯Ç—Y “OÚs§¹Öã0ϸ )" “°–Ï0Ëq‚  mIqª1wé žÈ{9ÁOœ)8R®áHy}œ"¿Dq®^9ç’Ê¡7CŠÿ®µ0KAUø‚ÎPŸMB_Ä9¯<þ5Ù%NëëÂÛ\–ƇRL¹ÅÂuoƒ´ô#ãYžnJ8‡}p–—q–Þz½õ—³¦›*.À…Û 00 ;ö +ï­9nñÒn1z·ê U+½ùÈ b³"—•µŸ$vÙŽöá^:‡K³‡VY3nâ8^Cçí÷*aÏCœ¦ËÊ¥H31Œ`„½GÅdŠVÝOpÉ‹ššgrRçOÐ3†Î!ô9‡ ÞR~€:¸ˆ¼†§©POýBà.± €W뺈˜æ ÛEÀá‚]Íýåþ%7ã5V"U¿´\äG’]m»³ 8 º Œqk;™pì(»Þ^~zP ~Ú™ÌÈùà ¶Œþ¢è]ö;ìöÑ(»˜“öÊåYߦ½g‹•žÐ@vUV¸>¯.܇}v*èu­ãV×Á-ž¿‰¡¡rdˆ½~åûTÉyýîeýûàù%.Iºƒ$A~2»½ˆÌE2Ú#Vž¬x Õ*¹C4Pü¾Ñ«iï?“æ/.Ù-RÃÐë¾§š¬â(YÈ"@0–ÑhT.Þ­ާ©扷 ‰ä‚1Í1'<ƒù«®ŸkìŒj÷~ò˜TÙñê1>Å+ðƒ—½ˆ‹šÌˆap…®â€Âi…ƒA0ù–ô÷FíAα;ñ*Ó ÷Àµ|tÀ!Þøcׇ!yz •²<η ô/üäK`ö|0Ðï¯%1IpRùæwh?ðwBI¬×T9gRç!ùéR„LäÅ'Œ·õóÕ‹÷ßÏAâ$Y*÷s¨Ê­|rÄ éž"ÃTC5»¦3CÈÛËçRÎ_±cµÄŒ}sŽ=Ôà'¿\[=¿9Yiþ,ûêݪƟ(ìJ %É5εnv­eø-\†×ò'8Zô¼XòÅô€~²‚KèüøË??üÌñô*sîf,/Æ*ð Ü\àxGï·\^«YUòáªøÕt8 2:áDkõÀTª¤d|Uà' ŒÏ]=E‰ÈIŶ–åVv™Š5c²#¸Àé ÔžéWßmÍ$qÊqYÌ)¨~k´;3\r\é»rð>V4š¾3BÍ;£ÀŸHþŧì endstream endobj 434 0 obj << /Type /Page /Contents 435 0 R /Resources 433 0 R /MediaBox [0 0 612 792] /Parent 410 0 R >> endobj 436 0 obj << /D [434 0 R /XYZ 90 720 null] >> endobj 437 0 obj << /D [434 0 R /XYZ 90 481.682 null] >> endobj 433 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 440 0 obj << /Length 1828 /Filter /FlateDecode >> stream xÚ­XKoã6¾çW¸ØCå"Vô–µ‡évØ^ tsk‹‚‘hKµ$º¤´Žýñ—lÅqÒK$‡Ãræ›aÂE?á¢yûE²^”ÝM ÜÝM(Ô V3‰Ÿnî>¥á" ü"(ÂÅÃf®â¡Züî}¨Õ~Ðv¹ŠãØËß/WI’z_t9ÚfXFkïÈ3ª¯˜(7ºß6½^®¢$Œ`I¾üóá—›'#Ò(ú+Qâ…™y´?N²HÌÌÖ‰Æ ›™ûùr•f‘÷sãÔcÛô[0'OÅ. ¬Þ·ª<ñÙ Ë8ôøGYF^œU˜ùI,'ñ+:#Ïlð[xC- ·\…^³ ½‰=­FÊ *Ûó9 ªÕÿŒºG=äò&)Ùõ¾pÚ#ØÀ¬“¡s'؇C3ÀyÆ î Lê=8fj<ïµGópvpnÄ/M »ÆižPÌvG7èKbïó$+a}Ë¢Õ,ÊÎ+aç¤ÕLS(hÕ‹ V÷ªù܃³¹r xq˜B?øåF.’*9g—ÓÃÀZ`Ð Ž‰=”¶àŠkLÏk&mYøÝq¸XûE–%Ü]iƒ±¿žr]6}OÆ~&‹UùéHóï®Yýò.J1˜’Û?òh¯†²Ö×nì¤m¾…3­²{¶!ÙîntöÎìuhú»GøÝ•û«TmóhÕ ¯YøÊÓošíh__‚¢ª‚[Œi¯J顼³eäWw_Š¢Z!òª:°ðN?í­vÚ~å]WW„¨ŸÄ¼±p~Bwíªšý*öc?ﯜ,ÙåÆÊhëÞôn&s ~«$òƒ¢€½3¿€/-¼o‡ÚŒ[L¤"@XsLM_%¶ùÚ¨ëÂëÔ0ZÈcHŸ$H9QrÈngßp1ߊ(U""•®Dt¹âRÕXÈcx‡ˆ5Qj÷Š* O,N#5s<;P^"föBþºc‡–IsÒ6Pz¨ƒ)€îÝiä]Hë‚h×ñøäßKø¦ˆx«fGÐÅ©\ìÜ«[Êé·oóª’øy°¾RU±@Í.!LoõãwƒG"aÀ[’C.!²`fúñ«ÕÆÍeÁ 5ø_”c©#ùIš'Ñú¶~ª‘³5×j`ùÙ:}^(páõSÙ*¨HÜq£Sv‡!×>u/zSÝ ¨ÇÉz^ê` L`ýç ³Ø: fÇÇŒkél2¾\æîûáÃyO*Í…ê销äSºe,<ï-·táÆéváÕÃP ¥Fž^ü.D? ð±Ä±fxe…žEâw1ÅÙsé©ä¦žÙ-ÓÌS|KPàFÃ}®9ö`a­ö‚Ät¨ÈÞoø¿ a?Â#EZ*ã~/ÛÆý8˜ã>Œ(tàK!yËôw ¤g‰ Ð@²â¿w 1T;BvQŽ >Q’G‘¼Û‘M ´ªÜd‘p­[1Ú/¼xL ŸÊ‹«b‹±g¨´½ÛÐI#Ð>ë}ÞzJ}‘¹åáÜJz_±•H TŽIL!Í$§ÏUýóWxåÅ…ÿ§ù0:ät endstream endobj 439 0 obj << /Type /Page /Contents 440 0 R /Resources 438 0 R /MediaBox [0 0 612 792] /Parent 443 0 R >> endobj 441 0 obj << /D [439 0 R /XYZ 90 720 null] >> endobj 442 0 obj << /D [439 0 R /XYZ 90 720 null] >> endobj 438 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 446 0 obj << /Length 1635 /Filter /FlateDecode >> stream xÚÙŽ7ì}¿ÂÙ²FsÀâ%Šäål0_6XLó¢He5¨»« Sï¯2†F 0:‘xµ¼¿fƒl’.&‹l°\ŸªX6ƒß“y5å‹él‘¼^K}§´ŽŠ¢Lr\‹d9¬Š$xc•h‡,ºz³<7ÍóÏØƒO *²A•.f³íÉÊ<-ŠÙ`V•iV”dÔó!ìœ&¿ç 2kZýF:IàNµ-3u»'hÅ<tÏ:ìc•BµïP-¸&Ž 2åììÐUà3×­êÿ0™N¶ÖÔì8#ªrŸœÖ«ôÁNê4Mû£røŽxÖ88;M7v]ºRzü jáUoíè{Z£T¨WGö©ÕÙeUlv6“¢ lOÆÓÉ1rº;;>‘C…£EZfS6µ¶J‡Ç—/#ÿ”ýõöŸ±Aݧ 9*æi±€4ÉaÏIÿÏJßCþeó¤ZÜÉNêa^%žhø"«AèVX¯êÐ ‹y€”àä:´¯¥ðÁJB0p­9×Óá¨,É+Þ· ÞÇ/ˆ„àÞˆß_Ô>ˆNˆ!ËJHéÖ"ͦ3 ™W“Äí—ÀóEÒ¤%ú0ÉJŠ‚£BIEn’YŠäúPŠ37ßË1FY¡âjù€:¤%zc¢ÈQùÞo”U$à4Ü Ý /ö(c8>É¡TÛ¶¸f1è€ö>"¼Û¨wmŸVkVSat1Ò¤ÒÎc¤@z¿@™ü¸&þÙé­Áb?![Â6PÀ7VçòŽÛ¤S`Î|äOÍîKÛG¬âþgt-IÆX¢xÔ¶S=ù ð ¿‘ó6ÀþQO<å©úÙR¦yÎ)þ<ÎK8ÜrÜÉg9gP×A7¢ÏzÑÑK-=†w;YCÓñýw F? ZW1ÿX­X…­<—°LW5kÞZõ Zy÷T ­¥K?)€cý ¯Št„B™ÁÆ5D0ëZʆE ­”:–y‚E_dämÉxÛ)ç°rˆj4­X-Z4*Á·êä9ˆYŸð†PA‹•õ±‘þúͯhó’…šåŒÝ_ê²;Ü%¬ŽÆW5’ :$y+;GÔò‚ô[‚ÖÃŒsDÒ– Õ#±:ÖZ›º]ãHŒŠj‹ Q*rVꤊM±Ôa äÚh6™S)¡1çÙ⌠[ ,ÕWU—\½%… 8wÖÄÊJô¹¤òsÄ­¡’cH€ügÌE¹/ˆtÚ%‹"Ü,¶ž0Ί’³4ïÐwcížPAil‚¿¹äد©äâ>.Q(­Ø½b•B#¦–p`s–ÇhB•¯Tô ëž5ƶ[ÂIR«J9Z›ØÛ ž³s/éÆ;›x`šNæpß•é¬âf°†ŠsÇÛ¶<¿mŸD6=½™¡3œ°NoîxábfùØR¦e¼N§<í´´·ÖmàZƒÂº]«GôóÒ|úB¯0›L¾ZáèÌLöé[]*2gºÛÙñüow&FçKU=™[`p,çßñ}¼³gØ*¤ hG¥•Ïæ§×:0äc-[GðInZ’5X’Äô\཰êWM¢1cã¡®VŠ@j|P£hªAa±R- Ô5ó"yÃ̧M½/-ùè¹Ñb_Éã±EEƒ ÚèQƒ7H€ˆ=ô^q ¾™ X ‡¦˜`uªãžd½8vEè:HƸððƒ4¿žvñEOCp`òkXïï'„KM=>! £¨3Ý`ÈßIJ#ä8cÒO[{Bi¶CÁí0 Î,.^OMú…Ý µþÇâ·” º¼áç˜I…eåáMÆÏ¶{Õà[釳—{÷?%¤¯ÇÔ-äßòì£êp›×p‡Jíáý Ýk£½Púð$»þîú³ïßKªž_ 4;CòãÅá‹½Ø _oøéˆc/ …ú$Ußþ²ö ÞCû8ýX^êŽùÓÙ.ö¶ÆÑõ%}Ÿ µ=BêÆšîú’­_¥fÝšívÝÿyðù‚ø endstream endobj 445 0 obj << /Type /Page /Contents 446 0 R /Resources 444 0 R /MediaBox [0 0 612 792] /Parent 443 0 R >> endobj 447 0 obj << /D [445 0 R /XYZ 90 720 null] >> endobj 444 0 obj << /Font << /F51 5 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 450 0 obj << /Length 979 /Filter /FlateDecode >> stream xÚµV[oÛ6~ϯ҇ʢE‰ºÈC¬À† 6Ðö–h‹¨n ©¸Á°ÿ¾Ã‹9‘ÓtØ`À<¤>~çJb/„öŠÐËâ$÷Êö"t«_.°“3Ä›‹õ‡{8DEX`o³›«ØTÞGÿ¶¦ƒbbÄqìgW«€Äÿ•£àjåþ£ýB»Ê åŽu{Þ±UÁ–bõyóóÅ›#‰$оÁR#^ÐŒ±—£"M‰f‰I†B{iNމ¥ú·>é¹=‰PX^%(ΰEnnï-ÆþAÐaª¹oL„•²ï>…˜ìGAï;·Hù[Àf>³“–vtÏ* aTòæÑÊÛÉ1Ä;=U0ònoÔå¢ú]i©TM£aR嘀3Œ!"©³Â°Ó¾×ñ•a³ CÝK…t°ˆÿk-bޝªfVØõ¢µ^;q/¸> ³SŸ½[A\ÍT¹ÖÚ%¢MÓìê§0 Ù×’ ÚgfØÐO ¿[^4îÇmÃK+K&xéLxáŒ\²®Ÿ6Wzsw·¤”wh§† @˜CIYkH”ž*š7±ü*ö ½èé`3dzûJÛ¡a¨{»ÿî×Û›s¬Ë§Ýú›µ1»Cü‰ñÛ6/™Ù ÕBEèÔóšJ+¨ÞŽ£t>øéþè ¾ì‰Áêr\p”£¸@yNæy6OÐbã%ilËÀQÖçeæN@“¹Ñ¹Ì­X÷ø”¸ÛѱQó¬û2ã4Ùβ›ÚÒcw$³¶“ŠK%øv<Öªv®-õžÚÂ4S»¾i:¶×Óc”'©ó‘ã^öÃã•1Š ÌTô̰µí6;Ý^8¦bR]?w™V„q„Š,9M¾¶¯ØuJÈbbB¹0q=µ'ÛΖ”,𙵘ç„ì'Ë(Ci9eÿ†ÐˈÆ)ŠHrêÌãÇ;©àx?âS95S ¤cu¯dæ\#«¸2æÚEÐvãô4HÍ’â®Ì_…àšÚ-UËõ_è—©YÂIö~Gi®"SÙåà> Sø‹M÷764´d7Mc±—ëQеÜòní:í%d8Cÿ®ê Óô%m, NÈB,^׬X£­½´ßþ[ÝúåÿÃZ4=”è›YKaD7Œ\Ì êK>óäûŽ6×õ8¼ýdYþtŸ™Ù¡æÇ6¤§ZvÀª·c×+'0SZGÝ“·öAe'‚µ¦&Œ‡ ê÷ ^!B·X.‚½—“ú‰W'xC})Ö³Ã<­tÂ5}5=9ÿÃëq endstream endobj 449 0 obj << /Type /Page /Contents 450 0 R /Resources 448 0 R /MediaBox [0 0 612 792] /Parent 443 0 R >> endobj 451 0 obj << /D [449 0 R /XYZ 90 720 null] >> endobj 448 0 obj << /Font << /F51 5 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 454 0 obj << /Length 1339 /Filter /FlateDecode >> stream xÚ¥WKÛ6¾ï¯0¶‡Ê@,ëA½¤‡nv‘mº@ôÐô@K´E¬D9$•Ý èï ‡rì¬Ñ*|àp4/g¾1ãE¿xQE‹"MÊ•‹º¿Š<÷á*öÔ V'?n®ÖwY¼ˆ£°Šªx±ÙšØ4‹?‚2Z®’*Ë«àf'Ô^*±\¥) >%¸¦ÁfY¦Áh-y·üsóóÕíæè.K’ÿˆ%ž”Æ‹2¬òœa\tú72×wE²ˆY˜²½|þÙ÷̵›Ú×P¯Q6¥óU‹éÁ®ÄbäÚ^“^)ƒ¾X5­èºW;¸‰‹9¸~Ršþ€€¯lvCÍ;²ŠRhÕý1xfôë†]%i˜àiàŢcÓBtÌ¤Ž»8tóøÅ×Yÿh1×YxQÈ—~5í0v Ñj°$–‰ÃitCõçôè|d Ï;€»ÚkÞ‡.Cx‹cçy:†/Á‰j…žxæÜ ˜³¢ö¡ò=t¶ñ›ŸîÞy®µ¼ÆºzÀ"Ïá®Þß3ȇ¶#þCìq»æõF1FïJ‹£ÔÇó^¸Yú”•V¬ãÐÄr ëšà6.;¢Á²Ïâ`;Zb÷ƒñTãµFj±;ËRãÚýòÃíœ՜ȃ5ñ®V1¡8†Òz÷µ†J¸p’c‹çÈÀ´C,’©` |à«ëãðAÞE›­ÃAœxÌm'zâ©jqn ! t lWbÎp7˜£¨ÿˆ(Ö¹¹€ŠÂÔZ`˜™ £Üº í† ‚ å(ÀF„o‡y²›±Ç:Ù®¦VA&ÜíÁ"a¾¼€H)¼ bæ›ÐOœkL±oãžÛ2ùê‡ø" Ð³AÚ°Y»{¡WJLˆtĈpû¯0P„,õ|ò4x®@z6˜i[é¤%‘©ã‘¦ëHÙIõ¦ÓÜ‚Ê$Üf'¸n_J¼­²<=Ǫ¯ » ™Kä 6›¡ãZÞÏÞSŠØ?²^ê{Ÿc|^uóúvÊï¸Û9hZß½ýõž¨ƒ‡v€7_†Ó3óåÐ&­ endstream endobj 453 0 obj << /Type /Page /Contents 454 0 R /Resources 452 0 R /MediaBox [0 0 612 792] /Parent 443 0 R >> endobj 455 0 obj << /D [453 0 R /XYZ 90 720 null] >> endobj 456 0 obj << /D [453 0 R /XYZ 90 409.404 null] >> endobj 452 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 459 0 obj << /Length 1479 /Filter /FlateDecode >> stream xÚ]oÛ6ð=¿Âh_d`V$‘ú*à m·a0¬@3ìaÛ-ÑJôHªnþýîxTb§^» ¢ãñxß_ÎWüå«6[ÕŒ¥-oVÝx“EìýM¡ lÎ(ÞÜÝÜ~_æ«åýÜÃнjJP±NYu ŽÍyÒ™ù¨%ÁfOßt³ÖÑQÌW1€±³æ>L‘‡ݺ¨BöñU¬'ÄxBœ‘§•ð…ú‘>’ýì´!è­ÑZ¢n»z„ý ƒW69‡€qø²4/ɬ=<2H{RÓÄKš£xRSÄ“gùÃúcú=Ëùa¶Â+3½"^¤BѤM],yp´¦“ÎIÈWp•C&\dÄKÊ‚wA+„„÷¢»'ø›%ÈáEƒ|Zˆpž•ÙE„Ã5í·ÞÎòjÈ!Ôm]_†ünͬ@:<ÙËaÀÕj>Þ[)œ™¼!Z;O1Ä×Gr2 :3ŽT’pÍ"ǯódñ™ O qT£Äȸlb ê÷qí0¦À©Ã`2Þ„de¼>`{éeçI+8:€´$BÔ5¾UŽPÍÊLJnZƒ¼©“7³'d†ƒXcÁŠ^Màž.¢ÝÀ"„1$䉞]JÕñ“¯Yìf‰ƒ—öpàCž{iƒ+8»‡xèpÅèpÐÓù4(4ñËa7œ½Zég_`7+Êv"%aq(c[FÕ®ŒWE0j™jE›fu LiðHU$?a{3c©1Ô<ÁEDKwÍC˜UÊYÜ™_ëº)hÒBój¶5Dô|gÆ+(Óƒ££ûØÊ*JC‹m%Q‡††ò`Æ3ñg0âIQÂ)І<Ñ5ˆn8Î9=åíÓªŽ‚0TW’=t½cœ¼ÂÓÀoÉÓ SÇ3õ[εÂstÊlóäÚy/À™1Œ::Ñ"±´m@H-i/!K¢¸°7¢ Ùæ8îN8$´üxÍž%Œ´mR³¿¶WÂÏ2Õ§U“~¯ôãV ]·h/ë½Ó"tݳ½³¸¬Ï[ä°1»?!Íü~©Aì…†£éåÿ]i³æ4I»U¿ÑÊùkö,ü†Ø>C!B‰m÷ê#$çíIØ —­tùö72áÑM endstream endobj 458 0 obj << /Type /Page /Contents 459 0 R /Resources 457 0 R /MediaBox [0 0 612 792] /Parent 443 0 R >> endobj 460 0 obj << /D [458 0 R /XYZ 90 720 null] >> endobj 461 0 obj << /D [458 0 R /XYZ 90 238.762 null] >> endobj 457 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 464 0 obj << /Length 1620 /Filter /FlateDecode >> stream xÚ­WKÛ6¾çW¸è¡2`Ë¢žvòhE.1ÐCS4\‰’‰•Hƒ¤Ö»ÿ¾3Ê+'Nr) ˜äp8œÇ73[$ðc‹]²¨²,ÞåÛE=¼Hõþ ³50¬g¯/6ï ¶`I¼Kvlqhç"Íâïh›.×é®(wÑ›V¨N*±\gY=¤8fÑa¹Í¢Ñi#y¿üçðNjߗëŠ4ý‰>ÈñB[lã]Yæ¨Oš³˜mw‹r›Ç,ËI)Ù)mÄþÄFáµ n Väe`Pu?6·9±ˆÇŸ²ÔGQßÛqØMqkß>Ù^w{gF±ÑjÓòÞ¤m‘÷k¿®YVÆi^,ÖY—,# xqWD¼i¤“Z-Yd‰âtŠÕr³çF„4É#Xôè œä´õ9aVš¼þô–ÀvÞ P݉!0qÕÐä¼L· þžÂ–ni¸â„KTç=±f9Ä,G³bVhÂÅ«eZEoþ´´"5`ò|/`¨—÷xW8ññù=Y $>M¬îÄ#N ?ѽz0Þq+kb¨Q$‡ûp‘VÄ6Wð¸†»Í ­ÏÛ—µ+ð0‹¤Z¬Ó*Þ¥{uÏ­ľÈãÊïCœÓà„_—€ê"z+ZŸ+8ç4ø“4E½q¬GuÐý³¢Û­p£l&fÝ>دz‹Ô ´qP€§ÏÌâáÄUf:?ÉQH÷ÛÑždÍŽâƒýoE¸98¢'1 1A¨J1§²¼LB ¾XAêT1ÃÚR¦ðö‚ xU3K!“àUr ‹h×R5<ížtyREX.òÚý @VäñxÅ ¨ì]æû·±ùpávxcÐâìµèHÛ#Q½ûqâ‘tÇõ$ì鈶 ^[0P–UôÁOCj«~ *túf!K<8(i13 ¼i<Ñë·D¿´•ô{€*’FwhrŠi7çßajšÐe†xžÈI$ÍçNê–w ¢ðÅç7æ"q¦ÄFîIÕFB:Ãóûé–ÝgéÀÝiZRäÒt¤¶‚»Ñàó2Í·‘tD=KÄ82|z !Qi˜ºH™ ‡´ç$ɤ[Uc/ºŸÍÉ.:àó6ˆ7AE0H›æ«\œÞõèÿm0Ç×®à’j%<Çíq€a><´Kr.EÄãhÁ}øôB–CØøÈÁjó°Äbh6õ%Uð€÷=Œ¸ ú\waAÃÀš¿ŽBÝ ‰g*­—|-¶óÊT„ÔÈ|lm­1gœ<ü²2£²¼ Ïuøìè€ N† ë<0ÉÌ ·ÈA]ߟiIØ¥3 óЕ”*˜|ƒäk‰g:pÃHqÁ¶MƒšÔ‘Âi¨5¶:TW½´nEß(x&SÄ}T¥£ù¥Å¡0ß´PÜó*ÞêQœm>…Ôý$ŒO*L»¾ÿÌï ù|×ýCº©¢#´Ã‡ö»©¯@¤}Ë*äDòH¼þÉ)hȯÝÔxƒÚ¾›µ;øêxè?£ÅWØôÉýÜ2O endstream endobj 463 0 obj << /Type /Page /Contents 464 0 R /Resources 462 0 R /MediaBox [0 0 612 792] /Parent 443 0 R >> endobj 465 0 obj << /D [463 0 R /XYZ 90 720 null] >> endobj 466 0 obj << /D [463 0 R /XYZ 90 210.545 null] >> endobj 467 0 obj << /D [463 0 R /XYZ 90 79.203 null] >> endobj 462 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 470 0 obj << /Length 1978 /Filter /FlateDecode >> stream xÚ•XI㶾ϯ0’Cd`¬ÖB- “N$@æÒÁ^Þ–h‹i-%uÿ}j“,õ¸“¼î‹EªX¬å«¢ÃMÿáfl²8ö÷*ßÍ»@¸OïB¡v°a·Øñýã»»Ÿ’pþ>؇›ÇãRÄc¹ù¯÷Péó`ÜvDZ—}Øî”J¼ßL1:;l£Ü»ðŠnK&Š£iO¶5Û]¤Â(öòxû¿Ç_Þýø8+‘DÑ?h‰;¾R3‹6¡òc•F¢fš+?Œ«™ùa¸Ý%iäý6ög[ØnìA¡,ñþBU›V7¦GM^ß f~±˜Ï•iÍ3Þ ¯¬"¼>™veÞÀŒî Wƒõ¶ç¹æ¡´ÎCç.ÂE{ Ñšw*o¨\7ž*æ³Zý«Ý“;­ü$Ck÷ö•0õX!Þ„Tý,YwÜ*RßãÕco°åe›+O¦¨ŽCÂîâ4ñlÏ£®ûŽ©®åq¨ 5,€ÝÊèFùðعWD¿´º²ÿt¨o|ðU¼¿°$Úˆ—¢¥—TøIÕéªßÜòdâgQ6íðåÿ–4ˆ£ý?ã§~›V&.À* â mkÛ¨G`¨úÂTÖ+Ñ¡wd`—ÝУ6ûb³Àï+^¸Þ&Úɧ½©Ë®afáŒLɓÔnx„Ÿ=ÔFfÝè 6ï^yðͯRV}–ßÓ29öÀ ½’gWù!¬IÓ'Š9×3wèdt—%#ò*»1¢M©Û“qìØsvÝÉé†LçÞƒäSŽù„ë/x„v­l×J/04Çd²å•æˆ'úœ^ë¡êFPS,ÊB¯í! X§×΢§¡yèW0†Û÷£y\3Ÿ4ÅÅ[×ò=¥ ñp´þBù( VØÃÛ+[à}o^g]°;Íàíîì¬pÉÝÈfƒhpÑ@®Až=☂z€’®0®àò WÁŠP(âgÈot)úÇkÞótÊRškTöm×pM8à•¥Pœì3§Ѐ- SWCá\yæË€Þµ½$pnrŸ¦ “3Êý|õÅWq:›np]ýTô#(#¤s$Àþí-%¿…ŒæjváYQ™â©¿½]˜$X˜Ÿºöc}®ô§±ùÉÒQÈ=ÉL!œ '¼%¿ýq¾ô[BxТ('t=žOLTCS/N#J®j†âÖéךù‰cõæñ~# Ôî)êÉÅë‹}¤Q`›ÑFâ®G,*Ñ>¿3=ûœ§µí¦=e(L8Ãä°’)ŠVK3@ 3 AQÀézÚV"PA* Ò&–vô²< ã“„Vh‹p:­7ÚqÒ Ö¢wXI”‚1öÃDŒ‰þPAŒÊav"É8ÎôºÄc‘Š8¥|Ë)ßh:ç êš „ôµƒ0•ì$ŽP ©%®|9Á,ZçšWª>Ó$ö>–¥ÝÍÁ±¸Ï.Ñ 2N²uq‡ù àݳŸˆK˜g¦’ü’¸kBC×èÁº¦rŠ,©qÀ(¸MíH.¾žš‰0… ²ò…íW÷˜ ¢iÎét@™ãè†jKþ…¨˜°Šô/ÀðâO€2yyŸ-CXÅ èek¦ú3›”ý'Ìe_s£¥àhÍÓÙŸ@–"“Ì‚ÄCðF8²†IÔĨlixKÙ¡_ê@¼dÖ\"×áºÈ}¸¶qBk;0úàĶ EÃôª(ÃüŠî0yAë¡§ÒFܲ㑊0eñ³sdÒZâÆ}Ôà(ò€×ç½'ª•\vÅ5N¥ÖÜ9Í~Þ&ØçZy¯ànÔx}$A&U&»Qeö¾ Õº|†ü‚zðÐÆýJaqG7š¿¯"è÷þÿ‘’`úÏÔ“Pµ8ÛlfYˆ9“Vàž JU†‰äᲪ8䎋ñs¦çÇR×–\ô‡<ô%<*Ð'˜G’šI…-Lm,qó Á©–1“‹½ÞÀ›()P`E—öƒÐ‡>RW*0.©tK ïõ&ŠÃ]cÍ1ÂØ¹xíR˜âc·6Z^kãYÞÂÇùÁ,ù‹«/UGWÁ C‘,¾JŽ+Q«SgJnÞRJW´~cg’ûižÌO∟Ä!\±#ï©yó›ˆÇ-<œ=oclr)Ã24k[0öC‹ +—·žÏ)dÈôkÁ²gV™Ô•-쎮۸N œu… ƒ`6÷»ðªè™~m™¼AøâÚ]Ó”_fHQïU²Å«å32Îè¦_-ÞÂ<6ͽ_HØ‹n¢7˜ö®´ æ ‹ÓvîJ .sÈП¼zá‡4ïD1…=^˜£oÀÜRÃ{@c<ÑVúùØxÀ7È‚ÁÜ|aÌÂ2ƈH¿wX´e¡Ñåïÿ¾éþ—pø@ôØü~ußì*ð˜z ‡»¥4éàØ]KƒªDûõaw¸Î…äÚÅÍ}S&Ò½Âß-›€ÇGøùõ‡ü󋹇‚¸”±~]ÐΟ¥§Â†ÄÕMŒ´íw‚±ôò㦠oE ²„cÞñú¼Içgíî¦_Úî JûåAnÐt¥¹OƒàŠæîÞuºkÊéû£ýÖôÓÜ_[\L endstream endobj 469 0 obj << /Type /Page /Contents 470 0 R /Resources 468 0 R /MediaBox [0 0 612 792] /Parent 473 0 R >> endobj 471 0 obj << /D [469 0 R /XYZ 90 720 null] >> endobj 472 0 obj << /D [469 0 R /XYZ 90 280.348 null] >> endobj 468 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F52 19 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 476 0 obj << /Length 2564 /Filter /FlateDecode >> stream xÚYK“·¾ëWÐ僇U&=/rHWåàÈVE©ŠNëÊÁÎËIhçÁ3»ÚŸ¯%ÊJñ€FƒG?¾î³EŠ_¶Ø§‹ª(Öûr·8´oRå>½É”ZaÂj6ãïo~z·ÉYºÞ§ûlñpœ/ñP/þHvår•ï7Û}òöh»“ëìrUeòœS[$Ë]‘ŒCïi–ÿyøç›ß¦í6yþóÐŒo(KKŒ–‹í®\gE)§ζÃþY–Žæ:¯’A/®iˆÊ“Çe–Œ®©¥gd¸6ƒy4Á ³? ÷Ï4+å–ù.9[nžÂØý¾«u0¾ö+õúQ‡ôX¹.~ÐCÒùn–„¤«Ln¶ÊŠu¶‘‹Éæ¦;ÙõrU•Ûäáìp€oÍ ZíÆ‹ïèâÄ0%'¥Ç òîB¬ç•ûgºI£÷ºBó*쾋ԋÎDÉ¿~ÝèŽ| kdÉõ2X+ÓÓ¾øf©Þ)ÓKH¥ÌShd¥Cg ¶&*K†^8áÜó)uü"­\S6Ûäc\éÜû ë<óe}p}d=Ò*\|ò¦ t¸tC‡‹ÛŒM}ÿDt3 ã]w‚@î\iÀ§3¹F–׬Wë¢^k:è¨Ì“xlFD°X‰øÜÞ”Û·—q0n¥z^5O|Ô@èG¢DëŽNÔi»àD,7g—£÷¹³çÅYd{9ƒÚ[Ѝ”0Z+Ü©sdÛ¤Òhzi2¸Öêç½pŒto ?v¤ ޳~ò–ï^%O¸K »Œ Z"~§“V$Tî)áy “€’Ì#ùn¾Ù°Ywø¼÷­iÈ”‰y4M°d¤Ô-ʼn˜tO`!èÜúÑÎ9>—ÈŽN¤cgÝùŽ1<³ôhöK©qÞu˜ l½´•7®–®·†%ÖwQvk^n–í:Û*ÿ›Ü°“&DÛäbQÅ\FLpì3)ÂúWé’¢»8‡áÌžÒ4?R·JÇA&°$hB¸8ï”Éø Þá;ÀuAÚ®d˜$L ÑH¥¼ Œ:“Ñèk˜™nF§*ó„÷/SÙ©³¤>Ýè“0t‘hƒÖÂl4l´Ü–$³RWž­W²ySÀ8ŽÐa¼\qvX;Ÿ#SéЇβ@]œsîâÊ#Tª¦¤ZŠ¢t¢â(&è`DL…Ê/Ÿ®G"êÂ=ZUœ~îp&O ª±†ö|–{ο>÷Auät®‘-ë%aÙÉú>ê(­ìúÞ¥Þ³”³X Pë+E}½÷ÎÖÂ0jbYe<̆E XjO“yJüljx ƒm'f'TÝw?è¢Ç0LûWÏïlþ…_ ¨­ 0ž«Öʼá-D^–›)nÓ¥2¡­7Â8ô½± öh¡ïtúɸ. 2h„©W©Ñm5hý vhâËÙÉqô0¤«û@¹ÛƒXë† /âÈÀÊ€'Í¢«0XÔe4‘²¸æN4ØEÿ#ª2 ¼dšxiÔÍ9Ê€‘î£ëŒCAZ’†ï!_9M1³ Œj¦Š€äÎíDF”³œ­PWªcôÙÅ0K¼µ @ ½ y{1NÁWn ¢6­‰ÐìÚÖÖ–ß¼~÷UìåXW䈽Àƒïéäùö³FSÞÎŒí÷k¸ 2Ú²ÖWé(ÈJ©6XË0£ZV Zö`Ìì}S;qæO:‹Ü_^þ òçQ‘n"/£"q9*ŠMJêÂ2? œÍ´%pT¨{b*h¦DTòdï§wUN’/ÊmNE !¯ÖûBå_¡r ü1OÞ¹ÆþF»~â$‰òþü¶æHY}e±êcƒÜîZ3j€j'SFgÊ$¨#y-Q,´µ"évÇ—@Ã@‰äÓç^ø²híõˆÜŸ95/ãu=oOÆ×qOnŽ$"DÿÒH&'I×åVD+ÌÚQdÑKíÈÜÅJˆ8…OoöEò‹N¦$ÆøA:|ê]t’]žÀzb6úý<ì1çjÈüØO:0O‰¡n¾»ñblpƒÔ”Ût·Q•î(W¬JT¾fEY±(SÊ´8ú)Jé>éLçŽAdw :᪺‚ê4û*³®–yWEG-#UË@{˜²7ÉâY^àë‰W÷F×P£/²Ån½ßnK2Úb·Î38hŽj:Z.›ûÌŽ6ðì¿IC©²PiziN„ËD|¼œ„8m3}“Ýs·UÜm±ßONWŠÓ}[þÒ\ÎæÃØÒ¡þÒív×´j Û:ÖN9š;­Yú‹TG\¬7.·•q:%µìAyRðÓ,/¦Nýɨ3¤èN†R%Z¼\Fo¥dN…º» 3to>ÏØZÄd6´5×TôSÊpõÉâ&˜S·u¨;Õ;Šb=„‡ƒ«õêlJàÅÒ¡¶{œ*?##"ÒfgkÞºäPõ—(AÛx ~šYÑ©Œ—,§–y>˜av±Äö“tÖlíG}¡±|42wõÍTât5r)]ö™²Ž°Šo:‚ÚÒ‡ÏÍï¾+9Ýú­…Òšy…f»ÞæStT¨²™”Ðá:“ˆaz3aÆìÑG]-™/¿I¡'˜i-õ*ÍfbP 5Nt°Æ‹‰TuŒ_ WéLà^ ÝúNhÏ¢Àb0$…#íÜ5äÖš.«æà\´-É ¢Ý@4š ˆTèú”8)ÿ„ W“2V)`gúÿì7‚;¿Ú#£*Žƒy^Ï*€œñ’ÂU””5 p°äÛ Äe4Õó¨ «ô˜³“ŠÚë“ÂN ‹žžh¤¶¡ ó Åžuò‘Ÿï„e”:x©Ÿ4®ÄC¢ Xd’jÄè)÷BKÈÖoL<èµÑÝÛ{Þ>Š’ÙÞv ­óˬ¢G­X¯ ×Ë ?&‘íoÚ™:ìÈe¶q-?úa€Aüº×¾à:8ÃÄÁ*¶‘¸¾[®¶{Æ'¡1öûäh_„˜ÎA9Š¢+ÎI“Fÿì¦Ð†ÑUFÎ:¦e„†>é46V\’Ðãu®Â¡^ÓŸNâ‘ôAŒIz S/mÿõ¬¬Ñwɰ©¥ý¹6„•Ü|«eš ÝdݺF©o ”‹iáF¯­½¶RGï[r÷*_}j$údÒ0—ueò¾n8÷~¸ý,¦çýÓíä5»Õ+•Ù[}]ØÊëLÈ6ÇU|Q cˆlŽ£h)øQõX¨kúxÔa(SÍŠäíM.‰¢vgÛ\"åõóÇXZöý M=(2ÜÓÒÑÛÿ޳'ôŠ•W„& uõ«V3èØV ¦ÞKÅ[ÌŠh*®éêÏwÂ[¾[ïn³< > endobj 477 0 obj << /D [475 0 R /XYZ 90 720 null] >> endobj 478 0 obj << /D [475 0 R /XYZ 90 466.721 null] >> endobj 479 0 obj << /D [475 0 R /XYZ 90 358.684 null] >> endobj 480 0 obj << /D [475 0 R /XYZ 90 227.546 null] >> endobj 474 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 483 0 obj << /Length 1579 /Filter /FlateDecode >> stream xÚ¥]oÛ6ð=¿ÂË&³l}X²ä¡]W´ÖHlÃ@K´Ì†"=’JâÁ?~GÞIµÇ{ŠTwÇûâ}ñœŒfð/-g£2Ëâe¾UíÅŒ¨÷ A`˜p¼½»˜¾Ÿ'£d/gËdt·>TqW~~Þ°­ãf<ɲ,*¯Æ“<ŸG·¼êŒpãtíð„©jÍU#OÒ¬æ¬îém ekOÝCC,òÙ"Z­þáÿðÄ'+tzÎX¸D) ××È ÁíSä¡J« © áÀ6àh[ô£ d‘^wNp;¨S=$ˆ&û4 ÝËb2Ü’neÖœÂIœÍ©< [(”V„jÈrÐó54 þ-‚ †™•/£e˜ôÛ‡Ùx"¤Xú&ú … $¨4C§ ?8±†­‹&5¬˜1;¬5O…85ĸ¦€-­$Oi‡sŽÂcñ4<1p€ VNŒ/`?ñ—qšÒ²è3™ååàzîʯ‰.Û  ÖË0ú¢±Ü‡½FŠ^?;©‡x¹žMö*…¢“†õà+¢kÜl‘A!‹§‰çoÛÁæãÆ+™¥Øíðe5ÌûP'€Ðø¨ß‡}-@H?àË ‚X­n‰RaÔüX1½0šOI2¼a^1„²Aüå{ ö>iÇOm^ôÎd)%9‰ÞÞ¾CÂÁS¦Ü"²=^M¼ô6l"Idi¿I÷›t–ÄÉ"ãÁèå©h—iÙs°î锞¤ŒÓ2;«fg°×öj yoøß0¼Æ+†ˆú;q:¦Âö|Þ—y Óäùu¹½B³G¿C`ÿƒ%ÊÛ Dó w ®åI~¼H»Ó=í׆ó•­÷¶SùÕë{å-wŸC˜o~h\B¨.©>eÈSýüìWÃå Sû÷|µÿ•™ý›­ïnÓ)ø“û7]³¿åÛýçÊí?é‡ý;^]¾ê– ìTס> endobj 484 0 obj << /D [482 0 R /XYZ 90 720 null] >> endobj 481 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 487 0 obj << /Length 2363 /Filter /FlateDecode >> stream xÚµkã¶ñûýŠí¥@e Öêmiû\$)ЈïS’\‰¶••HW¢öñï;/Êò®šCp(X gÈáÌpž¾ø&‚ñMÝìÒ4¬²ò¦îßE‚}x ´… ÛÅŽoöïn¿Ëã›8 «¨Šoö‡%‹}sóKP›mRåE| BóÊÁ™»Í¶ˆŠ@ùÃíÊ Öã¨wO]Û^Îõv˜9(¹Hñ§Q›d¼ðÂv )lӄʳ‰Å|òÀÐ>7Û˜õÙÆi笜kÆ;¸Ë ÄîÄKu>³4jÓþÎ'åþפ¥vŒœìj{‚`iÆÔ£QƒD¹%9é†÷¢éÕ ƒ>NH¯H4ŠY%ý|àÞÖ¸%¯J¼•9¨PwSC |"ƒ†G4’[!ôÍÏßn/J'^F§ûñŠ{4ú ¦Îñâ,T{v`Ya‰:»aƒâ¯”`ZÒ Â*¹«°*`'my/;®/wÉÎïØªçU.YXBäþ›*LóÌïP­“&àI©ç¾=žÈí™f4ÙÎ2™%Uð»½gà`sµˆé•QGÝk#6B¥¿4"3àºî4å&§ó[FZX-̃˓ÂÅ#†¶ "&sü;,ó48ZÈ÷×Y+ ³Bl zû€b€?ü]ò‡%¥:}p²/{$ÓÉ™Ã`{¡QÅí †Î.ÝßkÏ…•N(ûÂÒgZ@¾Ù ƒÒΪ@vºv—P_(c¬ÙŠÅ,y·bÁݵË‹¹Ì` êäå2mÃ~˜/(œçÁH†q1ýd§AnÃD‡ß?}’œ¶wIák Pù[‚]–z±Zæ®4UükÏ_®#YQL#Æ`2B`´òmûs§1?Ç;БhTóɹâ§î;ÙEŽ1oG ~9>a¸àÆ®½Ç>Ba¤àúÏ®•Îh­oµ“JɈëPñù”Y¼):…o¹µá%•gNšHÒËœ1Lñ•–j?"&¶'‰s’lüÉ´Ïo%[mX{*}rܳfY|o¥ÿGMSôo.õ(çÉn é”»Drnë¥$Ô0N v¢^£È ?é AVN™íœ’œSšW Ãä&|-Jg’v ¶iV$èu4U‰‚»0†Y./’àk<9±ÞN¨Ï.¾ÛÿÄ€~VèckŽ‘ g©L‡-eûã4HSMÅ9…‘ð’8·ès¤ O9þj@ñÕ%vzÿ™ÚÛ÷™W­§HÄÁ©Ù.¥djÀ?¶Ç¶S4opAz;óZIjRÑø/"ù˜œQ8êâ³îü³&Œ_îÌdôßóẕ+”°¦ÑyþþÚ•çòW§‘ôW'½éKã|ŸZš¡£õ%ˆé›œ˜¼QÎ9zJ^•äq°gq"97•—Í~„ˆLNü ¼8×âØ€´ËŠj(x†–ÂØÄǰuÃYqI&Hô¹Sµ«™±%±GWÁL—ÁïÔY òÔHc—Â,1O™8¿,ÇzCa›ù×E®Peì0@çÌøxÓÓêSýå˜>1¶y±„ ½]¶Ì „*{î•ìY´±t˜0Œa}ØŽ‹Ž»yźí{Ý´©ÜëÆÞZBuüe£ç“HàÕ[Qäúõ>ο$çvÕ:)‘<úe€‡"Ú@ÀPv3É ¥vòóÀÞOû-¼¼=/y^†­ãËCÑÕðO“?m.w¿ME…R×Ö E)‚†2 ß{þ1ƒ½jRŒgÅ ß© 'úÍ %…&'ª> endobj 488 0 obj << /D [486 0 R /XYZ 90 720 null] >> endobj 489 0 obj << /D [486 0 R /XYZ 90 406.094 null] >> endobj 485 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F31 46 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 492 0 obj << /Length 826 /Filter /FlateDecode >> stream xÚ­VËŽÓ0ÝÏW ‹)çÙTŠ„@°@bEw€k;­ÕÄŽl‡™Î×cÇI'™fÚ‚P¥Ú©OÏ=÷‘{ œ@€“NE^¯Tßý¯‡;Ðï\ pGˆ›;ÿsxygSŽ)6Øù¾ø¸‡"béFQ´ÈÖK7Ž“Å7‚ZAÕ2\-Žö2l7¨$lGYºa Âh±Ê–?7_î>mN"’0¼¢Ò ÎdFÀYyyšÆF%+oå¤Yä¥Yl…–´"rmŒ9¹ƒØqCí•fêN%¯  rm±—YðöG¥jô|¢ß@)´SI˜,jŽI‘Ʊ}â…à\iA, R”³¢¤M)ëèuuDãô5j¹‡˜?Œ¨ã øÔM»Õé õ?_è}`DeŸiaU-5],„I¨$eegƱth&!B¼9Þ`“ž0Ÿ"î­ù¯ð@ìN¶¢ßUÒ®´_¡]”h¥"}ÁwÖöa{´«‘DÙnš‰µžIÿcAÏóF¾†S±þ–2…‰TÅ$Ô­ÂPD™—&ù45]3ÚlBºLÏäTR =AÙÖs$.êBG‡ÌË£¬øîùØÔsÙÕ!Ó_œ•t÷š›3 [¯/^…^Å$€˜ü¦ˆH¿‘¤Åܯë÷Áú‰®ÛÐwnLÿÁl §éœ¡±»/ ¡Š3¢m)ÔôïѼ©îæë½;7> endobj 493 0 obj << /D [491 0 R /XYZ 90 720 null] >> endobj 490 0 obj << /Font << /F51 5 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 496 0 obj << /Length 1318 /Filter /FlateDecode >> stream xÚÍWÝoÛ6Ï_!´{Z–¨o¿e]3d(ºõ‡u´D[DôaˆTcèÿ¾;%Û‰»Ø€-Âãñ>~wüñ”Žÿ'÷4 ½<Êœ¢¹ò­öá*°Ò æ'?®®7qྗûyà¬6§!V¥ó»›e³9Ëã$wßoD»•­˜ÍÃ0r®¡»še¡;è®—¼žý±úåêÃjJ3öuŸ‡¢úhêÃo††«’}ÆÞŒÎЪ(!߯—Z?|ñc£w°ÌŽ+µ/Ï<,äkèÞû^p-ÎrØÓÍN>´ZöâFÖâ®\]4¼Þ}£@±|Z@ƒ,m¶vsÝví¡éEö7«»å)úåb-Û…:´Å›Ki¿^*é[MØöݰ»ÔµÚƒW´à¼èWÔr¼Ð_£*^vûÿêF?Ý-“(Š—æçõ7óÖ^²ly]<Ï”Ø 5i7]OBQuûöoØý=Fÿ¨xñKúÿ"q7)s‚È £„á䚇™Ç‚È™'¡—ÙišzA ¡æÞ­Ü{ø¦±«D1ôRÏBæ(ÔùPÆt¹À4QVà‹ülòcø&w» èÑd‡bM§R‘’[÷Zn+<×õ4;Þ©Qõ$ èÆk=(èˆRÞlžÀwà×öYŠ®µBÅÛòˆ,µiÉ¿áÓs =˜Þ¦ uPZ4dmHˆB)•îåzÀçE¶[R~ñƒ¨Š6º£•·Ô6aÉݽÔU7è3¨¹Û Q>Kchl\ûRô€±-ÇÒl¦1@RV¥@e|Â0˜Já6y/H) D-z•–“άµl¤U2w_AÁÉ[øl٘ף o¸–õ>æ­: Þ’9ØV£À%FQäÞn.A-ÀÚ÷©j­>Ñ —X}ëåã,Ž]^Hqæ\qÜ=Ž­ ^š‰§¢ÊQ‰}5Ñ`o¥äZÖ£Ñýж†¸VêêÉ Å·TÒÉûŸoÉO½Üi0Pxúîë¤' ¥#rŠüŠê¶=oíö•¤Òv*0ò`gIÚ¶ÓÖ^¢ Ã¢ËÀí•Wƒ¸!3xK… ñ˜-O3›+4‚ì‹¡9ö’ê¾twã#€ILVlÏ#:e­úd^ÀßmP~œ&0Op0 ­™»6×! >`$<ÁkÀ•Ó²Ú’7 T?ø ¯¥xæž'>!ÅÃìcä{ŠÊS¢§ô-ví“}À©„OöV£>¢a+Úþ~núŒ;â„¢p]³ƒ—´®ãÌ ‰x‰F¥à¤2<„uâ½¶^ØðØ9ÀAððÈ£ÈLmæg§S›…H2HÙІr¢DlÁLiX5\ËÊ"ÓGTÁŒÂ H̘ٸ4Ê5=¥’t%Mg͸„Õ^.m¸©þôª°Î²ÓÚS9ÇÇs:…²À8ãºÖµ]…:ß•Æj˜‡ã]gϧ( Åá)ÓnBˆd±¡3À ,^2b©aQfç*»ý‰ê«‘ޝ·Ïºtj0i½cüð ok§„ý$î~¿'Aíì;‘ô­LÝa¬Ý\“ q68|–êóÙ‘`JšèÒ0 ü PG:}°‘Ž“„:‹J;9’©‡öÿd¨õ¸Æ endstream endobj 495 0 obj << /Type /Page /Contents 496 0 R /Resources 494 0 R /MediaBox [0 0 612 792] /Parent 473 0 R >> endobj 497 0 obj << /D [495 0 R /XYZ 90 720 null] >> endobj 498 0 obj << /D [495 0 R /XYZ 90 238.685 null] >> endobj 494 0 obj << /Font << /F51 5 0 R /F31 46 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 501 0 obj << /Length 1686 /Filter /FlateDecode >> stream xÚ½XëoÛ6ÿž¿Â(L.jEÊ’ ôC_)2Cf†u‰¶ˆJ¢GIqaÿûîx'[vœ¦_6…Éãñ?ÞK gü gy0KãØÏE6+š‹€©_/B^-€a1áxssqy•„³0ðó g7«©ˆ›rö‡÷¶’›^Ùù"Žc/}9_‘xŸU1XÝÏ£ÌÛщlKZ+Õ®u«æ‹H„QìeùüÏ›_.ÞßìH¢è +‘ãi3—™ðÃX™þ¦Ð‚ ò† þ†ÞV÷Q~½úL‹Fn6óÐÓíºû$!þ÷Á£Xxo†žXÞ~¸¦ÅÆšµ•MGÂäЛFöºu½#;´´…^_éŽiÛ--~»~‡€c‹0öÄ̕ugPsXê¶@´Rá¢ð›x([ÓÓxP›®Ów5óö†x¬êz« ¾ÙW|,‹^›–å˜oH8ø†äm¥‹y”zmwø¬f ÎR—De[o ¯Ž\ É'¾g;U¯^ ÁKˆ ‘‰v1j§M%ÙŠ„I§mdMë/A(Fß e ˆ˜vô¸P]7GëŸJ —3pùŒ#Ä8ȼNÙû¹ÓDûB¶ãrq³ô^£&#ß ÄÐ=wÅ uÉK§ÐðS² ´ ûÄ $þ¤ûÇU,btÁ‰Ó¶”y§œ«=„6 ®À u&ôº“Ü]ºðÀ_ò;†G—ª1-z˜DÞuK§]elÿ‚Ö«ïç ¼oÁ"¬úkÐ`-í$‰éÔFZÙ+"b"¸d] Yæ„cTË" žœyNÛS±q>w˜Óth\ÑdM|¤ vóÀ3y^ U¦c¹²îÍZÖwV„J‘SR_ä\?YãÀ×¥{c¤.qp#ÝsmÓ¶Vå5 ˆMx*°Ù:ýòk ¡‹ØŠå!ýP E0v½®k¢ .vÄ´ÔâÎEpʲѭ†¸!_ñ¤¢8XìÝx€è>—Ю4åržfû¬Â5Es¸‡b'ÇH‚‹*ç“!Âíí-±S*A˜Z¾¿²¦!ž±nЮà@¶˜øÈXSÆ Äd´ª'î¡;ẑ ‹«/ôJ./ÒØE–ᮆàHl¤8ÎwW>ÊãKcØ÷,œobpa¬X7Öò‡A…uØe4•f¬·¦U<ùH*Aæ`§+—Wq8Ëü|¹8¸D™Ÿ¹LÌ.$ªÔýJCb½tj…ŸélÁ¬cã€a‚}ù(Ëß0Lü„Å•xKSXcz¬‡—~Õs"³cî*¿Õkh¼o­’“®øbɧï›M¿{ßöPݯÀÈOµ‚@;Çøz³QmùÑ%šòŒÇu©ÚÝ èëfûìèê#7‘–T%p·ŸýZ§æGoÿC…ñÌ!^•3 ‡g@'æ§Q¾‹úÿzø£î«o²ÙÔÊ7vý8è§ý"ŠýñMühÉ™ñû<‹¹3äà7‚¡¡Ôëˆì:9;œÁÇFG+üÚÀQ!qBÙjš%“qMŽ>]–ìTLÚÛ¢ƒ©…ˆ¤FqŸ¨kÝU®¶¥ð™ÇÚ(ç/¨}눰§ÀäaðúŽ}E³.0ñü€Õ¦~\EÓ J‚/#¦¡­’LaY†xTÛ Vò]CêþªXäÈ éVJü‚:ã×>.ÂŒ"Ìù+(4š"ìQè9Cê—át, 3פ Œpü^NF—6n|îüqú4_‡¤rð xàJ£×ÕØªÂì€ Sö¦PØ>¬'4áÇã°g65Á„¨8í®±›_!0xøÛsÆãG‚˜B|8m(G]k»ý Í£xaÈhnžÝ¹ ŸýI0‚œìŸ´Çà‰2û"Çeú‘úLÕª1¥zªig PØWÈ»À¡ŠˆÕS"|`¿ZéoP÷(»§ziÛgXÎ÷ëïXæXÚvJ>¶ÿúò/õäÖK endstream endobj 500 0 obj << /Type /Page /Contents 501 0 R /Resources 499 0 R /MediaBox [0 0 612 792] /Parent 504 0 R >> endobj 502 0 obj << /D [500 0 R /XYZ 90 720 null] >> endobj 503 0 obj << /D [500 0 R /XYZ 90 79.203 null] >> endobj 499 0 obj << /Font << /F51 5 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 507 0 obj << /Length 2778 /Filter /FlateDecode >> stream xÚ…kÛ¸ñ{~…¿ ÄŠÞ²Eîš ÚæÐÝCQô ”¶h›]Šr))»úã;/ʲ×A±ÀŠœ’Ãy.øK›dQçy¼)Ö‹]û&èÓ›TF+ XÍ(~~|óîs™.Ò$Þ$›tñ¸ŸoñØ,þm’å*Û”Õ&úe¯ÝÁ8½\åy}Ïð›GËuCç²Ë>~}óéq:®Ì²ÿÃR¼b¨ÎiçE• CÕºˆÓ¼`†ê8]/We•E^®ÒÈôË4Úik•ÓÝØSuõz7z3,ó4:3¤Ûóww¹ÌÌÐk»G¶ß}ÎÓÅ:ÞTU‡GeR/VYçYÍï:7øÎ¾GòÅ&.Òð 8¸áðPýÅÆKÊ$ú|feô;ŒyÔ¹ ’ò©×Â_eu¼©kú¦ëœ÷ý‚¬§ëh8šžGüÝÀ5Ìn³gc-\'^«†GÊ-³š¤“ß“´°Zv}>šÝ2[GG!ôúj“MÔ!öÙiÙi‹ÓsàM3ÍÚ0 ýè`æŒ;ð‰Pv+Ðî¦é¥yœ–|É“ï^µoÙ¨:ÏF,¡v‘ã#c˜+<ƒ~ÕÖŠ5N¼æà»ñÔ_oÔÁÙ¾Yæ×ö‘­ãºÚLæµaóúÍË›ïË ŽÝ‰¡.µÛùói0û‘aÏt§™ìùiZ›mrÂËw¦]AŠ-r9ºý Ã¶æÀ¨F+Ë #Ûöç~ЭP7­q¦¼Âcã媨³èof82)ë èôËN3g¨™äJ'è3E•01ÜÐlG¾ BÉIõý3ê óMÏ å€3z4T?!>I ƒv5й?üN¸L Ø‡^Ž5²£5Ã`†ŠÅ¯ëø Þß\"å[ H‘ÀxŽB{"Š èdöŸŽtp \©ÌQˆ{Óž(„ðßÝ–Ý]KcëŠMuò xÓ‚îáÈhâ ¾'‰ ±Æ=1‚‚h|@ËÎQìŒWŒüË—ž{}²è;ô"ÝjÖ Q\1ÍCÐÓšxî¼xUQW5 ºˆ–¼ÁÊ! yÃà?=ð€¤ )@.18ßDìîááO i05^ .ÏIp™;×ÿ%æXÍKòDž³jsò¼ñwÓHüס›¹CÃTa1Ô Š~b«€FÜÀéuÛ r]w¢ðHJŸ‹)yWqJŸGÊuµ:SQ“ŒØÜý ‚æÂôý(Ä€4ä-„…ÊM"2-ே£Ø€8èp]•”ÕÈ©jœ¨-†z‹[axz]wÌÓT0‡QyaTãR¯Ä+OŒ”r)ž‚ñxAø9,ócO^€ÔÆíQ¾ã!Ø çôò ²ë{C%í"ŒöbXêi:åµµ_‹1/Á»ùZ r+Ó"úhQnä´î¿›ÙYÏsÌN“Hè©£ƒÄ˜¾k…–\P…œ(C5–ÏC|ËfVÖ! Õ¯å{ÇX˜%K›ÂœÇJ!¯‚š°º¶g¹Î­DN’öJY^sHëdëkñÓ„å•þKÑV%Š)‘¥+û#ä–†AS ðÿÞͱFµd'çô*œ¦Ž>"fªµj t‘Ù—”,‚æaÜèj1IþXt‘)`]Gõü’Ãïì*FîùØÉ€ä5E_ÜBèɰÔÝ$Á›|Ž‘¤Å“Æ©,b äÄAÊû'ÇM†û«ŒÞI4¢6ŽÂíþâB÷;…‘9¾Gárº¬h$†‹?lŸ±»í¬e®X†™˜4†¨×ŽJ®L,¿óv>Uh¤y¶¾¬¸\öÙ«–{V@œ” Ä_GkXñöUô ¶° ûk׳Ãl%µfGbÙüÃhÜrÂØ±PJ©Óq@vþcBQ„ƒ~Ê<'©—Iðà$ú-~ˆq”†rŒ”½e$f©Vz7\m|épü ¹L Ño΄sŒ|ÓM™Ç÷Üç£Xg¶®¸ÚÄãfHàøÌ#²!{RÉ„0ÅŸuPRyÙh^Z„SÖ{pè,V)ßÈíU ûª­]}㱘:îóÂò=,ˆ³Î;áì^3œ•"Z¥ ë Z8®®apTTëî`¸‹‘ÖqKx*F0(RGÎÓIÛÈâÁ‘U9.¢¹š¶ržÓº¹Þ÷¿÷gt˜˜Sðch2©‚ƒ^Á†húr·àiHŸÔ9%Éñœ¯š¬s U=Áû¹(g«$•AÉš.šÔÔŸXýÂi=™j«A6•lH7ƒ/êAÇœg¾…“·³ÄÒ`<¹sJùšYYo°Ò6Vy†µz8^*´5W øõ»ñNÈ.bÅ´´ Ñv ômgÁ_ù¦ûieËÁÖ‰wÁhsäž.„à°Lɗǵ÷9æº2t¨%Ôl- KØgzY UïÇ-´ëp¥à^'Ù¬XŠkÒêÐ@"šÊ"š0U²oy)…¹l¹£d \å'©ðY¸õ%§¯‹è&q’‡—òÀuEÌiD…:^Ú#LRÂJdRíÏ;"Xké5âé-Ï.½¼G5Kt„é/oc˜Ù†?p•_ãþÌ›p endstream endobj 506 0 obj << /Type /Page /Contents 507 0 R /Resources 505 0 R /MediaBox [0 0 612 792] /Parent 504 0 R >> endobj 508 0 obj << /D [506 0 R /XYZ 90 720 null] >> endobj 509 0 obj << /D [506 0 R /XYZ 90 584.602 null] >> endobj 505 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 512 0 obj << /Length 3004 /Filter /FlateDecode >> stream xÚ…ÙŽä¶ñ}¿b«ƒmê2àLj'v²ÀNòGÍî&FWDõŽ'ùùÔE¶ÔÛkc€Y,‹Åº;}Hà/}h’‡*ÏãFÕmÿ.èË»TF{@د0þðôîñû"}H“¸Išôáé¸&ñtxøgôÝYO‹™wû<Ï£êëÝ^©"úhÚËl—]VGo¼¢‡Ú£Nv0»}¦Ò,št÷¯§?¿ûãS`¢È²ßà1~ƒÍ4Q°ªÊZÅi®˜×¿ä´H’È íüŒxÚŽ}¿Ëªè2ØV/vœÀ·Œ5´Fw²¶œ œFƒîÀèš‚Š·_ cŽG^ý9IUg\ŒWاÌê>Íã´`N?Ì#îûdÈa^Ëi8˜fûiW”‘^ð‚˜æ'B™'zÞì)pÏ{€4)³‚tÖîæ}§:`€G(ç¦]x†!Ô˲K£3Þ²Š’Ýp¢[%rŸ”/ô ï]Gãrf-8e‚ÃãHÊ£¢Å̺xfféá¨8K…Øß ×!ŽqàÌü‰¤0Ë؆‹fUú‡ç^ÞjÙÙ"ô<2SN¨¼ž žË“YžŽ´QEZöwV^–çx9ú<^ºƒ@5="qvËè>ð•»Qƒ$V¥ÜÎvædDXËȲš{šæqg12½¾?ITvE²áøÝ>@À`¬*úa‹¥¢#?`PÙÚ ²2 U»cíibÐó£ o쯬ã* Ø_­™ãC»àB¯_„-\Ò ì¬[¾fÚyúPÇMY*$½Ï“4VU¶Õ `d™ÇŽ6<4±JA’ð®‚ÖŸæ‹[þbÞÜ÷ó؃fEô ~NŠD®P¯ŽÇQå©¿ö`³qî.n»ÃX]ÄUå7ÕTÞµjâ {ÃŽ>ôvùœY¹Ìã}™aÆ^Û¤}[¾1tÇå›þ UïýÛx™IÅôÖG=š¥}tg}_œxÄo–ùbî½è>Ë㬂Oç¥FÕQIɪ£’  ÞáÀ@ó‹î§íPùðÞ¸DvˆøàLGh—Ù¢!xÛ‚¨…øÈ°ÖÌ pÍÀ ç¸²•SÇiŽÛ½ÿ¢µ± ¨TLOŽ[‘è…GWw ¸ £ÀÆO¶öª²c°E‹v‡ÄÁ»Ž\§òf¦‚5 xŠ:¢{œaQ”RbܰݲŸ½ç`_íl=Màc~>°¸u®ð±Ž¤Mœä¶«8KàÝË,zÚ5y„ÆVW¨að²ƒPXɬ[¯ò[­@.š8ͱ²]퉩n…’«¹3 Z‘è¬;Xç.²F"€MÙm²„`ØÁ¯°ŽÜ›Cw†ˆüZ¯Ú¤IôáòÜÙÖo80òöÍð‚5oŽggÓMéòµ®ÎªhØx €FŽ8<#3ä0֖膻7^ÔÇÅã±·2'É”•ð‹ü½]lÏP'¹b_ÙÅY0U$Ô8Î3ðV¡ãïhÌÁ¢Å=_Ø^‚ºf`”`§á\ÃÇ:R{=/“°r*Z²²Å›OF‚Ðb94ž&æm0Rú*²‚Jj_0°zi͚ɛ{Wp/l„œ3ãl ¿³éG’e–qâA/‰¾ ÉbM×”Ë1Ä?0.r¬†gð´'Éqòz¶œPðô`ZN›hIr œ„Çû\Ã|Ú§½!?(LÌ/LZ'#ëÖS” ˆ•YDèÌ_HžPÒÏ&Ì•Òð|<ÅXGO‚uè¢f'Ë ’è0U^G?äíâžvÅÌ 0ª¿"nP¤u2Ú æ™Fd%0÷rÉmÉ’n“†V$†yžQ>²]N^KŽW®™ò6S‚ –™»€ú¿íjÉ™&öuì³:®·ˆk'ޤŸôüè+‡Çiz øÀ1\2HȯÕÂÇœ­:‘:œ$â}X_ã!ãÌ‹D1æ³¶ëÝh¾ižIZà£aPMXQÑ©‚j 'Ì0x¶!Q…Ÿ'ÞaÔ÷\1A? Ò =Ï”ÏÐÃ\4/®³WDâoá—×/‡ËáÚ<åö‰“ÙMb’¡kè :R(‹¿÷,â…/á²Õ¢|·÷’¼*G§Ñi€æZî2”ÞœËk1ÿøí $>zaËÔÎQpçƒP@¾}t)Wñ8‡Êä¹¢ì4Jy’5D á«Ä>÷?A|RÌœ•¨ÛAs©ô{ÉD(¢8\ó3袼 ¿ƒ¶¾¬GF¬¼üœ?â[ÉšñÜApI±ÙÙu™ø ³3#Qbô*ˆToJVtÁ¨Ý1’$ U4u—@ƒî<›´w8ãr#Ë×WIæ† ÁâÒ›ônYpœYv7ýË£ÿñ‡dÇ áYnd}()ʹ äP¶ôÑ‹&#~΄Ìhpï¶œ£?·ôål—æ½\Ù9+J•…äåe`¡óÌ«tŠ`*}{õºíõL¶……ä`¶Ç-º{ ¡j¼6¦æM÷“pÒU€c¹›"Bržm£[œtnâûŠ!@¾¢–Ì ¬‹EaGuä/GP3ñL35“Ž&×–'Xé¶Šþ$âB¸Ü •4#9Êþà#€ÀÉ,ª¢Ù0!û®»‘ŒÉV‰’’U „Hía•ùšCªê¤Å¥¶Ó¶w¼—n 09šÛƒøag†êÈ^߬¤¨Àéu¹Q¡"\l£î xÖ'nøÂb4°>SÖÑw`ƒn©këžêBʼ±Ë‚)Ät¦ºÜx\ €uÝIQäŒkÕ¥ ÂàǘÐO¾¬O¥(äz†—Ÿ5Å1%~?~üññéÇ<Á>žî(¤Ng!!;Ý8rŽâ9òªw8îVj4ßéÉ:Ñ±Ž«ìÎ>Ï›‚ØôCyƒoÖ¸"'±¿6&(5!6„úžsÄ¢&M¢ #_ãfi@P5*ýyì–jtÉ”%JCÀÊ©à-…}ÇŽCÉ•F½!ºf,v\â~rÊñ Ó;Ë •› …)Ô%Å9·úŒsÁ[bsâÓ íèŸF'ŽRîN¡Ú ²UHY‰M8‡ß„ص:W5pçÕ¹b!WUtÄæ*Î=ÒlN g2­êêDd÷÷qD2¨®á@à1Ek0Û{Áë×µwþÄz•æàd‡>ÏàJ|¨@ vò…âšB;lW•CUÜ¡Ä; |û¢ñÙÃ5`í( cùG—½ª Î)JõÀvØÛã|ÔBIÌÖz~ç¤õ*!ÿ‰¯õ œ²/Çá߉{zá×D]$K@Pi³M à 涩ƒɺáË`;à[‘ÈÇe9û<¢s£GþR¾qÇtÈ…—«ŸvðU&w  7Ðë•”¥:Á¸öf`ÂÅʲéG@EËmk<@ ²¸Ãƒ KÐ)7¿Ñ¡ã*Ò0°Ÿ Ž×$ž£iÊúaÇØüçbÉ«f ×øOÉpDO ýº©B+ØÚŸ3RèË Œ~ik¤*S¹“Et©Ð`ù/È}Ñ çLþ?ï/ endstream endobj 511 0 obj << /Type /Page /Contents 512 0 R /Resources 510 0 R /MediaBox [0 0 612 792] /Parent 504 0 R >> endobj 513 0 obj << /D [511 0 R /XYZ 90 720 null] >> endobj 514 0 obj << /D [511 0 R /XYZ 90 466.381 null] >> endobj 510 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F31 46 0 R /F58 59 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 517 0 obj << /Length 2703 /Filter /FlateDecode >> stream xÚY[oë¸~?¿"o+ÇŽî²úp¶8Ø¢h‹&@Q´}`$Ú""‰^RŠ“ýõe9Q»AL‡Ôp.ßÌ0É] ÉÝ!¾«²lwÈ÷wuÿ%êó—DF[`Ø.8~~ürÿ£Hî’xwˆÉÝãqyÄcs÷¯èn¶é¡(Ñz8™Ao¶Y–G/)þfÑãfŸEÓhQÝæ?úòýqþ\‘¦¿#rü¾@å>ß%YÎ)GTÑ4<v“VÑe`Âhå·%Ž}tVn4ÚåÙ¥ÕN+Ï“zq8a“î#ëžeq°ÃÖ HµSõh^p¬»7¼ën³Í‹2zxh™yòÚ¿ûî`GcÔÜr›d»¤`ÙíöUôd†Æ 'žØð«dê&?ê'pP~’p‡Å^æ×ô 6fäô¨mV&ÑÑÙžGµíEü‘½ hggÉgjJõìœ@WúFÃÕ…Ðy+[:U6Œ;¨§Nó¼3=é ÇAösèW]O\=Yøz¸s’ìäTñSVÑc AÁSÉȲß_­‚D|¬(›z­óõ,š¦³:$ÄËпJåW¢µVbìÀx5~dÊÅŒ­dG|‡MílÇÒ}éŠ#˜FD[8$Nß»óš[Ñ­ ZÙS@¨ ‹”)éI †‚»CýrüÞ©³G}Ó A~žŽºë<3ÞÊÍBÌ­~ã‘›†NHO¼[¾"G­ëáË+W2èj1#h òk7*TÒÂnÃwk˜JÎcTõš)-e†a^nˆTo†Z k+œB/¸Ý-‹`£Z5–¬޽½ùHÉ<õk„ˬù¡Øú³ê{Žô´@ûl@]À–D"+Í£ï¯gãô·#ˆv\í…ëb/ÖxÈ1œ†“]JÀ5X¦Ì—š‡8èV­"z öÖIÕg ’+øç$¹•?K¤ÂslyLvBoMÓõ@gsºáßT ¸eGM—ÍF VÔ ü HŸ>±ò`â§§íaò“)+å”õp¦ä„ Ïa.†“ÿOŠ:ðì ÑaPö¼GÆ–Õ8jȧ悔ò¿NY.YWPv´‹0i-A՞ʞG^KÕ“ASA*ù&¼ÞøíŠz´Az`K±9B¥ñÒðD ”'L`ˆ¡·^Šó}¹ˆn.Ud;߯b!Ž|‘*BuÚóÄ:>k²Og9Ð Älq<¨^‡æ¶kWy15GE¢N½Æ“C`AýQr³=IÁ±bîkµ™¢ƒ8É•²(‘À¶ù¹w”óšÆA1;Ë}ìH’káB…} ´·Ÿ»´V⟲†tÝ)Ó QÅŸ>ÀðßQC ]TÊMH¾ åÌÉ$ðËxΈ÷7ó©`ÿEJˆûPõ?ùÕ«qU ºŠ€©vrµþ*(7¾G;ÂòToBá‘ÍÉ•ÐÍÌ·3ØõæÔR ˜+z»8äiÐÿÝ,šm¥{¹MêÛ¬H17%”TaÜi…_ HËø“pz±èn:¼4ëÆFN£J<ºˆãè¶*ð¸ _UîH%Eȶ@nŒæ/,¯X$Á% @Îã„-Ž˜:½^o/Œ”B鮸‡‘O²5ÂPM©˜º;•Í0Kc>,èÉ`tÌ~Ѫ Oþïyˆ…¥Ð¡…°%™ºP þÈúÁ÷ÕÚ5}ávu6Œ9a–¡…­@$=E0ôÌíß-ú@)bècpá•)»ú§=á9Ã+Ç8 ñ/~V‰oW‘4ÛÒ¿“| ‚­U|U!òVå"i ù‚êQÈ€ã˜áÁгª$`%ìÒƒ‡âׇ³(|*×IÄN(½PFª «!fÕÀ_<œ¹f»ÏKèç#3‡à ”ÜãÙ› Ñƒ¥OnO‰ròÝçòn–`áAŸDÑœQÔ›ßônñ2`ä'òU½%×íÄ(×08çô«%×g(­££$ɲ«‹©á·¤ ùÂ)j’bÝ2±!ßå-XSÔú~¢® §n„Î! üòBHDÛåññªËÿÅ®·=Uéû C'-2¾¸¼á„ëÓL…%ºAx-šË˜,/‡„Fœ¡zIý²à+gœ±oàÏ=ó½öm}#ÉníÔ¶æIŽ/lÜžåI(¹ˆL…ŽÂ/×ÈeF¦P‘»ì²„Órv¨’9Áò~ÅSèZo æoê iË‘¡ÇT×Ç·ò¿†S¥ž¥û Gi*9Óê Üdz¡€v Z˜= gøþC/5Óø40ùê^8›­‡¢ÍyêÔõþ$,ýòã)áœX‰ÇŠxø@ϤŸîZÅìe}ñ ñk´N^Ïþ‰¾ÈI½„.å¥VXV¥$} *&-âã{gÇšb~åEnÖÙÝv/–(›|vþÑzèèÆ`ÞÙ¦_dŒ¡}zU'ÒQózm¢ö‘lX†3ñk!™ˆ,Zîß+÷X^9BWÁ}K&/6°Ø~¥N%‰ø…eW'á¡Æ£ ý?R®å/†¿}À26üÏᅢœ+ endstream endobj 516 0 obj << /Type /Page /Contents 517 0 R /Resources 515 0 R /MediaBox [0 0 612 792] /Parent 504 0 R >> endobj 518 0 obj << /D [516 0 R /XYZ 90 720 null] >> endobj 519 0 obj << /D [516 0 R /XYZ 90 643.438 null] >> endobj 520 0 obj << /D [516 0 R /XYZ 90 504.041 null] >> endobj 521 0 obj << /D [516 0 R /XYZ 90 404.096 null] >> endobj 522 0 obj << /D [516 0 R /XYZ 90 291 null] >> endobj 523 0 obj << /D [516 0 R /XYZ 90 177.904 null] >> endobj 515 0 obj << /Font << /F51 5 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 526 0 obj << /Length 879 /Filter /FlateDecode >> stream xÚ…UÁŽÛ6½ïWøH±"’’eH)’C®õ¥hsàÊ´ED" ’Zw‹~|g8”Ö›¸]èÀáp8|óÞâ› >¾éªM+eÙÕûM?=TÙûýgk Û›ˆO‡‡÷_¾áUÙUßN·)ÇÍì×A]¢öÅVJÉÚŶ®ö›îgob!öì™V”=’ÑŸ´=«‹­¨¹¬“Å·ÃׇχD#Ä(1âm˜»}]rYÌG8oÏàTÉ+¦ÇlEGã²# zÑäìXpf¼î‹-gí§B´L‡8÷XÞ3¬@ˆ[¼íJÄZ†rÌk %çK’t'³é– _þ+ËšÆXõŒÝìiÖ»i‚B É–†\±Ãª® ÔX©ããlŽÿËBØlß—mRpYò†ÎÖô1‘ÔìV6›f=žT ¯Êq’§7*‡ƒ þ˜;ÁÀÅÙH0=Óz®¶'ÁÔIÏäó³ÍÎÞHr‰ùø«‰ƒ›#x—w1UUår8ÕsñæÉŒú¬K¢½eêRÖ;´C°hË}—‹oK±+¶ `þ¤] Éüî †Ç€h¢Ë·h½u'˜ 4*€‹Ó<’3Ø<=9Ÿ·L—QOÚ"-Xî)Øä¬‰Î'ÚRFÔùHö„¼(äÅ"·Q»ÆýYñÚ/-qŤX´N'*ö{±—Èý-]TF¯é¨MH<•»Š]iéâÝÙ«)ÐLyMF˜/Ô.è#¹’¬°ïn›î.L\>!yc‚ªŒD¯ ,¾y¬½/ûhdMhà{yIÐ9h¯ñFÕ»•zæ¹6O1ŒŒ&B`'Âs–Üý~2!gûìÎÙëÒßúŽ*šÝßÚ’éÌ ” ÷ »fy·jÙ°I}/¨š¶Í·¸ Àçyö*dW݉FEã ËZÃ"ÐÑÖ-ûôLë^Ÿ€#ÛSoA ´jÔù¨ˆ \ú¹¯Ôš3Ä›ÊäU™ gÓ¥Çv×G3Oä}y!P’B$½ÜDw„ÜX¹ u°>§YËrôã¼À©çÒO.¼ôu*ž©=Þ©{*DjË×(ëÜ•àµú)É’åœÜ²í+ý_~§è¤×7©A1äŠàÕͯøäÝ”7;o{´Ð_åòþ•yÉ endstream endobj 525 0 obj << /Type /Page /Contents 526 0 R /Resources 524 0 R /MediaBox [0 0 612 792] /Parent 504 0 R >> endobj 527 0 obj << /D [525 0 R /XYZ 90 720 null] >> endobj 528 0 obj << /D [525 0 R /XYZ 90 643.757 null] >> endobj 524 0 obj << /Font << /F51 5 0 R /F52 19 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 531 0 obj << /Length 123 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h KM]#KS3K ç´Ô¼ô̼TM]cc2#m¬¢ia¬QZ’_”™˜£âÅå·ÎÔÈ»{—%Ò endstream endobj 530 0 obj << /Type /Page /Contents 531 0 R /Resources 529 0 R /MediaBox [0 0 612 792] /Parent 504 0 R >> endobj 532 0 obj << /D [530 0 R /XYZ 90 720 null] >> endobj 529 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 535 0 obj << /Length 813 /Filter /FlateDecode >> stream xÚ…UMoÛ0 ½çWø('9vbï¸b¶ër¶Yþ@c«°ì¶ù÷#E:MÛC©'òQ|TT$á§¢RFûí6)³"2ýJ²÷a¥xµÀæ ñå°úô-W‘’I)Kêë‡*ú-î[ý8Ù1Þl·[Q|Ž7Y–‹ŸsßëñoÒ2-JQæñßÃÕ×Ã%Qž¦ÿa‚ˆTöi¤öIªòŒ©ìŠ,QÛŒ¨ñ&ߥ!y¼QBÇJÈü¾(2-Yò¹ûÚM7X¨!—¢óôÜD MŸÉA9…p§;´3ÑMoñzÀ¯vˆöÔnèiÍÀÚ´èõ !_CVë<ŒþH•5ó¨§Î KØŠóP,ÛŒVç¸ØŠËÃzÔ6QPd¨ç;Íöbj·l'ô8uædɈƒ³Õžn8iu„÷ÂZðH{ßéð.Üny$ òh—dÞÏc­ Ã]MÎçVsVƒ­©¡5,øêe4'®\B*2qÀ"Ý­"ëùX—™˜‡ÊŽ~¢››¨ÀŸéÎô ÙÍ5À¾èþñd=Y­ÙÆcnæ(­›Oz´ú}’Štaæ¥ÛKó`[~ͨÖ5Oe ñ »D± ;“R» åê)Îw¨±¡±äÆ‚g. FËÅÐÄ'Dâ\¢§§ƒg>ÜyãƒäÐé hmƒŽÎÓÁ)t=— B7¶ +Ù\Jy­µÕaÔq.Ö–©AŸC³&o7ÐT¹aH+ˆœd.ixráíÄÈúè£@4¹,èúÒœÜQŸ>Æ£‘Í¡ú¾wœ8|vd.Ó™…A¼¡ÃpÓ>¥ÑÚ+y3Ç Kˆ0sàlì`ÇÀ œ¡6pÒf*< ž5²6oOž±9A›`> endobj 536 0 obj << /D [534 0 R /XYZ 90 720 null] >> endobj 537 0 obj << /D [534 0 R /XYZ 90 720 null] >> endobj 533 0 obj << /Font << /F51 5 0 R /F72 4 0 R >> /ProcSet [ /PDF /Text ] >> endobj 541 0 obj << /Length 123 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h K3M]#KS3K ç´Ô¼ô̼TM]cc2#m¬¢ia¬QZ’_”™˜£âÅå·ÎÔÈ»{—­%Ô endstream endobj 540 0 obj << /Type /Page /Contents 541 0 R /Resources 539 0 R /MediaBox [0 0 612 792] /Parent 538 0 R >> endobj 542 0 obj << /D [540 0 R /XYZ 90 720 null] >> endobj 539 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 607 0 obj << /Length 2827 /Filter /FlateDecode >> stream xÚí]odžïý+Ø @$ í|íÎÈ…ãØh §)*57mÐä*&J‘ Ir}gÉYžÃÙ9glYB*iá Ëò«s¸ç}æsgWrTø?rT£JkQ7š^½(ÂwÿóB†¯Æ^0FŠï.^œ½±r$ Qµ]\â³Ñ?O^½Ÿ\o›õéXk}âþt:6Æžü|êÌÉd=Ÿ¼[4íÿ˜“–³æöt¬ª¢6'uuúï‹¿¼x}qHl•Ê|²VÑûh•ÉJ(iMøh¥3Bj³ÿh?ŸÖøST6| Ÿ{ÿ£FhSªöGýek)´SûŸüÃ^£åȉº,MH+TQK’”¢ríÞ ÄéXVrÿ—:ú÷ÍÏþ/üæïŸ/"A¹J8©G¥®„5ºµÚó·ûODC§#ÙŽ…ìˆCílQª—±®D¡jœ1Á_§êe¬5©e°(…ªí>ÝWy’¾HzP’l-EáÊIHF’Ôiv¶hK‘„Bq$Å»$O’µN”eH÷5CRè‹¿þWa‹ÉzúÞÿ-Tµ½gUXq°-ŒuYX@FÃ4ûn‡†B±°D8hYÑJèÒ"ÞÍ—›fý¡Y4x¸œÒ‹†Ïû”Ç¡T9AF{Œ«Îx ¡X£Œ=•ªRÈãéb²ÙP­Ý +Õ3oí¡’9@F#€Ma€P,QÆ~*.«#@µoeD-õÐÛ:¡¶9(@FCmR „b¡ˆ2ÆP˜º†iÉŠÙdÛ “€»]=3  ‘5tï€Bq Ä{ ø¬u­1ï¿Ý¬H¬ñK•§<ߤŒõÊ 2Úh\zºÅ£P¬ÑQÆžÑU)ð 0[-j 0~‰ Ì3pùÓ÷®t9Ç;í78À¸Ý…a½>ÊÕsº´ÂÕ‘×W“ùrðúS¼Å˹ 2ÚoìÓ‘C(Öó(cÏuß1W¯æ.'Ó›Åö#e{-*[=Û)¿CÙr~ƒŒö; JÒoÅúeìùíW÷¥Â+»ËßÞ¯6Û¡•J+Å˹2Úuìã:„b]2ö\÷ë}«ð8Îx>ÌÛó „zæ@ ¶†B± D{ øU¿Ñx7¿žÌfë†ÜÜy¶›w]©rƒŒöWñB±G{ûE¼6xm¶¸vnîiܵÍA2 l3³‡P,QÆ íô Oó¨y½òqÜ@Äçö¡¾.@Eb¢©€@QºÎ iñŠÛÁvù÷C%söƒŒö›Â¡X¢Œ=*/, B`36t¿ õÌ2l =i@¡X¢Œ=JëÍ•„ë)5DÔ˜rà ¿íÛU5‡Èh°AL¿¡X¢Œ=¬îèîßæãf2»¶ >¥Å˹2ÚuìÓ @(Öõ(cÏu£Eut{o;y7t_Ú „ªæp6ˆé ‹C”±‡ƒV¢<ºÉ·_5ÿ]-‡›|i£C½rFƒŒ6—ži÷Š5:ÊØ3ZI[ýdž¼Å7ÌóÝÿ®š9:˜ÂÐ…aí?ÊÕ;üÙ&¬]Xr~“?FüÍpŒøA«J‰ªÊ„d$C&sŒ…â8Š3öI2RXÖ®ãü1âñä´„NV×Ûùj™šW*?¯¬ž+WªZf§—HFó4™ù ÅòeŒ‡Õz¯ãïïïà}(aÎ{ÑÞc7è‡UP(Öû(cÏû¢}^*LhÆ—9ïµïGžôxWÛw­þâe"ü ª1’õýBíJ(û3§„t gLùT|Æ(Ô.ãI„ùK< Ì&<µ¿DG"Ì_âá(cŒ°¬µ(Â~ÜøýÐ{}~ï*˜qT¤ñØ INŽ!g{”®çº“¢6Ýœf9Ø~ÛC s¾ƒŒ6»Á8¡X료=ï«B8Û5ù¿ƒVzÐêÊ”´Œ´Ž*ž˜”„‘…â-6cŠ´2—x@˜Mxj¿&#ç]™K< eì!lkQ•á¶ÁøÃÐ}Ý¡û %Ìy2Ú{ìÓ}A(Öû(co=.•õÿ Ë»³üzü¬ÙNÏšÛëÕz»Ž‚!ÚÇ¢LžÑ;õ×$Š% Ê·þö)žîýg&ë³ée³üu¾l_ˆÅêׄÕRaÊ/¼£wŸ{ëáJ2€Š4—„Þƒ@\ù£tqõÛ}UkSÕ_Ýl¯o¶‰º×VîQtÀ„Oáš3>Šô O’;Sˆó)J×ýAû¯}ª_òûß¿ ûߺÿ­k¿ ÏŸ™8¨˜£t;I¦©C þ(ÝQºc„´ÿº=MQZ%*õ¿$HÒ¢î¶È'ÓEªïµÂ™êwèz÷ív+}ñ•º¦P]P§#Y 8ÔÎkSï’Ba¨wIÅ™Žˆ8 £œÐݱ¿ÉòãÀŽs*œãd4Ø,-“\@’‹(SºO±µóS¼0:}—ïS/cIïP«ŸAQÑÓ¢}sœuF(IÙÜ©ÆHÖ³9µßŒ0½Œµº(qƄՊÏ…JoF?ÕÞÐÌ%U&áq¨]BÓïáŠJHO ‰ŠÍ‡J_b×ÂøK<4V6aj‰eª±f.¯m¬q&¢±¶' l¸!ñ*ßX_½yùöí«·/ÏÏ_Ÿ?Ђûÿ»Ç§ì7…ÐämN°d´ýACÌSzÏéhæÁÅPÚ £À.¥Ç†"ÊDtÒ¯а}“ï.Â+<èøîS‡b¤=R¹,# £ nH0$#Q¦d§¡k-º§ƒ.ç‹m³þv°ÿ.ö‡BfÜi>v$=`@Êú(MºwhŸåªº‚?ç{‡öÕÃro¼X)\~¥Šd41AÃt( ÉL”‰€FiÑùÿ!ÏÌ|9L@ï0ÕEík˜]ž  GÐpý „!áˆ2¥áPí¹¨nóÇ<?Nn_…[››aìW¥EÖ}P‘æ ñ0Pë,¡¬Ò$gÊV–aR{µšÝ,šÙ|ÝL·«uj6Y)a”zšûɇ҇’äLí"®®.’6BÒÇ(Ñ„UG~Ê7áŸv'þ¶n.ç·CFöû"•·d´ýAõbCÚeJÛ/† ÏÛ¿n®§ï'ëaÉpFdY 岌 ÉH§aAa(FâL#ºE9Ï3Ò¾fX7Ü4Ê iòЀŒ†&h˜u CBeJN¤ÿ»¬ÂZssµ½¦ï5ßËb”Í¡`9›AFÛŒk/“¿Ù …!mŽ2¥m.Œ>ºv½˜oèåÏâ-aCUs,€ŒfDŒ†d!Ê”d¡Ý‚ên|œ(Ü ¡¨@E‚€ÝÑ.Å¡0ˆÒ$)hç“ÝnæþUP©¹b!ªgÿ¨îhM¨Xæ¨È3:¸ô‰n?œ«@Ü &]ˆ?ŸÃ^Ü_.Ûq fêÂ_XËo”†8›¡EÑýŽ´‹üd·{ÓѰáùyžÜÙmt÷„<»â¶Â¹sÛáî sf»}> endobj 543 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 637.543 297.029 643.322] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 544 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 591.086 297.029 596.864] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 545 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 542.711 297.029 549.684] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 546 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 531.618 297.029 538.592] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 547 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 520.525 297.029 527.499] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 548 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 509.432 297.029 516.406] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 549 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 498.339 297.029 505.313] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 550 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 486.001 297.029 494.22] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 551 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 476.153 297.029 483.127] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 552 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 465.06 297.029 472.034] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 553 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 452.722 297.029 460.941] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 554 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 441.629 297.029 449.848] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 555 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 431.782 297.029 438.755] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 556 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 419.443 297.029 427.663] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 557 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 409.596 297.029 416.57] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 558 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 398.503 297.029 405.477] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 559 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 386.165 297.029 394.384] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 560 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 376.317 297.029 383.291] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 561 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 363.979 297.029 372.198] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 562 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 352.886 297.029 361.105] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 563 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 343.039 297.029 350.012] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 564 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 331.946 297.029 338.919] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 565 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 319.607 297.029 327.827] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 566 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 272.776 297.029 278.555] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 567 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 224.326 297.029 232.097] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 568 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 213.233 297.029 221.004] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 569 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 202.14 282.182 209.911] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 570 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 202.14 297.029 209.911] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 571 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 191.047 297.029 198.818] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 572 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 179.955 297.029 187.725] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 573 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 168.862 282.182 176.633] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 574 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 168.862 297.029 176.633] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 575 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 157.769 297.029 165.54] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 576 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 108.148 297.029 116.367] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 577 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 97.055 297.029 105.274] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 578 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 85.962 297.029 94.182] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 579 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 39.131 297.029 44.91] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 580 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 638.825 522 644.603] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 581 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 626.365 522 634.136] /Subtype /Link /A << /S /GoTo /D (31) >> >> endobj 582 0 obj << /Type /Annot /Border [0 0 0] /Rect [483.091 582.474 492.306 589.996] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 583 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 582.474 507.153 589.996] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 584 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 582.474 522 589.996] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 585 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 540.326 522 546.105] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 586 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 498.433 522 504.211] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 587 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 456.539 522 462.318] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 588 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 446.072 522 451.85] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 589 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 402.186 522 409.956] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 590 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 393.71 522 399.489] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 591 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 351.817 522 357.595] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 592 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 309.923 522 315.702] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 593 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 266.037 522 273.808] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 594 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 255.57 522 263.34] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 595 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 211.43 522 219.2] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 596 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 167.29 522 175.06] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 597 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 125.142 522 130.92] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 598 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 112.682 522 120.453] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 599 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 102.214 522 109.985] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 600 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 91.746 522 99.517] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 601 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 81.279 507.153 89.05] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 602 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 81.279 522 89.05] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 603 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 39.131 522 44.91] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 604 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 -2.712 297.029 3.067] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 608 0 obj << /D [606 0 R /XYZ 90 720 null] >> endobj 609 0 obj << /D [606 0 R /XYZ 90 720 null] >> endobj 605 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 46 0 R /F38 610 0 R /F2 255 0 R /F93 198 0 R >> /ProcSet [ /PDF /Text ] >> endobj 613 0 obj << /Length 123 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h K M]#KS3K ç´Ô¼ô̼TM]cc2#m¬¢ia¬QZ’_”™˜£âÅå·ÎÔÈ»{˜U%Ö endstream endobj 612 0 obj << /Type /Page /Contents 613 0 R /Resources 611 0 R /MediaBox [0 0 612 792] /Parent 538 0 R >> endobj 614 0 obj << /D [612 0 R /XYZ 90 720 null] >> endobj 611 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 714 0 obj << /Length 4728 /Filter /FlateDecode >> stream xÚíYsÉ‘ÇßçSÐO F K]gWûMCzb½11áiŸÖŽu h‘°4Cí§ßªî:²Ê*È’<" Ð)2™‰Îß¿î£éUeþÑ«¦ºª9'ÐWóÕ•û黨ûîÆÜ‹Ÿ^ÿðâgI¯hEšª¡W¯ßB¯Wÿ3»}hŸvÝæú†s>Ó¼¾BÎnûõ¼{Ú?üózÑýv}ÃꪩgMsý·×ÿõß^‡˜’±Â‡²GŸªfW´&ŒJá>•Ò‚P.ܧ  –ã_ Â…bö¯ÌÊŠÔU=þÑFv¥I£”pÔÄmôÄ‚k`‰dÚäú†ÖtüÂ&ÿËýð“ÿà3øÍÄ;Ó5Ñ”_)ÖÁËÚhoø%ƒ·ºfƒ$ ¸CWÆŽ"65©Ì¯«„½ÕQÄ©œ¬+J˜ËMQN7F ‚Ïú§Ý²¿¦³uJ^šP󟥯g/:D'Ò|eš•tÌPx›!ËTa:®r:ÉE4*‘µ"µ×À¯QF}J‚ª/¶ŽÁàI,±V8z@ƒ£5Dt”? wT?H¡‰âÔƒ,Uwb ðc©‚æoËmûæ±[û’Ô~gù£ÊþZQñØmcŒ(Ñ<÷zÓ &í¼(–h†«ÅÙ i’•Kt•ÕK&¢• ³}`wëûåº#›U ¬ˆÒôr* µKY u4ÃQÃìs¢Ž®²¨3-jSî•靖Pî×݇ã"Ï4aB$˼i[’ÅÞv_/ w©Åe½¤–h†«T¸Z¢«¬Z2­Z*N(S'«eÛ¾O5¼&J~Ba‚Öç©L.Ï%}D3\Y¦áˆ®²ú8ˆxÔÓ5'Úl_|vOãE·›¿xè·»-éþ¹_¾?vXKÂiµ”)ëhðìÔƒ(DÈÆä¹Xƒ3T!ÞfTÚ®r ÉE´ú á^'Ñ7=Ý‚ÌûõÛ|Óù¨štÃc¾g³v½è;1 }ÅVâKëÃæ¿„-šáØ`&ñЏÊbËD´Ø¸6TʼnØúU—è%˜6Ÿ«|I• ùø>§…ËÈá(É(šá2‚de…Ê(ºÊÊ(ÑÊÈôyÅN”Ñ~Ûm¶åÞfJGü’†$ÿJ=ä@”ÍpA¦EWYe"ZQôDù¼o7/ÚÅêŇÝêé·c)IšŠåddNJI·ÓÁÏ’ ¼®ˆïb7Yþh,K¿ª‰±ô|¯e=3Œ}Ó¾!ý}'5-ø7V-`\Ü“–ÈD3œ L>\eùd"B¼Q¤n$F¨ßïžö»mš ùœ–nþù Ü€Êm’JZcÜ€«·\DËM+ƒ•p3åèôÒÅÌ8ëß!†Â=R E4ÃQÀìàE¸Ê¢ÈD´(̈¶n>¡{|² ¶æëvþšniLC&²oi>Ð7: ѳT‚¬p¶ ÝxÛeÉNÃMŽp! ÷Eúeqräå|Þm·nü:.Ò1=ÛmúÇB3~£ìœ;½˜85I-6•À ׂ³)¬ÉWY5d"Z1°Šè õtcûqõ¸\¿KM“R*‰lêß]'÷¼%NÑ çSW㜢«,§LDˉV#;Óûßãïva}ÓÍwýæc%B5ßJ‰Å¨¹§/Q‹f85˜È µè*K-ÑP3í™z´åÚÏn»ÍûErèÀåüYµ.pÑ åS‰c‹ŽrÔ2á,4m1­O£ö¸ÜîRÕ`])Ÿ}CˆAu*Qf8V˜l‰vj«,ØLDK¶6<z>¬™Ýþ2¢m—í6¹ì'+Óm忳À§®„<šáÈ!)QäÑUy&¢E®´QŸ O®î "uá; ?I.±%AD3\Q¦ˆ®²‚ÈD´‚&¨žêáDZ¸ûùUjþÕN5É‹S†}L_‰z°Â¡WŠŽ²Èñp–¸!Èë4òWýc»Y&ë}I*Î{éC` ]ÖJ¤£ŽÈ°Ž®²°3-m®ˆ®•ï½í–ýz„Ífýf1œÕ°Žß&›ŠC7ÍY"?J9#‚Ñ,²³ºfÇ\ ¹kPÆÑS–q& eÌ”‘€oÔ“µ6mH£ëïíù'×ï.µ¥bÍðb)áK²ÀUV™ˆVTŸíª/×k[Íï—ëû±ÀwÃOv›eçsºõX-,º7ûû{k™7 &¿n÷Cá©„"šá(`vð)Eà*‹"Ñ¢¨$áªíí®_-çþ¤Çµùè³nÓ5óøÃ0õaØoMVfí}7œ²Cí䤕æ)ùû Ê0bîÉKÄ¢N &Qámft•%–‰hˆÑF­Ô”Ø!›·(5%BÈ3i=À>QÀÀ <É9¸ÊÎE´€µ0üOÜ8×îwýÿ.–vθx®&µ]EéæœÛ]L.Å%iD3\ÞpWYid"ZiØ­ÒŠ}‚4VíÖžyþ.“¥áR\’F4Ã¥ie¤]e¥‘‰h¥¡8ᲉèWý~ìF¥àšñòǻԕG39¤ Бp•E~ñhwå’0꺊?wüÔέ"ÞíŸÆn‚íÞ5³þq9ÿ˜Þ@µ¼Àí”Q“Õâ° ˜ázp6£(ª‡è*«‡LD«Z?nøi¹n7nUÙ.QZî¾8œ:»€ªƒ=&­Ä:Xá¨Aöº+(:Ê‚ÆÃYÎUEX¥s ÝŒéªÝ %þ!=`n4‘õ7ƒæ2P¢Ípl0™½N¸Ê‚ËD4ätCêJæÀù¹îE7·“Ýéy»µ ùFkf„˜{ò°h…ò‚)èzdt”£• g/j JWu¿Y®A-:r;^—öNƒƒWí8“Ýýsß­ç©ócTŠaéû³»×H¶ÝG/d;Z¡Ù†9À Gt”ËöA¸ig†›ïSå)Á‰`n?ÝmºG£âY÷a¢cìæº‚³Ýµ›]ºÜ¨šÔâÌšºÃ+ª(3ã:y¥˜]Åæ>¼Õ 0;’À¡+ä¾{åpƒ]Š•‹ØSIjÉOÝŽäwÈ)O©ˆÐ:àËZ?¯KD„)jyJŸÈ4}ouÌŽ˜ºÂèW5¡æ×ÀUJÎ*ñÐÕñGTàÙGŒÏ¢N <ÿxƒÀ3‘‚À+aªÀækcN´7šˆZŸÙ·ÀÏeµ$…h†KR<)…è•B&’—‚lQ~FùöçkJÅìå/¿ÜþòòÕ«?¥ÖHkcÏÙy-ôé÷I)f(ÉI~™L‘n0’¹H¤¦„2î ­»3`~õÃúÙ¢K¾P惞Ş•“ ªÏT o4Ãñ¤‹dAnP¼™H¯jˆÔyº®ëùÐÛŽè··ì\¿AŽ_4¦"¾™¥ÑÝñ™Kœ‚Ž $O¤ ap‚BÂÃFR“Š×ÒoÝ<µ%ß®á»Íä¨çf:B†Ü!°Õ 0Kôܦ®ÆÖë*O¹®b>àÔU¾«Xx ç\ÀWÈÛAÐùlj$-L¯SI˦ C܃óClö´é‡)}{ "¹Až2Iÿ=ÆÀ÷œ%8Ñ ‡S†À‰nP8™H7_%õ·?ÿú—ÿ~ý*Ì é0+”8´.ˆ®õó«‚0z.%zÑ §sš…7(½ƒH“ÑUÀÇ8~Ê7à;bÙ ·y¸f2Ý—h[LXÕg2·„Ñvy+ÑŽf8mˆ@%oZnPÚ™H6¥D+é+ÒÍ~Ý-É.`ÿøë!º¬–¤Íp)@@ÇÛ)D7¨"¥ ~UÎØ‘&3ß ÞgÔûM›ºÄ–K"´8Ó DŸ¨Â"0C''9OL©ø®\t•íf"º*ô ³œ xà ¹VoPpþñg"y ­Ií¯ží׋ômp\?³)³“NŸšÏh†ó„YfÉ©à噉x*Jt%S<eÙ£îáöˆÐ 2xm™³kìÆˆŠTüßÊãâ±Ä%šá\`¶.Ñ Ê%)p‘aþ€ëí£Û{01ôWÏ®ÇóG›~½ü¿á ‡ÍpÙo²yÿ4ôxJf(/ê/~X"äË=E)õÑ O=LHz%¸ASŸ‰RÏ5©iãß!½Z¹SÛôi_©ôs¯Ð¾õz¸Ö'£>Zݳõ©«ômJôè…ž  ³šPm“î›1[ýù—V¡]ÏZZÛ‰‡Pð\fJe8šáe&©>£g&RÀIe|Aëm¿¶ ÕýÁ›0C3÷¶Ý?îÆÿ¬ÛUrV±¢¤¡ôY Év)(q‹f87˜Íô9%àå–‰¸U‚TÍÛ~Z7ÞK9íŽlº{{½÷v¼×*Õá„þ{ϧauãø€¥ª1Xá5#ÈTrn,ú@àQ<{«u24„Ýx÷Q`²@º¡§¸qwD÷mr!UJÓM_­⟡P€Z&éPÉqpƒåý0Rrº™iJ*ÿ&8“ÕÇ3ÍT&<~ÝâvX½¶U]÷”ì¼4„I}‡6}6Kˆf¸ ž,zÀ ªL¤ Õ¡üqÜ~ÓM^Íë.óœ·{[ÿê–˜úV«3mû䔈F3œ(̳HvK€”h&R *kÓð³'?dûGÿ&àŒë?†}è–»‡â‹S©P„Õò+¿:5äÌ=I)ýÑ O?LŠLvò4ý‘Ògàc„ûͱwÅ3ðw-8пì:pþ¨ëÞ¥ÏÃKZ_FÕZ™„Õåæ5šáJp6cóšœMnP%d"yØ{w•ø]×.3,O›~×ÍwËñm‰fLðŒ¯IFpúÌp3ç$É*yj¸Ápæ"œš›ž¬/´þÛÃ’Ÿ»®sêT׉Å T}þä¯Wûúç-AŠf8$˜ºô®>à…”‰ ÕÔt{}Ý GÝènaï:n.ý•K`‰z4éCé=pƒRÏD ÔU»Ëw]X18:ÒåÆôûmøm¿3÷!u)P²ÈÚWÝËÏ)²XÚÝ”ÒÍð´Ãd°ä$6pƒ¦=)¤]èØ§½ëÞ/çnôðf8Ym×çÚx xؽéV¦Ñ›åýÅKÃæèDÞkûl'æK±û´¥G3<ÅðÁët}Ý )ÎD )æ*ö[ÓïLa”dßoßÿd=¸Ô–ôÍp=@J29eÜ zÈD z`Ò´Vnqðî?oÿ’„}IÓ÷×+Ò§9}R ¦À 1ðIÎÛ/¨2‚('š»¥Ê»¥éäPþÚ®ÂÔÍ~Û…·°¸qþãbÞn*F:_ûVÝ•Šc4Ë#Ì ÒÝŒnP ™HBÅóoJ¼[Úµ7û]çóúµÛ¿ÖRË>|x½úsxÑdH°{ì«h†³‚¤Éá8pƒ²ÊDò¬šŠÔ­ ÞýŠ´¤Ÿ}ËEnùë>—àB-­ÐJ’Jö_£L™(^ðnÌ»~7y›=ôÛ]¨E–âÕó¿Y)ÛÙ»GCÑÎÜ=zàh†$›ÂÔ½£ÿ4«él endstream endobj 713 0 obj << /Type /Page /Contents 714 0 R /Resources 712 0 R /MediaBox [0 0 612 792] /Parent 538 0 R /Annots [ 615 0 R 616 0 R 617 0 R 618 0 R 619 0 R 620 0 R 621 0 R 622 0 R 623 0 R 624 0 R 625 0 R 626 0 R 627 0 R 628 0 R 629 0 R 630 0 R 631 0 R 632 0 R 633 0 R 634 0 R 635 0 R 636 0 R 637 0 R 638 0 R 639 0 R 640 0 R 641 0 R 642 0 R 643 0 R 644 0 R 645 0 R 646 0 R 647 0 R 648 0 R 649 0 R 650 0 R 651 0 R 652 0 R 653 0 R 654 0 R 655 0 R 656 0 R 657 0 R 658 0 R 659 0 R 660 0 R 661 0 R 662 0 R 663 0 R 664 0 R 665 0 R 666 0 R 667 0 R 668 0 R 669 0 R 670 0 R 671 0 R 672 0 R 673 0 R 674 0 R 675 0 R 676 0 R 677 0 R 678 0 R 679 0 R 680 0 R 681 0 R 682 0 R 683 0 R 684 0 R 685 0 R 686 0 R 687 0 R 688 0 R 689 0 R 690 0 R 691 0 R 692 0 R 693 0 R 694 0 R 695 0 R 696 0 R 697 0 R 698 0 R 699 0 R 700 0 R 701 0 R ] >> endobj 615 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 629.429 297.029 635.656] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 616 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 585.539 297.029 593.509] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 617 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 575.037 297.029 582.907] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 618 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 534.633 297.029 540.86] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 619 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 522.388 297.029 530.358] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 620 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 513.629 297.029 519.855] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 621 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 503.126 297.029 509.353] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 622 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 457.817 297.029 466.036] /Subtype /Link /A << /S /GoTo /D (52) >> >> endobj 623 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 447.563 297.029 455.533] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 624 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 438.057 297.029 445.031] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 625 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 427.555 297.029 434.529] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 626 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 415.807 297.029 424.026] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 627 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 405.056 297.029 414.022] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 628 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 394.553 297.029 403.52] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 629 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 384.051 297.029 393.017] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 630 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 373.798 297.029 382.017] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 631 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 331.397 297.029 337.624] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 632 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 319.151 297.029 327.121] /Subtype /Link /A << /S /GoTo /D (72) >> >> endobj 633 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 308.649 297.029 316.619] /Subtype /Link /A << /S /GoTo /D (72) >> >> endobj 634 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 299.89 297.029 306.117] /Subtype /Link /A << /S /GoTo /D (72) >> >> endobj 635 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 289.388 297.029 295.614] /Subtype /Link /A << /S /GoTo /D (54) >> >> endobj 636 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 278.885 297.029 285.112] /Subtype /Link /A << /S /GoTo /D (55) >> >> endobj 637 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 268.383 297.029 274.51] /Subtype /Link /A << /S /GoTo /D (54) >> >> endobj 638 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 256.137 297.029 264.007] /Subtype /Link /A << /S /GoTo /D (57) >> >> endobj 639 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 245.635 297.029 253.605] /Subtype /Link /A << /S /GoTo /D (57) >> >> endobj 640 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 235.132 297.029 243.102] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 641 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 226.373 297.029 232.5] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 642 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 214.128 297.029 222.098] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 643 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 203.625 297.029 211.595] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 644 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 193.123 297.029 201.093] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 645 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 183.49 297.029 190.591] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 646 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 172.988 297.029 180.088] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 647 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 163.359 297.029 169.138] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 648 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 119.469 297.029 127.439] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 649 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 108.967 297.029 116.837] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 650 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 98.464 297.029 106.435] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 651 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 87.962 297.029 95.932] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 652 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 77.46 297.029 85.43] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 653 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 625.552 522 633.522] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 654 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 613.76 507.153 621.979] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 655 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 613.76 522 621.979] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 656 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 602.217 522 610.436] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 657 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 592.666 522 598.793] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 658 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 579.38 522 587.35] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 659 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 567.837 522 575.807] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 660 0 obj << /Type /Annot /Border [0 0 0] /Rect [502.545 556.294 507.153 564.264] /Subtype /Link /A << /S /GoTo /D (6) >> >> endobj 661 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 556.294 522 564.264] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 662 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 544.751 522 552.721] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 663 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 534.951 522 541.178] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 664 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 523.408 522 529.635] /Subtype /Link /A << /S /GoTo /D (69) >> >> endobj 665 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 511.865 522 518.092] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 666 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 498.579 507.153 506.1] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 667 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 498.579 522 506.1] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 668 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 487.035 522 495.006] /Subtype /Link /A << /S /GoTo /D (65) >> >> endobj 669 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 475.492 522 483.463] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 670 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 465.693 522 471.919] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 671 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 454.15 522 460.376] /Subtype /Link /A << /S /GoTo /D (65) >> >> endobj 672 0 obj << /Type /Annot /Border [0 0 0] /Rect [497.938 440.863 507.153 448.833] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 673 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 440.863 522 448.833] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 674 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 429.32 522 436.842] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 675 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 417.777 522 425.747] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 676 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 406.234 522 414.204] /Subtype /Link /A << /S /GoTo /D (31) >> >> endobj 677 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 396.435 522 402.661] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 678 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 384.891 522 391.118] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 679 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 371.605 522 379.575] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 680 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 360.062 522 368.032] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 681 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 348.519 522 356.489] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 682 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 338.719 522 344.846] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 683 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 325.433 522 333.403] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 684 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 313.89 522 321.86] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 685 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 302.347 522 310.317] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 686 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 290.804 522 298.774] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 687 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 279.011 522 287.231] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 688 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 267.718 522 275.688] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 689 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 256.174 522 264.145] /Subtype /Link /A << /S /GoTo /D (59) >> >> endobj 690 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 204.433 522 212.403] /Subtype /Link /A << /S /GoTo /D (61) >> >> endobj 691 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 192.89 522 200.86] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 692 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 181.347 522 189.317] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 693 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 171.548 522 177.774] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 694 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 158.261 522 166.231] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 695 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 146.718 522 154.688] /Subtype /Link /A << /S /GoTo /D (72) >> >> endobj 696 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 136.918 522 143.045] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 697 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 125.375 522 131.502] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 698 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 112.089 522 120.059] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 699 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 100.546 522 108.516] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 700 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 90.746 522 96.873] /Subtype /Link /A << /S /GoTo /D (4) >> >> endobj 701 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 79.203 522 85.43] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 715 0 obj << /D [713 0 R /XYZ 90 720 null] >> endobj 716 0 obj << /D [713 0 R /XYZ 90 720 null] >> endobj 712 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F2 255 0 R /F38 610 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 797 0 obj << /Length 4700 /Filter /FlateDecode >> stream xÚíÝs7’ÀßóWhŸŽªŠÁǃ‡{¸KÅo%Ž«¢}ºÝ†ÉS¦8ºáÐkß_À >š$ÐÚ±-R®<(”ÚÝœþ5¾ ½¨ÌôBWŠs¢Es±ºÿ®r¿}ûuÿwe®€Ä_÷Ëš^ЊèJÓ‹ë[¨âúæâ´ª.¯˜®¤^üxÛnîºM{yŹX¼cö'_\_6|±û¡[®/ÿyý·ï~ºöjÆ _ÈJ}#Å.¨ \H澑l¡\Ìßè'k凜^4DK)¬Œy,ZÁÕ,ÒÞtãm·n·³(’‚.¥ù“à÷æ_ü£¢bmŸK°Åö_—¬Y´—tÑ>¸Ï¨ !¼ ÈåUtþÁö>ýÛ¿üs´ÿò€ ki(¿²!R+ëtÓ/uÄ&6З‡ª&p~dQ+R1 -&"ÁKe-ÚX¨š¹XØ\2½x× ýæ¾ÝXpãLñÝe­K“¬[ùÇ/_½þûõï ¦ÔDEÕðÏठŠá Ohƒˆª²2-!‰1üoH5#Í mN¡aôœJô¢N:” ”^T•¥—±héñz õ™ÞûUû0vý&ÙÑIRQýiˆ>WŸöía¼ßJ¼£Î"`xkª²¼,î‹8ã¤Qn4oֻ߯›ö?¸yCjÊžîÇ5vçÃü(†Ã‡82ceT•…Ÿ±hÙSF¤û쿟;臡7]ó}ªå7”Tò”¦8ƒèœQ‚ÅpˆÐ¯ï±£ª,ÄŒE ±¢DHzl±ÛÜÍ—«¹÷ž&8Ýfþ¹œÿ¶êçñxè×k;½™ÿú/;`/í_>¤fBµ Lþ ½>Á=L BÃ!@¿dºÑ¨* !cÑ@¨ueüâW ﺡý¯Û±ÜÜreü»ÜYóçm;ŽÒØÏ¿ü¿vèÿ’œ}*•ü³»^„€’ †ØsŠD U99‹–€Ò¦W ì¢tÑÆËÆõwp·ý°‘~­!Œ?Ñ~íÐwŠÙ¯íŸå„®¢Ô1«}Es¥ƒƒ™é8æR¤œPÖܾ"·ÈÆB1ûp!sÖöMÖ„Dã0ûp! ÷Íå"jQÆÜlýÅq‚Á§"Üÿ¢› ¶OX+Ûù¾™??,GºoRª(aš~†@ý£2Ÿi¢šâHÄpüN¦°üª²±hùS3QnD¤» c€eÛN?ÞºÎßPž:*;þ÷Ýv‹¬µ¨ÍÀ±§6û>ò##‚Ñà„œ“ºbÇäTÍ-5eÁe Zp•f›·~c;Œì†å4†'ZdC*ÑœÉêã:;¨„5HáT§ÑNÔ“eŠ[3H…–„ª:ÉÔ6C;÷MÀ4s\ÅåiÁü”/ðöÞ+b(ñ=(r )ÇüÐàaFC4‚hEgcHšß¬‹kþˆ4?’ã7SÓ‘œêøQ+1ïÅÂø ÄÐñwžÓª²ø,áWœ()~³ K泸ѢŸy>«Γ¥ˆbx@(™ˆª²!±h#@2RKê§à4 Á{3›NAE(ågÒ¿ÄÜλ¶4&D1|L€”4QS6"2mDÔ”ðZˆZ·ìºÅbÃtòM]?»ØÀÀ;–ÀG1<„ƒš²à3-xaZxÍøÝzýa&ÿ¿»åº³c~{3ù›å}r/²‘Dhuz‘€uëÎ'¥n=ŠáÝ:t/ûõ¨*Ë2cѲd检x·™óÛßû÷Õ;3à§Ög’ÔÕÉwôPç˜Ð(†…>f5 4ªÊ=°x”,ãº6°[üµ˜,ûëÐïbÞ¼»w}ø\L°Þ¥[¯™¬óSšè!”¹ÒDª"e †Rö2sbžb”ªåC‹‡r."”ë$î,ÂÄ‚Œ›nœ†Ùrssȸ›Wìíà`'ó¢5aŸZ¦ó¥¶½WJ8£Ž:8ƒ3ªÊâ<°xÜh¹ù販?ÛìÏËÁí,®ÖËKºØºÝH;ØúdÌzÝmÓy5ZqÂ?=ƒšï__NÖÉÌÝ1ºsTeÉf,Z®•"Ja[O[hoÍC/’¹NªO­ 9ù%2iö-Lš:iÞƒƒŽË@S62M 0mfK ýÜ®ØYEx¥Ïûî¼o C;‡=L퀪\Lä,Ú˜hjÂC¯ßß»4éM7´+[Üݺn=ŒÜËÝØß÷;Wó™èÙ§Ü—)ñÄX¸g*±ˆb8 螺BYDUY‹–…åî‘ÅÖÎlÒzHíiPÂøóÉvbÄçJÄ£NBèÒ¨ÊÏX´Ä%#šiœ¸_ߨs f¢5ØUR¢ªº1æØ“.ÀÈ9”ÈE1œt¦@ÇR *K.cÑ’3 O±Ú“ÛŽ~ök@ù ð];ºÞsv›•ýÓØÞ$gÃ’(úÄ] ˜{ð°(†ƒ>ijL@UXÆ¢&*âgÜ–—_§°ì:E)bàœi~ɹ¤D2Há oñÕLT”ň›³™&Ü'–~þûk_ùJ¿½µ½çï7û͸“)›¶u"cŸjƒFsS‰/9”bXÜ3–¸D1 t^© TeÑX<Ê P]áO8¼,¦º[Wƒ“ÒŒ-Mé·-¼G/JiS‘JË:€º(õ2ù² )59ƒ6fdC|%ØËÛŸÖˇm{ãÎ*¬>¾¶šÛÑg^… í×=Q¡ùF)´õB×à7*ÊRØ7w˜Ë¥µ"’;âÝݦÚoÅÕ{{O–ðG1œ?„‚WUÙÈX´ ¤é™Ý¶ýK¦±…3CÝœ[Ÿ;ÜÎS[NŸ¸"üPˆ÷`Óú’ënó6YÛPB5ºŽÅ\í¾rÉÕQ w5|úŒ«£ª¬«3­«¹-%wE3/ïï­§v¿rÓÎ;"݈Ö1MÙ ºç54bˆ«Jˆ£Žz]£© *‹8cÑ"fbZ‘ψýþõÔnmÆ}gsï+ì®b„Í™LŒ¬óP‰lÃÉBgã›Û@U–ìÅ£¡’2cÕm²v›ok?"‰à}X‚ÅpøG¦çŽª²ð3-ûŠIC³¶cÞ¦]aÝχӒ¥Å¶ö\?‡D-FÜy®D<ŠáÄ!©PâQU–xÆ¢!®+"ªÆŸ.½°Ãrÿ6,EV·Ë»Ý1cu՜ٌAì\U ¥PÀÐçøþWT”Û1g¯<Ò„U>_1¶îЄµ·DßYàí'½É4ÆO¾i#P‡ P£ ºš£‹Ù¨(õÀÜ~ŠÓùÁÞåQ¿¤“QV ¿˜¥I8½7§ØânöbÒ%¤TžúÃûºÌ¨§šúBJM4z7”—ºbG¸U!›1öþ/ »!,g)p®5 PLq2s:Æ›o‰‹ÇÎÒkª×,8‹ˆYê ˆ%"b_UºÒe ˆ¨ ˆŒ¡¢!M½àž {yƪõÕjùƒš¡N¢yc Ú¹¢Ô £Þ ¡WKò‹jP~KŸY9…{±~é—n׿åz9­šÓ[à’“ZœeÝÆÖ¹©Ä6Šál¡Çe•dÕ l3–[¦ˆò«5·`Z-×oÜ:ó©B¾Úû~ ;´S.,Mž²jè¿Z3Źg-Šb8 è¶ã­€ PTƒÊX €LoM…ôo4]m°—æu©¬ÞMûá¦Û,‡ó¯wÛôd‰Òzš¿}íþãå½Ä+Šá¼ —¨¯¨啱xU’Ô*ðÚ¿'••Ÿ¾X9Ó+ÿ<çÒRD1< ã æ8ˆjÐ8ÈXòqPkIª ‰·3ôãrL÷¡Š‘æ<ïñ(¼ƒ TJuÏ×5OQj0ª9KjcË%"ÕÎŒ•3ÙW¿™©Ð5’h¬žCÝÆÙ¹¬Ä9Šáœ¡÷YrÊ Ô œ,¥³µá¦}¶â×b¶â×åjè·é²™†±oõûQUNv1ϳ<\ç§Ü(†Ã….§É¹PƒÂÍX p©&²v–îç¹÷Ín¾ÄÓÇH–˜Y=kκ °p*ab8Vèlž\ó5(ÖŒ¥€µ²× ù6»‡Õ—ËØ“+Xm§MEpqëÃzwwÕ¥¯cb:ÛóåT÷¨%>Q ç½Æ’K^ 哱äùmwêŸM7NµO®¼é>\9ºœS…¥­ÓÛª§™5DÒ¼Þ…4/CÓ¼{ÞL…@ †-g(`kÑ"b›à$¯ÕäŒHþ­”87^zg.Cî—ãSëSD5hd,…PóÊ.v°}ºVënHVdÔ¤®õó](yï•G19!’ b Ež±KIšÊ•Äþº[݃¿g÷ÁÞŽ²yâ·S­ê]HÏg ðK>)« ¯õÓFýS–ÐD1 tO£@ Š&c) ©mD@³¶ÝVþ5RÉì“d쬋dÂðè¼Ti£>ÒB‡'×%@ JöÀP:;!L QÜUo¼*f'^íÝbÚ%v¼®¶‡|ä9÷ÁX §”ÔºÜùF1¼…;äôÝQ K! *J*¿ŽŒç žOçgº/û1ólçÁRëbxë‡0Òó쨥ž1ä©s[BWGê!ã´êí±ËX&7×@¦zSVŸn$ÒŠ½k ­ˆ¡­xÏËé)PƒñÌY <•&Mã†WívôÇbï§ T:­l;êZœóÕÙbç­â(†#†ŽOg‰qÆR@,Á±ßM;ÂËÙö/y²µÏô¹–ÅaÈeîüuD.ñóׇª×¯LÈeîìõŒû›÷>!*œ‡KQÅ𨀰ÒQµ Q‘1¢‚)RùÝó„̧4ý ͽȂ.¶¦k틤ү<³÷kŠº9‰û5Ã`éœPw£>îB"³é¨%—±ÈQI„<$7´Û~7¬Zd*Í›æ9N¥«J|£ÎzáÕ |3–ߪ&ö|_&ß">kùÖ_ätÛy¸Q   ™nG5hXd,ù°`º&œù°øíÚÕàØ]'{Tl9öCºé×L=Ãt§wW1Cïy>]”Ô`Œ-¥ÓÞLŠ©šn²õ[1íý›{éŸÅo_üjã[äÚFeê3»].€ª+"Ë™ †3w2ÈEó¨ež±ˆÛWUPáyÚ…²¯¸½m—£­±Úƒ÷.ûà:}.­ ýú£É=o RÃ!A×Ñä? …”± 1Ó É6/×Òn÷ߎ.•çy²ò¾*¬†€ºÚs{rpZP¾C¯½Ï^E¾áhÑ\(ç3¬ñÓI©#â©ÖÅcÓù¡Ô8£Þ8¡KÓ’€^ÆR€W5ÆÑÞnªHž¯Oèï.Ó¯¨ÿ„;çOøëÀÈy®„;Šá¸!„tÍ2Pƒâ>°”ž$Q¥ˆ®Ü$éuq’ôÚ6×GÔé|ï7¥ìåh®Î'UºÓõe÷—zTÚw§;@ ¥çe25;@ F/g)°«9¡~Á4“ßÀ+0ì,ǵ`–é]•$”Ñ3Èz'•ÈF1œ,ô7M“jP²K¬°5UûdÇvHΊ¸-îRß^õ’„ïüX‚Åpø O®b€~ÆR€Ï©j¿ o¡wýjû~l77ÉÛèuE˜jN÷ÅjÁßÎ %tQ GZ'·î]ÆR@Ç(þÒß×ÝC¨¶±ý°=áµ÷Ö´Þ¯@ÑÒJZ)Riù´ßÜì¾D,ŠáÄ ‘ž6ªA‰e,b´"Ú¯{_χuüþÍ”´g}Ũ”êYœÛò>*b8Xèîô¹  ›±ÀVf]âßÃ4õ¢ýº[}¯v[=»Í&^KþÆ×D~ØŽí=rYIó5_|‡r["ÅpBÐoé,> endobj 702 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 666.953 297.029 674.923] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 703 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 655.749 297.029 663.719] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 704 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 646.287 297.029 652.514] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 705 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 633.339 297.029 641.21] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 706 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 623.878 297.029 629.657] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 707 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 610.93 297.029 618.9] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 708 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 599.726 297.029 607.696] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 709 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 588.521 297.029 596.491] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 710 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 577.316 282.182 585.286] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 711 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 577.316 297.029 585.286] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 717 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 528.046 297.029 536.016] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 718 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 516.841 297.029 524.811] /Subtype /Link /A << /S /GoTo /D (4) >> >> endobj 719 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 505.636 297.029 513.606] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 720 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 494.432 297.029 502.402] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 721 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 483.227 297.029 491.197] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 722 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 473.766 297.029 479.544] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 723 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 462.561 297.029 468.688] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 724 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 451.357 297.029 457.583] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 725 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 438.409 297.029 446.379] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 726 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 427.204 297.029 435.174] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 727 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 377.933 297.029 385.903] /Subtype /Link /A << /S /GoTo /D (61) >> >> endobj 728 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 366.48 297.029 374.699] /Subtype /Link /A << /S /GoTo /D (61) >> >> endobj 729 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 318.952 297.029 325.179] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 730 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 307.748 297.029 313.974] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 731 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 294.8 297.029 302.77] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 732 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 285.339 297.029 291.565] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 733 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 274.134 297.029 280.261] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 734 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 261.186 297.029 269.156] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 735 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 249.981 297.029 257.951] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 736 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 240.52 297.029 246.747] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 737 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 227.572 297.029 235.542] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 738 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 178.301 297.029 186.271] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 739 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 167.097 297.029 175.067] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 740 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 155.643 297.029 163.414] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 741 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 144.687 297.029 152.658] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 742 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 133.483 297.029 141.453] /Subtype /Link /A << /S /GoTo /D (90) >> >> endobj 743 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 124.022 297.029 130.248] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 744 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 112.817 297.029 118.595] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 745 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 99.869 297.029 107.839] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 746 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 88.664 297.029 96.634] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 747 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 79.203 297.029 85.43] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 748 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 668.254 522 676.224] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 749 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 659.427 522 665.654] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 750 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 648.857 522 655.084] /Subtype /Link /A << /S /GoTo /D (72) >> >> endobj 751 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 636.543 522 644.513] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 752 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 625.973 522 633.943] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 753 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 615.403 522 623.373] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 754 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 604.833 522 612.803] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 755 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 594.263 522 602.233] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 756 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 583.692 522 591.663] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 757 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 540.797 522 546.924] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 758 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 528.483 522 536.453] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 759 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 517.913 522 525.883] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 760 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 507.343 522 515.313] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 761 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 496.772 522 504.743] /Subtype /Link /A << /S /GoTo /D (4) >> >> endobj 762 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 487.946 522 494.172] /Subtype /Link /A << /S /GoTo /D (61) >> >> endobj 763 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 475.632 522 483.503] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 764 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 465.062 522 473.032] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 765 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 454.492 522 462.462] /Subtype /Link /A << /S /GoTo /D (7) >> >> endobj 766 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 411.596 522 417.823] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 767 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 401.026 522 407.153] /Subtype /Link /A << /S /GoTo /D (4) >> >> endobj 768 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 388.712 522 396.583] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 769 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 379.885 522 386.112] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 770 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 367.572 522 375.093] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 771 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 357.002 522 364.972] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 772 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 348.175 522 354.401] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 773 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 337.605 522 343.732] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 774 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 325.291 522 333.261] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 775 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 316.464 522 322.591] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 776 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 305.894 522 312.021] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 777 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 293.58 522 301.451] /Subtype /Link /A << /S /GoTo /D (22) >> >> endobj 778 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 248.941 522 256.911] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 779 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 238.371 522 246.341] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 780 0 obj << /Type /Annot /Border [0 0 0] /Rect [517.392 229.544 522 235.771] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 781 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 217.231 522 225.201] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 782 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 206.66 522 214.63] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 783 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 162.021 522 169.991] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 784 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 151.451 522 159.421] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 785 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 142.624 522 148.751] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 786 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 130.311 522 138.281] /Subtype /Link /A << /S /GoTo /D (54) >> >> endobj 787 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 119.74 522 127.711] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 788 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 109.17 522 117.14] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 789 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 98.6 522 106.57] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 790 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 88.03 522 96] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 791 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 77.46 522 85.43] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 798 0 obj << /D [796 0 R /XYZ 90 720 null] >> endobj 795 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F31 46 0 R /F2 255 0 R /F38 610 0 R >> /ProcSet [ /PDF /Text ] >> endobj 854 0 obj << /Length 3228 /Filter /FlateDecode >> stream xÚíœ]oã6†ïçWän`ŠŸ"Ø›m·@ØE;ÉnQì.°Š¬$ÂØ–!ËÓæß—”(’¶yÈL;Ó&N‘‹8Îñ9Öûðã<¾(ô¾PÅEI)RL^Ôë7…}÷ýl_]iƒ«Àâ¯7o¾øšã \ U(|qsº¸Y^ügñåCµšþòŠRº¾¼bŒ/¾ì6u³¦7¿Ù,›Ÿ.¯ˆàª\à_þïæïoþvã‚rB2ßÊXœ|-r!‘‚Ù/%$C˜²éK}Ûw÷}µÖñYÜ]^áEׯ/ñ¢Lð/¾¦2ø°(§JG?Š´u‰§_äà¯Ô›ýÏñæéÿŽ”&Š F°ÓJK©ÙŽÿ Ôž­®³Å]Ú©Ó€%*ˆ FðÎVÉ€qI‘à2‚x7ôûzØ÷Mo)(ñ™à…€Zer@½ 4ê=%,Éfˆ2Af¤ÌLÁ¾›à…_JFØôzÛ¾¾ÛwC»¹wÌõë]¬C3TðWÑŸe‰$¦‚(TÂo­®³SüG®Fí(ù{WIþGOøs¥Påî]¶¼«êÆÐ§‹ZæÝfÙm·‰5‚Ê’½¬6ðÄm€KŽJNsm 0ÛÀl3µµÀUª ¤"šPrDÊ2Éw|çÇvx˜^mõÿö·«¶žþ|IÔ¢y4³|l4Àº *ò›N"{©9DÞ Fª¦0ˆÈ»J"JD4ˆô€*g@›eg'ÝÍ%‘‹ýÚ¨«Ó;Í é_=ÿ’_'ÿ³éŸÙQ¡×Ù¦ê…&àÐëÜ$‰Ä¢ø(׃0±cj¿lwÃéÈKtÚTÈÛÖf[§x©@´<ºOh­x9ÚÞ ær$î]%™'"è:Õ’óªí]³î†fêdžßÞîýPÛÝM¿ÿ[`¶j.qc=Ç>—)‚e/:Ë›Á°Bý°¼«$¬DDK/v©5O`5?5u„T}WÝ73QTa‰?C/}ò@©gýmÜu<¬ÕU`vÊãÈÄC}Í$Œãa­Ò\ß‚M.}‰®É%ºš.NÄÒ—èš\"¢ir„ ©ÄÜäú¦ZºµÖÿm£ ç&¡n^¯ïvMÿa‰ênsw:™p˜tcÅŸ"M”!öì’°*Ø›Á€CÍ…{WIÀ‰ˆ06+ü™ïn¨z¿˜®ïÌÀ²ŒoŸp¬^úJ B9I’#é¬`¶¸9:GIŒp8C±ÀÁzøãØ ã †_zža´šä8z3d(o¢GzWI”‰ˆš%S1Qz–}[{˜U]7;`E%õ‚ú¬WT³4¤ˆô@eJ ¤«ÒTDƒTH™“’i7Tžç”MÇ€rލ8ψ'eé³h9ØÞ †êÏÁ,=p•„ˆh`—…žíöõ»ýf ÄS>.ÃôF?æð«ÇXv^T’ç¶Y ¡²—œCåÍ`T¡zÜï\%QE<ÙjfLv¸†·šíº®ûv;ìÞú-Çj·³|õzk¥ÿÒ}yüc誸|-#:ÉÙ<(0ƒ¡Z›Ì&Và* 5Ñ Å:«‘6}¾nj³.žˆ‘E×/ÇSéi‘D ¥çµqœÎ2eN3ðtð@qðt0𔤛hè ìàîûv0—’/,äU»y?1î«zêŽ:oÚ,m¿ì+óÆ*ºƒ¥Ä‚¨ß¤ @=oºÆ\ÇsVp¿ Ä‚l¼£$—ÃpÇ»ÇTqäoÖMÿ—ØÆ°LKu–GpŸjÝ2+™Á˜ü À[E«T HE4-@2_#`ZÀx§[ÁtP÷Ðl‚C¼­É‚]f¤'Ëñ«n<3ª«ÕC·‹nZ2Œhñ¹fPˆˆ½²o E‚W’«$‘DDC¤dã¥%2Ü·v ìÌrÑ ³ê÷±õ‡:£™ê€V¶noã À…«$îDDƒ[PTÜáÞ,nEÊs™!ÜV¶noã $p{WI܉ˆ7§ˆh;› ͸Éb7-Râ[ ç³Gô ¶fÉr¨½Œ:TÞ? \%Q'"ÔŒøÚ›ë‡fµ ¦ÒõZç¶»y–mk3íÚš˜ec¶—6ö”p^žFfU^|Êâ8H}{9õ½¬~(-@õ½«¤ú‰ˆF}J|YÍõvªjÑÊ×me9|¸äå¢êÛê6¾•'$"œŸ÷²r&cÅÊAöf0äPw¦ÞUr"¢L0’ż°Ü®ÆEâ£ÛÚÓÑiýØjôë(f³/ør)C@­09 Þ j,à^ë]%&" X¯w@ÛØr‚ˆQñ &ÄO3Yqs›Á"äDá‘w•l‰ˆ¦Q…/×¹>:%5µ¢Õ½îÝó}ô®RœY1„ØJ•CìÍ`Ä¡êX€ˆ½«$âDD˜¨Â—Ç\ß|õÍ?ín}oælW¾Bw}+]”úå¯=wy]tÖ!Ã/0ùHŠÁ.¸JñKE4üJå«_®ÁÛ9ˆÒ#÷‰Oèȳ ¹†àÍà†²×·«dCHD4 A(W=sín嚎qlceÏáÀ:dÅ`äwf{ÂbµÈœÕx+ð¨&<©ñ~’øàh3¤Ê£û¯ƒ»:w£Æt3bmíqµ\G³5%Q!峦y|+Ö+KÉ3÷VÎVÉ[]”$vßlúÆÊñ¾ÙT$G¯¤ˆ³yIô¸šµç³1Ë ÝÐWC×Û vS­ ÎX1ú»Õ{•94Þ F FÊ(ïD“ˆäÐâo¶Ñl§^Ý»bE%\"q¦÷ed [½r½ 9”žª(dï„|é°0Åa¦Ä¯n"åÖ¦<Åœ Øá`h—§5,X"éºßÛƒ›8¦ýâÍrÇdÇÍ6–j1…—g½èqpµVø ƒ7ƒÛ‰µ™Ú ¶ïl'‰H®•¥0l‹¼ÑMÀ-qÅ…X/dÏaãã—UZ8HVºooó)°èó,7 ïD¤™7W)ÎfÞë&¬>îËÒ¼©,_=ïYº ïÀ ä}@át3ÓÐ Ü@¼S‘o)Ëx ïÝP­·ÓØ}[Õfð~¿ŽÜkì\v¤òVDoC ¥åÑA:pB<Št0E;Š%G¥°ãƒÎ›Á4Æ!ìÕíIC°­l9ØÞ †8-‡a{7 ìD$ÇZp„K—·I±è÷:G·å7moê¿5·êm c¤³±ÒüÅÕà@0­.9˜Þ †J¬¢Ómà„y)ž†sÊçv×ä_ñ"q“…Ûo³ß,›~Ww}Ÿ¸—æìê\ Ú¤ÐÃb™¥íÍ`ÚÖfZY‹(m龜äXj|HÌÄz7W‹Ï[Œ&»ÊUZŒ©˜±Š-S¼ÏÃba/+Ç›Á,B…h<ññn@G‘â=• anççÃ=Íz¨µu‰Ýþv7´Ãx"ä:ûzGöe&´lù˜”g›©ÇE'ËÀ D9É16O¨(#mO³•ûdñªî»hš«Qâåîò;Í­9|Þ ÆŠ àón@|‰H£:b„ÞÛù!Íæ¾Ýá“ôÜî"w&]r,Œ2 需 á0Ž#¥z -ŸrìŒë©RÙ¬¢·¹Q$0yžd!^öúsÀ¼L,”ò´pmDæÝ€Ì‘4¢s Å`hÓã_>´}·YÃe-Š!ò"6‡ vV†;o³ º›w²KDrìtÄ¢À;,L ¿-O*ät‡L¡}³Û¯†éõx ®W“ÉÎëwê©*8Ö5¥tÙ)lHYû%sÊz3XÙðzI¼Wx7 ²‰HNÙ#V$æ¤ýxÏnô¡\Ð×ðÜ2ÅJ•ãëÍ`¾¡êñÓÏÀ È7iæKU$G½¦oïü±ÇüPH²¸šŸˆµJêÞ@žu ›EÈ Ì@rzâèê:p‘;Ž_ÑQQ > endobj 792 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 682.391 297.029 690.361] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 793 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 671.915 297.029 679.785] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 794 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 627.962 297.029 635.833] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 799 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 585.753 297.029 591.979] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 800 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 573.533 297.029 581.503] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 801 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 564.8 297.029 571.027] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 802 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 552.581 297.029 560.103] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 803 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 543.848 297.029 550.075] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 804 0 obj << /Type /Annot /Border [0 0 0] /Rect [272.966 531.629 282.182 539.599] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 805 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 531.629 297.029 539.599] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 806 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 521.152 297.029 529.122] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 807 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 510.676 297.029 518.646] /Subtype /Link /A << /S /GoTo /D (17) >> >> endobj 808 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 500.2 297.029 508.17] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 809 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 489.724 297.029 497.594] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 810 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 479.248 297.029 487.218] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 811 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 468.772 297.029 476.742] /Subtype /Link /A << /S /GoTo /D (65) >> >> endobj 812 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 424.819 297.029 432.789] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 813 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 414.343 297.029 422.313] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 814 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 403.867 297.029 411.837] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 815 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 395.134 297.029 400.912] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 816 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 382.914 297.029 390.884] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 817 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 372.438 297.029 380.408] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 818 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 361.962 297.029 369.932] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 819 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 351.486 297.029 359.456] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 820 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 342.753 297.029 348.98] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 821 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 330.533 297.029 338.504] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 822 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 320.057 297.029 328.027] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 823 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 309.581 297.029 317.551] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 824 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 299.105 297.029 307.075] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 825 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 288.629 297.029 296.599] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 826 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 278.153 297.029 286.023] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 827 0 obj << /Type /Annot /Border [0 0 0] /Rect [292.421 267.677 297.029 275.647] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 828 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 682.391 522 690.361] /Subtype /Link /A << /S /GoTo /D (72) >> >> endobj 829 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 671.798 522 679.768] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 830 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 661.205 522 669.175] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 831 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 616.148 522 624.367] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 832 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 605.804 522 613.774] /Subtype /Link /A << /S /GoTo /D (41) >> >> endobj 833 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 596.954 522 603.181] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 834 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 584.618 522 592.588] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 835 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 575.768 522 581.546] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 836 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 563.431 522 571.401] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 837 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 520.367 522 526.594] /Subtype /Link /A << /S /GoTo /D (26) >> >> endobj 838 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 508.031 522 516.001] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 839 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 464.967 522 471.193] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 840 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 454.374 522 460.6] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 841 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 442.037 522 450.007] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 842 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 431.444 522 439.414] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 843 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 420.85 522 428.821] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 844 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 410.257 522 418.227] /Subtype /Link /A << /S /GoTo /D (25) >> >> endobj 845 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 399.664 522 407.634] /Subtype /Link /A << /S /GoTo /D (27) >> >> endobj 846 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 389.071 522 397.041] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 847 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 344.264 522 352.234] /Subtype /Link /A << /S /GoTo /D (31) >> >> endobj 848 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 335.414 522 341.64] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 849 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 323.077 522 331.047] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 850 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 312.484 522 320.454] /Subtype /Link /A << /S /GoTo /D (14) >> >> endobj 851 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 269.42 522 275.547] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 855 0 obj << /D [853 0 R /XYZ 90 720 null] >> endobj 852 0 obj << /Font << /F51 5 0 R /F2 255 0 R /F38 610 0 R /F72 4 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 859 0 obj << /Length 124 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h C#M]#K3K ç´Ô¼ô̼TM]cc2#m¬¢ia¬QZ’_”™˜£âÅå·ÏÔÈ»ƒ´1%ó endstream endobj 858 0 obj << /Type /Page /Contents 859 0 R /Resources 857 0 R /MediaBox [0 0 612 792] /Parent 856 0 R >> endobj 860 0 obj << /D [858 0 R /XYZ 90 720 null] >> endobj 857 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 876 0 obj << /Length 1337 /Filter /FlateDecode >> stream xÚÝXMÛ6½ï¯ð­2P3â—HöR4MƒlO)b ‡¦@/×+¬-¹’¼Mþ}‡âÈ’eQÚ"é¶[ø`›zš¡æ=·è"†]˜x¡8'FèÅfãêýÅ_+¬zˆ—뫯%]И˜ØÐÅú¶ob}³ø5úñ.=Ô¶\®8ç‘þn¹BF¯—”Òè‡%ÓÑ/þÊu~c?-WLÓDE4æËßÖ?_ý´>y–ŒÍlÍ!.ö¦Ø‚*¨¸·D B¹ð{ƒm0 Ûà´Ù†’¸ ðío„‹„¹[á¹ELT¬ü/=†-41I"A°MQ¦›%3ѽ{H[W`_°èC,ãCZÚÜ­Öw¶²,Q1ËÝ76»´‚ Äûàºç„ò„(®ÀYã„,WTQÿÅÎþýíÅÞµAè™VDS¾HDÒ$.¶Àxs±þµêÁ ú1šj‚]ÍŒ"13}#„·¨ çÌéÒPB ê1ÌŠüCLÅöXZOËÞquÜÕÙa‡+G­j¥ŠÒ­­Æˆ¢’pØÓõ˜ p)•$ñ,•*È$Bš‡ä:DdghŠÇ»K¹!B2ïìÕì |e¹ãŒëöP¹?*ú˜VöƯ¹ÿ.mãÚ­ÿ>.iTùÜ¥£CYlËt?ƵNˆÔ—\‡bÏ8áŒÎ¿ƒ…£þ8þÎÔdü/àVµçäÍ,o —ÿĤ–bv»ÆS•úÌèÿmŠ=œ®OQg{{ʈ.OÚòa)u”î*8VY¾=a$ëö<¾WPJYÿ~„5ΧâŸÍ¤O²øÈj äF(3jìÁ‚jl1M@“ {¦¦Ô8åÑiQ"•y„ÒŽ•Å ·6ßf9j«.üj#D!&õ·»âcºÃÛÊ&G4՛Ћ Õ¨<úìõÄÅH@^§TÏJ°ƒ…%ˆ˜†i‚ìLMJp£“ ôP³F$xSœ)ðcQ£¾šŸ£ùÈh›½_˜Z чa˜£¯ƒ…éëG”Ë }©Iú&<:ú VÅœÐצŸìSÃnwJ(%V¢ 3ÃïH(í·1#’É–ÒwÅÞ^ÖL¨¹²kè¿+T$1ê)ëTˆgŒ×Ï,Ìs?ô2\):S“<<ž÷-Pä‰Qt‘N@ÞçõxóÃ#nꚎ´>µ:9”~e—UõXã¯Â`/ϼ­Nß”¥% dЃÇ%ТV=Ø…†¦“ƒ›æ{fBóþÐÓ8õÒ˜æ$6¾ÞÎQÿÖÑ|>£?z>71Ñ‚þ§³ø£ˆ–ZiäÑ=Xè˜õ=3!¢‡žDKE’vz7Gô»Ã.«¿ŒÌ·€<ª`Ê·#kèñ¸yFOñK•:Kx Ž˜‰“Ý3$|à)@8ЩÚW;ë9Â×8X¶GØ÷Èÿ!÷u+e°~JüÇïh&T¸2R›îôCªj†ÔÀ|@¿Æ€ð Ûþ/ÎFB™žgg‹ ̨Nz=3!q=‹ÓM°\¢öÞωóý“ÑçÑbkQ…9ühúT(MEy k³±6¤76ÏšW[½ ×­XÄ®ýÚ]Š¿<Ù–)Jû;à“#g|lˆQî6Ï¡û I'ð0|Vj,,5Ä4¡PlTj™ Ô&<„Æè‚B:rM+’¶¹…ÑåÙÜfýgÜŽ§È{oHÀ2¤Â ÜeL—Û†)¤&4ö¹ªí~L:BÂaIþïãŸÖ&ªNkÕÐÔ”ÖÆ†©¿£¿Ó: endstream endobj 875 0 obj << /Type /Page /Contents 876 0 R /Resources 874 0 R /MediaBox [0 0 612 792] /Parent 856 0 R /Annots [ 861 0 R 862 0 R 863 0 R 864 0 R 865 0 R 866 0 R 867 0 R 868 0 R 869 0 R 870 0 R 871 0 R 872 0 R 873 0 R ] >> endobj 861 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 625.055 297.029 634.021] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 862 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 573.316 297.029 581.286] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 863 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 521.577 297.029 529.548] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 864 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 461.122 297.029 467.348] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 865 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 439.118 297.029 444.896] /Subtype /Link /A << /S /GoTo /D (59) >> >> endobj 866 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 425.832 297.029 433.802] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 867 0 obj << /Type /Annot /Border [0 0 0] /Rect [287.813 414.289 297.029 422.259] /Subtype /Link /A << /S /GoTo /D (50) >> >> endobj 868 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 627.754 522 635.724] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 869 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 585.595 522 591.822] /Subtype /Link /A << /S /GoTo /D (23) >> >> endobj 870 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 541.947 522 549.917] /Subtype /Link /A << /S /GoTo /D (38) >> >> endobj 871 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 489.328 522 495.106] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 872 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 435.219 522 443.189] /Subtype /Link /A << /S /GoTo /D (72) >> >> endobj 873 0 obj << /Type /Annot /Border [0 0 0] /Rect [512.785 414.289 522 422.259] /Subtype /Link /A << /S /GoTo /D (72) >> >> endobj 877 0 obj << /D [875 0 R /XYZ 90 720 null] >> endobj 878 0 obj << /D [875 0 R /XYZ 90 720 null] >> endobj 874 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F2 255 0 R /F38 610 0 R /F31 46 0 R >> /ProcSet [ /PDF /Text ] >> endobj 881 0 obj << /Length 124 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…h CM]#K3K ç´Ô¼ô̼TM]cc2#m¬¢ia¬QZ’_”™˜£âÅå·ÏÔÈ»ƒ´Ù%õ endstream endobj 880 0 obj << /Type /Page /Contents 881 0 R /Resources 879 0 R /MediaBox [0 0 612 792] /Parent 856 0 R >> endobj 882 0 obj << /D [880 0 R /XYZ 90 720 null] >> endobj 879 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 926 0 obj << /Length 2650 /Filter /FlateDecode >> stream xÚíœ[oã¸ÇßçSøÑ®x‘(>ݦ˜;»h²Ý‡¶ŠÌ8Bl9Õ%³ùöK™W9¼¤ƒ 6c€ñ%GçØüÿHR†‹Lüƒ –-(Æ€‘rQï>dêÝÛP=;gŽÅ÷—¾;Ïáf€e ..¯9,£ÆÍåzñïe³úïåß?üõÒøÉJš,E¢h)@0'S$ñYŠ’ˆ‰Œr¹bdY]mùê Ó|¹¿–?ìÛ†Ëˇ~ú,Ò˜hr%¾ #…ôWg¢|ùÓýt ïîþE^&¾£sC1&®>\ÄU•EäÕÓß|“gw}$&MÇð¢ dåA,ÑH‡¿9z*£3ÇÊHjôÈ•ã8^ž¹Á<ðL"Í1…h‘E Pä*˜„ϲlùëM5z0^6ýôH–õ5o7MËå»U»–O¾Üìå“Z\)Þ–/Æ^Ù5ß%7‚X'8Ê €iù‡‚óUÎ)O@Nr݈!å¥Ñ™µòèqä*¢¼ñ>Çè1 ¢ï*á‘þ¢”tõ¾ýOÉf쪡CˆGF1F‚‹o'ã‹`âÙ¯ A¤IQdÍb¹ò"/GÖO¤h(CR–‰ñË„Iÿà$1ÿÔüNÏ;s‚°$i€Þ&ßÂY.%R .kƒËU{á²~‚pECAÈ@)&¯¼¤²ÒÀef¨ކ§jÓ;[ÞÏæ(²ìø¦é‡®á^!Ïsøú (­[,¡´cQzÖü^¥?!¥ã¡ŒÒ”ˆ”Z¥õ”ô™+T.¿Lÿí»[©iÓN/Þ]W5÷ÏML|ƒò4´<%@ kÇUÓŽõ'Ê€Sd d88Îy³U ÎÅC?ð8òìóù…x€Òlß¹#Š|¾>Œ"Wã4ÞøÓÚB|^œ?7s!½Ô÷NéeÍbz¹è×Ëú ê eô"P³Òz­WµS-Ý‹%ç Q±òì­>?K}|€Þ}gq¢Ú;ʼn5‹qâŠG¼œX?AN¢¡ 'BԜ喓\qòã¾m†}×´µÈÜÝ­Î}|¨ä´0Ï|ÀbÉÃÈ[^¹„hP­š¢ÁšÅhp%òÓ`ýiˆ†24 qh(4 Õ­!aÛ´·þue^žªÏ3ñ()RY³B®®¹!ë'ˆP4”^¨æYyèô !=휯J¼ÛzšÖ«í .›aš{|•%`%<%•Ïî,„š’,…š5‹¡æêïGÍú ¢vj^¿eÙ‚PP†uåEÒÿƇAŽR4_öCÕ |í+¨C\T’—Wý*\7P¼NîX…ëä³¶¦>E7!E#ùP]˜EžBùÃa™1ÊåÃnz1öêO7ÕôRf´*eQ‹J׫ wS—»n¿éªw‘!€Yþ ô_Ýj‰þë˜EúïL¿ÚÖOPíh(£6a €D«­K?+Yä"eèÆz»@ù’¯o‡ãEfZŽFÖ,†‘«-óbdý1І2‰áœz.0…‰ïÇf»6IkuT]àªl9Û€iI`†1@KúúRÛãvÇ L_I7Y@jeuæ˜ù¤>r&3>ïvšã(¨u4–^ „†Vk3E\LÓýx§vFåRu] ¯ýÕŒ àŒª^>T3§ø°f1>\Í|XGA>¢± â=8e/šä㣾žj_ë(ùSæ•wɆjâÖ,Ɔ«ô–DGA6¢±4˜QAhÙÀ&½ä®‰ÞìÇ­š>©,qTéâpÃg%/ouÒ ‘F¿rtÚë&Lhï˜E´Ÿé½…-ÇQHûx,#àƒ²0ÚëªÄOwªqÐõšWS¦Ù»«‡ù²Á'xΞ¶³ùVrЪ…ShX³®\Ð[EpшÆ2hÐ PC†.jÕjR,7ué3ÍBV€æ§õÈó 6R˜PÆ*Æ“£1,¼87Ašb L9y®O™òù?Ƕ5K‘ù!?™ªònWµŠ¬íÃT+ý“üón¶ C¦ÃpiŽ\Š\®ãßx½öÖ3 „-ΠȘó¯±7©ÖÁ’ÝÁšÅúƒ²Šuë(Ø#¢±L—À ¼Ô]‚ê£EçŸ>ÿüËå…DW¢ßtûv7=§ºFw¿Ê‹eÕ5‡×¾!·Ëƾ‘M§öª SÚ[³˜ö®°ôjoµÆ2ÚÃÀŒjíËGõÜa¯†µFÕû®÷f%âç=¡gMÙ”:)¬¬Y +WêVÖQ«£X6~P)ÂÁB¡‘??î;u;Fµ¾_HÌ’õ¡À'Þ©gcçA(ƒbJÇx¾öH™·êïÒGZ9f¾Mœ#g²+z«0Ž£>DZüÝ^,€ANõF{št[õ½ÿ¨HXÈŽ¼„ÙF«—³È°0C!€uÄ.Ë`'–âéãu¦ô÷¯)Ö)„¬òŒWýÐ cð– D£ùi¶y:3ªéSÌX³3®ŽÈ[r™‰Æ2Ì j˜Ñ%Á_Ú5ŸÊ|-_›<4W‰ŸîÃêC'¢ 9‚úÚœDë‘ÉšÅ@rÅEÞœÄq)Ë€$æYˆtbb*Œ%Fv®æ@µ˜Wtíœãuü·)_#“—/s@èË>’VµPJZk“ÖmÖQPÚh,½q€Äã4hiÛcv;£áV•tˆÑØ»³ÄeðÝ !$T˦°f1$\™HXGA$¢± S¥9Hèd£:œpìùÿF.ÖnŸO$ãËû;ÅbB5mŠ kcÂÕ yÏ¡8Ž‚LDci& à Ä2¡“‰þ†o·µ;VDGˆïð\B€ݨ ³ 3…ü48ŽB4ÄcÊ ä[f'¡9__UõTó¼M1`ˆžV#ON"uÛ§ ±f1hfBf^h¬£ 4ÑXš‚L‘…FoGþ:AÓ5C3mÿ¨­ »í¸ÑG\w{yâi ÝŠCØ;È9B8¨VMá`Íb8Ì$òã`qˆÆÒk ˜‹Ä4 —ú ʆ·¼kj'ëTÚ£¹7—Õ¿jüG$§›.þAF‰“¢ÊšÅ¨š)í-“9Ž‚TEcª¦!Ò»áö¯üjÜlÌ2thîü7y•€ rªo> endobj 883 0 obj << /Type /Annot /Border [0 0 0] /Rect [441.93 643.088 450 653.051] /Subtype /Link /A << /S /GoTo /D (1) >> >> endobj 884 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 624.529 450 634.226] /Subtype /Link /A << /S /GoTo /D (1) >> >> endobj 885 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 611.378 450 621.075] /Subtype /Link /A << /S /GoTo /D (2) >> >> endobj 886 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 598.228 450 607.803] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 887 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 585.077 450 594.774] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 888 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 574.047 450 581.623] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 889 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 558.169 450 569.078] /Subtype /Link /A << /S /GoTo /D (3) >> >> endobj 890 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 545.019 450 555.928] /Subtype /Link /A << /S /GoTo /D (4) >> >> endobj 891 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 532.474 450 542.171] /Subtype /Link /A << /S /GoTo /D (4) >> >> endobj 892 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 519.323 450 529.02] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 893 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 506.173 450 515.87] /Subtype /Link /A << /S /GoTo /D (5) >> >> endobj 894 0 obj << /Type /Annot /Border [0 0 0] /Rect [441.93 476.414 450 489.166] /Subtype /Link /A << /S /GoTo /D (7) >> >> endobj 895 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 460.643 450 470.34] /Subtype /Link /A << /S /GoTo /D (7) >> >> endobj 896 0 obj << /Type /Annot /Border [0 0 0] /Rect [444.545 447.493 450 457.069] /Subtype /Link /A << /S /GoTo /D (9) >> >> endobj 897 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 434.342 450 444.039] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 898 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 421.191 450 430.888] /Subtype /Link /A << /S /GoTo /D (11) >> >> endobj 899 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 408.041 450 417.738] /Subtype /Link /A << /S /GoTo /D (13) >> >> endobj 900 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 394.89 450 404.587] /Subtype /Link /A << /S /GoTo /D (14) >> >> endobj 901 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 381.739 450 391.436] /Subtype /Link /A << /S /GoTo /D (15) >> >> endobj 902 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 368.589 450 378.286] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 903 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 344.409 450 351.439] /Subtype /Link /A << /S /GoTo /D (16) >> >> endobj 904 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 331.258 450 338.834] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 905 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 318.107 450 325.683] /Subtype /Link /A << /S /GoTo /D (18) >> >> endobj 906 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.861 286.227 450 298.979] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 907 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 272.578 450 280.154] /Subtype /Link /A << /S /GoTo /D (21) >> >> endobj 908 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 259.427 450 267.003] /Subtype /Link /A << /S /GoTo /D (24) >> >> endobj 909 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 246.277 450 253.852] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 910 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 231.005 450 240.702] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 911 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 219.975 450 227.551] /Subtype /Link /A << /S /GoTo /D (28) >> >> endobj 912 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 204.703 450 214.4] /Subtype /Link /A << /S /GoTo /D (29) >> >> endobj 913 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 193.674 450 201.25] /Subtype /Link /A << /S /GoTo /D (29) >> >> endobj 914 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 180.523 450 188.099] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 915 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 165.251 450 174.948] /Subtype /Link /A << /S /GoTo /D (30) >> >> endobj 916 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 151.798 450 161.798] /Subtype /Link /A << /S /GoTo /D (31) >> >> endobj 917 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 138.95 450 148.647] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 918 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 127.92 450 135.496] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 919 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 112.649 450 122.346] /Subtype /Link /A << /S /GoTo /D (32) >> >> endobj 920 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 98.892 450 109.801] /Subtype /Link /A << /S /GoTo /D (33) >> >> endobj 921 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 86.347 450 96.044] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 927 0 obj << /D [925 0 R /XYZ 90 720 null] >> endobj 924 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F91 928 0 R /F54 16 0 R /F52 19 0 R >> /ProcSet [ /PDF /Text ] >> endobj 974 0 obj << /Length 2523 /Filter /FlateDecode >> stream xÚíœ[sÛ¸Çßó)ôVùÁ(AùÔé:›v;ÛÎtã>íö–h…c‰tyÉåÛ/ \)áÉî¦IlMfb[>:‡ÂÿðàÐx•‰xUe+Nªh¹Ú^dúÕ‡Xw- ®=‹ïn_üùÃ+œ¡*«ðêöÞwq»]ý¼nÛ«k’e˜®oî›n×vø™õÛ\}½½*Ézžú¡­÷Wÿ½ýÇ‹ïom8–ç‰ë‘‰ ¿¥+.^ËWWEÆW×8˲õýN]É/â"÷Í( ëwC;MM§~sw•—ëêûÍ}½¯ç|=ÉËÑè"Z!®…çâêŽqRpõ¥ˆüô;_üï;ÑŠ’ É10Ã,Ä2éée¬®=³€f§Î”fô,&Ëüx>¤E"–ᣨ T–Ž\óñ﹟š­œ†¶ÛAá³\¸aiá¿¿¦÷0M0yf˜–³Lž#¦x, SI'……‰h˜~jvó¾MÍûÇ¡ǶïÂDåô9,%Ÿü>=ê)\œY —…„a\œ#—h,‹ Ï+™Å…j\~˜š¡žÄ’£€éå}è­¼÷4¡};Naxp…puYRïƒHÒ‚¤Hrf1’êò IÎHÒI,‘d`Š-rv#ZQF„s¶~ÙŒí®Sq¶®Õ—ݾ¿éÖñûñÃ85õý¦ïd´›%u}§ÀŸÀ D²á"ÖÙ¨TØ^!4ªÊêÚ3 |ÒSgjT«à¨:GਞÄægÎPÆôZ@‘IÿÖtb~îub(–ñvÛ¨‘ ÏIB£—IùY¤ðÔüsf±ùç«â¤DcYR0¯1CŠI"ÿ3ÚE¼k¦ÝÐÏ@)nù|÷ü'+@0iMR09³L¾ÀLÎS4–‰U%âÌÂd’ÈW­.Sɺ^Ý·Ý^?¡ª¸¸ò˪ó{œddyf²–jg!²ŠL¨Eó U˜^ÖŸ_G´)vœYŒ_O¬s=G ;ÑX–œ#^¹flOªŸË¶ëìÍá\Ÿ>NÁ,C˜áçzò A¢Ç:‰3‹Aâ ǂݤž#’h, ‰(D jnm7éòðã¯2Ó½ùhW}iÿû£@Òz¤@rf1|qœ#¤“Xg ]¤dˆ1}VÇtC—©›d·–k¨—­]ã¢Åë~è»+"nWêÇæ˜ÖÈו°|÷nðÊEUÇ‹O+±€~/óý^žY¤ßk9ÁJÄs úi¬ðì%E%Öu³RØã‹×Ó0o¦y°ó×< ÊU´é»ûà<¦D@óÜ·¤€ii:1-=³È´\ª&Ä9 ‰Æ²„0†ªÂ,öpãõã¾^vP¼éÇIeS{hÀ^]Z\¸k³®Ñ"‘3‹Aä [»pø°·ç”9ËÊœ1$€p2›f¸—M½Ýk¤¾§ ò.ÐÕrêÓÏÚû 7ú=ð„*Ø7Ÿ‘B(èM¡àÌb(,ä £à(Dc™‚W9ÊJC±GÒæy~ïÈBÍhèoF—Zã7nCk è8«9 5Ë8Î ÄM4YA0/Q•W–üÐS½ß×&S$.S”¹ƒl©=6ÅÈ-F¼ã$> åÏïYv=Ô)>œY …naBœ#‘h,ËHÁçnm±ÕÅÍÉ_ 9)8íZò ßð½RZXJigSz1úa¥#§ô¯¸·X endstream endobj 973 0 obj << /Type /Page /Contents 974 0 R /Resources 972 0 R /MediaBox [0 0 612 792] /Parent 856 0 R /Annots [ 922 0 R 923 0 R 929 0 R 930 0 R 931 0 R 932 0 R 933 0 R 934 0 R 935 0 R 936 0 R 937 0 R 938 0 R 939 0 R 940 0 R 941 0 R 942 0 R 943 0 R 944 0 R 945 0 R 946 0 R 947 0 R 948 0 R 949 0 R 950 0 R 951 0 R 952 0 R 953 0 R 954 0 R 955 0 R 956 0 R 957 0 R 958 0 R 959 0 R 960 0 R 961 0 R 962 0 R 963 0 R 964 0 R ] >> endobj 922 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 707.916 450 717.613] /Subtype /Link /A << /S /GoTo /D (34) >> >> endobj 923 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 694.765 450 704.462] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 929 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 681.615 450 691.312] /Subtype /Link /A << /S /GoTo /D (35) >> >> endobj 930 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 668.464 450 678.161] /Subtype /Link /A << /S /GoTo /D (37) >> >> endobj 931 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.861 638.705 450 651.457] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 932 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 625.056 450 632.632] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 933 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 609.784 450 619.36] /Subtype /Link /A << /S /GoTo /D (39) >> >> endobj 934 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 598.755 450 606.33] /Subtype /Link /A << /S /GoTo /D (40) >> >> endobj 935 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 583.483 450 593.18] /Subtype /Link /A << /S /GoTo /D (42) >> >> endobj 936 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 570.332 450 579.908] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 937 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 557.181 450 566.878] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 938 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 544.031 450 553.728] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 939 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 530.88 450 540.577] /Subtype /Link /A << /S /GoTo /D (43) >> >> endobj 940 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 519.851 450 527.426] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 941 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 504.579 450 514.276] /Subtype /Link /A << /S /GoTo /D (45) >> >> endobj 942 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 491.428 450 501.125] /Subtype /Link /A << /S /GoTo /D (46) >> >> endobj 943 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 478.277 450 487.974] /Subtype /Link /A << /S /GoTo /D (49) >> >> endobj 944 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 465.127 450 474.824] /Subtype /Link /A << /S /GoTo /D (51) >> >> endobj 945 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 451.976 450 461.673] /Subtype /Link /A << /S /GoTo /D (52) >> >> endobj 946 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 438.825 450 448.401] /Subtype /Link /A << /S /GoTo /D (53) >> >> endobj 947 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 425.675 450 435.372] /Subtype /Link /A << /S /GoTo /D (54) >> >> endobj 948 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 412.524 450 422.1] /Subtype /Link /A << /S /GoTo /D (54) >> >> endobj 949 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.861 382.765 450 395.517] /Subtype /Link /A << /S /GoTo /D (59) >> >> endobj 950 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 366.995 450 376.692] /Subtype /Link /A << /S /GoTo /D (59) >> >> endobj 951 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 353.844 450 363.541] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 952 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 340.693 450 350.39] /Subtype /Link /A << /S /GoTo /D (60) >> >> endobj 953 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 327.543 450 337.24] /Subtype /Link /A << /S /GoTo /D (61) >> >> endobj 954 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.861 297.783 450 310.536] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 955 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 282.013 450 291.71] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 956 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 270.984 450 278.56] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 957 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 257.833 450 265.409] /Subtype /Link /A << /S /GoTo /D (63) >> >> endobj 958 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 242.561 450 252.258] /Subtype /Link /A << /S /GoTo /D (64) >> >> endobj 959 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 229.411 450 239.108] /Subtype /Link /A << /S /GoTo /D (65) >> >> endobj 960 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 216.26 450 225.957] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 961 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 203.109 450 212.806] /Subtype /Link /A << /S /GoTo /D (67) >> >> endobj 962 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 189.959 450 199.656] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 963 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 178.929 450 186.505] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 964 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 163.657 450 173.354] /Subtype /Link /A << /S /GoTo /D (68) >> >> endobj 975 0 obj << /D [973 0 R /XYZ 90 720 null] >> endobj 972 0 obj << /Font << /F51 5 0 R /F54 16 0 R /F72 4 0 R /F91 928 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1002 0 obj << /Length 2004 /Filter /FlateDecode >> stream xÚíœMsÛ6†ïþ:R!@À!Óq“x¦i&m<õ¡é¡h›ŠÔR÷×$ñEí|zN”˜Õ®´ï`±W±øW<^QŒOØ*ßÄòî‡(_m„ÁƲøùüäÙ+s¸:¿\ˆú×ÚÏùvõWT–åúïó_O^kW¡™X½Å`­`p’¢>Xÿ}EìÓ1]o D$z[äǶ<¬1ŒnÖLI”ÕÛñE~YÔWe]ôßçÙ™øÎ–;H9 DDœá,¥ã% ¼»ÿÍÏ1¹•¾Dä…¥Pÿ|‘ñS†¿´R¨¬6–™#·¹Äwb’؎笷¸kÊŒ!h²J9„s @ñ;ã8Ž.®³ƒ ã¨ìúkuRKÄ¢›ŸFÕH2ñ(ˆ‹"³²}k-éçîÄAŸI%ˆ¤Ñjc™9Ô½í,@’åÈGR8–&‰Å Q# H’t:bôïѨi·ã»æRßeQÖÖe}åFŠ á‚ÔƒG%)¿”dŽ%cbi¢oâdÉ8ò²Œ¥YJ@\³„KÇC³ËeS»haàï:if»}ån±E?Î^•‡•Ö,³˜³ k9òñŽ¥y`@¦÷¾¡jÃ^\\¨¯9‰ã®H(HÒ¥ò¹'»¤ôRŽ9ŽŒYˆ#[[ÆœG^Ž‚±4GÔ>E&> qe—U•Õ…W4QTí<ª:ú˜Þ0ì”b::ˆÏÀ¨¨.K’>Ò¦¯O`>º§¦¡ãt·s§Àtöè^8–˜¤€1#0×zQF4Êò›Q¶w1‰‹:ooö}ñ ÞAwýÉ_2™b¤sä³9¶šÜÙ¢·yÉ ÆÒä$P¬wQ|ç Ìt§ïÃP•JšÚ,÷/`RF€îÔa cÈ•;›ò–#/@ÁX ,Æy¦wŠ‘ê¡žn31ƘE Ž*¹k8öÉ| ”¥‘ú¥«_)ÐYÆ,D–­6wöZ-G^²‚±4YP¯Ø¥z­o÷G=M4júÞ¼{Û™ ˜0^`ú>‡×•zsسv6 ìŒ#/vÁX;qEL7îêÿþ!&;Y 7õ¶< ]à±®ím"e3ôûo|G"(ˆ²§µ4÷‘ :G‚1 ‘`«ã!Á8ò’Œ¥HÀˆõ~3R-Ü®ü¯x.‰©UCnï]„‹¥>±–qèË2J¡´,³Z¹ÝhYŽ|h…ci´(P´Tï÷ØݵX’?Ÿ”݉˜ìúÍúh'܉åzoœ7»°ìÜËpA~lËpŸœ2+sr³œvŠ=rG^9ƒ±´œi"j ½-ŒR½gØã!ȪrÊCS“e£ç[w„•^s ³h¶øÜ¹9m9ò‚v+ÖÇjq¿ë˜¨½KõXíQüÓoo\Ίi‡¤ôÑÙ¯{a|tVåkæ9\Ë,ðî$ùÜy ßräÕ8«×8Ƨ¥?×<‰²¶ÌÞE%%Ñ/õ¶øè|L:ã¢OUìÊ2cs*³Êvú¹ólµåÈ«r0–PÑx¨‡0/š:/ö‡ûLÐ(°JÖŒÀ–Y@àIæ¹³'o9ò ŽÕ ŒHc¹\=[÷õiÿ?ü>£rÿH'OYäpUÆs5*}É¥ÕÆ2sI~ËÙR;§gË“ÑüÕjü endstream endobj 1001 0 obj << /Type /Page /Contents 1002 0 R /Resources 1000 0 R /MediaBox [0 0 612 792] /Parent 1004 0 R /Annots [ 965 0 R 966 0 R 967 0 R 968 0 R 969 0 R 970 0 R 971 0 R 976 0 R 977 0 R 978 0 R 979 0 R 980 0 R 981 0 R 982 0 R 983 0 R 984 0 R 985 0 R 986 0 R 987 0 R 988 0 R 989 0 R 990 0 R 991 0 R 992 0 R 993 0 R 994 0 R 995 0 R 996 0 R 997 0 R 998 0 R 999 0 R ] >> endobj 965 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.861 707.248 450 720] /Subtype /Link /A << /S /GoTo /D (73) >> >> endobj 966 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 691.478 450 701.175] /Subtype /Link /A << /S /GoTo /D (73) >> >> endobj 967 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 678.327 450 688.024] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 968 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 667.298 450 674.752] /Subtype /Link /A << /S /GoTo /D (74) >> >> endobj 969 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 654.147 450 661.601] /Subtype /Link /A << /S /GoTo /D (75) >> >> endobj 970 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 638.875 450 648.572] /Subtype /Link /A << /S /GoTo /D (75) >> >> endobj 971 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 625.724 450 635.421] /Subtype /Link /A << /S /GoTo /D (76) >> >> endobj 976 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 612.574 450 622.271] /Subtype /Link /A << /S /GoTo /D (77) >> >> endobj 977 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 599.423 450 608.999] /Subtype /Link /A << /S /GoTo /D (80) >> >> endobj 978 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 586.272 450 595.969] /Subtype /Link /A << /S /GoTo /D (81) >> >> endobj 979 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 573.122 450 582.819] /Subtype /Link /A << /S /GoTo /D (82) >> >> endobj 980 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 559.971 450 569.668] /Subtype /Link /A << /S /GoTo /D (82) >> >> endobj 981 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 546.82 450 556.517] /Subtype /Link /A << /S /GoTo /D (83) >> >> endobj 982 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 535.791 450 543.367] /Subtype /Link /A << /S /GoTo /D (84) >> >> endobj 983 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 520.519 450 530.216] /Subtype /Link /A << /S /GoTo /D (84) >> >> endobj 984 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 507.368 450 517.065] /Subtype /Link /A << /S /GoTo /D (84) >> >> endobj 985 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 494.218 450 503.915] /Subtype /Link /A << /S /GoTo /D (86) >> >> endobj 986 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 481.067 450 490.643] /Subtype /Link /A << /S /GoTo /D (88) >> >> endobj 987 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 467.916 450 477.613] /Subtype /Link /A << /S /GoTo /D (89) >> >> endobj 988 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 454.159 450 465.069] /Subtype /Link /A << /S /GoTo /D (90) >> >> endobj 989 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 441.615 450 451.312] /Subtype /Link /A << /S /GoTo /D (91) >> >> endobj 990 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 428.464 450 438.161] /Subtype /Link /A << /S /GoTo /D (92) >> >> endobj 991 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 415.313 450 425.01] /Subtype /Link /A << /S /GoTo /D (92) >> >> endobj 992 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 402.163 450 411.86] /Subtype /Link /A << /S /GoTo /D (92) >> >> endobj 993 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 389.012 450 398.419] /Subtype /Link /A << /S /GoTo /D (92) >> >> endobj 994 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 377.983 450 385.558] /Subtype /Link /A << /S /GoTo /D (92) >> >> endobj 995 0 obj << /Type /Annot /Border [0 0 0] /Rect [439.091 364.832 450 372.408] /Subtype /Link /A << /S /GoTo /D (93) >> >> endobj 996 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.861 332.952 450 345.584] /Subtype /Link /A << /S /GoTo /D (95) >> >> endobj 997 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.861 303.362 450 313.325] /Subtype /Link /A << /S /GoTo /D (97) >> >> endobj 998 0 obj << /Type /Annot /Border [0 0 0] /Rect [433.861 268.194 450 280.947] /Subtype /Link /A << /S /GoTo /D (99) >> >> endobj 999 0 obj << /Type /Annot /Border [0 0 0] /Rect [425.791 235.816 450 248.568] /Subtype /Link /A << /S /GoTo /D (103) >> >> endobj 1003 0 obj << /D [1001 0 R /XYZ 90 720 null] >> endobj 1000 0 obj << /Font << /F51 5 0 R /F72 4 0 R /F91 928 0 R /F54 16 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1007 0 obj << /Length 121 /Filter /FlateDecode >> stream xÚ3T0BCKscc=K …ä\.¨h6—!”¥ T ‹¤Â)„KßÍÔPÁÐ@ÏÒÀÒP!$ Ùˆ…hÌ2M]#Ks3 ç´Ô¼ô̼TM]ccc2#¢ia¬QZ’_”™˜£âÅå·ÎÔÈ»{»{&@ endstream endobj 1006 0 obj << /Type /Page /Contents 1007 0 R /Resources 1005 0 R /MediaBox [0 0 612 792] /Parent 1004 0 R >> endobj 1008 0 obj << /D [1006 0 R /XYZ 90 720 null] >> endobj 1005 0 obj << /Font << /F51 5 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1009 0 obj << /S /GoTo /D (Overview) >> endobj 1011 0 obj (Overview) endobj 1012 0 obj << /S /GoTo /D (What is cfengine?) >> endobj 1014 0 obj (What is cfengine and who can use it?) endobj 1015 0 obj << /S /GoTo /D (Site configuration) >> endobj 1017 0 obj (Site configuration) endobj 1018 0 obj << /S /GoTo /D (Key concepts) >> endobj 1020 0 obj (Key Concepts) endobj 1021 0 obj << /S /GoTo /D (Control files) >> endobj 1023 0 obj (Configuration files and registries) endobj 1024 0 obj << /S /GoTo /D (Network interface) >> endobj 1026 0 obj (Network interface) endobj 1027 0 obj << /S /GoTo /D (Network File System (NFS)) >> endobj 1029 0 obj (Network File System (NFS) or file distribution?) endobj 1030 0 obj << /S /GoTo /D (Name servers (DNS)) >> endobj 1032 0 obj (Name servers (DNS)) endobj 1033 0 obj << /S /GoTo /D (Monitoring important files) >> endobj 1035 0 obj (Monitoring important files) endobj 1036 0 obj << /S /GoTo /D (Making links) >> endobj 1038 0 obj (Making links) endobj 1039 0 obj << /S /GoTo /D (Functionality) >> endobj 1041 0 obj (Functionality) endobj 1042 0 obj << /S /GoTo /D (Getting started) >> endobj 1044 0 obj (Getting started) endobj 1045 0 obj << /S /GoTo /D (What you must have) >> endobj 1047 0 obj (What you must have in a cfagent program) endobj 1048 0 obj << /S /GoTo /D (Program structure) >> endobj 1050 0 obj (Program structure) endobj 1051 0 obj << /S /GoTo /D (Building a distributed configuration) >> endobj 1053 0 obj (Building a distributed configuration) endobj 1054 0 obj << /S /GoTo /D (Startup update.conf) >> endobj 1056 0 obj (Startup update.conf) endobj 1057 0 obj << /S /GoTo /D (Startup cfservd.conf) >> endobj 1059 0 obj (Startup cfservd.conf) endobj 1060 0 obj << /S /GoTo /D (Where should I put the files?) >> endobj 1062 0 obj (Where should I put the files?) endobj 1063 0 obj << /S /GoTo /D (Options) >> endobj 1065 0 obj (Optional features in cfagent) endobj 1066 0 obj << /S /GoTo /D (Invoking cfagent) >> endobj 1068 0 obj (Invoking cfagent) endobj 1069 0 obj << /S /GoTo /D (Running cfengine permanently monitoring and restarting cfexecd) >> endobj 1071 0 obj (Running cfengine permanently, monitoring and restarting cfexecd) endobj 1072 0 obj << /S /GoTo /D (CFINPUTS environment variable) >> endobj 1074 0 obj (CFINPUTS environment variable) endobj 1075 0 obj << /S /GoTo /D (What to aim for) >> endobj 1077 0 obj (What to aim for) endobj 1078 0 obj << /S /GoTo /D (More advanced concepts) >> endobj 1080 0 obj (More advanced concepts) endobj 1081 0 obj << /S /GoTo /D (Classes basics) >> endobj 1083 0 obj (Classes) endobj 1084 0 obj << /S /GoTo /D (Variable substitution) >> endobj 1086 0 obj (Variable substitution) endobj 1087 0 obj << /S /GoTo /D (Undefined variables) >> endobj 1089 0 obj (Undefined variables) endobj 1090 0 obj << /S /GoTo /D (Defining classes) >> endobj 1092 0 obj (Defining classes and making exceptions) endobj 1093 0 obj << /S /GoTo /D (Command line classes) >> endobj 1095 0 obj (Command line classes) endobj 1096 0 obj << /S /GoTo /D (actionsequence classes) >> endobj 1098 0 obj (actionsequence classes) endobj 1099 0 obj << /S /GoTo /D (shellcommand classes) >> endobj 1101 0 obj (shellcommand classes) endobj 1102 0 obj << /S /GoTo /D (Feedback classes) >> endobj 1104 0 obj (Feedback classes) endobj 1105 0 obj << /S /GoTo /D (Writing plugin modules) >> endobj 1107 0 obj (Writing plugin modules) endobj 1108 0 obj << /S /GoTo /D (The generic class any) >> endobj 1110 0 obj (The generic class any) endobj 1111 0 obj << /S /GoTo /D (Debugging tips) >> endobj 1113 0 obj (Debugging tips) endobj 1114 0 obj << /S /GoTo /D (Access control) >> endobj 1116 0 obj (Access control) endobj 1117 0 obj << /S /GoTo /D (Wildcards in directory names) >> endobj 1119 0 obj (Wildcards in directory names) endobj 1120 0 obj << /S /GoTo /D (File sweeps) >> endobj 1122 0 obj (Recursive file sweeps/directory traversals) endobj 1123 0 obj << /S /GoTo /D (Security in File sweeps) >> endobj 1125 0 obj (Security in Recursive file sweeps) endobj 1126 0 obj << /S /GoTo /D (Log files) >> endobj 1128 0 obj (Log files written by cfagent) endobj 1129 0 obj << /S /GoTo /D (Quoted strings) >> endobj 1131 0 obj (Quoted strings) endobj 1132 0 obj << /S /GoTo /D (Regular expressions) >> endobj 1134 0 obj (Regular expressions) endobj 1135 0 obj << /S /GoTo /D (Iterating over lists) >> endobj 1137 0 obj (Iterating over lists) endobj 1138 0 obj << /S /GoTo /D (Global configurations) >> endobj 1140 0 obj (Designing a global system configuration) endobj 1141 0 obj << /S /GoTo /D (General considerations) >> endobj 1143 0 obj (General considerations) endobj 1144 0 obj << /S /GoTo /D (Using netgroups) >> endobj 1146 0 obj (Using netgroups) endobj 1147 0 obj << /S /GoTo /D (Files and links) >> endobj 1149 0 obj (Files and links) endobj 1150 0 obj << /S /GoTo /D (Copying files) >> endobj 1152 0 obj (Copying files) endobj 1153 0 obj << /S /GoTo /D (Managing processes) >> endobj 1155 0 obj (Managing processes) endobj 1156 0 obj << /S /GoTo /D (NFS resources) >> endobj 1158 0 obj (Cfengine's model for NFS-mounted filesystems) endobj 1159 0 obj << /S /GoTo /D (NFS filesystem resources) >> endobj 1161 0 obj (NFS filesystem resources) endobj 1162 0 obj << /S /GoTo /D (Unique filesystem mountpoints) >> endobj 1164 0 obj (Unique filesystem mountpoints) endobj 1165 0 obj << /S /GoTo /D (How does it work?) >> endobj 1167 0 obj (How does it work?) endobj 1168 0 obj << /S /GoTo /D (Special variables) >> endobj 1170 0 obj (Special variables) endobj 1171 0 obj << /S /GoTo /D (Mount example) >> endobj 1173 0 obj (Example programs for mounting resources) endobj 1174 0 obj << /S /GoTo /D (Using the automounter) >> endobj 1176 0 obj (Using the automounter) endobj 1177 0 obj << /S /GoTo /D (Editing files) >> endobj 1179 0 obj (Editing Files) endobj 1180 0 obj << /S /GoTo /D (Disabling and the file repository) >> endobj 1182 0 obj (Disabling and the file repository) endobj 1183 0 obj << /S /GoTo /D (Running user scripts) >> endobj 1185 0 obj (Running user scripts) endobj 1186 0 obj << /S /GoTo /D (Compressing logs) >> endobj 1188 0 obj (Compressing old log files) endobj 1189 0 obj << /S /GoTo /D (ACLs) >> endobj 1191 0 obj (Managing ACLs) endobj 1192 0 obj << /S /GoTo /D (Using cfengine as a front-end for cron) >> endobj 1194 0 obj (Using cfengine as a front end for cron) endobj 1195 0 obj << /S /GoTo /D (Structuring cfagent.conf) >> endobj 1197 0 obj (Structuring cfagent.conf) endobj 1198 0 obj << /S /GoTo /D (Splaying host times) >> endobj 1200 0 obj (Splaying host times) endobj 1201 0 obj << /S /GoTo /D (Building flexible time classes) >> endobj 1203 0 obj (Building flexible time classes) endobj 1204 0 obj << /S /GoTo /D (Scheduling interval) >> endobj 1206 0 obj (Choosing a scheduling interval) endobj 1207 0 obj << /S /GoTo /D (Cfengine network services) >> endobj 1209 0 obj (Cfengine and network services) endobj 1210 0 obj << /S /GoTo /D (What services?) >> endobj 1212 0 obj (Cfengine network services) endobj 1213 0 obj << /S /GoTo /D (How it works) >> endobj 1215 0 obj (How it works) endobj 1216 0 obj << /S /GoTo /D (Emulating rdist) >> endobj 1218 0 obj (Remote file distribution) endobj 1219 0 obj << /S /GoTo /D (Remote execution of cfagent) >> endobj 1221 0 obj (Remote execution of cfagent) endobj 1222 0 obj << /S /GoTo /D (Spamming and security) >> endobj 1224 0 obj (Spamming and security) endobj 1225 0 obj << /S /GoTo /D (cfservd protocol) >> endobj 1227 0 obj (Some points on the cfservd protocol) endobj 1228 0 obj << /S /GoTo /D (Deadlocks and runaway loops) >> endobj 1230 0 obj (Deadlocks and runaway loops) endobj 1231 0 obj << /S /GoTo /D (Configuring cfservd) >> endobj 1233 0 obj (Configuring cfservd) endobj 1234 0 obj << /S /GoTo /D (Installation of cfservd) >> endobj 1236 0 obj (Installation of cfservd) endobj 1237 0 obj << /S /GoTo /D (Configuration file cfservd.conf) >> endobj 1239 0 obj (Configuration file cfservd.conf) endobj 1240 0 obj << /S /GoTo /D (Security and cfengine) >> endobj 1242 0 obj (Security and cfengine) endobj 1243 0 obj << /S /GoTo /D (What is security?) >> endobj 1245 0 obj (What is security?) endobj 1246 0 obj << /S /GoTo /D (A word of warning) >> endobj 1248 0 obj (A word of warning) endobj 1249 0 obj << /S /GoTo /D (Automation) >> endobj 1251 0 obj (Automation) endobj 1252 0 obj << /S /GoTo /D (Trust) >> endobj 1254 0 obj (Trust) endobj 1255 0 obj << /S /GoTo /D (Why trust cfengine?) >> endobj 1257 0 obj (Why trust cfengine?) endobj 1258 0 obj << /S /GoTo /D (Configuration) >> endobj 1260 0 obj (Configuration) endobj 1261 0 obj << /S /GoTo /D (Disabling and replacing software) >> endobj 1263 0 obj (Disabling and replacing software) endobj 1264 0 obj << /S /GoTo /D (Process monitoring) >> endobj 1266 0 obj (Process monitoring) endobj 1267 0 obj << /S /GoTo /D (Monitoring files) >> endobj 1269 0 obj (Monitoring files) endobj 1270 0 obj << /S /GoTo /D (The setuid log) >> endobj 1272 0 obj (The setuid log) endobj 1273 0 obj << /S /GoTo /D (Suspicious filenames) >> endobj 1275 0 obj (Suspicious filenames) endobj 1276 0 obj << /S /GoTo /D (Checksums and Tripwire functionality) >> endobj 1278 0 obj (Checksums and Tripwire functionality) endobj 1279 0 obj << /S /GoTo /D (FileExtensions) >> endobj 1281 0 obj (FileExtensions) endobj 1282 0 obj << /S /GoTo /D (NonAlphaNumFiles) >> endobj 1284 0 obj (NonAlphaNumFiles) endobj 1285 0 obj << /S /GoTo /D (Defensive garbage collection) >> endobj 1287 0 obj (Defensive garbage collection) endobj 1288 0 obj << /S /GoTo /D (Anonymous FTP example) >> endobj 1290 0 obj (Anonymous FTP example) endobj 1291 0 obj << /S /GoTo /D (WWW security) >> endobj 1293 0 obj (WWW security) endobj 1294 0 obj << /S /GoTo /D (Miscellaneous security of cfengine itself) >> endobj 1296 0 obj (Miscellaneous security of cfengine itself) endobj 1297 0 obj << /S /GoTo /D (Privacy (encryption)) >> endobj 1299 0 obj (Privacy (encryption)) endobj 1300 0 obj << /S /GoTo /D (Trust and key races) >> endobj 1302 0 obj (Trust and key races) endobj 1303 0 obj << /S /GoTo /D (Adaptive locks) >> endobj 1305 0 obj (Adaptive locks) endobj 1306 0 obj << /S /GoTo /D (Spoofing) >> endobj 1308 0 obj (Spoofing) endobj 1309 0 obj << /S /GoTo /D (Race conditions in file copying) >> endobj 1311 0 obj (Race conditions in file copying) endobj 1312 0 obj << /S /GoTo /D (size= in copy) >> endobj 1314 0 obj (size= in copy) endobj 1315 0 obj << /S /GoTo /D (useshell= and owner= in shellcommands) >> endobj 1317 0 obj (useshell= and owner= in shellcommands) endobj 1318 0 obj << /S /GoTo /D (Firewalls) >> endobj 1320 0 obj (Firewalls) endobj 1321 0 obj << /S /GoTo /D (Summary) >> endobj 1323 0 obj (Summary) endobj 1324 0 obj << /S /GoTo /D (Variable Index) >> endobj 1326 0 obj (Variable Index) endobj 1327 0 obj << /S /GoTo /D (Concept Index) >> endobj 1329 0 obj (Concept Index) endobj 1330 0 obj << /S /GoTo /D (FAQ Index) >> endobj 1332 0 obj (FAQ Index) endobj 1333 0 obj [355.6] endobj 1334 0 obj [314.8] endobj 1335 0 obj [599.5 571 571 856.5 856.5 285.5 314 513.9 513.9 513.9 513.9 513.9 770.7 456.8 513.9 742.3 799.4 513.9 927.8 1042 799.4 285.5 285.5 513.9 856.5 513.9 856.5 799.4 285.5 399.7 399.7 513.9 799.4 285.5 342.6 285.5 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 513.9 285.5 285.5 285.5 799.4 485.3 485.3 799.4 770.7 727.9 742.3 785 699.4 670.8 806.5 770.7 371 528.1 799.2 642.3 942 770.7 799.4 699.4 799.4 756.5 571 742.3 770.7 770.7 1056.2 770.7 770.7 628.1 285.5 513.9 285.5 513.9 285.5 285.5 513.9 571 456.8 571 457.2 314 513.9 571 285.5 314 542.4 285.5 856.5 571 513.9 571 542.4 402 405.4 399.7 571 542.4 742.3 542.4 542.4 456.8] endobj 1336 0 obj [569.5 569.5 569.5 569.5] endobj 1337 0 obj [514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6 514.6] endobj 1338 0 obj [1200 1200 1200 1200] endobj 1339 0 obj [333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8 527.8] endobj 1340 0 obj [525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525] endobj 1341 0 obj [525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525] endobj 1342 0 obj [525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525] endobj 1343 0 obj [555.6 555.6 833.3 833.3 277.8 305.6 500 500 500 500 500 755.6 444.4 559.7 722.2 777.8 500 905.6 1016.7 777.8 277.8 305.6 544.4 833.3 500 833.3 777.8 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 305.6 777.8 472.2 472.2 777.8 755.6 711.1 722.2 766.7 655.6 627.8 786.1 783.3 397.2 516.7 783.3 600 950 783.3 750 683.3 750 759.7 555.6 694.4 769.4 755.6 1033.3 755.6 755.6 611.1 280 544.4 280 500 277.8 277.8 486.1 555.6 444.4 555.6 466.7 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 427.8 394.4 390.3 555.6 527.8 722.2 527.8 527.8] endobj 1344 0 obj [613.3 562.2 587.8 881.7 894.4 306.7 332.2 511.1 511.1 511.1 511.1 511.1 831.3 460 536.7 715.6 715.6 511.1 882.8 985 766.7 255.6 306.7 514.4 817.8 769.1 817.8 766.7 306.7 408.9 408.9 511.1 766.7 306.7 357.8 306.7 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 511.1 306.7 306.7 306.7 766.7 511.1 511.1 766.7 743.3 703.9 715.6 755 678.3 652.8 773.6 743.3 385.6 525 768.9 627.2 896.7 743.3 766.7 678.3 766.7 729.4 562.2 715.6 743.3 743.3 998.9 743.3 743.3 613.3 306.7 514.4 306.7 511.1 306.7 306.7 511.1 460 460 511.1 460 306.7 460 511.1 306.7 306.7 460 255.6 817.8 562.2 511.1 511.1 460 421.7 408.9 332.2 536.7 460 664.4 463.9 485.6 408.9 511.1] endobj 1345 0 obj [1000 500 500] endobj 1346 0 obj [583.3 555.6 555.6 833.3 833.3 277.8 305.6 500 500 500 500 500 750 444.4 500 722.2 777.8 500 902.8 1013.9 777.8 277.8 277.8 500 833.3 500 833.3 777.8 277.8 388.9 388.9 500 777.8 277.8 333.3 277.8 500 500 500 500 500 500 500 500 500 500 500 277.8 277.8 277.8 777.8 472.2 472.2 777.8 750 708.3 722.2 763.9 680.6 652.8 784.7 750 361.1 513.9 777.8 625 916.7 750 777.8 680.6 777.8 736.1 555.6 722.2 750 750 1027.8 750 750 611.1 277.8 500 277.8 500 277.8 277.8 500 555.6 444.4 555.6 444.4 305.6 500 555.6 277.8 305.6 527.8 277.8 833.3 555.6 500 555.6 527.8 391.7 394.4 388.9 555.6 527.8 722.2 527.8 527.8 444.4 500 1000] endobj 1347 0 obj [625 625 937.5 937.5 312.5 343.7 562.5 562.5 562.5 562.5 562.5 849.5 500 574.1 812.5 875 562.5 1018.5 1143.5 875 312.5 342.6 581 937.5 562.5 937.5 875 312.5 437.5 437.5 562.5 875 312.5 375 312.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 562.5 312.5 312.5 342.6 875 531.3 531.3 875 849.5 799.8 812.5 862.3 738.4 707.2 884.3 879.6 419 581 880.8 675.9 1067.1 879.6 844.9 768.5 844.9 839.1 625 782.4 864.6 849.5 1162 849.5 849.5 687.5 312.5 581 312.5 562.5 312.5 312.5 546.9 625 500 625 513.3 343.7 562.5 625 312.5 343.7 593.7 312.5 937.5 625 562.5 625 593.7 459.5 443.8 437.5 625 593.7 812.5 593.7 593.7 500] endobj 1348 0 obj << /Length1 1256 /Length2 6221 /Length3 0 /Length 6966 /Filter /FlateDecode >> stream xÚ­•eX”k¨é.AZ`ABbhî®A:†nF:¥»AABº%%¤ABJZ8ãÞçÛ›ó}Ï5æ~Öz×s¿ë‰—…QK—KÚfV€9#¸€Ü@1€¬º äæÅca‘…ƒ-˜³œ%,ŠŠÒîv>d\HŒ_@Œ_ sñ†Cìì6Yö?IÂi'0bmé P·D؃5¬-¡]˜5ŒðæHC¡?O¸tÀn`¸؆Ø@¬+°Äç²³- ü÷°»ËB`¸R À†”d m`ÎPo€ ØG†œ Œ4ùÿ!õßÅÜ¡P K§?åÿ4é–N¨÷ÿM€9¹¸#Àp€:Ì wþïTCðßn20èÿÌ¢Œ°„B¬¥í `ïßC7ˆØF ‚°¶ØZBÝÀƒmþ[Ùµ¿xÔ”õAúŠœ¯æ_1-Kˆ3BÏÛ埪’ÿb࿌ì â0æåæå"‘¿ÿü3ý¯¹ä­a6gävXÂá–ÞxÈ}$A€/q¶{À^HangùÙ€- Ž÷g1…„<²†þ&Qü?$ÌàQþ—D<ÿ2SóðèýK‚ý ™iô!wå¿„¬iõ/!3­ÿ!AdÌEî°ÿŒyy<6÷àßC>í¿ø‡ ÷¢È—±»‡Hcû{ˆT¾Ÿ,àq¸‡HiÇ{ˆ4ƒÞC¤¶Ó¿ˆ\hž{ÎÈÅ»‡H-—P9 ò<Àî½)êz‘¢ð{ˆu»‡Èˆ{ˆu¿‡HQ{ˆõ¼× ¤¨×=DŠzÿ…ÿ»™ed`^¾\B|.>AÞ?„yýÿŸDkw8ìŒøëš@‰ÿ°-y€À`/°5Þü,ÌúÙK‡´æðòùÂϘ¨2vï4;§>â‡Î%¢BK†T]9–@W•™dD›˜› ž7´nQm~Ú£ ?ƒ]Ògn7=,63}ZhAÇ™êÞ.L硻ĭÍÓ§{‚¨š“KÃåÉFE½9‡}»ùZlrz[Ø Œ(]ÆM]Y/…„A ™Pýˆ°V~F’t×òHˆEO’ä׋ã¡8ï9¿ÁÚÜI¯ qò’nÍQ.­±¢£Ýh"¿ ð ¿îÓJ…ø·,7 s‰ ~ _ËݪzÓ\þvL§†¶sãÅwÎY/Ï–3æµMôWkr‹ƒ•´âÖ! sý—3í·ÃT\uk©$'h*/Ä!J6EkÁQ«4¼l„DÏÀ2¥.‡J'ÔØ¯è+£ \î<õ³£¬ï«²%mº­ÉX:ð2*¥Ÿ}ýZø–F’"½Ì`Ï_ÀA¤µ®À¹a(‘?‡£¸ý…`¶Å¨×¡>‹pØHê¯Y—ÊõTDhÌ3V?°õ ˜¦‡.üeµY¢˜I¶ž_K©bÈD•qw{·A ÊöqûÓoôëU3YK­-:bëª ý“"Ô]UŒƒzl5´ÙR.Jˆò½xYŒ´»óp|Œ 5:¹¹/sþMG4c¨oÓÛ·89Áã‚eØ¢*h°5 Ì ˆ1)YjlBÜ(Ń-ê2׋°|o¬s_c®+‡M—4;Ðf`”f·Õ s{»V„è“liñü29Á 9 z嘠‡¶cq‹¯xÒ„¾4˜:6º|´Î˜æ_ó$»Ãë0¬hÃÄyå§´K¿Ávnœ_ãrEoƒ<óçÃ"§jJSöI?>½ zâ/³Ï¸ã´Îû ßZjä ßmTê4Œ>¿]ºG¯»Æ<½e> õ!Løê‚üF&#>·úÓ®ÝtÁ ª¾6oô ²uÝ;v_å4…G”æS«Å%&ø)·×ÁÚ"„‚.üËÉ_®:ü ÉßGX²›Ho õzP_ž?Š[.@ipœãa<ê}g¦}þÊâò}di,»%<¯iþU>“„$M0‘ž:ºD°ibO~ËÎØS(ÿTÂp)ŒìÍ/Ôâ§Éá›24c‰&AjÉR›âs½e~?FÇSÎ1Ç(ɲl³Þ¹ÎPGõ´ã¦=¬+X¡2îÛšRWÞ«‘ÑÏV)O3ùã½*8”äÝ6÷¶ÂC¢ì‡ó li»g‰´Ù–.9´Ê:2ñ 7{=Êæº#¥ÛŸã¾wqÈ“%¶M­i3P/wh8Ðùe³µ<êŽÿ\ß3K™aó˜1z½tfž¢±e,¼{ÎÀå÷cËÅrI£jýë"ƒõ6 oûÖ°šìá3ßÚöôÓˆñ`÷™¸ÙJ¼)1*S¶Vž&Ä(Æ\-@Ÿ´Jn.ßcâ°köî5Ÿ) YµºÔ—ÌÕöT©Éæ¨ÜáN×L£2PÒ'§ŽõÏn)Ä=ž4Ùt\} ûö ßäÚ]k~—¢<íjH°"›¾Eä ÞX» Ì¯Ñør#ÎáûÊV¢fÄîøóªÆD§ú ÍùÁ@Û%þH/Ź© 8§¼›  úÕ7ß"Idî¼–ó×Jç¥6àfÇd¹ÖjXÒ…t5\à1ñOŽ|É^{«†Zäyá\é½K„ÿá\9Ô´—¶R‚|ðƒ„¾žxjJHj¤C“Èáµ/½²OzS¤¸Õǰ=ÖŽ0pXos™®cXÛÍ•ºÝ±¬h烥áÄWÏ>þ´^$í… –Ò•Ñc¼Þ#Mj(rp«TG9çð ü)V~sÑ¢Îû–üFéÚE¦òÝÓ 6r@£³ÜpÄ.¼›nnUýÇÁ™&ð'Kk ëÂ㸄aß‚‹šúTi€ ¤‚Ó7z›>PÒü{^ZxëëQUNUÝT˺ƒŸM,½KŸ³QZÔÛãpÐøÚ„³]06öbùUW¢ò³Qªrâ>!ºzFÖd“Q6öÓcXøHÆÏ;øÝPn~NÙDÐvcÚ¿”­†~8‘ÿ×jÃ_´™òÍLJîiø*îuÝîbû°iÊÎ9íêž‘užœ4MñÝ-¹DN³lb÷ˆá§QuòïÇqð]Ç b¹°–fÛ·¢­dI‚J7‡¹örÜQœêžµBYïT6Y¬´”UËñ>â½ÈÒá,äKÅU¬Ê§¢§˜´xÍÕ“‡Í»‡Ãmn-(ÂÜ+0Ñà -êúMÀGáßU9‡G¯iÎGx”s©Š¶IW¬p†'Ä9Jb6÷ö<àMûâòq€É,Ûæ”v|÷P}7{y°¾ðбk wIïKýÀÌ¥²'p|bZu”X§ïÆú}ôæVå»Í«¡>Ùs ΠN›@@tZêo3Ú6åÐùÒŠ¼¥"•6£[ íwYõ‚µµÐ|Юù-úIG#A'S{Èë¯f\/ /ìÖnгᣫ³;ê0¹8O…’=‚4§yZ"õmº ˆÏ—ªWà ÒoªžD&|€<$-ÆôÍB¢T@tY(*…~ž}ìæÙ׬õó„˜wXçù=oµIUoA¾Í%ù^VRLQÅŒÐa.é¥ /-lú\Öû9\édã¦í\¼¨s 0j( -γGÀPÿÍË7D*ÞÄVfä÷ÐþS„µ@@#¦atœ£`å\AÈ‘›èºÐð!ëàS¯üòqú‰`¬YV»º²¨'X€aÖЋÃ;ty¿óÅÐrlk|§Uz¬IP_j gýrŸBíM~,ÆÎq6Œ0t5È6_¿È.0,Ùè£:ç=ןÅ@yÄ z¼ìѵ£&KgÚJu®üK8À×gŠ;—šBKý”O÷¡]PQ;·\µ6åuY8â»Òɧ¦—a‹Mª,y¯‚":ìlWc½.¹Ô–¼$G™?P”zN·s iw£)o8yø¥# Ú;#ŤQB‰ÿ íŠB8–JLÐ?duЙÒ8^JÐÄun%™Bs8ˆïPœ¤þ“ûçÓYyŸÖ¨yVT{¿jDƒX j;Î÷Z;ù(vlãOü®ÍRÈûø´äôog¶ª·†æ~Æ(ýÏL3€SõšÆ¨ë2$.vJõ»“ÛæÒÔ%Ø=lt¥|HR®6`×™Ï÷M`rÌ, ¢.rCµ7edª.ïê ,o‹!ßk“•N¶çP[ÌÏí‚»2ý·žÀ#Rqn´:gùÎw© ˾ëÝÚTq߯²¶J„œVOΈ|`”Îô•®v‚àÞˆ+‹ù’_§¾:÷tbIƒyg«gtWëØ îŽ)mšH˜"N«Ï¾ž{f‰¯Ø“h–ƔؔÅu ƒæÉ›Ø?¼ïéöRâ7²§ÕÙ(’ÒßœÖ3%¿m•ä´"¹4ç÷z²1®‰6Ä;oõùš Bà”£^•=‘bà˜ÃY‚3”kÌ}eàBÕ®~¤ýxé鬰º*¦xÓÛÈÑ×OXƒÁ¥Mrl¦’Íõ”“RîëÛS®-²¾×O.Oz4q)Dµ>‚–töJ›‘œ1Ì\6Å%±5î?Å\+Ô}¤¨å²É¹¹@}ò:“N“Ç•;¥õUÜO|oQóGÎ¥«”º¨å˜û°6‹.øFrã€*£TdÆ%³vþçîŸ7n×i€“Ls ¨>oíV;Jç;—mW‚w ã`Ÿ÷å{¯È¢uº¸Œ3k0ÉÏÚÈ”zgÔ½>Ê8sŠ­Fð~µ0y˜†¶)˶òÄ9€g¢ê#ªŒ.cÚ`ºì|q±ß&gê#ðO¥#*¹¥{%Fon )B³mJ­ì¦ðƒÔÚþNi»åfênÛY(3Фª álöœ"ô{Ã\‰wåm›©„|ËR„ǪCK¸ƒîH…^¶~1{×µº|sT!tš3âS•“ª÷fg¨ð#pÁèå²¥kÕõN['À)höÕ„©_OÀ|u¬"Jÿ1H¬ÂD'ÝŸ4OpöBVÌ›§xÄh’ú£þ½–Žã£‚]…î„r—Ó­ÿ“±Z?Tœ¡çZÕ$ìi]ˆ÷öùÑö˜Ó…Z 7ç_A$~ŠaÒxȺ’÷…t ñš–YÏ埤s1T$=Ø&QŸlÏ £jY¦· LGëIë«ùzL»Ê „;hÛ·¶ªæ÷”Vq|ùØ·oDù>£´ª¼ë/ª‹-"ŒKúæ1°°ÇªÏ5V½î½¡ê.1‚ø4—²+Pd÷³ï¸j¹µ‚ÑðŠ¶á•¿ eƒáóчûÒ©kÁìö…ÛZXÅ=©ß;…¦ÜR›NYù:Žûâ,ý²0zž›ivàpü`úõûêênÕ ýéÖ•zõ6²°ùÃÍÍH¼5{Üo\~—m­wœ„zõàK¯)ÅÄGäâÒ3– ™©—Ñ)Œ§qû¼ÔÄmï Ø'îDÚÂ?Ù÷¿æWÞŒ#.@L@ÐѾ­þš õšúF34¿§/1ØaÒù‚嬚Nifdü®þú¦©gÂA'‚źW;vŠs>³Õ´R—}Ù›$¥ÓlzdÏEtFo{­‚îM+ªÕ¦yr«ž©eìüÌö±:/­@~ó  ÔÏÒU–ó$’8¦¤é/~5©ìL’±æNI çÚzœ‘É+æRã–`¯éš¿Þ8 tA_ú¨,iSýùÒ@·@jB@8Õ…Á‹wÑÛ|â‰IdG …Ã꽉þwü^;Œg*˜<•™[ë±|y†šœM9€W1 æ9l}¥Ü!¤‘î(,_^¥ÈK¬s:-Bã÷ý•x§QÙ×ïçC?jÕ‡é‹MRIаÖÄмWŠÛ±5³%1ò4öï óºM‰´½„TÖ9ȉ ›£/$ -ÜŠËŸð§ÞÄu¦ÿ8ö•"Û!î‘ÃÃ+UÐ"YÄz³þ¹´w…:ìNdò±¸Ò pùMý»SibÏ€ ž$oîÜÖzš¾ñŠ¢1÷×]”»œˆ)ò¢_ã¬XÒçð;[Ô„“æUhcO“0}YU?0K½F—ê㕤œ—éOwÌ‹Sc[;χ˜Ÿý˜1¦b’¼þvÑ‘ë~Òš ìòÇ7¿¿2¼: —ùÌëžà·TŒ…í+ö?­-öîœ=Zÿ0“œ`L<ÖH±ŽzxM%·¢•àŒÅÃ6ÒBq±H,3**ÞÈÇŽOqkó™ŠìSLAÔYÒ§÷> "¥›×"Ž¢9Uöç8%^2VµêÞÕüWá)†OÒªÔÃ/fpOWò*BE½ÞR›jq"a¡Kz³^ª)ßéZÕ@¼¤ä·ÐWø+¬5u—TB(ß›ÓiIÐ?Ï£·H;ÝÅŸ7örÕjdS ûÍÑþ&uk¤eM ’'¨óžÄ]š= ·Ð€²“ëmAJw-f;<#é$ŠÉyÍòVZ6³ "Çôy³Õ¿ð'‹¯qú4ðnúy¦‡õåst4‡]¸Ï†SÜR?¡5ÌšWûTÆŒÀE,¨£”Uôæ%U+8y w©’­Ë£[Oo=P§×°0A3wêpÌ`0ÕŸÕ¨°_ÇB*dÁ§¾8ùF1(!aEOÔÕ89s 258 ªVXÒLÛnûî#n¤ºuô^3ͨ rµ»ñ•Œµ5a«æœŠ˜ÄÉ6 Ú›*t¨Pè µE“Z¼‹€¢9Lw+£¿Vp€WkˆÞͼ¤M͉¯¼Ûö•HF†YéœE’äVO4_[RøÁ.çÉžŽ/&lkÝ5’3kàIJ¯“›ë%tÌöç£i»žáÏΰv-ÞòMmª¾îÛ°pa¶–ˆj*CVÇvFÔÈȨçàoMa°Í;” K©Ê¥gOnåokò½¦_±¨U¥`ƒwöÁqxá\’Ì™=¯ó¶õf¸ùn€$НWß¼*ZœÑ­¿–«‰È5÷™]§x<§ ".4 äýV6q,›Pgøêp§Íp¦åìDñºS_>²@,`G “x4{GqšgœsÓpè?@Iw9þÙßÐÓ/áT¡Ö.oW\_‹ë>ÙõÜàË»ò0[ÎÀЈÏûœôk}w;XÁÌMK„FÏðÍS>Ê:aõ/¤ÐøK 2ìyꩼgF—•"J$Õ4D‘dj.³Išdò'Uçöº‰tŽ;ÞàM‘ÙÀ7äy>›=½°&>VÏÕ{Ø2 'Àº”}1)¯JXäÁeé°ùÝ$ëdÚ8ËÇx_OßÞRÈšâûb“â…ü€xŒ1ëÅu¡Ñº…@*­Õ ]](úu¢¿H‰Æ< ᛕ§ƒÉFÛ\ìÑZ‡2øÅŒºgÿ'Ÿƒbüå©Oyš˜V ?ˆ ¿ðrTIŸ4èU¾'yM¶~¦ F»d é¤èk/?Ô膔bTA?MJÊMJ¤áüˆÑÎ^ÞZ[¯ F2H©Œ3ÔÙæŠ('<‚â‰Ö ò.—Ž:t¾G:I“qNMÕX’/s‡"“×AÚ4Ê¢c¸¢óÖÛqËg$ësö94å:=Q¾JÝÍFÔz§>–¥yþg˜yL¾›ô~õ/Æ¿ƒ¼ÿmßàTQwÔ¼*ò"—›±I!¬ã†%G C¡‡&õ‚Ð s—b8Í•_¤œÄží¹-cx {RUâÖÍô`ŸõÍ3™GªnFØÙáëK«ô䓱9:QMójñ¨¯ƒ¹\„í~?7‡z{õ ¦çõ¤¢ÐV¥jô¡Žx¾¥×_íß;TfÖ9'Â:%Ý{”õqî)F;%è]v÷¯.ÿ¦—™í6èM°1ŽM$1‚•‰§Ž?^wFv¼n'öö°Mdºþò[_hí‹®®|‘UŽcê€MÓé'Qªa°åÙ"tÅìhw[kŽ}y#+,ÇÆ"ezZ•Ó?Aæß_jjécO+iµJ¯5NSŽ OÃRɶå›uôêBÑ(Ť =X°[Õ¦hÙr ½ò^"ëþ]öÂr×[+ÿ‰F‰Nœ×¥b!|TqˉR^ÌŠr Öqì z[GWœv›¼È\#ýµuwú›7ƒào)ß$„•.­½3¶J'‚år)0Z`ŒP rY³ö(È=,–|¯DÀ[œZ; €¢½¢¿'?þIÊÜ#‰íP#f)‚SÓêhú0|4y ý3Ãa#ç·Ô /MäÑjý;ý.»k$¬Ôs¾¬X¶q"(Dl(»\ÙUa“†gh7D6±w×øÖÚ4©¢_€dyÅv—¯]N¿ýþ@c?j¹jJioÖÏãdöT%¾0ÚW˵áÒÓTÒ^·k÷Ì1‘îv¦n¡HG¬6ìèƒë©YƒT— L=%­Fû˜‘÷Ï‘VÂPyšùŽÂ‘ZQïq£ ~Ú™™ï&±y€ž³«óÃ…yô¬Ëº.³TéG=#´ã%;¦Á‰óe'‚èèi^Úæû´Ýa¡š¢µ’§&-5Å›rñ˜¬¨^ÄXtd̵WÏzgd3%ÇãÓ«‹M^W«{†#¯9™&ž…!ÑÄÛÍhõòÓ'e1Î;Ѓ³ç0<§§Æõù7Qùõÿy ¬{ endstream endobj 1349 0 obj << /Type /FontDescriptor /FontName /LIUXUG+CMB10 /Flags 4 /FontBBox [-62 -250 1011 750] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle 0 /StemV 108 /XHeight 444 /CharSet (/C/E/I/N/O/T/U/Y/a/b/c/colon/d/e/f/fi/g/h/i/j/k/l/m/n/o/p/period/q/r/s/t/u/v/w/x/y) /FontFile 1348 0 R >> endobj 1350 0 obj << /Length1 1858 /Length2 11701 /Length3 0 /Length 12716 /Filter /FlateDecode >> stream xÚ­˜UT̶­àwoœ [pww‡Æ¡qw Ü‚;‡àOpw àÁÝõvöÞç'ûœ×;xá«Zµæ¬YEu¨(”T…ÍÀ& °½ # È •Ѳ€L,ÈTT¢N c+°½˜± ˆäá„]-¬, '/;/;2@ìàédeaé ¥ûSĶ9Y™Ûä],Av¦Æ¶U°©ÈÅ“ lk Pù³Â r9¹Ì˜@€™•© ÀdaeÌüÇ‘´½9Àõïa3W‡ÿ™r99CLh!&é‹f`{[O€È™Y ÑAœüÿ0õ¿›K¸ÚÚ*Ûýiÿ¯”þϼ±•­ç*Àv®. '€<Ø ädÿ¿K5Aÿ6'¶ý?2Ò.ƶV¦Âö¶ Ë¿‡¬œ%¬<@fJV.¦–sc[gпÆAöfÿÛ$¶`–ÖÔ•aøÏyþkRÉØÊÞEÍÓ៶ªÿÅÀ†¤ãdåÐeabaB !?ÿó›þÿ·7›YÙC.'ÀØÉÉØr3 Äð¬ìÍ@Ä13“=ز‰Ä`vBþsœœfá?Cÿ&N³È q˜E_ˆÀ,öB<fñˆ‹À,ñB@³ä ±˜¥^ˆ ’Ê AÔe_¢.÷Buù‚¨+¼D]ñ↨+½D]ù… ê*/QW}!v³Ú A¼¨¿Ä‹Æ A¼h¾D]û‚Üjfã‚ø4y!H¥é?ÄÑ3ÛÙ½TY ÖÍþA6ˆ¨ØÖÖØé¯ Èv@ÿ 䌙ÿ}kÿ9ˆ?󎮿¢º@6 9q[c»¿º@b0Á?dõÒ”íº½¨ÿ ¼4äøSvýÛ¤Àâ/„lÌòe› -=,AöU@ƬþBHf6!$4Û¿’Ú_ÞŒ^Zq@–Ú[Ùÿeòh1ƒ_Ô!‹Áÿ5 qïð2 iæ`ì²·™¿„ÈüϨÓeËIÛò`ÍþjÙºãKúÈäüç~9uÎ?ƒ`Ði°ñügô¿5€@HxE „$åü²Û?rû+JH¹3ämøÇ#$g[cgË¿Z@ô_8 {s±týu‰ ¸¸ƒÿZéáúBŽÃí/„wÿëî@V{ü…öž!$m¯sN^ §KýßGRDìá͹~Œ¬—hy /‹ïšº:AÎÅå_Ÿ?§öØÜ ò0ƒ@ SäÅ9°)_ˆõ§Æ¥~âepôÐ"Mq u]Óí(Á ñжÅC²Žô?kµîÊӱѶá¶É݈#Û|”G%ŽãRgŸ¶ÝŒ¶Ó½ZˆµÎÒå=·Þ\6Î\p@+Ný.MÒ.ìÍ:éÛÏS¢Sû°LÕ­ëVßÂÉ¥%‘n«ZKÍF¡‚‘êXζ⎑”»2ìg†ØÌ°t nsź+@ÌM|2|e6ªat-{”≺¡s7rõ%@¿$rÃ5W>M;¦òÁDw™<¨k{•1CsþÎE/­ªÃáGÕLv¡Î­""!{™d„ ªUä×öB u¨/qÕÔþãM+ùm–F: Wd#s$–²’Ï á^|‡«õÓh1_;©¯ß© öѪi3è(ŸeØdCcçBÅ+ëýÓȜ㾠íXKU‡›wa¼Q¢œÝúÀ(ý³aá`8yQ$¸™ó½eaœ£˜Æ ÿ†’8f¤MW]™x"†䣦/JFòiÞOîÌ›3ðªñ¼B:Fœ“øv•¼ZærcÄ•%ÄBV€š,ðŠ•XO]ŸRK32â7#м w^¨®ü ͸Èk Ý­fØû\¹“%ªÏ.…?™õbPDáÕÆýÙ‰ˆ—¨Ý»“Ü*µzC/²OEŸ`Ðs~-BE›£n¡dÌç—8¥µ³Íç1ˆ[46àEó2Rüˆ6sXPž´ÌOæ~ôàQN7!PÍøKr™íf |ÁˆÔ;«¨¼³•0Ýa Õ·àßlŠ5 Êñϧ.×<ñðUðÙ@›nÚGeáèʼn.Y¼c—bÇy,ÙXζ•Ì8JÇÌUóD4,4%šÌÜå\ÕŽ~ønµWŸ=vªêfLOq¥$ñrÚ0áD¯ç93pÒ`dJ ³¢µ®ÿ =‰@crjtÄæõ'{Ëæãú›Î,q¶£Ëôõ²¿B²ÛÒ-þÖ¿_bn*šsˆ`ŸqÖ*þ€$¯1Ãã~~hKlÞˆÙTeKà¶$cHˆr¾øÊU_ÕnEŒKÍ3ëœçMEehBñ5ÆÛF££ð÷-,¹v÷ 7JÎA¢¼qè¤ßKOv"©mmñ_ÇrnU{ÐpöIÒ_óéÚ·ë@]ëÌw ÄæáêÖ9€_W0|™ T}•‘íú*ß”åà»\5?A¡À±]N‡A¡ïø @œ4¥> ùšb¼‹WbU#—ÈpToWs¬;ãë¥e§á}!·ò»k²Btþòщ¨R'×=aM?ŒîK*åèy°íB‡+EФbàI%Ü¥ìú¤žÑéÚ2ÏU¤¼ìq±Ë¯Q©FüF¤C]ÆLë Ž½¥_Fÿ´jUëµ¹¸&c5žŽòn·1âöµÃg^Ðé$iñ>B^Bcl”û[ÿ|Åó áêDô¥£‹8‡¨a­î@S»Fv™•}=ýåI~1ùðS…H!|ç[…üõ@7tsœßò H«ýy«£v»êØÙœrY¡äŒ÷ƒá?Œ‹='‹¨LKW·”ã4µMŠ_%âÆ<¼^ý¡Ù„}µ¼;›·¥×•ÁäÄ©ôÄÝÙ×QÿŽS¦ŠòwLöëßRfE{$^£ñ2JMùÏžZ|xØÆÔ'þU jžs곉T ¦úº¼(¸F²ð­®‘g°iqÒAc3󙨶®\\ñ>³‹Še~ðNO–xsÎp‘3ouÜÕ¯R£Ë·¨ú;uÃ8ñ¢Ê䮟¤t"œÝšú’ùhPH¾à¢ß‡¾5Ó§_È%ߦ’¿*;m…¡é×:¸ aÈío FjnÙõ¨ÒÞ¡VU—8›’&-ÜÙ>ß?“¨WMÅVxî Ÿœ6rìhyÏÝ…5,œUÿ Ë÷ìÊÜ ÿ¥ƒB–-²£ãìµJÝœ2Vž¸}IWèóìpdÏs?Ð*Ÿ…~ŠXÍ=ÀðŸUB'œu2Ûa¾dæ°-BEÈËí]<ÎQWÞ]سÚ(#ˆ5Ïc£´SX:Äœe¶Dýdv‘-u:#§;loAæÅXëÀ¼¹D§­ÐßÕͼËr(§D«×7)¿Ì”›&1DUO”(ôìéãs`ÕàÔS\·ïf:‡Rþ ÙRD{òÍ4ÞN«PšŠ¡Ò¯Ö¶Ã÷lXï‰òðä’[‡ýƒƒ ˆÎNȱJŽrúÌǦ‰'VÇPJÈ%‚´°Y`°ÝÖà –f«ÂXïñºÚ‡=Z \{›ÞÓ÷²®¯«;„Öfr¾†!lÊ>›ÒáR‘YÀÄÐ÷¯%%ö²çHÓíšÛL3‡Å” Yml  e™.rŽ;Ɇbì è^TÓíXÃÓ³çºbBq¶1ߪ£PÏœò(µ#Ê6Öiòà ïƒ'øfêŒ Ýá=GÝÛ`IŸ/?j$ë#D²uWÔX)Ó€E=Ÿó¥ ¿Ò ˜":ë)BW.8³ùìW*™¤¨©%ËdwÉŠØÈä$‰ö°x6VSùÝ1žTƒáJ¾uSö¬•ðÿh 9[8õ«cvpV²,NZÕ§_5áÁÚ±{T¼ßBH,k° ×ÈÑਫ਼ÛßUv\ê8>U=øåÆɆí}Îé7|ždÞý¦çm½b8Ø›±'Öíìúîá]Ø™¾Úª=EœnÓ*Hq~žyrâ³|-‚%Ü#¶«Á÷«$ä•Öα•§`•+ÛŽÈ+uQaÔwAOq-‡ÙIš²…ïzß— ¸†Aåæ^ìÞÖE\ÊÐU<—ËŸÓ<+rÏ£Ewc3¥%6|öKt_ë’Ÿ·Ï­‰†šIžÊÈ#qŠS­2åªU“NäIeÂ(Ѿè˜ñ xúýÑ)Â]ÎkÕÍóÕc¤gs[Ÿð|¹‡‚üOvn²›A¦žÂSœ¦2$"pÄÐaÆð¯¶áic:šUœ»Lú@3ÿð½€z¶Ž¨Y™oûŠT÷:¹ˆÚ_½ ½§æI8ÎuVÏÅuþÞpÏß>‡¨Ó,€gL×®Î>ÖŽŠ•ˆxÜž¬†úV‘™š»€ˆöÅIL%P# õÒüÈ4…GÿC ‹ž¿j]ܲ¾L ¬àð!ý1-˜ö³Ú­LÝœK›ß>-Iç¾]Q‡x÷.gDa—jÖuðrX`Qëûb{&&ŠÖ'ó´®í|ZÍ$kU6|ïû; „ßñø ò¾Þ–ë&ùéJÒä[¸•»/•¸¸7»»ù¦4÷âøá2&Ÿ™ˆ‘¥†’+&]Ñc+üsH& Îl R,UuýùœHÜÔÖ7Èú”W+(JÆ.ŸÇ¾ ”Ñv;ΗtGÛ Ñ•L;ÌrÓ6ÄiKæ1~]‡võe|szÒµè1Z©\#xïó1IdÒ†s!Ì>uè`‰)*aRN§]&P¡õ‘KVêD.¥…½aBed£˜aäæêcíñäïÐÇ3ã3jqèAd¡(~¦­¦’º7 à§ë §¡d8^Ùkt]éç©6ôÊ6^»®Û׎ßQTïÜ•ø³ŽR{™æó~ðœG°ëél,Þùw˜éõ‘þ õ¤Á“µ'†Þ°þæJsæ¥\ŒfòÙùq˜‡-”>õvOóÛ$Âož'*ûåýV6À,Gd $qœ$ŠNáü ƒÏ$µ­’Õ|ó•{\ÅæôIÃÉ¢†í^¥¨é'δ–‚Æ-9¤I5õÒAWPzK‰ ½-±\2lüx`š }Ë“ðó—KFÍŠÄ#ñ7Nü: é'§qEKÏÞƒÌÙSë¹ucírýZŽ ij¯ü*ó±ÔÌ™ü~;žð%~¶/æ²ÈŽ‹‘’É¥DÜûÃÌ.pW vqjŸµØˆ ¼Ì¿9;ß^ƒ½×`_‘Ü bܻݜވ‘Âx¥ÓkºtÏ ’ ʃçB3 “¯À¯Ü¸Ú#¬@©Ê> Uì¶INxW×ÐLôðns­ 5òð¨¸CBÌF÷F’ˆ@FJ?œ¬{å÷‘¡:Š»ËÁ0]9™üe(ªú°Hocâž¶qórŸñ¯"Ε–P"€™ç'1DP»‚ßFD‘¨Ur7¦ É"tFÇÐgª yö’^ ú°¦nšëœÎ‘‘Èv†_ÌèÆ~Ù¶4‰ë¾šßÙ(#("eÊÓpÉGm 9K‰â ãûÉÌ;¿¯3>¹$²ºÞ¾û„‚S÷.ššªV›ö7ââ«ÓjïÀ›ê®ŸÛyǺªŠr¥£7ªö"Ç<ŸsÈ…HÏ ðø½Y(Élð'SÙ —‰IÄg޹իdJ —RgE¹³ì¢º>y1aÍ…ÎhÕ~èc*8úÈ÷{“4|5¯j?%†‰/­´­Úä8ÆévÏ1i]»&¹¿ Ýenl4jwh<ðÀ•tEäsâ h½ÜŠÙ‡!+œ·& ÁG „™Óð¦™ôÌ’/sÜŒJüì ‹øl:$q;“<F‘RY´~¾Kè)hV –÷ø4W•¥·8™7›S­þ“7ø$ÃÁñzåƒ24Ñέ½¥6/R œò”¨+u p£´áÑ Úˆh­4|\]ý­øêog¤Ñ†D—²ÓVÞa® —ÂïÝeë¦êÒô*†éi˜qˆ¼îà:yÊ*?ú+*¡²ã%ë<:ÉÙ© ‰ ªõdÜæö‘ž0ßP®Æs´Õù¿"ëÍ쿘@´Z6K0æâà2«fäHMºcîœû¶Ûo™áØTòÚ¶„…ôäÇW|§\;X^BIÉÑg±Jáñž¹2õ”ÂÝh0•ð’Àñ2rÔ¯}ž‘ç‹sµ È¿yøxˆZ}uËeZ ê¯ÂCÁµÚþDÇMÞÉ Þdr4 ·A€|œ3‘þbÄelÀí;(Hzš? C:—6*º;ƒnI°7M+á }õq€žXzÒú`=ó]"ݶ'ÎðÀMk"ÀÃIäZùAÝWN” G²ÆSîq;«°hHñ>ðPʸ·œ_æ¤G¹¼ä÷HðùT¿±Tâ›xÇOqºlYÈ o[Û†–ít]ÞèKÝ:ù‹PSÉXóžxúb×÷E±—D]ãÂ<…k‰¡d™5x^eã¼|ô¨gáD¼­8ô{75_DôÚÌ”GÆ­³º‡Uì{âïkNZÃÆ2ùñÃté”Ósöù½›DÝÄÄ'6¥€W_ä~€ÒˆÆ±s²»Ñ%%âÌ~1ÄÅÒsÎÌÚÂÌ{“^›>uÓ1…>\Ò\“ËçíÌ%sç¡a0JV@“©,ãKÀä?f|â–1PW®¸KüÐQxpÞ8k˺t¸) ÷«î¬öJ}w{¤Õ,­^–ºhoYãÃ’LxE±Æ‰Òå,Îñy“;`ÒîîŒj®–ŽÏ!¹˜Ìµ! Ì)òÊaî"²ùõŽí•ΰgQlàlßû§Ì˜N\C£Í=®÷ä_‰ŸË¯õÄÐð’(‹ýß¿æƒ³Ô RÍ/ÏfX^ƒY€Þ±í;®|Ç^ÝÁË¡øxß—Œ¢ä÷3HÈs¹)Ì¢îz¸oòM—ZÌ»ï° ¶÷,˜ä«Q¿hF½Ý=ÚàXmeÀ†7â* AØ*ò@Z Ua‰ rÎ{£mÓ╼+Ͼý© và;®ì¤oUäÉsÕÑE¿ÿ×ï]T=õ¾$×N¨G´ü¿br!<´­¹â­+Î:6Kjüò øõP‘rQ†Ã Ò‰ð¶’ZÇÇþ¾§-½@ßÝKÄ*Øë«Ðì¼Ý”¶{¶voÕM&‹&3ó5ÔˆÒLÛËOn±RM„Ôã=– Dï¤ö¾_‹Œ(™ΟÁ¯T®ö·PðÐ73¨”Xà i 5| Âc³ð(—øñy_m«—)Ç’úÕw \å7˜ 0ÄJVDrHµÔ´=¾¬Ž’7ö à ¿º¼ d¸TCß™(Ùë±r½ÿä-\ƒêm…{ÒÚ„ƒnÖÕuÿæL1«×Wi1yÊÐÔJLßÒøVWbôýñVûüžÍ³Ï"Égeq¬L.¡ááQöëÉþáÖÍÓÞ&·£ÌÊöv& Úˆ÷†HêLâ+‹æu¹ ½eü 8ó9ñ*Êù¬Q†PðtÁ*§!Ô1ØéÒ&´˜ü1εNPõ×µ™_CJ ¡ÂâDί ìÖ~¤£ sðvŒãIaÝEÓZ*Ü;Ð3}è–Snâ#:Øú±Bg_t, k‰?b ¥‰õpák—ɤ¹Ž0`‡ah"ëZU©¿{bìÝs°ïÃeÁ;@%&k¢ÖDûœøc#>˜¨>Á!;á‚y×Ü“«™ÜÚUóÎrจ›Û …”Tû8ç]¿Ð=ö2ç "ÞZå©Ü\Ÿäfïô©Ñî7Ðk¸”…ãÐbuqÜXÙŠ¿îò$’é\Ç*ÀÒâ0€´/ôJsG°Iä•_[ÔrÄnMb%¢M•tû‰v/¾ŠµÀÒ£{uh3ëÓÄžlBÀl“tNç²»UÞP»µ5Ù{½ó…*ù§‡`+OwøU÷t)Ÿ ¹8¥l… úÖù¥BaHö¼G¿ç¢3¦åÓ¶…xSÌ‚ž”^:×$NÑdì'M‰-¸B1ôæ\u”öŒ- 8‚’êž*Ê?,mL€Po'\c¨Ä¾Ü1žræú«Í­¬=Ô{H·2Èn®‘ó(½ÍÅY©ÿaaS“B’t´~çPТŸÈKXMYPŒÔ>·m_옘ÏòùsÃ!¾ûV“]ÐØÇ!]v¬ ~XR%@”(þUâS¨¯¼´~õ^:N·dB¯Ö8áÔ‡3 <½Ã¬È“î6n´ŠX%Zú#dDß À×õö‡ró}òõÜ#M!Ú¨è*ìÌuì@/,¶u&û˜ÀžP¤5doSa,5âWÒVvu“Û¼mv¦ƒ;|ŠŒ´¯mS @2ʰe'Ô”?àæ\ Ç"?ÛkÚ…O;@éÖ¾·6v([k®ó–í3wu¸W`ÇÑ×6\»7^?û›uÇIÀë¶`|Z[ùá–õíšm=_Ì“TÚl {v˜ÿ|s5N{Ye„¡ K;lÔ¾ž³Sâ„a¨öLD¨[³¢Êg2ô,Xÿf–ìk“¥ëëw„>>H6Ò–8fŠjë&†ž{Ù‚_7<¸±h­Óù  Í#ôF#Ì2É&54Žg[û¶–=Ù×Ö‚IëAáhf·‚çÒâÚe~¯ro¬ †RS7É7挥}“×-S gø­WìÙ¶µ: tµô˜Ò Ué#‘Qäè!}É"ƒ¼ÎÄ1³¹^1Ñ»Ózô íè®Üz§˜vææÌ5_¼S‰ÃÔ”$Ä=oVQÁøÑx`Â&ž´hUó$B¾$ë„.þåÀOOãÌ£îm opíù0 6ÆÈÖ}çÕØÖÚBÎ#œ˜"‚ŒuMaL»]áš»Ÿ˜ú “S„¶¨ˆ7C{–†…Jâ(õø³íóÊn¶1_¤OE0Õ—],œc”K¢˜êB¿âˆnê&Fžò–H½ÝV×é­çšYýÓ> ÐÈÆ 1Öƒ7iöÓuµI„Ì]`sæ8lEab*xu8³¤û¢eX€-ÜaKO3Ëf—'¾mbªì2g„EÓ2 õJ$‡Ž3ôU1½FžöSDëœ>ç)_f„—š”OÿH£¾¨Æ¢Ú:ÔÞâѦ§>`X3ÊÏ¡Š°Ûšbƒ¬spÍÿzMS¸¥,=œqý6È’ÜȰÙ};!‘"«P…‹‹e¦™ƒ`½¥æ‚5jŠšÕð® é¸È‡ùzÃ×°§z°tÄl/AvØÏfº"ž³¯½ùx.‘•hõäW––ò»£3ÌR5|žiëøÊÛ›‘ZY–èO¥lÓ‚›MHV=õ±DX è]ÓQVCºî%Ö.=§ /ÑÖ )§±Õ>c[[#.?®ç(îÆ ¸Fð˜ÊûäD.Fà “oçR0ƒÔmš$Rîö‹Ž€®˜S …¦ìƒÌ€¶k'3+Ù»šëgø1Ü16»5Î.¾g¼¨ècökuÆ„öÍaÅ& ³r"˜D®Ö±‘Žû5”)ñ$‚Ù)jÚ³‹üŒj9ª,-ÉíÕ¨ëÜä8G¤½m¬?‰YçÐçõÇRžHÚ"Ééz ‡I<\Y–Yâ¹”S;ìÎSBô]S€S9ÍÙm&°ÃHÞÓ’"tu_4¹mQ·.scG+ñ:®xë~¼©Öè;rȽö¦Ä-°Þ%ÔxS¡ŠOJÚ©›áÛùèþðb–é-/ò\ŽŸ™ÈCå¬ËÕÃoã$ðyYðš3j½õuU‘¨¹\Ò8Dã±íÞ>é_ £Û‰ ðP>)Í{FjæR7¢/¥ a ¯F1¯§ýÃeZÞ/³!)ï›±>†ÛŒÃ"gÄVèx0&è#åðr/’ /_þ¨‘2`ÈÑpÊR¾½¹xk€NU‰—8F9+õK¦ùÔ÷Í¢~ÃX=е5úñ´ÌcÇQR= ½‡tíãVŸ€åÛá3·ÈWC¾þ?©,¢¶˜‡¶ˆjÞ¿7RZXÊ n ”[–óF;ãBæ3]#û€ŒAXDMçš"l…´$h]lÞÛ™˜*÷¥­)é™$€ëX°,,+ ׂ $,®œûµìAëAºñiQÛµì@9=ªç¬•Õ4_•2FdCñÝÞäùâʰLsÊå9–™­ûÀÜà`PÅ-Øzª=nz_ˆÀž9B‡bór`Á%jVÔ°¹šߤ4Œ£*ý*f×ï`ÇÈæ ¥=3~)ñŸ*ɺ˜Ñ8éwçca œüç]Œ6ý“‹¡^f“W«°< 7{°ìåoUä”zÏ!ô×þX§ëòFöŽün4‚+Kùäì HË/f0v¡ž;ªô¾)¦æYcÈ!|‚±$EÿÝÌfužò ó™eË¢]1L W°²¯–ȱ¼_q\O Þ¥³´ª L,Úä{¤…QXã"]/caA®7 _]Pj'Q<ôÕsá›Ø¯×7…šRjâÃ_…6¬×o¢â•P°Åò,‹I*}M€-Äaç9©ÉûÑÚá$3Ô£¿fj«I^¡¿”ý±Këw¾¬Žhh¬P‚£npI ±†)`à]žÐÇ” ._p¯‹‘\Òó¨8|³ð×rÛ#<žGÏ£I ÁíSK™ÇK+9÷lFížÊw¸]œ·Æ_}±­iLÌ"dö.(^ûqäyîЈ yJ´‘ŒÑ}~‡Y~É›„HÍG æ©­¤!iØc RGQ}›Kµš$5šWšÇ†oièÑïñ“ÚÊ병mUïÏõ±.ÖX-öëWp_вã輨-õQûìa#¡ÚQˆÛäÄò VoKä[®1 â:dz4¯6 ä]÷a•‰~VA/fA€ß%ðû¶©BæÌçcÊâ4å#/æÑŽÒÅf©¸Ý¢¢BŠæeš ãŒtÚg—¢·ÉûÖÿšŸ9‡~¸· O§Û}ÒÇfOÌg¡sÆÇè)ù±”æzc›%xˇýÆëÍPUh0Ojß·S¼ß<…pY÷ÎÅ[¤Í U>†˜æËëwRá+íy<©C‚¨ù’);?}v.»œ¬ªÎ9ÍOb8û¥’Þ]šÙ\©È UÌɸJЧFöæ–’ Ïñ} ¤}´*¦8µžwðñU=(ã­åÙ# 2¼®¯UX9M»†|'ÃZàýuéëm ¹µKÞÖ²3×V:—"p-"„ÿšÝ®­•)KGÉôxæÕFD#R·‘´pü”È=‹¹¿äÑW i.Uš[Z>ãl9NM q~8‘Ë~ɦõamÄ›'ˆ×ƒ4°N6èäc¨¼%‡¶üΤ‰ÆE8úíê#YC–hµDÒÁOL‘/%;:KÐVO=-ÅX=_©Ðùë¥sû”ƒ¢#‡|Âq­8ü`XØÙ?NxDM ­ Üjü`ìÓv2ú| ²vaÝEmF©ÍtO‡·–'8–»è9Yª¼!wŸ—(ÏŒ ó\C<¥Ðó¡éõÆJ.Dj½ãnfºå÷áíb_›W`FÕcÓÞ¯¸Á¢•íéî&ôw«¿©Þ1‹'™Wø&~¬%ü«áQãûuU3F°fÉ%™‰H­èž¯Â¢ùÚü°R kÌN7ʾàWY8ªO…ÁÄ6ÛLGØ!ÜŸ(ܪ ·›ÖûÕŽaøÒXÏœ—¤ê7sò+—±ô›­2j£/â½·”<ôÏÓ.Írï)X:~W,Zµ’õ¬ÂÁ³ÕÑl»…iØ.ÃË8QÁˆÉþRz /f`Wkߨܒ Áì£[ê.VÎJ_%,טæjé$M34ïåÕ¿#O5ª¶è½˜Sô'áyu·´ýüˆ#˜ÿÍ£‡œ¹S«^ócøhïúÈR»Dþx|ÖÙ_Æb€iâÚç}!ó›oPRÞƒéÒ®KS‚ËL*ÒÞJ†¸(1²\En_“A‰­O{Ø›v3#4 ©j …ù,žEy¦«©ôP ÷ÆÐd;ϵۿʙw4mÝÀRÃ{M§29n=V¬^'?I ­›Ü+L°1ý*hD°¿ áOvÃã¯%+M (b˜~䓹!Q•®@Ͼ=9Wþ2  ÂÖýòùÕGvªÄ³’™%å•ÇÆ…ƒ:.1io<6“—bާ=â‘„CoÌ{Ö*ƒÎ´0?!à=ï~¨{ž©~Úêð©DèÂt‰3ᮆœÞñ­û”z!=7´Äî÷-Sßçä³å\®ß)Ó4Cˆo;&žQ«ˆt—NNã•kÖSGD+¯À`ªdÂ4Øšj~Ÿ¥ÉÊÖ$W…Å,Õ?j|<—n4‚“øxÐV—B6²H—J7M[ °•»*T†1l8΄KÁÓÓ@sä–Ð=¥îUúÓ¿>HΡ”ŸÊ— @Ä1ªœ*üc–aÛ«q&7š?"´lЩÁµq-Õ7f¤$”JÇìà¥ø=ËPF„ 𘢵ܘù©[‚)SA®ž|Øe-ÝŸØ“ûíñˆ nuŸ*åÁH ·qb¿båÆíªw=RPeTþP±¸¤Þß½›j1!„ýÊS¾Q-ïÜ/³ä'ØÓ‘¡¹ßx†ZÊ{Ä89‡w\ˆ9\M6ÛC”æERS1 ¤«›ö¸‘¾xC»Ê'•&8¾tÞ@x-&Ü€dé]É7ç¬îÑs®p%¶Ž`uø± ámmPÜ ºXŸ,k`]˜ÆÈÁ^$S‘2ŠÜ‘º™Ž|°é&7&þJ7.1p¼ÚÅrßãyáct™>ôà0Õì|ÿX¼Ö@r$€g,đ▷sM®Åæd‘A1ŽˆqÁ¶Ž W³žo‚p[޳MWÃùdTžöЇGÜv¹æ ÞNu”0,vLøôù1oÍHÌXK€»XsÊÎHmè=.9ŸD¶î­UmhØÅ½æ€!œ×ùþ+`Y«Ex£õOÎ_HÑzëH*ïs®„*£(·¼æa\~ìYÀñ‚pßWmâV´Öùó{ÎQaë åÄ/™J³‘õƒ†wðfüµ‰æý»˜5¸°i0XË+ÐGöý£Æp´xz5Øè*—Ñôד’’ObÌjQÑS™|^\T±éîNÄbš1ÛwŽæPóœßGÔùÔÌöÓˆj•í¥±dȼèÁ;RíZ-j7XW#ÌÂZZ/] T&ëðDÀ_%PîË~e}º‚s`c)÷0Ð"´;¬™6ÞM¥8­ Õ½j+£ÑŸ3'$==RÂûÑhP'‚¡QL†Ì1?˜ksU%ЃQl*ëÍäLƒÝ£k¿ðj `€ŸpßÞô†*”;’£“VLŸ+±Žô µ$™0Ê•`<ç[]×xï¦kJrîfƒÃ8 ]Ï•-lñ±˜,Ö7U}Ð Qá-ÇØ˜cRÔ*ˆ%qaÔ§¢?h m¿fÙ§Ù1Ùç-.õ0ít(GUµ2nèvËšL©éP繸±XçB›>ýŽ×æ”5£Lô|üf¢[¯,~ŸXƇëÔ‡l‹ÑLÞ+§ÎÇ7¾èúþÖ¦»7ï›0BëæóBÛÐgQú×3óæUVî c*"Öäxƒz/è@°åÆ}N…hÝá÷¹}zi9¸=®s×É;üà,;„½‰PCU!ÛŒÎäáˆ.g;×:ÊÁ_(v1nTX*q+ÉÙfZ Òw:8r¡vÀBÓvXƒãñõŠø¯t4ÞíjÆÚ¿¹#åïöNnvU_†šPþfïsКHgÔ°"@Ï„™´Ö‡åwqé³òŠ›äJY!²½eR{Еg]‹öEwBoÅœ\ç‚3ïÈHÀãjHÎ\§dézG‰[DC&/ 'cÎs˜nA 1ütôf»Œ²G´qD þ2ˆ%ªi ëcšrŽC9‚L.EBpÑú÷»ÓÇÕåöÁ:ƒ%l“Ì.Ñ;†Ûïª?¿sx±&j&ÓN*‰CÛóA½+¸$ÎC¾é¡ X5%.p#òƒ£HV2?ˆœÈ?4u°ï‚šæE_VÂ(DJÔFxô[wÂÈ®Oöÿ˜Ü #I'“qfeÒh;r°CÁ%¸éÆüþtæTþöKYß”¦ÆáA¨šÉJ,`“ëÚ˜¸:̾ó×2)ŒqÕœ4 ud¾;N5a…îÄ›×'žï¸g%³d¤É3PH“CEV[“}äÌлLñ{à8½U8¨¥›ÌÚ¶?3‹ÉF䤯^.Μ‰Ç³µ\î ð¨ÍY õ¼‰ƒ9ÛRPYØ+¡Áîy"[š¹úðÉ\ùÄì-~³08{ Ì<ÖõÙs) !¤Ø$KRk7uaõß.c"öëǽ("加î Ïõ¾.µ„#ÿ<˜‘)$TYÉ.6ð9«Ô°Å޾Xñ2 É+Üêç¶k¨Þ\Ι7nƒ—üÀº;2OÅŽ—­hñæmɨË)gÐn:Ç-£GÁ€«ÈLí¼‚|±c„TæÉÿk+ endstream endobj 1351 0 obj << /Type /FontDescriptor /FontName /IWYCFJ+CMBX12 /Flags 4 /FontBBox [-53 -251 1139 750] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle 0 /StemV 109 /XHeight 444 /CharSet (/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/W/Y/a/b/c/comma/d/dollar/e/eight/equal/exclam/f/fi/five/fl/four/g/h/hyphen/i/k/l/m/n/nine/o/one/p/parenleft/parenright/period/q/question/quoteleft/quoteright/r/s/seven/six/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 1350 0 R >> endobj 1352 0 obj << /Length1 753 /Length2 987 /Length3 0 /Length 1506 /Filter /FlateDecode >> stream xÚ­’}\LYÇ×–bZÙ #Âa*’ym¦—ÉJŤ”MEZ±{»÷Lskº7·ij$í'Mò¶’Ù4HŒ¼Ÿ¼Uˆ"oE/²¶š¼J†6Úl{ ë³ùw?çŸó<çwžç{~ϱ›ÌöÄÈ(! ›Ïá‹w€×¢_>ð9<†7N³¾›xÆG¾+່…Îb'Z¼ÉX…GÊ`Š·CŸÈxÆ@ G Œ¡k ˆ“(*ð”ËAPß8ã ¥„‡Áç G FâƒÛÇäKHIàò!ÅÇ~:RB*ކShH@#b$!W JÜy$Ý Ò$ÿÔÀâ’x¹|ÓWþ£O_(\®ú¨!cbã$)b 4~Àó"å_4òU rõ$"å°ùBOø!ÇIðDˆâ T¤ˆ<öç! ä Ýë§àú‡ùy9þ;Øþã@'!ªXxŸõý1ÿsLÛDá‰`1Ããñi!½>í– h7›@I '"@ä ŠBT ú Ñ‘$ñN`0ÀDš™Ë!H}ÐÎ$)I1úæ*tÜXz8$Ö—g|ù//21‰-plˆ.,p‘0ù?B4ž¢ ¡èÿ,´!Ÿb)N{a"DúFuO‹ÚR’~`åìÝ× ;ÄÙh÷¥Õ”«kÝ9wÜ-oP¥õ!p|—…Ú" /ü6Û0÷“ŠîY—x®¸œÌU7[\6Âa×Ö`ÓhGøÒ¯«ò.UÉ]óD?¡5¶ÔñE «û®²|p‘;ßEgmXk| ©ñíË•Ñ)µ÷ôf9ëQ6cI^™ÿ¯paÛÝÌ«½Ï|Èݤ~O3|k·Õ;½uåíëÑ·†iÝÖå|5wUŒ°m=x^<¹ÎÂlÎÐÝ}°|CWŽçiG˜MT>6°Rðf¿ÏɆ4ʴܱÑ&Ê“ûÞðÞªè™à`‚èt]ìÎÆFïå\ÕZL=æ^íú,løŸYöa–KKVÚ›uNQ·nÛ;hãÔYìl¢ëyïÂ' D¬9áê;¶0ïïb꺃ÝÃæTUÞdÓóñùšÎ¿æÏX%xòhV¬žšpF~óxjz×Û/5eè¸FŸ¨ÀM‘ùÛ÷Øí›¶Ç<õܵõŽ.ìbÿ0ßËÁ%0´éÈôZ;½#AÚü†ÕW-ó–@i7-»U?bÓ®ê!Ä7èæÀHÙëø¤æq#l$ÛºMŸWj#vš:Ê—¬Wg¼lÌH¯µ7¹í~ý]Í Ô6DÓ>ã©eÁ óCf]~‚dOÎ_+ñÖ<ºcÒ!ñWêÞ2]ÖºÎEYe¯ƒ—àÈe))ÍôŸ: YúèÅoçûÙÌS•}÷»c3™YëQØs8¯§+ U5³ ë¶H½£ŸÕºé{5b¶·Y¹·~B 3¦(èÍ2¤Å¥Ú~_ò\žœtÖ)«2û¬ƒîÖÅS…3vzlè0Ê­ßWŠ Ó¢¦Õ÷¶?í¬hie¶•ËØ¬”w-]¶‡VK­G…?äû¶…2“5‡ÐìС‚ûpùîåBk¼v¢yè£]z›ž!na^AÉ–JÑPÛ¦±•6dvVÆ‘ª+BcÃã‰Zuo ˆ°’õøø<ýmMf~uW‰ƒÕ‰·'Cgæu37¬Ør~iQ~BbQÊ¥6È4õºeu®!äTír¿Àsku†LòÂ-S÷ñò]Õ?ü^Šÿòê@tÂÍû[-]§Öï_–ü€wIí²¢>Ñθ0U:Ç/)(9ÊÚÛPCÝXcöäž$³¢WÛ[\£Õv®ç–û>ôPµ®êmbYÝÝš”œ…!9ëY5í=cJËÐ3G˜y$2ÑŸ‹þ9Ç®úL]*Ï£â|ñSc×ÿ) œôeÆ›ì*ÞvÖvv¶ù‚ÔUì=;Ê*h&YLɰ&ƒ½Ä⤱óˆIãëÿCnÞ endstream endobj 1353 0 obj << /Type /FontDescriptor /FontName /PLSYJB+CMBXTI10 /Flags 4 /FontBBox [-29 -250 1274 754] /Ascent 694 /CapHeight 686 /Descent -194 /ItalicAngle -14 /StemV 107 /XHeight 444 /CharSet (/period) /FontFile 1352 0 R >> endobj 1354 0 obj << /Length1 2118 /Length2 15533 /Length3 0 /Length 16658 /Filter /FlateDecode >> stream xÚ­µst%̲ÿ;Û¶mÛ6vlÛš˜Û¶m'Ûæ„N0yóœsï™9÷÷ﻲWÖþTWW}»ªz7‘¢ ‰½‘©¸½ =7¡ˆœ2#!=#£0 ™ˆ“)ÀÅÒÞNàbÊMÈÄÅÅL(njôùåóÃÍÆÊÍÆ CF(bïàédináBH)Bõ¡­©“¥1ÀŽPàbajûÃ`C¨boliêâIO(dcC¨üÏgBeSgS'7Sz&&BKcB#SsK;†$IÙ™ÙrüÛlâêð¿Kn¦NΟ¢)ÿ%“ŠðS¤‰½'¡‰© ƒ¼ýg6ÓO-ÿÈú¿ÁÅ]mlä¶ÿ„ÿ§PÿÏ2ÀÖÒÆóìm\]LåìMLìþ¯«†é¿µÉ™šXºÚþßU)€¥±¹)!ã¿M–Îâ–¦&Š–.Æ„fgÓÙMíLþ¯ˆÏÊýKƒ¢°¸ºÍ¿{ú¯5E€¥‹ª§Ã¢þãü/fúßÕq²ô Ôaü,/Ó§ãçßÿ~Óû?¹ÄìŒíM,íÌ ™ÙØ NNO˜Ïéù$6Bo&BK;SBSOÁ ôvö.Ÿ[?kâKhfïóOCÙÙ>Eþcú7±2ÿ!B‘?ÄIÈ ú‡¸ÄþCŒ„ ∉Aâ12Hþ!B©?ÄJÈ ý‡>µÈü¡O-²èS‹ÜúÔ"ÿ‡>µ(ü‡8?µ(þ¡O-JèS‹òúÔ¢ò‡>µ¨þ¡O-jèS‹úúÔ¢ñ‡>µhþ¡O-Zÿ¡Ï‰gü‡X?³œ?ÒÒÙúËçv£?ô)×È `lmêbcjæòÇÎòû¿oÔ>óÿ‡Ø>ƒÛÛ|ÞÌÿädýÇbkûGãgLþÂÏ”¦"|žÔô¿201†0µ58[üeûÔó9÷ÛØÿ‰ãèúyÿ×Âò“‡± Àö¯lŸ50ûƒŸ{ÌþBÖÐò¯4ŸüÙXþA·?b™þ1üÉÇö»½«Ó_Ù>ÌÿÂÏø³~¶ØÂÓÁÂÔî/OÛ_ù?«aõ~¶Óú/ü¬¶Í_øÙŠ¿NúyáþDfûÜjgi÷—öÎnÿGÌçfûÿZþ<ŒÃŸåÏ`'S»ÿš V¦ÿ±þ÷L°~ªvøœ2û¿ºüO©ÿôêr5uþçeù3JÌÿí]LMŒlþ+ 럅ÿ3}ìÿ³òßþ\ÿcýog¦ÚûWs˜>kíü§@Ÿ›œMm-ÿ{|Ùþñ1uû«ElŸAœ?ÿsØÏÂ:Ûü×p2}ªú“–í³H.N¦Íøg1]ÜíÿÚðÃõ/üì«Û_ø©Ìý¯™üÜíñ~†÷ü ?‹èõGÜg$/S§§úßaa{o:æO…Ÿÿÿ¹™\Ÿ%åòý/OcW§Ï»üë þ¼rÿËf–Ÿ“©©‡©1ÌÚ²½1OˆUjKh¹ŸXál85°°yk¼|cßB7lðj°MÉ„Œ#õvƒæKeÊ—cðc÷7çÈ.¥)ñë@Çø´¥ßÇn†Ç^í8š?3ä<ˆŸ‚ t¶,Þ_°+ÌoO–'i gߌüÈW¤U=Ü$ê×qkêÏ açÐϰQ ûÚ@ÎB¤Œ˜æXζ厘ô lk&ØÏ* ªfãÖ¾Ëù¥*/ñ·îZ’q‹ò>5ªò‰ÀEYQ"BýÇÐX­`&¡¹Šá1ø:”ò„TpJhm¶¶˜ÁÜ Æ´X¸œÛ5m{—&Ñ;»ÞvÉ¡ E‘ôj1ãÍ·BûªŠ_P^¿Ï Sž¹ ºdýIw®}]òcÔu©´Á‰àÛ­H0´‡32gQ½˜¾Üg©a ùÁ;$}x» fè ù–8ÃX ¾X S½ù)Á" ð*žå`ä4ãËÊ )c81àÇ Þî ÇzÒ×îêj+.D+#ɽÍË©‚øô’!o!Ùƒo *—V«´ø&y„L³™áH¡ äçÀP‡ÂyÔBùŽk ʾȋ}Á€ps;îl¢Î ­ê⯛ðöâù]¦pÉõýÕVU§¡k(G=Õ²2;IÍfñŠôZ#Ó¨e“»6V`$ˆÒ‰=–GØe b‚½6ÎX¼GdÔé;)­Ì pŒc~©lFÒ%Pbñ«©Æý®+¢Dí aÚE!p[BGÊQà-ª”ÒŽŽ+sã{a³«6góI*ue? DvúÛ3f¶cÛÆ}²bÇyÖm»Oïè÷©Øï‰Q؈-¦¾g$%Za¨Þ¨0’Δ'¿}1ÃBâE€Åàv»Ð®Î£§ŒÃïÞx®W׆€€uLTlAÕÉë?`,W˜Góƒmuû¬/E(œ¨Ž:4ÛO#I™­æï$š%¸šÂɪÍÒŸæ0Îe¥/D{m+€Ò·ß™ØRtM<‰‚¢~Z^ŒyÑàFWÛx´ê S{hF'˜›T]¥pδæÙÄùÍs”ýÄìÝe¨Ÿß­Žð0D¥ÿFpîmœA+A‘À/ÍŸòàão"ž>"tÍ´’5Û_ýò4j] q´Æ:?ù4þcq5žþÆ c°¦jÒgˆ)½¶u— V)>.ÅÒ½;:ò½û~VSTÞ×7Á#æ<ݧ\,žÞKÆ»p ö^õ­6ƒßº™|~©™/f>¯^_¥«í`ѼñËüm{-q)‡ˆ ø"ÝÙH ê7ëwÑÄ9Q—°¨2¸™ótΞÊF¿Ï3• ,ZåÁ!Zà”§ÂCßž+ä«[§ì…J‹H¯_?âæÎ»-¤‰JåÿJÄ,ûÍ>»ò³(… §´ƒ€ßìCˆÁŠYD๛Êb%ë‚{vwj]Ie ÷¹ÈŠXô—´ÔדñC©6/‹5Ñ÷: 퇈:cPU¤ßì•z.ò á“:CH!ªQþ?òbN(c5Î ‡ ªNOŸI;Eyœ•>mÎ ÷oQd¦å<ÅÎ}zì—À«?}F9ÊÛˆš-Š h[¼M¨øk¾ˆ<ØÏBºóê=áðQšð’ÁM“Ýy)&/eÕ®eÏmÀûU‹É¢ˆË=~è-’pyzÕˆ;„¨!ôsÙbް+B6¼Û‘SêÓþ¶+=K1- äµ¹$'çhÌ"ÿˆcšß¾óno fQP:G l -\úmBZŸæTãÓ¢1¶¦ÁÚß®PT²Œ3>?‘)Ÿ\@Û‘g& :WËü Ö¾G¢b‰Zúîf š3 D9†Øû ^Ñe˜ýà¿—­DÀ,Ïœ pâ°ÅµÄÉ…%z é¸Ûì,fŸr„ À›’ ÌÜ+šyá&Iû‰·•r`¸‘v…" D,ÔWä|;ž o³± ¾þ„\¼{¹ûÆ[ÐT€¤þm†Øó›KñLMÈXV¢×ÕLÖ(6sZ /ã‹E~¸ãžË,›z¤3«]|WŒ8Ì—IIÿ&„Uía›c«ìÁáÆ'™¯úëÇil(¾rno?йÒü®ÉFÖʉz7–mBVk}#y<_ÊשŒß%,r”r;iܧmw¥u?ßæÞ¤âR cm½opü"Ö¨MÙÂtèÊh!â¸e3d$¿ÇdÁ¨ê6îE ÇE\4CNqïËø- ¨YÜ?ÄŒãþÜ=r%t®áµ%eÚK:Ü2—=ï,Wî«[Ì-ö<¨†…l@œ‚ÀE˜ûÌiÂêf¥—GöË‚.‡š×•Á³n)ë­¢Û¶K!x.{bL`ÚdX… ¤QOOHrëz\LÐO-© &`Ï@Nvñaj”¨‚Ê —LضcÑs>”Ú ðÑI јË-dAŸ¯„•Ì©ñL;oUëãPû‚|1,øÎ!ÁW_$ƒ!Q4*f$`_Å\̳¬ÍÂWèL½Ná²l„Óœ¹~QlìO 4E]S¶‘ê2à ß}PðK*Ë1ãK¶ÖÇÐýñ‘œþȘiºdä>ÞÖ̓ü£59ÜС`°Z”!³#bn$²ûVç¼&I5ãÍ™¡¡ÌGÖ¡êð˜R®³Šcâër¬D=›w±_¼Ý(¼Å©ª©D2¦·ú…y‰ÜAÜhò—2`aU‹LsëYjF‹K¿¥Åñ L®ªÆ|O+@Q“œÞ™¯¡lº '|*õ8H8îb>qBœ#ž9èí;6>Ð:¨û.U'îUˆ¶€l—´µšd£t’t?ÿî:¦R!ktÑ*ÜÄ8°õ/¼U€))ò4²ê#aN}ëðlFÙ.²ó¹¡©Í˜“;²>w^À5—ÞssÎ+ä~Œ¾3ª/ðŠ(Kg6‰blÃë„n™½vÖÂfŒQù¹‡s‚Y?ˆ´÷ä0fiN‹á.ºÌ²Eï5 hT!¯©«~¾¢ä$øË‚¹8D“`ŽaXtÚë^ŠÐñØ–=g‡Ó8ÖVƒ¬Q$%=˜>š p ³I‚¤Ùbz‰ØÚEÞ„–V"3‚§L¾G§PKˆ;RzÖÏÚ¬jÂËó£ ±Þµ¥ëkÅ'Úf¼ð¡+¬È]˜á1yΩ\þ\»K¨Gcˆ¼Kß®è\Þ`Ž’¶»·lò-|_SXC…„pkã¶k]l-ÔÆ²·KmÜ4O¹{f-#ƒÁ¯ëZÌ>ùRH—›HZ Ûqsiˆ£Ûã¸Ãá"b»£Fò†E ½ÁTêµP7lƇm-ÿLÖ×KHáãÐ~!úɼ7^ˆ7£¬+´£8ß]~‹+¥¶íP1«¸™›ÜsrÞ¿&ÔËEìjô#¹ã7¾Á+Ö•È5d0‹%ÿSO«}nªvh&Z"_·÷Zó®Ö0ŒíôñpŒŠ ‰€¾Ýr:L'ÞîìêÒÞÖœBÕ¹³¸¶m O\êìe2”ÓZ°biš´é@M¿¯áõ*s@ª@Sï¾erG€ P\pÕ …8< G…ýÃÆpå<=Ýl… O'djo ,‡Ño/ùà¤Ó¹ƒ|8Ã¥cÐåZ³—RÒÅß–\¥CÓ3ˆ“#¡±Øªû§UžfS!'š84b}©²DƯù.N&•8°ÁºS<×vÃè¹Æ” !Ûãû¾ïÆdÒ™EÓÇ-4ÓolBYŠó7š§ý Vóô›µßNº(»9 p «æŽ_ŸÝ\¿InÕÛ\[ÛúäÇÕå†áÉ)Â\µýŒV%Ã'¥6X¨%©‹§Ý„c`À—¤¿ÇBB5¢ЯÉ_F&øbˆ›ÊxcP¾ÒÚ UœQå=g M¼šÚòŽa™ÿaCÁ'HñV»þBÂl/¸—ƒžªÝ ðû² [¥_C[},úogì%x1“a5Fó‚4-ZÝO8áÙ‹E gÿX¹®º‹ aa×káEKÜ­(ek;b°ûî2: EX²Mê: ûêÑç }ÓÒ“IgGB(íÈð«êj€ZýN–§xHʦSHðBmÐÌ8¾-P±­ßUõLx¤ÝŸÖ>ø1ÔãÓ áüïb1ÍÜ8‡/?(Gñ&cáü~_7ê¤ÉW Q±rPf$oŠë&Ðßf’øž‰”ÛçŒä¨ì|Ïü> ` ë˜Ô@øð0u?½¸aÇwt2&oëAŸë˜´MJ®tY´`‹ü€B¿¸²e"Y)vÖ/OÆP#‚mNÁ™Æz |×Ud¬£WɪμÄs‹óƒµ6>>†Þ•]Ŋ昄 yÝBV‹4]]bUŸ,¬ ¯;´@]§Ã p½*:›ýAþì£C†#z…‹AÝhò}þ'•X2ʯG¬3Õkn¦mA܆UŸuæ¡×¾–/Ø=ˆ‰ºÄ;$\VZ:o—‹@;Î3€ó´üeš®A”ZXœWŸ¸óL)ÏFcæ¦5ôó÷2ÏPWIÕàJ&¥B©„³Mò\§‰f¡ÙEœçÕÊ‘Hz­Ë&e¸þF²::·Á™EUâŒCW©9A¾ÍÊ7E§_>rÏD„å@ŽÙ%MrP—Ê]×Pb )ö©otyyJilØq.ðòú¨Þœª-AÛèVoLÝÇšê(¢¯cÊñéƒÐÍi:Ï‹È=oþt;èXåƒ5ï×-ñ÷R-¯º“¤ã]ÏòKÖ‰ù[äU£d šÈáS¤ ´ßâeÀµf’zeá’ÁU˜èĽA%î‹r6\èT*+0Ê‹/ò‰ÙcÃÚ¼á ‚aýé'EÐ;ðr“ɦ"°š‚ã¹Eó‘ú¢kÑ;Ú/õ—ž¡Zß²|P„øšÈgë=Η f”.jv9Ò¾þØ*<2mö‹‰ŒÇí7ÞúŒ¢ºÊ âªS°@[·Ì5/úÒ zÊo?×FZžÏQe—ñ ±÷VVòdNÃWn"A4JŠÜ”ëá”y"%[§Õ{©)7;q2z.BM¡ªC= 6sÄd(ÕF»ÍhÓÛ?7`W²ÅWjz@*;Rò>Cxp«±G×A`΂çMŒÙŸë‰)Ðð›/ºOø’ˆQö»0'‡…^‘ªF7˜ª[‚Ì8¡U –_Ì_;í‡ÁÞ¶´aR$eÒ8¥ã)ŠUzÕõ4Êç¤Nnõãuh ¤SqÜEªCI¬ÊfVr‹Æ÷îK/bS–E•‘<Ú¢V´Û×D²ë׆Ì&lL÷@»µèŠ¥ýZ¸¾ÚYŠš¦÷¦nFßl«&ºöêW}€–²x;oêk wFʺ ¡ç*Œ}Ý.¯Ýü. ï÷«x ‹#Këì'†Ó®³Yˆ$­ë|׬NìoɆ ½,Fõ‹gOcƒÝëƒþ¯$¸ïùÇâ†ø°¶Ï+¾©´Æa¾‰býEF‡:È$yVì~U[À÷)ëç̨¨Iëe"t¯"^SÈk–›hGˆ(}Y÷ð¬Jx[ñâ¡zûmÕr’7¯DÑr„_ÌTi¼¬&¶Rcâ8 ÔtDß똢«ÒX)Vc'ðe;–’¹Œo¢&–L•ðxäá˜NVjož?ÜÅÇ_à}Kˆ3Q'ç#ŽV­|ˆâƒ³š°¹WÜxš<Õ@lS߯I½Íßã“zP¥3à­×î©Ì(PîkSº. „=ˆÂF¢®ŠÉòàhê•«]mѦ–7êÀó‹F˜,5‹]»|´"Z0Ö²_¢XÔúw¡×ô¯Û7mÑ›¡Ô×zû®ƒ¾6Sµu60.¡ˆø€8«Cñ à}Q &Y“Wdêi^Fò»SHeÿ tqÑdZ“ª)>Ì/¤x»{D£_‘-PNk:xô›äŠ‘‡¬æ½p‹OŸÅ¦óM üÔŠÕ¥‚‘sü:èøÖ 6Y1닇JZýœ c[7]{eÌ¢M=5ÑÅÞà¼Ñ{Æ–uÊè ëÉ[pBØa‘9V8VAˆC÷î¼Dc0±+ -=ÂVW²geAhävžúN÷qCB¶ŽvvæÊŒ°nls’hN(Pš_m^§‘T®wÎdz¤ÀC`tb,«N€™K ÓFä¡ïÚò($BȘ¨ÆÒ©×óô22½½› r¨5ÛkI¨bû Æ/¿R:«r¾sðMÌ5ïÅ¿8@€cЇuÇY,­ähí%â;˜£š,P$髦ôÕ·ÍKê~|žAðËîEâ9߇§uqô¬BâÌTˆÔ-aýß,û>£ ÷é(ÚgßÓØ¨¹¼%¤Î›B{ÂâÀÔ¤$5¬g%ûºÁ$üY¬,Ð0N|,›B#ƒÞÓ´$HØQFÇHqé†îåö› icå?€ìiàsêÐØ5'Ðl¶H¸ã¢Oõ*ÓOÛ!ƒg1bf¸ºHÇ%i…ÀÁ¯X`s×Ãa!yFå¶G„@ÄQ4Û°h5vÅ/aêèŽ;ím¢½•ù~Ū÷î'-Á#‡±iQØöAžåÄ—¬nùaå•Ì š4F€_ÒÚ0ÅŸcwÛÒ“‰ºTÔ—€õ~ÉšQwÔÐØgÅQW â‘ÿ™í"ÝÍ“>Ÿu»g¤j%¤™ì^ØÁïñÈçaðŽÍîq߆2‹%«I'«›9«P¢b)æñŽ7 ãql4·ß.…›75âLœIg¼Nظ®lÉþÚ´d®Ñ5¨n Ū1Z}‹9Ó“'ªÝ‚v²:)úT,ƒàˆe¶>%ò()J{>­Õ¾= 0¨^\Dxì„'LÊ—D·É˜ƒÈDÄè§0]ã­QäŽr¶ÛéµwYàÀ†á§…ÖºU"ŸWÒ‡ÊhÙä‚tV’=Rê·Wr`5<ÕùZžÐáåĵ]$cúš£9]ê²,zcIoKæš­<êi@Ø4ýÊM ·mÔªNCÂÅRM(¥uýæ ý3p+’)ÏÁp 3eTp62‹b3įƒØÝCJ”Á'>oø}‘´=¬ý6&` ©A:•6Ì]#44~]ÉéIZë'XסŸGÂná¡Ù°áäÛxî2?ûÆ¢Ðó·«?™x‹ÞVñªöÁŠ*+¯‰ØðÄ,Z,û ¸€x©§ê€¸l}¾ó®šPÑVÜ+ Šn§ø ‡ ‡°ú@–ï=çâA[(µsg€õÕœ£Ä }»Dm¢ßÞ83ï!*t¦÷WÔó“(SÈj;ƒ‚”¸„÷†j¼'ætUïF×àGuÔ¬ s¾=é&DÅ9Ýæ¸ØôjèÃ<°Bó%Lg¥I4;ç®­}[LDm$v­^㣗 püüùaTðäÄiòð°˜îµÛhn$íÔÑ¿ÕH7,œ8äZ2a{¶+1ÈB ÛŽ3a“­·Ï}FTeB,ru Wy%×調°Q{ X–-oY°l9g b=pÌ ÊóÃ…›¢L¤@¨²èR›K#G,äG_åWë¡ø9ƒÁ%\H×!œrÞ{·àVìhöß‚j²Gøôä—olÈUϧ7¯s¨­¾˜‰[„¤½cµF‘&Dæî(#£´Ä'…jÊ¥\£Mê(éÛЗržNc ½Ibb¾ô |³­Žùu­§©î£ Ky!š¬1ozÒê«#¹RNBó2,”¢Á38ž,Š)²”jdí¿œPBæÄg™ 0ö³‚ïlHåkúÌüš§öv>>Ó^ýò.„ [£Ãr4Å·Öp7ã !IgѲK‘TH­_QAÅç»BéȈ¾ÌNá×Nm5…a§SøP‘0qÍx5c¡ªéº¾õ‹3Þˆ&“¸ “ÛÐÉí"ü0ÂÔ&#®Àšƒ·ð¥¯ávßâ èÁxJV-_;óOÍù%u;TÎÔöäIâSPؘ­åÖ~)YÈ-KIJ…4™J¨¸¦50lY¿´e,Åõ9ÉìêêT鯉 åN½‹†ÛûN}'‘Œá–×=Ñ œYt âoµƒçˆqm6ÿxíⱕüt?Z½Ÿ:•&…ðtâý8dï .³ V^˜ƒ’÷õ­ðY+eQ¨_则Pî€ /ªF]—Åk¥ °+óªïá0ÊÃ!â‚R³x5À8—_þ• Ú: x¸ô8#XPn ÿGr™LÕÞ÷Ø8ìÒùïÌ¢Ášg¢™ÚÏ›g$ÝÌ ÕÆñ2wòøªÇáíŽ;™¼„=¡Y¨•| ©–¨:8±íï1Ubzx/‚û}ëö“Ëï4°4$¤TÛ¶:96ýÁZÑ_ây}%H]>n¾]§I,|±Àâ^#I¸Á*Ð×Â'ë ¦B‰p>ÂóŸÑ„ɧ=¹”)Üký ºØÎ`µT¹Ù ßñ YDzutç-ž‘âè@ïÆïhfÃC³Jh6äÕ(¬@™ëÙ 'Tº=)%‚sô·g‡Ÿ«¬í˜ïä/ì…Š׌^QMrpü»«w tW}ßR¬VoåG'‰Uèï®Ò˜Æ‘M—ûŒ\éaoœQ×·Õ®åSz°-k.—RRµZv—ƒzÔÚ­|ïµÐ^æZ—-·Á¯ß:ŽÂE] §Ã›Uwtߩ܀P¿u¦ü »(´¼5œÿyø wÙ\Is~ŠÀ×åÚÕI_¼D|yÚn¶_dCÚþsL]´§¥òÄÍ-û Vi<~žÔóvf±=€…ö×$j°Ëç7‰Ã÷^ý aÎúØ÷}£yc"8è† àþÊa}žFë4‡pIñË+ÖÉRR} ´ä"òOóð@¸D¯«„:þ]+òäaê@ç3Ó‰a7὚Ø €\R|ÊsŽ0Hcló9Œ y{ƒØhhÞ Â_„sêPö§‡M5ëÈÛo)ï§}­Üš­Þáã«“ ^Ì™]@Ö+,+b³3ïíE¢• Á¶*/òmȆs5ò.5îˆOäQá8î¶ê1‹‹i𕼨Tß±l7Orö &ˆßt‚EĽwj¾ZVÞmôK\%äå9²r\Š ’óWË} ©fÈÞ‰Å5álárµzdôÖê8âÃr5›(„Ò’T®Õ $ÊÞ…ïñ¼ Å$Lµ´²Í8êŽì:ŽÓ/¡NÄ>q3šªvð·)-smÄè6N¨D«30^13u»„Ú»$ŽÓ ÑŸ½…Ä( †¼/}(È.ºÚ_²Vº.Ê€Ù™˜ß',eCBŽ à$W‡Ôš®}FãZK‰5Žjzbd9rîsgi}¼u~ëñ˜ŠÇçmN”pw„wï”u¸<ÛJËs¨ÉKŠ8Q Óží‡ÇË€—vºÙ©b‘ßÚsò Ð IìrÓ“1é–´ñõ•­P:H`@¦wX¼ô:æn´4pœ …lø~€Ï¢OZræ[²&Ù¸ ߃Íò1–g,D§'5Ïsm¡fÓ)¤ÕþnÙ¯ïb8ÃBMÏ8¼ŒxßJR(y)›–nDÌàãa•ëEÄÑ ç|üí%˜Š·Zn»ªËª« èee=8‰:Ú5Uc‘ÀÝ`}IÌ·;:ìA­O7£!2†¡ Ö*>1ØgñYͨ¤üÑôb³œU\?iÃ\SÂáËUµšgÏ‘oÀºÀïOT!j"!¹Tûº´ÃÆõ•ÂF=n±¤&7‚i­T$"*K1¢u“Ê{-=Ãû0ÅÚ[3l¥P2¨I˜Ì伞~%à·#šs Žm¬™¡×ñ¹ª@¦ÅÙÂÖC×WGBèB©ë¤Òq¥‚ã Ô±®»öÊ8EÀ@I®Õ#çÞ^Ë»óiFbxE%òÞĉ¥"ÂÐGêØS´)ƒ™ Ë(KÓh[‹óɯÓJc[Bi³ã ‰ŠÎþR ÏÂ>¢ç±èP±ì¬¢™Èt¯…¸Ô“Þ`-g«çœ‚ƒLÔû‘ýCðù·4S*L’ƯÜåû°Nu´; ú`~½(??N‰ ÷#5tD—5ò‚2ú*G#2ÙFú^çáþoqˆ^eþz&ß)ÜP”ƒË¦ªƒ„gT·¦ƒ‘ڱ̆ÔÈå¿÷âüqq[Iÿ6ßÒï¬æJ‰HŸO+q›ö€ûÚÝìLS³ ƒl8*-_ËËÑ/ÝÖº 400¦:Ú¾´*–YfÐÏS’Q0$ö-ã5^qoŠr,†(1œ™!.³ŒŽa” ¨òËVc°UÚ¹Q«+v@b±Ée¹¤§œ3ÆÕ½ö‰!#rë…á8óVKœ$ºç€`®û(5¨"¦}jM´c HÔVt•;YèÍx¶zJÿÎe¯—i³üóÍÒ¥BÒc¢„–­Äb±‚MdX¡’­Ê³QŸr¬ÉJt¦v./‡‹ÑÇZô‘F‰‰Ý#J¨J»ƒÔNjß=µ¼/j^µ8X·ï3¢KÕBW+P3©Í6E«µñ8-uÌeÝÅ/ò¦Ñ¢èeÊ-æº >“¢=ŒFF=©~O-¼¥WˆP £ DdEê*óoÙ…aýr~÷ÇžIif%̬(ôƒ@<­ÙO½:WÙ1€ò’pv¨ÂÕ\MÓR°U?V’åþÕV¢N‘b ¹G…cHî+åút¥(.¦Uð¥ÄiHªÕL–—Ö¦$x»˜Tæ¼ù¾ñfËh© %- h¬€j§·1EmE®,j‡'Ug¤¤µ“Ò>‘cÖk÷ Ï,R7DtÕ5xJŒ”'à—&zwHÉ>ÚÊoB¢6¦”4ã‡7¼‚$bö6«þI•BÍžø  ’›)N½EýÁn Þ«ã(/4àdó)j€'pÝàY8 ìvñô0bXÖQÊŠ»Þèù2:- b¤þHäð]˜Š \VYÑü…ž>woÑ8¥0ÝÊÔŸ4XõMdEƒ+;õ— v?0;ä2®š¸PÔMjˆœÞ®d0Èf<òµ†‘H”âNÇí ¼•ê®cš6^Î9j[{º–,[­Ò9¼±dG)Sä Ðp¼p’Ì ¿(Þÿõçfެ\:ª)WœØ­ÇIúI#@æf/Aù*wì´Q·.ÔÆCf;¸kr%HzÞ府êµ™d•ÃìTD¯PQO¾^@öð„Ì`(KGºè朌¤æ©|+Ù¬ÐC²çÈë[v˜ªëýÚä¸9q*£& I†F¬ MË;é_Œen#á9Ž)t†PódF?® I*¯å ïÀ•ž©Ð`—xbtcêF²ÍhNâüÉrìY2 Gz\Ý!Iª:4ÀkØûã­`ŠcSâŒá׸¹¶gºÉû) ;4ÁÍÉ´ ›È«W6ÇG¸­>ç ýãˆ{ÁóúbjŸŽÒò*k¤^ãÓ`AuuœgRGiO ¥#K‚Ê…p›¡¬ø¸MB¸ªØ—#TŽÞM„Á6wüŽ0¦]r¿ž?>DÔØÆŠß8àȪ‚¿D…Dcëw]Œl¬é:²½¡/OzømÙ>#eÿ’Ýí)ñkÁiE`À?–K*.PNöÀóU÷±s¿1¤ŽñK¸&9s>¬¸P¨!œ`eN"n´®¤[æ]>àFÄh´àsmt€Ö<‡ïé*Kñž}‹ìHÑ,ªŽ|9W¸Oþ¤UК+Û( ÷“ôiº™Ž^ _œ„âºD3ãGîÞÔž“‹Ÿ²T}™¢ºö@«¹Rr¸òP ¶-ø¤¥²ZxÓYÑ ÐA’Ùå79*¡ÈìÜg»ªÍ…°æßJÂËGô†=b¹¿“]ûˆª|Ç£\Òb7°3'në}Çeùà\#O[b—н§€öä{ݡѤÙÌþOšÚ ì²pîrI ßÌÁÀÑeplóËÔ_Œ>@Q@ÌðG?kIî°Ð ÀàWª ¬lðÙ±à z2 ½K0”] ë, H°™rKícL£®w"a°5Œ„ámŽ M“LÇ6]Š6‚'KLÞaræAÇ´æø&#ëØ\k5(n¾!ÖuŸ?̱Þb¢T²ÒŸ}óÎOñfÐûYšÖµ(-* ¶€óK_4jda’‘ø R|¼C'_ó—‹lmÇ©>‰öÔD§óßhujʦÁú=˜Êañ¯‰ý䘴ƒSDèlmÎ Ë J¤ÎÕ*çÏ¥ÄÏ'næD-85/B[%@ ;Ë0˜±[H+o!ø:[ú¢Š #úKlƒ<9‡#7êêwØ/á0Àž߈biÚu±G8õÃ$Krlsæ ~ßAÓ‹AnýN^ÚLôv;ÃÙþ:î÷N»¦kIj%ˆIɳsÇòr»¡¼_òbßòQÝÃÄÝ›N¾µþV¦qaÎÈ9–—í¶/õK,6·Cô‰4~QòVü£++˜v®Ö+h¦мu¸às_±6Öì`R>± ñÍL^WœvúûæbmÂÖ¦Þ…q“ò‘ø×W‚Ðpp¶~¿Ãs³4Çå D¸T¶ëÛ5!6 5B°QXRÏÞÂäû8‡,4ó }ˆt/Eç†GWæCÏ^ MâÊÌ,s·õ÷ÓyíxfrÚ‹w㞸Z7ÏŸi5g\^êÆ¯BFF*¨qÌ}ƒ…¡J™Fæ?tªµ˜€Ô ªô†‹Ö<’ #¥âÅàôšŠm’®øprÒ凷æ~Ô–¢Éú»Ó0Œ­*´mtŒ"GûNYñšDÁLžœ{´hKÁpû¤0F—±gð‡iÁEòé¥mr<¸Ùõê?|Ýii‹8暎†jÉNê¸%ïáEGhìÒBËW‚¾›åÝ7Võ·åö3ƒ-ɦ¢&·I#Èm‘@kñAƒÂ÷ l%¿„i](œëmªµxø¹ ×`æ„n¤F˜G%ûkÔlKd›“òðÑ7NÝx^\¤/ñG2®¼ñí&ÁÑÄ?ô­C϶ŸM¦X4­n]æÀæT%$ᘯ¸t¢YXU[”ښጠðQø6†í (%¿ÿÖ<;ãì&÷}9 ·]$ÿ@F°`ðpÌtsFîeõ˜©fç¶½‘­˜Þh{¾,Wé±®xÝÅ]?¸G#lo‚nEç2¦%ºÐR°Ÿj²µ®(ã' v±*F¾‹Æfg¾óeØõ6¼n»+Z{Ï—sè"ßq¡™J‚š,˜¿« " tFFsñçiåµ›~ÄVAÿFLûȺ ÇÈ¿6t=”‹ÿþŠ‘¯œµs˜¬ëZŽdÆKºçèEi7)Æé´žg­Á9ÁÍÓ§›²E@tùóBuR´(β£o®:­FtÙ+Üèúó2ÍÏm#å¾UíOº ð¤æÌï“dcâFPzIa: ˆù™=œ°îŸù!ºœ»+"PïÔß¾faµŒ¹Ê6‡~íãU¹zÇÿ(¼ÞnâÉŸX§G‡ ]ó?Å+ ôðÓhf‚3££W§f©ØeBB!£Gp¦pš'q³Ìô/гd[UT~‚‡µzʧªÓA•>ò°I‡ v1^wpa§µk‚Kþ@©vpló ™ÞʼnFö=#ÎãCx;}2”žpê¯"ÞÊY +£Tqív3¯\7$‰1ŒüÔ[}› b‰~ß 3ÏfÚià÷g¾çlþÑYÖ–z4¶ ¬²´k_‹¦;ZT/¤Ñ¬Œ-û«£deº6Ï/† U×Ö]Ù þƒ<ìÝi*ûú ¸¤»Ïo[ªËÌ<È®_ÁCŸï§WÀ‚%©¤´Äz‹4ñ³ržg`ôz|@¼:)f ñ|_Ö훹27ÊÌG!Äl–E¯ÖûÈÃy^—€ ¯îWt`×}Dþßœ¿\Ã9¢K#¬¿“aîûï¹Àãó7ò5Îòd æù*1S -¨Œ âµ¥jJ=K+æÍ–ð²¾RÛ\™OÙ¹pQkRàJšs+î×·Ÿ³ÙùF´ÎH3è4LX‡‡©¦ið,´–¯IK¢'y8ÛHº¿&˜Õgü~ÿåâRÎSŸ„Áè*?Rµ5¡€Ò;AᾊaqG1\Õdë<-¿ç(!)çx?è› e Né^4¿š{FӝС>÷Lgª"§ŸßïêM oOnÊöñ¸bRyù˜2™íâ¨j°N¥ûÍÆ´L•¤­Š­¶ƒb2ø®±æJÞ‹‹I3¼ÄÚt÷vÄÃÁQFuJ€ Qˆ U¶jœðmò–9ñëuöÏ6Þåñ™8Ф´‘?ˆdÔÝäÚ6®Å|”¹#œß:’Zïè+}å_TèÕ)­Žcöm;ý…ADÀåð`Øà••'Õ{½·¿ `#˜s-HÕv=rd&ç¶,>KÈåÑ‘ÏÊ®þ@@fë”lu„O.ÝR°a¦¬ŒÀJRÏ¿‡Á<®Ú„:4lTM1#+h¿úòdòíx-ó«÷L(ð‰~yiư¶Íúœ}±M ;ô/S}co.³²Iè3º½ïòÄã¹/}æN§°Â¹¼Ð,<2Ö.eºD²ï†.§èwä åØ3)> ŽªrñÝä0û¾u?PŠçT R# Ñqͺnì³?2JË3ƒ> ö?ƒ&y—©›äÇèÃÅ>–žnœ·R{…ñêIMvÏ·ý‰Å MÒ¨±yމ=™$„Àû#V¸a£!F]E2•}ýÿ,å)-5ÕÙw1¾ î¡@Ç϶¬ÑL}ߤ/2xõÈQVE¤ðG×g7Äzj! +µwx©Rœ«èϘĤYÁ=¾¡ŠÆ½2R\šv¹Ö«è) Û ‘áñSªÚÖh;ñpÎEj0a+ñ2ª1ÍÀ”œÞ›(Ðæå4a¼C`/÷±oÛÀÄL+Õ{ÆE ÈŽæ~s°â¹»-”£ÐD9\ì¿…7²ŠôÔiæÈmXM~ù½©&ÁÚ–í4*½*ª¼r¢'ÅßO)Å©Âp ¦¸ã½B[t¯ Í+3ÃØdä¥nŸ<µý•Tp=w&^x‹ëµ%0[Ð@Í›ÜNIçû3é´h&gÃgyI2ð^Ô/Ð2–ŸLQV_RÉ{nÒ1ÿ¦È:Æ î»“ŒY…ÂcIÅ{n7@»l/½6ÕûÕb*Ý D©¬›6”ò¬ºð2ß²²j‹Í= ©_Ï/õád‘f¤Þ™™!4÷­Ã(~PrTHãV·cWuq\7“@—¥m}á¹ ¥ ¤¿ÈËÏ…2ŸÙÁ„è¤^…;pã`óIºnÍÙ¾±|û¾ÇÐzx2@…¹0üîiw¯u°à­ºz¦Íl5 €«¦(ëÂ:ÆÒÆ­fBÌš¹šú¥r]g,jÿ&ÌÄÚ‰ÞŒi¤JMLŸ&£ üžå!°ð6œÓᛥYÐfÍ8yeÐÙjISëO°Ì1–gè«á/'þµÙ{”¶kËÈtŽyBüÈT£t‡Ûšô€qth0Š[òC.ÆîËÌãÜŒ``ç8<™%a¼âÎ_Ö hh$½Ì+a[FÝ ¢êŸa*6¶,ß04;Ø@Ð ´ËëÀ-Å™çu•æí(-Õd:®ô¦IGlœ Íöl‹”²jƒ‰Û=Eå€  &Æ×·qžÆ+é,úÂt€’É $0³ã)«iCZ%ìTÉ øÐ™ðö‘g±ÈS¥Òh†…¿hOAœ9ªc¡D« êÜ·Cý2švh Y]:«¤»ÔÌ:«ÅÈ¬ÏøD§èÝoRó$­õ¬Š(Ì|\9©0úâbN” \¥ ™cÃGÓËÀà®âöŒ’›× jgR˜ ¬ ¨³;;Àç/úqÃq¤¬UÔ ƒ=ç=âxw ¢7k †Oµ¶þ"SÀÙË ¸kÏÆ$LšŒô´­~ãª=Ý/KE¯æ(e³qº³Jä½Uøêj^ø®KEKÒܲ—¯(  Ó}—³ŽêÉã+â§Ò¹‚™ðßé©›a•wëe: ó\ì”Ç#Ii 4¢þ6t ¦Åá‰âó@\ßBáG§-%q°çêZhqá2d&еJµBh?ö·h‘)­·E¤QÓ_ïÓë2oâæ3Ë?Bmá9ž.ºˆqC–ÂM# ÕöùŒk ¯¬èÈÓH‡jQš;éÎ_eßYg³¹qÝq ½¹'q¡Óê‡ôxÙXèvÆÌ³PZ¥Ë¤wipù;Ò¾eVÉXKîözˆWZðŒ*‹ˆžù]° ‘èå¶Ýn#eŒ‚Rœ9=Éf¤x¤žMÖ*ˆÕ!H‚VÐ5ë,"|"ò„i9ôçc.ÝR\š±óáEñ Ыœü5s±§<€øÜ”‰7o~½w‚Y_‹ìĆŒ̈ Öýh67WSc(Åv¤Ì]^t|9ÈÒn«F7CKºÛ€,Œ›Û™}¡9ó§q/5/B~„€d´àÃË¡,»kö×¾’Ë, b hBû—aüè3QÓÅNÖ£fFúÞ^õJy§çAÑ«µÿêb~x endstream endobj 1355 0 obj << /Type /FontDescriptor /FontName /APBFVA+CMR10 /Flags 4 /FontBBox [-251 -250 1009 969] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 69 /XHeight 431 /CharSet (/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/a/asterisk/b/bracketleft/bracketright/c/colon/comma/d/e/eight/emdash/endash/equal/exclam/f/ff/ffi/fi/five/fl/four/g/h/hyphen/i/j/k/l/m/n/nine/o/one/p/parenleft/parenright/period/q/question/quotedblleft/quotedblright/quoteleft/quoteright/r/s/semicolon/seven/six/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 1354 0 R >> endobj 1356 0 obj << /Length1 786 /Length2 1532 /Length3 0 /Length 2085 /Filter /FlateDecode >> stream xÚ­R{<Ô馓¥¡A´9¹ý\&†˜KÆDŠ£IäV´Ë˜ù £1¿1f˜!ã~©6+—HmJ$—”%ìì¢BYt¡u‰"IMkQªƒ¦:í9§ý÷|ÞÞçù>ï÷}Þçý"Œ¼|­4($B,®ÆcìôðÁk4 ØÉ)\Är¡pA{cg‡¼0‹0¶ö[ìì±Ø ±FX80߉\áB$ÈaP),ÀƒÂ #å=¨&à Q W` ˜LÀgùD4àFƒœf Ã`ƒÊBÁ0 †ZöCbÑ!ÿ™¦ñØ_J1 'Zn 0—›Dr‹4ˆÅ4CyBò»@¹“ÿ‡©¯›yL¦'%r¹½<£¿U)‘ ¦àßu(’Íã‚À¢Ö×Rð³5ÆàE~]%q)L•À c‚ú3ň&2ø Í‹Á¥†t 3\áAíkòØV, <÷¸ûúúZ®üæJÉ‹Â`qý쿚.kW0æ?Xž ‡Á¢­ÑhŒ\(__v_]åÊ¢B4K>8[€ÂáP0ù\ÈˆÇ  ä _îeÍ‚¸ò#€<’€q`ËŸ‰Ã(:Äã,³+„€‚Xà_‡PÜpø_ ZÎÄB+øïÏvv†øñVX<`…• 1,ÀãÐ ÿ#¤ò8Å]™(yx_0!ù 6ø¢nK‹(¼žQ)t½p¯JÉBÑ9¬!ÇSÜòP¢š:pB‘yñ®{”Ũ(`¡ºX >©4i»¤}ô§ÃÞÝÄ?’£rŠúe“1!“ÅqºsÅ‚çlã÷©Rõæë}o_ã÷>íªÌ?PvûÇ™véy/s¿ÊZÆÔ·žN³Å‹™û2ÓE›¶ùhEUfÙdŽÄjäç®éMFdªÜ°ž…~â­[¸ r.OFž¿q·¹d‰ysöe-vÎF"KxF*¨«ùäãœ]ª–Ý÷1úYYÚ‡_f·dŹènìt«%œøuøÅ&øû#úÖÞáøˆ«²Ô[üN¿öpVÊVç”4,¦¦e£47ÿˆC³²”o+ïþ†Þ¯Í˜à‹2æLÌçjÓþÐÙ>¡yÆÉ,ª”TÕºà‡cÀÌï×s34B:Ö:ŽýâªåðÁ­Ô}oí¢Ã+Å×iUÆ‚¸iBEçCá9îϱécÿ ˜5ì˜CÓ‡©§²ÏcÝIÓóï\C|ж”lJºH{½¨RÚ£ìeÛS+¹kÓò.ãf³Ùô‚kÿ®÷å=“ðЈ½©í%/í}Mµìù¶(töñ_“FÔHcøî;5*MÏrSÆ#â<¾_º`ÎLRZš|¥rHúÆÐkg’He]©fo‰TÓº­ØQ,Ù‘œTÒŽ´É¬p ß<¨—ó-ëL·žÜäfÜu@›éJ4Fpë,EÅZ~W6°Fj¬ÊÜuµ[àÜ#]uÂð´Àø缕¦'(ω½©äŸ#‰ûLܲc±<½wƒ¬›[%—ýû·ùÌۨהèí¦Ç]Íïè2Ü2ß‚¼3{Qf°Úâ^Ó¹â¡&”$±‡cÏÀ7DlS·›Ån¾¶Þ…Íâϰ§>ªª)‡`’䘜Rö}ÐCAæ§wYß” M_zØòK»QkWüFá%“5»aÊG:¡Îié÷ô¤Õa„$wÏÃçg®«åØŸWŸ©–²/äèL¡’ù/ŠÄ±µæI2»&øx¾wz‚˜DÚTSÖmÒc¾»?Põ©+l4î™ Áûºæö›Q%zÏÙ)à%d:ðò¼»óB.9§Ìþ‘Úu4)ê`ÛuKCv.®¼bû©¨µ1 ŽQ£ ñû£ê¯\ff röõ«VwdÁãÏßÝóSêtјn3žXÌI,ô&×i¬J¹sÎÔüàÙTÇ6lU’ >˜+¿íŠ&×í¯è¦i‡ë˜’5­®Ê^>­9Y/ª%‘)…pÒeÌOdWaÝt ÐbMáÉ´qŠnyœnG“'þ±{e_BT|ŒDn0B(W Ú ¯ÒÉײM°OÈW³*­M%M«¼îO¬:»þšֿéùÒ§}-í¡ãkSz‘ÈÜÌMY3•&i12¿¾Sðã<™âš–-‘ýê9FhŽÖ»3ìµÆ'n¿)²m¾zúºÓÃÚùt¥ï@éæŠË‰šÆ:“W—–fí«ÈÇ ôȨ́qóí´U¼^5:$~"lµÏ+;ìZD§ù!–‚HO7òŒ \Ä"©î¥~ló,oW¤þð ÷®Ü“Çm,Ɇ–8CDÔ»#¹D÷™§k•ÚjðÈçE§ôX/p{ÕœVÄE4‰ã¾]ðò¸sݶ$KÒð~4f½Ùó¬ú‹Ƶ §6yDkö³‡ûC¤¤#õèb^ÿvÿüçñ`ŰB€Kn ñýæ±³ºô ´BEï{,9ªè@׆%®ŽƒþDHôÀ¸ú“$³Å¥'NÁk¼æ«Z‹;§ËãÌôTEëRÌŠß ¯Ÿ lj»/ \\\üÎû÷M5"a¬PcUù`|ö?¨Äa‘·þ†H÷à endstream endobj 1357 0 obj << /Type /FontDescriptor /FontName /NLKSSS+CMR7 /Flags 4 /FontBBox [-27 -250 1122 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 79 /XHeight 431 /CharSet (/four/one/three/two) /FontFile 1356 0 R >> endobj 1358 0 obj << /Length1 1883 /Length2 12662 /Length3 0 /Length 13693 /Filter /FlateDecode >> stream xÚ­¶eX̲¶ Á5¸Ë` îîÜ\Ü]‚»[p·à.Á]‚w'¸Û™w­½V²÷÷÷\ógîªîª§žîi "SRe1™J€lXYxbò*<FfD**1SC' ÈVÜÐÉ”ÀÂÃÃq6°2X8yÙxx9x©b ;w ¹…€ZŒæŸE\S ±¡-@ÞÐÉÂÔ\ÃØÐ  2š:¹3D¬­*ÿìp¨˜:š:¸˜š0"²°L€ÆN#Ss -"Ó?z¤mÍ@®‡Mœíþ“r1up‹PƒEÒÀM@¶ÖîS3D&¸—)XÉÿ¢þoq gkkC›ʃ=ú²†6@k÷ÿɃlìœLò SÛÿ»TÓôßÒäMM€Î6ÿ7+ídh 4±5·60ÿ;t”º™š(Œ-f†ÖަÿŠ›Úšü_`Ûþ%IY]擺Ý¿Nó_)%C ­“š»Ý‹þ³ö_Ìò‡ÁÞ8Ý:ÌŒÌÌ,à…àϾéþŸVŸlA&@[ðuàà:8º#‚ï˜8ž, ­‰©ÀÔ ¬—‰ÑäÞ[â 09 þs˜œ&‘Bÿ&N“èâ0‰ý!n“øâ0}ú/q1˜$þ €Iò±˜¤þ€Iú»Ëþ!pw¹?î.ÿ‡ÀÝþ¸»â‰Ü]é»+ÿ!pw•?î®ú‡ØLj¬Eýµhü!°Í?î®ý_ßi&Ã?Öiô‡À+ÿKàœ1Èü›ùO„ýŸˆÍŸý,ÌàaLþBð4¦*€UýûÒþ÷þÉÛ;ƒBÿ‰°g¸µ¡Í_UÀ.˜ýAð³¿ðŸ$ðO¶ÐåOS–êsü³äìðWuðó¿<”ÅŸÁ¶Z¸ÛY˜Úþµþ…à©,ÿB°¡V!Ø5ë¿lé_“±€íúS™¼Õhû—öfýÞ ú_ið0vÒàbv†¦¶Ö¦f,fgùŸ¨Ãÿrž¬Úü–þ:­¬²ÿs6ÿ³©ã?o÷Ÿ+ÁùOädú¿z°ñüOô÷`a{ù—Ó,`ãÿLû™ºüå,x¹#øáø¯F°ŽÖ†Ž•÷ÿÓ€<›“…ƒé_W ì“+è¯ àÎ!ø8\þB°p׿®x·Û_.ïþ‚Ýöø#\ÉÃÔáß­þß÷STäæÉ6†¬ |É8Áϳ÷ÿZhìì>§ýi¿Âÿa3 øÍ65u35Fü52æ ²LiüZêó)ª †RÔ¼)V¡®{¦)p1ÒºhDÖžv­Vë±<ufÔõ™Ð1¼ÝKy\âÌß>6uîuÏÅ`/Ý£…Pë2]Þ}׎ü.ðø}[ãìõ ¤âϵÑÒDí‚þ¬óã\%jqµ}¸2ˆ:.õ?2‚8¹´$Ò­ÕC‚k?°‘© ¥Ú—†²‡¬º¢%ÆC¯NúX†À7Ó-_€Ú1óás^¿ÜaÇ ·“²©lÑb©ì ”„ ½¯yëªΘ«:ö`–àUF¤¿a~­Îò ø¤?}Ž;ñ)TÞ匾¥]‹ì…ŠSw­hGŸNߢ@f±ù<>TÙè>©Õú2³Kü2ƒÕB` Ž½@óÐGó¢ÏÁŸÅ©ƒÕ Õn3£rN‰CŠË@¥ŽDH¶6Ç  ª~¨Áˆ3'^¤×6yX]ßøiaáܧ?„ÇR*r‰Ú? ˆÀ¨žmĊšÑ„˦ýyãÈ áá+—G2,ÒmnÕxv±È+ ñœ kç¸z‰Åª1zº˜Ý=+ýèIhFO1Ũ0ö³L)âãÖ&7}é$JÔ“éyùéKºI›¼# #Q:ny̵¢]/ϰ²Ë;Ú:Â/™Z釲¡åJ ®ö( «èž ž’A -$EÌ e¡¢î²é§Zˆ Ú´L2qÝm\_²ÅƲ:nàP€¡`QɆ¤•;Éè9ßë²æ¹ûÑ›"ˆ[v=Ë®ªC›>z’Œ+B­¤aùn4>`Ó²wSJ,6§a¿_*âªMZˆ/T†¨Gÿ[L ÆèKZe½ &×G;Â|Hk³^CÏ$¬ù Rô$â”n8C:„/)¼ø„lc|ÞúéõýP«1^ógS ãW†Úèí®véѶhê·t\-"ç"b>zü[ Ôî+IÍœŽB‡ÉôKZÖåNáÁ–;ÁÞRÿðPíC߳ÎþÞgGv}Ð ñ˜SÍ0MêRtv`QW°¸4ç&Áì>FüM‡¤óŒg¸sV²^6Vp„¸T^8Ùü޹*Å´˜Û? CÉ RÆè }^dÿáÕ¦îKò¥m”Þ³Õz®þ(H°\{Ó rЇpÄ)0?V}íCù‘v¾¾½ÔÀ¼§aÇD•=k~úÍ-y¡„³YΚw¦Ÿ¶±*P‡4Oá-G 6öCcÙ…%þÜçä‘*Íœyÿ÷«è%GÛfkFíšvŽDî‡KóÁj­‚|zs•Ë:yõ\.8§jUåM²œ8>'y>Düó5N.D®Í¢SÇÓqv™qS¹ÌŠšØjþ#fsoô\‹+EBŸ‘©‡FVì¨õ"Ûé'€qØæñ»Ï§v·£ƒ½süKÇóõ®Ÿ3cƒÍ®#Ù´ŠÐ%R÷Óq@ÛÇà/$¿¼Ó Aœz­ßVƒö.¯3'ÓwŸgÆŠý6OùoÕ % ‘igÞî×S]»uè1Ƨ¯ÔjçŠr¨)ª„íã£ÔI;eÈiØß ý䜤šïˆíðÑ´GkäI²Ð80Þ¼¡¦±}XàqUkzQGø+“hœš^vx•&)à_åNS¦×O”Êïh`Œx†} =TÕDm¢â?Bc?³vìB®V^2þJì P3©MÂ-oeZ Á(øÂ–¾ 8L»z¸@Ü£œw6zÅW? »K¯ŸÄ{þÀŽþ^æ·õì–©úÛç“·ü˜WÚ‘ +V(®Ýϯ¤Ÿå{4×¼ ‹¨ÑuF®PDz5„D©•%{÷Ý; -ç¡iŽ¡÷/l~„L=g\ ÁeÜžeâ êCHO°¨èŸ±E˜±Ì4»ÙÁ›7ìßç(®O™KÇi‘Gøçå ÇÄcž·M eÝ+h•ÿâÂFÚ`艂lÕ8quŠÓØ'ìaå¨Rü*ÿ;>Ì)¦Æ{^72YNö…0ãMVxºÿÀp ¯[òzgævZªzoüÃ%¢(ò6ð+úJ˜ý|^}"©µ¶s ™ÈRTÏœµ‡ƒW$/w2ôúÒ±ª[Õ]V/*”Ë*Ÿxsa¥çZD?U`Ûò‚ÇzOÆÙêÿÓiM “ûÜâ`Æ&Gdkd\VñÄwô5 `ZO¾IR¸–ÚL%°ÔdænTWòÆ÷ïæÆLÇñºáŠðʱÒEåMÍ'ã†,tZÎÜA>ç¸]º^håS®(ñ¦ª5œÅš qw ¬&!#ØÂvƒ?ú*;ïzn‡—=Î;#$6¸&#¾·¸„ºÞÌ¡º†#Ç&D6‹Ìv]Sf¾ÍÚú’Aéb.@õ×áÜH"`Ì?+æöO%®ÐïåϺ)™™çn#¥_ˆ ý «Õºhê‘OÕòF²RN®Yœn$-ƒÿ|úÔùÈ‚9l²!òÀã0i1>&¬_ØHÛ¼ö,Ô=ɲ¸ç]A*‡KhvÍ»]Re·øõàp–Mzº»´".™´•¥Ñ¯uÓ•ïÉìâæN•˜e„AâY)¼:}È^›äÛ!¹¯ÃWþeבW|zuº½bµÀ°g1Õžqö,ðSSÅÔx7&Ek¥{”·v F²*X€¥ƒH«OWòjÁlz}\DBÔØE%¦™0“­º×Õ1¤èi­Ù„ôÑ;x´g éŽqÓˆ MŒo…âoþ’É#à‘ëWÊVÇÀ“‚¡éq[éÝóÕFÇ8ô¡Ê‡§i=&0’M‘¸Ø@õ!ó Ë™¤0²škf§åIFÖ@ãºíëŠéjó*Š(” ™´ ®êƒ_O¼¿ÕÀ%Ò;{Œ¢·÷~nxJ¤°ýН[ˆV—B“ñ×2'æš·ïuÞûåÀ° ‹ÅÛ¦ÌÊkˆ¸Qq¬²þì’¦’®$¾ÊdaéC$=]Œ™Répr_Ól¦âa˜ðà;$ý¦C·¬íU<¹sà)²ø˜ƒ&bzéCio‰öÙ'÷†‹ÆÂ42Å{]y+æ‹;^âÀê=©›:mV/¢u‘*À1\NDQäÝÅ GéjûÃFKüK/úï0••‘'(oæ=›ï‰!JtÑ­ÅÚà ´'PHW… êpNÄÞñD×Ie[çôÍ®•—«˜tñõ„Ö"u4ΜҩZÅxÛH ¥Yk¤ lþxÊ"6ÁlÇr8tÆ•ªXâ[¯ß'èv¬Yp¢4Èj U¢ºß°‡iPR3. -cg)¾§¾l„ØV¡MÀ“¾ 墽íPI –ÌîªCEìtÚ­ô¬ÜØc}z ?ÒYHø"ÿ®n_`T.ãäÈÖç¶eÁ™Õ€I s-Jrfñ¹Ë½¿"O4,GŒ*ÛG‰ûNÂ<±yИûñÙ9 L¨”ëÔxš`£•k5gŸ×«²€%œõE?ad " Œ…â…l¾PqÁÓ¡óúµ+5"ó #³©ïRÍ>hé[ i”L?jNâ„WÁ]¢h¬Äìåó=ÅŠKΈ„ŒdÕ‡†4s¹iRØásj(žì,îŠ3F²ÞCç¿orÆx zY¡ؘØT6T­¥Þ·û rçÍ-F_é`3$Z¥4Ýï¿¶â!,gyÅÿBÎgjg\4ÁjÙ+)ìdϸvx$}mù”(È­›´¦°ZŽ4›ÒÉ3JŸü5JªUH5nÂ.Y0µr̘F§»ˆúÆ£ÿT-ˆfKÿ[^ðC‹Esœ¶Ø ï;¤Ç‚/²”;¨¬K*xEVÁq뾪æT™x2~S9±†‹X‚¢DtiIûÞSÎü$½˜=P °±ë³ÙrÙÃð§O‚!]´MGB¹†±ñ¡?Š M( Û3©Ó“@?‡(”Ò 9ÍÙ»ÃÃÃCfç*Æå»YˆIš È-hÄ>ñ—®ÔW7BÓ˯‹„èʆÁæot¿Åù‰$JâOØe¿­}H5ÈÛÝ”mJõóZ›1øèñø"„R½âÍŃ|?´áòQT¢ÒlÒ¯ä·g*Õ·<øÔ«ýëµüÆ]î_¬•>b㮵P®³¡f)PÄôŠSó6ø“-* År³´Øi¢_ßôwšU– œ±NÉÉŸú&ˆøyg Èz®¥°éÚ}’gåAþ5ò#rŠ¿£*?õŽüz¹ÆxŸÿŽ׃6'qÑÃÌ[f5GàÇwD}li±Tgy¬ü?{{7±ö*BñKåê èmîßðMûšŠÇ(sµå¤È©è@çÚ‹°0xØÖåÓŸ¡rROñÞêÌŠ¤d%D¥ÞŸNšÉñc3»N  ü ¤'XŒ* M(ìU¦¦„LϸG;  =µBª%µmKûÆ’MîÐëLƒPÂowSQõ·àG\×þtíA㬤¶šòÈÞ…å·ð|’èk 1ÚÅØK=S YЃ»žsP3‹Q…@©»›&µC¦6ñ™ÓìPB[ó%k‘]ÚÒò¤ÒJ¿³{¨¦4ÓУm,zÞ%u2Ÿcº…pëqñœãòóÄ·M¯8$ ‰ÎùÎ϶ì4ª~¹ïWáG¤[ë×Éú¥:بl¥\¸ŸÂi= ß6ZнåïÐá·ˆíÒb|Ÿó ¬bŸ‘kc÷±r/]ûÉñ‘puo•RÄÕ¶—9'?¿a¤hˆ`ø@DeÀT6Å| »·Ù©àQ ¢TœN1Ý—Ùéý‚ÔÙFWÍêÓLíëRþdì¦BsŠ‚5Nãá|© ½P1¥"ÿÑúÍÁ cì»;¹ƒ§rÔ¾²Q¢%eq,Y>‹z²Æ)Ú†Ì$]4ÂÁ¢ú̦Ñ%ŽÀ/Š-Xô`ÕÔ¼ZrÃÈêvp*Nz>J ùc­dy©ßCBº½â졊QÀáj9¬s•EûŒêîÛÄmÈ*!ºç…äØ( šª Á ÁZ]Ê3¿¤ƒÜW?òùNÐ;brKoÉ2]ÕóQâ7¿_No‡Õ?®íñ:·?mÜË&°br¡ÃøbË Rß’˜â¶>£I*A’<€9î™o* ­TåO·òÕÜö0<¡õ÷€Å¢~Ô'íÜÑ_óÄuXôåúëîä Û+aól” $ÂëÙ‡!^áVÓЗ )*p`fTW"»€Îª6ZÎÈ™=BÇ^·Ö8ë Î ŽÄùÜrÒ1ë9_ÛŒSiso¤²Jº|¢¼ä&¤dZ¢q!íûð‰)Kò›yÒ·}å%F4 °+Ü.#cà°6;mT°½dƒn)Ü^&J~?×TpcÜ‹B&ðö^pé’sZœ;r*Æ_À󟸜¿r’N“ xëîB¹~ BIE¹¸¶,°—H  2{#vp±ÇܘN ?:§DSO o˜î÷•Æ oþæn;*1ioPaHkx÷¹eeƒÙ¤¨I{my~ R„®mËÝ¥®VWn?w‘x—Ÿ‹XMÅO½0lx/¦§0^$FLü"rJ›Ÿ}/ §Þ)Êë˜ð^²9ùµhØ{Q²) €²"Jp¶0¼‡Íóy]óW‚ ‡bŒ(Tâ¹ás Ú6N?r Õb¨i¾ú+ºR: ’%É|ô¦FŒXx4ÙäàîB ² òHŪ“_¥xà¤Õ®ž*³î/Κ1L lf ¡¸lŸ=F¡šJ“‚Ù ]~ºàޏ==ÿøE.ÐX‹M›ç¼ÁŠ<:ÈÐ÷cŠG¦V®Z8êZ«m=.³Á’°´}¬¤]³}Ö÷/*»\D5 ‰¸··7+ºß4Ü—9–‰‡õ!(Q%®AfKŠ_% Ð6Ž¡ü2^ˆœÑ±ój#³xOÑHxZÊm‚g{ó2É™;–Èš3Ô£´è‡œÔÊLTÉyo¤ÍT«¯á‰4ážsÇÍ@©†¦1“KÐyËSöõ𯫭ý5šq¿l–µ°{×(ŒÒŽâ_•‘bâ¢Ýd «)ðÐ ¦ˆŸölnÉL¼\úëp‚)ªZið ]Þý¨9íæXª¶žZbÃ.ˆò‹zf_BÈ„+¯.ª¶T3vQ³‡ vßÔi`Ó&r?ð*ׯ"o³V=N9c6!e0Wòµ¬­Aj?¦,yhN“+}\Ó‘ÞìF'ÔëydÛv'„£éœôÎ%ñÐ1ëcÿÈÿz‡u´‘è£høý¹kY¾ècbØÎ[â¾hò…`×–núæ5«Ã?ûÉNËýèº'þã±2í“×òÛ»gŠ_7d±µTÖÞr{ËP¬/üW _©³€P;?™ÎhèßáV· Ǧw¹ºã j-×Á¤§=~‚š:•0Ón袗gØ– ›´Ñ‘ËåVÑ ôYšô;.WôÝ8EÚNIÕ®¸Ë?Ç„K¿tv’I!›…ç úÞ丳QaÇÓO¡=ÿK°ÈÓ½~ƒŒÔs¾šÛèìÚØWÁ+sµ–„0æHz’—*ˆ¤„¸¢Ezo0‹ÓvbЉ#áS¬ß$÷ð„–‰Û•Ê¹Éå¨*]uA½ÉÉxÖc]‡iæ[Fg`Žâ ³)ZÕô\xXykãù¯’=r•µþ©L´ËQ©[þ…Çæ¢.íu. Wˆ¼@ìÓ{‡Œ{ãÛæ¸pˆ ¨…š*F \Un9õáŠxÅy[d¶=t G?‰˜ðN4$Âê`|ð‡Ôœu=ˆ‹üšk àPyŸka]V×½‹ ‘zHs/ „AñæËTdd‰¥ç‡ì8øZy‹_K>e ^BxLH&)´å^HsC ðâ5m?ÃÕÈs-ßÓTW€´æ•®¡3… 7ý¡^W>ö}~†Ñ%ñ±k›o¬W"LÚ Ö âÍÿ(ÐÓ[uæ.t†hnÃ(˜ª7÷¼:cÿ. ]•*y#qyî½õµc¹@ÆqÏ"”Wƒœ“Þ£UÎîÁX‡õ1 ­]+sYec ¤7[ãªúD„>ÛÈx»®×»ÔÛ­…?b§ e§U.F·ñW°ðøù“ÒWoÙë‚ï°šq®;\ãmP Ñˆ´Ö_8„ö={ur<Ž”7årÞ4S€ûšüoô€¦’( ¾ ߦÑÄhûev(¯n™ªþÝ[r¹š>d §8}AöÚÝ‘°[/1£tà¹4‰Ðü›Žò#(Ƥ`ò^ò„rT@ˆÛ-ñ*·¾»«ÎkjÀb"Å@ˆr"LËŒÝ5­õÒ¬îºP;^zð'dø¦h?²Óõe8¥îìs×BÅ—„<{gg½é'Z©súëÒî¯ñßïQ­w¢Í6æì ̧-Ÿ’÷¢¦³ kÐPM˜™;¦G×…õ.Ó(÷`S¿˜ ˜é÷y­ž“Áòô¤ìÏ¢0œóZ(9Z2? Ó^º¿eÑ:Õ\CHüM÷/ö¨?Š‚Þ— EH̪lØËH·Ú¾EÔ_íM3²1ºÒW<ñTGLüƒI ‚ç’õ`!³#¶Úoô ´ðýLqgé8¨Ž à¥/çÕë¾ã½» °ó%uÏΈZ¬l–À¾PÖx‰!e\3Ñ.¨òâ¥hÐ4:Ò|!¡…_Têˆ4|¬ˆÇ™Ìßæ‹û)Í+Þï·í¦15„ǹ¼&öªÀ¼U/¹åó¯éé^AKË6"‰³~1Z1[²Nð±a.ÃRScp`bŽ£|3üÑøì ‰š)Ñô›ã\“t é5o¾äì7™¤¹ù‹¬fΉY‘Ûª¹ø‘Þ±œµ9Z2ïwö×kj²¢Žûo»7ÚM—ÁÛ(Žzƒ5µ0 5À*‰íï˜$Ë‘ $ƒ¨ü²³?·Õ2­©á "¼C|JÕï¾'ÖÖˆ· 4Ê©%xlavâ!•=bD‹A/&BCê›i/ŸÎVE)_uŸ¬m3ÅjĪf ¸œ Û$æg8ü¾êRþôÒ÷Øh©NÎ4g~F4G §úÁ7Ö8Pµvñq4qY*ßqðƒÍ{É_¡ä»œôðD'ʯ–¡†¨«¢4™ÍÜ!ÈË5̚ŒIâÄ}%O¤ä>Ži2èÇç‹iBÇfÊ”ÿÀ½Æ÷‡ok>Œ™m= Qç4(@…†a±e‰!àíÍn?í„Þ™¸èÐ}’vËÓÁ‹˜Ægƒm”Üþlu=e;mõD€&’£ò±6º£DH©ßá·ÃŸ|OŒ 5-È5ñI“lgä¡i XHL-XoHúD®(ÎVÛVy‚’ 0h@iT&|°Ãguì¾^,5Û“”» sfOxõÐ 8~ã5«tu%Žî“PûH^ XùéÓÝË«cŸk!?è4í-Þ e³Ä‰[ÄKi½Å+"«ôå ÉrGÒL·0‰µ3„À£èUÊ$ݵºþ™l\â•‘Uã— ö©6ËÑ{„4Ø‹é;°î®!ÅmŽºØ6ú|KdÖýá~ÙîOI›QÕÞ¨Ís ÿÍãÈ"û[E{‡SèŠo‘S†OzêK9×T'\Ú¹éd\3†ô졼½”£ååw@ýD›.’Z?­`Œ‘ºê.%3U"Qª}#ȈX£V{¯ÀåÀ>NóLñW—ÒE-"H€•~ÊŒÀrtR™‹`‹nRŸöÊ:ûƒ¤Cî8^0 -SþR´ôˆÞϺÔ3Ã)6Wš°‰´Úf‡q6Žù›ºö˜ß{ØèÓ&fr;öéÒe§…ð»ò‘À7ôc¨sÓ§@;’ rg¢Ï”•$ã9ïjËh©—§Ì"m…e;îûg•è ¤‡Ä“ë…|ÕWá&æFÜ>Õº¯IRÅ`à¥æ ' ‘æ«.Ʋ¨lÊzã9ê¿t·\¨«äD‹Ç±¥Ä«aûÀXR°¢±Añ¯Žf°Íi,ËÝ4óÊãûÚò`Wš¤$#y:`z* äÖµ8]䔽m€”Joneœ²É] ßgºÀŽîÃ(Ö³† øÓ—ÅÔŸ^QÙÓ¥+)Ø”@1QJxœ"êÜUÊãÈb0•§QÎ.bÔË8âÿœïÖQê+ñ&Ò0mãÀ>ŒÉ±öìHc²ò<¡._äRævÜJ³uÚ¡>-}6JGß áqÃÇ4¿MmºV2Ó¥¿àƒ‡ä-¨‡ÕË)WQÜzê>0©ÓÊ3Ó¶b.B$s7[và¢L‚@j .í(E/§}¿³µòôà,,ÐT2VV­Üò“ت’cD•wn+ÿœwh„ 9?½²£v­(RÉwõPÒËñ—÷XB>oŸÁ<91ÙdÁ¡A÷’Ã2Ùìïì¦t‹¨ÛÁCÏß'ïue>'}™ªäl;[¶^L«-y¤›Trjõì]¦õ)_ƒS¨4CSguN¤û‰!¤ŽiöMßßæ²_œ±})…AÔݺº´DÅ]AÌÝ*ú‹ó]2ïŒ&Ú¤ˆbÇ…ÓDé NÐ;ÿœëÙLï±ÐR Ä.›àuamÇGOCˆeNŒ…Yè›ñíÄïOÅ¿!çì”ÂKÞ™$Ãn¸‡îl*f†X,-§4¢#O¡ žl>b×¢Ù`ï¡ÐïX; _ÏÏ”hé0›`jjQÞºÜqz¬é:+B6ïÕH¨óUc‡ºkŽïǾ§èZIïÀš§q¤ Ž€Ór#‘8ôæ…  ±<„xI†òwÁ!)¿˜Z™¸áÁ%9!%Lc•±Cr÷†N&|QÀßß.ùØ,VÃi7ózÕ¾}LÌñ:0:*µ½jJSXKý&ÇŸ(ç<:Ͼºaðµ,o[°ðì<¬r‹ŸcÄÿk¡Ç‡V432k ~£ùäyÕ@uB‰q}¬gB%ZhäDIHÊ"~l8öN·{¢üi´ÑZ}k‡[L.ç®M‘æÄf·ò1,¿ñèPÑ·Œ‘‰*r˜÷"Zããt)!ìÜ2aÑ;c@ókµ!D6e#€NP^EÌk#‘x)#1å’â¶±âšb›UºÍ—6׿ˆâÖEµëMàæ… ã„7ðU–q'BzÔ¤«¡Â7B_E¿è­NDYQb3†¾Ú_Y¡]UÄaª:êÕ9#éóâXêÕ©ÿ"¦YH Ö ‹Ðn/ÖÇd Ò_º{õNûj¼¼¹´g6žUó8x»v¡Ÿ‡t1ÒîI=ëa‡;Aý-˜Ë½0YÜyR)„H0ê²)¨Õ/™Gm¼Î˜j¶ëõÅeë“B ‹Ûj4óøTM ãôèÔø·"¸î\èNYÒïpïËËVÅ}<Ÿƒ-#Oòªi4;Ž˜rWŸ4ÅŸ”bÙdÉXZ²Êý™¬oð¿·ìHd«¨29gg8n¿–³­1zkWo=«‰jÇ©Æ$1fkÅAOXmø¿SÝ¥øÅÿïåÜm¹"õI¤ˆÁ¡ãMbq[--Ö±­ÿã~2ùÏú“óÊ DZµØ8Œ!•Yõ¡b¼‰t±ÑÖË̓„x_D|ñô (z#ÜqR/}¡o¤´ÿNcÉðú…Ã}H&·×Ø1 r¦YyÕG{tH®ædä $ N™Eý!iýÚ.‚q7ºRjIzŸÚÁÈFb¿E ‘ίûHO,å×ÏÑ—Ye6Þ ³3¬q“8֧讀5áȼÙ†ç$‹¶.‹Cß®#[­ÃÂz¸ bã°ÕœÂ¹åÞ‡ñ»ô‰žÖ•(·ÞèÌPб÷x3ô!ýVJÖ¼Çd-’NÑ8)´7KÊyÝUQ–Sâ¼üqÝŠªÍ¥] /¹æ…,çjoSÂÝçü2]¸›ýÎÇ«Žu'× “|Æ/íRD5!ïL:ÙެÅphilVPLîp]gÉ? ÔŠ"õXçÈK‘ôE*|ÇÚ3>¹5âW¿Y]¼ZF‡È²× [›Ûu.ÍF 6~!áN‚½ä3´ÊB%‹_^µsã¶DþlPx¥.«Gâ¤,b“Jºn¹,zÒîy™Io<ù;€ÌÓS±ÌªcXÃÍŽN¥y—ºt±äwúÐø¼«ý<'5ñX&•nòÚ¡t±chט\ºô×›â-„I[`Ûã‘™{ä<®kÍ\Ô‘ÇïmϦèC¢ï©Ú›P_­§¸WHÚRxiˆ€î£xö™Ö3_#Üšt¯'uªbëñâüÄ€ý›ÎŒÖÍŸ>;MQ|WÔ6a»è’ý±n¥'_¼±GÖ{ÈèÄÖ¹‹²?ʼ¼ˆÒ¹¶3K©Þob÷¡ái+³É×CZ—¦6-1¿H‰ JÇAã@Þ1Ô^NÕ ÷·…û^|‰>†©¾7Ú/âø8ÂVO Z+{xNýþNU@÷M y‚ˆæ6Ь}Û›4CmÿôúIþ¾>g xx9s‡ 1b¡-àð9‚ŽÃÆBË[¬}  ÌXÇR ÕUõ£!Ñç4¨J!¼ÞÒ’ŸRå«´A.[ìƒÙÐIG›Båo…òÈ.;G/§lØöž‰YÐJöÎ ‘…ë"%E7<ôu®‘Æþúz~ôãÉÎ_MŒúÏÚº{7W¯}’¨Ä¡Ì™ÛŸEÝ‹¼¿c ~ì?O`GT’¼–éïdÛž±ÑöºYLàm†ífëȧ|T)*ê­pd0”¹(asžF}3$0Qß]˜g x§ó†è7O‚¸ŸÐ8¢RØ-ÿt·wýÁ¤Tb{Ã9Õ?EÅšì`²ëÛ/x_îµu f˜×QŠI®øÕz8õQûȤoE}SpiÊèØmGs&Pó¾h'1€££{÷Ûi®ÃíµE…«Ò’°Ll»á€|`ø×ðyS”|Õ+ë7ÄÙØªC©Á"¬ç!uW i·Räਓi°M ^û+û¸Õ2²«…mÝ4º;ï˜ûÝHVtO„¯ÀuB¿^ÉÄðO™Ñ‹"1Xu¥4]ƒ"ò,Á:™Ïò–…\üÔ(ƒR¸ÏÑŸ74JhKú‹úš†H]Æ.yÛ÷uwlÓ¤‰ÉA‰ê¹¿Þ?¥Ñ~fvôŒ¸þHª´”-üÖøÛv³±ÜfæëpÍç×F£¶oã’Êï‘ÏKLôä?†½LPŽ Ïi9~‰¡ˆ'Lhð&ªÐ!A{|чR­ÇÛxÏpE­ SGM¹zŠôSA–È âœ¸üv`kDâ²Î·sN_¬JwL“ad—7êSÂþûL‡×ظñNw´Y£§=aµ dtö"=š¡Óu‹C gì¬]?ž_5œá¼LŒ²¢ÐžÔ‰ IÖ¸£%ð zQ}…<£apah½¬œdEb05 Å¥Öœ¢‚¿ÙUKmUí3Þ'æ,éDÅ>Žôx3¦ÕLÛ´ïZÉ`ÝÜLUrãÂZ54òÊÏ‘Uû¨eê §ˆ˜>=šSÊöórfB#qùs!±âö­7¾øܤÇ@j³“!R- À¥Ë3uz%ìZ´eŠ,^7gà£Å?ŠÔtÿÖèâꌡ[Ëdø®Ÿ }K; Ògî¶«Ü̘ó=[:RóÕ®;¯ôù¦Ô~; S¸+kÊC{6›u y¡ë¹Ó° -U²M¾c¦ø+²„ßûsÆÂ Ž‹ÿÆÚáF2múZÍqs5¯ü6ü@vÓW.ï7x…í„Í'm· }lJ?{''Wù„‡ÚÚLY2C®%»ŸX%þ/?æê2£¸§q¿e™ë¢1û8—:ðÂåP ‡x±l!~žNÀä‰s¯ÃOvÈ€HûGâ5G¶uŒµ_ÈŠgk-xÃÒœ›úìé²Ú‡ñÜ? ÝDæoˆPïÍæã”)ê+“»†ŽcØÃO¿C ŸñÀRg ©µÚÄVXIb ·û¼ìœïå+€ø–³Nfš3V,ÜŒ¤eDPxXv¥ÂüeÄcëbOâ)yô@ÿ¼Ô¢Wí@ÑÙ·´ò Ò?ÿNûR’>Cæ£úžbeg52‰Ì¤Àµ\J kk̶;Y#emØmû@ËÆtssýž{’ŽR¶`*Ä…ÖÖq€ÀJý÷½ MÈ;9€²_˜MΗD²`4ê]´yíæ~ Û… F/)þVøÄ«ò®Ô«à= dbx(ƒõ\L ‡XžÀ¾ç˜dí‚!FúÜžøãÿ~’î( endstream endobj 1359 0 obj << /Type /FontDescriptor /FontName /QUJEUC+CMR9 /Flags 4 /FontBBox [-39 -250 1036 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle 0 /StemV 74 /XHeight 431 /CharSet (/A/B/C/D/E/F/G/H/I/K/L/M/N/O/P/Q/R/S/T/U/V/W/Y/a/b/c/colon/comma/d/e/eight/equal/exclam/f/ff/fi/five/fl/four/g/h/hyphen/i/j/k/l/m/n/nine/o/one/p/parenleft/parenright/period/q/question/quoteleft/quoteright/r/s/seven/six/slash/t/three/two/u/v/w/x/y/z/zero) /FontFile 1358 0 R >> endobj 1360 0 obj << /Length1 1019 /Length2 4299 /Length3 0 /Length 4957 /Filter /FlateDecode >> stream xÚ­“y<” ×Ç%‘e›d쌱6”}ɾ¯Y3cLÆŒÆ=û®²ï[¤D¨¬E YY²“%k¶l ÏÔý<ÏÝ{?ÿ¾ŸëŸë{Îï:ç÷9ç\À+Æfâªp¬B ‹Á‹ƒ%À u3}°$,!IªãP< ‹Ñ€â 0¨z"R¤¼œ‚Œ¤‚IPǺûàPH<@H]ø—H ê†À¡`P ÀŠwA¸‘jÀ h€†Bà}$ªh4Àô×S„ç…€KЀÁ8 †8!( è—#Œ3 ÿWîéþŸ”çA2"™,±´Žp¦bI½$'ÿ¦þY\Ë6„ºý*ÿ{Jÿ“‡º¡Ð>ÿV`ÝÜ=ñÀ Gà0ÿ”Z!þ2g€€£<Ýþ™ÕÁCÑ(˜*‰FÄ!2r…QZ(oÜ…‡¹œ¡hÄï8ÿ§Òð~Û™YÝ´T3ý÷V'¡( ÞÜÇü[ý›Á3iF8”7à–¤„¤$˜$$=ÿy³ÿG3M GaHg!+€âpPÒ}Hà 0p„7áMr ’À`ñ¤O¤Áœ±8š_K%mýú‹ ì¿–”€à BüÒò”€\þ‹2²$òqwA`þPb¨?ÔÚõ¼¡ÿ@’·¿‘4>Ð¥Hç Âþ¤Þ¸?ÔÈão+¤>h¨‡Ë9ÿ’Z{ýR¤â>¿ñ÷ª¦†õö—“ˆKÉ’æ –’ÈËJü!̇C`ð¿Òuü‡Q¤{B ¼0šÑa,L1ìNJmDi fA_Ù9a®´’°î¦ðê4E‰Õ)Å ƒ¸×DsÏ6s8óÔ3¦'ëzÏApgÙ™Kµªþ?3Pøgf=«p^ºÕlÕμ#§½…Ñ-+úë(ï¼ûkѱ«»Ó^Mç*ô—Áòù—Öc(JG†w]ï÷̌Ҧ¯.<¡±Ï©×OFX.M?êú±¦-ÀŽu°Û¥ï²œŒ^j™p OƒÄæœJ»ñ“ZRØÛy¶‡œáÊ;j$üvšâ\"pt°û¬ÆÎaJi6ú)»Úãb[ž v~ì„[}ù'ˆëJSãwn'!Ã=²Ú¯bddü%½¯›V36)É*‰Ì™#k¬ïÝá#xrkžÙͪn´Œ~lÅ%5«ø"y™æñŠj¬ÊF'‹êuбoç¶uˆ÷i¦c‹Èœè‚Ï*½ˆ3Ü~?µ¥Ðæ¹õª¾K}CÑÛüÂQäind…‡(Ÿäá6ËÝ Ö%£U|§Mè>nõªîÖ„·f{£5ÃË<]evSÌ6/2CÇŸ?î訫”7Ü3í§cTúʤëŒÿd%R!®YB»Oɪý…g®µùê4¤¥ÿÕ-µÓ”¦&×N#ÿ¬öEžö@#$Îòd”RïÓ|Í廕þ… eÙÜAA‹c5`*æoþ*á9¥²•Éü/Ba•°¡)§R‚'ÓU­öÑG\êö¹Ðt»¨ ‚btþ´ƒ—ÿ-3W›o T£UžÁbz}pz+vô(ÆØ}G8´ž /?gL•6í@óé.>Ù&uü­å‰·ï[>h'›öM䦖ê)nyí2÷ÎÞx½ñcÝ_»æ91^›l×Ïm—a‘ýµóÛü¨ ƒ×Ú÷uãvenÝ—u©Þíõ)jÐÓwÿ«0ZÑúæ¶-Ùpàá:¯ËdÙczÍêë3ÔªÍìÄs¯ï½ç6Ó­¢£LìŸÜ¤-O-ÌE·R{þn¤Y‹.ù ýÚËòs,üýËÎCj¯OS¯­æ{s|§]ÉgC+åжø¼Ü.u )Üä^ýÖQ9¨ØÌ—=öøÊRÅãa‹'Y‡#§­n5eŠªC9µ›À’žŒ†™^·åO?$»ÒÅ àzñ¡ˆ<”ÏžVzì&àX0â cX³­80aX útÁföÉÒûÐRX ó/E$Ó“™¦±‰¿£EçÍ ïõ¯ˆy^_ ɺ—oT© YÝ<¹V‡7~Í`²@¿Ñ›ìa›~Õ…}  ZéjÿºyŽ“ïðû1lú{PÉãK&±áÎ*+ýòØ‹À1KLŒ¸'VâØ¬Ê1›§kɱú®„£/iS®1³¹—d”_·RV1DÔО¦Ê·õõžãº˜G«œv>„28pÁúÙr·¬øf7?h,“«PCÆaÍùÁOÎZHTü egF Oce$¹¢6°vû±=à¶e9;KÝñZƒØ®áÌ<šE¹þž^+²IRTá\ÈgÜ Ø-ìí QqâÙ²ß=å=c=‡œÕ~Î%õ7k=ÿ¾.ìɲÀé[KÞMÛÎHµã6…ñmqšjCåY@ío£¢âW©W ™­îßíumÙÃìmª<Ÿ3íØ ‡Mû^ð 2 ÷HÑ·]M©ç«•´9Ò!ˆ‘'ÌKDôÙT8ÂÛãÐTË×gÀy«N·Åk".|mÅó«™KµD ØÍ&^9Dg¢)éýMxæl šÝcö†ø;¹ÊM÷?Æåˆoyk…oÛZ°ìwáŒôó˜­:Ш„½­5,Ò†dŸ\ïgˆš º}p½»IçKjÑm1L¬Ñœ6AýPvZöˆ#ŽêGoÿO¡ ÷^ß FĽâ8@émc÷‚ïÂtØ7ÄÛ9dÑgÞ­þGIyÜgFÌÞMÁÄ;£Sîg hu‚¡Àp°=ÎäTNÛ´ù¢ÞžâèsçpÀ|4®b… ¾SåSåpÜ­ž9~±Îù<þƒÒsaÙ~L×Ñ|U— ]—GyÀUŸ¿†V»Ý2ú|©³ÃÃy©*R¬ò!té/áTv¼–"˜OštÕÄîÎw]Üc£æ‚7  ï¡38ÅÅ©¯B0Ž*cë¬M1”A6Q)VfÈEeßþÞÄŽ9/:Y™¸æìª…TÉè–¹9Ÿûˆý•,oÚʉsö?nô²—[à+Tçºõμo´ŸŽÅ™ŒŠ}c*º§A6ä×Ì"§v1 }_`61à¥x>ëAZ/:ñI˜ZÔûî'ø.Æ@­NÌ1YéµJQ`i¢ðÞ‘žXh(Å$=«1à+ß‘ÎkJÛÿÍ·jg&Îe«þ¸wülpQÕíöš•¡Êx<±°Nð±Êe WYNŽè|±•2õÓ°‰ Š–Ã ÷˜!ôQëù¥¹ï“^fhëýx·-QÁÐÊV“ÎÊžíZ|áJöÀÅÔ^¡7¡¬pÊ“8>%†µò½¿æ2ŠÕʈ®2ý˵ÙN¸cX›3pÔÇölý|ª&nàS£rÖ4Â[ððŒË§ôë‡5oPá?=æôÛŽ×|…;óvîâŸÞ߃ø‰ÍS\^åŸ7*5Þ ÈÙ\` vlP-XÇÛÁüû9KÍoC, †ãNÎþ˜r\ 9|ý¡T› ykÊEÕ39hí.w.GÌ™â<1ò“ýÔd`Æð¾èç£óܰ1•g©«ùf>óœY%¬‘{#:}t=÷—ªru´oŸ?è^bØx 7þ}eš¹7è¡gQêH܇úózí©ÂÛôˆÒ[C¼õF7e$Ç3Ö€!º†Ó–`»ò}3J¾=¢ä¡žè#~õ«RÂ03½€¢W×##Çk¶gÄ®¬ÆñvkšœþZêü™Ï3=àstËëŸcú!k;·#¢sûá)_™Ôº¹ê‚ªcRãc^Ü«.‘™è?üóÚiQ”®£_(íú|ӳ¡5'“dÂäBÂ}Éò~ûrB~—þ6GwÙ­§Qr[®[Òm²ÉQòb%Y¡?ž» Udí:XÙ2ŸÍû ç#LžhÓø9êså¾c·æM]B¾«Ä’}½ßÝW7G`Ä%Õ¾á[SqƲ»#ZÊ<ɪÝ>;²ÅY·²yT>Ì ·¬×Ó΋x²æ1]•jò­2\½vç+ýçã¤0?GïþÎÛò¢u†€÷SŠìàxµñ§º}”ºHi[cÈŠ÷±Gmîmó÷Ô!™®u‡ WWHº>•–'æ²b5Ö7ÃýŠ…=8Ôu>&û¼SVWLB^xPÀìŽRœ·ŽOÚ>@ÀšD:ýKiÊÆ;gm—ùÕØ?&“­T!\˜AªtbH¿úºuà£Ù-oĈ_µìâ¹Óuo*ñ—ß´‰Œó2×}}E'6.Ùjõ·y\´Š —šD-¼|6_k¢HÅ.Véþö1úÍ…üðGp©´ öø>ë· “×AçR$ºuQÀÌ9ÔOé–»ÍhEÊØ7é£-pÔ,k skj tF¾çSü<³HnÕoA³§wfŠÜXË(…°Õ‹ ÎÔÁ´J¶ž±€Lâ7€ïdA¼&¼|R÷ xbzÉÜnÓêE®Ýô|­kï2d">jBç$li6¦J¡ù!½÷K‡PþÍ íÔç“×¾®iÛX™>4ÔxzÊké™ b¾ùœ… ­m_¢v a bböæ‹|3V›ùÓÜq 8brÞqÔk X7 Ù?~q˜(ÙX<Ç3,ãt“LÌM¼ÚƒÈó:e5a¡\»­Õ%DVöðñŒôó4+Ç'„、KW ž»¥ !‘2.î,e³Ì$ÆïÙQi̽ÎD/þ rgÖFøüW²£ÚwW;”‰#S®ÙL´Y¯.­ÈmÝ&¿™ø¡º‚éäW?ƒGH!ß"¦ê;Ú÷ïCbŽì·KÔ)u#©µØ¢ Ì=þrœ"ÚQuâ­·¾È“éØì{îV žå”Þ˜fÎºÏCAôÊÉ´S…ò8d“sFvÄ5”ÏI3ÑU³Ði­(XOzaoHO£JÆô·Ë鄿º;¯Àm€ñínwi‹ïÊUþ¡*ùò{MBcp3â—dê¶ß»Ç=/O Ÿ°ª ¿{K¹f÷¬1|¬Î°¢D·–fÀŒw‹årz÷¹+)TݶGP¾)ÌS}#²nSŒ|ñ6OU‡™½½ÂÖ ˜á¯ÐßN¿Òú¨±Ò &.®çf±}€áä²Î©»*-mÏ3JŒç_í&uM¦øÍÃ&UòÜ÷ÔTâiícϲܾåó°l84Iç+uÃÓÔ+î_Çúʹ~zÿÅÅýTsTâµVɶ"ÉwíO,šßÔ)E¤ ì–¼«xÌ-Â8ÞCˆÒ‘d'Ó綈r½¿@n¦4\L e‡põpLˆü\,+l:w…u¸—­Ý•†Ñgõ=GcDÓ‰AJO¿pMƒ6p³WK´£ÓîY½2dö•¶¸¦ÏœýîÉ‚5tîôu·TãIôJ€n#úˆR è£çƒ0ÍWláã(—v_¦e$Eº† f<3ƒÐnånwËö³ŸPkU–*:œdO‹KU:FPºœ-×п¥:Þe øa{_Æèc•{ƒž3r¸)ª¥ U 0R—<˜6)[$¸X®E‹¹áWÉFK ¯ƒá:DPÍ5G)²Nö—ˆ´x_õOå¤ËõirЉ¶GYëä/<)ãt3ß䬗»ÌôW\µyxz3À˜!,3“Õ¦%U8£Ç®4 žk  ‹{œ”GÕ]è|HÙ=r>—myqX´Ði‚ ‰«26”?äw¦H¸‘™¨ &8*¯LrÓ`[Z'Ë©=-ªY%"e8rÔJ¦Gf3o¨ü¤»!‡<¿<%›úxÎù]<¹‡×ÝËNe¥.ÊHg¹-04ÒpÑ´oëÍ¡@ˆ·¡6æŠ=§¾(E†‘õd(@kót<#ý¸Ïfi~¦> endobj 1362 0 obj << /Length1 1304 /Length2 6629 /Length3 0 /Length 7397 /Filter /FlateDecode >> stream xÚ­—eX”[Û°éD”º»‘îîΆºK¤¤ ‘î’î锎”î–ÞÙûyŸ­ß~ÿ~Çü™s­ëºÖ¹ò8nZJ5MV +ˆHâäÎÊÉÆ)”RÖ|­¥ÅÉädãÐÒJ¹‚ÌÝÁ'iswSP(áaä‚õó ñp ñphRgW°­;AŠñ¯ ~ „#ÈliîT6w·9ÂjXš;5!–`»PÂÁ¨ñW†PärõY±89V`Kw Èì`ÿËIÁÉäÿO³•‡ó»š-÷:sf>ÁVÉN´œÝ¼è÷orÕw=|UFöî…Q_Ô\'ÌÔªòR(Ͻá†Î[|Âü¸…+š™.÷­‘.áyBÎ:rM©R3fLª°Î6¦g¨â&5(FÝ]H˜‘Ì,ëé %¢›ûS›>¢ _¾!,+îB} 8=â6©ï4o±u¹3ݯϵ;0òçekBMo~{–yR .ffW1Ù„Ñ ‡ÅrM‚§³–“Ý@ª½µ/²)Î Ì—ãð6CE1s0SÙQ)ùäGK;$Âï/,/z—zÝGØPÓ+µtÖ¸Û¤†‹E³óÌyª¥ ZP"µ®AÌ¿$¹ÔO¹ácÀÕØâê»(ëüa{…g³dŸwùªÁj׿»×ò ÔÌÅï,‰Ð2†(¦©Þó<=옪f7I1NEð,¹¡J§ÏÅ‚B"¥uÖ_©>Œ)/TÙMâ‰N´ °¼–!i?òÓï#&Gß»VϬJLÃÎ9uà3õ#LuJÄÁ„I²BI™´ïØ/{ë+˜Í >0ÇTyS9¤\<ªØQé*îÖæþ«‚_[¼?rj%×D¸ñÓéCÐíöÊ^ýùå€ñW÷K§8O3–õ"ò]8¨SÇ‚¦¢XÜHŠ`œ Àc&Â;È.þó3Ï)ÕôQ¿~üúìÓð+,”Å«4}xñÌ1íg¹{¬Ã‡}JU?‘çóAHLc{’V]à¸pÁ0‹ï_Å¡­ÙnŠu½å?âF}¶k¾ööÞVÐ펥R(~»çä¢b/|öÒîe[® Ðö#¬h›2bÜRw°Éƒ×ÒÒúÁðN ’ÑñKL‡É HöÀsñY¦÷ÄýÈ=µX“—R‡„ ÕÛõªi®áT£Ù¯Ã,¤GE&”ImCG»ý Ñ‹òß¾ƒ±ü?­ÊëXR°Ç¾--b t21Í÷d8|¹Ùaª1Ÿ}Ì–²×iýºÑØ™ õNæz¨Vr^íÑÐÆä‰fÊXêuΙí¤ÒrŸ¶ßíCã÷ûþÝßÌC›ÿ•*ÜýÀnb-¦ü k`r ÀÚoöP—墢÷´&1 %ȧu´L¹XºrB:9ž’;CÙX‹öæGlΈl«ÕO˜E.åµ·5LÈ1ásåGgL:ÏEâ~MwÞæÓEÖqV\ùÚnÂ:-Žœñý©š{Ä4É»©±%‹ßPÁ³ï¡Ó…¾[ì¦Ú±œ½à¬GñÝ0ë¥Mmô“ݩʄèHýx ¢è^™2AmÎ7õG,‚óÃiÏì ¤hÙ‰XèÚjBw·„âËdŒcjÚÈÈ7 ð(yçBÙ)¾†Øj×<•FÈÀ«åñ6î©F©^©]|å¢[­ÇÊxÀ1¶pà6¼«Ö‘ž÷ðÌP}Ƹªünú—ƒª€u¯;£í—îIÏSVûþ¹ê¬;iŠø¶ò¯ôóXTý«ó!ClŸIÑ6ÛÅì&X¾ä´ºöW[}‘–¦ÕÜ8Œv.~®b@ûÆd|&Žõ!1õ¾.WEmÁå'ﳄº¤â‘nt$Å xøþLë€dŒ‚Ñ 7ÐC(’I÷h*ã~/k” ›R8Ú¼Zôan¾8tUŠù8´*ÎÈKr@[7Ë›åGþµ„^(¡¸©g4c*^o“àÒŒ¨%g[¢7gûã, Ð.m&ÕG+ñÎ{ÒÑ¢µ'FÝèÕEtü(‘ðú9dÇ—H—TvEe5ŒáÐUˆÀž8]ÄÞ ê-×ÞQg‰LÒóf"öà`'è!Ⱥí…Y„R_;\¿>ž ´®uxÒQAD¨„͵s‚ow¤[,º™b%â}¡>7$vAŒ}Ï›ü5-ÈÞï¹âN¢ç%¥ÑfkÒ§!ï…q,JžLݶ¦¦ T±Ã:é»ÓA𔬓|ÉHº.a 1rΨŒ€§{õIH‚Ù›{j5„ò–,W._”hwú)ç5¥Ý+¬‹Í{_GNiM΄(+È~_ΰ5šMfƒÇ„Qlhòà3U¶ …ˆbàf9ü[ÅÔ”ë4ŒÔ´íß?§÷vøeÌ™ —#ùdeòKüKÌéùDËsmM¢þ±—!ƱË8\Ì{í¦OU©Û}»8$G{´"c OY¹ã’ '%ãžÍŠ•æ¬ñøLqL³s€{;NíW1H:>Ö“)ÇWÞë}‚Ôt¿ŒÐä°·MXÄ•ÄàB¤øeju¥Î†›ç¸ð~¸ø^N¯-­Æ•µ-.­JØîŠž›´b2XÉ"Ap Ø9žûª ˆNÅŠíqæ|ÿsyMÐìè±` { ¯§S³Ú Ü\ØìÛ–"R[ƒþ/gš"äær)t*¥º&:A2&ŠÀº´NÝ=K5¡Î€B…·8 :•Fâ]Ä2–…ž£š™Éަ|b¤¸±¦mÛbdI(ý%‹8Gê»ö^«½_®nØýÚõl¦? ¾Ör´‰h:­š¥Íã±þ˜\MÔ¼¿Þ¬Åž”80VRõô«÷åê3™ÈnÍÃç³iZP±Ú Þ ýÀ`î]ëmÁít¬:cé‹wÄ@ñá$ÓÛå súèa0ó,BÄ‘ð„{³ì¥~ñNOr¿´öÈe­¥¹"Fb0nŒ· '˜zÝ[d—³-»x‰!/ᚊùòûhrŸˆ‡áðuÙ:Ê®}÷•2m€‹Ó•Ø1jÈbäû­6O[÷»\c"ó‚ïžö¿û"Ce;Á*™*1l )2:ü_ H?ñ×z —Fw}»t;¶Œè':ÞÑÓ_… ï‹<?)ÎûT¿ŠÝÏA—r^Õ¼^@­]¯›µýÀ õ#%TôD½Ëož+úÕ·óñqÅ·ôu&s}ÌAKëw?3_Eç"¾&ÅAÍ–ÔÊÏF ßC›[wï%Oˆ‘ÖÖU‚~CE¥yÔgììûfˆ.•GVxR{P»Õ•\ø°y3©ÓåÖí˪rNðoª0³`eꆤط¥^é´u‘³76Ä›(Q,ØT~›z¿±óãƒFäK_½¹ ŸNÝðüæÈµ€v§Çhì7¶øÔAB{)ㄊ:}WòÀIÄn¥\î¬[*ë³çZç:q·QÝÊzÄ,‚/ŽIÛ/;¾n.îÞ¶ Jï¶ì0þBÕéÒíõ'Qo o.$ˆO*ÛèÄ_¶Ö]Ò GW­Úú&kÁaXI/^ñ„x«!/~9CèÈ??ƒÁ”YÆhCÊ¿„ñİÀº¶[<›¸¥¨A§¸ X¥n ƒƒ[s½ýÈríXWÐÞV·y‡Œp/¹ŸÔ"µÔc¯IY«W°_ôT€tq¦Í»ýî|ôÑgV‡Ÿ¶.Þ¯ƒ›}™P˜¶|½â‘¯w´›>Ƀ2{aíÁq8¹q^KE•<ÑíÓæzvS‚'Ô«ŸïnX~žÚðgŸöØ)¡¿` >ÃA,6Q:á Tp1⻣^Ž›µèu§ô3àKR©S7´‘xrgq™¦`AVžÒðd–æëünKÀyêåM~…¨„É÷]å°‡ Ñö¾cðFYjÚS0ë{0•‰ TUH²ÃÁ;àаèS>ýWIæ¨Éu®Ÿ{±yÎèíÅ÷“ÏòÖ·µ® oEm.l E¾Á3ï8^ójÝ"Õ§äí¹vøiØDÜO¬`¤_ó‹ F½èªXæz}œA­Õ(H‰&©üÙ§yÆ?)UÌ{ªüždáü ®Š±°öuxnQ§Ú¤„´}¾ÛÉšÔÍAf[ÉîÚüœ˜Á´hf9Œ¼^oò—x먞3–6—ÆIÊ]6c ¯êþm¹­·Uk{~”¯-ä2¹Ò©3 Fßï~}G¯ÏÐ;Ì|éšF²ê¾¦&{ -@×”ö •+ jØÞRDgm1-BÜÁ2W]™÷#çÀv‹}÷M÷y…ŸÛÆf€.SMÔcár uzn×i«oœ±]HŒn‹+9]ÜöVÆû²«çô‰»žàö$ãUw­IÂÒ™ôeÊÙO¯È1½Ú8f›€¬ï#H+_º =1Æ<¹2¨tq;† 5<ëÃË=!µößéz%Øø¸Ç¥ÇwÇ"©ÎŸ1à¢@—+§¾œ×w×îû #EÄ´â®ÿæ4üm ßêYÞ—6Âb¨È‡(IB}¢ÉžÙo Qï?SêAI¼Û5F•%âbL³´xˆ¶2qVû1|ÐÛpÊåÆx`T/”•ôxÓNúµÈºÙäçDJ mV)ã¸õ¼†&èÕŽS–>úŠz·ÍîÔ¨5&ôm2»CêF֞貨ڛ0JŽàj>·–Ù`ÃíX4Ÿq Õè)NŒ¡ÃXy?;\ML¢ãå…:Õ¤½™vâS×Få‰}OHi\`(îRìÍù€]d€—óžc›µÎ÷[>ÇØ Û’îÒpã6ec„F À7:‰/Þ1u´¡\ʰK·º)&keûhî­S-1‰\cpÇÓFÈ ÄkÛñp'‡§MÜ ë6ÌTc=›íäC«ºoûÂìj¼F$gû\˜!‡ÏÕϘZ$Ûe¢ˆöëÆ×+VÛ°Ð÷t»D1 —¥ÎH2¦Q¨6ˆ–‚¿º SˆgŠL¬ax¦"I%‹i›×*QÎ[{Ð=Êp.(q°iŒ&×y5‘8IúqQ_å?~· £‹NñŠQPByƒ¿“‰5±…Ýä𣜛ŸÁ³`ƒ‚{ƒ½TŽÎDÁ7Ùo?½í)ý! Ÿ%’fc%)ÊyIò”XÄÂö®½Fo•È÷ ¸°Hš”œï€¤J×þ²0»ÌEÌ­y¦)œåšÑà‡ÍÙi–v½ê˜@ÓÛð¹OB€èñmS7LÖ©”º(ÅHËÊyasÄ`©rrMapž#µrÊ®fÔÆèBa$áÇAºÐ"œwµßW¦ÿ® UûJ´xº3tS‹vl1 GÈ4EOÜDü"T—WP³öV½Èz¾h¡ùžvh5ª€‰hBäsR®ñžÍX9åºDh‡I1‹Ì*¼á³[*LWhèžÛ6LV3žË¥&l‡û•ó¸cîõ‰C©gG=|¡iDk@±c )´1+ͶåäÒà‰›f ÁyôU®SH#ó~žCN©?¶‚æpº'¾ ²³œŽžÈŠ´ áÂé ß vÛªÁ6ãKØ$þB4vt•Ý82²fIGÍíÉgvFù …“†;±ò|"¢kŠ!$ofgu]Wuœ„är¦++Q6âüÐ¥VØÐíaèí÷Wö=iáþØm UBÕ*Ù>¡÷f7ò¨Ê #Ï42 n)cÐl6£Æz™Ýà ×КeáHÚ¾øAèí©Ñk#åŸÄKDxxÌÜÂèµÈ«%ÔŠ 5}oQHŒ˜ùˆx†q¡Ï¾žE$,Mn7žÉ-xä+pBT3*õ ¸Øü½ÚÒxŠ]ÆHŽ+Ä \žVÒ%ÄŽLÍ,Ù'x¤zÐÞ +4 3{ë;÷{6Ñ¿Ê_ÊBø¼ m3¼ŠäDZ¡JGY,å*Ë^}jÜ51¶ÄͶg©“‰xœÎ´oÁÛ'¢{­*ýµkî…ïÒ Øü;}"üû¨Õ‡s Ó–¦9Kõæ…oö‹rKD ?Ÿc*¨ùÏ 4û¦ £YF»:¶KùFd_ ~î‡A·ÜK·°Á¯Žï¬s†x±­ùÛ§H,KÇ\zÈ,,‚{³FoÏ SmëxcØ ,èÞûøƒØ 4pMЖ¼û›±!'†&½²d di˜$Ž3 )Ž¢hq“~'ÚéºñÚFó;ƒy/+ËÜÑ3>W™oŠ~¸t(X­ÖJoì_i‘æ• HE•·h7b}!ÒÜÖ·Á5Á‚‚q–Ç2*y!ï¤ßúë2Ñv¦(.Òú•<ö”-öø¶W>ŽW÷–ézêáCμ~(NEº݆ÙöXê9·×ßûmÙ‘/Ôg±hÌÕÆA?(%c;`ØÙ›´jÎÕ ³·ß(ë¥vgÔ!ÅÍÆpFò_XŒTò›D2J(CsQ”4eaG¢^îòм£ñ@8†æÁ§=Ù‚Î&Rsˆ ïË%Jæ“ZðF€¡r©òlÕ+¼Å3ñÒ{ö·*&ŒZéÎÉØ4þUÎÆYé_žÙ­¨èìPPˆ~Q@ç‰D…; †ZK¼ƒœ?¢ÜGYª<)¿êÐI"Ô¦~¿O£˜Ûl½Ž§Þ1èÃfïG‘xç~ù«Ëü¾`mÀmF¸ö¶î³8º/þZç£{ö‘ºóiá˜V zã%3•¤û“:™÷Œ• ®Ò[: {=•¹öÞØecK6šÂÕÖm4E>G]*þ–2Ê -fC»\4»ŒŒ$=)#WʲÍd÷PÅÀ\C.uø)„Ï47桳‰)òÎþ,"8Ki-ŸÏ,ö„È»á‹÷³îëi®£ Ô£ ˆxy¬J/> =*+Ó‡«ÈŸÿ¯cðœ|Ä\(r¥¢aJ±ð¹ê;º&˜ŽAÉPŒ`\+–-Ú'¥$z¹qeÈvKž›qªˆ²cŠJ˜¨qXøì± 1ŠºYŸ†Á¢’ù[G¼Ï–N$=£Üly4ìW ¦Ñ2P&Ñ&‹GU¨ŒE¢›_Fh}:èÇ9ב¬•æ5×€#¼†»¦}…T¤.o¨rˆÝ¶µ‹+±|å?NªFŽ÷ô3¬xd‡? ®æ¨òþ ±ñ¡¯4y·… §}íé§sŠýç|O‘œòÏkE§6i2²v‹Pæž·sôeãÌ}/AC47•a€×¿Ø‚†Ê™ñ‹ôDœ¬ÕÒ>ÉC.FS·ôo‘&ŸkxŸ|˜-­Y³òƒ…¸»8´i½_ôkÀÒSéðx<ÝÄ<GRºÄœ¹“šÙí( §³±[f¼”ˆ7Tße.`¿`ƒâÖD‡ròä[üË~c¥˜Sé‹<«I{E‚žF4èM„¯AÈ]ÀîMÊŒÛ<$ÊëóÏÑrþœBí* û™7Ý¥S¯H^¹Î¨”âïnD/Le$Úy®h~tŸàK;¥žÏ|7/ɪÒ:}zŒØy¢frgUøÔÛ|^û&Ù´@¯^~;ï˜:7ü‡NÆœZÄž¶d¸Ë îÏÇ}¬i¼„«oÎOÞœ¸>Û©·b¢ó¾öÙ&‘6ø!l´Òã72IêƒTzçY 4tÇÆûµÌfÔù©t–_𢠔e–æ 2‘h•¸eRú\&/(ì™Þ¸lpò9dùøl¿’®08•±zÛ˜ç›lÂäâö£áëá‘TÙÑM³P‚¤ƒØ‰ÊÅÿ4 Ǻú!ÏÍrîYÕ›æÛ­†á±Ä`½‰5ÏìýJë5zDs–s¢3h}ÄóKãŽy»Ë3²Ù9äË‹xÇÉž"Y8¶ìÞç5Ÿo›àº+@tƒÕŒ¬"„Xµq<ÅWÐï¨Ôó>g7«Q!n©3ñ²™Øì>"šgÙ+Qü:²•©”Y;=o㫊pŸ· ²:s‘&,IÔ¥y#†lI”xM‘»¤ƒÉtòžÅ:¶ÑjiôãGÜŒ—À_€×0³ÆWHßð'¹Á9Í.&ZÛ,ŸV·´s‚Q¹s|>šÀtN»ƒýVĪ̖lÒîßjv,,r¥E¾§kés¸¿› 8ýô?v‚x endstream endobj 1363 0 obj << /Type /FontDescriptor /FontName /NCLYYD+CMSLTT10 /Flags 4 /FontBBox [-20 -233 617 696] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle -9 /StemV 69 /XHeight 431 /CharSet (/C/D/F/G/I/M/N/P/S/a/b/c/d/e/f/g/h/hyphen/i/k/l/m/n/o/one/p/period/q/r/s/slash/t/two/u/v/w/x/y) /FontFile 1362 0 R >> endobj 1364 0 obj << /Length1 775 /Length2 709 /Length3 0 /Length 1241 /Filter /FlateDecode >> stream xÚ­R}TSe× &CË$›|^òÙv±™ŽÉˆd0¢Æ!½Üûn\Øî…ËlM@Q‘3Tü ±ÒÐ4Q’d¡”;`!f»9žðßÎûÏû<¿ßû<¿÷÷cOÄȳ˜u‰& JÈ –Èž©[ô´f$Fᩞ"€Ò4jä²ÄF"`BAâРU,à“Ã>¬5©@MÑ\ËXÙuİÖBÆ’ŸLyFИb–ANÏÿÐߟ2˜<<}‡¯ÛA|€X,JýÓÓ4$™‰%b}šŠÕë-„ˆqÛ[)ÌoG\áÅ?O (i¼8½nö¼Ïÿ½’+£­¶ó–‡ï]¾ÈAÜþ§cæë> endobj 1366 0 obj << /Length1 1485 /Length2 10156 /Length3 0 /Length 11014 /Filter /FlateDecode >> stream xÚ­¶eXœÝ²µ‹»;BÁÝÝÝÝ]Ò·àîîÜ ÁÝÝÝ=‚Þµö^É^ßßsuÿè»jTÍ1kÎ繚’LEQÔÂÎ (evfdebåˆ+jȲ²X™XXÄ()ŦΠ;°„©3ÀÊËËš½ýxûòqrñ±r!QÄíì=AV4â´ÿˆ¸¢¶@G¹) hêühûÖÃÜÔ ng:{0DmljÿT8Ô€N@GW ++Àdî 0ZÀHÌÿx’[Ú¸ÿ¶p±ÿß”+ÐÑéÍ€æ_6io&-ìÀ6  %³’ÝÛjÀ7/ÿØúïæR.66J¦¶ÿ´ÿפþŸ¼©-ÈÆãv¶ö.Î@G€¢ÐüßRmà¿Í)-@.¶ÿ•u6µ™‹‚­l€FV&ŽÇANR w … ÈÙü#ÀÒÔÆ ø¯8lñßNÞæ÷/ÌÒbòRêêôÿs´ÿJª˜‚ÀÎö@Ëõ¿˜õ¿ ÉäÐgy›2ë›ðíó¿¿ ÿk1I°¹l`ãä˜::šz ½]¢7âx²@`  ;èþ昙 lçüVx›Œ7ÀÒÎéŸsåâ0‹ýú7q˜Åÿ€Yâñ˜%ÿCÜìfÙ?ô¦TúCoJåÿ€Yí½Õ©ÿ!³Æz«Óý½]fÓ?ô¶‚ÙzSšÿ‡8ßræv6o×ò#ÿDlmÿÔ³²°˜-þBV3ð²½Ùz;HS§ÿ‰±ÿr7·1µý«êm/–ð­‡å_øOô—ø­Õ_øæéOwÎ7ò°ÿÿ¥x‹ý]ÿ6€OáÛ.mþ·üåìíz1ÿÕêkvá›5û?k¿¹ýÛãh÷×ó¸ôü:uÝБ û~ïvl]rKš=Bƒà¤¡Ã‡âëe-U,"ýà S ÜÕ)¡JP»Õ n³P«Ï™Sd·E&LˆÉšª ª <ä0 ¨`æ[ð`Ãò¶AI!zÉ5^Qjá ïè3v¥ùeÄ =Å£¯ç †HzÙWÖh< Pì.j›ÕÜ2³ú±’¨M¨Ôty#ùZÜä¼G:kgò¬n”}!QEˆÂåNïß oœ›7"Vb¤GÙ }¤­3L6P\ fE²ÿĆTgíÌ`G›Ì¦ñ¨±\½6ëêMØ>“ÑèZsŒàïð l²À/ }¯Ñ2ÔåBäMÏ&™ÎcúíGÍR”fçø½ÒÚðy¸£Í™úŽU´»9ãåÇêËïßÚ¼üË…¼Å…½)¿LØÊü·>xzòóïÚ^‡§½Ù'³R‹Ó¥ø(ϯ™ÌïbÃfèiª‰ Eá±°ÊæÞÛöBà‘KÛ6‡K%)w¢vÓ²9ʺh\©ÿÚÖÞ%Î` ¦qÅè\"€"š°ð0:èȰPûêÕñÂu×zÅÙ÷åìªìc)ÈD|5uÁ4ù9þŽà¥LBŸ“hhb`¥£¦ñn„³ædv{üÄâ„\ÜÕžs†_Û‹Œ>MrDðáþñçU\ñÇ4q{=ôn›!«ÁÆ—B" œm—óÄî"êsjÅ{F¼Ž'I÷¦$^D ÚÅýžÚl…'‚q‘3ÝçÇæÜ ò­Çü?ŒÔ/Ø„Ep-RVqÑ>4G8¾ê7=ͽ‹3ÐeÕð›J¨!jÖ_È}a:C+Á%qŸ“0,¦èŠêE„üôÎ ¼°7ùR¯•wß/¯VÀ±ÍZMÖ>Ö/²\ö¤qضrÊnódxͨ>9ï%ÙT®uè+¶x7E½kÖŽF[öãw1í鯍éùr“µË']Ý%¦è"Åø3Ĉ{ãd:åÓÏå%ß%ÂP¦gKÞÐW.·„WÚšÿ q*¢²œ”à ÷é«myoM+íàý<Œ^ï$§ÞDvÈv^"©°(ȵ­–'@M»€BiÝ‹àQÕ„ËÅ9Bx³9B…‡šÌ]§0–NÐ¥mø@hÛÖ0(¶&í6ÛÇ¢.Îþ®XËÆž&߯*sÍÞ¬ÓÛ¿,2zœÓ6‚5p{:©ßÛ–•]ÏúÊR„ì]áS†ÒñJÔ9-ƒô²Wà -YF<•Õ…Ôë´#%-#ɈÚÔy&æHMDØÕpøÌ Ûñ“‹¨cúa)Z{íxïGðÁ«IøÊ6”«½‘4í&¡”„¸mÌ$yóÏ{tW?v.›Ô’Yx£‹(K¹[?üÛ×$tín0KŠîP†¦†G3ÙÏÆB-×µtÊóŽgéA©è–H3} qnBóT  ‹ ¥hJ&RõÅE)îôeuxÉ%8#ý8Þ。ä}©%0` q;sªþòôPñÃÙý4æL§qrßÂ<~„Âõ"j¯<”ØM¸vÀºz€Åͤ;šgdûG¢;.?JF¨05ͲÐÛ ­òB±ââe=†òàÁüæ-xúžòPƒ›]!Ï íüœ"1Qáy5czIÁज़‘Ï v½¤—çª.C9‚ˆi=PC…WµÄ¶aèðåéß–¬Üô¼ø÷aXÐY;M*­ç¾2 ÷úúÇÃ/rŸ=í˜NçÂÛ¶6ÆYjyµ¯M8ËÈm ®yGSņÖ3ÌfClUÇH¬ P–‰¶ö:`³QQ¡&ßs’¿½Q1¡½Â[?4Þ{©Jn~œ€» ÙÒ&õ—éVÂ{˜]ö¡wdáHé¾¢¥oóPk$+¤wò=¨ã*öï- ÔQ­ó¶4Ghp¹C’·ÍmlJúx›`¨ÇSŽô² ÓíU,Ÿê@AåÁƒZÈŠBlY §z•ï¾0†@Wm´dŠ ‰@øæÍ®²7ÖœÈ*uý Hè×ëÃrv®‡Ô{‚GBÀc6ßH…S’cÊÈòP¤‘9>$QŽe5Lžéo€îÜ[øvÒ†_ Ÿ;HÚÑüù.ÖÍÄ ”‡ iÏqä‘…MξH*T-S/ÚAsÒ ‰Ó,tiW=<‰Ž¸“@¦ÿ[4ÏGïÖÏ‘qœHî&õá¶/‘ú 'gÂWxãrÙë}ú—/¥b¦ð»¿!é›~£g|“Xåæq פIý Ķô©ÜzYž‚ÂÇíØòÌéõŠK‚zêK_{l‚Œ5gÄ\ü¬…=~{XÎÎH0×ÕwêYÓq*°I8V„€^óqO`žW®ãÇZì¶8›ÈóóŸ¿V˜_õ&Ýe8ú9cz¥? Òž„@g)1;ýi¦¹¤‹©cÐG41zqÞg¦!® ƒ´ýÝÕ¡ÝΖã…5…é½á|2vÄLãV5\*rI¹Ó#6º–&c½Hua½Ûá,ô™´™¯uq¶’œlžkë=žLú%ò[Ùa™ÐA”XL±]5k#A^šáÁ¢ªß„±©ê‚aÚÎ \ØÎý'²DtÍÅH¹1.©aøŽŒ1·£FïÅgêDþ¶!“F´ø#î8‡ò¥@¡¸‚C—¶<ÔëåÈK6ƒ*ÒJO˜Ä¨’çT“rC¥‘$ÇÛÕ÷(D’Ð{íª|.S!Ot\•]9-”Ç-VZ9ï§NZ&à‹‘@%}¢õðCnìmV¼=»À.¥HÃ$ÃóaM‹‹¼§pz5lªXVÝÊtµkŒj¬V/çÖJ+½C c¶T׸³éh%°È?K;?>æâO1õš¾´ÐâÙÅ1V/ÛîœñxëÑΤKžÃx²u/¡,†B=¶»n@Ä-ñž6ꉌ L&ZBKW~–øô.¯½`7Ú31è>ÈÃ,“Lq×3ó³±ò¾}9MbÜÜU’ù”«D†e!²ˆŽãeïû•Ñš5üN6R÷+Ð9í2Б§úîŽyÖøC£Ÿ­®PùEOß |Ï­¾u{¦JixÏ™k3t¸2¢6œ®Š‡ÁxU9‚ðk¥UÖþH\¡¶VEßÀ‘(ˆuâ¾®†»ú[Š<à˜Ñ‚!cý2.7õ[ þ>á¸à¡s’ÛÌ@¢ìMHÅ¥eh‰–Ò†Îmü¸Ú2R¨Â‹ØvâK4StLW7¥- ŒòYw¾0æNÆ÷üŽ{.ˆÐ G1Â$YMмç|éîW'Ÿ<ÓœèåŠÕeÁ»BG³'’BØ]éKgK [Ÿ!.Gj:FZyŒÜaÄŒ)u¤~çaŒïòœO¼ÀÆfѦ•Y.åuäû!có—à©PÑÈ:•õtïñÉv\cˆ‚œãÝNikó›c @|gÉ"ràŽ1„éo÷¶ëÏ3mŽâ•;ïS­9æDÔØX Ç¿Àå zWY†¼ãkm£“’û•,´³ÛœËq'vóŒštÜŸÚ#,é¾ ûAçøõNòøiµ0È=Ÿ¾û¥4T@Í-¾‹—áZí§Q§ç9Cüxú–dÁEŒ˜ËK¶¸O•-U»®¸!£%ÒFÜ&‚ŒCV3fö{‘ÇªÏ )¥D˜0ôš´Á¶w¬dìò¶iñ¬È|cý”ÍÜ6ÂßÉÄ+&éWÒ_JÖWK¥sÎP¹ôU{꥚RpÇlMïôµÝw3è [&õ-ë«Pû¤/p.tùÆŠÙ+ýjŒhýDÎ îùù\Ãí´=¨êD_;¢ËüWOxMCm«ˆŒÚ,ýŒ ?y½\n¥·;ÁW‰ŒÅ”,jE,{?7ų'ÔoâNªŠoOAtkÿ–*¯±¬"Šë”ÉCM Ós63+œÃ”ý&i#ÜØÏnĬ¦eé™H`g!¼°/óÕÉu~NÀšt®`•¿ÍänñZ±|¯h‘¹Þþ‘„Ú.u9;ÄHœt& ¿«èÌc„bâ'i‹5oóúUØiUHédêȺ˜€¢Íîþëäw·þdñ[†-Öß0ƒL½{ÒŽ¨<]4:X°Qùøú¿‡í…g-ç‘–°µ]*dQKÚNM¦Ë®HóGæA€`ƒÅ¢`™ÔZ3©…rÃÌUõ1¶%Œ¤oÓe{tF^mHKÚÚº¥Ì³b¦ý­ F(›C^Ãê]×ZsÕLsíXðÿ<W•X’8üîÇ¥5¼Q%]r’©‚Ë#su~mºÝ…Rñ«!åCäHíù` ¶*^û³ÄÁ?Ê*ö>^™¬kÖP.$ë’-tí¥Ht+=X}FïA_²JMzŒ¬üi\rñ1ÎEoÆoâyËko=d+±ñÛ¶C¯äÚ a„p“ã]ür$–¾S4&7¹~f6:7MlµÇé´Ç„̉¾ª!bæË]³)^¦l쎤⥠L@GS*h ecúÜPêoþk^îŠ2ó§+¶G}Æo-X9IŸU•½æï1©¿ °3|!]´_§ ¢ôVS« ¾é°·ûð$ÕŽÜànî¾OðQÙXŽ}÷!•„“ºµÃX6º‚EŸ+ßû«D ÷õ)æ}p7,:ÇûŠó“‹SåV)ç#êXû‰¨<æŒÛ9Ð-Œte¤9w%-v'Þñí=¿\ø’w *êvÕëS€ÚB†~²Ô'Yv[ ïÆ´êž-g>æ }(½NÜbú]&èRÓ¬Zû(—›|±XíZç’¼u¾ú`Ħ[XØlûæ69UÅü Ë rãMw 6ŒHL/\üPmÆBZkä‚þew£¸Ê½{™G£U&%+tGý·Ñë¢~KÉs¥M´SYá‹t_òÊž¥_ʸÕ>B¹?M©ôþºÎXë9=]Ÿ¨Vã̈š¿õ$›ÝÈ(Xj{CY~½›ü@Þ_œFZ$|=ƒ®^‚wšT–VRˆqDž¸p³*ß‚Ñ|‹âº ådkvÆÌ£õ‹Ç÷†ã¥6@…<ó€ÓwQ ›cæ¦n?·p]Òj¬0D)Á½4|J’Xp½LD}A\Ã\ׂ-±Q\’Ôq<Û÷Žl–R·‘ Pµr;èKxe£LöÌÓ`µ‘Bˆ±b 0ä=…þ2˜ À¬Åxv¼ ì¥Ï62´\ªC'vºêÛ–˜#æ}`åÈJœuÞØë$Sû¬ìR>v,þuVÛÞdÙ³ þ}ê9> ѪêÑ…-UŽïÁ®fG_©W¼SïJòÃ‹Ž¿_´{K ÐVù³ƒT}›#1UoXø¤mò×B[DÙÔg{71±ŒÓ$ì ¦¦°²hV£hî#²ï¦ñg¢HÕ}£¿-ªy†€‰"9”ºþ™¤\ ¿r˜xdäŸ{¶vß«?»ç[ªNE ¹<È»mæ÷[M\Gh†è:£çºe-K<ÔbòÉð©•,úÔ“Òy÷ãX1…Yg»ôýÚ­©3˜÷ò{AÑO%=3Q9bîí]FJý|ôféuÑOÄ AefK;°M½ ‰KBºb–Hš”ß;õIËç˽4ðkh[Yn5L‹>†Gõ#ãJ7nShšÁqVÿº¯MJ@yÚCzVï‡G.»«òßþ ƒ;Â8—5SAR‹e!ºzÀGÈA²ó7d)9.*=oJ¿ÛÚ: ùjuR8œî1ofyRGâáÌ6{š§/휭+mÿ$X@¯ê{ä{¡`Uv<–#÷ X«-äµJÐQSÊ[Âp˜ »¤ÈäÀ‹~mJ7%àä]•$5Å–} ˆzXµ¢%©®^QS3“þä3ñ‘ç$FŸJEm fƒLú¬dÕZެóëòˆpÞïÖµ ‘Gn§ñ¿x~߯¶~Ÿ‚•äÕ¦¾L'pì#8£NÙÈ£ù‘gÒj$™€xÖCîV;ìU,¥Jt/å ãªUÙ¿®Í*Z|ƒüù}UqCЯ´½øâßVt‚Ë=)ôÆ„ë«ç'âH &Š%yµN½ˆ ÆÑG”GЍ’΄ï( }z‹ã´0n&otht-E!„8–ñ={\Ž—ƒëTí¾ex¬¬ï‡=dÏúgùÁŸ”¼¬ >® ŒYä*«Ó͆âV‹„>;Iˆ£M}{.œåÅcƒ©WÕêËåx2|Ñ'—ùNå(Ží©î}Ø$ hx1Tó‹þreKLD¬l,FÊYù‰Wº‰[YŸ {Š¥CĘ—TtûWØÞè@Nã+¿!ª4Nùx~+(ÕoB/ub‡‹gamýä›(_}yšÕP1…åÖ²§Ow}Ó,)@.eM"H™Ø9Ó–<Ï¥{Ÿä«~³0r((5¬if¶šgZhlHÙ<$Ø6X¥‡²Oìº?¯½+m{QdAkœÇ7–ü<¿§…q?hkþ[Ò©Z 9©\op?e»5¡tEaaô]Cnu„E7,’Ö»±+â_š›¥ßzƒ­ Ø*¨mggªw†Ô˜‘ú« ¡ÓäØ07??[-ª¡>Ñ2€Î, ©‚óøê}%ed2ªLìë9=F þh8 ¯À$þ[EìƒrSÎ9Ó±Çâi-¼–‚í.ãBì•úˆÞVHêÆdºç³µ¬¼+O¶¯ú¦ìã›6U{RJKB®Ž é½GüÛ “^S¨;‹“ȺÍV —f¿W’´[¯öJ‰ ϨÌï2‡6bbcea=÷Ú+?Rq]) á9+Íi)•c®nlzTKE¢õ1‡ø½ƒ°»"ú¿ã,ï=§6zŒ·A„ºáÕ$}˜à†Ðõêgk–9î›6á(»Î<3´œ« e>¥“­èi¿âQdÒïß(Á‡zÊÆEÀðQÐS™S¶Œ8E•¯–€G=J,OÈëSlî1_×åµU‚]JˆÃJáÚù°—ûÈuq§“yÒRæ"Iέ³˜#•"{ê‹B†È-‹ãôJîè½£•6ŸU*Å )ã)·‚ Ak„(°”òD¹Èüxüj´hnøk&øóòYÂ5Þ©EÚ€Ï^¢Õk˜œ{Ém].pDÅ·åŒãé.c|Ã:Uvµñ<~R)*-i˜HS 'üä,KSqÖnã°å}áNôÓù3Ý^ô.rôÎÙ6}ç=¥»ªÑ8Í窯¢ RVÙ3~ZÓ•64^Œ*’>ƒåNQ™$>+`˰#þ °Dkífh‰‚Œ‰»móèh/ ¦øî+22Žn šÝšW/¡¿Â7ÐŽ§G¤%dÎñsj`ð5¡rÀÌmé“¿§`K•× Q‹]77´…(îG÷Ù¶D…# ‡XT{°2 ˆóàÂÝô‰ýTÜQ!›§©ô§;{UÔ"½"Õ*[ÚÞ+ëºA½þšÚ艌!‰›Ô)!«csûìÚ†å¶Æ5Á¯ˆwÏòךS >Ê+TíwÂvÞ¢C㎎̵™u¯5òÎtQ´5öÈ;ûõ¿îÝ#ů·8<ó))ÌO1IS"7¹Í]tîQE´qv¾€º~N<Ôæ…nf&3å ßÿ†>Ta98‚ºÙ÷úybÔ“‚ùîƒù9öšêÒLðϳRìB7÷ÁøA±„Ëõ 9¿´˜_ìg =·¶hÚdFÕ«K¹íc]ZùçzÑk÷"70@X &³ñ'LÀ‘ÙiWŽËæëêCÁ^!¬LØ þxŽõRÅ"þÓÀÐô>G jŸ&w‚”yŸNXÜso³3=zžþ³“P`©’áe;vmñÅ—¢æ±ûïÖò2æxdŒŠyú¨¾FMXV4¨_®—Ä‚Á­—ÑëÖ8$H-(ÝkL¡ß¦5bä­%Õ¤Õ÷:Ð>ÑUŽž q– Ê«!¶ÕƒîÇÚ }>Ÿ5î\ÞiÓL”úw‡~…Ñ ¤éú˜wCG 1$æØ½,?ç½ösîv¾2g¸Ô a¦ê8v‹>aš~NÄl»¡}*~5ˆwD ,ȱØÖ/}àœùCçYÆ mAôÆ -¯\~qœ‹f¤±e°xlïlæšK ×vãt *A=ÏUž¢æÇ×-5£~ê!òUû'ãVíHª¥Ô:ÌÕMj¿›¥àAŸ³ñ—㈌MÝ’îžÒÇV¢‡rJQ!»%]A f¹¬². v·wŒ=tP‚_ÚÜ¿€Wñôð[t¥hžÚŽMèƒÃ-óJ-5z“²éVs_‰Ì?‰tÝ¡_?¾Óÿ¾Ï(äÿ²ë=sÐ OßR¥\œJï“Õ;of×ë•h5ÛŠ-z^qxÌs9{Û¥7 gS‡ÂUm{iÙÓÌ{çtg91Š~òTÝÔÓ šˆca³õýppqy"A‚ÚÅ…¨à HÇÃÉW¬=æ©é½dÁG·ª}AõãqóŽšá^ñ,Ì¢ä€fÅ¥½Ìq dßÞ˜U_Ò.|•0*ˆ‚*§‘ÉD³Zˆx2ã§ÂH¶> „įǙ!wýÜeä¿”BLðÜvæSXŠ\c›Vj"Òµ¶oS«ÀÙB„¥(︩£bØN7lnæs¢­SÎ!ß½JFª¿ú-Ì2ÜäдL( 3ëØXj½{ZK%ò‰.OQ}@ÕºÓŸ|Ê:Vò¢ƒ,}ö¡§|¢…ßYbÔz‚Q) ±rŽòBæMßjp­ óŹšÿR›E»Ò¸_0gœ­wÔÏAÕ$ë3>´S S¼Òô5ÍßF(§19«_Û@^ µic²¨´ÂWšÅÍüÒAC0k°«S¬/ˆ®niæC ÅD©vÅMZËT5{Ç~^Ø2ËW 6´¦c/({•pÅÄ™³þól®ìkCO£·—±E·)î•£.ÄÍš%„Ø—ûŸÞàUH¸8¿AÒ6÷ŸÚg‡~^n7˜I" ±¶`ônvÝÅyˆ©n'ôðü9ÜÕǬ:×öïYY-µ|Øý°9­ð0.àï]UE•e›¬—µNlIú„žÝñßoõOƒ8½šæ‘ÍZÍ[‘ÊRLOséìÚo rˆ[ÃBà„AãitêF5ß³Dp†A9·4pîÕª½î `wÍ.Q(\ýáêW¤ð•´{.n9Œ›\±¦rü_¡*XUHΟ¨B(T[Éyßê{% $SÁ–‰µÒ·æ$Ú;-²z!ݹ¬&ÐþNÏÜhìúã´W&Sè¯I_qÔ)χ¬÷°ƒZYª ;{õ’ûËMˆ8Oè‘VÁø†¦Ø²É¥ü föëê½_jmÆN¬0t¨êÎuz‘;‚ô‰ j|î¼µû,ž3|ìçfÔˆë„CJ#Œ$Æ2W:4ÿnÿk£Ö-j¾àêµ\²‹=šÀ$îsn×c¤„ka½6ÞÖŠèì8,þlq ¢°q~²CæMšxüÃk˜Ü]•PïXñ½¸#5¯3¤á°œpfÚøÅ´h8 *#^c=ȉðþÑÜù™…Gåö‘ÁZA)­#É­žoJª†L¾î5[™õ:6|'–¸Å‰»<‚õEÚhõfÍ7MºŒÁºcÈ6=a¦® ñ!¹ˆÙYßwö/7!VEݤØŸéï»îö@o'ÌÞ$1=÷†U’Ðòšf$ü”Æõ Â`$9Ph/¯¾‡£×ËKÛLPÇXQ«CH–nDR?¸.¬HÊY£¹Zc°+ºy|Èå~Q§Wû«'4l{  =®}ö}  ó9`3ìµräŒõMƒ”<±€Ó™n/bÊÀVë’8Z—¶–Åžõ$7rdpsÙB0di–.VF™¨ ¼CKL é%?áø¸¡H¤N CõAG/'F¾s*S%SмlŸ{l+óÈžB3{tAW>ƒ`oš3gNFŸÂPuDsÿy Z®Ì<ÑóD¾ 6bFNANã¾çç`$¹#¨F½/¯­Ô±´Ùürn1ã¢,F(QNØc½ÐMáÄ2Úž‡NEP¹¡É”‘¾L/Öˆkèî7N³7þÂdOrt²'¬-?Ò½´Ä|QÙ`¨Ä[c‰‰–Óòš¯êjÔœƒ×—=¢µŠ„'÷?ñp#µÉ›yEh.(ÓYyõ¯êóœ8^‘i¿ƒˆq[ïÜT™Á$ž6 r†\>ÇU;ÙXH1‘¸á¶_HŽÝ3œpàb‡mL¨iöÊéÅÑ":ë²Vª©äfö7ìZµ†×?õ&ÀËB%ò¿È´E*>äï§bwªF0C¼zÉR›ÛõÊøÎ˯Ë`_?6=ì±PßH×Þ]çìãÄëE™¯4IaðÇÏ¥ 0Ëg8÷¹žÄ°Çÿ=ŸqÇÚi„ÔŸ”è9Ø3q }—Ö:1Æ D×’-¾fMãÝ—TC¯ÛÏZ¦õ¯ªèa’%xĦx³çëÞ‹|¿®P¸p…ܵQPãæêû¤“Ö¥°´Áâìq¿÷¨ƒ$6_mæ>O}Ÿ.23ó*NÎczþô–‚U%šØÄ!**gHC0~"V@Ǻ"s%ÖqæŒðì„ëv©t l(›” íÏb|ùu÷Åèfö7‡k}B;¯æ ¨@þ:hmý¤%KÄ8ÁlàLÔ6(ÔbÖ cÞ!¿¸åãEAKÔAý˜¹œ d}ðÿ‘#l‰ßiƒn˜ò¼Ùc¢}™Y«ØèmD†ñ都¦Ào=X­Q賦Á°iËÎK¾ÇÛ‡%pj@65Wù˜ –Ð Ðì\­š‘Æs[§µCªÙÿd\mâtxÚ`ÈàJ8 „ñcü…ÃÏš±¿¯äªþ$1Óì_l]¾bxã‘EM´Â—3"rC1Ë+S³PMÚn.ÿ$ ­…¹¢Iãz|èÄ£e<–Á¶JyGšën^½-Ð!«€nð32·iø™Ø>4é+… êä·Ã#gBªº9.ÆV.*`kaí£s[¹ý,fQ¦—nòBÊ N±CxÙ|â=ªmOªÂY‡™à]¼x2Ã^zø2}ï!úÂβ„Pntx„VOªY¦ {Ë-Ïåh?Ó†ßóâ:Úš“Æ^2úOÆKŒ¿Q€’9âöé>|Z±«µÁM„m„ã!cžQÕÔHÄ'.X˜#f'yQtßýä²Ç€½.¡£w’ÛbæíÕ¿È0.B}•´ºd£C€…l…¤º¤¾ÓÛz5ºÊŒr@ÉÆi@n΄$Ív”š’дdðõéø"†á¿‡±Ñ²-eX©Açô«)+ÖßâÔèê­j¸¾“øÿÉv€Q endstream endobj 1367 0 obj << /Type /FontDescriptor /FontName /GBKFSS+CMTI10 /Flags 4 /FontBBox [-163 -250 1146 969] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 68 /XHeight 431 /CharSet (/B/C/D/E/I/N/O/R/S/T/Y/a/b/c/colon/comma/d/e/endash/exclam/f/ff/fi/g/h/hyphen/i/k/l/m/n/o/p/period/q/quotedblleft/quotedblright/quoteleft/quoteright/r/s/t/u/v/w/x/y) /FontFile 1366 0 R >> endobj 1368 0 obj << /Length1 746 /Length2 987 /Length3 0 /Length 1509 /Filter /FlateDecode >> stream xÚ­’{XLyÇI‰±.‘K²ù…lQ3s¦™¦rÉ(”L&"ŠiÎoÆÉ™9³Ó™ÌlåÚDe[”Ú¡-‰..튭Tf(—<„M‹z0ÚuY[D7¤Éž²Ïæß}Î?ç}ßïïûûœï{ìBJDÀÅ„œtAèˆ'ðæûy„Τ98x+¡ˆÄ¹ˆ„žñð@O%ˆ;`!žLwO&—æ¼ …F‰I7ÀÑÛ©OÄ<Tbb‘ðEä(£<Ä" 1I ðpõˆA0 *£!J§!@11 " “Ó}@~r ¸Û¨Jñi •Qp¤ …ˆr\P(¡1ê.H‘üPÍ«p<@$ë³ï 鋱H†áš„L¡"¡ð *å¥!ð#¢˜J6pêGŠpLÌ“Kq\6ÉþØÇ¢cjˆ 0R¼HDxìïC9:„ ¯Ÿƒêï²4höÇ¥öÏ"LNk0?‹ûkäsME¤ÄÔ` “Îd"”z>½… ¸k‘\L ˜\ X7 R*E“²bq8 ˜…jÕ0ƒ.'Hê ‚‰BIëÛ)Û 0Ôb´¯Oûò;.$Ô1.®àÂâPÆÛp9̸ÿÅ*¥ÊÉþ…JãS-Á¨!TC1­á!ž™Q’P¸yQî­cNQStùñ×õÚ3º9ôæ‡sÆÖ+KoC»6+­U$v|Lú ÿ“ TÂydS‹½#dhïY]ií”s@hÙ*n^nV“}¹j´ì§Äg S+Jg·6Nï4Fë-~^öá¶y‘d^x÷Ž©}óÆ-µFüˆN’N Ë®X¶®ü˸çZwË"—h8Z3qíÎq½ 6Uê6Þ©óHÎæù]7¯g8ÓI-iª¥!7NmX•åáûá´1æÃ˜«çŽ´>éJÚ}*Ûóç»§uoªêZãÓ–œÎ’ŽmN–;3|Ýñ+7'à3|­}²ítžÇ:{}m,¸b¥o{b³¥Þ[P”µ.^/uÝiÇ«.´!3'¿’ŒËÂ'úÙ£ç*ÓÖ ù]ºõyþÙiÙ=³¶’«´7N/4)5‘±™ºªzj'<_{hÕÌ#-Ý‘ëÊæòòÇÙ•CíÙ]íø{oXq=DšùÛ}©wNœq­fvÑkyùbtäô¼"î®^¼h{SŽyyKrëÃÞ@'FDøz7†{B—Ù ž½v25Hl]Y±úÛÃ'Ç6¿Ÿ“»¢lwb\¦¢†÷ÇLõUÙ»Tö«wù]¯Û±tp ^oÚæù!#ϺSm [çûüBá !£èT€Twï¼ùÈ ½èh¸T“&IhƒÖÜ«ª,ÐížzÖ9`£ÆöÐM;«9©ó—·ËËJ_réçl‡Ÿ·¬íðÚ~«”ãCl˜52¿ÃʹQ¸~¢§´¬&¹SP2<äÙ?Î@æ‹ endstream endobj 1369 0 obj << /Type /FontDescriptor /FontName /ZKKWJR+CMTI9 /Flags 4 /FontBBox [-35 -250 1148 750] /Ascent 694 /CapHeight 683 /Descent -194 /ItalicAngle -14 /StemV 70 /XHeight 431 /CharSet (/period) /FontFile 1368 0 R >> endobj 1370 0 obj << /Length1 2260 /Length2 14823 /Length3 0 /Length 16046 /Filter /FlateDecode >> stream xÚ­·e\JÒ=Œ»»3@pw‡àî$8 0¸»“@p Npw ÜÝ݃; î¼sw÷¹¹»ÿ¯ï>pª«ëœ:ÕÝ3PS¨j0‹™;˜¥ì]™ÙYØJššìlv66q$jj g ‰+ÈÁ^ÒÄ(`çççˆ9:8xìl\à_$j€„ƒ£—3ÈÒÊ@'AÿW/@Ìè 23±(™¸ZíÀ5ÌLlf  « @ÌÖ þ×€:Ðèì4gAbg˜ƒÌ\¦@K=ë_šäì-¼ÿ›»9þß’;ÐÙ, @÷/™ô°Hs{[/€9ЉUÙÌkùÿCÖÿ—v³µU6±û«ü¿œúÖMì@¶^ÿÉp°sts:”ÌÎöÿ›ª ü·8% 9ÈÍîWå\MlAfbö–¶@Û¿C i'Ð\äjfpuvþ+ ´7ÿ_ `çþ¥€UZ\WCF›ñ?Cý×¢ª ÈÞUÓËñïªeÿ ³ÿÁ`{œAž€l`ÙÁ‰àŸÿûËàȤìÍÌAö–n€‰³³‰øø€7À‡²7z€ž`Á¬,ö®à-°'~ g¤¿&Êà `û+ôoÄ`ÿƒx¬€Uòâ°JýxÙÀ½þAVÙ?ˆÀ*÷qXåÿ 0»ÂfWüƒÀìJ˜]ù³«üøÀìª;€UíkQÿƒÀZ4þ °Í?¬Eë³kÿA`v?Ì®û7â³ëýAà}&#Nð>;Gðu1Ÿ’¿sÀ¼&.f ÈÙÌÍîï8;øZÿ{Ádkü;ÎÅñW|A.6ðW×?5ÁL¦x‡©‰™‹­‰‹Õ?êsývþG쇩³‰Ðháú0÷Âÿ¾¾WeÿwØèú_ùüœÇÿgØ(³¿7X¢™ƒ-øÝø»1®¿"vv cg»ùÇ)N°!æ¶¶ÿÔ ¾¬¼zVà‘òüµîä~Wþ®Ö¾¶&ÿ°š ìÅŸ*à û?ÊþµìàöOZpŠåðºå_o3ðŸ)àvþ¸Í6ÑÊËÑ hÿ p ôoý>;6ÿ€`¿þ4Á6Æèâòu°»ÿèüÀ°þ¡âײÙÿéˆLmïfgú×ÓmùIàWŸÕáhpM‡ìbg7êøgÌáhâ ´ÿ¯ùs±ÿ'úßÓçK}3 ý?Ryþ9ü™1ØXG[·4ÆŽ8ýiü/ätùëcðOm®¿‚®@sÓ?ñóü'ø_ê8ùÿýouììàÿ;ØŸ?¸ÿB@÷ÌŽœî~“ÿ– îî®;˜ÿ7ØW+gà?Ø=W‡l×pû#Ìé~¯]Ìœÿ9ð9pÿ÷ãñ» .êùfõúÏûfp%o ó¿ü¿ŸYââž>Ì\fðaáåd?¬l~ÿ•fææ ³ë¿¾€?÷þ[€À’@ 'Ð iyÁÁLð“uÊ÷ÐR©ü©2XHq˦8åú®Ùvä¥xHÛ¢'†:Çòtl´}Ø}rgb—ˆ6_µqé‹ §¸Ôù×}wãýtïbËt%¯=GÊ»ôßç®O¹!Uf6FK¿êôû5p’«J'©y¿FÑýѽ¡;㯎tº­VØç:N uŒT§Ò/\aë_`Ö'Cü­ÃšW;´¹a=æ#ä$¾A<˜ÁEsˆg-5MZ ‡¥3ò­ëKZ>¬G ê‹:Y©M3ªºÓª"çZí—Ü­tNýÔh­íö‚˜{ÞF4e'<T¤ƒŸâwÑ>ƒ/—FU‡9jªP°q® ‘ýÌÆQ,uÿU4Cå È¢WB[Ò€éýFª0BÖˆñý3~òT(¸É0*´ÕÃT±.•x)Ù­|Цç+ßG•pOÙ&®ýŠUÍyÝyð†9™‚£´pê˜××½{E—{B½ËMýD†×åO7Æýí–\ÜÆOìØåÓº­FR!tÙÂÏ!f¾ìiŠCPšWVÀ»Ò¯2,¹hUˆ–ˆ¨˜e3òlËö¸…¤ÎHO‚3[Ñݹ…CgCˆÅR‡4Ï6B^G®ea‰ø=¯^•‡g*¯QÌl²¥DÛè\Bæ€2Æ)3˜ç1äsÔžy;‹_vuïø¤è(G‰—ðÇÒÚw-3´xv{®²Êû=:,T‡:žð¨@nÄŽ_÷(bd?2Jf戫"¡¾®…Þ­U9¸¨“¨ŒéþqYkÕ•\äA?ÓP*­KÒÍm_ˆ>qçäªáÙßÞG¨u&/ýöQ`GÒ©\£>uñô;D~3‰Z5Sq~úOY=„€i7æÛX­FF¥bYht†â=Çúy[åJŸ —§®bnS *68üÈt›î¸ fÜÆÔˆ‡ýÇï~xFL¸üD>¢ªƒ V Í‘>gŸé´ñ¡†)ƒëVP°C»ÿvt¢zØ›Wþ½"ýéƒDÉZsûýq–7šïr[Trýaø`ÊÔÝ›¬ ¤p®ØÃ@‡gÑyæ–?üÞÞ‰ˆ^×yÖ^_ EtÛfB Háµ–YÑhFâýäë\Úàˆö© ÖäÓ=©Ä-¬Û@/›CËïàÊ©2œ¾%‹tü®l³wpÕ¹I(JküY§H{q¸ ç„øÍ(õáz~sO‹&›ºý²<€¨˜I!°ÎÞ·¦U.•h"ów¶z(ܲ%XIn©Èpƒ¸ÕëZC›¡gHž!rlµÅ‡L†5Êz~I,NvK—¦nçî8“åZÏÛ?N—‡Ñ—¸³¾"‰YSµëà†4¼…Õ$˜ÝýR¯/ÀvX°¯ëgœ³]\e‹/hŠ0vªeRÂ'f€hŠD#‘¬YF,¿ºÁî¾…?ÚÙ>ˆ2]’mr)xn<~Ól,¡Rrå`h“Ǿ þ’RÞIñÑo>œûÌóìü.‘ÕÝÞÞ¹ç¤QWcs»ºgç…3gà×Ë‚}öbòÁ;êäªÏÍ”ÜîÔ;N3¸öŠ0¨ϳœ>‰›p¶ß_ɰ“á O|Ïõ*fºÌ Ï2wÃà„ˆÅ#Ãj¯H!$QÛð"Ï,=¡£nZù ,:,Á¯Ûp_#£$²O •G³0×ÛÜ1wâv̼!ó0?‰5ñJÛ—0*þþ*IK™¸Ú5—ZGTj€³†,4ÄŒ×&ÜÖþh&S‚Ã\óè“I§?ÅÓÞN½Xüˆóô.îð!÷# [¤V\³” YÜ2»ÈuK zÄ­š}ÿBéÚÆ¹,0$È]Ûæg‡rwF?ÿ É`Í©h7™§QÑC3ˆD&µÕNèG®ýÔ'رž®‡C¹}Ës<¤&š"BòS«œF¡kæÌS7oû†A#Ø5h¢ÉË bòÉÊ ¦þ¨LMBe,l­½£õ˜Ð~Ö¾éªu«|}o,±ô®„÷G4{GúY’ÆeÏŽEû©ýp.%Nô|l $Çü$kÓÕ{êüÖ]DÖŸæ#¹PèÅ3lÊŽ>O™žÖѤUÜ»$€ˆ!éѼ¼ç¹0SfŒ/„Ðd¸(*Üs´½à4úQ5w­Ðpžð²ÜÕH7†¦Óô툜ŠÍ›ÓãOŽ—»Å½­1+f)‹õ8¹|Õ{癚"ŸeÜŸ²¶ áekh™ÛÝDà(kìWí¡.T1²¢mÈtI'BÉ&¯ôf(X,Ý·Dˆ :½~€Ÿ¬àÒÆ»2çëCÈIŸ!Qý>ÔÇÆ*Æí;^~\ýÛÍ—ýb9£óÏÆ(9ðÁ|E›G6rð*IyËŪn³ôÜb2HÑ®|gö{“rËlRUo­?6ᎮÂãô¥2²ËöÞóÏdw¡µÜsH,…šÓAÄ!w léY!²uän:ˆXRé Ûè#œ#™:¥jž.  øÌ‰â âȼI±bŒ^h”¼â6šÚ”Lõó}P âR ÚZ1Ðø^Ÿ“g徜èG‹—Y#JÓï’Nû®†‰pëœ.}ŠC—ôwä*Xœ|¦À×û:cÔÌXtc”ÀÅìL…:é0`¿,@[kû$œøü6°ºvOEhžÝ3æØ9“½EúHúé—ó—IJÁE(â »J/˜>§#òdàU(¾/«ÚsÃ÷ž¢×»ç âdÁl¿7,B ÀÁ›u‡†VþþT¸N¶Îî¼;ïZ:¼3tÁµ&Vxô²V–@×D$Ýx4{—† lñF½Üy4þ­áð3‡Dââ‰þmØÅ6z*ÒILLáÌŠ}>‰_ ÁÊ[#¡‚/÷¸ÜÃO¢ðÃLåú5­fé»uÈ’~x³×É+ Ú²8<’Qàs™ã4yº>ùtaç;œ•ó¹€ûƒ×)4^m$¡{•¾ÛÔ~!FÀ®’–|]|úÇ'$\>¾ÛÓ(±‘"Õ\Î%þ·+ä3ÓïECf j‹Çp¸@$6)Ëéü½}x‡·Ì˜ºKøà“ øQ~áB®Íù_¿ ëߪ¡Y—Ó‡¢Q¹LÐ~\­ç9ýl2ÙQ˜«+=ió·®Fñàfóâû ÈŸZm›Ž¬sÂýìž×mŽ—ž«üeµº§oîöÀ$I†.CÁG‚Ïí–ñõ¦oÛЮENϘD n‘Žm茦çžáI?“x4øˆu+¼"¨§O© è×€2÷ù\xqï­cyõ»R×°ËUʌ̦j=¡©Ïsò4cˆPyfÚ¿Ö὘¿€ÚísÛR0T¾øÃ•L1FE•´Tü21:Y4GÉU‡Cý ]ïÂ6âù;’çÕ> Õa‰fÖñ6ýJÛ$ÿ9Äò( %H šPHÉåcÝa+gµ|Â6B¢Ow6ßp>qÅ®bÒF{Mô;—N9æ1°r¢Ë{Ê$+€—Ë_e×z€Šv2©ðm]VFÕÎø½ü”ìX>¤Ä—û[¢Y4bG|ùk¡ÅƬHc²˜”sÁä:µDø"ªLFÈpüŒýÜ:ŠêÝ N¦µÑ+¡àán†û4Û°ÿAJuE.ýz_‡›T37i`H.þ+Öj—€FàÜNV>¡K‡UÉwûða«åj®õe\ˆ¯?ǯ‰²T¸3O–Û·|—¢³ªƒ®$ëÛ£ *#~~Fü¹rR¨gÃÁ៭ÓKÕ‹Òóâ1½§Ü™<µÛýÅó'…Úú€EuÆŒ„ž]’¿ƒ[è -ã=wíĂҰ”K+.Ôæ"‚ÌçyÕ½©¡‘´&bA‚I9ióQ0*Œ{â=Óá"›ý&Ãr¿©3ùûC^†šiä”YÚcHæ™áÒ¥H„û“Míñ«Ûî’åæ8šHÒŽçfãAQ.«1âØJ¨Â4î³%²ÅláË^taìµÜÂlt"d„$=^äÑLZ[W=x=w,á8©ïj"áÜ> ÖG_ïèmõ&ëÁ­ Aû\>õïãõiû ôÞ(Gý(f9Aåiƽעõ‹pPÂ8ïÌ÷'ršÊ…å @Gñ LöÉ—ÀoÜ›ü>ÐJ ãh'E°^ä×›þŸºÍh¡«Dš(]LÐîâFÖvG ¢€ßà ’ÏÂé-FW6{ް×8î-SfLfÁ*bûI˜ÿƒkúÑê –Öéáóc/«cBÜÈÙó,¨Æ™¹1Šœ½ÊïâóËdÄËt€úÝm•sHUŒˆGþF*¾+«lR°¥š@D}Ñ€!âÚN¢ÒÚ†9va¤ÙJË| 'ÏL؇àݲö;Ô º°õ;Ó pSû~‰|ù€jéJçµ)ÿ5@µöà‚›Ãê µ?j„ zïhPå ʱV]¯÷É®þ%µ`m~Ú7k£Ð«TxÎo:é"Š:¿€Ñ¼p¦œ¸ª÷R.¾dá¯ðOÒÚ¶Nê‚–Ô¼,Ü™VüJBbˆ×Þ3¬d×°áq›/çg,çy®kg!b§ý˹Ó"ý×’Ïk¾¾H ôMÞSõ¶'\Õ=‡»ÌuÖ_Qì|¿>±uÕ‘8ä…Œxä ÈKË]~Îæ¼n+’0;SA˜‘M]®#–t©¶?{3®Þ+-ÊÖ6uÝØH‰WOˆ8!Þa{p½g*›šø!Nî2‹îo<*_çv3¡EqÛ ¸ŠÝ´sÿ*I |A2ù`ÿÓ±÷ãêa7ûWÜÅ76˜#Aµ<— Øå>ñ›!!jUð”#ícEƒÏ196eøWöðO†ˆl9¾A ê°±Ûc_+ïJ8 šUÉFÏ]Å@d–ê Œ+W\µx,í¢  YvT1xòѵ§ãà š'qt€¿Ù~ $7 ‰é†µ“æì–á¯Àö•vŠ9*³êà¡èPGøÚò>² ]€b[uÛǤ›€­ô0Ô•ÿ =iÁÐ'úÓBô@¥¹ò†ßÿdc­ãd'M7x] Æö¾Á—ÊÜcÍîÛ›È`^5lËv?Z7Ï­·.Áá¼ â’¯´ØH· AL }ºû]p8ÙŽõ•ª¾ŸýñH€YÒ•ûe€Yd÷U ÛÕéWlÙšà%àg6D9J¡Þ§°À¤÷ŸQÑ °v¿=¯P nýúkÅlå¹Cöûfº¬u aßÖKZ—Ô‚ Cþ(tÕB‰È×:íëìÊed'ã)®º:QÚåÌû°Á¢e¡ºF¬XØwküÞÊBŠÅÝ厒g;Ç"gÛ£a5å“ ;—?‡ë±’å Õ<ËìÏi¦^r DÅçGþr´äÐãpi”Jx®ØÚï¨ÿœ±\´è+mOÉO¶‡í ÏÍõ鯯¯ÛŒ!Ê…yÍ¿ÍMee/™©„‘0¦!± Q¾63Ôƒ4ú%{JH,³˜ápr†ä‹Ì·H¯µi•ë1¿Åªðk{­y*ÉåjäXVA”¢íÊŽÿós¯.4ÊÐDMÄãê{Š£²+¢¿´*¥¼3Ø>1ÇȳË馪R™±TâdFmº“édM&¨ù"ÛÊnØIå½-Œ½ˆ„v›œH~ᱦŸ§ä ‡GÃ~òwáà…÷½ÀqÚ¿í)% æ÷”˜‚@“ì]ZÈ™5c-&§bô…]" ¦·>ju )zný~Ò®}WKgt%;ÎʯÇÞm±å·~W¨1M´HKZN.^÷|&q9öˆ1ª‡ÔÕâ!Áðå'cBÍ7<©ï[<s¬Wò|¸Å{¬hÖ¦[ZUÏ“ËW\vßÇsSV¥Ëå¢ÔFT2V»‰Ö%ÛÓ7êr]U: q†¹#C¬Ç Rñwyº ¢5_ЦÌ7ÞÙ×\a©¹Rú ÿÚp£w• _h?Í@‘ bø´<õ^â!xTÛ¬­UžT5_ÒXèQ3KI…³·ÓÐA'?¾äx]—É£>hô<Äå$RÝnŸ»_ø«mÈw}ŠîVtgINÌbÄ=6Ò×ÓßýÓ5äº.6ýAµ1Iß¼ŠB{9Ê«sµê¶Ã53 tŽ+2Ë"ç@Ñ…\®û[6O˜cÙ {Á`c‘8ewŃrÜW–¾k QEØ,Ž¥¬ á>¶‰v® •âÈÒñN¸Õ oLäçцmËC,G‡¾eõ sínûjWPK^)U&3°Ÿý‘j‘{扣 Y%ž95Šø“u’&Bã‚–o¾±¶ÿ“’5;D3Á}mò+…±Ç%º­Ø½œÉOl£?:ÒõG·KYæÙ«§ŸQâÎtÇŽ[ˆ°&ª« œ÷v~Câ› ›E¡ªG7>¸Ã},ÿVs>Ë嘼yH˜­ë\ìb,Tµa¦e‘¦SR=š2ä! ZMùøA)fùý·)½CXü‘bÿ`¯ŒoNsÅÛ»sèõ5×°Ø}ùι)ÔåÔ(¾ùÛ^ö Áã’jfN¢È¯xòù'_Ä…~e±SRS zó¸—Zï_ÌD ¨Uò”@ž]'¼6Kõ« 8:°þú,å¯;µ}R»ïL.„ð U³Ógƒ$æ´’e—¨&ôñ†å‹Èa;@<—mä÷Ô(=}¸¥Övž'ŽlúÕ>1е}fÎ5±Âóó}1jAu4q‚˜00{NûPCHŒ1#~sߵٌ̾‚Âà¼Z„ÜbB{wi­¦ªQØd*øwíw­.Ž…´ÂÆ`>1ÐÉHf[±EÉÀ³G2úŽ?´U Ûyf©s XëÉM°!õä(ÕO /z%ø¾âwÒ˜o)%ߎ„['5z¯Ÿ¦á2Í7RÚ‡Ô®áÖÙPÔOMA&Žqëy‰l­úw#\ñ˜x»ìûœ O @ž÷ÁFÛÒB%=Ó*?WGñ£%1IL­,†ÉOQF IöO, ý˳P@„e~dää–üºWÑL*é jãÏ”œ´-êÙâÄÆZD¨¨B‡ïvZ {4èðW?Ç'\;ª?Ã(]éOª~ ¸×gÐ1Ðÿ}“£ã5ºlG8Þ«˜‹–ØŒS/ùËpyr/nœgÞ\36à§ÙÙð/˜dUªæƒX<„ÄÓ´{ÆØ,-PBð‘˜zb”lâ bZïm¦ás ¥ß{„NáVÏa¿¸M¤Í éňOŠ®ôN,̾ÑÈ$µ±Êâ¡ÁÒu ¹b£µ¡ `¯ Øª 9¤Ç±»ÔÅ3ã+í?ÑGavNغuYÿ¢Æ& 1ocá#œúµ¨Ëâ ‘Ü™ygXQU•ŒÇHh‚Ê¥õ^[v¾’mÁ(̧‰A® &zd N–÷%ed•–>.1\ΆÿNZ#1Ђ墧àÛ·TÙ6jüÓæ %Ñ'ŽZF"‚éŒ9*à À@¯ÿÁ¡¡}M/·ùƒµ~s¡lexN“]â‹KC¾×\÷ø‹DmVôOH–·Ïœ¯¸©lƒküüY§G¸Ó“˜ Êý¿¨Lò¬%ÎdXáX‹1.<µ­~ñM¨”—`'ÃUC„alÓ¸ ׂ„~Éè š¤w°y1ÙñËôôÔåmB¿¾ ØM]ÐŒíÊ©’g¥V4ñKþfr žGõÙxE9jöq–Lêä½ —'Ή¼`½!‡qµ{~•d£Û:ÓåäË8?Ò¿eÍØi¢×Ð6„)©üÖöaÉè«#äªìL„öÌ ×èV]ίcâi@”­4Å4œ5ô"áÁô8:e€õc©nð{9¢ÂŒ2³9ë_"ò{vê`Œr“¢rQô›JÙÔôü˜MÕn–¤¼¿Õ¥Šß†|´!«ùÈ‹R$K'òvêJ§FVu0!;¸D€Âµ\3Æè.›÷^a%áîÑ#Œv<І³ùЇöZjeñ:’—+3…øH¿ì²™Ý°/ã ë§7Ç·Ù`[·”œ.ãÇÂg›¤64½B¾(g‰îkí_ˆNUî¦ÂÕj¯}aΧیuüå˜UøÓPÄð1ߨÜ?SÌ…ú9 ¦éºô›Õ pŸdÖ‰„H‰Ó)\2"~úÈPp‘Ç–?$òâÐÂ;E*B/ï™5ݵÈôµAØ7FV…LÔ¡Ÿš*Nˆ-¶¢[Ÿ õƒ^<$x!(ôæ”2Úã?)œX=—wìëU¹$¦D.¼«üdy”CÙy¯r)ozMßú=¿Ì+UÁ²BƒznqïWHKY8Ë%UÇL!ú Ú´ OýsIì>}­>Ì0O’å¼¾‹XD±3¯æÿÄTÓB¬iã‚„LÞ+]*¯†òÁKºñl4ÊÁõz—ÝæKËK]è»°wbù´;ûßnŽ©øM&bv4È = @é‹4%pßÕ„Ïêbf;cîâ ­õZ2#2X üÕƒ~'â]س}$šÀ[%ªqžö~j£†ŠSFy#D—äzÕä\ EÍ?–ß=u¿y3|ž• OXc9]騱׊ »Jó$Ó'ºSpZÜ{ÕP¬_&=œ`n±0ÀÙ%Àdp§”ó Ž@>Â8KzU›2“ð‰ùhßùËo¯ ÄÄg‹˜z“6w^®2TÌ}¾¥tqd{–m_ÛÎ/Y\âä²pNÍtá¢pa¶)DÌÚµü´ò5k†bË„µmšï=€…¡=† ’!ì‡îöc„ŒºkQaGép!L+dÒX—ÛyÝ„\$'¢®IÉ­†¥¿II6×;K!œˆbôéí÷•ïu†NH„íÑlt Zö©2'õö¦çß¾¥ð¯~è—™¹u§?²|É‘VoªWpsÁ=‚2%‰è CûÅø=ÌÔ±Íßô‡èüÉGëiŒt{x‹.Žc …ÍäÆRÉ“{019Ó÷2»÷.fÙ8tÆÏ vÛç'>Öd2’æ ©¢‚oH-‘Wa’ÌP½L-5I›>Q”Õ„lySºŸÞ†×ùÙ?XŒÝÔ‰*ûË&{KÚ%œ0³8Šz•–zW÷4?Û9j±ù¼Uê7Ô ˜ “Εyˆ K÷_0—.Ý"A0Tf PʿЎbÛBB ÈŽK#¢¨Êïúß;Ð܆<_§øX\³œÄÝÿLg°è<[{Š\:K’ ¶$ïKç/S½…LgÚ|­fßmÑÆ/@vPÆ÷ÃÁ¥|ð7Иbeí :ë%>^3‘wØ­sŽ>/¡Ø(b!~Ì éа×|bI¦”‹Û§ËÂH½Âœ¢…¾ƒÕ %ö.6ÂNgý~vüͤÀ§Wðû¤_Qøøž7;§Ý¾îu6å°2†Fn;»ccfÆ&àÖ=°Êjd¸àøª¾…Ã:ÿŽí{î‹ÆKñ7O=¤ƒnÚ­Ü…ß%Ô|ÚdDd¹¯ïõ2nEv~WÔF‘š¶ü ¸r ÈØî<Ÿå¶Ž L©Zlxò^%å”况!Úí ;?±½S¡”è?QÒ¨¾@ÇF ,%ƒåúki¬NËÚY4û š5E;VÕÔNƒj“•v‡¾UÈC_Ù_r½7A|:Ÿ¢p¸D"ÅPËþ¹•}Q¸/ L¸G(ò¼~ë2aSrɳýª(ôjK8ÕéI"jjŸÒ«æ<Äœòg#ÏòØþî…—cç½»•ÐèoÉGCýï J4v÷!¸Å¼iŸ\º¯>-“!³6Wòˆ,!5à³ádtŽ+E 3k™»mùSOúñßÔ Æ1kD ‰5݆x‹, ƒÊZµšn×¾Iªùx ÓnÜ‘œ½Ã4pÛ„­vh 7ž_½1´wkî|I`K($Ãq/p1øÝ~ß´:oܽ3­ÞB&¤Ù¸ÑÛ‰à¬i `"£¸–¿%fåÜ,€+†úû è…M=&”¥OúCŸN]>;ÄÝNÌ¿#ç*ÿ2†åôõ•ÓŠÃæmIñ7%½ÏáKí¾¬Ôh¶Ò÷´º¹=kÆÎþ1jHhžc˜.A_¡«úì«›€°l×çäÒŒ 4™.ÖkªcJçÕ©«æÏ‘_NõfœêÌ–áG“Ž—'uµɹѪ'†ðÖ>6õ‚Þác“÷o$ñ–Ù·àÒ¹©צÊž³¥l‘Û>nΕù|~ç8Sz÷î›õƺ»îÅÇ,w^M¤SzfÅô²ã´dRšj„¾gqã]«·–S­ÇåÝò±ã˜žß‚>T@±ùÁ8•¨˜+cÃ/¤ÌLà³Jl²vaàiUp±yxö0B ’O_ïÖä9i>5ÒÔ„\hPðï­õ}Ú¨àm©kiGÝ-O%ËkN†=²9QDàHy›¥ï)“dÞïÒWîÑÝ©H²Ð±êG„­<êVŒ_Û®x.táÍ>Z±ü¬¦rF¨’D.…mëím/§ãò½ã›¥É«üþ.óVÒ]ÉÔ™ÜûfµÚÓcùŽ+\±fŠÊ§«t\˜—.èM¤²‘ÿ:­þ~+ëÑGÚÜÓÏ‘F•Âí“v^‹ònZÀÎÊ:a¤k ç±9©h…5S¤®¿cDhý‹ù‹çz8QiäëÌ®XT>ò¦-6¶ƒÊi>fq3ü»<Þcv3?ENäG“-gp¿{‚~Z£fE?Ï­å"²'v;½˜±Ê0ø m&®"ð2~Ê¢ —ÑËd!92?ÜÕ㔈€] àYxA^6ðäwö‚î‚ Ò”Dâ²ÕÏ홼jyçQ¼¼¬âüĹ\ïÆ­‹3]ȹúù]*šþ#Ð×—Ö½nÔŸYSŽÆ¾Ì'–ëÑñD§fÝ¿”cBl£Q2xÄ_jFpo`{Qœ?‚’ü>ÏÕ¢¥ =ú[)ÕáUå '6p<…À@¦É×}ßï†Ò0 …ú­W\h8Um÷iŸ›ûb§üZ]ñ³4½F<ÛbV|ÿôÄçã4µ8ßïto|·Ë·*¶kó â ÜõqQ0!%¡®¤iA ËtTãÒr J?žÊýZ)-J¼wçgýJlêÍkóRyóžÖ‰s†TÌ£ÃÕ=k†ë9¡uñÇ߸]öê7ñsyÓ‰6’ìÞ ›4„”O»‡øH&^â…¡~ãê…ñmÐÓF}\ ôÝ2w}‚ËC¥¡C¤Ë×"8:û÷ôÛ'SS‚f¾ú¡Çõ0ªIN’TËã©É2Ƽ÷uѯ_Åç±(z4 øÙ½ZPN9ÐuÏû9}I¸½4ËY$“tËcÏ9Ü^äÅ›.ÇE¿ßëå› ú;y.ãÐe或–˜þ©1{Úžý6 ¤§ôþÂýÙ‹ôë{·ÇßÖ]åpÞ¥™\-ŠÅðìh„ÁEþ(ö› !‰BVc¥é}È–Æž^Äï÷Bœd¿a„c,©ú Eêæ®ôñhÑŠäûFx,𱡹0é—)NÎÕ x¡ØËlˆ@]Åñ)y¯çº–0Æ{o¹væ²ÞNø ×Ñ+ “›ÁmÁô—í1˜rÛBª~o)ö}ý’‡4qRò›‘ñ–ãå*ò‘d”¡Ü¼ºòcx/ëJÓ­#Ǧ£Kçuê鿱jß>ç5‰â™KÂÉ×)êAl\-O:’RxnüÃEÜÚZ = жC–±ªRõh¯·³ÝÄ©Ðûˆ¶ÏÈÍû¶GÝ3x~àÓ3xê³ïÖóÄÒ¡äž¾v°}•&Þ¸ øv^²ĉowH¿õÐQ ëGÄ®H5Ý >ÁÜbíSÝó6àe ibœ$ǧ•íA«g~öPƽ=â‚×*Hƒ Õ5ìÞi~W§÷³ö¼Í3 ‘h…*|D™ŒÌL$<¶€x£å©Ã龜xÛUb¤£Äì¿Q–A†F!@–Ž:²† ¢òÑUãò…QPׯ$¿²W1«; ×pûy¯ñÐ⸉XýÉõ¼X„‰Ú{YÙÕÀŒNžÀÛñçGï˜øä·L¤jŸ*Å|lÜAªL*ãí$’Zß’++k6ƽ„A Ú9Âô-Hl-}ú'{ºÜÒ9Zæ¨îû>¯2æ6*Nþ«Ïo6\°;OÄ™¬0wßßcUT óe’%GêN¸ì2Ÿ :+4áä ÞB øyrîùˤ&A´äÚ§¡xåız„Ü¥¸o&ÏöǺŒü&õ“@†Ç]†§Óú© xáÒäXpd^ÇD7„Éðòx;VgÂÔð=3&èXÙaܤM<cûǰ—¹±ÓÆÓW!ןI¡#Žß„´<ÖS…e€‚íMÜÆ 3h¿kT ˜O}@Ú./yˆÞU°—I;gBS=)%Hä«üq¤ëéõiÐØš02ÆêkÉX欳˜Ô.—Ї>NÉ×)‘n¾ÚiéÛþjBC!sÃÁOñ[±‚×éS‹Ê5/LïpܾЦ˩V>2 ¨SߌèVá½jzŠ7 £’Å‹¼EmDŠÈNC8¤³Iø }Ñ1öõž_ü¿Ë¨Ô ‘ÅcƒÁkFóü£"Í÷/Rª•0!1”1EmH¹ßsk#aáëµ™9ß‘)±&táÈ‘âä5=?¥wY¾²ÍBµ—V´·ÌðV÷ÄSõØë Å¥jâ(hJ¥Z¬Ù.ÕF½†ÚŠË³° ñ&PûL[JÀFH…Í•c Œuä©Î,ìbë1Ø{´‚Þš1±¸©î‚ÓV‹óÔu¯cd h£ÿa~é™,Ëð!À‚AúÝ.BÉWæ½Æt1lÉä"ˆUÅÅÆ’A4¾Xp‹ß|¼ÒIÂ< :ÞèÁÈE¦ëEìsâ…¦ÿ^Ù¡‰c·OÏì0‰L0.¢ ·4pÊÄ¡NÏn¦¡Øô»­J³ Ée¨‹5enÙ¹:7ßYÌŦÜ֦Îg+'3X@hRõQφØMÉn:ñT)îc3PU@” ”£gU×§¡Ð¶tjØÓaÂìBP¼¯Ý„  ðVy}te‘éÆ÷ç6Çrs@v öŸ˜Ï b‰ŽŸ8ôº¼2 ®³#ÊË/ù9~wZ4´5ô6 ôHÄšl´Û-nMª“§Ô·ºè@ Þ} F¢#õvø(¯°Q¡ù•Xò1Þz #×t2rž°‹VÖˆÞá¿FÝÌ…ãýbOŸ—,5´I‹Ü=p•F„-‰zêÍa99y¢(ÓNrA¤¥ø P5È~’¿‘ʳȸ”‡ ª‘H§ `‹ÈóIΰ3+J™¢±< : ˧në½ïy±¶Nç…ÐNÿ:Ä̃ô;´RrÑé‰iÙÀóÛ¢éN÷¶ DZZ(N·Gƒ¾lœ”}D€„ýYœ»)J¬$"%ö“2IÎÉëÀãn¡´¼ÚgáyÙ¢ÚwNà£|ƒ(Á:U M›÷‰EêëfcTÝYyœ:­‘;4=™S’üG۽ƭ”H9=r,"ú4ÍÏNG÷?”’æW„^‘ÖëFɬ“/Nr ü÷g¾,}Ɖ°Z=F-hP“‰þê&·=û°ß†0Ÿ^Bé9Ê2í m[û3ÞP?77”;‚iB&§¯'“x¥YQ³bûR02û2°;‘Y}o Ï&|Jà°% ç~¥"ãåF±'N;~cª“aû‘ þ{/<Ëp 9ËÛå h%™hÅ•«%ÜÆž=÷ÇPš;ÁûBð)A33Ž›lèÌ‹Ú+ìõDÌßœ ¡6YˆŠQÙ¿²QSx¥(BÛZßû"ª…Sþ^Jc TžôP;›÷ãS}‚Sp@¼pfTÆ]µ«u"Ò8z0NŸ @5o‰Þ”ƒÌ)òHŠð_Õ&æb>íÜp=ˆØß¿ð~‚Qé¢ÌQsVÝÝ0à=$Y ˜á9>ªïuX"±Õ&X°ÌÜÙ12p 9CU"¬Âî{eÂý…%–׬i´ý–·Ò¦¦íþmÊwC™ôuI:¬EùôãâPïõ®¡h·F{³úP˳GjÉ; Sû>Ò'+{ª—Ú{ýý§Ýì{ ú5µ>téŸX¶£rÃS¹l wŽ’T7œç‰ýCÓ–/Qh> endobj 1372 0 obj << /Length1 787 /Length2 1570 /Length3 0 /Length 2119 /Filter /FlateDecode >> stream xÚ­R{8”éNä0Š0¥RùÔjbæ†FćZ9Ž*1Í|fæc Í8Œú9+§Æ–S­A6á*&B%Ê9!Õ8Tµ‘H f‡¶Ýë×þ»×ûÏ{?Ïý<ïýÞÏ£©áDÔÃS࣠Ì`éú  @°wu1¨Fhj˜‰E…V$d€8àCý L ±&†FM€q˜T? EÐ^"x:Ĥ’I ÀžÄò‡èâd Âd*Äâèx pYª\ ˆQô P¨dpò£2¨%Eû¾0`ü-L úž ƒ˜!bQ€–X¤6 –H4@|(Xü$Vò_ˆú±¹M(æ@¢/µ_vé_yJãüÅ€éA¡,ˆ ØÃˆÉø‘ê}gQ¨¡ô³ûX$•ŒgøÑ ý-D ±¡²!Š•EöXÌPh9 1(?jû¶¬å°Ÿh»o¯î_]N:‘¨ –+'èï®Kìe þƒÅö0©làZÅDñù~óúá1k¦PâÀ$&“ÄAˆWCŒ°@Pˆ @l±`”>f‰K±'Q€/ÌD,ÍS<i)´Œ@  CC ³ ÊQÚ?  8Ëðßß¶´„Ùz  ‡×b1†€õ4r(“ 1XË %¶î;ö¥Š}† 6DF¸´JGÂÒïZºƒ ¡ç¦|Ìã Zq«]°ÎP¥ÇbiŽŠÂøªqõcŸÕB’oD:wؼ=œžÕ÷u<Ìg<'¼VÍã]Ž=g,hÛǘ ÅëÕ½ï'±Ž‡ÚJ2=‹šÎM7Oð´¬\_Ê h¬¸}(ìêíÜX#c›Ú„¸Ê.k³‚K ­Í<-5Øà H­ÑÎÀ7B• eóy_½%)n>_UD7dZÞ^ù…û[}öÞÇ ™®GT˜+ê8_½IÉŽ~ºëG4·înóÌ]TðÁêó°%=â•xjæìÈ®cœí² JM¶³$ž[#ÇÒµzŸenª2±øi¼ãÙëœyÉdŒO>6¥¯BHô@­) ÒîJ©“;ÝWbÃ^X2›’ûe“ûsÒ˜ÿ*Òàþ6Òh4';jN’祳!ü×^È4ÁêK˜À¬˜æJ¿„­ý‚Ôu+ÀÂ!·S)Æàïœ×—åÊ7ñµ‘\·DÝãþÃÆ-‘aë3gÀ€…="®^9益(@ÎLV»Z ok|¥f¤N*¨Æ#+k.^Lrån.f ð>;E÷°™?•efÊŸ_»º»å°>Üd~#‰}9˜¥õ¢4“Z#ÒŸ{³à®uF5GâÓF]w†}ÞÏ%ñêÍNÉF É“’V¼ „ªúÝͺ<Šñ­â‚.xöTç$ᘔžTyÕlzÍ;äÔª‡öñÜ%쉩Ôh-—îâ q Ofmô¡{=Ã3 2üfKd>!ftÇø*!8¿Ýʽ^-I7-Í6@bªgUµâÔ‚íb²{ÝTmìF" |b7·»o SÚ²§‚îMl´Íªx?(müdA`æÒ‡ºwNóÖQˆ”y¨¶'ÉITµç÷ŒI›8•F¥ðiÃ… ´ÚxC§gv¾ç”Õó/Wùèé¼þšÑr=ÕV­Ÿªº]µKŒßÌ?IÚOª‹é£ã˜q÷Gkéå\»ÝñŽíý)¢ð»³É2:û&Ožá`÷÷©äâ­nÆFk¨ÏŒÆÝt#¦)ÒŽþñ]=7£yON±X’Ýk%Ú¸0À'·ø»ŸQÛ”¼ëE_ÍqÁê¨ZtWÙŸóO endstream endobj 1373 0 obj << /Type /FontDescriptor /FontName /NLSGIH+CMTT12 /Flags 4 /FontBBox [-1 -234 524 695] /Ascent 611 /CapHeight 611 /Descent -222 /ItalicAngle 0 /StemV 65 /XHeight 431 /CharSet (/a/n/quotedbl/y) /FontFile 1372 0 R >> endobj 1374 0 obj << /Length1 2289 /Length2 14098 /Length3 0 /Length 15329 /Filter /FlateDecode >> stream xÚ­·eXMÒ5Š{p‚;ÁÝÝÝÝ6îî.ÁÝÝàîî N°\Á³33ïCf¾¿çâkuuÕªUÝ}Ã'bE:!S{c€¸½ =7‘ˆœª*=#ܧO"N#K{;Q#7‘«93#;7+;73+Ü'"{O'Ks "Jª?ADB¶'K#;"9# €-0‡‰‘ ‘н‰%ÀÅ“žHÈÆ†HùÏg"e€3ÀÉ `JÇÄDdjiâBd 0·´ƒcø#HÊÎÌžˆãß´©«Ãÿ-¹œœ¢ˆ("©ˆ€Mííl<‰Lfp òöÀZ ’ÿ?DýorqWy#Û?éÿ˜ôÿ,ÙZÚxþ'ÀÞÖÁÕàD$go p²ûßP À¿µÉL-]mÿwUÊÅÈÆÒDÈÎÜ@ÄøoÊÒYÜÒ`ªhébbAäâä ø °3ý_ @Ûþ¥€ARZUB[æßãüך¢‘¥‹ª§Ã?Iÿÿ 3½c 9N–D:ŒôŒŒLÀ@àÏÿý¦÷?µÄìLìM-í€çÈÈÉÉÈx0€ˆÈ›‰ÈÒÎàAðêe ·³wn!ZâKdfï÷gšìlD B¨#v"áwÄAÄ òŽ8‰D߃Ø?ˆƒ‘ˆAü11H¼#f  ˆAê±1H¿# ™wÔ"ûŽ€ZäÞP‹ü;jQøqµ(¾# ¥wÔ¢üŽ€ZTÞP‹ê;jQ{G@-êï¨Eãµhþƒ¸€Õµß0ÒèÄŒ4²u^#à‘ù'X×ÈÙÄÒÒÄÒÉÄÕöž‰™ý? .–6¦€xVæ?4ðT[:[¿ãO—÷œÀJÆï¸ÃØÈÄÚÙÆÈÙâ¯ü¬h§¿ ÆNF&€™Ë_4Ûè_å²2ý›¶¸üW<Ë?üÿlŽÉäÄ”hbo|AþiŒõckûn#ÐÍw§X€†˜ÚÛØü­x)Þ½^Àeÿ³îè |cþÉÔ¼6FYÍtÈì= 0ÂÌÒí¯´–í]ÿ. 1/\7ÿóJþ¶óî6+ÐD O €Ý_@Îò/oõžë¿ Я÷&ØÆØœÿZºûWGLÀ€÷RlÀ\v–vï±KÛ¹ÚÿyÄÍÿ’|ÿìßEsÚÿµ‹‰ بÃû2°†ƒ‘Àî¿æÏÊôö¿§Ï”<ú&»¿BÙÿÅYڿϘh¬ƒë_1Ç÷Æÿ W€óŸâ{nÖ?¤½ ÀÔøÝ".öÿÿ¥Ž…ë?ì«cb¦økxL@Þ5°79l-ÿû¼²ý‰¸ý5Q6`gà»ýO3ÀžÿçÒ1U½—ezåbáøë¨=uq·ÿk0‡ë{SÀš®À7ÝÉÙÄÞéïÁO‡Û_(Øý¯ LêñVõü ‡êõ®˜É àôoÿïgMXØÞÃ›ŽˆŽxØ€o;§ï…™¸:‡ïò¯¿€ŸÆÿÃf–Àï(à0û¾doÂb•ÖVá'Vô­’Tؼ5^¾±o¾>x%Ô¦tBÆ‘z³Aó±* qrŸÐý×9²ËGiZü<Ð1>}ñußÍp?Ó«Wó2SÎsÏä.ø©³eáú” Tans²"Y«x8çbä¤@‘RTõz¤_Ç­©?+„CS<ÓF-<´œ…X9ݱâ3kø†;rr"ÄÆ×`?«p˜6šµßö]®¨E0ùI¯ &PQA̹+­_­øÂ3騘f ô°F4 ‰´.¼÷íìž¹–«ÚŠ'>º¶^z¨öxЫ¹¨Í$%ûCdðN;étŸœ¾%X›ëff°ý&O-½¥”à5”Ná0µØ²£Ò^º³9IÊIFac†„ÏÑž»ÆÉ}J&ûfDŠÖ–ûšéÈÄ"Ø yÊC°vAãŸ{-A‚ô“iyQö)²€¿ãØyÐ1IøQLy ᬅg¡^:ó°Ú>ŸDxípU¼EÆúÅ:äòãsTÑÒçYm‘(ô›½Í/Ôé‚Q<¦Ævœ©åjma¿û±ŽêÕbww@§~ÔEQêê­ÿCUÊ ²¶–ËB:ôÅ5½M@¦ÂçÛVï”`-ÂlO²ï{ò83S*ò“È1n3þP•¤;Òož×2r?tÒÏê|8‚ØÃ¡ ÔéaÐâá=?\¾CöÄî vP÷R·8seù£f¥Qm¨™Ž¦ˆÇó„tNÜg×4$‘9ý ª)ìînúf¸Œ3UNE[ÂÒÜ‚–†¡¥@.¥F÷Iµ§ mÆ…?4@™ƒô1{Y"´ÑPc÷ È“Û0Ä—+Æ¿ŸCQ@ð*ÊÒ´viwo0@šï“)8y|éf:FEfWL0ÇÛ³²•NôÓÖÐÎ!ûDgZnÈ¡’$çW2Ñß#¯=×á{x•ÎCZ^ DXÃÁc¹m³ËÊÑ ßÕWÙ–ÕÉDí¬‘²ÓgÉL'<–T·ÌµÝ=—až…ç’ä¦@J¼“ª$Ô|†g/8»¶åÂ1µf«2ª=È5€•­žØóµO)C^QŽä:-À£ü ‘-‰#ýX;ð©Ä¤äÙþ2b£ÌhêÔ½¤Õ)^šÎ¾ ûŠûýNgìzÍ[1Fub }ã*Jع¹ˆoÀ\:¥Hwn’,8Û MB |50}Ø¢ ñå^P&\ù—Šð‘ʧ™LÜÃs|cgŸWŽ] ©&˜‘ãó¢J ÛIMQZ樂åã·-^:i²2š¬Úµx×4)2رø¥¹Ééfãýó/Æ0„‹zµ*…Š7¸W'r܄ݦä(&Ž=I[ßÜUwA‰á "JÑÒM´áãîæ…]IÆ`‡´=”%ß1@CwaÍÛL›q8ÿºG‰Ê ½M L0_ÖV8Ї«ü±× %mÔÃûBC5ðx™ ;r»ø]€ Ÿ0Š!.#íD€Z—9hIrùub%^ÅSpÀYž>#ûÕç1äMá¥Ù£¿·‹¸Â'fgš¬í´˜ýéü·ã¨õ²šèˆótfZSˆ½6å¡}/™Þ䘖«È¢6Ó žŽõ°‘<ÌN¥ðH˜,±4#-¡Dý3sYËhdjTr)!ÑDècŽ?§ÁóÒ&Oê^ÛŽžè™Å÷ñ'í ·ÁÎUÙ¡ûй[Ù7"Ò\‹³‹—.̃t·¶eiÁ¤M¿#G®ïYì%@VÑ(™_ Û¼ñw8›»f2g+KÀÍÉ„“ȮǸíƒ/u”'ïPMD¥ɇö§ÈÆd!§Ùçè7UÉI«ª> ð‹ð~§Ä7Ó YöÌ^ £nÍeê~²&*}F1ú€q,ž|Á,DTÀ[2• gß±ï.øŒéjó}£†üÒuûÊ ·þÛf8©OS©ç‰ikùÚÊÆ¬rYtÝéZX]6®cX›gÛg1Ûè 7ƒåHÉq6ü¹´ê†DôC;BÁ‡‘h+·)ÄÒÜ1§›êÅ´Ä“²Ýö{‡¥’®ÙÈÕß¼UAi/ÑÍõ5èf1dœ½›WÍpWÂN%:ûö¹êÈoSADZy*ô×yz22ô‹*©Oß;½SFõIÜ‹$ãû‹I1¹‡ay¥,Ža~Q)Ôá)5/>`~Ê’,:ðl‰Z350çCh~˜Üˆ…_GÃ^QÅùíùš—äQÌò4k9ÁîçïÒÃò«K{~($> ´¢='3ùjW\S^Qk8^>¿êüT‡Ø)Jä ¢ÌÈÄË󊓞Ø>ÐGí(½Ñ‹ê’°]Ñ?Œ¦{odGNï;La ~ÑÜ}\p`ÖIšÎ:8tÜŒæÁ@<¿+>éûZH 4zNªÁ…ÇüµÁDåûTƒŠÎéÒî|NJ|µ2ù_™ŽÄŽç‹j‰?Æz Á©WÚ¬Š¤5 ´U‚î¨à1å³|ŒèyÊš‹ÝwÇ¡÷ËN$Ç›}Ž´éÌØc8LaW`' 7 ŸYÈçº1Š˜&I'rõýÏÃófänšHjÖ<,}ÝKXj¿kDã^ë ãeª ÕPÆ šñ’©­|ýfØÏÅZKuç¬KŠ ÃN ã8LÅ‚ !nÆZ"¤V’5†òûÉŒÉ@Ÿy”ˆúãdÙ…U,½è>V×ÃfU˜»ß¯î{W]o)­´Cꂞ¶Ð,èÝ,ƒ«÷;É)ɦ#ItSWlŸÄ*Ô~ÄC-ÏʤӤÄÓ3¼ÉΕ±¹Ã$³“jùÄ“u²j€æv$v *º*OßÔ1^Ê1“ñ»^º†BDîs#› G,I‹ŽZ׉î‘}Df… È™X=["^¬Ãxð¡„{k©~<*¸^ݧÖµ¢Éî0:Ò·fyM³ãYW¿Êš_.†¥^raÕlkq?ÕVHdóì¥T»&í±Ï)¤¨pîEálÐí»DÉê¿ÅbWÿؘE/ñC+:îNy9w*:·TÇaq&y½Bz ÄÞ„·X‚m½›—Xl÷×ZVŒ¥z\ÀβS8–_…Àžã5º!˜Ö?cC…·4ߨ/~S‘ƒèöï]ý>9r¢8¡M°è:-LNk+T¢°%áh¾ª››Xò[ !ùTÊ÷2ÔÀ‡:F e¤,³0+ô–ã¹ÖOJ­±FÛ6`.dÈ$Î'ñ, Ö«'ÎñkûÂ&¸ÞÂÆÔns±‹âçÂ6ö¶+»¬ Ñi¬ãgõ™:ŽÛõG1&[kƸ^Eš/Ã1Ç xå&ƒ»m9ä‰~@ú†¦ˆ½Ê(t8Ë¢{Ú³ÓŽàß}mñþ&%5‰¦Ï>#Ñ\¹‹ Öü=â:ìHÙ”ö;Ÿ\°¢5eç‡uä‚•¹®3íËJ“µÔ{áÊ}rÅ_ Ã]åïÈŒEÙ¿"-­RäêmŸ,1-Ét”]žN3Ç[|ŒuKÌžj¨Úè×ϯ W,jþƒ„»3–,¹ºãø’ùä35ÊÝNÃÞr°ü%áÁá¸Ü¶ÏBtãw ¼›'òo !ÎÁæN¸AwyåÏ.·_ Gå†YðªpŠk4TNc`ƒûüó¯Œj%èóŽgo(ê:8'u¹#µ¾};C¦1»Ã|¸Ô•ôˆàúz=Cîó‘ODC¸ð÷ÜwȹV÷~I°SªŸüVïoÞ‡Ë÷k­f“þxé]šr£BÄÑG—mé‹}ù_eRkòhë˧©Ñæ+ΞâpÌtQ—#‰ÙçÓŒki5•™xŽb_uè)mšN g½çøø)Y žq\3îÜ®\\çÑ¥¿ƒ:¢¥¦$=#ó?_ˆ'±"æ'™jîiœc¦ Z󇑘iû©B³0󄜒øüVúùÐôµ¦Qàûç^êQ«0¾ð FˆìâhÞj+c‘#./¤[õ6ë¥ÀèãrÿCgè7ê¬è[6Ùñv ?ã=˜]‚6Ü"-væ/’-¼ÛñyH £ä¥V5ä‡+Ù¶2žº‰Ðäö¤Ã—WÌ Ãìì/ã¾xœáœ+JÊò> `dL/(W5>‹ZJ¥Ävà‚UáœW¯8üèâGõ×ââC%*燑d îg×ú~£¡ý‹µK½ÑôR%+|¢²ØY,S”Ix=¢Ï«Pf ßIXv÷-î‡}–>|ÈsÖmŽH­²x±ñ ô :‹½+{ó¾ÈLüîyfÎØ-Î`´¡cE7[·ÞÒž/ÀO;rŠÜX¾ëž¬’ï‘W˜ùè᳂N­sˆÆá¶^ðàl‹ª­eÒdÖ¥sªÄ:óN:t­–ä°ó‡2Z™ŽÆ"º·¬4ÜFg||ß(+¿7$×Þ0GUùö-VítF1høQ˜11:åÜD˜Þ‘î´×½<Öv9¹ûz¬( Å$·­[leÞ­õ6=W¥š>dö3FÔO£‘üëulÛK˜Ý:Ä(:³s8Œ`/9f–‡cÉÙØ•»MU+6õGŽr…ƒHdUŸ õÒ‚ôîñ² ŽSûHÔ‚ÝCPmPgŠòÔÛÄ‘¾9‹oh¤Ô¸öó+P¤K!~¾3ïL\a½<›EŽ5AÑŽï§"œ-uE³åu’‚*Ó ÿ¹é–=JúÍ#Ùu{N"Ú칞ÒÊó3Ä—ZïqÂ,ï3}Z¸“@WÄ"Z bÇ!¬—xEÈÏ£Õ¦d¸T¬1Cýní2‚òÖº››@³k£ ­E£ÔÈ[.l'˜8žA…š‚L„ŠògaÈKá*Ë ¸[·z}L4þ±Òã>Bë»å¬§®± çºBIm”s )›G±£´T®î®Ût©Për1Úe^–ìiø-²8P䀗]M:(ÓPIôa”>GaÄ¥?$òÙ„Ùy)6±ã/…»o!VÅk‚JçÂÕx>jô™©íútaàrÛ{›•gN6öt 1*UO蓽žž{P_' h‚Ç`¸SØp?·màÁÄü¼ R‡àÀŒ’ 7FNÚ [.m H½Žì³]4Ô²Qó¬°]3UwÚ_T &‰ä/„7j!!å!4•×UGÌR<k¾¡3¤}©ÅsåxÔžEYúZsM.©Î6O'F‚âc‚ÔOG=þû!V'ØM9ŠðX‚X¼úûs®í7BÖ–ow(DÚñˆµPÊl^5z:›óRЋ.;,<¸¦,5XUÀ¤Eèò‘ƒ­ö÷×d¹²NÑ¡¡”áÃÓòp¸"é©ï_›Z|XeT{ÍNÆ4•ÎGÅ×â"å‰kE VWKÑÄUŠÎº?»_*It2ÖÖ½’QZÂg~N<ìʱӽ)"8èÓ5ÜZ.£M Ì'y)Lñ“´rÉ ø6ªÜùìvm &kÜ¡ŽB­™A·ÝAUlì-1x¨äd*er‰«°éÕha$è}¸Õ8¿SSF×-<³qwŽžÎ^¿±Yâ lç]éïÒ§jëA¢‚ ï ZÈœXOâüé¥ÞÈÜ'sh¼ûvq™b±] òú”ï‹g“@Y«±s¿³Gƒç,³ã'€Þ+úZFV(l”½ðfp+#ÿ›k[¹`¾ýv—m M!ÇÁWðšå#ÙšŠ. ¦ÚH&ce$žÀczß2+yÉ˵ûËé˜ç/O…«åÇ©5d¬)g†ÈÀ»$‡7ܪ™%B³ÝOW-×€3™ì˜éoe.íhtÃ\É‘.¯$²þ‰cõ™ƒ’¥x _wåc¡õÀâ ot_éyµ‰È’i+zeO&d‹š¼ëí²xw‚¬ ;’BmR×§Í:bCâ k/EsKœf°N?9œÙ J-rœR·PW'åzRÛVbà ŠmÈkç^0ùŽ•P31¸~‚46KÔ¼~qBži©©(ÞߦHÒ{ùn’=rƒñ™É¾u²Zudèàšp&“O9¦öí<Nƒ¤à¼”WŽ.‘¿i¶êIØ9¸ã¢Òüå3N¥ÁùÕŠy¸A-„Y î±ÔjÄÖ0¸0E„’¥ò¼еð.ÓÛµpÏ…Á a¶»fg"Açßú£›2_æ-ÞhO+â¥|}žÄhxz ÁS¥Ü1Œ"ðQ»šù9ņ¯ªÌs˰ b‰2“ËÇQÏIzœÆ~c¨hoõÑe8‘j2÷FcJy”¶ÇŸïƒŒ Kd–UŽ¡æi•D¢¡È+ bøÑ‚Fqþ¾.ö;äT㿊š¥Úõ5ƒUI¦´õW½+ëνÊkŒyDŸ@šã¤ÆéÍ rÓÅØ.€ܹõÏ%˜j?:ñ0ÚÄ¥Å#ûµékã^0ß¶½ygÇ]¢œÓÏôøó-Hçnþ)Qw%éØ%†¼A¨dVe\TÏNÓmƒì3=1§A^mVAs;,¶×ì`Ô<;m>’vG’ÿé¹Zç0ÚÚ&HzngöÛK_aê55‹ÑÛ€[Å'ÕÀP²æg,¥;=?`w™ýØeU8ºAeYcòÕ9Û¾ÎiÇ'?]XÕ•ãÚ1®7°Ù€ª»W÷¨ {$,€^\cdA²ßèZyÕ{òœý&×绾ÖKÃaSøq†ó¥It%2îÁ~”…å)w¹Jr”¢Ü·îòa+Yþ1ú¢"•.EûàVºNÀ]ZŘo@ÍÚ>!츮)´ÍÉÙœlðÃÉ{ G{E5÷¡”4õC»_{™Ze¨IÐÓ²™îkD•°xuliÚ­^ÄT¶i¬sJÌä\¯¥[üÇO5¼Çª_JkÝ3ê (-£ù*ȹ\1·æÓ¡žUŽóŠúÀñëÊFs#:)(˜!+ˆ¬”ÀÁÒ˜ü‹E]÷fKã˜HCñ4~óS˜ÞYÀ)ƒ¸õä¶ùÃJS~í=¿{Ú±*O§ç6û®,›*®ƒ£ê¿]ø Ríó§PÔâän0%ëÁøóÔŒ ¨Jâ[+ªÏ°ôǘyUqÍ€)®MƒIêoÎͳÃòX¢¾„«ºí{NƒŸoÌ"Ü"’Ûáñ~+r2ºÙF_[ÏL£B7ÅûÐ J-à+š¨F“[2ưÚqQ€`”§Ã@…¡WãIrÔ 5"ŒœsZBð7©]ÉOÂh[ BfL“œ?$iƇ¶u ÎÄöJµ`œ³T „ÜB)™/COðîqëvöºÙRÎBª(ñ›Ÿ\Cð¢¾x$g­~#;ØKŸ&’s–¤ÙÇUgzËEª‘J²FÈŠv‡BÌÁÆUB´ç£Ô‘XÌ :µ!âLË7<~·0 Úú¶ˆ$VDƒ¬ù‹—ê "ÍçìíM·#ÅæÔJ‹ÉþkÌ™SmG~w‘¥‚ÿUñ©1 Èïøªøš™…6»âÖ_#r§ñÕ;sQ˜'þÞˆ2Ái±³×äcnÞ൒ B­Ž›Á6H:Z’E,%ƒ_}ï$¹xŠI`¦[,/ÌÙÖ=ëŸ(Ki>N‰(BÔÔ¿°«çzÓNk®<íAÇ€{n ŸU6%? ·oS3Ï&ß#Ì>ð R ~ŒÍ?Y¢¿ ë§ë½Y°j}î•4<¯ÆõÝ2O+NI•AÃz €ƒ³’Aš Oo&{æÐuJÃÉ,ËÍ<¬v†£,ᲚŸ§#;ÔÙí,7®¨rŸ‰ÑTé¯èäGõ`߆“›f”íº±Ä`ô.ªƒcLŒe†êþz‘6ŠårÞ6_¦ÿmL9U­¦RºÏ=E]3@wÝ-YX ¹;ˆÅú“q÷üK³U¯`]®‘Ú _´  ‚îãôhgIüÒ ü¬ü>ƒŸr×è`OXðÆÎÃŽLø¡_ gJñו\ÈÝÒT÷6˾¦dWû~!ƒºY;vº ‚ZÖÏ®IK,ZþtçÁB¡Òfa}I²= ÃâÛ—§¨6p™Æò=XÏ}u={Í67t,F]eùnÞ®™ü‘dñgqªç`¼¥©YCª¾B"{_”ô*4š‹â®Ó—,**ðàôDáÒ¯2ÉFýãpÙ('ùpCPá+âh.äµVŽVü÷Š“ÁA/§# &.K)ZÜ’j#‚p2œÊØý+EÓGH EÌ7fT â{a¸Í…mÙN æ;ånÉe Íe„³„šwžA5_¹yŠ, :RìRøÀQÍÐ {}ÁÕ™?X#ðáh¦¹qòMÓÍ#³n´Íµ‚˜}ë%|æ…o囨ÃÚrŽ”úL1TÙLÂæõg«(Õø§ìì¹|6þ>­Äš• 447®3óâ6@5Ç>6dº¿þŠb++5% Zyh‹v&îŒ „s|Yn4ÔXÚ˜XŒì…¼KâGME³ÚØwϧ¼êNÄ¢†Ò\¯È€šÁê-ñ}eUÏê‡ZBZßµeÛV1QûÙºÞ,ž1¾(/†'ÅêRÙIÞqLÝ6Š·N>½D )å={cÞä‘27,ì£Õ>½æè›`—6wÎÿBññmuЬù¶žRbͨn[¨TkøA¥°>uPðÔ÷T¤(idè’øÞX(î·WñL Ê håÊôªö8n§~Áa&¤ƒ™Ó‚k*YwE¿T-u©§€h÷lL¹‡€i‘Ô§u=3)&NÊ“_Ð’äÏ8…ÏÝåm1„)_5â£~%—Ž*~³³¶^½oÖyüÞjλÝç¸Y€¹Hõ“Ƶ÷×`O_zl¡çaÒ4Ù*W½ý“·6çÎÇmð”ê"yj¨#Âgu-t~”WwþKþ²tZý/ÓÅt9üÅó§%Ÿ†¦­w‘*ãça@à­hŠÅƒ©¨¥®TïáÍ·ÍÀ¾KPû†ÐÊø0‡¯ä{Þš®S~›ü¾q{ÄŠ¢uÜ©d¬lÝžb)¸D0hZùÄðZ$1Dç¿[^ãåJ¸KùµŠ“º4rÚöŒš¬)`VÒÓ EàÓ)SEt„Äy…¶±úÐP&3Õ"×à½Ñ}VJ>|5ÇWèÓMfed1$Pòmýμ­dØC‹ØÊf­g<足ljä@ãþ›&tQ¿9¥¬Z%«ý(òSçžä ®ÓÞŸ~˜zA%Ü¡üêÆ¿‚ Ê68ÑÁ‘§¢d؇ ™-Áø$£ôB®Úñd=vçû@LŠŸmÔéÀ\Œ…؇ ïJ³Û.c9µ~Töʹ‘§x~°¯¸F*¿¿ðAð°>ôµ–݈ý²#ÏêAüÆeÎ…­YŸS"rû=ø’mž¢]˜‹ÆÝÎ D<ÛQwQfË¢HÑ7Ƶº9F2¥{ÿ˜c¡å€Hж¼„I»A5ãÁ ÜtlÉ^ )ö4.XžLnƒƒ8,®Æq±m³ÁÑ.ó ç.AQÔµ ž Ó¸”i´µWÚ‘ÎHû ü»¦É!-RÝǯˆ(s?tæÚ΂õ=—ÙZú×Êý mÉÏŸ¬ŸÅ•¥ž{Cåè`J–Pš_d®ë–®Ç%t9üÉ\Ê1g•é·!›zš¸ã@…V'}½ÕšÑ¨¹ÍÆïõâ³:ÃŒ¯¡ŠeNíº+€Ih¬¸åYgÛg¸;òÚªÈ÷=?:Ad;fNZ·t„’oÎí˜øæ5³ xj¤77þyÿx­0âÈ» ´oKF"gª….Ì ‹¬t"½´çë5Oá¬E9Â%‹’î=‡”4e+¯rÊÝCÛ#V¨ê.WdØP*© ‚ÿ©'zyªÉ—x3íÏ2†e5^_h¦VO‚}N"Hž´†#âó×D}Ø ƒ~l#CÃÌÓfoðÖ~õùù¹£öJŒ1A.äeäÈîp,ÛüFWÖíšÑÿŽgí gË—M "U­5.&rª¹0—0™‚Ùùn+ªœßºþ"ÍhŒÂ\y×V‰ «âÕVÎ^ÜaÎpöò–±¡©_‰{^ù«B¾´ƒ® Ž  À©;k>Í ˜vS‚Íàä½äNý0$§Ü‚ÊÛ⻕t³|EÂïpYЂùk|õæÔ s(Òæ”K 2[ç \¼ U+ª‰ÔKüºœ²ÊQ4Ð#*A±Ôsa80fòÊ£±ÒÚŒ‚ø:r;#(çà³H˜÷_d¾é`ÕK39fß3l½…aQhIB÷ R†0ÂÒꃶqƒó_ZIÍ·Œ¹ˆNÜÞþÌN¡±ñ{’©?)/DÕԪì J•ªvj)Æ;BM%¨µÍøß%]>F&®ÝnÊ!¦‘?„(Ø®»†Áà7ïJûÈ5«À9ßyI&ÏXe0Û$-ãIHŠ4ÆrŠ’öð%!×b5OzS(ƆYî3B{³7g7õàœ–Fk ¨2M©*ÈXÒA‘á×}(¬—<”(³‚ ®×Ýø* ½á—±LÀÙ/QÇ.0Disv¥ð %õŒcý¡î|«Ñô 'ͪ†DâÓl5Ta°^V¨¸Íj4÷lßq¢4ô‹ax þnûìqÚ6¸WÉÙ†@¤¿.d\ÏÈO/‚øúr«¹ |%6LÚ”•ŽT|'u¸ÊÚAJºvü+r+ØeeçÖÀAöêOÓñ½ÃL'4¸ûrmN“¥ dImH¿ žˆšRýÀ1åáGñs¦Ô~Mò6 j4Äã,¬‚®¬]Á[¢ø ¦úa°âßSäTŠÍ(겜¸WM‘rA‡ò­­O~‘ÅõsbÀúŠ“ÙOeoêË%œèËËœ>öôr…ïE's“mƒ2|¿†QÒT„_p™gÓ•Zœá†n{ Ëüèm hWü2ªµû ­ž·ÍQ`Њ)÷{‡ùHhWx‘ö ÐÝDQkÛ…Üf+?UEëîëk?×ê%•fnî Š 10©LÎä$ YÝzm¥ÖôZ1•#Ä ³ùkӃס ªLxÞûƒ€šŸ œfò•%¯Yþ%_Ö‚Õ¾³sB_ìwâÑv¯à<ᤣăËVÊ7u$‹ø/à+k?¾RÞàÑ.;f5±í£)óËsÃÔÄÈžŸhåÅ›Hö‰…ùÿ”.¢¶KC“0¹Lq(öã›ÚÚ»“â¨ñ(ýZ¸ÃòÛìw>i¸ŸB@ò-%Ô˜DÓq¿!ú¥m™~c¤×ovIB Ù¡ÎÝ„©˜€ 8M,û\¦¢–t@æ|©–÷ñ+-/ú5Ž£´V™ÝFÞ¬ö ±û–dÀ®UQ¾…š‹¡ÑD©s^äðêéb}þ€Å+ .±†·Î7ÁÀj²ì(ÞÐ!ukxÓv 9³ñÂzwÆã±À2ë@¾—Þfï©ãû[«†V*ž~¬ÒíÌ㪈3¤úñÄäW“D4&ñ +ÖtÄâY|þ˜T÷9BrŽ®¬0t, [.|;©¾†ÐDO ‚Ù1ÃñOÓqúyŽS¸–¿c_ýÔ¿;“ŸJwVRÀ|Ë8kíü‰ JAO! ýZØ?ZM¸óëˆjkòœ²Ð‘ñÎÅtÿ»Œ©åã™&ã(·TF=;5É )Ê|ÀªŒN¶X°¼(-’¤Ž hz”ëõ¢$¹'ÈÜMž +¹KÒmå¡k*X b•yJn}"=v—<á Ï ÊµAMac¡(¥þ×Pÿ;žJN?ø•t O4¦Š9ÇS›<ÅÓmvdôiѶ”ß=A¹/f¦}{~œ§ÔY€údÄ4\ýf§eÍÂÑF+˜ª«gg¼s"öúAé‰uפ“ךX©ì¯öŸhæÍHô ©¢3C4GW£rO3§>XëÚûgJÒæzÔ1ƒNÜ TžU66Ì׺È;»~{4÷aÚ¤µ~ªø" Ûpªƒ´ Š0ê \ñ™æ¦´ß8›Ž½=56ì·Š¯*¹V%_ QV¹³nè¾O…ú©ÉˆòK´Øö÷kèR ±sþHÈØ•œ ;CÕ>>õaê-Áu„D Ær†Ë–„0Mˆ,îø=UZlmt/=¼-l,­ÃFUR§)Œm£•¯c6yüŽðëvP”à+42ƒ ÚóCYi€KF·®¬nYSžf!-èj­ºßöçŽ ˜•þ˜ûK„è™ ¶?7‡T,Fzøª‰|Z×'gÝJ*T—‘I^’ã–ŒÄ(DØùn%2ÊJlnj©ÓÎý3 wÅ2E£QÜ@œvnì}·¥_Ky”E:Ƭ¾N¯ê·À_v~‹•·„YÜ5«Í*íÙŸü˜gøÚë4~²0w›Àßè±]‰â+Š%æ›Ï©r>ƒâaÆ÷‚Ã@!"ýÖ’;Óm¹¡c´NÁ1ÿëì)e6øÖxÚ[¿`š¡Ó…êªY¹½ Åðà§ø²K圖‚õ\fJ¨ÃŒb‘Šx“èÒL¥TÆ¿T ÁÔƒï£wæEê)„â×ÕÓºœ¨PUmÙà3+$ƒ2QÆ(Âsý{J¼í’/Œàg•UkÔÑä€hv?n’ͬ"3íÛXÕ¼<5›CÝ,¨ïó9¨€¥½r¨UÅì!*ÃrŒ-^ª¾M±®hCBdÉtæ—9B¶€¾<L´WfìC{@QËC¿ì³ÚÓÅû­gü§.Yø‹äFßÅØ¾Õß:›Çd!†ÝäùE$i“ëÇÙ,£MKØç¿Œ„Òð‚-\òLØÆw’±oÅD;øGd&h¸S-Mè‹ë ¸9ƒ ~ñºäF•oöÍø…`ÓÒ°7vðŠ®¬:²Hè2ùç'”=¶°]é òf‘«eýFº[\Åwö5x‘ï.™EuÅËX$½#ð” º}£Åu|JÓÃl\&:°°²sò"*mD‹ÊyÓâ»—zÒ"ö¥GGf+ó¯‡:ê>TÅ[u3´â S@#­Lu^ý19£QR4¶¬áHb¡ÓDË1 ÉAøýVÄçËF³ÁÍÜB^ÕVpGrQ—Öi£[c_š§³b Yp’È¥˜àŒ·cïå$P°äœ˜IeÁëŒèL ¡3M Ÿ‡~¼hžyù ¶Ï%J­aðyw.|øî¤Èç =¯¾R;ˆ\×…5«·À–%Ë×xÎcn“ükû—{ny«®ÀŠ1òzÎq6žü–U.%åCËÉÃ[Ž òÓ@ãJ¤À%TÌY·Zô1\ͺ±Š.Ê‚\£;Q¨¶õF( ƒ2‚:Gá9üó3þ¡âŒ÷.\D\¿Gù…žnOÑAÚ‘ª‰ãÚ¬OŠ4§Â%|¥wfúZÝ‚v£æ³âÖL‰ -@ájœ½l׉{=RÇ|" L˜^8¬s;½¬ÜÑÁòçW@Å[RÊKߌºÑòø‰òö¨e’‡‹Žõ˜%jŸÀד>¯'Ë2¤¾ð)ïÅ–. û`±[Ñíèús t$*‹BìŽEÊ Ì¢YíŠGd ”¦ºOÞE¬>eÔ_®¨Dk¨ô'`’u.‚ÛÏÚ¯•’ˆUÏN<¶Äâ¦ð ùfÓ‡ëºLH„•¥««`è«"cŸ:r¬©`; ñ«Kzý8ý‚Jqö¦WW Î\ƒ9_¹íº'Nª“ô <"¬¶yA…»4f¦>&¥¸sȼ~Ú“„ç¼mÎõ)¸ãÛô(òž°ô¨‡Y£,ÉBÆ{û B0,¾Õ“èÐo"¸.? ‚ #q©áG;ô5RRãk¥Sé‘2$Vl`çOô˜Œ-O> endobj 1376 0 obj << /Length1 841 /Length2 1196 /Length3 0 /Length 1747 /Filter /FlateDecode >> stream xÚ­RkTSW†Q48È(Pìä%$y$ÚVH`oÁeHáJró€ja¨¼Ä(Êc@P¤ UªB׋ˆ‚ˆµB4ËÃBxD¨¥ŠÒ:é ý;뮵×ýöþöù¾½Ï±·‰`ºùr…± @ˆJÝHî$ B¥3¨!þ$"Dr'I8{{ª°¥ˆ¥±¥€‘Èd çH!Ø‚‰˜Dñ$c$HD$Ë$ë„‚d(Dôü/DŠb„/…œ¨Î 'y».Q}@ŒpØ(Ê–Æ&Çaó!¦ƒ©Âòåó!ÆBŸb '®;ŽD‚¸æ#ðGX˜€ŽÆ !ï¥4W&zWJâkÓâDÎ6WˆòÄáaBL `ŽþæVJÈøü0¶YÞîŸ(lÂWü‡ÄÞ ¢V"Á’·PÀEd‚•Uº”ÍG8¾( âR ‘ rÀ@¤œx(ŽÍ—€Å<@¹+¥±Í- Bý"Y!þ.<ÅzA¥;¢å“1éŒíFŒÈ¡=Ä…cDì{÷³BÏå¹ʃ`O/ˆ-³8ì±aÈJ!AÊrÈ1ÓwT(ÅZ ‘LzŠŠq —ŠÙ"°±€%—0i“–±}–CäEôç¡ýü„ò7쎉ÐR„‰[–ÂÁÿ!sdb1@¥‹Ï [ß;‡`Ë@8¸Ç„œärÆñê/ss7gm+j5åØÙT¯—YdÙ5—ù×W‹ø½øP†×éG~ºÈ'—Ö€Û-æ>tüAÝwÙÞqš+íuµg½[˜ç/ÜLô]¹385a32Vbèß"I91máÿë&%Eù¦ÄñŒƤ“V5ï¤Ö5Q§b:D›üä«Viõ‹m¿Ö3-£ÛŠäåñÛš¤EOÙ«Ú˜ ½µøÕÁiZ´þÌj{ò¯ŽYãä/þF¥´©ðÅ_TΦ:–9Æ]1²|jj7üùk_ð”áÖx¬çØUdŽÊÉÝVz37‘wÆÍqNmî«kzžgåhÖ¡.è ‰X-­·0 ͵ӬÛjZÓÆòfL’µBµíhìÞC.!óZ“öSG$ÁOÈ_g%lðøþzÛœõW6/¨³)ßš¬¤Œ×™Á {‚«"³šiùþŒè£o^ïØ÷°zBβÎ3±í±šï©Ö$•$´æÜ¿ß` ?Ff:aÓØÛ2]¸ÿï´pè3Ù3ýÂ!ö+¿NÝßb:…¹ÇÛLJúíW¯-Teß*W*³X„Î#/ÜÎ4&­ŸÉµ?:´ÝÙ½Kj.Ê`ÄËj×05óŽú3šúj³'ži÷}*¸{Ò°É‚±ªªèNj—䨋<¤á6LÁ5àôŠrŸ‹¬TÜ“s1™L¤”<£ø ßܪî­šþ(ý% ¨š…îÖ½ÀFUuù<åÞzæ'®Uë<ÿülW¬>XOj’”FôôҨ漹G³Y±ƒï$oøI)Ä×äë5¼aÒHß5oòSbÙ–‘AõæIÑ,ÇìÎÖýºE$« àÐeØYe¡Ýé fQ×JrUž5ñ¬»ÎNn4œÁÖÒFûœæ›²®¼™ÝÑPéaúò½r`È­B: I*cõ·÷ºŸŽh÷ýó_ôþî1¢jþýÈè©í—'ÈϳîŽM‚¢YWYÖ½îî°E*¿kW’%rï oêUmZJþ4;}Ê…rîtº«Jù]}¨ºcD¹þ0pî«:ÚK}|Í.áÈZ~…ê8µ·‹bU­§Æõ©â§_[æ9oû}´`çßúÖ.=¨ísãÞ>QøtÇtÖ{ä±Àúà–kG9µ£÷æ†üßåö6©èaf…ûo½Ýêñ0ÜàhTPHËáµ'’·ý|™§¿[¯?&h6³/üh«®DGg¾¶ö”âT“‘ø÷6¼Ýûë³áy•OϺk•ZÔ!kp8–ÆÅOËr/®Mš4¢G÷&n_ßß­W¾I›q9Åö$óı«©œÌ=ãçô“º’d“Ù9(†£=Žè×àÑn¯û,§«ðvó&žùae™FåÞ™†:‘±ô)Ü—É ^Å û©Iz‚uÎñ1ç‡9r>9¡…† p­OÌ7~©:7ߤ¬Ïnn|þòñ¤ñÍÒÉ_g#­ç 7G¸ÖóUE‚¦€Ëþq£Ý7k2¶ –ä?/ë >ŸÚh;¢x« ïv Í÷/ÿáÐ%yd@ȳ´Þ4Vå‘[óTÓ endstream endobj 1377 0 obj << /Type /FontDescriptor /FontName /MBWZLE+LCIRCLE10 /Flags 4 /FontBBox [-2000 -2000 2040 2040] /Ascent 0 /CapHeight 0 /Descent 0 /ItalicAngle 0 /StemV 40 /XHeight 0 /CharSet (/a10/a11/a8/a9) /FontFile 1376 0 R >> endobj 18 0 obj << /Type /Font /Subtype /Type1 /BaseFont /LIUXUG+CMB10 /FontDescriptor 1349 0 R /FirstChar 12 /LastChar 121 /Widths 1343 0 R >> endobj 4 0 obj << /Type /Font /Subtype /Type1 /BaseFont /IWYCFJ+CMBX12 /FontDescriptor 1351 0 R /FirstChar 12 /LastChar 122 /Widths 1347 0 R >> endobj 928 0 obj << /Type /Font /Subtype /Type1 /BaseFont /PLSYJB+CMBXTI10 /FontDescriptor 1353 0 R /FirstChar 46 /LastChar 46 /Widths 1333 0 R >> endobj 5 0 obj << /Type /Font /Subtype /Type1 /BaseFont /APBFVA+CMR10 /FontDescriptor 1355 0 R /FirstChar 11 /LastChar 124 /Widths 1346 0 R >> endobj 254 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NLKSSS+CMR7 /FontDescriptor 1357 0 R /FirstChar 49 /LastChar 52 /Widths 1336 0 R >> endobj 255 0 obj << /Type /Font /Subtype /Type1 /BaseFont /QUJEUC+CMR9 /FontDescriptor 1359 0 R /FirstChar 11 /LastChar 122 /Widths 1335 0 R >> endobj 60 0 obj << /Type /Font /Subtype /Type1 /BaseFont /SWHVBQ+CMSL10 /FontDescriptor 1361 0 R /FirstChar 45 /LastChar 121 /Widths 1339 0 R >> endobj 59 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NCLYYD+CMSLTT10 /FontDescriptor 1363 0 R /FirstChar 45 /LastChar 121 /Widths 1340 0 R >> endobj 10 0 obj << /Type /Font /Subtype /Type1 /BaseFont /AQTFCU+CMSY10 /FontDescriptor 1365 0 R /FirstChar 13 /LastChar 15 /Widths 1345 0 R >> endobj 16 0 obj << /Type /Font /Subtype /Type1 /BaseFont /GBKFSS+CMTI10 /FontDescriptor 1367 0 R /FirstChar 11 /LastChar 123 /Widths 1344 0 R >> endobj 610 0 obj << /Type /Font /Subtype /Type1 /BaseFont /ZKKWJR+CMTI9 /FontDescriptor 1369 0 R /FirstChar 46 /LastChar 46 /Widths 1334 0 R >> endobj 19 0 obj << /Type /Font /Subtype /Type1 /BaseFont /FBYSGW+CMTT10 /FontDescriptor 1371 0 R /FirstChar 33 /LastChar 126 /Widths 1342 0 R >> endobj 198 0 obj << /Type /Font /Subtype /Type1 /BaseFont /NLSGIH+CMTT12 /FontDescriptor 1373 0 R /FirstChar 34 /LastChar 121 /Widths 1337 0 R >> endobj 46 0 obj << /Type /Font /Subtype /Type1 /BaseFont /HJTGZV+CMTT9 /FontDescriptor 1375 0 R /FirstChar 33 /LastChar 126 /Widths 1341 0 R >> endobj 167 0 obj << /Type /Font /Subtype /Type1 /BaseFont /MBWZLE+LCIRCLE10 /FontDescriptor 1377 0 R /FirstChar 8 /LastChar 11 /Widths 1338 0 R >> endobj 6 0 obj << /Type /Pages /Count 6 /Parent 1378 0 R /Kids [2 0 R 8 0 R 12 0 R 21 0 R 26 0 R 35 0 R] >> endobj 48 0 obj << /Type /Pages /Count 6 /Parent 1378 0 R /Kids [42 0 R 50 0 R 54 0 R 62 0 R 66 0 R 71 0 R] >> endobj 80 0 obj << /Type /Pages /Count 6 /Parent 1378 0 R /Kids [75 0 R 82 0 R 86 0 R 91 0 R 96 0 R 101 0 R] >> endobj 112 0 obj << /Type /Pages /Count 6 /Parent 1378 0 R /Kids [108 0 R 118 0 R 129 0 R 133 0 R 137 0 R 143 0 R] >> endobj 150 0 obj << /Type /Pages /Count 6 /Parent 1378 0 R /Kids [147 0 R 152 0 R 158 0 R 164 0 R 170 0 R 174 0 R] >> endobj 186 0 obj << /Type /Pages /Count 6 /Parent 1378 0 R /Kids [181 0 R 188 0 R 194 0 R 200 0 R 207 0 R 212 0 R] >> endobj 225 0 obj << /Type /Pages /Count 6 /Parent 1379 0 R /Kids [219 0 R 227 0 R 231 0 R 236 0 R 240 0 R 246 0 R] >> endobj 256 0 obj << /Type /Pages /Count 6 /Parent 1379 0 R /Kids [251 0 R 258 0 R 263 0 R 270 0 R 275 0 R 281 0 R] >> endobj 289 0 obj << /Type /Pages /Count 6 /Parent 1379 0 R /Kids [286 0 R 291 0 R 295 0 R 300 0 R 304 0 R 309 0 R] >> endobj 318 0 obj << /Type /Pages /Count 6 /Parent 1379 0 R /Kids [314 0 R 320 0 R 326 0 R 330 0 R 334 0 R 338 0 R] >> endobj 348 0 obj << /Type /Pages /Count 6 /Parent 1379 0 R /Kids [343 0 R 350 0 R 355 0 R 361 0 R 366 0 R 373 0 R] >> endobj 382 0 obj << /Type /Pages /Count 6 /Parent 1379 0 R /Kids [379 0 R 384 0 R 388 0 R 393 0 R 399 0 R 403 0 R] >> endobj 410 0 obj << /Type /Pages /Count 6 /Parent 1380 0 R /Kids [407 0 R 412 0 R 416 0 R 422 0 R 428 0 R 434 0 R] >> endobj 443 0 obj << /Type /Pages /Count 6 /Parent 1380 0 R /Kids [439 0 R 445 0 R 449 0 R 453 0 R 458 0 R 463 0 R] >> endobj 473 0 obj << /Type /Pages /Count 6 /Parent 1380 0 R /Kids [469 0 R 475 0 R 482 0 R 486 0 R 491 0 R 495 0 R] >> endobj 504 0 obj << /Type /Pages /Count 6 /Parent 1380 0 R /Kids [500 0 R 506 0 R 511 0 R 516 0 R 525 0 R 530 0 R] >> endobj 538 0 obj << /Type /Pages /Count 6 /Parent 1380 0 R /Kids [534 0 R 540 0 R 606 0 R 612 0 R 713 0 R 796 0 R] >> endobj 856 0 obj << /Type /Pages /Count 6 /Parent 1380 0 R /Kids [853 0 R 858 0 R 875 0 R 880 0 R 925 0 R 973 0 R] >> endobj 1004 0 obj << /Type /Pages /Count 2 /Parent 1381 0 R /Kids [1001 0 R 1006 0 R] >> endobj 1378 0 obj << /Type /Pages /Count 36 /Parent 1382 0 R /Kids [6 0 R 48 0 R 80 0 R 112 0 R 150 0 R 186 0 R] >> endobj 1379 0 obj << /Type /Pages /Count 36 /Parent 1382 0 R /Kids [225 0 R 256 0 R 289 0 R 318 0 R 348 0 R 382 0 R] >> endobj 1380 0 obj << /Type /Pages /Count 36 /Parent 1382 0 R /Kids [410 0 R 443 0 R 473 0 R 504 0 R 538 0 R 856 0 R] >> endobj 1381 0 obj << /Type /Pages /Count 2 /Parent 1382 0 R /Kids [1004 0 R] >> endobj 1382 0 obj << /Type /Pages /Count 110 /Kids [1378 0 R 1379 0 R 1380 0 R 1381 0 R] >> endobj 1383 0 obj << /Type /Outlines /First 1010 0 R /Last 1331 0 R /Count 11 >> endobj 1331 0 obj << /Title 1332 0 R /A 1330 0 R /Parent 1383 0 R /Prev 1328 0 R >> endobj 1328 0 obj << /Title 1329 0 R /A 1327 0 R /Parent 1383 0 R /Prev 1325 0 R /Next 1331 0 R >> endobj 1325 0 obj << /Title 1326 0 R /A 1324 0 R /Parent 1383 0 R /Prev 1322 0 R /Next 1328 0 R >> endobj 1322 0 obj << /Title 1323 0 R /A 1321 0 R /Parent 1383 0 R /Prev 1241 0 R /Next 1325 0 R >> endobj 1319 0 obj << /Title 1320 0 R /A 1318 0 R /Parent 1241 0 R /Prev 1316 0 R >> endobj 1316 0 obj << /Title 1317 0 R /A 1315 0 R /Parent 1241 0 R /Prev 1313 0 R /Next 1319 0 R >> endobj 1313 0 obj << /Title 1314 0 R /A 1312 0 R /Parent 1241 0 R /Prev 1310 0 R /Next 1316 0 R >> endobj 1310 0 obj << /Title 1311 0 R /A 1309 0 R /Parent 1241 0 R /Prev 1307 0 R /Next 1313 0 R >> endobj 1307 0 obj << /Title 1308 0 R /A 1306 0 R /Parent 1241 0 R /Prev 1304 0 R /Next 1310 0 R >> endobj 1304 0 obj << /Title 1305 0 R /A 1303 0 R /Parent 1241 0 R /Prev 1301 0 R /Next 1307 0 R >> endobj 1301 0 obj << /Title 1302 0 R /A 1300 0 R /Parent 1241 0 R /Prev 1298 0 R /Next 1304 0 R >> endobj 1298 0 obj << /Title 1299 0 R /A 1297 0 R /Parent 1241 0 R /Prev 1295 0 R /Next 1301 0 R >> endobj 1295 0 obj << /Title 1296 0 R /A 1294 0 R /Parent 1241 0 R /Prev 1292 0 R /Next 1298 0 R >> endobj 1292 0 obj << /Title 1293 0 R /A 1291 0 R /Parent 1241 0 R /Prev 1289 0 R /Next 1295 0 R >> endobj 1289 0 obj << /Title 1290 0 R /A 1288 0 R /Parent 1241 0 R /Prev 1286 0 R /Next 1292 0 R >> endobj 1286 0 obj << /Title 1287 0 R /A 1285 0 R /Parent 1241 0 R /Prev 1283 0 R /Next 1289 0 R >> endobj 1283 0 obj << /Title 1284 0 R /A 1282 0 R /Parent 1241 0 R /Prev 1280 0 R /Next 1286 0 R >> endobj 1280 0 obj << /Title 1281 0 R /A 1279 0 R /Parent 1241 0 R /Prev 1277 0 R /Next 1283 0 R >> endobj 1277 0 obj << /Title 1278 0 R /A 1276 0 R /Parent 1241 0 R /Prev 1274 0 R /Next 1280 0 R >> endobj 1274 0 obj << /Title 1275 0 R /A 1273 0 R /Parent 1241 0 R /Prev 1271 0 R /Next 1277 0 R >> endobj 1271 0 obj << /Title 1272 0 R /A 1270 0 R /Parent 1241 0 R /Prev 1268 0 R /Next 1274 0 R >> endobj 1268 0 obj << /Title 1269 0 R /A 1267 0 R /Parent 1241 0 R /Prev 1265 0 R /Next 1271 0 R >> endobj 1265 0 obj << /Title 1266 0 R /A 1264 0 R /Parent 1241 0 R /Prev 1262 0 R /Next 1268 0 R >> endobj 1262 0 obj << /Title 1263 0 R /A 1261 0 R /Parent 1241 0 R /Prev 1259 0 R /Next 1265 0 R >> endobj 1259 0 obj << /Title 1260 0 R /A 1258 0 R /Parent 1241 0 R /Prev 1256 0 R /Next 1262 0 R >> endobj 1256 0 obj << /Title 1257 0 R /A 1255 0 R /Parent 1241 0 R /Prev 1253 0 R /Next 1259 0 R >> endobj 1253 0 obj << /Title 1254 0 R /A 1252 0 R /Parent 1241 0 R /Prev 1250 0 R /Next 1256 0 R >> endobj 1250 0 obj << /Title 1251 0 R /A 1249 0 R /Parent 1241 0 R /Prev 1247 0 R /Next 1253 0 R >> endobj 1247 0 obj << /Title 1248 0 R /A 1246 0 R /Parent 1241 0 R /Prev 1244 0 R /Next 1250 0 R >> endobj 1244 0 obj << /Title 1245 0 R /A 1243 0 R /Parent 1241 0 R /Next 1247 0 R >> endobj 1241 0 obj << /Title 1242 0 R /A 1240 0 R /Parent 1383 0 R /Prev 1208 0 R /Next 1322 0 R /First 1244 0 R /Last 1319 0 R /Count -26 >> endobj 1238 0 obj << /Title 1239 0 R /A 1237 0 R /Parent 1232 0 R /Prev 1235 0 R >> endobj 1235 0 obj << /Title 1236 0 R /A 1234 0 R /Parent 1232 0 R /Next 1238 0 R >> endobj 1232 0 obj << /Title 1233 0 R /A 1231 0 R /Parent 1208 0 R /Prev 1214 0 R /First 1235 0 R /Last 1238 0 R /Count -2 >> endobj 1229 0 obj << /Title 1230 0 R /A 1228 0 R /Parent 1214 0 R /Prev 1226 0 R >> endobj 1226 0 obj << /Title 1227 0 R /A 1225 0 R /Parent 1214 0 R /Prev 1223 0 R /Next 1229 0 R >> endobj 1223 0 obj << /Title 1224 0 R /A 1222 0 R /Parent 1214 0 R /Prev 1220 0 R /Next 1226 0 R >> endobj 1220 0 obj << /Title 1221 0 R /A 1219 0 R /Parent 1214 0 R /Prev 1217 0 R /Next 1223 0 R >> endobj 1217 0 obj << /Title 1218 0 R /A 1216 0 R /Parent 1214 0 R /Next 1220 0 R >> endobj 1214 0 obj << /Title 1215 0 R /A 1213 0 R /Parent 1208 0 R /Prev 1211 0 R /Next 1232 0 R /First 1217 0 R /Last 1229 0 R /Count -5 >> endobj 1211 0 obj << /Title 1212 0 R /A 1210 0 R /Parent 1208 0 R /Next 1214 0 R >> endobj 1208 0 obj << /Title 1209 0 R /A 1207 0 R /Parent 1383 0 R /Prev 1193 0 R /Next 1241 0 R /First 1211 0 R /Last 1232 0 R /Count -3 >> endobj 1205 0 obj << /Title 1206 0 R /A 1204 0 R /Parent 1193 0 R /Prev 1202 0 R >> endobj 1202 0 obj << /Title 1203 0 R /A 1201 0 R /Parent 1193 0 R /Prev 1199 0 R /Next 1205 0 R >> endobj 1199 0 obj << /Title 1200 0 R /A 1198 0 R /Parent 1193 0 R /Prev 1196 0 R /Next 1202 0 R >> endobj 1196 0 obj << /Title 1197 0 R /A 1195 0 R /Parent 1193 0 R /Next 1199 0 R >> endobj 1193 0 obj << /Title 1194 0 R /A 1192 0 R /Parent 1383 0 R /Prev 1139 0 R /Next 1208 0 R /First 1196 0 R /Last 1205 0 R /Count -4 >> endobj 1190 0 obj << /Title 1191 0 R /A 1189 0 R /Parent 1139 0 R /Prev 1187 0 R >> endobj 1187 0 obj << /Title 1188 0 R /A 1186 0 R /Parent 1139 0 R /Prev 1184 0 R /Next 1190 0 R >> endobj 1184 0 obj << /Title 1185 0 R /A 1183 0 R /Parent 1139 0 R /Prev 1181 0 R /Next 1187 0 R >> endobj 1181 0 obj << /Title 1182 0 R /A 1180 0 R /Parent 1139 0 R /Prev 1178 0 R /Next 1184 0 R >> endobj 1178 0 obj << /Title 1179 0 R /A 1177 0 R /Parent 1139 0 R /Prev 1175 0 R /Next 1181 0 R >> endobj 1175 0 obj << /Title 1176 0 R /A 1174 0 R /Parent 1139 0 R /Prev 1157 0 R /Next 1178 0 R >> endobj 1172 0 obj << /Title 1173 0 R /A 1171 0 R /Parent 1157 0 R /Prev 1169 0 R >> endobj 1169 0 obj << /Title 1170 0 R /A 1168 0 R /Parent 1157 0 R /Prev 1166 0 R /Next 1172 0 R >> endobj 1166 0 obj << /Title 1167 0 R /A 1165 0 R /Parent 1157 0 R /Prev 1163 0 R /Next 1169 0 R >> endobj 1163 0 obj << /Title 1164 0 R /A 1162 0 R /Parent 1157 0 R /Prev 1160 0 R /Next 1166 0 R >> endobj 1160 0 obj << /Title 1161 0 R /A 1159 0 R /Parent 1157 0 R /Next 1163 0 R >> endobj 1157 0 obj << /Title 1158 0 R /A 1156 0 R /Parent 1139 0 R /Prev 1154 0 R /Next 1175 0 R /First 1160 0 R /Last 1172 0 R /Count -5 >> endobj 1154 0 obj << /Title 1155 0 R /A 1153 0 R /Parent 1139 0 R /Prev 1151 0 R /Next 1157 0 R >> endobj 1151 0 obj << /Title 1152 0 R /A 1150 0 R /Parent 1139 0 R /Prev 1148 0 R /Next 1154 0 R >> endobj 1148 0 obj << /Title 1149 0 R /A 1147 0 R /Parent 1139 0 R /Prev 1145 0 R /Next 1151 0 R >> endobj 1145 0 obj << /Title 1146 0 R /A 1144 0 R /Parent 1139 0 R /Prev 1142 0 R /Next 1148 0 R >> endobj 1142 0 obj << /Title 1143 0 R /A 1141 0 R /Parent 1139 0 R /Next 1145 0 R >> endobj 1139 0 obj << /Title 1140 0 R /A 1138 0 R /Parent 1383 0 R /Prev 1079 0 R /Next 1193 0 R /First 1142 0 R /Last 1190 0 R /Count -12 >> endobj 1136 0 obj << /Title 1137 0 R /A 1135 0 R /Parent 1079 0 R /Prev 1133 0 R >> endobj 1133 0 obj << /Title 1134 0 R /A 1132 0 R /Parent 1079 0 R /Prev 1130 0 R /Next 1136 0 R >> endobj 1130 0 obj << /Title 1131 0 R /A 1129 0 R /Parent 1079 0 R /Prev 1127 0 R /Next 1133 0 R >> endobj 1127 0 obj << /Title 1128 0 R /A 1126 0 R /Parent 1079 0 R /Prev 1124 0 R /Next 1130 0 R >> endobj 1124 0 obj << /Title 1125 0 R /A 1123 0 R /Parent 1079 0 R /Prev 1121 0 R /Next 1127 0 R >> endobj 1121 0 obj << /Title 1122 0 R /A 1120 0 R /Parent 1079 0 R /Prev 1118 0 R /Next 1124 0 R >> endobj 1118 0 obj << /Title 1119 0 R /A 1117 0 R /Parent 1079 0 R /Prev 1115 0 R /Next 1121 0 R >> endobj 1115 0 obj << /Title 1116 0 R /A 1114 0 R /Parent 1079 0 R /Prev 1112 0 R /Next 1118 0 R >> endobj 1112 0 obj << /Title 1113 0 R /A 1111 0 R /Parent 1079 0 R /Prev 1109 0 R /Next 1115 0 R >> endobj 1109 0 obj << /Title 1110 0 R /A 1108 0 R /Parent 1079 0 R /Prev 1091 0 R /Next 1112 0 R >> endobj 1106 0 obj << /Title 1107 0 R /A 1105 0 R /Parent 1091 0 R /Prev 1103 0 R >> endobj 1103 0 obj << /Title 1104 0 R /A 1102 0 R /Parent 1091 0 R /Prev 1100 0 R /Next 1106 0 R >> endobj 1100 0 obj << /Title 1101 0 R /A 1099 0 R /Parent 1091 0 R /Prev 1097 0 R /Next 1103 0 R >> endobj 1097 0 obj << /Title 1098 0 R /A 1096 0 R /Parent 1091 0 R /Prev 1094 0 R /Next 1100 0 R >> endobj 1094 0 obj << /Title 1095 0 R /A 1093 0 R /Parent 1091 0 R /Next 1097 0 R >> endobj 1091 0 obj << /Title 1092 0 R /A 1090 0 R /Parent 1079 0 R /Prev 1088 0 R /Next 1109 0 R /First 1094 0 R /Last 1106 0 R /Count -5 >> endobj 1088 0 obj << /Title 1089 0 R /A 1087 0 R /Parent 1079 0 R /Prev 1085 0 R /Next 1091 0 R >> endobj 1085 0 obj << /Title 1086 0 R /A 1084 0 R /Parent 1079 0 R /Prev 1082 0 R /Next 1088 0 R >> endobj 1082 0 obj << /Title 1083 0 R /A 1081 0 R /Parent 1079 0 R /Next 1085 0 R >> endobj 1079 0 obj << /Title 1080 0 R /A 1078 0 R /Parent 1383 0 R /Prev 1043 0 R /Next 1139 0 R /First 1082 0 R /Last 1136 0 R /Count -14 >> endobj 1076 0 obj << /Title 1077 0 R /A 1075 0 R /Parent 1043 0 R /Prev 1073 0 R >> endobj 1073 0 obj << /Title 1074 0 R /A 1072 0 R /Parent 1043 0 R /Prev 1070 0 R /Next 1076 0 R >> endobj 1070 0 obj << /Title 1071 0 R /A 1069 0 R /Parent 1043 0 R /Prev 1067 0 R /Next 1073 0 R >> endobj 1067 0 obj << /Title 1068 0 R /A 1066 0 R /Parent 1043 0 R /Prev 1064 0 R /Next 1070 0 R >> endobj 1064 0 obj << /Title 1065 0 R /A 1063 0 R /Parent 1043 0 R /Prev 1052 0 R /Next 1067 0 R >> endobj 1061 0 obj << /Title 1062 0 R /A 1060 0 R /Parent 1052 0 R /Prev 1058 0 R >> endobj 1058 0 obj << /Title 1059 0 R /A 1057 0 R /Parent 1052 0 R /Prev 1055 0 R /Next 1061 0 R >> endobj 1055 0 obj << /Title 1056 0 R /A 1054 0 R /Parent 1052 0 R /Next 1058 0 R >> endobj 1052 0 obj << /Title 1053 0 R /A 1051 0 R /Parent 1043 0 R /Prev 1049 0 R /Next 1064 0 R /First 1055 0 R /Last 1061 0 R /Count -3 >> endobj 1049 0 obj << /Title 1050 0 R /A 1048 0 R /Parent 1043 0 R /Prev 1046 0 R /Next 1052 0 R >> endobj 1046 0 obj << /Title 1047 0 R /A 1045 0 R /Parent 1043 0 R /Next 1049 0 R >> endobj 1043 0 obj << /Title 1044 0 R /A 1042 0 R /Parent 1383 0 R /Prev 1010 0 R /Next 1079 0 R /First 1046 0 R /Last 1076 0 R /Count -8 >> endobj 1040 0 obj << /Title 1041 0 R /A 1039 0 R /Parent 1010 0 R /Prev 1019 0 R >> endobj 1037 0 obj << /Title 1038 0 R /A 1036 0 R /Parent 1019 0 R /Prev 1034 0 R >> endobj 1034 0 obj << /Title 1035 0 R /A 1033 0 R /Parent 1019 0 R /Prev 1031 0 R /Next 1037 0 R >> endobj 1031 0 obj << /Title 1032 0 R /A 1030 0 R /Parent 1019 0 R /Prev 1028 0 R /Next 1034 0 R >> endobj 1028 0 obj << /Title 1029 0 R /A 1027 0 R /Parent 1019 0 R /Prev 1025 0 R /Next 1031 0 R >> endobj 1025 0 obj << /Title 1026 0 R /A 1024 0 R /Parent 1019 0 R /Prev 1022 0 R /Next 1028 0 R >> endobj 1022 0 obj << /Title 1023 0 R /A 1021 0 R /Parent 1019 0 R /Next 1025 0 R >> endobj 1019 0 obj << /Title 1020 0 R /A 1018 0 R /Parent 1010 0 R /Prev 1016 0 R /Next 1040 0 R /First 1022 0 R /Last 1037 0 R /Count -6 >> endobj 1016 0 obj << /Title 1017 0 R /A 1015 0 R /Parent 1010 0 R /Prev 1013 0 R /Next 1019 0 R >> endobj 1013 0 obj << /Title 1014 0 R /A 1012 0 R /Parent 1010 0 R /Next 1016 0 R >> endobj 1010 0 obj << /Title 1011 0 R /A 1009 0 R /Parent 1383 0 R /Next 1043 0 R /First 1013 0 R /Last 1040 0 R /Count -4 >> endobj 1384 0 obj << /Names [(-1) 927 0 R (-2) 975 0 R (-3) 1003 0 R (-4) 1008 0 R (1) 14 0 R (10) 73 0 R] /Limits [(-1) (10)] >> endobj 1385 0 obj << /Names [(100) 798 0 R (101) 855 0 R (102) 860 0 R (103) 877 0 R (104) 882 0 R (11) 77 0 R] /Limits [(100) (11)] >> endobj 1386 0 obj << /Names [(12) 84 0 R (13) 88 0 R (14) 93 0 R (15) 98 0 R (16) 103 0 R (17) 110 0 R] /Limits [(12) (17)] >> endobj 1387 0 obj << /Names [(18) 120 0 R (19) 131 0 R (2) 23 0 R (20) 135 0 R (21) 139 0 R (22) 145 0 R] /Limits [(18) (22)] >> endobj 1388 0 obj << /Names [(23) 149 0 R (24) 154 0 R (25) 160 0 R (26) 166 0 R (27) 172 0 R (28) 176 0 R] /Limits [(23) (28)] >> endobj 1389 0 obj << /Names [(29) 183 0 R (3) 28 0 R (30) 190 0 R (31) 196 0 R (32) 202 0 R (33) 209 0 R] /Limits [(29) (33)] >> endobj 1390 0 obj << /Names [(34) 214 0 R (35) 221 0 R (36) 229 0 R (37) 233 0 R (38) 238 0 R (39) 242 0 R] /Limits [(34) (39)] >> endobj 1391 0 obj << /Names [(4) 37 0 R (40) 248 0 R (41) 253 0 R (42) 260 0 R (43) 265 0 R (44) 272 0 R] /Limits [(4) (44)] >> endobj 1392 0 obj << /Names [(45) 277 0 R (46) 283 0 R (47) 288 0 R (48) 293 0 R (49) 297 0 R (5) 44 0 R] /Limits [(45) (5)] >> endobj 1393 0 obj << /Names [(50) 302 0 R (51) 306 0 R (52) 311 0 R (53) 316 0 R (54) 322 0 R (55) 328 0 R] /Limits [(50) (55)] >> endobj 1394 0 obj << /Names [(56) 332 0 R (57) 336 0 R (58) 340 0 R (59) 345 0 R (6) 52 0 R (60) 352 0 R] /Limits [(56) (60)] >> endobj 1395 0 obj << /Names [(61) 357 0 R (62) 363 0 R (63) 368 0 R (64) 375 0 R (65) 381 0 R (66) 386 0 R] /Limits [(61) (66)] >> endobj 1396 0 obj << /Names [(67) 390 0 R (68) 395 0 R (69) 401 0 R (7) 56 0 R (70) 405 0 R (71) 409 0 R] /Limits [(67) (71)] >> endobj 1397 0 obj << /Names [(72) 414 0 R (73) 418 0 R (74) 424 0 R (75) 430 0 R (76) 436 0 R (77) 441 0 R] /Limits [(72) (77)] >> endobj 1398 0 obj << /Names [(78) 447 0 R (79) 451 0 R (8) 64 0 R (80) 455 0 R (81) 460 0 R (82) 465 0 R] /Limits [(78) (82)] >> endobj 1399 0 obj << /Names [(83) 471 0 R (84) 477 0 R (85) 484 0 R (86) 488 0 R (87) 493 0 R (88) 497 0 R] /Limits [(83) (88)] >> endobj 1400 0 obj << /Names [(89) 502 0 R (9) 68 0 R (90) 508 0 R (91) 513 0 R (92) 518 0 R (93) 527 0 R] /Limits [(89) (93)] >> endobj 1401 0 obj << /Names [(94) 532 0 R (95) 536 0 R (96) 542 0 R (97) 608 0 R (98) 614 0 R (99) 715 0 R] /Limits [(94) (99)] >> endobj 1402 0 obj << /Names [(A word of warning) 425 0 R (ACLs) 324 0 R (Access control) 204 0 R (Adaptive locks) 519 0 R (Anonymous FTP example) 489 0 R (Automation) 426 0 R] /Limits [(A word of warning) (Automation)] >> endobj 1403 0 obj << /Names [(Building a distributed configuration) 78 0 R (Building flexible time classes) 113 0 R (CFINPUTS environment variable) 121 0 R (Cfengine network services) 369 0 R (Checksums and Tripwire functionality) 472 0 R (Classes basics) 141 0 R] /Limits [(Building a distributed configuration) (Classes basics)] >> endobj 1404 0 obj << /Names [(Command line classes) 179 0 R (Compressing logs) 323 0 R (Concept Index) 716 0 R (Configuration) 437 0 R (Configuration file cfservd.conf) 397 0 R (Configuring cfservd) 126 0 R] /Limits [(Command line classes) (Configuring cfservd)] >> endobj 1405 0 obj << /Names [(Control files) 30 0 R (Copying files) 261 0 R (Deadlocks and runaway loops) 127 0 R (Debugging tips) 203 0 R (Defensive garbage collection) 480 0 R (Defining classes) 178 0 R] /Limits [(Control files) (Defining classes)] >> endobj 1406 0 obj << /Names [(Disabling and replacing software) 442 0 R (Disabling and the file repository) 312 0 R (Editing files) 307 0 R (Emulating rdist) 40 0 R (FAQ Index) 878 0 R (Feedback classes) 191 0 R] /Limits [(Disabling and replacing software) (Feedback classes)] >> endobj 1407 0 obj << /Names [(File sweeps) 210 0 R (FileExtensions) 478 0 R (Files and links) 249 0 R (Firewalls) 528 0 R (Functionality) 47 0 R (General considerations) 243 0 R] /Limits [(File sweeps) (General considerations)] >> endobj 1408 0 obj << /Names [(Getting started) 57 0 R (Global configurations) 168 0 R (How does it work?) 278 0 R (How it works) 371 0 R (Installation of cfservd) 396 0 R (Invoking cfagent) 104 0 R] /Limits [(Getting started) (Invoking cfagent)] >> endobj 1409 0 obj << /Names [(Iterating over lists) 234 0 R (Key concepts) 29 0 R (Log files) 216 0 R (Making links) 45 0 R (Managing processes) 266 0 R (Miscellaneous security of cfengine itself) 503 0 R] /Limits [(Iterating over lists) (Miscellaneous security of cfengine itself)] >> endobj 1410 0 obj << /Names [(Monitoring files) 461 0 R (Monitoring important files) 39 0 R (More advanced concepts) 140 0 R (Mount example) 284 0 R (NFS filesystem resources) 267 0 R (NFS resources) 161 0 R] /Limits [(Monitoring files) (NFS resources)] >> endobj 1411 0 obj << /Names [(Name servers (DNS)) 38 0 R (Network File System (NFS)) 32 0 R (Network interface) 31 0 R (NonAlphaNumFiles) 479 0 R (Options) 99 0 R (Overview) 15 0 R] /Limits [(Name servers (DNS)) (Overview)] >> endobj 1412 0 obj << /Names [(Privacy (encryption)) 509 0 R (Process monitoring) 456 0 R (Program structure) 69 0 R (Quoted strings) 222 0 R (Race conditions in file copying) 521 0 R (Regular expressions) 224 0 R] /Limits [(Privacy (encryption)) (Regular expressions)] >> endobj 1413 0 obj << /Names [(Remote execution of cfagent) 376 0 R (Running cfengine permanently monitoring and restarting cfexecd) 105 0 R (Running user scripts) 317 0 R (Scheduling interval) 358 0 R (Security and cfengine) 419 0 R (Security in File sweeps) 215 0 R] /Limits [(Remote execution of cfagent) (Security in File sweeps)] >> endobj 1414 0 obj << /Names [(Site configuration) 24 0 R (Spamming and security) 364 0 R (Special variables) 279 0 R (Splaying host times) 353 0 R (Spoofing) 520 0 R (Startup cfservd.conf) 89 0 R] /Limits [(Site configuration) (Startup cfservd.conf)] >> endobj 1415 0 obj << /Names [(Startup update.conf) 79 0 R (Structuring cfagent.conf) 347 0 R (Summary) 537 0 R (Suspicious filenames) 467 0 R (The generic class any) 197 0 R (The setuid log) 466 0 R] /Limits [(Startup update.conf) (The setuid log)] >> endobj 1416 0 obj << /Names [(Trust) 431 0 R (Trust and key races) 514 0 R (Undefined variables) 177 0 R (Unique filesystem mountpoints) 268 0 R (Using cfengine as a front-end for cron) 125 0 R (Using netgroups) 244 0 R] /Limits [(Trust) (Using netgroups)] >> endobj 1417 0 obj << /Names [(Using the automounter) 298 0 R (Variable Index) 609 0 R (Variable substitution) 155 0 R (WWW security) 498 0 R (What is cfengine?) 17 0 R (What is security?) 420 0 R] /Limits [(Using the automounter) (What is security?)] >> endobj 1418 0 obj << /Names [(What services?) 370 0 R (What to aim for) 122 0 R (What you must have) 58 0 R (Where should I put the files?) 94 0 R (Why trust cfengine?) 432 0 R (Wildcards in directory names) 205 0 R] /Limits [(What services?) (Wildcards in directory names)] >> endobj 1419 0 obj << /Names [(Writing plugin modules) 192 0 R (actionsequence classes) 184 0 R (cfservd protocol) 391 0 R (shellcommand classes) 185 0 R (size= in copy) 522 0 R (useshell= and owner= in shellcommands) 523 0 R] /Limits [(Writing plugin modules) (useshell= and owner= in shellcommands)] >> endobj 1420 0 obj << /Kids [1384 0 R 1385 0 R 1386 0 R 1387 0 R 1388 0 R 1389 0 R] /Limits [(-1) (33)] >> endobj 1421 0 obj << /Kids [1390 0 R 1391 0 R 1392 0 R 1393 0 R 1394 0 R 1395 0 R] /Limits [(34) (66)] >> endobj 1422 0 obj << /Kids [1396 0 R 1397 0 R 1398 0 R 1399 0 R 1400 0 R 1401 0 R] /Limits [(67) (99)] >> endobj 1423 0 obj << /Kids [1402 0 R 1403 0 R 1404 0 R 1405 0 R 1406 0 R 1407 0 R] /Limits [(A word of warning) (General considerations)] >> endobj 1424 0 obj << /Kids [1408 0 R 1409 0 R 1410 0 R 1411 0 R 1412 0 R 1413 0 R] /Limits [(Getting started) (Security in File sweeps)] >> endobj 1425 0 obj << /Kids [1414 0 R 1415 0 R 1416 0 R 1417 0 R 1418 0 R 1419 0 R] /Limits [(Site configuration) (useshell= and owner= in shellcommands)] >> endobj 1426 0 obj << /Kids [1420 0 R 1421 0 R 1422 0 R 1423 0 R 1424 0 R 1425 0 R] /Limits [(-1) (useshell= and owner= in shellcommands)] >> endobj 1427 0 obj << /Dests 1426 0 R >> endobj 1428 0 obj << /Type /Catalog /Pages 1382 0 R /Outlines 1383 0 R /Names 1427 0 R /PageMode /UseOutlines >> endobj 1429 0 obj << /Producer (pdfTeX-1.40.3) /Creator (TeX) /CreationDate (D:20090411220154+02'00') /ModDate (D:20090411220154+02'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX using libpoppler, Version 3.141592-1.40.3-2.2 (Web2C 7.5.6) kpathsea version 3.5.6) >> endobj xref 0 1430 0000000000 65535 f 0000000509 00000 n 0000000405 00000 n 0000000015 00000 n 0000471166 00000 n 0000471457 00000 n 0000473194 00000 n 0000001079 00000 n 0000000975 00000 n 0000000588 00000 n 0000472179 00000 n 0000004226 00000 n 0000003962 00000 n 0000001159 00000 n 0000004069 00000 n 0000004120 00000 n 0000472323 00000 n 0000004171 00000 n 0000471022 00000 n 0000472612 00000 n 0000007994 00000 n 0000007781 00000 n 0000004342 00000 n 0000007888 00000 n 0000007939 00000 n 0000011544 00000 n 0000011166 00000 n 0000008098 00000 n 0000011273 00000 n 0000011324 00000 n 0000011379 00000 n 0000011434 00000 n 0000011489 00000 n 0000015281 00000 n 0000015587 00000 n 0000015155 00000 n 0000011648 00000 n 0000015426 00000 n 0000015477 00000 n 0000015532 00000 n 0000171119 00000 n 0000018772 00000 n 0000018503 00000 n 0000015703 00000 n 0000018611 00000 n 0000018662 00000 n 0000472903 00000 n 0000018717 00000 n 0000473302 00000 n 0000019851 00000 n 0000019692 00000 n 0000018900 00000 n 0000019800 00000 n 0000023040 00000 n 0000022775 00000 n 0000019944 00000 n 0000022883 00000 n 0000022934 00000 n 0000022985 00000 n 0000472032 00000 n 0000471887 00000 n 0000025550 00000 n 0000025391 00000 n 0000023192 00000 n 0000025499 00000 n 0000028364 00000 n 0000028150 00000 n 0000025667 00000 n 0000028258 00000 n 0000028309 00000 n 0000029427 00000 n 0000029268 00000 n 0000028492 00000 n 0000029376 00000 n 0000031392 00000 n 0000031123 00000 n 0000029520 00000 n 0000031231 00000 n 0000031282 00000 n 0000031337 00000 n 0000473413 00000 n 0000032568 00000 n 0000032409 00000 n 0000031520 00000 n 0000032517 00000 n 0000034052 00000 n 0000033838 00000 n 0000032649 00000 n 0000033946 00000 n 0000033997 00000 n 0000036419 00000 n 0000036205 00000 n 0000034144 00000 n 0000036313 00000 n 0000036364 00000 n 0000039065 00000 n 0000038851 00000 n 0000036535 00000 n 0000038959 00000 n 0000039010 00000 n 0000041861 00000 n 0000041584 00000 n 0000039169 00000 n 0000041695 00000 n 0000041748 00000 n 0000041805 00000 n 0000044630 00000 n 0000044995 00000 n 0000044490 00000 n 0000041966 00000 n 0000044942 00000 n 0000044786 00000 n 0000473525 00000 n 0000163576 00000 n 0000048701 00000 n 0000049029 00000 n 0000049319 00000 n 0000049639 00000 n 0000048537 00000 n 0000045112 00000 n 0000049476 00000 n 0000049529 00000 n 0000049582 00000 n 0000048865 00000 n 0000049174 00000 n 0000160771 00000 n 0000186540 00000 n 0000183867 00000 n 0000050282 00000 n 0000050117 00000 n 0000049756 00000 n 0000050229 00000 n 0000050721 00000 n 0000050556 00000 n 0000050352 00000 n 0000050668 00000 n 0000053923 00000 n 0000053648 00000 n 0000050791 00000 n 0000053760 00000 n 0000053813 00000 n 0000053866 00000 n 0000056961 00000 n 0000056796 00000 n 0000054064 00000 n 0000056908 00000 n 0000059912 00000 n 0000059747 00000 n 0000057079 00000 n 0000059859 00000 n 0000473643 00000 n 0000062329 00000 n 0000062107 00000 n 0000060030 00000 n 0000062219 00000 n 0000062272 00000 n 0000064547 00000 n 0000064743 00000 n 0000064415 00000 n 0000062446 00000 n 0000064690 00000 n 0000115911 00000 n 0000067500 00000 n 0000067705 00000 n 0000067368 00000 n 0000064861 00000 n 0000067652 00000 n 0000473047 00000 n 0000102949 00000 n 0000069782 00000 n 0000069617 00000 n 0000067825 00000 n 0000069729 00000 n 0000072319 00000 n 0000071987 00000 n 0000069900 00000 n 0000072099 00000 n 0000072152 00000 n 0000072205 00000 n 0000072262 00000 n 0000075273 00000 n 0000074995 00000 n 0000072448 00000 n 0000075107 00000 n 0000075160 00000 n 0000075217 00000 n 0000473761 00000 n 0000078458 00000 n 0000078179 00000 n 0000075416 00000 n 0000078291 00000 n 0000078344 00000 n 0000078401 00000 n 0000080504 00000 n 0000080282 00000 n 0000078575 00000 n 0000080394 00000 n 0000080447 00000 n 0000472757 00000 n 0000083258 00000 n 0000082923 00000 n 0000080646 00000 n 0000083035 00000 n 0000083088 00000 n 0000083144 00000 n 0000083201 00000 n 0000086548 00000 n 0000086326 00000 n 0000083387 00000 n 0000086438 00000 n 0000086491 00000 n 0000089405 00000 n 0000089126 00000 n 0000086665 00000 n 0000089238 00000 n 0000089291 00000 n 0000089348 00000 n 0000092125 00000 n 0000092586 00000 n 0000091985 00000 n 0000089522 00000 n 0000092419 00000 n 0000092472 00000 n 0000092272 00000 n 0000092529 00000 n 0000473879 00000 n 0000095629 00000 n 0000095464 00000 n 0000092703 00000 n 0000095576 00000 n 0000097866 00000 n 0000097644 00000 n 0000095735 00000 n 0000097756 00000 n 0000097809 00000 n 0000099957 00000 n 0000099792 00000 n 0000097983 00000 n 0000099904 00000 n 0000103116 00000 n 0000102784 00000 n 0000100075 00000 n 0000102896 00000 n 0000103002 00000 n 0000103059 00000 n 0000106408 00000 n 0000106186 00000 n 0000103233 00000 n 0000106298 00000 n 0000106351 00000 n 0000109690 00000 n 0000109525 00000 n 0000106525 00000 n 0000109637 00000 n 0000471600 00000 n 0000471743 00000 n 0000473997 00000 n 0000112455 00000 n 0000112234 00000 n 0000109820 00000 n 0000112346 00000 n 0000112399 00000 n 0000116082 00000 n 0000115693 00000 n 0000112596 00000 n 0000115805 00000 n 0000115858 00000 n 0000115968 00000 n 0000116025 00000 n 0000119455 00000 n 0000119290 00000 n 0000116187 00000 n 0000119402 00000 n 0000121870 00000 n 0000122193 00000 n 0000121738 00000 n 0000119585 00000 n 0000122030 00000 n 0000122083 00000 n 0000122136 00000 n 0000124591 00000 n 0000124369 00000 n 0000122298 00000 n 0000124481 00000 n 0000124534 00000 n 0000127072 00000 n 0000126907 00000 n 0000124708 00000 n 0000127019 00000 n 0000474115 00000 n 0000128631 00000 n 0000128466 00000 n 0000127166 00000 n 0000128578 00000 n 0000132327 00000 n 0000132105 00000 n 0000128725 00000 n 0000132217 00000 n 0000132270 00000 n 0000135641 00000 n 0000135476 00000 n 0000132444 00000 n 0000135588 00000 n 0000138388 00000 n 0000138166 00000 n 0000135759 00000 n 0000138278 00000 n 0000138331 00000 n 0000141457 00000 n 0000141235 00000 n 0000138505 00000 n 0000141347 00000 n 0000141400 00000 n 0000144825 00000 n 0000144603 00000 n 0000141586 00000 n 0000144715 00000 n 0000144768 00000 n 0000474233 00000 n 0000147635 00000 n 0000147358 00000 n 0000144954 00000 n 0000147470 00000 n 0000147523 00000 n 0000147579 00000 n 0000150702 00000 n 0000150537 00000 n 0000147764 00000 n 0000150649 00000 n 0000152850 00000 n 0000152685 00000 n 0000150808 00000 n 0000152797 00000 n 0000155275 00000 n 0000155110 00000 n 0000152956 00000 n 0000155222 00000 n 0000157546 00000 n 0000157381 00000 n 0000155369 00000 n 0000157493 00000 n 0000160405 00000 n 0000160881 00000 n 0000160265 00000 n 0000157640 00000 n 0000160718 00000 n 0000160562 00000 n 0000160824 00000 n 0000474351 00000 n 0000163633 00000 n 0000163354 00000 n 0000161024 00000 n 0000163466 00000 n 0000163519 00000 n 0000166836 00000 n 0000166614 00000 n 0000163762 00000 n 0000166726 00000 n 0000166779 00000 n 0000167805 00000 n 0000168005 00000 n 0000167673 00000 n 0000166965 00000 n 0000167952 00000 n 0000178196 00000 n 0000171175 00000 n 0000170787 00000 n 0000168087 00000 n 0000170899 00000 n 0000170952 00000 n 0000171005 00000 n 0000171062 00000 n 0000174709 00000 n 0000174487 00000 n 0000171268 00000 n 0000174599 00000 n 0000174652 00000 n 0000177996 00000 n 0000178253 00000 n 0000177864 00000 n 0000174838 00000 n 0000178143 00000 n 0000474469 00000 n 0000180479 00000 n 0000180314 00000 n 0000178406 00000 n 0000180426 00000 n 0000183924 00000 n 0000183645 00000 n 0000180611 00000 n 0000183757 00000 n 0000183810 00000 n 0000186710 00000 n 0000186375 00000 n 0000184017 00000 n 0000186487 00000 n 0000186597 00000 n 0000186653 00000 n 0000188092 00000 n 0000187927 00000 n 0000186815 00000 n 0000188039 00000 n 0000189848 00000 n 0000189683 00000 n 0000188186 00000 n 0000189795 00000 n 0000191495 00000 n 0000191330 00000 n 0000189956 00000 n 0000191442 00000 n 0000474587 00000 n 0000193081 00000 n 0000192916 00000 n 0000191589 00000 n 0000193028 00000 n 0000196961 00000 n 0000196686 00000 n 0000193199 00000 n 0000196798 00000 n 0000196851 00000 n 0000196904 00000 n 0000200500 00000 n 0000200221 00000 n 0000197042 00000 n 0000200333 00000 n 0000200386 00000 n 0000200443 00000 n 0000204107 00000 n 0000203828 00000 n 0000200581 00000 n 0000203940 00000 n 0000203993 00000 n 0000204050 00000 n 0000206994 00000 n 0000206772 00000 n 0000204188 00000 n 0000206884 00000 n 0000206937 00000 n 0000209214 00000 n 0000208996 00000 n 0000207087 00000 n 0000209108 00000 n 0000209161 00000 n 0000474705 00000 n 0000211188 00000 n 0000211023 00000 n 0000209307 00000 n 0000211135 00000 n 0000212495 00000 n 0000212330 00000 n 0000211270 00000 n 0000212442 00000 n 0000214219 00000 n 0000213997 00000 n 0000212577 00000 n 0000214109 00000 n 0000214162 00000 n 0000216094 00000 n 0000215872 00000 n 0000214312 00000 n 0000215984 00000 n 0000216037 00000 n 0000218166 00000 n 0000217888 00000 n 0000216187 00000 n 0000218000 00000 n 0000218053 00000 n 0000218110 00000 n 0000220540 00000 n 0000220318 00000 n 0000218259 00000 n 0000220430 00000 n 0000220483 00000 n 0000474823 00000 n 0000223626 00000 n 0000223290 00000 n 0000220645 00000 n 0000223402 00000 n 0000223455 00000 n 0000223512 00000 n 0000223569 00000 n 0000225544 00000 n 0000225379 00000 n 0000223719 00000 n 0000225491 00000 n 0000228304 00000 n 0000228082 00000 n 0000225638 00000 n 0000228194 00000 n 0000228247 00000 n 0000229481 00000 n 0000229316 00000 n 0000228409 00000 n 0000229428 00000 n 0000231184 00000 n 0000230962 00000 n 0000229563 00000 n 0000231074 00000 n 0000231127 00000 n 0000233265 00000 n 0000233044 00000 n 0000231277 00000 n 0000233156 00000 n 0000233209 00000 n 0000474941 00000 n 0000236428 00000 n 0000236206 00000 n 0000233347 00000 n 0000236318 00000 n 0000236371 00000 n 0000239828 00000 n 0000239606 00000 n 0000236521 00000 n 0000239718 00000 n 0000239771 00000 n 0000243175 00000 n 0000242729 00000 n 0000239945 00000 n 0000242841 00000 n 0000242894 00000 n 0000242951 00000 n 0000243008 00000 n 0000243065 00000 n 0000243118 00000 n 0000244438 00000 n 0000244216 00000 n 0000243256 00000 n 0000244328 00000 n 0000244381 00000 n 0000244900 00000 n 0000244735 00000 n 0000244531 00000 n 0000244847 00000 n 0000246082 00000 n 0000245864 00000 n 0000244970 00000 n 0000245976 00000 n 0000246029 00000 n 0000475059 00000 n 0000246532 00000 n 0000246367 00000 n 0000246163 00000 n 0000246479 00000 n 0000250130 00000 n 0000250263 00000 n 0000250396 00000 n 0000250529 00000 n 0000250662 00000 n 0000250795 00000 n 0000250928 00000 n 0000251061 00000 n 0000251193 00000 n 0000251326 00000 n 0000251458 00000 n 0000251591 00000 n 0000251724 00000 n 0000251857 00000 n 0000251990 00000 n 0000252122 00000 n 0000252255 00000 n 0000252388 00000 n 0000252521 00000 n 0000252654 00000 n 0000252787 00000 n 0000252920 00000 n 0000253053 00000 n 0000253186 00000 n 0000253319 00000 n 0000253452 00000 n 0000253585 00000 n 0000253717 00000 n 0000253849 00000 n 0000253982 00000 n 0000254115 00000 n 0000254248 00000 n 0000254381 00000 n 0000254513 00000 n 0000254646 00000 n 0000254778 00000 n 0000254909 00000 n 0000255039 00000 n 0000255168 00000 n 0000255297 00000 n 0000255430 00000 n 0000255563 00000 n 0000255692 00000 n 0000255821 00000 n 0000255950 00000 n 0000256079 00000 n 0000256207 00000 n 0000256336 00000 n 0000256464 00000 n 0000256593 00000 n 0000256722 00000 n 0000256851 00000 n 0000256978 00000 n 0000257104 00000 n 0000257231 00000 n 0000257359 00000 n 0000257488 00000 n 0000257617 00000 n 0000257744 00000 n 0000257874 00000 n 0000258000 00000 n 0000258126 00000 n 0000258362 00000 n 0000249510 00000 n 0000246602 00000 n 0000258256 00000 n 0000258309 00000 n 0000472468 00000 n 0000258862 00000 n 0000258697 00000 n 0000258493 00000 n 0000258809 00000 n 0000264561 00000 n 0000264694 00000 n 0000264827 00000 n 0000264960 00000 n 0000265092 00000 n 0000265225 00000 n 0000265358 00000 n 0000265491 00000 n 0000265624 00000 n 0000265757 00000 n 0000265890 00000 n 0000266023 00000 n 0000266156 00000 n 0000266289 00000 n 0000266421 00000 n 0000266554 00000 n 0000266687 00000 n 0000266820 00000 n 0000266953 00000 n 0000267086 00000 n 0000267218 00000 n 0000267351 00000 n 0000267484 00000 n 0000267616 00000 n 0000267749 00000 n 0000267882 00000 n 0000268014 00000 n 0000268145 00000 n 0000268278 00000 n 0000268411 00000 n 0000268544 00000 n 0000268676 00000 n 0000268809 00000 n 0000268942 00000 n 0000269075 00000 n 0000269208 00000 n 0000269340 00000 n 0000269471 00000 n 0000269600 00000 n 0000269729 00000 n 0000269861 00000 n 0000269989 00000 n 0000270118 00000 n 0000270247 00000 n 0000270374 00000 n 0000270503 00000 n 0000270635 00000 n 0000270764 00000 n 0000270893 00000 n 0000271022 00000 n 0000271151 00000 n 0000271280 00000 n 0000271411 00000 n 0000271538 00000 n 0000271667 00000 n 0000271796 00000 n 0000271925 00000 n 0000272053 00000 n 0000272186 00000 n 0000272315 00000 n 0000272443 00000 n 0000272572 00000 n 0000272701 00000 n 0000272830 00000 n 0000272959 00000 n 0000273088 00000 n 0000273217 00000 n 0000273346 00000 n 0000273474 00000 n 0000273603 00000 n 0000273730 00000 n 0000273858 00000 n 0000273987 00000 n 0000274116 00000 n 0000274245 00000 n 0000274374 00000 n 0000274503 00000 n 0000274630 00000 n 0000274759 00000 n 0000274888 00000 n 0000275017 00000 n 0000275146 00000 n 0000275275 00000 n 0000275403 00000 n 0000275532 00000 n 0000275661 00000 n 0000275787 00000 n 0000281722 00000 n 0000281855 00000 n 0000281988 00000 n 0000282121 00000 n 0000282253 00000 n 0000282386 00000 n 0000282516 00000 n 0000282649 00000 n 0000282782 00000 n 0000282915 00000 n 0000276019 00000 n 0000263741 00000 n 0000258932 00000 n 0000275913 00000 n 0000275966 00000 n 0000283048 00000 n 0000283181 00000 n 0000283313 00000 n 0000283445 00000 n 0000283577 00000 n 0000283710 00000 n 0000283843 00000 n 0000283975 00000 n 0000284107 00000 n 0000284240 00000 n 0000284373 00000 n 0000284506 00000 n 0000284638 00000 n 0000284771 00000 n 0000284903 00000 n 0000285033 00000 n 0000285166 00000 n 0000285299 00000 n 0000285432 00000 n 0000285565 00000 n 0000285697 00000 n 0000285830 00000 n 0000285962 00000 n 0000286095 00000 n 0000286228 00000 n 0000286361 00000 n 0000286494 00000 n 0000286627 00000 n 0000286760 00000 n 0000286892 00000 n 0000287023 00000 n 0000287153 00000 n 0000287282 00000 n 0000287410 00000 n 0000287539 00000 n 0000287668 00000 n 0000287797 00000 n 0000287926 00000 n 0000288055 00000 n 0000288184 00000 n 0000288313 00000 n 0000288442 00000 n 0000288571 00000 n 0000288700 00000 n 0000288829 00000 n 0000288957 00000 n 0000289086 00000 n 0000289215 00000 n 0000289344 00000 n 0000289472 00000 n 0000289601 00000 n 0000289729 00000 n 0000289858 00000 n 0000289987 00000 n 0000290116 00000 n 0000290244 00000 n 0000290372 00000 n 0000290500 00000 n 0000290629 00000 n 0000290758 00000 n 0000290887 00000 n 0000291015 00000 n 0000291144 00000 n 0000291273 00000 n 0000291401 00000 n 0000291530 00000 n 0000291657 00000 n 0000291786 00000 n 0000291915 00000 n 0000292044 00000 n 0000292173 00000 n 0000292301 00000 n 0000292428 00000 n 0000292553 00000 n 0000292675 00000 n 0000296852 00000 n 0000296984 00000 n 0000297116 00000 n 0000292853 00000 n 0000280918 00000 n 0000276137 00000 n 0000292800 00000 n 0000297249 00000 n 0000297382 00000 n 0000297515 00000 n 0000297646 00000 n 0000297779 00000 n 0000297912 00000 n 0000298045 00000 n 0000298178 00000 n 0000298311 00000 n 0000298444 00000 n 0000298574 00000 n 0000298707 00000 n 0000298840 00000 n 0000298973 00000 n 0000299106 00000 n 0000299238 00000 n 0000299371 00000 n 0000299504 00000 n 0000299637 00000 n 0000299770 00000 n 0000299903 00000 n 0000300036 00000 n 0000300168 00000 n 0000300301 00000 n 0000300434 00000 n 0000300567 00000 n 0000300700 00000 n 0000300833 00000 n 0000300966 00000 n 0000301098 00000 n 0000301227 00000 n 0000301356 00000 n 0000301485 00000 n 0000301614 00000 n 0000301743 00000 n 0000301872 00000 n 0000302001 00000 n 0000302130 00000 n 0000302259 00000 n 0000302388 00000 n 0000302517 00000 n 0000302646 00000 n 0000302773 00000 n 0000302902 00000 n 0000303031 00000 n 0000303159 00000 n 0000303288 00000 n 0000303417 00000 n 0000303546 00000 n 0000303675 00000 n 0000303803 00000 n 0000303932 00000 n 0000304061 00000 n 0000304242 00000 n 0000296280 00000 n 0000292971 00000 n 0000304189 00000 n 0000475177 00000 n 0000304730 00000 n 0000304565 00000 n 0000304360 00000 n 0000304677 00000 n 0000306446 00000 n 0000306579 00000 n 0000306712 00000 n 0000306845 00000 n 0000306978 00000 n 0000307111 00000 n 0000307244 00000 n 0000307377 00000 n 0000307506 00000 n 0000307635 00000 n 0000307764 00000 n 0000307893 00000 n 0000308022 00000 n 0000308257 00000 n 0000306218 00000 n 0000304800 00000 n 0000308151 00000 n 0000308204 00000 n 0000308745 00000 n 0000308580 00000 n 0000308375 00000 n 0000308692 00000 n 0000311982 00000 n 0000312109 00000 n 0000312237 00000 n 0000312365 00000 n 0000312493 00000 n 0000312621 00000 n 0000312749 00000 n 0000312877 00000 n 0000313005 00000 n 0000313133 00000 n 0000313260 00000 n 0000313387 00000 n 0000313514 00000 n 0000313641 00000 n 0000313769 00000 n 0000313898 00000 n 0000314027 00000 n 0000314156 00000 n 0000314284 00000 n 0000314413 00000 n 0000314542 00000 n 0000314671 00000 n 0000314800 00000 n 0000314929 00000 n 0000315058 00000 n 0000315187 00000 n 0000315316 00000 n 0000315445 00000 n 0000315574 00000 n 0000315703 00000 n 0000315830 00000 n 0000315958 00000 n 0000316087 00000 n 0000316216 00000 n 0000316345 00000 n 0000316473 00000 n 0000316601 00000 n 0000316730 00000 n 0000316858 00000 n 0000320188 00000 n 0000320317 00000 n 0000317038 00000 n 0000311546 00000 n 0000308815 00000 n 0000316985 00000 n 0000471310 00000 n 0000320446 00000 n 0000320575 00000 n 0000320704 00000 n 0000320833 00000 n 0000320962 00000 n 0000321090 00000 n 0000321218 00000 n 0000321346 00000 n 0000321475 00000 n 0000321604 00000 n 0000321733 00000 n 0000321861 00000 n 0000321990 00000 n 0000322119 00000 n 0000322248 00000 n 0000322377 00000 n 0000322506 00000 n 0000322635 00000 n 0000322764 00000 n 0000322893 00000 n 0000323020 00000 n 0000323149 00000 n 0000323278 00000 n 0000323407 00000 n 0000323535 00000 n 0000323663 00000 n 0000323792 00000 n 0000323920 00000 n 0000324048 00000 n 0000324177 00000 n 0000324306 00000 n 0000324435 00000 n 0000324563 00000 n 0000324692 00000 n 0000324821 00000 n 0000324950 00000 n 0000327700 00000 n 0000327825 00000 n 0000327954 00000 n 0000328083 00000 n 0000328212 00000 n 0000328341 00000 n 0000328470 00000 n 0000325132 00000 n 0000319760 00000 n 0000317156 00000 n 0000325079 00000 n 0000328599 00000 n 0000328728 00000 n 0000328857 00000 n 0000328986 00000 n 0000329115 00000 n 0000329244 00000 n 0000329372 00000 n 0000329501 00000 n 0000329630 00000 n 0000329759 00000 n 0000329888 00000 n 0000330017 00000 n 0000330146 00000 n 0000330275 00000 n 0000330404 00000 n 0000330533 00000 n 0000330661 00000 n 0000330789 00000 n 0000330918 00000 n 0000331047 00000 n 0000331176 00000 n 0000331305 00000 n 0000331434 00000 n 0000331563 00000 n 0000331748 00000 n 0000327324 00000 n 0000325238 00000 n 0000331693 00000 n 0000475295 00000 n 0000332229 00000 n 0000332058 00000 n 0000331855 00000 n 0000332174 00000 n 0000332300 00000 n 0000486676 00000 n 0000332347 00000 n 0000332376 00000 n 0000486592 00000 n 0000332432 00000 n 0000332489 00000 n 0000486493 00000 n 0000332546 00000 n 0000332585 00000 n 0000486353 00000 n 0000332636 00000 n 0000332669 00000 n 0000486269 00000 n 0000332721 00000 n 0000332776 00000 n 0000486170 00000 n 0000332832 00000 n 0000332870 00000 n 0000486071 00000 n 0000332934 00000 n 0000333002 00000 n 0000485972 00000 n 0000333059 00000 n 0000333098 00000 n 0000485873 00000 n 0000333163 00000 n 0000333210 00000 n 0000485789 00000 n 0000333261 00000 n 0000333294 00000 n 0000485705 00000 n 0000333346 00000 n 0000333380 00000 n 0000485565 00000 n 0000333434 00000 n 0000333470 00000 n 0000485481 00000 n 0000333527 00000 n 0000333587 00000 n 0000485382 00000 n 0000333643 00000 n 0000333681 00000 n 0000485242 00000 n 0000333756 00000 n 0000333813 00000 n 0000485158 00000 n 0000333871 00000 n 0000333911 00000 n 0000485059 00000 n 0000333970 00000 n 0000334011 00000 n 0000484975 00000 n 0000334079 00000 n 0000334129 00000 n 0000484876 00000 n 0000334175 00000 n 0000334224 00000 n 0000484777 00000 n 0000334279 00000 n 0000334316 00000 n 0000484678 00000 n 0000334417 00000 n 0000334501 00000 n 0000484579 00000 n 0000334569 00000 n 0000334619 00000 n 0000484495 00000 n 0000334673 00000 n 0000334709 00000 n 0000484354 00000 n 0000334770 00000 n 0000334813 00000 n 0000484270 00000 n 0000334866 00000 n 0000334894 00000 n 0000484171 00000 n 0000334954 00000 n 0000334996 00000 n 0000484072 00000 n 0000335054 00000 n 0000335094 00000 n 0000483932 00000 n 0000335149 00000 n 0000335208 00000 n 0000483848 00000 n 0000335267 00000 n 0000335308 00000 n 0000483749 00000 n 0000335369 00000 n 0000335412 00000 n 0000483650 00000 n 0000335471 00000 n 0000335512 00000 n 0000483551 00000 n 0000335567 00000 n 0000335604 00000 n 0000483467 00000 n 0000335665 00000 n 0000335708 00000 n 0000483368 00000 n 0000335768 00000 n 0000335810 00000 n 0000483269 00000 n 0000335863 00000 n 0000335898 00000 n 0000483170 00000 n 0000335951 00000 n 0000335986 00000 n 0000483071 00000 n 0000336053 00000 n 0000336102 00000 n 0000482972 00000 n 0000336152 00000 n 0000336215 00000 n 0000482873 00000 n 0000336277 00000 n 0000336331 00000 n 0000482774 00000 n 0000336379 00000 n 0000336428 00000 n 0000482675 00000 n 0000336481 00000 n 0000336516 00000 n 0000482576 00000 n 0000336574 00000 n 0000336614 00000 n 0000482492 00000 n 0000336673 00000 n 0000336714 00000 n 0000482351 00000 n 0000336774 00000 n 0000336834 00000 n 0000482267 00000 n 0000336895 00000 n 0000336938 00000 n 0000482168 00000 n 0000336992 00000 n 0000337028 00000 n 0000482069 00000 n 0000337082 00000 n 0000337118 00000 n 0000481970 00000 n 0000337170 00000 n 0000337204 00000 n 0000481871 00000 n 0000337261 00000 n 0000337300 00000 n 0000481731 00000 n 0000337352 00000 n 0000337417 00000 n 0000481647 00000 n 0000337480 00000 n 0000337525 00000 n 0000481548 00000 n 0000337593 00000 n 0000337643 00000 n 0000481449 00000 n 0000337699 00000 n 0000337737 00000 n 0000481350 00000 n 0000337793 00000 n 0000337831 00000 n 0000481266 00000 n 0000337883 00000 n 0000337943 00000 n 0000481167 00000 n 0000338003 00000 n 0000338045 00000 n 0000481068 00000 n 0000338097 00000 n 0000338131 00000 n 0000480969 00000 n 0000338203 00000 n 0000338257 00000 n 0000480870 00000 n 0000338316 00000 n 0000338357 00000 n 0000480771 00000 n 0000338412 00000 n 0000338458 00000 n 0000480687 00000 n 0000338501 00000 n 0000338535 00000 n 0000480547 00000 n 0000338612 00000 n 0000338671 00000 n 0000480463 00000 n 0000338734 00000 n 0000338779 00000 n 0000480364 00000 n 0000338837 00000 n 0000338877 00000 n 0000480265 00000 n 0000338946 00000 n 0000338997 00000 n 0000480181 00000 n 0000339055 00000 n 0000339106 00000 n 0000480041 00000 n 0000339170 00000 n 0000339220 00000 n 0000479957 00000 n 0000339273 00000 n 0000339319 00000 n 0000479817 00000 n 0000339370 00000 n 0000339403 00000 n 0000479733 00000 n 0000339457 00000 n 0000339502 00000 n 0000479634 00000 n 0000339568 00000 n 0000339616 00000 n 0000479535 00000 n 0000339676 00000 n 0000339718 00000 n 0000479436 00000 n 0000339773 00000 n 0000339829 00000 n 0000479352 00000 n 0000339895 00000 n 0000339943 00000 n 0000479227 00000 n 0000340001 00000 n 0000340041 00000 n 0000479143 00000 n 0000340103 00000 n 0000340147 00000 n 0000479059 00000 n 0000340217 00000 n 0000340269 00000 n 0000478918 00000 n 0000340329 00000 n 0000340371 00000 n 0000478834 00000 n 0000340427 00000 n 0000340465 00000 n 0000478735 00000 n 0000340521 00000 n 0000340559 00000 n 0000478636 00000 n 0000340608 00000 n 0000340639 00000 n 0000478537 00000 n 0000340683 00000 n 0000340709 00000 n 0000478438 00000 n 0000340767 00000 n 0000340807 00000 n 0000478339 00000 n 0000340859 00000 n 0000340893 00000 n 0000478240 00000 n 0000340964 00000 n 0000341017 00000 n 0000478141 00000 n 0000341074 00000 n 0000341113 00000 n 0000478042 00000 n 0000341168 00000 n 0000341205 00000 n 0000477943 00000 n 0000341258 00000 n 0000341293 00000 n 0000477844 00000 n 0000341352 00000 n 0000341393 00000 n 0000477745 00000 n 0000341468 00000 n 0000341525 00000 n 0000477646 00000 n 0000341578 00000 n 0000341613 00000 n 0000477547 00000 n 0000341668 00000 n 0000341705 00000 n 0000477448 00000 n 0000341772 00000 n 0000341821 00000 n 0000477349 00000 n 0000341881 00000 n 0000341923 00000 n 0000477250 00000 n 0000341974 00000 n 0000342007 00000 n 0000477151 00000 n 0000342087 00000 n 0000342149 00000 n 0000477052 00000 n 0000342208 00000 n 0000342249 00000 n 0000476953 00000 n 0000342307 00000 n 0000342347 00000 n 0000476854 00000 n 0000342400 00000 n 0000342435 00000 n 0000476755 00000 n 0000342482 00000 n 0000342511 00000 n 0000476656 00000 n 0000342581 00000 n 0000342633 00000 n 0000476557 00000 n 0000342685 00000 n 0000342719 00000 n 0000476458 00000 n 0000342795 00000 n 0000342853 00000 n 0000476374 00000 n 0000342901 00000 n 0000342931 00000 n 0000476275 00000 n 0000342977 00000 n 0000343005 00000 n 0000476176 00000 n 0000343058 00000 n 0000343093 00000 n 0000476077 00000 n 0000343145 00000 n 0000343179 00000 n 0000475993 00000 n 0000343227 00000 n 0000343257 00000 n 0000343283 00000 n 0000343309 00000 n 0000343969 00000 n 0000344013 00000 n 0000344561 00000 n 0000344601 00000 n 0000345036 00000 n 0000345364 00000 n 0000345760 00000 n 0000346156 00000 n 0000346782 00000 n 0000347458 00000 n 0000347491 00000 n 0000348124 00000 n 0000348766 00000 n 0000355853 00000 n 0000356155 00000 n 0000368993 00000 n 0000369463 00000 n 0000371088 00000 n 0000371320 00000 n 0000388100 00000 n 0000388666 00000 n 0000390871 00000 n 0000391108 00000 n 0000404923 00000 n 0000405394 00000 n 0000410472 00000 n 0000410740 00000 n 0000418258 00000 n 0000418574 00000 n 0000419934 00000 n 0000420176 00000 n 0000431312 00000 n 0000431699 00000 n 0000433327 00000 n 0000433555 00000 n 0000449723 00000 n 0000450356 00000 n 0000452595 00000 n 0000452828 00000 n 0000468279 00000 n 0000468923 00000 n 0000470790 00000 n 0000475384 00000 n 0000475500 00000 n 0000475620 00000 n 0000475740 00000 n 0000475820 00000 n 0000475912 00000 n 0000486801 00000 n 0000486931 00000 n 0000487067 00000 n 0000487194 00000 n 0000487323 00000 n 0000487454 00000 n 0000487583 00000 n 0000487714 00000 n 0000487842 00000 n 0000487970 00000 n 0000488101 00000 n 0000488230 00000 n 0000488361 00000 n 0000488490 00000 n 0000488621 00000 n 0000488750 00000 n 0000488881 00000 n 0000489010 00000 n 0000489141 00000 n 0000489363 00000 n 0000489697 00000 n 0000489963 00000 n 0000490217 00000 n 0000490497 00000 n 0000490728 00000 n 0000490977 00000 n 0000491263 00000 n 0000491520 00000 n 0000491747 00000 n 0000492019 00000 n 0000492356 00000 n 0000492610 00000 n 0000492862 00000 n 0000493122 00000 n 0000493376 00000 n 0000493654 00000 n 0000493958 00000 n 0000494064 00000 n 0000494170 00000 n 0000494276 00000 n 0000494417 00000 n 0000494557 00000 n 0000494714 00000 n 0000494855 00000 n 0000494895 00000 n 0000495008 00000 n trailer << /Size 1430 /Root 1428 0 R /Info 1429 0 R /ID [ ] >> startxref 495281 %%EOF cfengine-2.2.10/doc/cfshow.80000644000175000001440000000314010673271351012421 00000000000000.TH cfengine 8 "Maintenance Commands" HiOslo .SH NAME cfshow \- Dump cfengine databases .SH SYNOPSIS /usr/local/sbin/cfshow [options] .SH DESCRIPTION .B cfengine is a language based system specifically designed for testing and configuring unix\-like systems attached to a TCP/IP network. .PP cfshow is a tool for showing the contents of the internal databases used by cfengine in its operation. Many users will not care about these internal details, while cfengine manages the system transparently. More advanced users might desire a simple way to dump the contents of these databases to text, for reporting purposes. HTML and XML versions of the output are provided for easy integration with reporting. .SH EXAMPLES cfshow --locks cfshow --last-seen cfshow --checksum cfshow --active cfshow --audit cfshow --classes cfshow --regex .PP These show the named databases. .SH OPTIONS Here are all of the options supported: --help (-h) --debug (-d) --verbose (-v) --locks (-l) --last-seen (-s) --performance (-p) --checksum (-c) --classes (-C) --filename (-f) --regex (-r) --active (-a) --version (-V) --html (-H) --xml (-X) --purge (-P) --audit (-A) .SH FILES cfshow reads cfengine internal information that is normally stored in the Work Directory /var/cfengine. .SH AUTHOR Mark Burgess, Oslo University College .SH INFORMATION http://www.cfengine.org cfengine-2.2.10/doc/mdate-sh0000744000175000001440000000516710202127306012464 00000000000000#!/bin/sh # Get modification time of a file or directory and pretty-print it. # Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. # written by Ulrich Drepper , June 1995 # # 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, 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. # Prevent date giving response in another language. LANG=C export LANG LC_ALL=C export LC_ALL LC_TIME=C export LC_TIME # Get the extended ls output of the file or directory. # On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below. if ls -L /dev/null 1>/dev/null 2>&1; then set - x`ls -L -l -d $1` else set - x`ls -l -d $1` fi # The month is at least the fourth argument # (3 shifts here, the next inside the loop). shift shift shift # Find the month. Next argument is day, followed by the year or time. month= until test $month do shift case $1 in Jan) month=January; nummonth=1;; Feb) month=February; nummonth=2;; Mar) month=March; nummonth=3;; Apr) month=April; nummonth=4;; May) month=May; nummonth=5;; Jun) month=June; nummonth=6;; Jul) month=July; nummonth=7;; Aug) month=August; nummonth=8;; Sep) month=September; nummonth=9;; Oct) month=October; nummonth=10;; Nov) month=November; nummonth=11;; Dec) month=December; nummonth=12;; esac done day=$2 # Here we have to deal with the problem that the ls output gives either # the time of day or the year. case $3 in *:*) set `date`; eval year=\$$# case $2 in Jan) nummonthtod=1;; Feb) nummonthtod=2;; Mar) nummonthtod=3;; Apr) nummonthtod=4;; May) nummonthtod=5;; Jun) nummonthtod=6;; Jul) nummonthtod=7;; Aug) nummonthtod=8;; Sep) nummonthtod=9;; Oct) nummonthtod=10;; Nov) nummonthtod=11;; Dec) nummonthtod=12;; esac # For the first six month of the year the time notation can also # be used for files modified in the last year. if (expr $nummonth \> $nummonthtod) > /dev/null; then year=`expr $year - 1` fi;; *) year=$3;; esac # The result. echo $day $month $year cfengine-2.2.10/doc/cfengine-Tutorial.texinfo0000644000175000001440000077143711124375001016026 00000000000000\input texinfo @c -*-texinfo-*- @c ********************************************************************* @c @c This is a TEXINFO file. It generates both TEX documentation and @c the "on line" documentation "info" files. @c @c The file is structured like a programming language. Each chapter @c starts with a chapter comment. @c @c Menus list the subsections so that an online info-reader can parse @c the file hierarchically. @c @c *********************************************************************** @c %** start of header @setfilename cfengine-Tutorial.info @settitle Cfengine v2 Tutorial @setchapternewpage odd @c %** end of header @defindex mb @include version2.texi @titlepage @title Cfengine v2 concepts @subtitle Edition @value{EDITION} for version @value{VERSION} @author Mark Burgess @author Faculty of Engineering, Oslo University College, Norway @c @smallbook @page @vskip 0pt plus 1filll Copyright @copyright{} 2008 Mark Burgess This manual corresponds to CFENGINE Edition @value{EDITION} for version @value{VERSION} as last updated @value{UPDATED}. @end titlepage @c *************************** File begins here ************************ @ifinfo @dircategory System Utilities @direntry * cfengine Tutorial: (cfengine-Tutorial.info). Cfengine is a language based tool specifically designed for configuring and maintaining BSD and System-5-like operating systems attached to a TCP/IP network. @end direntry @end ifinfo @ifnottex @node Top, Overview, (dir), (dir) @top Cfengine-Tutorial @end ifnottex @ifinfo Copyright @copyright{} 2008 Mark Burgess This manual corresponds to CFENGINE Edition @value{EDITION} for version @value{VERSION} as last updated @value{UPDATED}. @end ifinfo @ifhtml @html COMPLETE TABLE OF CONTENTS

This manual is for version @value{VERSION} of cfengine and was last updated on the @value{UPDATED}.

Summary of contents

@end html @end ifhtml @c ********************************************************************** @c CHAPTER @c ********************************************************************** @menu * Overview:: * Getting started:: * More advanced concepts:: * Global configurations:: * Using cfengine as a front-end for cron:: * Cfengine network services:: * Security and cfengine:: * Summary:: * Variable Index:: * Concept Index:: * FAQ Index:: @end menu @node Overview, Getting started, Top, Top @chapter Overview @emph{In this manual the word ``host'' is used to refer to a single computer system -- i.e. a single machine which has a name termed its ``hostname''.} @menu * What is cfengine?:: * Site configuration:: the problem * Key concepts:: the solution * Functionality:: an advertisement @end menu @c ----------------------------------------------------------------------- @c SECTION @c ----------------------------------------------------------------------- @node What is cfengine?, Site configuration, Overview, Overview @section What is cfengine and who can use it? Cfengine is a tool for setting up and maintaining computer systems. It consists of several components: @table @r @item @b{cfagent} An autonomous configuration agent (required). @item @b{cfservd} A file server and remote activation service (optional). @item @b{cfexecd} A scheduling and report service (recommended). @item @b{cfenvd} An anomaly detection service (strongly recommended). @item @b{cfrun} A way of activating cfagent remotely (use this as you need to). @item @b{cfshow} A way of examining the contents of helper databases (helper). @item @b{cfenvgraph} Ancillary tool for cfenvd (helper). @item @b{cfkey} Key generation tool (run once on every host). @end table The agent @file{cfagent} can be used without the other programs, but not all of the capabilities of cfengine will be available unless the components are installed and used appropriately. Cfengine incorporates a declarative language---much higher level than Perl or shell: a single statement can result in many hundreds of operations being performed on multiple hosts. Cfengine is good at performing a lot of common system administration tasks, and allows you to build on its strengths with your own scripts. You can also use it as a netwide front-end for @code{cron}. Once you have set up cfengine, you'll be free to use your time doing other things instead of manual configuration. The main purpose of cfengine is to allow you to create a single system configuration which will allow you to define how every host on your network should be configured, and to do so in an intuitive way -- either centralized or decentralized as you prefer. An interpreter runs on every host on your network and parses the master file (or file set). The configuration of each host is checked against this file; then, if you request it, any deviations from the defined configuration are fixed automatically. You do not have to mention every host specifically by name in order to configure them: instead you can refer to the properties which distinguish hosts from one another. Cfengine uses a flexible system of ``classes'' which helps you to single out a specific group of hosts with a single statement. Cfengine grew out of the need to control the accumulation of complex shell scripts used in the automation of key system maintenance at University College in Oslo. There were a lot of scripts, written in shell and in Perl, performing system administration tasks such as file tidying, find-database updates, process checking and several other tasks. In a mixed environment, shell scripts work very poorly: shell commands have differing syntax across different operating systems, and the locations and names of key files differ. In fact, the non-uniformity of Unix was a major headache. Scripts were filled with tests to determine what kind of operating system they were being run on, to the point where they became so complicated and unreadable that no one was quite sure what they did anymore. Other scripts were placed only on the systems where they were relevant, out of sight and out of mind. It quickly became clear that our dream solution would be to replace this proliferation of scripts by a single file containing everything to be checked on every host on the network. By defining a new language, this file could hide all of the tests by using classes (a generalized `switch/case' syntax) to label operations and improve the readability greatly. The gradual refinement of this idea resulted in the present day cfengine. As an inexperienced cfengine user, you will probably find yourself trying to do things as you would have tried to do them in shell or Perl. This is probably not the right way to think when using cfengine. You will need to think in a more `cfengine way'. When reading the manual, keep in mind that cfengine's way of working is to think about what the final result should be like, rather than on how to get there (with shell and Perl you specify what to do, rather than what you would like). The remainder of this manual assumes that you know a little about BSD and UNIX System V systems and have every day experience in using either the C shell (csh) or the Bourne shell (sh), or their derivatives. If you are experienced in system administration, you might like to skip the earlier chapters and turn straight to the example in the section @emph{Example configuration file} of the Reference manual. This is the probably quickest way to learn cfengine for the initiated. If you are not so familiar with system administration and would like a more gentle introduction, then we begin here... @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Site configuration, Key concepts, What is cfengine?, Overview @section Site configuration To the system administrator of a small network, with just a few workstations or perhaps even a single mainframe system, it might seem superfluous to create a big fuss about the administration of the system. After all, it's easy to `fix' things manually should any problems arise, making a link here, writing a script there and so on --- and its probably not even worth writing down what you did because you know that it will always be easy to fix next time around too... But networks have a tendency to expand and---before you know it---you have five different types of operating system and each type of system has to be configured in a special way, you have to make patches to each system and you can't remember whether you fixed that host on the other side of the building... Also, you discover fairly quickly that what you thought of as BSD or System V is not as standard as you thought and that none of your simple scripts that worked on one system work on the others without a considerable amount of hacking and testing. You try writing a script to help you automate the task, but end up with an enormous number of @samp{if..then..else..} tests which make it hard to see what is really going on. To manage a network with many different flavours of operating system in a systematic way, what is needed is a more disciplined way of making changes which is robust against system re-installation. After all, it would be tragic to spend many hours setting up a system by hand only to lose everything in an unfortunate disk crash a week or even a year later when you have forgotten what you had to do. Upgrades of the operating system software might delete your carefully worked out configuration. What is needed is a separate record of all of the patches required on all of the systems on the network; a record which can be compared to the state of each host at any time and which a suitable engine can use to fix any deviations from that reference standard. The idea behind cfengine is to focus upon a few key areas of basic system administration and provide a language in which the transparency of a configuration program is optimal. It eliminates the need for lots of tests by allowing you to organize your network according to ``classes''. From a single configuration file (or set of files) you can specify how your network should be configured --- and cfengine will then parse your file and carry out the instructions, warning or fixing errors as it goes. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Key concepts, Functionality, Site configuration, Overview @section Key Concepts @emph{Some of the important issues in system administration which cfengine can help with.} @menu * Control files:: textfiles which configure * Network interface:: ethernet parameters * Network File System (NFS):: sharing resources * Name servers (DNS):: setting up a name service * Monitoring important files:: permission and ownership * Making links:: aliases @end menu @c ..................................................... @c SUBSECTION @c ..................................................... @node Control files, Network interface, Key concepts, Key concepts @subsection Configuration files and registries @cindex Configuration files and registries @cindex Files, control @cindex Files, configuration One of the endearing characteristics of BSD and System V systems is that they are configured through human-readable text files. To add a new user to the system you edit @file{/etc/passwd}, to add a new disk you must edit @file{/etc/fstab}, etc. Many applications are also configured with the help of text files. When installing a new system for the first time, or when changing updating the setup of an old system, you are faced with having to edit lots of files. In some cases you will have to add precisely the same line to the same file on every system in your network as a change is made, so it is handy to have a way of automating this procedure so that you don't have to load every file into an editor by hand and make the changes yourself. This is one of the tasks which cfagent will automate for you. On Windows systems, configuration data are stored in a system registry. With the right tools, the Windows system registry can also be edited by cfengine, but this requires more care. @c ..................................................... @c SUBSECTION @c ..................................................... @node Network interface, Network File System (NFS), Control files, Key concepts @subsection Network interface @cindex ifconfig @cindex network interface @cindex network configuration Each host which you connect to an Ethernet-based network running TCP/IP protocols must have a so-called `net interface'. This network interface must be configured before it will work. Normally, one does this with the help of the @code{ifconfig} command. This can also be checked and configured automatically by cfagent. Network configuration involves telling the interface hardware what the internet (IP) address of your system is, so that it knows which incoming `packets' of data to pay attention to. It involves telling the interface how to interpret the addresses it receives by setting the `netmask' for your network (see below). Finally, you must tell it which dummy address is to be used for messages which are broadcast to all hosts on your network simultaneously (see the Reference Manual). Cfagent's features are mainly meant for hosts which use static IP addresses; if you are using DHCP clients, then you will not need the net configuration features. @cindex DHCP @c ..................................................... @c SUBSECTION @c ..................................................... @node Network File System (NFS), Name servers (DNS), Network interface, Key concepts @subsection Network File System (NFS) or file distribution? @cindex NFS Probably the first thing you are interested in doing with a network (after you've had your fill of the World-Wide Web) is to make your files available to some or all hosts on the network, no matter where in your corporate empire (or university dungeon) you might be sitting. In other words, if you have a disk which is physically connected to host A, you would like to make the contents of that disk available to hosts B, C, D @dots{}, etc. NFS (the Network FileSystem) makes this possible. The process works by `filesystems'. A filesystem is one partition of a disk drive -- or one unit of disk space which can be accessed by a single `logical device' @samp{/dev/something}. To make a filesystem available to other hosts you have to do three things. @itemize @bullet @item On the host the disk is physically connected to you must @emph{export} the filesystem by adding something to the file @file{/etc/exports}. This tells NFS who is allowed to access the disk and who isn't. @item On the host which is to access the filesystem you must create a mount point. This is a name in the directory tree at which you want to add the files to your local filesystem. @item On the host which is to access the files you must mount the filesystem onto the mount point. The mount operation is the jargon for telling the system to access the device on which the data are stored. Mounting is analogous to opening a file: files are opened, filesystems are mounted. @end itemize @noindent Only after all three of these have been done will a filesystem become available across the network. Cfagent will help you with the last two in a very transparent way. You could also use the text-editing facility in cfagent to edit the @file{exports} file, but there are other ways to update the @file{exports} file using NIS and @emph{netgroups}, which we shall not go into here. If you are in doubt, look up the manual page on exports(5). Some sites prefer to minimize the use of NFS filesystems to avoid one machine being dependent on another. They prefer to make a local copy of the files on a remote machine instead. Traditionally, programs like @code{rdist} have been used for this purpose. You may also use cfagent to copy files in this way, @xref{Emulating rdist}. @c ..................................................... @c SUBSECTION @c ..................................................... @node Name servers (DNS), Monitoring important files, Network File System (NFS), Key concepts @subsection Name servers (DNS) @cindex Name server @cindex DNS There are two ways to specify addresses on the internet (called IP addresses). One is to use the text address like @samp{ftp.uu.net} and the other is to use the numerical form @samp{192.48.96.9}. Alas, there is no direct one-to-one correspondence between the numerical addresses and the textual ones, thus a service (called DNS) is required to map one to the other. The service is performed by one or more special hosts on the network called @emph{name servers}. Each host must know how to contact a name server or it will probably hang the first time you give it an IP address. You tell it how to contact a name server by editing the text-file @file{/etc/resolv.conf}. This file must contain the domain name for your domain and a list of possible name servers which can be contacted, in order of priority. Since this is a special file which every host must have, you don't have to use the general text file editing facilities in cfagent. You can just define the name servers for each host in the cfagent file and cfagent will do the editing to @file{/etc/resolv.conf} automatically. If you want to change the priority of name servers later, or even change the list then a simple change of one or two lines in the configuration file will enable you to reconfigure every host on your network automatically without having to do any editing yourself! @c ..................................................... @c SUBSECTION @c ..................................................... @node Monitoring important files, Making links, Name servers (DNS), Key concepts @subsection Monitoring important files @cindex Monitoring important files @cindex Files, checking permissions Security is an important issue on any system. In the busy life of a system administrator, it is not always easy to remember to set the correct access rights on every file; this can result in either a security breach or problems in accessing files. A common scenario is that you, as administrator, fetch a new package using FTP, compile it and install it without thinking too carefully. Since the owner and permissions of the files in an FTP archive remains those of the program author, it often happens that the software is left lying around with the owner and permissions as set by the author of the program rather than any user name on @emph{your} system. The userid of the author might be anybody on your system --- or perhaps nobody at all! The files should clearly be owned by root and made readable but unwritable by normal users. Simple accidents and careless actions under stress could result in, for example, the password file being writable to ordinary users. If this were the case, the security of the entire system would be compromised. Cfagent therefore allows you to monitor the permissions, ownership, and general existence of files and directories and, if you wish, to either correct them or warn about them automatically. @c ..................................................... @c SUBSECTION @c ..................................................... @node Making links, , Monitoring important files, Key concepts @subsection Making links @cindex Links One of the difficulties with having so many different variations on the theme of BSD and System V based operating systems is that similar files are not always where you expect to find them. They have different names or lie in different directories. The usual solution to the problem is to make an alias for these files, or a pointer from one filename to another. The name for such an alias is a @emph{symbolic link}. It is often very convenient to make symbolic links. For example, you might want the sendmail configuration file @file{/etc/sendmail.cf} to be a link to a global configuration file, say, @smallexample @file{/usr/local/mail/etc/sendmail.cf} @end smallexample @noindent on every single host on your network so that there is only one file to edit. If you had to make all of these links yourself, it would take a lifetime. Cfagent will make such a link automatically and check it each time it is run. You can also ask it to tidy up old links which have been left around and no longer point to existing files. If you reinstall your operating system later, it doesn't matter because all your links are defined in your cfagent configuration file, recorded for all time. Cfengine won't forget it, and you won't forget it because the setup is defined in one central place. Cfagent will also allow you to make hard links to regular files, but not to other kinds of files. A hard link that points to a symbolic link is the same as a hard link to the file the symbolic link points to. @cindex Hard links @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Functionality, , Key concepts, Overview @section Functionality The notes above give you a rough idea of what cfengine can be used for. Here is a quick summary of cfagent's capabilities. @itemize @bullet @item Check and configure the network interface. @item Edit textfiles for the system and for all users. @item Make and maintain symbolic links, including multiple links, using a single command. @item Check and set the permissions and ownership of files. @item Tidy (i.e., delete) junk files which clutter the system. @item Systematic and automated mounting of NFS filesystems. @item Checking for the presence of important files and filesystems. @item Controlled execution of user scripts and shell commands. @item A class-based decision structure. @item Process management. @end itemize How do you run cfagent? You can run it as a cron job, or you can run it manually. You may run cfagent scripts/programs as often as you like. Each time you run a script, cfengine determines whether anything needs to be done --- if nothing needs to be done, nothing is done! If you use it to monitor and configure your entire network from a central file-base, then the natural thing is to run cfengine repeatedly with the help of @code{cron} and/or @code{cfexecd}. @cindex cfexecd @c ********************************************************************** @c CHAPTER @c ********************************************************************** @node Getting started, More advanced concepts, Overview, Top @chapter Getting started @menu * What you must have:: a skeleton cfagent program * Program structure:: an overview * Building a distributed configuration :: * Options:: spices and conveniences * Invoking cfagent:: from the command line * Running cfengine permanently monitoring and restarting cfexecd:: * CFINPUTS environment variable:: the cfengine search path * What to aim for:: @end menu @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node What you must have, Program structure, Getting started, Getting started @section What you must have in a cfagent program @cindex Musts in cfengine A cfagent configuration file for a large network can become long and complex so, before we get down to details, let's try to strip away the complexity and look only to the essentials. Each cfagent program or configuration file is a list of declarations of items to be checked and perhaps fixed. You begin by creating a file called @file{cfagent.conf}. The simplest meaningful file you can create is something like this: @smallexample # Comment... control: actionsequence = ( links ) links: /bin -> /usr/bin @end smallexample @noindent The example above checks and makes (if necessary) a link from @file{/bin} to @file{/usr/bin}. Let's examine this example more closely. In a cfengine program: @itemize @bullet @item Use of space is unrestricted. You can start new lines wherever you like. You should generally have a space before and after parentheses to avoid confusing the parser. @item A comment is some text which is ignored by cfengine. The @samp{#} symbol designates a comment and means: ignore the remaining text on this line. A comment symbol must have a space in front of it, or start a new line so that cfengine knows you don't mean the symbol as part of another word. @item Words which end in a single colon define @emph{sections} in a program. Under a given section you group together all declarations of a given type. Section names must all be taken from a list defined by the language. You cannot define your own sections. @item Words which end in two colons are so-called @emph{class} names. They are used for making decisions in cfengine. @item Statements which are of the form @code{@var{name}=( @var{list} )} are used to assign the value on the right hand side to the name on the left hand side of the equals sign. @end itemize @noindent In simple example above has three of the four types of object described above. The @code{control:} section of any program tells cfengine how to behave. In this example it adds the action @var{links} to the action sequence. For @var{links} you could replace some other action. The essential point is that, if you don't have an action sequence, your cfengine program will do absolutely nothing! The action sequence is a list which tells cfagent what do to and in which order. The @code{links:} section of the file tells cfagent that what follows is a number of links to be made. If you write this part of the file, but forget to add links to the action sequence, then nothing will be done! You can add any number of links in this part of the file and they will all be dealt with in order when---and only when---you write @var{links} in the action sequence. To summarize, you @emph{must} have: @itemize @bullet @item Some declarations which specify things to be done. @item An action sequence which tells cfagent which sections to process, how many times and in which order they should be processed. @end itemize Now let's think a bit about how useful this short example program is. On a SunOS (Solaris) system, where the directory @file{/bin} is in fact supposed to be a link, such a check could be useful, but on some other system where @file{/bin} is a not a link but a separate directory, this would result in an error message from cfagent, telling you that @file{/bin} exists and is not a link. The lesson is that, if we want to use cfagent to make @emph{one single} program which can be run on any host of any type, then we need some way of restricting the above link so that it only gets checked on SunOS systems. We can write the following: @smallexample # Comment... control: actionsequence = ( links ) links: sun4:: /bin -> /usr/bin # other links osf:: # other links @end smallexample @noindent The names which have double colons after them are called @emph{classes} and they are used to restrict a particular action so that it only gets performed if the host running the program is a member of that class. If you are familiar with C++, this syntax should make you think of classes definitions in C++. Classes works like this: the names above @code{sun4}, @code{sun3}, @code{osf} etc. are all internally defined by cfagent. If a host running, say, the OSF operating system executes the file it automatically becomes a member of the class @code{osf}. Since it cannot be a member more than one of the above, this distinguishes between different types of operating system and creates a hidden @code{if}..@code{then}...@code{else} test. This is the way in which cfagent makes decisions. The key idea is that actions are only carried out if they are in the same class as the host running the program. Classes are dealt with in detail in the next chapter. Now let's see how to add another kind of action to the action sequence. @smallexample # Comment... control: actionsequence = ( tidy links ) links: /bin -> /usr/bin tidy: /tmp pattern=* age=7 recurse=inf @end smallexample @noindent We have now added a new kind of declaration called @code{tidy:} which deletes files. In the example above, we are looking at files in the directory @file{/tmp} which match the pattern @samp{*} and have not been accessed for more than seven days. The search for these files descends recursively down any number of subdirectories. To make any of this happen we must add the word @var{tidy} to the action sequence. If we don't, the declaration will be ignored. Notice also that, regardless of the fact that @code{links:} comes before @code{tidy:}, the order in the action sequence tells us that all @code{tidy} actions will be performed before @code{links:}. The above structure can be repeated to build up a configuration file or script. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Program structure, Building a distributed configuration , What you must have, Getting started @section Program structure @cindex Program structure @cindex Structure of a program @cindex Comments To summarize the previous section, here is a sketch of a typical cfagent configuration program showing a sensible structure. The various sections are listed in a sensible order which you would probably use in the action sequence. An individual section-declaration in the program looks something like this: @smallexample @var{action-type}: @var{class1}:: @var{list of things to do...} @var{class2}:: @var{list of things to do...} @end smallexample @noindent @code{action-type} is one of the following reserved words: @smallexample groups, control, copy, homeservers, binservers, mailserver, mountables, import, broadcast, resolve, defaultroute, directories, miscmounts, files, ignore, tidy, required, links, disable, shellcommands, strategies editfiles, processes @end smallexample @noindent The order in which declarations occur is not important to cfengine from a syntactical point of view, but some of the above actions define information which you will want to refer to later. All variables, classes, groups etc. must be defined before they are used. That means that it is smart to follow the order above for the sections in the first line of the above list. The order in which items are declared is not to be confused with the order in which they are executed. This is determined by the @code{actionsequence}, (see the reference manual). Probably you will want to coordinate the two so that they match as far as possible. @cindex Order of actions @cindex Sections, order of @cindex Actions, order of For completeness, here is a complete summary of the structure of a very general cfagent configuration program. The format is free and use of space is unrestricted, though it is always a good idea to put a space in front before and after parentheses when defining variables. @cindex Free format @cindex Program format @cindex Format @smallexample ###################################################################### # # Example of structure # ###################################################################### groups: @var{group1} = ( @var{host} @var{host} ... ) @var{group2} = ( @var{host} @var{host} ... ) ... ###################################################################### control: @var{class}:: site = ( @var{mysite} ) domain = ( @var{mydomain} ) ... actionsequence = ( @var{action name} .... ) mountpattern = ( @var{mountpoint} ) homepattern = ( @var{wildcards matching home directories} ) addinstallable = ( @var{foo} @var{bar} ) addclasses = ( @var{foo} @var{bar} ) ###################################################################### homeservers: @var{class}:: @var{home servers} binservers: @var{class}:: @var{binary servers} mailserver: @var{class}:: @var{mail server} mountables: @var{class}:: @var{list of resources} ###################################################################### import: @var{class}:: @var{include file} @var{class}:: @var{include file} ###################################################################### broadcast: @var{class}:: @var{ones} # or zeros / zeroes defaultroute: @var{class}:: @var{my-gw} ###################################################################### resolve: any:: @var{list of nameservers} ... @end smallexample @noindent @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Building a distributed configuration , Options, Program structure, Getting started @section Building a distributed configuration @cindex Distributed configuration If a configuration is to be specified at one central location, how does it get distributed to many hosts? The simple answer is to get cfengine to distribute the configuration to the hosts. To do that, a separate configuration file is used. Why? Imagine what would happen if you made a mistake in the configuration, i.e. a syntax error which got distributed to every host. Now all the hosts would be unable to run cfengine, and thereafter unable to download a corrected configuration file. The whole setup would be broken. To prevent this kind of accident, a separate configuration file is used to copy the files and binaries to each host. This configuration should be simple, and should almost never be edited: they key word here is @emph{reliability}. @c ..................................................... @c SUBSECTION @c ..................................................... @menu * Startup update.conf:: * Startup cfservd.conf:: * Where should I put the files?:: @end menu @node Startup update.conf, Startup cfservd.conf, Building a distributed configuration , Building a distributed configuration @subsection Startup update.conf The file @file{update.conf} can have more or less the same form for all sites, looking something like this. @smallexample ####### # # BEGIN update.conf # # This script distributes the configuration, a simple file so that, # if there are syntax errors in the main config, we can still # distribute a correct configuration to the machines afterwards, even # though the main config won't parse. It is read and run just before the # main configuration is parsed. # ####### control: actionsequence = ( copy tidy ) # Keep this simple and constant domain = ( iu.hio.no ) # Needed for remote copy # # Which host/dir is the master for configuration roll-outs? # policyhost = ( nexus.iu.hio.no ) master_cfinput = ( /masterfiles/inputs ) # # Some convenient variables # workdir = ( /var/cfengine ) cf_install_dir = ( /usr/local/sbin ) # Avoid server contention SplayTime = ( 5 ) ############################################################################ # # Make sure there is a local copy of the configuration and # the most important binaries in case we have no connectivity # e.g. for mobile stations or during DOS attacks # copy: $(master_cfinput) dest=$(workdir)/inputs r=inf mode=700 type=binary exclude=*.lst exclude=*~ exclude=#* server=$(policyhost) $(cf_install_dir)/cfagent dest=$(workdir)/bin/cfagent mode=755 backup=false type=checksum $(cf_install_dir)/cfservd dest=$(workdir)/bin/cfservd mode=755 backup=false type=checksum $(cf_install_dir)/cfexecd dest=$(workdir)/bin/cfexecd mode=755 backup=false type=checksum ##################################################################### tidy: # # Cfexecd stores output in this directory. # Make sure we don't build up files and choke on our own words! # $(workdir)/outputs pattern=* age=7 ####### # # END cf.update # ####### @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node Startup cfservd.conf, Where should I put the files?, Startup update.conf, Building a distributed configuration @subsection Startup cfservd.conf In order to set up remote distribution from a central server, you will need to start the cfservd service on the host from which the configuration is to be copied, and grant access to the hosts which need to download it. Here is a simple get-started file which does this: @smallexample ######################################################### # # This is a cfservd config file - it is used for the server # part of cfengine, for remote file transfers and control # over cfengine using the cfrun program. # ######################################################### control: domain = ( iu.hio.no ) cfrunCommand = ( "/var/cfengine/bin/cfagent" ) any:: IfElapsed = ( 1 ) ExpireAfter = ( 15 ) MaxConnections = ( 50 ) MultipleConnections = ( true ) ######################################################### grant: # Grant access to all hosts at example.org. # Files should be world readable /masterfiles/inputs *.example.org # Make sure there is permission to execute by cfrun /var/cfengine/bin/cfagent *.example.org ######## # # END cfservd.conf # ######## @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node Where should I put the files?, , Startup cfservd.conf, Building a distributed configuration @subsection Where should I put the files? Where should the files be located? To organize your files, you should think of three potential locations, for different purposes: @itemize @bullet @item A version controlled repository for authoring, testing and applying changes to the files. Once a version is approved for release, these master files should be moved on to a publishing area. e.g. @file{/usr/local/masterfiles/cfengine/inputs} on `masterhost'. @item A centralized location, into which you publish your altered and tested configurations. This is the `buffer' location from which each client will download new and tested versions of the master configuration. e.g. @file{/usr/local/masterfiles/cfengine/inputs} on `masterhost'. It acts as a buffer between the testing ground and the production location. @item The Work Directory. This is the production location. It is a location that is normally chosen to be the private directory where cfagent expects to find its configuration files, @file{/var/cfengine/inputs}. Your @file{update.conf} file has the job of copying from the master location (second bullet) above to this location. @cindex Work Directory @end itemize Modules and methods are normally kept in a separate directory than inputs files are kept in, because they require a directory with special authorizations whe executing. This is good practice As long as the @file{update.conf} places the master versions in the correct location (usually @file{/var/cfengine/modules}) on the local host, all will be okay. You should not try to copy files directly from a version controlled repository, as you might end up sending out an incomplete or partially tested version of the files to all your hosts. @smallexample # Example update.conf control: master_cfinput = ( /usr/local/masterfiles/cfengine/inputs ) workdir = ( /var/cfengine ) copy: # Copy from bullet 2 to bullet 3 $(master_cfinput) dest=$(workdir)/inputs r=inf mode=700 type=binary exclude=*.lst exclude=*~ exclude=#* server=$(policyhost) trustkey=true $(master_modules) dest=$(workdir)/modules r=inf mode=700 type=binary exclude=*.lst exclude=*~ exclude=#* server=$(policyhost) trustkey=true @end smallexample @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Options, Invoking cfagent, Building a distributed configuration , Getting started @section Optional features in cfagent @cindex Optional features in cfagent Cfagent doesn't do anything unless you ask it to. When you run a cfagent program it generates no output unless it finds something it believes to be wrong. It does not carry out any actions unless they are declared in the action sequence. If you like, though, you can make cfagent positively chatty. Cfagent can be run with a number of command line options (see the reference manual). If you run the program with the @samp{-v} or @samp{--verbose} options, it will supply you cheerily with a resume of what it is doing. Certain warning messages also get printed in verbose mode, so it is a useful debugging tool. You can ask cfagent to check lots of things -- the timezone for instance, or the domain name. In order for it to check these things, it needs some information from you. All of the switches and options which change the way in which cfagent behaves get specified either on the command line or in the @code{control:} section of the control file. Some special control variables are used for this purpose. Here is a short example: @smallexample control: domain = ( example.org ) netmask = ( 255.255.255.0 ) timezone = ( MET CET ) mountpattern = ( /mydomain/mountpoint ) actionsequence = ( checktimezone # check time zone netconfig # includes check netmask resolve # includes domain mountinfo # look for mounted disks under mountpattern ) @end smallexample @noindent To get verbose output you must run cfagent with the appropriate command line option @samp{--verbose} or @samp{-v}. Notice that setting values has a special kind of syntax: a variable name, an equals sign and a value in parentheses. This tells you that the quantity of the left hand side assumes the value on the right hand side. There are lots of questions you might ask at this point. The answers to these will be covered as we go along and in the next chapter. Before leaving this brief advertisement for control parameters, it is worth noting the definition of @code{mountpattern} above. This declares a directory in which cfagent expects to find mounted disks. It will be explained in detail later, for now notice that this definition looks rather stupid and inflexible. It would be much better if we could use some kind of variables to define where to look for mounted filesystems. And of course you can... Having briefly scraped the surface of what cfagent can do, turn to the example and take a look at what a complete program can look like, (see the reference manual). If you understand it, you might like to skip through the rest of the manual until you find what you are looking for. If it looks mysterious, then the next chapter should answer some questions in more depth. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Invoking cfagent, Running cfengine permanently monitoring and restarting cfexecd, Options, Getting started @section Invoking cfagent @cindex Invoking cfagent @cindex Starting cfagent @cindex cfagent, starting Cfagent may be invoked in a number of ways. Here are some examples: @example host% cfagent host% cfagent --file myfile host% cfagent -f myfile -v -n host% cfagent --help @end example @cindex Default file @cindex Config file, default name @cindex @file{cfagent.conf} The first of these (the default command, with no arguments) causes cfagent to look for a file called @file{cfagent.conf} in the directory pointed to by the environment variables @code{CFINPUTS} or @file{/var/cfengine/inputs} by default, and execute it silently. The second command reads the file @file{myfile} and works silently. The third works in verbose mode and the @code{-n} option means that no actions should actually be carried out, only warnings should be printed. The final example causes cfagent to print out a list of its command line options. @vindex -n option @vindex -f option @vindex -v option The complete list of options is listed in the summary at the beginning of this manual, or you can see it by giving the @code{-h} option, (see the reference manual). @cindex Help @cindex -h option @vindex -h option In addition to running cfagent with a filename, you can also treat cfagent files as scripts by starting your cfagent program with the standard shell line: @smallexample #!/usr/local/sbin/cfagent -f # # My config script # @end smallexample @noindent @cindex Verifying with -n option Here we assume that you have installed cfengine under the directory @file{/usr/local/sbin}. By adding a header like this to the first line of your program and making the file executable with the @code{chmod} shell command, you can execute the program just by typing its name---i.e. without mentioning cfengine explicitly at all. As a novice to cfengine, it is advisable to check all programs with the @code{-n} option before trusting them to your system, at least until you are familiar with the behaviour of cfengine. This `safe' option allows you to see what cfengine wants to do, without actually committing yourself to doing it. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Running cfengine permanently monitoring and restarting cfexecd, CFINPUTS environment variable, Invoking cfagent, Getting started @section Running cfengine permanently, monitoring and restarting cfexecd Once you are happy using cfengine, you will want it to run least once per hour on your systems. This is easily achieved by adding the following line to the root crontab file of each system: @smallexample 0,30 * * * * /usr/local/sbin/cfexecd -F @end smallexample This is enough to ensure that cfengine will get run. Any output generated by this job, will be stored in @file{/var/cfengine/outputs}. @cindex /var/cfengine/output @vindex /var/cfengine/output @cindex Output logs In addition, if you add the following to the file @file{cfagent.conf}, the system administrator will be emailed a summary of any output: @smallexample control: smtpserver = ( mailhub.example.org ) # site MTA which can talk smtp sysadm = ( mark@@example.org ) # mail address of sysadm @end smallexample @noindent Fill in suitable values for these variables. @cindex Mailing output @vindex smtpserver @vindex sysadm @cindex cfexecd An alternative, or additional way to run cfengine, is to run the @file{cfexecd} program is daemon mode (without the @samp{-F}) option. In this mode, the daemon lives in the background and sleeps, activating only in accordance with a scheduling policy. The default policy is to run once every hour (equivalent to @code{Min00_05}). Here is how you would modify @file{cfagent.conf} in order to make the daemon execute cfagent every half-hour: @smallexample control: # When should cfexecd in daemon mode wake up the agent? schedule = ( Min00_05 Min30_35 ) @end smallexample Note that the time specifications are the basic cfengine @emph{time classes}, @xref{Building flexible time classes}. Although one of these methods should suffice, no harm will arise from running both cron and the cfexecd side-by-side. Cfagents locking mechanisms ensure that no contention will occur. The other components of cfengine can be started by cfagent itself: @smallexample processes: "cfenvd" restart "/usr/local/sbin/cfenvd" "cfservd" restart "/usr/local/sbin/cfservd" @end smallexample Note that, to start cfexecd by cfengine, one must do this @smallexample processes: "bin/cfexecd$" restart "/usr/local/sbin/cfexecd" @end smallexample It's important to use as specific a regular expression as possible in match statements (the path to the program and the regular expression metacharacter @code{$} meaning "end of line", in this example) because bare strings can often match unexpected processes. For instance, using @code{cfexecd} by itself will also match a process spawned by @code{cfagent -F}, which shows up as @code{/var/cfagent/bin/cfagent -Dfrom_cfexecd} in the process table! @cindex Restarting cfexecd @cindex cfexecd restarting by processes @cindex processes cannot start cfexecd @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node CFINPUTS environment variable, What to aim for, Running cfengine permanently monitoring and restarting cfexecd, Getting started @section CFINPUTS environment variable Whenever cfengine looks for a file it asks a question: is the filename an absolute name (that is a name which begins from @file{/} like @code{/usr/file}), is it a file in the directory in which you invoke cfengine or is it a file which should be searched for in a special place? @vindex -f option @cindex CFINPUTS variable @cindex Environment variable, CFINPUTS @cindex File search paths @cindex Path to input files If you use an absolute filename either on the command line using @code{-f} or in the @code{import} section of your program (a name which begins with a slash '/'), then cfengine trusts the name of the file you have given and treats it literally. If you specify the name of the file as simple @samp{.} or @samp{-} then cfengine reads its input from the standard input. @cindex STDIN, reading from @cindex Piping input into cfengine @cindex @file{cfagent.conf} If you run cfengine without arguments (so that the default filename is @file{cfagent.conf}) or you specify a file without a leading slash in the @code{import} section, then the value of the environment variable @code{CFINPUTS} is prepended to the start of the file name. This allows you to keep your configuration in a standard place, pointed to by @code{CFINPUTS}. For example: @example host# setenv CFINPUTS /usr/local/masterfiles/cfengine/inputs host# cfagent -f myfile @end example @noindent In this example, cfengine tries to open @file{myfile}. in the directory @file{/usr/local/masterfiles/cfengine/inputs}. If no value is set for @code{CFINPUTS}, then the default location is the trusted cfengine directory @file{/var/cfengine/inputs}. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node What to aim for, , CFINPUTS environment variable, Getting started @section What to aim for If you are a beginner to cfengine, you might not be certain exactly how you want to use it. Here are some hints from Dr. Daystrom about how to get things working quickly. @itemize @bullet @item Run cfengine from cron every hour on all your systems. Be sure to label long tasks, or tasks which do not need to be performed often by a @emph{time class} which prevents it from being executed all the time, @xref{Using cfengine as a front-end for cron}. @emph{Running cfengine from cron means that it will be run in parallel on your systems. Cfengine on one host does not have to wait for cfengine on another host to complete.} @item Set up @code{cfservd} on all your systems so that cfengine can be executed remotely, so that you can immediately ``push" changes to all your hosts with @code{cfrun}. Think carefully about whom you wish to give permission to run cfengine from the net, @xref{Configuring cfservd}. Set up you @file{cfservd.conf} file accordingly. You can also use this daemon to grant access rights for remote file copying. @emph{Cfrun polls all your hosts serially and gives you a concatenated indexed list of problems on all hosts. The disadvantage with cfrun is that each host has to wait its turn.} @item Don't forget to add @code{cfservd} to the system startup scripts, or to @file{inittab} so that it starts when you boot your system. @item Add @emph{all} your hosts to the @file{cfrun.hosts} file. It does not matter that some may be master servers and others clients. The locking mechanisms will protect you from silliness, @xref{Deadlocks and runaway loops}. Cfengine will work it out. Cfrun allows you to remotely execute cfengine on groups of hosts which satisfy a list of cfengine classes. @end itemize @noindent When you have set up these components, you can sit back and edit the configuration files and watch things being done. @c ********************************************************************** @c CHAPTER @c ********************************************************************** @node More advanced concepts, Global configurations, Getting started, Top @chapter More advanced concepts @menu * Classes basics:: * Variable substitution:: * Undefined variables:: * Defining classes:: making decisions * The generic class any:: a wildcard * Debugging tips:: nullifying classes * Access control:: specifying user access to programs * Wildcards in directory names:: multiple searches * File sweeps:: * Security in File sweeps:: * Log files:: * Quoted strings:: * Regular expressions:: * Iterating over lists:: @end menu @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Classes basics, Variable substitution, More advanced concepts, More advanced concepts @section Classes @cindex Classes The idea of classes is central to the operation of cfengine. Saying that cfengine is `class orientated' means that it doesn't make decisions using @code{if}...@code{then}...@code{else} constructions the way other languages do, but only carries out an action if the host running the program is in the same class as the action itself. To understand what this means, imagine sorting through a list of all the hosts at your site. Imagine also that you are looking for the @emph{class} of hosts which belong to the computing department, which run GNU/Linux operating system and which have yellow spots! To figure out whether a particular host satisfies all of these criteria you first delete all of the hosts which are not GNU/Linux, then you delete all of the remaining ones which don't belong to the computing department, then you delete all the remaining ones which don't have yellow spots. If you are on the remaining list, then you are in the class of all computer-science-Linux-yellow-spotted hosts and you can carry out the action. Cfengine works in this way, narrowing things down by asking if a host is in several classes at the same time. Although some information (like the kind of operating system you are running) can be obtained directly, clearly, to make this work we need to have lists of which hosts belong to the computer department and which ones have yellow spots. So how does this work in a cfengine program? A program or configuration script consists of a set of declarations for what we refer to as @emph{actions} which are to be carried out only for certain classes of host. Any host can execute a particular program, but only certain action are extracted --- namely those which refer to that particular host. This happens automatically because cfengine builds up a list of the classes to which it belongs as it goes along, so it avoids having to make many decisions over and over again. By defining classes which classify the hosts on your network in some easy to understand way, you can make a single action apply to many hosts in one go -- i.e. just the hosts you need. You can make generic rules for specific type of operating system, you can group together clusters of workstations according to who will be using them and you can paint yellow spots on them -- what ever works for you. A @emph{cfengine action} looks like this: @smallexample @var{action-type}: @var{compound-class}:: @var{declaration} @end smallexample @noindent A single class can be one of several things: @itemize @bullet @item The name of an operating system architecture e.g. @code{ultrix}, @code{sun4} etc. This is referred to henceforth as a @emph{hard class}. @item The (unqualified) name of a particular host. If your system returns a fully qualified domain name for your host, cfagent truncates it so as to unqualify the name. @item The name of a user-defined group of hosts. @item A day of the week (in the form @code{Monday}, @code{Tuesday}, @code{Wednesday}...). @item An hour of the day (in the form @code{Hr00}, @code{Hr01}, ... @code{Hr23}). @item Minutes in the hour (in the form @code{Min00}, @code{Min17}, ... @code{Min45}). @item A five minute interval in the hour (in the form @code{Min00_05}, @code{Min05_10}, ... @code{Min55_00}) @item A quart hour (in the form @code{Q1, Q2, Q3, Q4}) @item An abbreviated time with quarter hour specified (in the form @code{Hr00_Q1}, @code{Hr23_Q4}, etc.) @item A day of the month (in the form @code{Day1 ... Day31}). @item A month (in the form @code{January}, @code{February}, ... @code{December}). @item A year (in the form @code{Yr1997}, @code{Yr2001}). @item An arbitrary user-defined string. (see the reference manual). @item The ip-address octets of any active interface (in the form @code{@w{ipv4_192_0_0_1}}, @code{@w{ipv4_192_0_0}}, @code{@w{ipv4_192_0},@code{ipv4_192}}). @end itemize A compound class is a sequence of simple classes connected by dots or `pipe' symbols (vertical bars). For example: @cindex Compound classes @cindex Classes, compound @w{} @smallexample myclass.sun4.Monday:: sun4|ultrix|osf:: @end smallexample @noindent A compound class evaluates to `true' if all of the individual classes are separately true, thus in the above example the actions which follow @code{compound_class::} are only carried out if the host concerned is in @code{myclass}, is of type @code{sun4} and the day is Monday! In the second example, the host parsing the file must be either of type @code{sun4} @emph{or} @code{ultrix} @emph{or} @code{osf}. In other words, compound classes support two operators: AND and OR, written @samp{.} and @samp{|} respectively. From cfengine version 2.1.1, I bit the bullet and added @samp{&} as a synonym for the AND operator. Cfengine doesn't care how many of these operators you use (since it skips over blank class names), so you could write either @smallexample solaris|irix:: @end smallexample @noindent or @smallexample solaris||irix:: @end smallexample @noindent depending on your taste. On the other hand, the order in which cfengine evaluates AND and OR operations @emph{does} matter, and the rule is that AND takes priority over OR, so that @samp{.} binds classes together tightly and all AND operations are evaluated before ORing the final results together. This is the usual behaviour in programming languages. You can use round parentheses in cfengine classes to override these preferences. Cfengine allows you to define switch on and off dummy classes so that you can use them to select certain subsets of action. In particular, note that by defining your own classes, using them to make compound rules of this type, and then switching them on and off, you can also switch on and off the corresponding actions in a controlled way. The command line options @code{-D} and @code{-N} can be used for this purpose. See also @code{addclasses} in the Reference manual. @vindex -N option @vindex -D option @cindex Classes, defining and undefining @cindex NOT operator @cindex Logical NOT @vindex ! @cindex ! A logical NOT operator has been added to allow you to exclude certain specific hosts in a more flexible way. The logical NOT operator is (as in C and C++) @samp{!}. For instance, the following example would allow all hosts except for @code{myhost}: @smallexample @var{action}: !myhost:: @var{command} @end smallexample @noindent and similarly, so allow all hosts in a user-defined group @code{mygroup}, @emph{except} for @code{myhost}, you would write @smallexample @var{action}: mygroup.!myhost:: @var{command} @end smallexample @noindent which reads `mygroup AND NOT myhost'. The NOT operator can also be combined with OR. For instance @smallexample @var{class1}|!@var{class2} @end smallexample @noindent would select hosts which were either in class 1, or those which were not in class 2. Finally, there is a number of reserved classes. The following are hard classes for various operating system architectures. They do not need to be defined because each host knows what operating system it is running. Thus the appropriate one of these will always be defined on each host. Similarly the day of the week is clearly not open to definition, unless you are running cfengine from outer space. The reserved classes are: @smallexample ultrix, sun4, sun3, hpux, hpux10, aix, solaris, osf, irix4, irix, irix64 sco, freebsd, netbsd, openbsd, bsd4_3, newsos, solarisx86, aos, nextstep, bsdos, linux, debian, cray, unix_sv, GnU, NT @end smallexample @noindent If these classes are not sufficient to distinguish the hosts on your network, cfengine provides more specific classes which contain the name and release of the operating system. To find out what these look like for your systems you can run cfengine in `parse-only-verbose' mode: @smallexample cfagent -p -v @end smallexample @noindent and these will be displayed. For example, Solaris 2.4 systems generate the additional classes @code{sunos_5_4} and @code{sunos_sun4m}, @code{sunos_sun4m_5_4}. Cfengine uses both the unqualified and fully host names as classes. Some sites and operating systems use fully qualified names for their hosts. i.e. @code{uname -n} returns to full domain qualified hostname. This spoils the class matching algorithms for cfengine, so cfengine automatically truncates names which contain a dot `.' at the first `.' it encounters. If your hostnames contain dots (which do not refer to a domain name, then cfengine will be confused. The moral is: don't have dots in your host names! @emph{NOTE: in order to ensure that the fully qualified name of the host becomes a class you must define the domain variable.} The dots in this string will be replaced by underscores. @cindex Fully qualified names @cindex Dots in hostnames @cindex Host name gets truncated In summary, the operator ordering in cfengine classes is as follows: @cindex Operator ordering @mbindex Brackets (parentheses) in classes. @mbindex Parentheses in classes. @table @samp @item () Parentheses override everything. @item ! The NOT operator binds tightest. @item . & The AND operator binds more tightly than OR. @item | OR is the weakest operator. @end table @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Variable substitution, Undefined variables, Classes basics, More advanced concepts @section Variable substitution @cindex Variable substitution @cindex Variables, environment @cindex Variables, cfengine @cindex Environment variables @vindex site @vindex faculty @vindex binserver @vindex host @vindex timezone @vindex domain @vindex sysadm @cindex Variables and Macros @cindex Macros @cindex Environment variables When you are building up a configuration file it is very useful to be able to use variables. If you can define your configuration in terms of some key variables, it can be changed more easily later, it is more transparent to the reader of the program and you can also choose to define the variables differently on different types of system. Another way of saying this is that cfengine variables also belong to classes. Cfengine makes use of variables in three ways. @itemize @bullet @item Environment variables from the shell @item Special variables used in cfengine features @item General macro-string substitution. @end itemize @noindent Environment variables are fetched directly from the shell on whatever system is running the program. An example of a special variable is the @code{domain} variable from the previous section. Straightforward macro substitution allows you to define a symbol name to be replaced by an arbitrary text string. All these definitions (apart from shell environment variables, of course) are made in the control part of the cfengine program: @smallexample control: myvar = ( /usr/local/mydir/lib/very/long/path ) # define macro ... links: $(myvar) -> /another/directory @end smallexample @noindent Here we define a macro called @code{myvar}, which is later used to define the creation of a link. As promised we can also define class-dependent variables: @smallexample control: sun4:: myvar = ( sun ) hpux:: myvar = ( HP ) @end smallexample Cfagent gives you access to the shell environment variables and allows you to define variables of your own. It also keeps a few special variables which affect the way in which cfengine works. When cfengine expands a variable it looks first at the name in its list of special variables, then in the list of user-defined macros and finally in the shell environment for a match. If none of these are found it expands to the empty string. If you nest macros, @smallexample control: myvar = ( "$(othervar)" ) @end smallexample then you must quote the right hand side and ensure that the value is already defined. @cindex Nested macros @cindex Defining variables using other variables You can also import values from the execution of a shell command by prefixing a command with the word @code{exec}. This method is deprecated in version 2 and replaced by a function. @cindex Variables, setting to result of a shell command @vindex @code{exec} @w{} @smallexample control: # old method listing = ( "exec /bin/ls -l" ) # new method listing = ( ExecResult(/bin/ls -l) ) @end smallexample @noindent This sets the variable `listing' to the output of the command in the quotes. @cindex In-built functions @cindex Functions, in-built @cindex Random numbers Some other internal functions are @table @code @item RandomInt(@var{a},@var{b}) Generate a random integer between a and b. @item ExecResult(@var{command}) Executes the named shell command and inserts the output into the variable. @end table @noindent For example: @smallexample control: variable2 = ( RandomInt(0,23) ) variable3 = ( ExecResult(/bin/ls -a /opt) ) @end smallexample Variables are referred to in either of two different ways, depending on your taste. You can use the forms @code{$(variable)} or @code{$@{variable@}}. The variable in braces or parentheses can be the name of any user defined macro, environment variable or one of the following special internal variables. @table @code @item AllClasses A long string in the form @samp{CFALLCLASSES=class1:class2...}. This variable is a summary of all the defined classes at any given time. It is always kept up to date so that scripts can make use of cfengine's class data. @cindex CFALLCLASSES @vindex CFALLCLASSES @cindex Class data and scripts @cindex Scripts, passing classes to @item arch The current detailed architecture string---an amalgamation of the information from @emph{uname}. Non-definable. @vindex $(arch) @item binserver The default server for binary data. @xref{NFS resources}. Non definable. @vindex $(binserver) @item class The currently defined system hard-class (e.g. @code{sun4}, @code{hpux}). Non-definable. @vindex $(class) @item date The current date string. Note that if you use this in a shell command it might be interpreted as a list variable, since it contains the default separator @samp{:}. @vindex $(date) @item domain The currently defined domain. @vindex $(domain) @item faculty The faculty or site as defined in control (see site). @vindex $(faculty) @item fqhost The fully qualified (DNS/BIND) hostname of the system, which includes the domain name as well. @vindex $(fqhost) @item host The hostname of the machine running the program. @vindex $(host) @item ipaddress The numerical form of the internet address of the host currently running cfengine. @vindex $(ipaddress) @item MaxCfengines The maximum number of cfengines which should be allowed to co-exist concurrently on the system. This can prevent excessive load due to unintentional spamming in situations where several cfagents are started independently. The default value is unlimited. @vindex MaxCfengines @item ostype A short for of @code{$(arch)}. @item OutputPrefix This quoted string can be used to change the default `cfengine:' prefix on output lines to something else. You might wish to shorten the string, or have a different prefix for different hosts. The value in this variable is appended with the name of the host. The default is equivalent to, @smallexample OutputPrefix = ( "cfengine:$(host):") @end smallexample @vindex OutputPrefix @item RepChar The character value of the string used by the file repository in constructing unique filenames from path names. This is the character which replaces @samp{/} (see the reference manual). @vindex repchar @item site This variable is identical to @code{$(faculty)} and may be used interchangeably. @vindex $(site) @item split The character on which list variables are split (see the reference manual). @vindex split @item sysadm The name or mail address of the system administrator. @vindex $(sysadm) @item timezone The current timezone as defined in @code{control}. @vindex $(timezone) @item UnderscoreClasses If this is set to `on' cfengine uses hard-classes which begin with an underscore, so as to avoid name collisions. See also Runtime Options in the Reference manual. @vindex underscoreclasses @cindex underscoreclasses @cindex Name collision @cindex Hostname collision @cindex Hard class name collision @vindex underscoreclasses @item year The current year. @vindex $(year) @end table @noindent These variables are kept special because they play a special role in setting up a system configuration. @xref{Global configurations}. You are encouraged to use them to define fully generalized rules in your programs. Variables can be used to advantage in defining filenames, directory names and in passing arguments to shell commands. The judicious use of variables can reduce many definitions to a single one if you plan carefully. @cartouche @emph{NOTE: the above control variables are not case sensitive, unlike user macros, so you should not define your own macros with these names.} @end cartouche The following variables are also reserved and may be used to produce troublesome special characters in strings. @table @code @item cr Expands to the carriage-return character. @vindex $(cr) @item dblquote Expands to a double quote @code{"} @vindex $(dblquote) @item dollar Expands to @samp{$}. @vindex $(dollar) @item lf Expands to a line-feed character (Unix end of line). @vindex $(lf) @item n Expands to a newline character. @vindex $(n) @item quote Expands to a single quote @code{'}. @vindex $(quote) @item spc Expands simply to a single space. This can be used to place spaces in filenames etc. @vindex $(spc) @item tab Expands to a single tab character. @vindex $(tab) @end table @noindent You can use variables in the following places: @itemize @bullet @item In any directory name. The @code{$(binserver)} variable is not always appropriate in this context. For instance @end itemize @smallexample links: osf:: /$(site)/$@{host@}/directory -> somefile @end smallexample @itemize @bullet @item In any quoted string. (See @code{shellcommands} in the Reference manual). @end itemize @w{} @smallexample shellcommands: any:: "/bin/echo $(timezone) | /bin/mail $(sysadm)" '/bin/echo "double quotes!"' @end smallexample @cindex Variables, using @noindent The latter possibility enables cfengine's variables to be passed on to user-defined scripts. @itemize @bullet @item To define the values of options passed to various actions, in the form @code{@var{option}=$(variable)}. @end itemize Variables can be defined differently under different classes by preceding the definition with a class name. For example: @smallexample control: sun4:: my_macro = ( User_string_1 ) irix:: my_macro = ( User_string_2 ) @end smallexample @noindent Here the value assigned to @code{$(my_macro)} depends on which of the classes evaluates to true. This feature can be used to good effect to define the mail address of a suitable system administrator for different groups of host. @smallexample control: physics:: sysadm = ( mark,fred ) chemistry:: sysadm = ( localsys@@domain ) @end smallexample @vindex -a option @cindex System administrator, name @noindent Note, incidentally, that the @samp{-a} option can be used to print out the mail address of the system administrator for any wrapper scripts. @node Undefined variables, Defining classes, Variable substitution, More advanced concepts @section Undefined variables Note that macro-variables which are undefined are not expanded as of version 1.6 of cfengine. In earlier versions, undefined variables would be replaced by an empty string, as in Perl. In versions 1.6.x and later, the variable string remains un-substituted, if the varaiable does not exist. For instance, @smallexample control: actionsequence = ( shellcommands ) myvar = ( "test string " ) shellcommands: "/bin/echo $(myvar) $(myvar2)" @end smallexample results in: @smallexample cfengine:host: Executing script /bin/echo test string $(myvar2) cfengine:host:/bin/echo test : sh: syntax error at line 1: `(' unexpected cfengine:host: Finished script /bin/echo test string $(myvar2) @end smallexample This allows variables to be defined on-the-fly by modules. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Defining classes, The generic class any, Undefined variables, More advanced concepts @section Defining classes and making exceptions @cindex Exceptions @cindex Excluding actions in a controlled way Cfengine communicates with itself by passing messages in the form of classes. When a class becomes switched on or off, cfengine's program effectively becomes modified. There are several ways in which you can switch on and off classes. Learning these fully will take some time, and only then will you harness the full power of cfengine. @itemize @bullet @item Classes may be defined manually from the command line. @item Classes may be defined locally in the actionsequence in order to execute only some of the actions within a special category. @item Classes may become defined if cfengine actually needs to carry out an action to repair the system's configuration. @item Classes may be defined by user-defined plug-in modules. @cindex Plug-in modules @cindex Modules, user defined plug-ins @end itemize Because cfagent works at a very high level, doing very many things for very few lines of code it might seem that some flexibility is lost. When we restrict certain actions to special classes it is occasionally useful to be able to switch off classes temporarily so as to cancel the special actions. @c ..................................................... @c SUBSECTION @c ..................................................... @menu * Command line classes:: * actionsequence classes:: * shellcommand classes:: * Feedback classes:: * Writing plugin modules:: @end menu @node Command line classes, actionsequence classes, Defining classes, Defining classes @subsection Command line classes You can define classes of your own which can be switched on and off, either on the command line or from the action sequence. For example, suppose we define a class @emph{include}. We use @code{addclasses} to do this. @smallexample addclasses = ( include othersymbols ) @end smallexample @noindent The purpose of this would be to allow certain `excludable actions' to be defined. Actions defined by @smallexample any.include:: @var{actions} @end smallexample @noindent will normally be carried out, because we have defined @code{include} to be true using @code{addclasses}. But if cfagent is run in a restricted mode, in which @code{include} is set to false, we can exclude these actions. So, by defining the symbol @code{include} to be false, you can exclude all of the actions which have @code{include} as a member. There are two ways in which this can be done, one is to negate a class globally using @example @cartouche cfagent -N include @end cartouche @end example @noindent This undefines the class @code{include} for the entire duration of the program. @c ..................................................... @c SUBSECTION @c ..................................................... @node actionsequence classes, shellcommand classes, Command line classes, Defining classes @subsection actionsequence classes Another way to specify actions is to use a class to select only a subset of all the actions defined in the actionsequence. You do this by adding a class name to one on the actions in action sequence by using a dot @samp{.} to separate the words. In this case the symbol only evaluates to `true' for the duration of the action to which it attached. Here is an example: @smallexample links.onlysome shellcommands.othersymbols.onlysome @end smallexample @noindent In the first case @emph{@code{onlysome} is defined to be true} while this instance of @code{links} is executed. That means that only actions labelled with the class @code{onlysome} will be executed as a result of that statement. In the latter case, both @code{onlysome} and @code{othersymbols} are defined to be true for the duration of @code{shellcommands}. This syntax would normally be used to omit certain time-consuming actions, such as tidying all home directories. Or perhaps to synchronize certain actions which have to happen in a certain order. @c ..................................................... @c SUBSECTION @c ..................................................... @node shellcommand classes, Feedback classes, actionsequence classes, Defining classes @subsection shellcommand classes For more advanced uses of cfengine you might want to be able to define a class on the basis of the success or failure of a user-program, a shell command or user script. Consider the following example @smallexample groups: have_cc = ( "/bin/test -f /usr/ucb/cc" "/bin/test -f /local/gnu/cc" ) @end smallexample @noindent Note that as of version 1.4.0 of cfengine, you may use the word @code{classes} as an alias for @code{groups}. Whenever cfagent meets an object in a class list or variable, which is surrounded by either single, double quotes or reversed quotes, it attempts to execute the string as a command passed to the Bourne shell. If the resulting command has return code zero (proper exit) then the class on the left hand side of the assignment (in this case @samp{have_cc}) will be true. If the command returns any other value (an error number) the result is false. Since groups are the logical OR of their members (it is sufficient that one of the members matches the current system), the class @samp{have_cc} will be defined above if either @file{/usr/ucb/cc} or @file{/local/gnu/cc} exist, or both. @cindex Classes based on shell commands @cindex Shell commands which define classes @cindex User programs which define classes @mbindex Define classes based on result of user program @c ..................................................... @c SUBSECTION @c ..................................................... @node Feedback classes, Writing plugin modules, shellcommand classes, Defining classes @subsection Feedback classes Classes may be defined as the result of actions being carried out by cfagent. For example, if a file gets copied, needs to be edited or if diskspace falls under a certain threshhold, cfagent can be made to respond by activating classes at runtime. This allows you to create dynamically responsive programs which react to the changing environment. These classes are defined as part of other statements with clauses of the form @example define=@var{classlist} @end example Classes like these should generally be declared at the start of a program unless the @code{define} statements always precede the actions which use the defined classes, with @code{addinstallable}. @c ..................................................... @c SUBSECTION @c ..................................................... @node Writing plugin modules, , Feedback classes, Defining classes @subsection Writing plugin modules If the regular mechanisms for setting classes do not produce the results you require for your configuration, you can write your own routines to concoct the classes of your dreams. Plugin modules are added to cfagent programs from within the actionsequence, (see Reference manual). They allow you to write special code for answering questions which are too complex to answer using the other mechanisms above. This allows you to control classes which will be switched on and the moment at which your module attempts to evaluate the condition of the system. Modules must lie in a special directory defined by the variable @code{moduledirectory}. @cindex moduledirectory @vindex moduledirectory They must have a name of the form @file{module:@var{mymodule}} and they must follow a simple protocol. Cfagent will only execute a module which is owned either by root or the user who is running cfagent, if it lies in the special directory and has the special name. A plug-in module may be written in any language, it can return any output you like, but lines which begin with a @samp{+} sign are treated as classes to be defined (like @option{-D}), while lines which begin with a @samp{-} sign are treated as classes to be undefined (like @option{-N}). Lines starting with @samp{=} are variables/macros to be defined. Any other lines of output are cited by cfagent, so you should normally make your module completely silent. Here is an example module written in perl. First we define the module in the cfagent program: @smallexample control: moduledirectory = ( /local/cfagent/modules ) actionsequence = ( files module:myplugin "module:argplugin arg1 arg2" copy ) ... AddInstallables = ( specialclass ) @end smallexample @noindent Note that the class definitions for the module should also be defined in as @code{AddInstallables}, if this is more convenient. NOTE: you @emph{must} declare the classes before using them in the cfagent configuration, or else those actions will be ignored. Next we write the plugin itself. @smallexample #!/usr/bin/perl # # module:myplugin # # lots of computation.... if (@var{special-condition}) @{ print "+specialclass"; @} @end smallexample Modules inherit the environment variables from cfagent and accept arguments, just as a regular shellcommand does. @smallexample #!/bin/sh # # module:myplugin # /bin/echo $* @end smallexample Cfagent defines the classes as an environment variable so that programs have access to these. E.g. try the following module: @smallexample #!/usr/bin/perl print "Decoding $ENV@{CFALLCLASSES@}\n"; @@allclasses = split (":","$ENV@{CFALLCLASSES@}"); while ($c=shift(@@allclasses)) @{ $classes@{$c@} = 1; print "$c is set\n"; @} @end smallexample Modules can define macros in cfagent by outputting strings of the form @smallexample =@var{variablename}=@var{value} @end smallexample When the @code{$(allclasses)} variable becomes too large to manipulate conveniently, you can access the complete list of currently defined classes in the file @file{/var/cfengine/state/allclasses}. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node The generic class any, Debugging tips, Defining classes, More advanced concepts @section The generic class @code{any} @vindex any @cindex Wildcard, any class @cindex Class, generic any The generic wildcard @code{any} may be used to stand for any class. Thus instead of assigning actions for the class @code{sun4} only you might define actions for any architecture by specifying: @smallexample any:: @var{actions} @end smallexample If you don't specify any class at all then cfengine assumes a default value of @code{any} for the class. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Debugging tips, Access control, The generic class any, More advanced concepts @section Debugging tips A useful trick when debugging is to eliminate unwanted actions by changing their class name. Since cfengine assumes that any class it does not understand is the name of some host, it will simply ignore entries it does not recognize. For example: @smallexample myclass:: @end smallexample @noindent can be changed to @smallexample Xmyclass:: @end smallexample @noindent Since @code{Xmyclass} no longer matches any defined classes, and is not the name of any host it will simply be ignored. The @code{-N} option can also be used to the same effect. (see Reference manual). @vindex -N option @cindex -N option @cindex Annulling entries when debugging @cindex Debugging, annulling entries @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Access control, Wildcards in directory names, Debugging tips, More advanced concepts @section Access control It is sometimes convenient to be able to restrict the access of a program to a handful of users. This can be done by adding an access list to the @code{control:} section of your program. For example, @smallexample control: ... access = ( mark root ) @end smallexample @noindent would cause cfengine to refuse to run the program for any other users except mark and root. Such a restriction would be useful, for instance, if you intended to make set-user-id scripts but only wished certain users to be able to run them. If the access list is absent, all users can execute the program. @cindex Setuid scripts @cindex Access control @cindex Restricting access Note: if you are running cfagent via the @code{cfrun} program @cindex cfrun then cfagent is always started with the same user identity as the cfservd process on the remote host. @cindex cfservd and access keyword Normally this is the root user identity. This means that the access keyword will have no effect on the use of the command @code{cfrun}. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Wildcards in directory names, File sweeps, Access control, More advanced concepts @section Wildcards in directory names @cindex Wildcards, in directory names @cindex Directory Names, use of wildcards In the two actions @code{files} and @code{tidy} you define directory names at which file checking or tidying searches should start. One economical feature is that you can define a whole group of directories at which identical searches should start in one fell swoop by making use of @emph{wildcards}. For example, the directory names @smallexample /usr/*/* /bla/*/ab?/bla @end smallexample @noindent represent all of the @emph{directories} (and only directories) which match the above wildcard strings. Cfagent opens each matching directory and iterates the action over all directories which match. The symbol @samp{?} matches any single character, whereas @samp{*} matches any number of characters, in accordance with shell file-substitution wildcards. @cindex Wildcards @cindex Patterns When this notation is used in directory names, it always defines the starting point for a search. It does not tell the command how to search, only where to begin. The @code{pattern} directive in @code{tidy} can be used to specify patterns when tidying files and under @code{files} all files are considered, (see Reference manual), @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node File sweeps, Security in File sweeps, Wildcards in directory names, More advanced concepts @section Recursive file sweeps/directory traversals File sweeps are searches through a directory tree in which many files are examined and considered for processing in some way. There are many instances where one uses cfagent to perform a file sweep. @itemize @bullet @item As part of a @code{files} action, for checking access rights and ownership of files. @cindex @code{files}, file sweeps @item As part of a @code{tidy} action, for checking files for deletion. @cindex @code{tidy}, file sweeps @item As part of a @code{copy} action, while recursively checking whether to copy a file tree. @cindex @code{copy}, file sweeps @item As part of an @code{editfiles} action, while recursively checking whether to edit the files in a tree of files. @cindex @code{editfiles}, file sweeps @end itemize @noindent The problem with file sweeps is that they can be too sweeping! Often you are not interested in examining every single file in a file tree. You might wish to perform a search @itemize @bullet @item excluding certain named directories and their subdirectories with @code{ignore}. @item excluding certain files and directories matching a specific pattern. @item including only a subset of files matching specific patterns. @item filter out very specific file types. @end itemize @noindent The tidy action is slightly different in this respect, since it already always expects to match a specific pattern. One is generally not interested in a search which deletes everything except for a named pattern: this would be too dangerous. For this reason, the syntax of @code{tidy} does not allow ignore, include and exclude. It is documented in the section on tidying, (see Reference manual). Items declared under the global @code{ignore} section affect files, copy, links and tidy. For file sweeps within files, copy and links, you may provide private ignore lists using @code{ignore=}. The difference between exclude and ignore is that ignore can deal with absolute directories. It prunes directories, while exclude only looks at the files within directories. @cindex @code{ignore=} @cindex Ignoring, private lists in files, copy and links For file sweeps within @code{files} and @code{copy} you can specify specific search parameters using the keywords @code{include=} and @code{exclude=} and as of version 1.6.x @code{filter=}. @cindex @code{include=} @cindex @code{exclude=} @cindex @code{filter=} @vindex @code{include=} @vindex @code{exclude=} @vindex @code{filter=} For example, @smallexample files: /usr/local/bin m=0755 exclude=*.ps action=fixall @end smallexample @noindent In this example cfagent searches the entire file tree (omitting any directories listed in the ignore-list and omitting any files ending in the extension @file{.ps}), (see Reference manual). Specifying the @code{include=} keyword is slightly different since it automatically restricts the search to only named patterns (using @code{*} and @code{?} wildcards), whenever you have one or more instances of it. If you include patterns in this way, cfagent ignores any files which do not match the given patterns. It also ignores any patterns which you have specified in the global ignore-list as well as patterns excluded with @code{exclude=@var{pattern}}. In other words, exclusions always override inclusions. If you exclude a pattern or a directory and wish to treat it in some special way, you need to code an explicit check for that pattern as a separate entity. For example, to handle the exluded @file{.ps} files above, you would need to code something like this: @smallexample files: /usr/local/bin m=0644 include=*.ps action=fixall @end smallexample Note: don't be tempted to enclose your wildcards in quotes. The quotes will be treated literally and the pattern might not match the way you would expect. @cindex exclude=, problems For @code{editfiles} the syntax is somewhat different. Here one needs to add lines to the edit stanza: @smallexample editfiles: @{ /tmp/testdir Include .* Exclude bla.* Ignore "." Ignore ".." Recurse 6 ReplaceAll "search" With "replace" @} @end smallexample @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Security in File sweeps, Log files, File sweeps, More advanced concepts @section Security in Recursive file sweeps Recursively descending into directories and performing a globally `destructive' change is an inherently risky thing to do, unless you are certain of the directory structure. Suppose, for instance, that a user with write access to the filesystem added a symbolic link to @file{/etc/passwd}, and we were doing a recursive deletion. Suddenly, cfengine becomes a destructive weapon. The default behaviour is that cfengine does not follow symbolic links in recursive descents, for this reason. The option @code{travlinks} can be set to true, in order to change this. However, in general, you should never change this option, especially if untrusted users have access to parts of the filesystem, e.g. if you clear @file{/tmp} recursively. Cfagent checks for link race attacks, in which users try to swap a directory for a link, in between system calls, to trick cfagent into believing that a link is a directory, as of version 2.0.3 (and 1.6.4). @cindex Race condition @cindex @code{travlinks} Note that, even if @code{travlinks} is set to true, cfagent will not follow symbolic links that are not owned by the agent user ID; this is to minimize the possibilty of link race attacks, in which users with write access could divert the agent to another part of the filesystem. @cindex Security, link races and travlinks @cindex travlinks @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Log files, Quoted strings, Security in File sweeps, More advanced concepts @section Log files written by cfagent @cindex Log files @cindex .cfengine.rm @cindex /var/cfengine/cfengine.log @cindex /var/log/cfengine/cfengine.log Cfagent keeps two kinds of log-file privately and it allows you to log its activity to syslog. Syslog logging may be switched on with the @code{Syslog} variable, (see Reference manual). The first log cfagent keeps is for every user (every subdirectory of a home directory filesystem). A file @code{~/.cfengine.rm} keeps a list of all the files which were deleted during the last pass of the @code{tidy} function. This is useful for users who want to know files have been removed without their blessing. This helps to identify what is happening on the system in case of accidents. @vindex /var/cfengine/cfengine.log Another file is built when cfagent searches through file trees in the @code{files} action. This is a list of all programs which are setuid root, or setgid root. Since such files are a potential security risk, cfagent always prints a warning when it encounters a new one (one which is not already in its list). This allows the system administrator to keep a watchful eye over new programs which appear and give users root access. The cfengine log is called @code{/var/cfengine/cfengine.log}. The file is not readable for general users. @cindex setuid root log @cindex setgid root log @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Quoted strings, Regular expressions, Log files, More advanced concepts @section Quoted strings In several cfengine commands, you use quoted strings to define a quantity of text which may contain spaces. For example @smallexample control: macro = ( "mycommand" ) editfiles: @{ $(HOME)/myfile AppendIfNoSuchLine 'This text contains space' @} @end smallexample @noindent In each case you may use any one of the three types of quote marks in order to delimit strings, @smallexample ' @var{or} " @var{or} ` @end smallexample If you choose, say @code{"}, then you may not use this symbol within the string itself. The same goes for the other types of string delimiters. Unlike the shell, cfengine treats these three delimiters in precisely the same way. There is no difference between them. @cindex Strings @cindex Quoting strings @vindex " @vindex ' @vindex ` @mbindex How do I quote quotes? If you need to quote a quoted string, then you should choose a delimiter which does not conflict with the substring before version 2.0.7. From version 2.0.7, you can escape quotes. @smallexample qstring = ( "One string\"with substring\" escaped" ) @end smallexample Note that you can use special variables for certain symbols in a string @xref{Variable substitution}. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Regular expressions, Iterating over lists, Quoted strings, More advanced concepts @section Regular expressions Regular expressions can be used in cfagent in connection with @code{editfiles} and @code{processes} to search for lines matching certain expressions. A regular expression is a generalized wildcard. In cfagent wildcards, you can use the characters '*' and '?' to match any character or number of characters. Regular expressions are more complicated than wildcards, but have far more flexibility. @emph{NOTE: the special characters @samp{*} and @samp{?} used in wildcards do not have the same meanings as regular expressions!}. Some regular expressions match only a single string. For example, every string which contains no special characters is a regular expression which matches only a string identical to itself. Thus the regular expression @samp{cfengine} would match only the string "cfengine", not "Cfengine" or "cfengin" etc. Other regular expressions could match more general strings. For instance, the regular expression @samp{c*} matches any number of c's (including none). Thus this expression would match the empty string, "c", "cccc", "ccccccccc", but not "cccx". Here is a list of regular expression special characters and operators. @table @samp @item \ The backslash character normally has a special purpose: either to introduce a special command, or to tell the expression interpreter that the next character is not to be treated as a special character. The backslash character stands for itself only when protected by square brackets @code{[\]} or quoted with a backslash itself @samp{\\}. @item \b Matches word boundary operator. @item \B Match within a word (operator). @item \< Match beginning of word. @item \> Match end of word. @item \w Match a character which can be part of a word. @item \W Match a character which cannot be part of a word. @item @var{any character} Matches itself. @item . Matches any character @item * Match zero or more instances of the previous object. e.g. @samp{c*}. If no object precedes it, it represents a literal asterisk. @item + Match one or more instances of the preceding object. @item ? Match zero or one instance of the preceding object. @item @{ @} Number of matches operator. @samp{@{5@}} would match exactly 5 instances of the previous object. @samp{@{6,@}} would match at least 6 instances of the previous object. @samp{@{7,12@}} would match at least 7 instances of, but no more than 12 instances of the preceding object. Clearly the first number must be less than the second to make a valid search expression. @item | The logical OR operator, OR's any two regular expressions. @item [@var{list}] Defines a list of characters which are to be considered as a single object (ORed). e.g. @samp{[a-z]} matches any character in the range a to z, @samp{abcd} matches either a, b, c or d. Most characters are ordinary inside a list, but there are some exceptions: @samp{]} ends the list unless it is the first item, @samp{\} quotes the next character, @samp{[:} and @samp{:]} define a character class operator (see below), and @samp{-} represents a range of characters unless it is the first or last character in the list. @item [^@var{list}] Defines a list of characters which are NOT to be matched. i.e. match any character except those in the list. @item @samp{[:@var{class}:]} Defines a class of characters, using the ctype-library. @table @code @item alnum Alpha numeric character @item alpha An alphabetic character @item blank A space or a TAB @item cntrl A control character. @item digit 0-9 @item graph same as print, without space @item lower a lower case letter @item print printable characters (non control characters) @item punct neither control nor alphanumeric symbols @item space space, carriage return, line-feed, vertical tab and form-feed. @item upper upper case letter @item xdigit a hexadecimal digit 0-9, a-f @end table @item @samp{( )} Groups together any number of operators. @item \@var{digit} Back-reference operator (refer to the GNU regex documentation). @item ^ Match start of a line. @item $ Match the end of a line. @end table @noindent Here is a few examples. Remember that some commands look for a regular expression match of part of a string, while others require a match of the entire string (see Reference manual). @smallexample ^# match string beginning with the # symbol ^[^#] match string not beginning with the # symbol ^[A-Z].+ match a string beginning with an uppercase letter followed by at least one other character @end smallexample @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Iterating over lists, , Regular expressions, More advanced concepts @section Iterating over lists Shell list variables are normally defined by joining together a list of directories using a concatenation character such as @samp{:}. A typical example of this is the PATH variable: @example PATH=/usr/bin:/usr/local/bin:/usr/sbin @end example It is convenient to be able to use such variables to force cfagent to iterative over a list. This gives us a compact way of writing repeated operations and it allows a simple method of communication with the shell environment. For security reasons, iteration is supported only in the following contexts: @itemize @bullet @item in the `to' field of a multiple link action, @item in the `from' field of a copy action, @item in the directory field of a tidy action, @item in the directory field of the files action, @item in the ignore action, @item in a shell command. @end itemize This typically allows communication with PATH-like environment variables in the shell. @cindex Split @cindex Iteration over lists @mbindex Iterating over lists @vindex Split In these contexts, any variable which has the form of a list joined together by colons will be iterated over at compilation time. Note that you can change the value of the list separator using the @code{Split} variable in the control section of the program (see Reference manual). For example, to link all of the binary files in the PATH environment variable to a single directory, tidying dead links in the process, you would write @smallexample control: actionsequence = ( links tidy ) links: /allbin +> $(PATH) tidy: # Hopefully no-match matches nothing /allbin pattern=no-match age=0 links=tidy @end smallexample @noindent @var{no-match} is not a reserved word in cfengine, this is just a string you do not expect to match any file. Alternatively, you might want to define an internal list using a space as a separator: @mbindex Split, using a space @smallexample control: Split = ( " " ) mylist = ( "mark ricky bad-dude" ) tidy: /mnt/home1/$(mylist) pattern=*.cfsaved age=1 @end smallexample @noindent This example iterates the tidy action over the directories @file{/mnt/home1/mark}, @file{/mnt/home1/ricky} and @file{/mnt/home1/bad-dude}. The number of list variables in any path or filename should normally be restricted to one or two, since the haphazard combination of two lists will seldom lead to any meaningful pattern. The only obvious exception is perhaps to iterate over a common set of child-directories like @file{bin}, @file{lib} etc in several different package directories. @cindex Multiple package configuration @cindex Package configuration, multiple @mbindex Configure multiple packages @c ********************************************************************** @c CHAPTER @c ********************************************************************** @node Global configurations, Using cfengine as a front-end for cron, More advanced concepts, Top @chapter Designing a global system configuration This chapter is about building strategies for putting together a site configuration for your entire network. @menu * General considerations:: * Using netgroups:: a common database for classes * Files and links:: * Copying files:: * Managing processes:: * NFS resources:: the cfengine model * Using the automounter:: * Editing files:: * Disabling and the file repository:: * Running user scripts:: * Compressing logs:: * ACLs:: @end menu @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node General considerations, Using netgroups, Global configurations, Global configurations @section General considerations In order to use any system administration tool successfully, you have to make peace with your system by deciding exactly what you expect and what you are willing to do to achieve the results. You need to decide what you will consider to be acceptable and what is to be considered completely untenable. You need to make these decisions because otherwise you will only be confused later when things don't go the way you expected. @cindex System policy @cindex Policy for running the system Experience shows that the most successful policies for automation involve keeping everything as simple as possible. The more uniform or alike your machines are, the easier they are to run and the happier users are. Sometimes people claim that they need such great flexibility that all their machines should be different. This belief tends to be inversely proportional to the number of machines they run and generally only applies to very special development environments! Usually you will only need one or two machines to be special and most can be made very similar. Site configuration is about sharing and controlling resources. The resources include disks (filespace), files, data, programs, passwords and physical machines. Before planning your sitewide configuration you should spend some time deciding how you would like things to work. In the remaining parts of this chapter, you will find some hints and tips about how to proceed, but remember that when push comes to shove, you must make your own choices. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Using netgroups, Files and links, General considerations, Global configurations @section Using netgroups @cindex netgroups @cindex NIS @vindex /etc/exports @cindex Exporting filesystems If you use the network information service (NIS) on your local network then you may already have defined @emph{netgroups} consisting of lists of hosts which belong to specific owners at your site. If you have, then you can use these groups within cfengine. This means that you can use the same groups in the @code{/etc/exports} file as you use to define the mount groups and classes. A netgroup is a list of hostnames or user names which are registered in the network information service (NIS) database under a specific name. In our case we shall only be interested in lists of hostnames. To make a netgroup you need to define a list in the file @code{/etc/netgroup} on your NIS server. If you are not the NIS administrator, you will have to ask to have a netgroup installed. The form of a netgroup list of hosts is: @smallexample mylist-name (host1,,) (host2,,) (host3,,) (host4,,) norway-sun4-host (saga,,) (tor,,) (odin,,) foes-linux-hosts (borg,,) @end smallexample @noindent Each list item has three entries, but only the first is relevant for a host list. See the manual pages on netgroups for a full explanation of the meaning of these fields. The usefulness of netgroups is that they can be used to stand for a list of hostnames in system files like @file{/etc/exports}. This compresses the amount of text in this file from a long list to a single name. It also means that if you use the same list of hosts from a netgroup inside cfengine when defining groups and classes, you can be sure that you are always using the same list. In particular it means that you don't have to update multiple copies of a list of hosts. The netgroups can now be used in cfengine programs by using the @code{+} or @code{@@+} symbols in the @code{groups} section. (see Reference manual). @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Files and links, Copying files, Using netgroups, Global configurations @section Files and links File and link management takes several forms. Actions are divided into three categories called @code{files}, @code{tidy} and @code{links}. The first of these is used to check the existence of, the ownership and permissions of files. The second concerns the systematic deletion of garbage files. The third is a link manager which tests, makes and destroys links. The monitoring of file access bits and ownership can be set up for individual files and for directory trees, with controlled recursion. Files which do not meet the specified criteria can be `fixed' ---i.e. automatically set to the correct permissions, or can simply be brought to the attention of the system administrator by a warning. The syntax of such a command is as follows: @smallexample files: @var{class}:: /@var{path} mode=@var{mode} owner=@var{owner} group=@var{group} recurse=@var{no-of-levels} action=@var{action} @end smallexample @noindent The directory or file name is the point at which cfagent begins looking for files. From this point the search for files proceeds recursively into subdirectories with a maximum limit set by the @code{recurse} directive, and various options for dealing with symbolic links and device boundaries. The mode-string defines the allowed file-mode (by analogy with @samp{chmod}) and the owner and group may specify lists of acceptable user-ids and group-ids. The action taken in response to a file which does not meet acceptable criteria is specified in the action directive. It includes warning about or directly fixing all files, or plain files or directories only. Safe defaults exist for these directives so that in practice they may be treated as options. For example, @smallexample files: any:: /usr/*/bin mode=a+rx,o-w own=root r=inf act=fixall @end smallexample @noindent which (in abbreviated form) would check recursively all files and directories starting from directories matching the wildcard (e.g. @file{/usr/local/bin}, @file{/usr/ucb/bin}). By default, @code{fixall} causes the permissions and ownership of the files to be fixed without further warning. One problem with symbolic links is that the files they point to can get deleted leaving a `hanging pointer'. Since cfagent can make many hundreds of links without any effort, there is the danger that, in time, the system could become full of links which don't point anywhere. To combat this problem, you can set the option @code{links=tidy} in the files section. If this is set, cfagent will remove any symbolic links which do not point to existing files (see Reference manual). The creation of symbolic links is illustrated in figure 1 and the checking algorithm was discussed in section 2. In addition to the creation of single links, one may also specify the creation of multiple links with a single command. The command @smallexample links: binaryhost:: /local/elm/bin +> /local/bin @end smallexample @noindent links all of the files in @file{/local/elm/bin} to corresponding files in @file{/local/bin}. This provides, amongst other things, one simple way of installing software packages in regular `bin' directories without controlling users' PATH variable. A further facility makes use of cfagent's knowledge of available (mounted) binary resources to search for matches to specific links. Readers are referred to the full documentation concerning this feature. The need to tidy junk files has become increasingly evident during the history of cfengine. Files build up quickly in areas like @file{/tmp}, @file{/var/tmp}. Many users use these areas for receiving large ftp-files so that their disk usage will not be noticed! To give another example, just in the last few months the arrival of netscape World Wide Web client, with its caching facilities, has flooded hard-disks at Oslo with hundreds of megabytes of WWW files. In addition the regular appearance of @file{core} files@footnote{On some systems, core dumps cannot be switched off!} and compilation by-products (@samp{.o} files and @samp{.log} files etc.) fills disks with large files which many users do not understand. The problem is easily remedied by a few lines in the cfagent configuration. Files can be deleted if they have not been accessed for n-days. Recursive searches are both possible and highly practical here. In following example: @smallexample tidy: AllHomeServers:: home pattern=core r=inf age=0 home/.wastebasket pattern=* r=inf age=14 home/.netscape-cache pattern=cache????* r=inf age=2 home/.MCOM-cache pattern=cache????* r=inf age=2 home/.netscape pattern=cache????* r=inf age=2 @end smallexample @noindent all hosts in the group @samp{AllHomeServers} are instructed to iterate over all users' home directories (using the wildcard @code{home}) and look for files matching special patterns. Cfagent tests the @emph{access time} of files and deletes only files older than the specified limits. Hence all core files, in this example, are deleted immediately, whereas files in the subdirectory @file{.wastebasket} are deleted only after they have lain there untouched for 14 days, and so on. @cindex Tidying files @cindex Backup policy As a system administrator you should, of course, exercise great caution when making rules which can delete users' files. A single slip of the hand can result in a rule which will irretrievably delete files. When making a `tidy' strategy you should probably coordinate with your backup policy. You should not delete files until after you have taken a backup, so that --- if the worst should happen --- you are covered against possible accidents. Cfagent helps to some extent to keep track of what files it deletes. When tidying users' home directories it creates a log file of all files which were deleted on the last tidy operation. This log is called @code{~/.cfengine.rm}. You might consider tidying certain files only once a week, in which case a command such as @smallexample tidy: AllHomeServers.Sunday:: @var{files to tidy} @end smallexample @noindent could be useful. Nonsense files, such as `core' files could be tidied every night. @cindex core files, caution! @emph{NOTE! Be careful when telling cfagent to delete core files. If you write a wildcard like @code{core*}, then you could risk deleting important system files such as @code{core.h}.} @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Copying files, Managing processes, Files and links, Global configurations @section Copying files The administration of a system often requires the copying of files. The reason for this is usually that we would like to distribute a copy of a particular file, from some master location and ensure that all of the copies are up to date. Another use for this is to install software from one directory (perhaps on a CD ROM) to another. Cfagent helps this process by allowing you to copy a single file or a file tree, from one directory to another, perhaps checking the permissions and owners of a file to adjust the copies in some special way. The files are checked by cfagent using one of two methods. @itemize @bullet @item A date-stamp comparison with a master file, using last-change times, can be used to tell cfagent to recopy a file from the master if the master file is newer than the copy. @item A checksum can be computed for each file and compared with one for the master file. If the contents of the copy file differs in any way from the master, the file will be re-copied. @end itemize @noindent Cfengine allows you to do the following @itemize @bullet @item Copy a single file to another file in a different location, perhaps with a new name, new permissions and a different owner. @item Copy a single file to all users on the system, changing the owner of the file for each user automatically. (This could be used to distribute and update standard setup files.) @item Recursively copy an entire file tree, omitting files which match a list of wildcard-patterns, or linking certain files instead of copying. @end itemize @noindent You can find out more about copying in the reference section. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Managing processes, NFS resources, Copying files, Global configurations @section Managing processes Cfagent allows you to check for the existence of processes on your system, send those processes signals (such as kill) and perhaps restart those processes. Typical applications for this are sending @file{cron} and @file{inetd} the HUP signal, after editing their configuration files, or killing unwanted processes (such as user programs which hog the system at peak usage times). You can read more about this in the reference section . @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node NFS resources, Using the automounter, Managing processes, Global configurations @section Cfengine's model for NFS-mounted filesystems @cindex cfengine model @cindex NFS mounted filesystems Most of the filesystems that you will want to make available across the network are going to fall into one of two categories. In cfengine parlance these are called @emph{home directories} and @emph{binary directories}. A home directory is a place where users' login directories are kept. This is traditionally a directory called @file{/home} or @file{/users} or some subdirectory of these. A binary directory is a place where compiled software is kept. Such files (which do not belong to the pure operating system release) are often placed in a directory called @file{/usr/local} or simply @file{/local}. In this chapter we shall consider a scheme for using cfengine to make NFS filesystem management quite painless. @menu * NFS filesystem resources:: a conceptual introduction * Unique filesystem mountpoints:: avoiding collisions * How does it work?:: * Special variables:: binserver etc. * Mount example:: example program @end menu @c ..................................................... @c SUBSECTION @c ..................................................... @node NFS filesystem resources, Unique filesystem mountpoints, NFS resources, NFS resources @subsection NFS filesystem resources @cindex NFS resources Using the Network File System (NFS) in a large workstation environment requires a bit of planning. The idea of NFS is to share files on one host with other hosts. In most cases, filesystems to be shared across the network fall into two categories: @emph{binary} filesystems (those which contain compiled software) and @emph{user} or @emph{home} filesystems (which contain users' login areas). The most simple minded way to share resources would be to mount every resource (each available NFS filesystem) onto every host. To avoid collisions, each filesystem would have to have a unique name. This is one possibility, but not a very intelligent one. As experienced users will realize, cross-mounting too many NFS filesystems is a recipe for all kinds of trouble. @cindex Binary server @cindex Home server Cfengine offers a simple model which can help you pick out only the resources you need from the list of NFS filesystems. It will then mount them automatically and edit the appropriate filesystem tables. It does this by defining classes of hosts. For instance --- you really don't need to mount a binary filesystem for an @code{ultrix} system onto an @code{HPUX} system. There would be no point --- binary resources are @emph{architecture} or @emph{hard-class dependent}. But home directories are architecture independent. Cfengine lets you to define a list of allowed servers for various hosts so that only filesystems from the servers will be considered for mounting! @c ..................................................... @c SUBSECTION @c ..................................................... @node Unique filesystem mountpoints, How does it work?, NFS filesystem resources, NFS resources @subsection Unique filesystem mountpoints @cindex Mount points @cindex Naming convention The first step towards treating NFS filesystems as network resources is to invent a naming scheme so that every filesystem has a unique name on which it can be mounted. If we don't sort this out now, we could find two or more hosts with a filesystem called @code{/usr/local}, both of which we might like to mount since they contain different software. A simple but extremely useful naming scheme is the following. @footnote{This unique naming scheme was suggested to me originally by Knut Borge at USIT of the University of Oslo.} If you don't like this scheme you can invent your own, but the remainder of the text will encourage you to use this one. If you follow this scheme, exactly as described here, you will never have any problems with mount points. We shall describe the scheme in detail below. Here are some points to digest: @itemize @bullet @item When mounting a remote filesystem on your local system, the local and remote directories should always have exactly the same name. @item The name of every filesystem mountpoint should be unique and tell you something meaningful about where it is located and what its function is. @item You can always make links from special unique names to more general names like @file{/usr/local}. If you this involves compiled software and you do this on one host, you should do it on others which are of the same type. @item It doesn't matter whether software compiles in the path names of special directories into software as long as you follow the points above. @end itemize @noindent Each filesystem is given a directory name composed of three parts: @smallexample /site/host/contents @end smallexample @noindent The first directory (which only exists to create a suitable mountpoint) is the name of your local site. If you are a physics department at a university (with a separate setup) you could call this `physics'. It could be your company name or whatever. The second piece is the name of the host to which the disk space is physically attached. The final piece is the name of the filesystem. Here are some typical examples: @smallexample /physics/einstein/local # /usr/local for einstein@@physics /physics/newton/u1 # user partition 1 for newton@@physics @end smallexample @noindent On the machines which are home to the `local' partition, it is better to make a link to @code{/usr/local} than call the filesystem @code{/usr/local} directly. This is because it makes the procedure of organizing the entire network much clearer. It is worth noting that, when you ask cfagent to mount such a resource, it will automatically make the mount directory and can easily be asked to make a link to @code{/usr/local}, so this small amount of extra work is really no work at all. The whole naming convention is compactly summarized by defining a mount point variable, @code{mountpattern}. With the present scheme, this can be defined as @smallexample mountpattern = ( /$(site)/$(host) ) @end smallexample @noindent so that it evaluates to the name of the host executing the file regardless of who that may be. This variable is used together with the @code{homepattern} pattern variable, which is used to distinguish between home directories and binary resources. (See @code{homepattern} in the reference section). You can think of this as being part of the naming convention. In this text, we use the convention @code{u1 u2 u3...} for home disks. You could equally well use @code{home1 home2...} etc. As long as the name is unique, it doesn't matter. The full list of named resources should now be listed in the @code{mountables} list, which is simply a list of all the resources available for mounting on the network. @c ..................................................... @c SUBSECTION @c ..................................................... @node How does it work?, Special variables, Unique filesystem mountpoints, NFS resources @subsection How does it work? @cindex Binary servers, declaring @cindex Home servers, declaring @cindex cfengine model, how it works Once you have defined your unique names, how does cfagent know what to mount? The idea is now to define a list of servers for each class of hosts. Suppose we make a @code{binserver} declaration: @smallexample binservers: mygroup.sun4:: einstein newton @end smallexample @noindent This would tell cfagent that it should mount all binary resources from hosts @code{einstein} or @code{newton} onto any host of type @code{sun4} in the group @code{mygroup}. Every filesystem which is listed in @code{mountables} and is not a home directory will be mounted. Home directories and binary resources are kept separate automatically by cfagent, because a home directory is one whose contents-name matches the @code{homepattern} pattern variable. @xref{Unique filesystem mountpoints}. A @code{homeserver} declaration: @smallexample homeservers: mygroup:: einstein newton schwinger feynman @end smallexample @noindent would correspondingly mean mount all the home directory resources on the hosts in the list on all hosts in the group @code{mygroup}. Clearly it is unnecessary to distinguish between the architecture platform types of the actual servers for user directories. In each case, cfagent will mount filesystems, make the appropriate directories for the mount point and edit the filesystem table. @c ..................................................... @c SUBSECTION @c ..................................................... @node Special variables, Mount example, How does it work?, NFS resources @subsection Special variables @cindex Linking to binservers @cindex Special variables @cindex Variables, cfengine model @vindex binserver Once you have mounted a resource on a unique directory, you have access to all of the relevant filesystems on your network --- but you really wanted the `local' filesystem to be mounted on @code{/usr/local}. All you need do now is to make a link: @smallexample links: any:: /usr/local -> /$(site)/$(binserver)/local @end smallexample @noindent The meaning of this is that, on any host, the directory @code{/usr/local} should be a link to the `nearest' binary server's `local' resource. The @code{$(binserver)} variable can in principle expand to any binary server in the list. In practice, cfagent goes through the list in order and picks the first filesystem resource which matches. Could this lead to a collision? Suppose we are on the host `einstein' and we execute the above command. The host `einstein' has a filesystem @code{/physics/einstein/local} on its local disk --- it is in fact the binary server for the network, so it certainly doesn't need to mount any NFS filesystems. But this is no problem because cfagent automatically treats @code{$(host)} as the highest priority binary server for any host. That means that if you have a local filesystem, it will always have priority. @cindex Binary server, matching @cindex binserver variable and actionsequence @vindex binserver In contrast, if the host `schwinger' ran the command above, it would find no local filesystem called @code{/physics/schwinger/local}, so it would go along the list of defined binary servers, find `einstein' and try again. It will succeed in finding `einstein' @emph{provided all the binary servers were mounted before the link command is executed}. This means that you should structure the @code{actionsequence} so that all filesystems are mounted before any links are made. With a little practice, the cfengine model can lead to an enormous simplification of the issue of NFS-mountable resources. @cindex Exporting filesystems NOTE: cfengine does not try to export filesystems, only mount already exported filesystems. If you want to automate this procedure also, you can use the @code{editfiles} facility to add entries to @file{/etc/exports} (see @code{editfiles} in the Reference manual). In practice this is very difficult to do and perhaps not desirable. @node Mount example, , Special variables, NFS resources @subsection Example programs for mounting resources Let's write a very simple configuration for a network with only one server called hal, where all the hosts are of the same operating system type. In such an example we can avoid using classes altogether. @smallexample control: site = ( univ ) domain = ( univ.edu ) actionsequence = ( mountall mountinfo addmounts mountall links ) mountpattern = ( /univ ) homepattern = ( home? ) binservers: hal homeservers: hal mailserver: hal:/var/spool/mail mountables: hal:/univ/home1 hal:/univ/home2 hal:/univ/local links: /usr/local -> /univ/local @end smallexample In this example, we have only one type of host so the configuration is the same for each of them: no class references are required. If we look through the action sequence we see that the program first mounts all the filesystems which are already defined on each host. It does this to be sure that everything which is already set up to be mounted is mounted. Let's assume that there are no problems with this. The next thing that happens is that @code{mountinfo} builds a list of the filesystems which each host has successfully mounted. Then by calling @code{addmounts} we ask cfagent to check whether the host is missing any filesystems. What happens is that cfagent first looks to see what servers are defined for each host. In this case all hosts on the network have only one server: hal. Hal is defined as a server for both binary data and `home' data --- i.e. users' home directories. The list @code{mountables} tells cfagent what filesystems are available over the network for the server hal. There are three filesystems which can be mounted, called @file{/univ/home1}, @file{/univ/home2} and @file{/univ/local}. Cfagent checks to see whether each of these filesystems is mounted and, if not, it builds the necessary directories, edits the necessary files and mounts the filesystems. Finally we come to @code{links} in the action sequence. This tells cfagent to look at the defined links. There is one link defined: a link from @file{/usr/local} to the mounted filesystem @file{/univ/local}. Cfagent checks and tries to make the link if necessary. If all goes well, each host on the network should now have at least three filesystems mounted and a link from @file{/usr/local} to @file{/univ/local}. Here is another simple example program for checking and automatically mounting an NFS based @code{/usr/local} and all home directories onto all hosts on a small network. Here we have several servers and must therefore use some classes. @smallexample # # Mounts # control: site = ( mysite ) domain = ( mysite.country ) sysadm = ( mark ) netmask = ( 255.255.255.0 ) actionsequence = ( mountall mountinfo addmounts mountall links ) mountpattern = ( /$(site)/$(host) ) homepattern = ( u? ) # u1 u2 u3 etc.. groups: MyGroup = ( host1 host2 binserver1 binserver2 ) ###################################################################### homeservers: MyGroup:: host1 binservers: MyGroup.sun4:: server1 MyGroup.ultrix:: server2 mailserver: host1:/usr/spool/mail mountables: host1:/mysite/host1/u1 host1:/mysite/host1/u2 server1:/mysite/server1/local server2:/mysite/server2/local ########################################################################## links: /usr/local -> /$@{site@}/$@{binserver@}/local @end smallexample Let's suppose we run this program on host2 which is an ultrix machine. This host belongs to the class @code{mygroup} and the hard-class @code{ultrix}. This tells us that its homeserver is host1, its binary server is server2 and its mailserver is host1. Moreover, since the homepattern matches any filesystem ending in u-something, it recognizes the two home directories in the mountables list --- and therefore the two binary directories also. The action sequence starts by mounting all of the filesystems currently in the filesystem table @file{/etc/fstab}. It then scans the list of mounted filesystems to find out what is actually mounted. Since the homeserver is host1, we know that our host has to mount all home-filesystems from this server, so it checks for @file{host1:/mysite/host1/u1} and @file{host1:/mysite/host1/u2}. If they are not present they are added to @file{/etc/fstab}@footnote{Note: if the filesystem was in the fstab but not actually mounted a warning is issued telling you that the filesystem was probably not exported correctly on host1.}. Next, we know that the binary server is server1, so we should check for @file{server1:/mysite/server1/local}. The mail server is also checked for and added if necessary. Cfagent then tries to mount all filesystems once again, so that the new filesystems should be added. Note that, in the process of adding the filesystems to @file{/etc/fstab}, cfagent creates the directories up to and including the point at which the filesystems should be mounted. If something prevents this --- if we try to mount on top of a plain file for instance --- then this will result in an error. Finally, we reach the link section and we try to expand the variables. @code{$(site)} expands to @file{mysite}. @code{$(binserver)} expands first to the hostname (host2), but @file{/mysite/host2/local} does not exist, so it then goes to the binserver list, which substitutes server1 for the value of @code{$(binserver)}. Since @file{/mysite/server1/local} does exist and is now mounted, cfagent makes a link to this directory from @file{/usr/local}. The script is then completed. If the script is run again, everything should now be in place so nothing happens. If for some reason it failed the first time, it will fail again. At any rate it will either do the job once and for all or signal an error which must be corrected by human intervention@footnote{One possibility is that an NFS filesystem cannot be mounted because the host serving the filesystem is out of service. If this is the case then a subsequent re-run when the server resumes normal service will succeed.}. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Using the automounter, Editing files, NFS resources, Global configurations @section Using the automounter @cindex automount The automounter is a daemon based service which replaces static mounting of NFS filesystems with a dynamical model. When the automounter is running, filesystems are mounted only when a user tries to access a file which resides on one of those filesystem. After a given period (usually five minutes) any filesystem which has not been accessed is unmounted. The advantage of this scenario is that hanging servers do not affect the behaviour of hosts which mount their filesystems, unless a specific file is being accessed. In both cases, filesystems must be exported in order to be mountable. It is not the purpose of this section to explain the use of the automounter in detail, only to offer hints as to how cfengine can be used to simplify and rationalize automount configuration for the already initiated. Let us begin by comparing the behaviour of the automounter with the cfengine model for mounted filesystems. The automounter is designed to be used together with a global configuration file, distributed by NIS (the network information service). As such, all hosts read the same configuration file. This makes it appear as though all hosts end up mounting every filesystem in the automount configuration database, but this is not so in practice because filesystems are only mounted if required. Thus a system which does not require a filesystem will not attempt to mount it. Moreover, the existence of a global configuration file does not affect which hosts have the right to mount certain filesystems (which is specified by exports or share on the relevant server), thus a request to mount a non-exported filesystem will result in an access denial. The automounter is configured locally on each host in files named @file{/etc/auto_master}, @file{auto_direct} etc. @cindex @file{auto_master} @cindex @file{auto_direct} In the cfengine static mounting scheme, you define a list of binary and home servers. The filesystem table is modified on the basis of these decisions, and filesystems are only added if cfagent deems it appropriate to mount them on a given host. The idea here is to minimize the number of filesystems mounted to those which are known to be required. Again the issue of access permissions must be arranged separately. These filesystems are placed directly in @file{/etc/fstab}, or the equivalent for your system. From cfengine, you can use the automounter instead of the static mount model by @itemize @bullet @item omitting @code{addmounts}, @code{mountinfo}, @code{mountall} from the actionsequence, in the control part of your cfengine program, @item using @code{editfiles} to edit the relevant configuration files such as @file{/etc/auto_master}, or @file{auto_direct} etc, @item using the @code{AutomountDirectResources} command in editfiles to dump the list of cfengine class-based list of mountables into a file of your choice in the correct format for autmount's direct maps, @item using @code{processes} to restart the automounter (send the hangup signal @code{hup}), or perhaps stop and restart the daemon by sending the @code{term} signal (you should never send the @code{kill} signal). @item using the multiple link facilities to link in indirect mounted filesystems as required, and @code{files} or @code{tidy} to clean up stale links afterwards, @item perhaps using @code{copy} to distribute basic automount configuration files to multiple systems. @end itemize The automounter was created to solve certain problems which cfengine now solves (in the author's opinion) better. For example, the use of the `hosts' map in the automounter mounts filesystems like @file{/usr/local} on different (uniquely named) mountpoints for each host in order to avoid name space collisions. Using cfengine and a unique naming scheme, you can achieve the same thing more cleanly, without all of the gratuitous linking and unlinking which the automounter performs by itself. Moreover, the idea of a unique name-space is better practice and more in keeping with new global filesystem ideas such as AFS and DFS. @cindex AFS @cindex DFS The only advantage of the automounter is that one avoids the annoying error messages from hung servers about "NFS server not responding". In that respect, it seems sensible to use only direct mounts and a unique name space. @cindex Home directories and automount @cindex @file{/home} @cindex @file{/users} Some systems advocate grouping all users' login (home) directories under a common directory called @file{/home} or @file{users}. The automounter goes through all manner of contortions to achieve this task. If you use a unique naming scheme like the one advocated here, this is a trivial task. You simply arrange to mount or automount all user directories, such as @mbindex How to keep all users in @file{/home} @smallexample /@var{site}/@var{host}/home1 /@var{site}/@var{host}/home2 ... @end smallexample @noindent and then link them as follows: @smallexample /home +> /@var{site}/@var{host}/home1 /home +> /@var{site}/@var{host}/home2 ... @end smallexample Finally, you should be aware that the automounter does not like to be mixed with static mount and unmount operations. Automounted filesystems take priority over statically mounted filesystems, but the automounter can be confused by manually mounting or unmounting filesystems while it is running. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Editing files, Disabling and the file repository, Using the automounter, Global configurations @section Editing Files A very convenient characteristic of BSD and UNIX System V systems is that they are configured primarily by human-readable textfiles. This makes it easy for humans to configure the system and it also simplifies the automation of the procedure. Most configuration files are line-based text files, a fact which explains the popularity of, for example, the Perl programming language. Cfengine does not attempt to compete with Perl or its peers. Its internal editing functions operate at a higher level which are designed for transparency rather than flexibility. Fortunately most editing operations involve appending a few lines to a file, commenting out certain lines or deleting lines. For example, some administrators consider the finger service to be a threat to security and want to disable it. This could be done as follows. @smallexample editfiles: @{ /etc/inetd.conf HashCommentLinesContaining "finger" @} @end smallexample Commands containing the word `Comment' are used to `comment out' certain lines from a text-file---i.e. render a line impotent without actually deleting it. Three types of comment were supported originally: shell style (hash) @samp{#}, @samp{%} as used in TeX and on AIX systems, and C++-style @samp{//}. A more flexible way of commenting is also possible, using directives which first define strings which signify the start of a comment and the end of a comment. A single command can then be used to render a comment. The default values of the comment-start string is @samp{# } and the default comment-end string is the empty string. For instance, to define C style comments you could write: @smallexample @{ @var{file} SetCommentStart "/* " SetCommentEnd " */" # Comment out all lines containing printf! CommentLinesMatching ".*printf.*" @} @end smallexample Other applications for these editing commands include monitoring and controlling root-access to hosts by editing files such as @file{.rhosts} and setting up standard environment variables in global shell resource files--- for example, to set the timezone. You can use the editing feature to update and distribute the message of the day file, or to configure sendmail, (see FAQS and Tips in the Reference manual). An extremely powerful feature of cfagent is the ability to edit a similar file belonging to every user in the system. For example, as a system administrator, you sometimes need to ensure that users have a sensible login environment. Changes in the system might require all users to define a new environment variable, for instance. This is achieved with the @code{home} pseudo-wildcard. If one writes @smallexample @{ home/.cshrc AppendIfNoSuchLine "# Sys admin/cfengine: put next line here" AppendIfNoSuchLine "setenv PRINTER newprinter" @} @end smallexample @noindent then the users' files are checked one-by-one for the given lines of text, and edited if necessary. Files are loaded into cfagent and edited in memory. They are only saved again if modifications to the file are carried out, in which case the old file is preserved by adding a suffix to the filename. When files are edited, cfagent generates a warning for the administrator's inspection so that the reason for the change can be investigated. The behaviour of cfagent should not be confused with that of @emph{sed} or @emph{perl}. Some functionality is reproduced for convenience, but the specific functions have been chosen on the basis of (i) their readability and (ii) the fact that they are `frequently-required-functions'. A typical file editing session involves the following points: @itemize @bullet @item Load file into memory. @item Is the size of the file within sensible user-definable limits? If not, file could be binary, refuse to edit. @item Check each editing command and count the number of edits made. @item If number of edits is greater than zero, rename the old file and save the edited version in its place. Inform about the edit. @item If no edits are made, do nothing, say nothing. @end itemize Equivalent one-line sed operations involve editing the same file perhaps many times to achieve the same results---without the safety checks in addition. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Disabling and the file repository, Running user scripts, Editing files, Global configurations @section Disabling and the file repository The existence of certain files can compromise the integrity of your system and you may wish to ensure that they do not exist. For example, some manufacturers sell their workstations with a @samp{+} symbol in the file @file{/etc/hosts.equiv}. @cindex @file{/etc/hosts.equiv} This means that anyone in your NIS domain has password free access to the system!! Since this is probably not a good idea, you will want to disable this file by renaming it, or simply deleting it. @smallexample disable: /etc/hosts.equiv @end smallexample @noindent Other files compromise the system because they grow so large that they fill an entire disk partition. This is typically true of log files such as the System V files @file{/var/adm/wtmpx} and @file{/var/lp/logs/lpsched}. Other files like @var{/var/adm/messages} get "rotated" by the system so that they do not grow so large as to fill the disk. You can make cfagent rotate these files too, by writing @cindex @file{/var/adm/wtmpx} @cindex @file{/var/lp/logs/lpsched} @smallexample disable: Sunday:: /var/lp/logs/lpsched rotate=3 @end smallexample @noindent Now, when cfagent is run, it renamed the file @file{lpsched} to a file called @file{lpsched.1}. It also renames @file{lpsched.1} as @file{lpsched.2} and so on, until a maximum of 3 files are kept. After passing 3, the files `fall off the end' and are deleted permanently. This procedure prevents any log files from growing too large. If you are not interested in keeping back-logs, then you may write @code{rotate=empty} and cfagent will simply empty the log file. @cindex Rotating files @cindex Log files, rotating When ever cfagent disables a file (@code{disable} or @code{links} with the @samp{!} operator), or saves a new file on top of an old one (@code{copy} or @code{editfiles}), it makes a backup of the original. Usually disabled files are renamed by appending the string @file{.cfdisabled} the filename; copied files are saved by appending the string @file{.cfsaved}. @cindex @file{.cfsaved} files @cindex @file{.cfdisabled} files It is possible to switch off backup file generation in the copy feature by setting the variable @code{backup=false}, but a better way of managing disabled and backed-up files is to use a directory in which you collect all such files for the whole system. This directory is called the file repository and is set in the control part of the program, as follows: In the @code{copy} directive, the option @code{backup=timestamp} can be used to allow multiple backups. This is useful when using cfengine to make disk backups for users, since it allows multiple versions to co-exist. @cindex Timestamp backups @smallexample control: repository = ( @var{directory-name} ) @end smallexample If this variable is defined, cfagent collects all backup and disabled files (except for rotated files) in this directory, using a unique pathname. You can then inspect these files in the repository and arrange to tidy the repository for old files which are no longer interesting. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Running user scripts, Compressing logs, Disabling and the file repository, Global configurations @section Running user scripts Above all, the aim of cfengine is to present a simple interface to system administrators. The actions which are built into the engine are aimed at solving the most pressing problems, not at solving every problem. In many cases administrators will still need to write scripts to carry out more specific tasks. These scripts can still be profitably run from cfengine. Variables and macros defined in cfengine can be passed to scripts so that scripts can make maximal advantage of the class based decisions. Also note that, since the days of the week are also classes in cfengine, it is straightforward to run weekly scripts from the cfengine environment (assuming that the configuration program is executed daily). An obvious use for this is to update databases, like the fast-find database one day of the week, or to run quota checks on disks. @smallexample shellcommands: myhost.Sunday:: "/usr/bin/find/updatedb" @end smallexample @noindent Cfengine scripts can be passed variables using normal variable substitution: @smallexample control: cfbin = ( /var/cfengine/bin ) backupdir = ( /iu/dax/backup ) shellcommands: "$(cfbin)/cfbackup -p -f $(backupdir) -s /iu/nexus/u1" @end smallexample If you need to write a particularly complex script to expand cfagent's capabilities, it might be useful to have full access to the defined classes. You can do this in one of two ways: @itemize @bullet @item Pass the variable @code{$(allclasses)} to the script. This contains a list of all classes in the form of a string @smallexample CFALLCLASSES=@var{class1}:@var{class2}:... @end smallexample @noindent This variable always contains an up to date list of the defined classes. @item Use the command line option @samp{-u} or @samp{--use-env}. When this is defined, cfagent defines an internal environment variable called @samp{CFALLCLASSES} which contains the same list as above. Unfortunately, System V boxes don't seem to like having to update an environment variable continuously and tend to dump core, so this is not the default behaviour! @end itemize @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Compressing logs, ACLs, Running user scripts, Global configurations @section Compressing old log files In the previous two sections we have looked at how to rotate old log files and how to execute shell commands. If you keep a lot of old log files around on your system, you might want to compress them so that they don't take up so much space. You can do this with a shell command. The example below looks for files matching a shell wildcard. Names of the form @file{file.1}, @file{file.2}...@file{file.10} will match this wildcard and the compression program sees that they get compressed. The output is dumped to avoid spurious messages. @smallexample shellcommands: "$(gnu)/gzip /var/log/*.[0-9] /var/log/*.[0-9][0-9] > /dev/null 2>&1" @end smallexample Cfagent will also recognize rotated files if they have been compressed, with suffixes @file{.Z}, @file{.gz}, @file{.rbz} or @file{.rbz}. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node ACLs, , Compressing logs, Global configurations @section Managing ACLs @cindex Access control lists @cindex ACLs @cindex Permissions, extended Access control lists are extended file permissions. They allow you to open or close a file to a named list of users (without having to create a special group for those users). They also allow you to open or close a file for a named list of groups. Several Unix-like operating systems have had access control lists for some time; but they do not seem to have caught on. There is a number of reasons for this dawdling in the past. The tools for setting ACLs are generally interactive and awkward to use. Because a named list of users would lead to excessive verbosity in an @kbd{ls -l} listing, one does not normally see them. There is therefore the danger that the hidden information would lead to undetected blunders in opening files to the wrong users. ACLs are also different on every vendor's filesystems and they don't work over intersystem NFS. In spite of these reservations, ACLs are a great idea. Here at Oslo College, it seems that users are continually asking how they can open a file just for the one or two persons they wish to collaborate with. They have grown used to Novell/PC networks which embraced the technology from Apollo/NCS much earlier. Previously the Unix answer to users has always been: go ask the system administrator to make a special group for you. Then do the @samp{chmod} thing. And then they would say: so what's so great about this Unix then? Addressing this lack of standardization has been the job of a POSIX draft committee. Some vendors have made their implementations in the image of this draft. Solaris 2.6 has a good implementation. In spite of this, even these systems have only awkard tools for manipulating ACLs. Not the kind of thing you want to be around much, if you have better things to do. But the incompatibility argument applies only to multiple vendor headbutting. Some institutions who share data on a global basis opt for advanced solutions to network filesystems, such as AFS and DFS. Filesystems such as DCE's DFS make extensive use of file ACLs, and they are not operating system specific. Even so, DFS provides only interactive tools for examining and setting file permissions, and this is of little use to system administrators who would rather relegate that sort of thing to a script. The need for this kind of thing is clear. Systems which make use of ACLs for security can be brought to their knees by changing a few ACLs. Take the Apollo/Domain OS as an example. All one needs to do to kill the system is to change a few ACLs and forget what they were supposed to be. Suddenly the system is crippled, nothing works. The only solution, if you don't have a backup, is to remove all of the security. Unix has a simpler security philosophy when it comes to the operating system files, but ACLs would be a valuable addition to the security of our data. A cfagent bare-bones file-checking program looks like this: @smallexample # # Free format cfagent program # control: ActionSequence - ( files ) files: classes:: /directory/file mode=644 owner=mark,ds group=users,adm acl=zap action=fixplain # ... more below @end smallexample @vindex @code{acl} @cindex ACL aliases @noindent This program simply checks the permissions and ownership of the named file. The regular file mode, owner and group are specified straightforwardly. The new feature here is the @code{acl} directive. It is a deceptively simply looking animal, but it hides a wealth of complexity. The @code{zap} is, of course, not an access control list. Rather, cfagent uses a system of aliases to refer to ACLs, so that the clutter of the complex ACL definitions does not impair the clarity of a file command. An ACL alias is defined in a separate part of the program which looks like this: @smallexample # ...contd acl: @{ zap method:append fstype:solaris user:rmz:rwx user:len:r @} @end smallexample @noindent As you can see, an ACL is a compound object---a bundle of information which specifies which users have which permissions. Because ACLs are @emph{lists} the alias objects must also know whether the items are to be appended to an existing list or whether they are to replace an existing list. Also, since the permission bits, general options and programming interfaces are all different for each type of filesystem, we have to tell cfagent what the filesystem type is. It is possible to associate several ACL aliases with a file. When cfagent checks a files with ACLs, it reads the existing ACL and compares it to the new one. Files are only modified if they do not conform to the specification in the cfengine program. Let's look at a complete example: @smallexample files: $(HOME)/myfile acl=acl_alias1 action=fixall acl: @{ acl_alias1 method:append fstype:solaris user:len:rwx @} @end smallexample @noindent ACLs are viewed in Solaris with the command @samp{getfacl}. Suppose that, before running this program, our test-file had permissions @smallexample user:*:rwx user:mark:rwx #effective:r-x group:*:r-x #effective:r-x mask:r-x other:r-x default_user:rw- default_group:r-- default_mask:-w- default_other:rwx @end smallexample @noindent After the cfagent run, the ACL would become: @smallexample user:*:rwx user:mark:rwx #effective:r-x user:len:rwx #effective:r-x group:*:r-x #effective:r-x mask:r-x other:r-x default_user:rw- default_group:r-- default_mask:-w- default_other:rwx @end smallexample @noindent Suppose we wanted to to remove 'w' bit for user @samp{jacobs}, or make sure that it was never there. @smallexample @{ acl_alias1 method:append fstype:solaris user:jacobs:-w @} @end smallexample @noindent Note that the method used here is append. That means that, whatever other access permissions we might have granted on this file, the user @samp{jacobs} (a known cracker) will have no write permissions on the file. Had we used the method @code{overwrite} above, we would have eliminated all other access permissions for every user and added the above. If we really wanted to burn @samp{jacobs}, we could remove all rights to the file like this @smallexample user:jacobs:noaccess @end smallexample @noindent The keyword @code{noaccess} removes all bits. Note that this is not necessarily the same as doing a @code{-rwx}, since some filesystems, like DFS, have more bits than this. Then, if we want to forgive and forget, the ACLs may be removed for @code{jacobs} with the syntax @smallexample user:jacobs:default @end smallexample In Solaris, files inherit default ACLs from the directory they lie in; these are modified by the umask setting to generate their own default mask. @cindex ACLs, Solaris DFS ACLs look a little different. They are examined with the @samp{acl_edit} command or with @cindex ACLs, DFS @smallexample dcecp -c acl show @end smallexample @noindent In order to effect changes to the DFS, you have to perform a DCE login to obtain authentication cookies. The user @samp{cell_admin} is a special user account for administrating a local DFS cell. Suppose we have a file with the following DCE ACL: @smallexample mask_obj:r-x--- user_obj:rwxcid user:cell_admin:r--c-- #effective:r----- group_obj:r-x--d #effective:r-x--- other_obj:r-x--- @end smallexample @noindent Now we want to add @samp{wx} permissions for user @samp{cell_admin}, and add new entries with @samp{rx} permissons for group @code{acct-admin} and user @samp{root}. This is done with the following ACL alias: @smallexample @{ acl_alias2 method:append fstype:dfs user:/.../iu.hioslo.no/cell_admin:wx group:/.../iu.hioslo.no/acct-admin:rx user:/.../iu.hioslo.no/root:rx user:*:-x @} @end smallexample @noindent The local cell name @file{/.../iu.hioslo.no} is required here. Cfagent can not presently change ACLs in other cells remotely, but if your cfengine program covers all of the cell servers, then this is no limitation, since you can still centralize all your ACLs in one place. It is just that the execution and checking takes place at distributed locations. This is the beauty of cfengine. After running cfagent, with the above program snippet, the ACL then becomes: @smallexample mask_obj:r-x--- user_obj:rwcid user:cell_admin:rwxc-- #effective:r-x--- user:root:r-x--- #effective:r-x--- group_obj:r-x--d #effective:r-x--- group:acct-admin:r-x--- other_bj:r-x--- @end smallexample @noindent For the sake of simplicity we have only used standard Unix bits @samp{rwx} here, but more complicated examples may be found in DFS. For example, @smallexample user:mark:+rwx,-cid @end smallexample @noindent which sets the read, write, execute flags, but removes the control, insert and delete flags. In the DFS, files inherit the inital object ACL of their parent directory, while new directories inherit the initial container object. The objects referred to in DFS as @code{user_obj}, @code{group_obj} and so forth refer to the owner of a file. i.e. they are equivalent to the same commands acting on the user who owns the file concerned. To make the cfengine user-interface less cryptic and more in tune with the POSIX form, we have dropped the @samp{_obj} suffices. A user field of @samp{*} is a simple abbreviation for the owner of the file. A problem with any system of lists is that one can generate a sequence which does one thing, and then undoes it and redoes something else, all in the same contradictory list. To avoid this kind of accidental interaction, cfengine insists that each user has only one ACE (access control entry), i.e. that all the permissions for a given user be in one entry. @c ********************************************************************** @c CHAPTER @c ********************************************************************** @node Using cfengine as a front-end for cron, Cfengine network services, Global configurations, Top @chapter Using cfengine as a front end for cron One of cfengine's strengths is its use of classes to identify systems from a single file or set of files. Many administrators think that it would be nice if the cron daemon also worked in this way. One possible way of setting up cron from a global configuration would be to use the cfengine @code{editfiles} facility to edit each cron file separately. A much better way is to use cfengine's time classes to work like a user interface for cron. This allows you to have a single, central cfengine file which contains all the cron jobs on your system without losing any of the fine control which cron affords you. All of the usual advantages apply: @itemize @bullet @item It is easier to keep track of what cron jobs are running on the system when you have everything in one place. @item You can use all of your carefully crafted groups and user-defined classes to identify which host should run which programs. @end itemize @cindex Cron jobs, controlling with cfengine The central idea behind this scheme is to set up a regular cron job on every system which executes cfagent at frequent intervals. Each time cfagent is started, it evaluates time classes and executes the shell commands defined in its configuration file. In this way we use cfagent as a wrapper for the cron scripts, so that we can use cfengine's classes to control jobs for mulitple hosts. Cfengine's time classes are at least as powerful as @code{cron}'s time specification possibilities, so this does not restrict you in any way, @xref{Building flexible time classes}. The only price is the overhead of parsing the cfengine configuration file. @mbindex How can I use cfengine to make a global cron file? To be more concrete, imagine installing the following @file{crontab} file onto every host on your network: @cartouche @smallexample # # Global Cron file # 0,15,30,45 * * * * /usr/local/sbin/cfexecd -F @end smallexample @end cartouche @noindent @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @menu * Structuring cfagent.conf:: * Splaying host times:: * Building flexible time classes:: * Scheduling interval:: @end menu @node Structuring cfagent.conf, Splaying host times, Using cfengine as a front-end for cron, Using cfengine as a front-end for cron @section Structuring cfagent.conf The structure of @file{cfagent.conf} needs to reflect your policy for running jobs on the system. You need to switch on relevant tasks and switch off unwanted tasks depending on the time of day. This can be done in three ways: @itemize @bullet @item By placing individual actions under classes which restrict the times at which they are executed, @smallexample @var{action}: Hr00.Min10_15||Hr12.Min45_55:: @var{Command} @end smallexample @item By choosing a different @code{actionsequence} depending on the time of day. @smallexample control: Hr00:: # Action-sequence for daily run at midnight actionsequence = ( @var{sequence} ) !Hr00:: # Action-sequence otherwise actionsequence = ( @var{sequence} ) @end smallexample @item By importing modules based on time classes. @smallexample import: Hr00:: cf.dailyjobs any:: cf.hourlyjobs @end smallexample @end itemize @noindent The last of these is the most efficient of the three, since cfengine does not even have to spend time parsing the files for actions which you know you will not want. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Splaying host times, Building flexible time classes, Structuring cfagent.conf, Using cfengine as a front-end for cron @section Splaying host times The trouble with starting every cfagent at the same time using a global cron file is that it might lead to contention or inefficiency. For instance, if a hundred cfagents all suddenly wanted to copy a file from a master source simultaneously this would lead to a big load on the server. We can prevent this from happening by introducing a time delay which is unique for each host and not longer than some given interval. Cfagent uses a hashing algorithm to generate a number between zero and a maximum value in minutes which you define, like this: @smallexample # Put this in update.conf, so that the updates are also splayed control: SplayTime = ( 10 ) # minutes @end smallexample @noindent If this number is non-zero, cfagent goes to sleep after parsing its configuration file and reading the clock. Every machine will go to sleep for a different length of time, which is no longer than the time you specify in minutes. A hashing algorithm, based on the fully qualified name of the host, is used to compute a unique time for hosts. The shorter the interval, the more clustered the hosts will be. The longer the interval, the lighter the load on your servers. This `splaying' of the run times will lighten the load on servers, even if they come from domains not under your control but have a similar cron policy. @cindex Splaying host times @cindex Contention during copying under load @cindex Load balancing Splaying can be switched off temporarily with the @samp{-q} or @samp{--no-splay} options. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Building flexible time classes, Scheduling interval, Splaying host times, Using cfengine as a front-end for cron @section Building flexible time classes @cindex Time classes @mbindex How can I make complex time intervals using time classes? @mbindex Time classes, picking out complex time intervals Each time cfagent is run, it reads the system clock and defines the following classes based on the time and date: @table @code @item Yr@var{xx}:: The current year, e.g. @samp{Yr1997}, @samp{Yr2001}. This class is probably not useful very often, but it might help you to turn on the new-year lights, or shine up your systems for the new millenium! @cindex Years @item @var{Month}:: The current month can be used for defining very long term variations in the system configuration, e.g. @samp{January}, @samp{February}. These classes could be used to determine when students have their summer vacation, for instance, in order to perform extra tidying, or to specially maintain some administrative policy for the duration of a conference. @cindex Months @item @var{Day}:: The day of the week may be used as a class, e.g. @samp{Monday}, @samp{Sunday}. @cindex Day of the week @item Day@var{xx}:: A day in the month (date) may be used to single out by date, e.g. the first day of each month defines @samp{Day1}, the 21st @samp{Day21} etc. @item Hr@var{xx}:: An hour of the day, in 24-hour clock notation: @samp{Hr00}...@samp{Hr23}. @item Min@var{xx}:: The precise minute at which cfagent was started: @samp{Min0} ... @samp{Min59}. This is probably not useful alone, but these values may be combined to define arbitrary intervals of time. @item Min@var{xx}_@var{xx}:: The five-minute interval in the hour at which cfagent was executed, in the form @samp{Min0_5}, @samp{Min5_10} .. @samp{Min55_0}. @end table Time classes based on the precise minute at which cfagent started are unlikely to be useful, since it is improbable that you will want to ask cron to run cfagent every single minute of every day: there would be no time for anything to complete before it was started again. Moreover, many things could conspire to delay the precise time at which cfagent were started. The real purpose in being able to detect the precise start time is to define composite classes which refer to arbitrary intervals of time. To do this, we use the @code{group} or @code{classes} action to create an alias for a group of time values. @cindex Grouping time values @cindex @code{groups} and time intervals Here are some creative examples: @smallexample classes: # synonym groups: LunchAndTeaBreaks = ( Hr12 Hr10 Hr15 ) NightShift = ( Hr22 Hr23 Hr00 Hr01 Hr02 Hr03 Hr04 Hr05 Hr06 ) ConferenceDays = ( Day26 Day27 Day29 Day30 ) QuarterHours = ( Min00 Min15 Min30 Min45 ) TimeSlices = ( Min01 Min02 Min03 Min33 Min34 Min35) @end smallexample @noindent In these examples, the left hand sides of the assignments are effectively the ORed result of the right hand side. This if any classes in the parentheses are defined, the left hand side class will become defined. This provides a flexible and readable way of specifying intervals of time within a program, without having to use @samp{|} and @samp{.} operators everywhere. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Scheduling interval, , Building flexible time classes, Using cfengine as a front-end for cron @section Choosing a scheduling interval How often should you call your global cron script? There are several things to think about: @itemize @bullet @item How much fine control do you need? Running cron jobs once each hour is usually enough for most tasks, but you might need to exercise finer control for a few special tasks. @item Are you going to run the entire cfengine configuration file or a special light-weight file? @item System latency. How long will it take to load, parse and run the cfengine script? @end itemize Cfengine has an intelligent locking and timeout policy which should be sufficient to handle hanging shell commands from previous crons so that no overlap can take place, @xref{Spamming and security}. @c ********************************************************************** @c CHAPTER @c ********************************************************************** @node Cfengine network services, Security and cfengine, Using cfengine as a front-end for cron, Top @chapter Cfengine and network services This chapter describes how you can set up a cfengine network service to handle remote file distribution and remote execution of cfengine without having to open your hosts to possible attack using the @code{rsh} protocols. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @menu * What services?:: * How it works:: * Configuring cfservd:: @end menu @node What services?, How it works, Cfengine network services, Cfengine network services @section Cfengine network services By starting the daemon called @code{cfservd}, you can set up a line of communication between hosts, allowing them to exchange files across the network or execute cfengine remotely on another system. @cindex @code{cfservd} daemon @cindex @code{cfrun} program @cindex @code{cfwatcher} program Cfengine network services are built around the following components: @table @code @item cfagent The configuration engine, whose only contact with the network is via remote copy requests. This component does the hard work of configuring the system based on rules specified in the file @file{cfagent.conf}. It does not and cannot grant any access to a system from the network. @cindex @file{cfagent.conf} file @item cfservd A daemon which acts as both a file server and a remote-cfagent executor. This daemon authenticates requests from the network and processes them according to rules specified in @file{cfservd.conf}. It works as a file server and as a mechanism for starting cfagent on a local host and piping its output back to the network connection. @cindex @file{cfservd.conf} file @item cfrun This is a simple initiation program which can be used to run cfagent on a number of remote hosts. It cannot be used to tell cfagent what to do, it can only ask cfagent on the remote host to run the configuration file it already has. Anyone could be allowed to run this program, it does not require any special user privileges. A locking mechanism in cfengine prevents its abuse by spamming. @item cfwatch This program (which is not a part of the distribution: it is left for others to implement) should provide a graphical user interface for watching over the configuration of hosts running cfagent and logging their output. @end table @noindent With these components you can emulate programs like @code{rdist} @cindex @code{rdist} program @cindex Remote distribution of files @cindex Remote execution of cfagent whose job it is to check and maintain copies of files on client machines. You may also decide who has permission to run cfagent and how often it may be run, without giving away any special user privileges. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node How it works, Configuring cfservd, What services?, Cfengine network services @section How it works @c ........................................... @c SUBSECTION @c ........................................... @menu * Emulating rdist:: * Remote execution of cfagent:: * Spamming and security:: * cfservd protocol:: * Deadlocks and runaway loops:: @end menu @node Emulating rdist, Remote execution of cfagent, How it works, How it works @subsection Remote file distribution This section describes how you can set up @code{cfservd} as a remote file server which can result in the distribution of files to client hosts in a more democratic way than with programs like rdist. An important difference between cfengine and other systems has to do with the way files are distributed. Cfengine uses a `pull' rather than a `push' model for distributing network files. The @code{rdist} command, for instance, works by forcing an image of the files on one server machine onto all clients. Files get changed when the server wishes it and the clients have no choice but to live with the consequences. Cfengine cannot force its will onto other hosts in this way, it can only signal them and ask them to collect files if they want to. In other words, cfengine simulates a `push' model by polling each client and running the local cfengine configuration script giving the host the chance to `pull' any updated files from the remote server, but leaving it up to the client machine to decide whether or not it wants to update. Also, in contrast to programs like @code{rdist} which distribute files over many hosts, cfengine does not require any general @code{root} access to a system using the @file{.rhosts} file or the @file{/etc/hosts.equiv} file. It is sufficient to run the daemon as root. You can not run it by adding it to the @file{/etc/inetd.conf} file on your system however. @cindex @file{/etc/inetd.conf} file and cfengine The restricted functionality of the daemon protects your system from attempts to execute general commands as the root user using @code{rsh}. To remotely access files on a server, you add the keyword @code{server=@var{host}} @cindex @code{server=} to a copy command. Consider the following example which illustrates how you might distribute a password file from a masterhost to some clients. @smallexample copy: PasswdClients:: /etc/passwd dest=/etc/passwd owner=root group=0 server=@var{server-host} @end smallexample @noindent Given that the @code{cfservd} daemon is running on @var{server-host}, cfagent will make contact with the daemon and attempt to obtain information about the file. During this process, cfengine verifies that the system clocks of the two hosts are reasonably synchronized. If they are not, it will not permit remote copying. @cindex Clock synchronization during copying If cfagent determines that a file needs to be updated from a remote server it begins copying the remote file to a new file on the same filesystem as the destination-file. This file has the suffix @file{.cfnew}. @cindex @file{.cfnew} files Only when the file has been successfully collected will cfagent make a copy of the old file, (see @code{repository} in the Reference manual), and rename the new file into place. This behaviour is designed to avoid race-conditions which can occur during network connections and indeed any operations which take some time. If files were simply copied directly to their new destinations it is conceivable that a network error could interrupt the transfer leaving a corrupted file in place. Cfagent places a timeout of a few seconds on network connections to avoid hanging processes. Normally the daemon sleeps, waiting for connections from the network. Such a connection may be initiated by a request for remote files from a running cfengine program on another host, or it might be initiated by the program @code{cfrun} which simply asks the @cindex @code{cfrun} program host running the daemon to run the cfengine program locally. @c ........................................... @c SUBSECTION @c ........................................... @node Remote execution of cfagent, Spamming and security, Emulating rdist, How it works @subsection Remote execution of cfagent @cindex Remote execution of cfagent It is a good idea to execute cfagent by getting @code{cron} to run it regularly. This ensures that cfagent will be run even if you are unable to log onto a host to run it yourself. Sometimes however you will want to run cfagent immediately in order to implement a change in configuration as quickly as possible. It would then be inconvenient to have to log onto every host in order to do this manually. A better way would be to issue a simple command which contacted a remote host and ran cfagent, printing the output on your own screen: @smallexample myhost% cfrun @var{remote-host} -v @var{output....} @end smallexample @noindent A simple user interface is provided to accomplish this. @code{cfrun} makes a connection to a remote cfservd-daemon @cindex cfservd dameon @cindex cfrun program @cindex Running cfagent remotely and executes cfagent on that system with the privileges of the cfservd-daemon (usually @code{root}). This has a two advantages: @itemize @bullet @item You avoid having to log in on a remote host in order to reconfigure it. @item Users other than root can run cfagent to fix any problems with the system. @end itemize A potential disadvantage with such a system is that malicious users might be able to run cfagent on remote hosts. The fact that non-root users can execute cfagent is not a problem in itself, after all the most malicious thing they would be able to do would be to check the system configuration and repair any problems. No one can tell cfagent what to do using the cfrun program, it is only possible to run an existing configuration. But a more serious concern is that malicious users might try to run cfagent repeatedly (so-called `spamming') so that a system became burdened with running cfagent constantly, @xref{Spamming and security}. @c ........................................... @c SUBSECTION @c ........................................... @node Spamming and security, cfservd protocol, Remote execution of cfagent, How it works @subsection Spamming and security The term `spamming' refers to the senseless repetition of something in a malicious way intended to drive someone crazy@footnote{Recall the `spam' song from Monty Python's flying circus?}. In the computer world some malicious users, a bit like `flashers' in the park@footnote{Recall the `spam' song from Monty Python's flying circus?} like to run around the net a reveal themselves ad nauseum by sending multiple mail messages or making network connections repeatedly to try to overload systems and people@footnote{Recall the `spam' song ... get the idea?}. Whenever we open a system to the network, this problem becomes a concern. Cfengine is a tool for making peace with networked systems, not a tool to be manipulated into acts of senseless aggression. The cfservd daemon does make it possible for anyone to connect and run a cfengine process however, so clearly some protection is required from such attacks. Cfengine's solution to this problem is a locking mechanism. Rather than providing user-based control, cfengine uses a time based locking mechanism which prevents actions from being executed unless a certain minimum time has elapsed since the last time they were executed. By using a lock which is not based on user identity, we protect several interests in one go: @itemize @bullet @item Restricting cfengine access to root would prevent regular users, in trouble, from being able to fix problems when the system administrator was unavailable. A time-based lock does not prevent this kind of freedom. @item Accidents with cron or shell scripts could start cfagent more often than desirable. We also need to protect against such accidents. @item We can prevent malicious attacks regardless of whom they may come from. @end itemize Cfengine is controlled by a series of locks which prevent it from being run too often, and which prevent it from spending too long trying to do its job. The locks work in such a way that you can start several cfengine processes simultaneously without them crashing into each other. Coexisting cfengine processes are also prevented from trying to do the same thing at the same time (we call this `spamming'). You can control two things about each kind of action in the action sequence: @itemize @bullet @item The minimum time which should have passed since the last time that action was executed. It will not be executed again until this amount of time has elapsed. (Default time is 1 minute.) @item The maximum amount of time cfagent should wait for an old instantiation of cfagent to finish before killing it and starting again. (Default time is 120 minutes.) @end itemize @noindent You can set these values either globally (for all actions) or for each action separately. If you set global and local values, the local values override the global ones. All times are written in units of @emph{minutes}. @cartouche @smallexample actionsequence ( action.IfElapsed@var{time-in-mins} action.ExpireAfter@var{time-in-mins} ) @end smallexample @end cartouche @noindent or globally, @cartouche @smallexample control: IfElapsed = ( @var{time-in-mins} ) ExpireAfter = ( @var{time-in-mins} ) @end smallexample @end cartouche @noindent For example: @smallexample control: actionsequence = ( files.IfElapsed240.ExpireAfter180 copy tidy ) IfElapsed = ( 30 ) @end smallexample In this example, we treat the files action differently to the others. For all the other actions, cfagent will only execute the files part of the program if 30 minutes have elapsed since it was last run. Since no value is set, the expiry time for actions is 60 minutes, which means that any cfagent process which is still trying to finish up after 60 minutes will be killed automatically by the next cfagent which gets started. As for the files action: this will only be run if 240 minutes (4 hours) have elapsed since the last run. Similarly, it will not be killed while processing `files' until after 180 minutes (3 hours) have passed. These locks do not prevent the whole of cfagent from running, only so-called `atoms'. Several different atoms can be run concurrently by different cfagents. @cindex Atoms in cfagent @cindex Atomic operations in cfagent Assuming that the time conditions set above allow you to start cfengine, the locks ensure that atoms will never be started by two cfagents at the same time, causing contention and wasting CPU cycles. Atoms are defined to maximize the security of your system and to be efficient. If cfengine were to lock each file it looked at seperately, it would use a large amount of time processing the locks, so it doesn't do that. Instead, it groups things together like this: @table @code @item copy, editfiles, shellcommands Each separate command has its own lock. This means that several such actions can be processed concurrently by several cfagent processes. Multiple or recursive copies and edits are treated as a single object. @item netconfig, resolve, umount, mailcheck, addmounts, disable, processes All commands of this action-type are locked simultaneously, since they can lead to contention. @item mountall, mountinfo, required, checktimezone These are not locked at all. @end table @cindex Lock files for ordinary users @cindex Ordinary users, lock files Cfagent creates a directory @file{~/.cfengine} for writing lock files for ordinary users. The option @samp{-K} or @samp{--no-lock} can be used to switch off the locking checks, but note that when running cfagent remotely via @code{cfservd}, this is not possible. @c ........................................... @c SUBSECTION @c ........................................... @node cfservd protocol, Deadlocks and runaway loops, Spamming and security, How it works @subsection Some points on the cfservd protocol Cfservd uses a form for host-based authorization. Each atomic operation, such as statting, getting files, reading directories etc, requires a new connection and each connection is verified by a double reverse lookup in the server's DNS records. Single stat structures are cached during the processing of a file. MD5 checksums are transferred from client to server to avoid loading the server. Even if a user could corrupt the MD5 checksum, he or she would have to get past IP address access control and the worst that could happen would be to get the right version of the file. Again this is in keeping with the idea that users can only harm themselves and not others with cfengine. @c ........................................... @c SUBSECTION @c ........................................... @node Deadlocks and runaway loops, , cfservd protocol, How it works @subsection Deadlocks and runaway loops Whenever we allow concurrent processes to share a resource, we open ourselves up the possibilty of deadlock. This is a situation where two or more processes are locked in a vicious stalemate from which none can escape. Another problem is that it might be possible to start an infinite loop: cfagent starts itself. @cindex Deadlock protection @cindex Infinite loops Cfagent protects you from such loops to a large degree. It should not be possible to make such a loop by accident. The reason for this is the locking mechanism which prevents tasks being repeated too often. If you start a cfagent process which contains a shell-command to start cfagent again, this shell command will be locked, so it will not be possible to run it a second time. So while you might be able to start a second cfagent process, further processes will not be started and you will simply have wasted a little CPU time. When the first cfagent returns, the tasks which the second cfagent completed will not be repeated unless you have set the @code{IfElapsed} time or the @code{ExpireAfter} time to zero. @cindex IfElapsed, caution setting to zero! @cindex ExpireAfter, caution setting to zero! In general, if you wish to avoid problems like this, you should not disable the locking mechanism by setting these two times to zero. The possibility of deadlock arises in network connection. Cfengine will not attempt to use the network to copy a file which can be copied internally from some machine to itself. It will always replace the @code{server=} directive in a copy with `localhost' to avoid unnecessary network connections. @cindex server= when copying to localhost @cindex localhost and remote copying This prevents one kind of deadlock which could occur: namely cfrun executes cfagent on host A (cfservd on host A is then blocked until this completes), but the host A configuration file contains a remote copy from itself to itself. This remote copy would then have to wait for cfservd to unblock, but this would be impossible since cfservd cannot unblock until it has the file. By avoiding remote copies to localhost, this possibility is avoided. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Configuring cfservd, , How it works, Cfengine network services @section Configuring cfservd @c ........................................... @c SUBSECTION @c ........................................... @menu * Installation of cfservd:: * Configuration file cfservd.conf:: @end menu @node Installation of cfservd, Configuration file cfservd.conf, Configuring cfservd, Configuring cfservd @subsection Installation of cfservd To install the cfservd daemon component, you will need to register a port for cfengine by adding the following line to the system file @file{/etc/services file} @smallexample cfengine 5308/tcp @end smallexample @noindent You could do this for all hosts by adding the following to your cfengine configuration @smallexample editfiles: @{ /etc/services AppendIfNoSuchLine "cfengine 5308/tcp" @} @end smallexample @noindent To start cfservd at boot time, you need to place a line of the following type in your system startup files: @smallexample # Start cfengine server cfservd @end smallexample @noindent Note that @code{cfservd} will re-read its configuration file whenever it detects that it has been changed, so you should not have to restart the daemon, not send it the HUP signal as with other daemons. @cindex HUP and cfservd, don't need to @cindex Restarting cfservd @cindex Rereading @file{cfservd.conf} @c ........................................... @c SUBSECTION @c ........................................... @node Configuration file cfservd.conf, , Installation of cfservd, Configuring cfservd @subsection Configuration file cfservd.conf The server daemon is controlled by a file called @file{cfservd.conf}. @cindex @file{cfservd.conf} file The syntax of this configuration file is deliberately modelled on cfengine's own configuration file, but despite the similarities, you cannot mix the contents of the two files. Though they are not compatible, @file{cfagent.conf} and @file{cfservd.conf} are similar in several ways: @itemize @bullet @item Both files use classes to label entries, so that you may use the same configuration file to control all hosts on your network. This is a convenience which saves you the trouble of maintaining many different files. @item Both files are searched for using the contents of the variable @code{CFINPUTS}. @cindex @code{CFINPUTS} variable @item You can use @code{groups} and @code{import} in both files to break up files into convenient modules and to import common resources, such as lists of groups. @end itemize Note that the classes in the @file{cfservd.conf} file do not tell you the classes of host which have access to files and directories, but rather which classes of host pay attention to the access and deny commands when the file is parsed. Host name authentication is not by class or group but by hostname, like the @file{/etc/exports} file on most Unix systems. The syntax for the file is as follows: @cartouche @smallexample control: @var{classes}:: domain = ( @var{DNS-domain-name} ) cfrunCommand = ( "@var{script/filename}" ) # Quoted MaxConnections = ( @var{maximum number of forked daemons} ) IfElapsed = ( @var{time-in-minutes} ) DenyBadClocks = ( @var{false} ) AllowConnectionsFrom = ( @var{IP numbers} ) DenyConnectionsFrom = ( @var{IP numbers} ) AllMultipleConnectionsFrom = ( @var{IP numbers} ) LogAllConnections = ( @var{false/true} ) SkipVerify = ( @var{IP numbers} ) groups: @var{Group definitions} import: @var{Files to import} admit: | grant: @var{classes}:: /@var{file-or-directory} @var{wildcards/hostnames} deny: @var{classes}:: /@var{file-or-directory} @var{wildcards/hostnames} root=@var{hostlist} encrypt=@var{true/on} @end smallexample @end cartouche @noindent See the reference manual for descriptions of these elements. The file consists of a control section and access information. You may use the control section to define any variables which you want to use, for convenience, in the remainder of your file. Following the control section, comes a list of files or directories and hosts which may access these. If permissions are granted to a directory then all subdirectories are automatically granted also. Note that plain-file symbolic links are not checked for, so you may need to specifically deny access to links if they are plain files, but cfservd does not follow directory symbolic links and give access to files in directories pointed to by these. Fully qualified hostnames should be used in this file. If host names are unqualified, the current domain is appended to them (do not forget to define the domain name). Authentication calls the Unix function @code{gethostbyname()} and so on to identify and verify connecting hosts, so the names in the file must reflect the type on names returned by this function. You may use wildcards in names to match, for instance, all hosts from a particular domain. Here is an example file @smallexample ##################################################### # # This is a cfservd config file # ##################################################### groups: PasswdHost = ( nexus ) ##################################################### control: # # Assuming CFINPUTS is defined # cfrunCommand = ( "/var/cfengine/bin/cfagent" ) variable = ( /usr/local/publicfiles ) ##################################################### admit: # Can also call this grant: # Note that we must grant access to the # agent if we wan to start it remotely with cfrun /var/cfengine/bin/cfagent PasswdHost:: /etc/passwd *.iu.hioslo.no FtpHost:: # An alternative to ftp, grant anyone /local/ftp/pub * # These file paths must not contain symbolic # links. Access control does not follow symlinks. any:: $CFINPUTS/cfrun.sh *.iu.hioslo.no ##################################################### deny: /etc/services borg.iu.hioslo.no /local/ftp *.pain-in-the-ass.com @end smallexample @emph{NOTE I: cfservd is not @code{rpc.mountd}, access control is by filename, not by device name. Do not assume that files lying in subdirectories are not open for access simply because they lie on a different device. You should give the real path name to file and avoid symbolic links.} @b{NOTE II: access control is per host and per user. User names are assumed to be common to both hosts. There is an implicit trust relationship here. There is no way to verify whether the user on the remote host is the same user as the user with the same name on the local host.} @b{NOTE III: Cfservd requires you to grant access to files without following any symbolic links. You must grant access to the real file or directory in order to access the file object.} This is a security feature in case parties with login access to the server could grant access to additional files by having the permission to create symbolic links in a transitory directory, e.g. @file{/tmp}. @cindex Symbolic links in admit @cindex Links in access control @cindex Access control by directory @cindex Access control and symlinks @cindex Device boundaries and remote copy access @mbindex Why does cfservd give access to files on a different filesystem? @mbindex Why do I get network access denied to files I have granted access to? @cindex Access control in cfservd @c ********************************************************************** @c CHAPTER @c ********************************************************************** @node Security and cfengine, Summary, Cfengine network services, Top @chapter Security and cfengine @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @menu * What is security?:: * A word of warning:: * Automation:: * Trust:: * Why trust cfengine?:: * Configuration:: * Disabling and replacing software:: * Process monitoring:: * Monitoring files:: * The setuid log:: * Suspicious filenames:: * Checksums and Tripwire functionality:: * FileExtensions:: * NonAlphaNumFiles:: * Defensive garbage collection:: * Anonymous FTP example:: * WWW security:: * Miscellaneous security of cfengine itself:: * Privacy (encryption):: * Trust and key races:: * Adaptive locks:: * Spoofing:: * Race conditions in file copying:: * size= in copy:: * useshell= and owner= in shellcommands:: * Firewalls:: @end menu Computer security is about protecting the data and availability of an association of hosts. Briefly, the key words are authentication, privacy, integrity and trust. To understand computer security we have to understand the interrelationships between all of the hosts and services on our networks as well as the ways in which those hosts can be accessed. Tools which allow this kind of management are complex and usually expensive. @node What is security?, A word of warning, Security and cfengine, Security and cfengine @section What is security? For a computer to be secure it must be *physically secure* --- if we can get our hands on a host then we are never more than a screwdriver away from all of its assets---but assuming that hosts are physically secure, we then wish to deal with the issues of software security which is a much more difficult topic. Software security is about access control and software reliability. No single tool can make computer systems secure. Major blunders have been made out of the belief that a single product (e.g. a `firewall') would solve the security problem. For instance, a few years ago a cracker deleted all the user directories from a dialup login server belonging to a major Norwegian telecommunications company, from the comfort of his web browser. This was possible, even through a firewall, because the web server on the host concerned was incorrectly configured. The bottom line is that there is no such thing as a secure operating system, firewall or none. What is required is a persistent mixture of vigilence and adaptability. For many, security is perceived as being synonymous with network privacy or network intrusion. Privacy is one aspect of security, but it is not the network which is our special enemy. Many breaches of security happen from within. There is little difference between the dangers of remote access from the network or direct access from a console: privacy is about access control, no matter where the potential intruder might be. If we focus exclusively on network connectivity we ignore a possible threat from internal employees (e.g. the janitor who is a computer expert and has an axe to grind, or the mischievous son of the director who was left waiting to play mom's office, or perhaps the unthinkable: a disgruntled employee who feels as though his/her talents go unappreciated). Software security is a vast subject, because modern computer systems are complex. It is only exacerbated by the connectivity of the internet which allows millions of people to have a go at breaking into networked systems. What this points to is the fact that a secure environment requires a tight control of access control on every host individually, not merely at specific points such as firewalls. This article is not a comprehensive guide to security. Rather it is an attempt to illustrate how cfengine can be used to help you automate a level of host integrity on all the hosts of your network. Cfengine is a network configuration tool with two facets. It is a language used to build an `expert system'. An expert system describes the way you would like your hosts and network to look and behave. CFengine is also a software robot which compares the model you have described with what the world really looks like and then sets to work correcting any deviations from that picture. In many ways it is like an immune system, neutralizing and repairing damaged parts. Unlike many shell-script packages for sysadmin, cfengine is a C program which means light on system resources. Also it works on a principle of `convergence'. Convergence means that each time you run cfengine the system should get closer to the model which you have described until eventually when the system is the model, cfengine becomes quiescent, just like an immune system. In the words of one user your hosts `never get worse'. This assumes of course that the model you have is what you really want. Using cfengine, model building becomes synonymous with formulating and formalizing a system policy. What makes cfengine a security tool is that security policy is a part of system policy: you cannot have one without the other. You will never have security unless you are in control of your network. Cfengine monitors and indeed repairs hosts with simple easily controllable actions. From an automation perspective, security is no different from the general day to day business of system maintenance, you just need to pay more attention to the details. We cannot speak of `have security' and `have not security'. There is always security, it is simply a matter of degree: weak or strong; effective or ineffective. @node A word of warning, Automation, What is security?, Security and cfengine @section A word of warning Before starting it is only proper to state the obvious. You should never trust anyone's advice about configuration or security without running it past your own grey matter first. The examples provided here are just that: examples. They might apply to you as written and they might need to be modified. You should never accept and use an example without thinking carefully and critically first! Also, in any book of recipies or guide to successful living you know that there are simplified answers to complex questions and you should treat them as such. There is no substitute for real understanding. @node Automation, Trust, A word of warning, Security and cfengine @section Automation Even in the smallest local area network you will want to build a scheme for automating host configuration and maintenance, because networks have a way of growing from one host into many quite quickly. It is therefore important to build a model which scales. A major reason for using cfengine is precisely for scalability. Whether you have one host or a hundred makes little difference. Cfengine is instructed from a central location, but its operation is completely and evenly spread across the network. Each host is responsible for obtaining a copy of the network model from a trusted source and is then responsible for configuring itself without intervention from outside. Unlike some models, cfengine does not have to rely on network communication or remote object models. We also need integration, or the ability to manage the interrelationships between hosts. It is no good having complete control of one important host and thinking that you are secure. If an intruder can get into any host, he or she is almost certain to get into the ones that matter, especially if you are not looking at all of them. Using cfengine is a good way of forcing yourself to formulate a configuration/security policy and then stick to it. Why cfengine? There are three reasons: i) it forces a discipline of preparation which focuses you on the problems at the right level of detail, ii) it provides you with `secure' scalable automation and a common interface to all your hosts, and iii) it scales to any number of hosts without additional burdens. We'll need to qualify some of these points below. The first step in security management is to figure out a security policy. That way, you know what *you* mean by security and if that security is breached, you will know what to do. In many cases you can formulate a large part of your security policy as cfengine code. That makes it formal, accurate and it means that it will get done by the robot without requiring any more work on your part. As an immune system, cfengine will even work fine in a partially connected environment it makes each host responsible for its own state. It is not reliant on network connectivty for remote method invocations or CORBA-style object requests as is, say, Tivoli. All it needs is an authentic copy of the network configuration document stored locally on each host. If this is the case, a detached host will not be left unprotected, at worst it might lag behind in its version of the network configuration. @node Trust, Why trust cfengine?, Automation, Security and cfengine @section Trust There are many implicit trust relationships in computer systems. It is crucial to understand them. If you do not understand where you are placing your trust, your trust can be exploited by attackers who have thought more carefully than you have. For example, any NFS server of users' home-directories trusts the root user on the hosts which mount those directories. Some bad accidents are prevented by mapping root to the user nobody on remote systems, but this is not security, only convenience. The root user can always use `su' to becomes any user in its password file and access/change any data within those filesystems. The .rlogin and hosts.equiv files on Unix machines grant root (or other user) privileges to other hosts without the need for authentication. If you are collecting software from remote servers, you should make sure that they come from a machine that you trust, particularly if they are files which could lead to privileged access to your system. Even checksums are no good unless they also are trustworthy. For example, it would be an extremely foolish idea to copy a binary program such as /bin/ps from a host you know nothing about. This program runs with root privileges. If someone were to replace that version of ps with a Trojan horse command, you would have effectively opened your system to attack. Most users trust anonymous FTP servers where they collect free software. In any remote copy you are setting up an implicit trust relationship. First of all you trust integrity of the host you are collecting files from. Secondly you trust that they have the same username database with regard to access control. The root user on the collecting host has the same rights to read files as the root user on the server. The same applies to any matched user name. @node Why trust cfengine?, Configuration, Trust, Security and cfengine @section Why trust cfengine? Cfengine has a very simple trust model. It trusts the integrity of its input file and any data which is explicitly chooses to download. Cfengine places the responsibility on root on the localhost not on any outsiders. *You* can make cfengine destroy your system, just as you can destroy it yourself, but no one else can, so as long as you are careful with the input file you are trusting essentially no-one. We shall qualify this below for remote file copying. Cfengine assumes that its input file is secure. Apart from that input file, no part of cfengine accepts or uses any configuration information from outside sources. The most one could do from an authenticated network connection is to ask cfengine to carry out (or not) certain parts of its model, thus in the worst case scanario an outside attacker could spoof cfengine into configuring the host correctly. In short, no one except root on the localhost can force cfengine to do anything (unless root access to your system has already been compromised by another route). This means that there is a single point of failure. The input file does not even have to be private as long as it is authentic. No one except you can tell cfengine what to do. There is a catch though. Cfengine can be used to perform remote file transfer. In remote file transfer one is also forced to trust the integrity of the data received, just as in any remote copy scheme. Although cfengine works hard to authenticate the identity of the host, once the host's identity is verified it cannot verify the accuracy of unknown data it has been asked to receive. Also, as with all remote file transfers, cfengine could be tricked by a DNS spoofing into connecting to an imposter host, so use the IP addresses of hosts, not their names if you don't trust your DNS service. In short, these faults are implicit in remote copying. They do not have to do with cfengine itself. This has nothing to do with encryption as users sometimes believe: encrypted connections do not change these trust relationships---they improve the privacy of the data being transmitted not their accuracy or trustworthiness. The point of cfengine is normally to have only one global configuration for every host. This needs to be distributed somehow which means that hosts must collect this file from a remote server. This in turn means that you must trust the host which has the master copy of the cfengine configuration file. @node Configuration, Disabling and replacing software, Why trust cfengine?, Security and cfengine @section Configuration The beginning of security is correct host configuration. Even if you have a firewall shielding you from outside intrusion, an incorrectly configured host is a security risk. Host configuration is what cfengine is about, so we could easily write a book on this. Rather than reiterating the extensive documentation, let's just consider a few examples which address actual problems and get down to business without further ado. A cfengine configuration file is composed of objects with the following syntax (see the cfengine documentation): @smallexample rule-type: classes-of-host-this-applies-to:: Actual rule 1 Actual rule 2 ... @end smallexample The rule-types include checking file permissions, editing textfiles, disabling (renaming and removing permissions to) files, controlled execution of scripts and a variety of other things relating to host configuration. Some of the `control' rules are simply flags which switch on complex (read `smart') behaviour. Every cfengine program needs an actionsequence which tells it the order in which bulk configuration operations should be evaluated. e.g. @smallexample control: actionsequence = ( netconfig copy processes editfiles ) @end smallexample You should look at the cfengine manual to get started with your configuration. Let us step through some basic idioms which can repeated in different contexts. As representative examples we shall take Solaris and GNU/Linux as example operating systems. This is not to single them out as being particularly secure or insecure, it is merely due to their widespread use and for definiteness. @node Disabling and replacing software, Process monitoring, Configuration, Security and cfengine @section Disabling and replacing software One of the simplest things which we are asked to do constantly is to disable dangerous programs as bugs are discovered. CERT security warnings frequently warn about programs with flaws which can compromise a system. In cfengine, disabling a file means renaming it to *.cfdisabled and setting its permission to 600. @smallexample disable: # # CERT security patches # solaris:: /usr/openwin/bin/kcms_calibrate /usr/openwin/bin/kcms_configure /usr/bin/admintool /etc/rc2.d/S99dtlogin /usr/lib/expreserve linux:: /sbin/dip-3.3.7n /etc/sudoers /usr/bin/sudoers @end smallexample Although this is a trivial matter, the fact that it is automated means that cfengine is checking for this all the time. As long as a host is up and running (connected to the network or not) cfengine will be ensuring the named file is not present. Another issue is to replace standard vendor programs with drop-in replacements. For example, most admins would like to replace their vendor sendmail with the latest update from Eric Allman's site. One way to do this is to compile the new sendmail into a special directory, separate from vendor files and then to symbolically link the new program into place. @smallexample links: solaris||linux:: /usr/lib/sendmail ->! /usr/local/lib/mail/bin/sendmail-8.9.3 /usr/sbin/sendmail ->! /usr/local/lib/mail/bin/sendmail-8.9.3 /etc/mail/sendmail.cf ->! /usr/local/lib/mail/etc/sendmail.cf @end smallexample The exclamation marks mean (by analogy with the csh) that existing file objects should be replaced by links to the named files. Again the integrity of these links is tested every time cfengine runs. If the object /usr/lib/sendmail is not a link to the named file, the old file is moved and a link is made. If the link is okay, nothing happens. After putting the new sendmail in place, you will need to make sure that the restricted shell configuration is in order. @smallexample # # Sendmail, restricted shell needs these links # solaris:: # Most of these will only be run on the MailHost # but flist (procmail) is run during sending... /usr/adm/sm.bin/vacation -> /usr/ucb/vacation /usr/adm/sm.bin/flist -> /home/listmgr/.bin/flist linux:: /usr/adm/sm.bin/vacation -> /usr/bin/vacation @end smallexample Link management is a particularly useful feature of cfengine. By putting links (actually all system modifications) into the cfengine configuration and never doing anything by hand, you build up a system which is robust to reinstallation. If you lose your host, you just have to run cfengine once or twice to reconstruct it. Of course, the fundamental tenet of security is to be able to restrict privilege to resources. We therefore need to check the permissions on files. For instance, a recent CERT advisory warned of problems with some free unix mount commands which were setuid root. If we suppose there is a group of hosts called `securehosts' which we don't need to worry about, then we could remove the setuid bits on all other hosts as follows: @smallexample files: !securehosts.linux:: /bin/mount mode=555 owner=root action=fixall /bin/umount mode=555 owner=root action=fixall securehosts.linux:: /bin/mount m=6555 o=root action=fixall /bin/umount m=6555 o=root action=fixall @end smallexample One area where cfengine excels over other tools is in its ascii file editing abilities. Editing textfiles in a non-destructive way is such an important operation that having used it you will wonder how you every managed without it! Here are some simple but real examples of how file editing can be used. @smallexample editfiles: # sun4, who are they kidding? @{ /etc/hosts.equiv HashCommentLinesContaining "+" @} # # CERT security patch for vold vulnerability # sunos_5_4:: @{ /etc/rmmount.conf HashCommentLinesContaining "action cdrom" HashCommentLinesContaining "action floppy" @} @end smallexample TCP wrapper configuration can be managed easily by maintaining a pair of master files on a trusted host. Files of the form @smallexample # /etc/hosts.allow (exceptions) # # Public services sendmail: ALL in.ftpd: ALL sshd: ALL # Private services in.fingerd: .example.org LOCAL in.cfingerd: .example.org LOCAL sshdfwd-X11: .example.org LOCAL # Portmapper has to use IP series portmap: 128.39.89. 128.39.74. 128.39.75. @end smallexample and @smallexample # /etc/hosts.deny (default) ALL: ALL @end smallexample may be distributed to each host by cfengine @smallexample copy: /masterfiles/hosts.deny dest=/etc/hosts.deny mode=644 server=trusted /masterfiles/hosts.allow dest=/etc/hosts.allow mode=644 server=trusted @end smallexample and installed as follows @smallexample editfiles: @{ /etc/inet/inetd.conf # Make sure we're using tcp wrappers ReplaceAll "/usr/sbin/in.ftpd" With "/local/sbin/tcpd" ReplaceAll "/usr/sbin/in.telnetd" With "/local/sbin/tcpd" ReplaceAll "/usr/sbin/in.rshd" With "/local/sbin/tcpd" ReplaceAll "/usr/sbin/in.rlogind" With "/local/sbin/tcpd" processes: "inetd" signal=hup @end smallexample The services which we do not need should be removed altogether. There's no sense in tempting fate: @smallexample editfiles: @{ /etc/inetd.conf # Eliminate unwanted services HashCommentLinesContaining "rwall" HashCommentLinesContaining "/usr/sbin/in.fingerd" HashCommentLinesContaining "comsat" HashCommentLinesContaining "exec" HashCommentLinesContaining "talk" HashCommentLinesContaining "echo" HashCommentLinesContaining "discard" HashCommentLinesContaining "charge" HashCommentLinesContaining "quotas" HashCommentLinesContaining "users" HashCommentLinesContaining "spray" HashCommentLinesContaining "sadmin" HashCommentLinesContaining "rstat" HashCommentLinesContaining "kcms" HashCommentLinesContaining "comsat" HashCommentLinesContaining "xaudio" HashCommentLinesContaining "uucp" @} @end smallexample @node Process monitoring, Monitoring files, Disabling and replacing software, Security and cfengine @section Process monitoring When it comes to process management we are usually interested in three things: i) making sure certain processes are running, ii) making sure some processes are NOT running and iii) sending HUP signals to force configuration updates. To HUP a daemon and make sure that it is running, we write @smallexample processes: linux:: "inetd" signal=hup restart "/usr/sbin/inetd" useshell=false "xntp" restart "/local/sbin/xntpd" useshell=false @end smallexample The useshell option tells cfengine that it should not use a shell to start the program. The idea here is to protect against IFS attacks. Unfortunately some programs require a shell in order to be started, but most do not. This is an extra precaution. When the cron daemon crashes, restarting it can be a problem since it does not close its filed descriptors properly when forking. The dumb-option helps here: @smallexample "cron" matches=>1 restart "/etc/init.d/cron start" useshell=dumb @end smallexample To kill processes which should not be running, we write: @smallexample processes: solaris:: # # Don't want CDE stuff or SNMP peepholes... # "ttdbserverd" signal=kill "snmpd" signal=kill "mibiisa" signal=kill @end smallexample A couple of years ago, a broken cracked account was revealed at Oslo College by the following test in the cfengine configuration: @smallexample processes: # Ping attack ? "ping" signal=kill inform=true @end smallexample There are few legimate reasons to run the ping command more than a few times. The chances of cfengine detecting single pings is quite small. But coordinated ping attacks are another story. When it was revealed that a user had twenty ping processes attempting to send large ping packets to hosts in the United States it was obvious the the account had been compromised. Fortunately for the recipient, the ping command was incorrectly phrased and would probably not have been noticed. @smallexample processes: "sshd" restart "/local/sbin/sshd" useshell=false "snmp" signal=kill "mibiisa" signal=kill "named" matches=>1 restart "/local/bind/bin/named" useshell=false # Do the network community a service and run this "identd" restart "/local/sbin/identd" inform=true @end smallexample Process management also includes the garbage collection which we shall return to briefly. @node Monitoring files, The setuid log, Process monitoring, Security and cfengine @section Monitoring files Almost all security programs available are for the monitoring of file integrity. Cfengine also incorporates tools for monitoring files. Here are some of the elements in the faily complex files command: @smallexample files: classes:: /file-object mode=mode owner=uid-list group=gid-list action=fixall/warnall.. ignore=pattern include=pattern exclude=pattern checksum=md5 syslog=true/on/false/off @end smallexample In additions to these, there are extra flags for BSD filesystems and ways of managing file ACLs for systems like NT. Here are some examples of basic checks on file permissions: @smallexample classes: # Define a class of hosts based on a test... have_shadow = ( `/bin/test -f /etc/shadow` ) NFSservers = ( server1 server2 ) files: any:: /etc/passwd mode=0644 o=root g=other action=fixplain have_shadow:: /etc/shadow mode=0400 o=root g=other action=fixplain # Takes a while so do this at midnight and only on servers NFSservers.Hr00:: /usr/local mode=-0002 Check no files are writable! recurse=inf owner=root,bin group=0,1,2,3,4,5,6,7,staff action=fixall @end smallexample In the last example we parse through a whole file system (recurse=inf) and as a result we get a number of checks for free. Any previously unknown setuid programs are reported as well as any suspicious filenames (see below). @node The setuid log, Suspicious filenames, Monitoring files, Security and cfengine @section The setuid log Cfengine is always on the lookout for files which are setuid or setgid root. It doesn't go actively looking for them uninvited, but whenever you get cfagent to check a file or directory with the files feature, it will make a note of setuid programs it finds there. These are recorded in the file cfengine.host.log which is stored under /var/cfengine or /var/log/cfengine. When new setuid programs are discovered, a warning is printed, but only if you are root. If you ever want a complete list, delete the log file and cfengine will think that all of the setuid programs it finds are new. The log file is not readable by normal users. @node Suspicious filenames, Checksums and Tripwire functionality, The setuid log, Security and cfengine @section Suspicious filenames Whenever cfagent opens a directory and scans through files and directories (recursively) (files, tidy, copy), it is also on the lookout for for suspicious filenames, i.e. files like ".. ." containing only space and/or dots. Such files are seldom created by sensible sources, but are often used by crackers to try to hide dangerous programs. Cfagent warns about such files. Although not necessarily a security issue, cfagent will also warn about filenames which contain non-printable characters if desired, and directories which are made to look like plain files by giving them filename extensions. @smallexample control: # # Security checks # NonAlphaNumFiles = ( on ) FileExtensions = ( o a c gif jpg html ) # etc SuspiciousNames = ( .mo lrk3 lkr3 ) @end smallexample The file extension list may be used to detect concealed directories during these searches, if users create directories which look like common files this will be warned about. Additional suspicious filenames can be checked for automatically as a matter if course. This is commented further below. The mail spool directory is a common place for users to try to hide dowloaded files. These options inform about files which do not have the name of a user or are not owned by a valid user: @smallexample control: WarnNonOwnerMail = ( true ) WarnNonUserMail = ( true ) # Warn about mail which is not owned by a user @end smallexample Corresponding commands exist to delete these files without further ado. This can be a useful way of cleaning up after users whose accounts have been removed. @node Checksums and Tripwire functionality, FileExtensions, Suspicious filenames, Security and cfengine @section Checksums and Tripwire functionality Cfagent can be used to check for changes in files which only something as exacting as an MD5 checksum/digest can detect. If you specify a checksum database and activate checksum verification, @smallexample control: ChecksumUpdates = ( false ) files: /filename checksum=md5 .... /dirname checksum=md5 recurse=inf.... # If the database isn't secure, nothing is secure... /var/cfengine/cache.db mode=600 owner=root action=fixall @end smallexample then cfagent will build a database of file checksums and warn you when files' checksums change. This makes cfagent act like Tripwire (currently only with MD5 checksums). It can be used to show up Trojan horse versions of programs. It should be used sparingly though since database management and MD5 checksum computation are resource intensive operations and this could add significant time to a cfagent run. The ChecksumUpdates variable (normally false) can be set to true to update the checksum database when programs change for valid reasons. Warnings are all every fine and well, but the spirit of cfengine is not to bother us with warnings, it is to fix things automatically. Warning is a useful supplement, but in security breaches it is better to fix the problem, rather than leaving the host in a dangerous state. If you are worried about the integrity of the system then don't just warn about checksum mismatches here, make an md5 copy comparison against a read-only medium which has correct, trusted version of the file on it. That way if a binary is compromised you will not only warn about it but also repair the damage immediately! The control variable ChecksumUpdates may be switched to on in order to force cfagent to update its checksum database after warning of a change. @node FileExtensions, NonAlphaNumFiles, Checksums and Tripwire functionality, Security and cfengine @section FileExtensions This list may be used to define a number of extensions which are regarded as being plain files by the system. As part of the general security checking cfagent will warn about any directories which have names using these extensions. They may be used to conceal directories. @smallexample FileExtensions = ( c o gif jpg html ) @end smallexample @node NonAlphaNumFiles, Defensive garbage collection, FileExtensions, Security and cfengine @section NonAlphaNumFiles If enabled, this option causes cfagent to detect and disable files which have purely non-alphanumeric filenames, i.e. files which might be accidental or deliberately concealed. The files are then marked with a suffix .cf-nonalpha and are rendered visible. @smallexample NonAlphaNumFiles = ( on ) @end smallexample These files can then be tidied (deleted) or disabled by searching for the suffix pattern. Note that alphanumeric means ascii codes less than 32 and greater than 126. @node Defensive garbage collection, Anonymous FTP example, NonAlphaNumFiles, Security and cfengine @section Defensive garbage collection We tend to be worried about the fact that crackers will destroy our systems and make them unusable, but many operating systems are programmed to do this to themselves! There are few systems which can survive a full system disk and yet many logging agents go on filling up disks without ever checking to see how full they are getting. In short they choke themselves in a self-styled denial of service attack. Cfagent can help here by rotating logs frequently and by tidying temporary file directories: @smallexample disable: Tuesday.Hr00:: # # Disabling these log files weekly prevents them from # growing so enormous that they fill the disk! # /local/iu/httpd/logs/access_log rotate=2 /local/iu/httpd/logs/agent_log rotate=2 /local/iu/httpd/logs/error_log rotate=2 /local/iu/httpd/logs/referer_log rotate=2 FTPserver.Sunday:: /local/iu/logs/xferlog rotate=3 tidy: /tmp pattern=* age=1 @end smallexample Process garbage collection is just as important. There are lot's of reasons why process tables fill up with unterminated processes. One example is faulty X terminal software which does not kill its children at logout. Another is that programs like netscape and pine tend to go into loops from which they never return, gradually loading the system with an ever increasing glacial burden. Just killing old processes can cause your system to spring back from its ice age blues (hopefully without littering the system with too many dead mammoths or bronze age axe-bearers). If the host concerned has important duties then this lack of responsiveness can compromise key services. It also gives local users a way of carrying out denial of service attacks on the system. If users always log out at the end of the day and log in again the day after then this is easy to address with cfengine. Here is some code to kill commonly hanging processes. Note that on BSD like systems process options "aux" are required to see the relevant processes: @smallexample processes: linux|freebsd|sun4:: SetOptionString "aux" any:: "Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec" signal=kill include=ftpd include=tcsh include=xterm include=netscape include=ftp include=pine include=perl include=irc include=java include=/bin/ls include=emacs include=passwd @end smallexample This pattern works like this: as processes become more than a day old they name of the month appears in the date of the process start time. These are matched by the regular expression. The include lines then filter the list of the processes further picking out lines which include the specified strings. On some BSD-like systems the default ps option string is "-ax" and you might need to reset it to something which adds the start date in order to make this work. Another job for process management is to clean up processes which have hung, gone amok or which are left over from old logins. Here is a regular expression which detects non-root processes which have clocked up more than 100 hours of CPU time. This is a depressingly common phenomenon when a program goes into an infinite loop. It can starve other processes of resources in a very efficient denial of service attack. @smallexample any:: # # Kill processes which have run on for too long e.g. 999:99 cpu time # Careful a pattern to match 99:99 will kill everything! # "[0-9][0-9][0-9][0-9]:[0-9][0-9]" signal=term exclude=root "[0-9][0-9][0-9]:[0-9][0-9]" signal=term exclude=root @end smallexample Under NT this is not so simple, since the process table for the cygwin library applies only to processes which have been started by programs working under the Unix process emulation. Hopefully this short-coming can be worked around at some point in the future. @node Anonymous FTP example, WWW security, Defensive garbage collection, Security and cfengine @section Anonymous FTP example Configuring a service like anonymous FTP requires a certain amount of vigilance. It is a good idea to automate it and let cfengine make sure that things don't go astray. Note that we constantly ensure that the ls program used by the anonymous ftp server is a trusted program by checking it with an md5 signture of a trusted version of the program. If for some reason it should be replaced with a Trojan horse, cfagent would notice the incorrect checksum (md5) and move the bad program to ls.cf-saved and immediately replace it with the correct version without waiting for the adminstrator to act. The inform and syslog options ask for an explicit warning to be made about this copy. Here is a complete anonymous ftp setup and maintenance program for Solaris hosts. @smallexample control: actionsequence = ( directories copy editfiles files ) # Define variables ftp = ( /usr/local/ftp ) uid = ( 99 ) # ftp user gid = ( 99 ) # ftp group directories: solaris:: $(ftp)/pub mode=644 owner=root group=other $(ftp)/etc mode=111 owner=root group=other $(ftp)/dev mode=555 owner=root group=other $(ftp)/usr mode=555 owner=root group=other $(ftp)/usr/lib mode=555 owner=root group=other files: solaris:: $(ftp)/etc/passwd mode=644 o=root action=fixplain $(ftp)/etc/shadow mode=400 o=root action=fixplain $(ftp)/pub mode=644 owner=ftp action=fixall recurse=inf copy: solaris:: # Make sure ls is a trusted program by copying # a secure location... /bin/ls dest=$(ftp)/usr/bin/ls mode=111 owner=root type=checksum inform=true syslog=true /etc/netconfig dest=$(ftp)/etc/netconfig mode=444 o=root /devices/pseudo/mm@@0:zero dest=$(ftp)/dev/zero mode=666 o=root /devices/pseudo/clone@@0:tcp dest=$(ftp)/dev/tcp mode=444 o=root /devices/pseudo/clone@@0:udp dest=$(ftp)/dev/udp mode=666 o=root /devices/pseudo/tl@@0:ticotsord dest=$(ftp)/dev/ticotsord mode=666 o=root /usr/lib dest=$(ftp)/usr/lib recurse=2 mode=444 owner=root backup=false include=ld.so* include=libc.so* include=libdl.so* include=libmp.so* include=libnsl.so* include=libsocket.so* include=nss_compat.so* include=nss_dns.so* include=nss_files.so* include=nss_nis.so* include=nss_nisplus.so* include=nss_xfn.so* include=straddr.so* /usr/share/lib/zoneinfo dest=$(ftp)/usr/share/lib/zoneinfo mode=444 recurse=2 o=root type=binary editfiles: solaris:: # # Make sure that umask is right for ftpd # or files can be left 666 after upload! # @{ /etc/rc2.d/S72inetsvc PrependIfNoSuchLine "umask 022" @} @{ $(ftp)/etc/passwd AutoCreate EmptyEntireFilePlease AppendIfNoSuchLine "ftp:x:$(uid):$(gid):Anonymous FTP:$(ftp):/bin/sync" @} @{ $(ftp)/etc/group AutoCreate EmptyEntireFilePlease AppendIfNoSuchLine "ftp::$(gid):" @} @{ $(ftp)/etc/shadow AutoCreate EmptyEntireFilePlease AppendIfNoSuchLine "ftp:NP:6445::::::" @} # Finally...useful for chown @{ /etc/passwd AppendIfNoSuchLine "ftp:x:$(uid):$(gid):Anonymous FTP:$(ftp):/bin/sync" @} @{ /etc/group AppendIfNoSuchLine "ftp::$(gid):" @} @end smallexample @node WWW security, Miscellaneous security of cfengine itself, Anonymous FTP example, Security and cfengine @section WWW security The security of the web is a slightly paradoxical business. On the one hand, we make a system for distributing files to anyone without the need for passwords, and on the other hand we are interested in limited who gets what information and who can change what. If you want web privacy you have to exclude the possibility of running untrusted CGI scripts, i.e. CGI programs which you did not write yourself since CGI programs can circumvent any server security. This is because of a fundamental weakness in the way that a WWW server works. It makes user-CGI scripts incompatible with the idea of private WWW areas. The problem with CGI is this: in order for the httpd daemon to be able to read information to publish it, that information must be readable by the UID with which httpd runs (e.g. the www special user (you should not run with uid nobody since that can be mixed up with NFS mappings)). But CGI programs automatically run with this www UID also. Since it is not possible to restrict the actions of CGI programs which you did not write yourself, any CGI program has automatically normal file permission access to any file which the server can see. A CGI program could choose to open a restricted file circumventing the security of the daemon. In short, privacy requires a separate UID (a separate daemon and port number) or a separate server host altogether. Provided you acknowledge this weakness, you can still use cfengine to administrate the permissions and access files on say two WWW servers from your central location. Let us imagine having a public WWW server and a private WWW server and assume that they have a common user/UID database. We begin by defining a user-ID and group-ID for the public and private services. These need to have different ID's in order to prevent the CGI trick mentioned above. @smallexample editfiles: wwwpublic:: @{ $(publicdocroot)/.htaccess AutoCreate EmptyEntireFilePlease AppendLine "order deny,allow" AppendLine "deny from all" AppendLine "allow from all" @} wwwprivate:: @{ $(privatedocroot)/.htaccess AutoCreate EmptyEntireFilePlease AppendLine "order deny,allow" AppendLine "deny from all" AppendLine "allow .example.org" @} @end smallexample Your documnts should be owned by a user and group which is *not* the same as the UID/GID the daemon runs with, otherwise CGI programs and server-side emebellishments could write and destroy those files. You will also want to ensure that the files are readable by the www daemon, so a files command can be used to this end. You might want a group of people to have access to the files to modifiy their contents. @smallexample files: wwwprivate:: $(privatedocroot) mode=664 owner=priv-data group=priv-data act=fixall wwwpublic:: $(publicdocroot) mode=664 owner=public-data group=public-data act=fixall @end smallexample @node Miscellaneous security of cfengine itself, Privacy (encryption), WWW security, Security and cfengine @section Miscellaneous security of cfengine itself @smallexample control: SecureInput = ( on ) @end smallexample If this is set cfengine will not read any files which are not owned by the uid running the program, or which are writable by groups or others. @node Privacy (encryption), Trust and key races, Miscellaneous security of cfengine itself, Security and cfengine @section Privacy (encryption) Encryption (privacy) is not often a big deal in system administration. With the exception of the distribution of passwords and secret keys themselves, there is little or no reason to maintain any level of privacy when transferring system files (binaries for instance). If you find yourself using a tool like cfengine to transmit company secrets from one place to another you should probably book yourself into the nearest asylum for a checkup. Cfengine is not about super-secure communication, but it can be used to perform the simple job of file distribution through an encrypted link (e.g. as a NIS replacement or other password distributor). Cfengine uses the triple DES implemenation in the OpenSSL distribution (or equivalent) to provide `good enough' privacy during remote copying. The most important issue in system security is authentication. Without the ability to guarantee the identity of a user or of trusted information it is impossible to speak of security at all. Although services like pidentd can go some way to confirming the identity of a user, the only non-spoofable way of confirming identity is to use a shared secret --- i.e. a password. A password works by demanding that two parties who want to trust one another must both know a piece of information which untrusted parties do not. Following the second world war, the now famous pair, Julius and Ethel Rosenberg were convicted and executed for spying on the U.S. bomb project for the Soviet Union in 1953. At one point they improvised a clever password system: a cardboard Jell-O box was torn in two and one half given to a contact whom they later would need to identify. The complex edge shape and colour matching made a complex key quite impossible to forge. Our bodies use a similar method of receptor identification of molecules for immune responses as well as for smell (with some subtleties). Without matching secrets it is impossible to prove someone's identity. @cindex Immune identity To copy a file over an encrypted link, you write: @smallexample copy: source dest=destination encrypt=true server=myserver trustkey=true @end smallexample Bear in mind that the server must be a trusted host. Privacy won't help you if the data you are collecting are faulty. In order to use the encryption there must be a public/private key pair on each host. The public key must be known by both hosts. You can use the program cfkey to generate a new key file. This public key file must then be distributed. Cfagent/cfrun and cfservd can exchange keys securely over the network. This is fine, provided you trust the sources of the keys (how do you know the key is from the host/user who claims to have sent it?). Under encrypted communications cfengine conceals the names and contents of files. Provided the private key files are private, this has the added side effect of authenticating both hosts for one another. On the server side, you can choose whether root on a client host should have server-root's privileges to read protected files on the server. In the @file{cfservd.conf} file you make a list: @smallexample control: TrustKeysFrom = ( @var{ip-address/series} ) admit: /filetree *.domain.country root=myhost,yourhost /etc/shadow *.domain.country encrypt=true @end smallexample In the second example, you can also restrict access to certain files to encrypted lines, i.e. demand that clients use a private connection to collect the file, in order to prevent wiretapping. @node Trust and key races, Adaptive locks, Privacy (encryption), Security and cfengine @section Trust and key races Trust is the central issue in the security of any system. Public and private keys help you to trust other hosts, only after the genuine, legitimate public keys have been securely distributed to all relevant parties. Until that has happened, it is necessary to trust the identity of remote hosts. Cfengine provides trust policy options which decide whether keys should be exchanged on trust or not, when remote parties connect for the first time. If you do not want to blindly trust keys, you could arrange to exchange key files manually, e.g. @smallexample scp /var/cfengine/ppkeys/localhost.pub remote:/var/cfengine/ppkeys/root-@var{IP-number}.pub @end smallexample @noindent or you could arrange to connect at a specific time, so minimize the chances of spoofer racing you to the finishing line in transferring a key for a given user at a given host. @cindex Race condition with public keys Note that, even program like ssh which use "privileged ports" are no longer immune to spoofing. Privileged ports are ports which only the root user can bind to. The idea used to be, a connection on a privileged port must have come from a trusted user, because only someone with the root/Administrator password would be able to bind to a privileged port. Today, that idea is naive at best. Anyone can set up their own host, pull the plug on another and spoof an address or user identity -- there are so many ways to attack a system that it is impossible to know with certainty to whom one is talking over the net. The only security one has is in being able to keep a secret key. However, if someone gets there before you, with a fake key, and claims to be you, the receiver cannot know better. This applies to any and all cryptographic software. @cindex Privileged ports Cfengine secure copy is not based on SSL/TLS (although it shares some of the lower level libraries). SSL is not appropriate for a system administration tool, because it uses a trust model based on a third party, such as Verisign. Most adminisrators are not prepared to pay a fee to register every host on their network, with a trusted third party. @cindex Trusted Third Party Cfengine does not use the Secure Shell protocol either. The ssh protocol is not directly appropriate for a system management tool, because it provides only unilateral authentication of user to server. Cfengine authenticates these parties mutually, i.e. user to server, and server to user. Moreover, ssh requires a user to manually accept a key on trust, when the public keys are unknown to the parties, whereas cfengine works non-interactively. SSh uses the notion of binding to a trusted port, to confirm privileged user identity. Cfengine does not make this assumption. @node Adaptive locks, Spoofing, Trust and key races, Security and cfengine @section Adaptive locks Cfengine treats all of its operations as transactions which are locked. Locking prevents contention from competing processes and it also places reasonable limits on the execution of the program. The fact that operations are locked means that several cfengine programs can coexist without problems. Two locking parameters control the way in which operations can procure locks. The IfElapsed parameter tells operations that they can only be performed if a certain period of time has elapsed since the last time the action was performed. This is anti-spamming protection. The ExpireAfter parameter tells cfengine that no action should last more than a given length of time. This is protection against hanging sub-processes. @node Spoofing, Race conditions in file copying, Adaptive locks, Security and cfengine @section Spoofing Spoofing refers to attempts to masquerade as another host when sending network transmissions. The cfservd program which can be used to transfer files or activate cfengine remotely attempts to unmask such attempts by performing double reverse lookups in the name service. This verifies by a trusted server that the socket address and the host name are really who they claim to be. @node Race conditions in file copying, size= in copy, Spoofing, Security and cfengine @section Race conditions in file copying When copying files from a source, it is possible that something might go wrong during the operation and leave a corrupt file in place. For example, the disk might become full while copying a file. This could lead to problems. Cfengine deals with this by always copying to a new file on the destination filesystem (prefix .cfnew) and then renaming it into place, only if the transfer was successful. This ensures that there is space on the filesystem and that nothing went wrong with the network connection or the disk during copying. @node size= in copy, useshell= and owner= in shellcommands, Race conditions in file copying, Security and cfengine @section size= in copy As a further check on copying, cfengine allows you to define acceptable limits on the size of files. After all, sometimes errors might occur quite independently of anything you are doing with cfengine. Perhaps the master password file got emptied somehow, or got replaced by a binary, through some silly mistake. By checking making an estimate of the expected size of the file and adding it to the copy command, you can avoid installing a corrupt file and making a localized problem into a global one. @node useshell= and owner= in shellcommands, Firewalls, size= in copy, Security and cfengine @section useshell= and owner= in shellcommands There are dangers in starting scripts from programs which run with root privileges. Normally, shell commands are started by executing them with the help of a /bin/sh -c command. The trouble with this is that it leaves one open to a variety of attacks. One example is fooling the shell into starting foreign programs by manipulating the IFS variable to treat '/' as a separator. You can ask cfengine to start programs directly, without involving an intermediary shell, by setting the useshell variable to false. The disadvantage is that you will not be able to use shell directives such as | and > in your commands. The owner=uid directive executes shell commands as a special user, allowing you to safely run scripts without root privilege. @node Firewalls, , useshell= and owner= in shellcommands, Security and cfengine @section Firewalls Cfengine is a useful tool for implementing, monitoring and maintaining firewalls. You can control what programs are supposed to be on the firewall and what programs are not supposed to be there. You can control file permissions, processes and a dozen other things which make up the configuration of a bastion host. By referencing important programs against a read only medium you can not only monitor host integrity but always be certain that you are never more than a cfengine execution away from correctness. @node Summary, Variable Index, Security and cfengine, Top @chapter Summary Cfengine is not a tool, it is an environment for managing host configuration and integrity. In this article it has only been possible to scratch the surface of what cfengine can do. To fully understand the syntax of the examples here you should read the documentation for cfengine. The big advantage of cfengine over many other configuration schemes is that you can have *everything* in one file (or set of files). The global file is common to every host and yet it can be as general or as specific as you want it to be. You can use it as a front end for cron, and you can use its advanced features to make your hosts *converge* to a desired, correct state. @c ********************************************************************** @c INDEX @c ********************************************************************** @node Variable Index, Concept Index, Summary, Top @unnumbered Variable Index @printindex vr @node Concept Index, FAQ Index, Variable Index, Top @unnumbered Concept Index @printindex cp @node FAQ Index, , Concept Index, Top @unnumbered FAQ Index @printindex mb @ifhtml @html @end html @end ifhtml @contents @ifhtml @html @end html @end ifhtml @bye cfengine-2.2.10/doc/cfetoolimport.80000644000175000001440000001436610261007217014021 00000000000000.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "CFETOOLIMPORT 1" .TH CFETOOLIMPORT 1 "2004-09-21" "perl v5.8.4" "User Contributed Perl Documentation" .SH "NAME" cfetool import \- import the contents of a database from XML format .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBcfetool\fR \fBimport\fR \fIname\fR \&\fB\-\-file\fR|\fB\-f\fR\ \fIfilename\fR [\fB\-\-path\fR|\fB\-p\fR\ \fIdirectory\ name\fR] [\fB\-\-daily\fR|\fB\-d\fR] [\fB\-\-weekly\fR|\fB\-w\fR] [\fB\-\-yearly\fR|\fB\-y\fR] [\fB\-\-verbose\fR|\fB\-v\fR] [\fB\-\-help\fR|\fB\-h\fR] .SH "DESCRIPTION" .IX Header "DESCRIPTION" Creates a new database from it's \s-1XML\s0 representation, in the format created by \&\fBrrdtool dump\fR. .PP The \fB\-d\fR, \fB\-w\fR, and \fB\-y\fR options specify which databases to create and look for in the dump, and may be combined. If they are all ommitted, the default is to only import the weekly database. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-\-file\fR|\fB\-f\fR \fIfilename\fR" 4 .IX Item "--file|-f filename" Specifies the \s-1XML\s0 file to restore. .IP "\fB\-\-path\fR|\fB\-p\fR" 4 .IX Item "--path|-p" The directory in which to create the new database folder. If this argument is not provided, the current working directory will be used. .IP "\fB\-\-daily\fR|\fB\-d\fR" 4 .IX Item "--daily|-d" Create a database for recording daily patterns. .IP "\fB\-\-weekly\fR|\fB\-w\fR" 4 .IX Item "--weekly|-w" Create a database for recording weekly patterns. .IP "\fB\-\-yearly\fR|\fB\-y\fR" 4 .IX Item "--yearly|-y" Create a database for recording yearly patterns. .IP "\fB\-\-verbose\fR|\fB\-v\fR" 4 .IX Item "--verbose|-v" Print details of the command's execution to the standard output stream. .IP "\fB\-\-help\fR|\fB\-h\fR" 4 .IX Item "--help|-h" Print a short help message and then exit. .SH "EXAMPLE" .IX Header "EXAMPLE" .Vb 1 \& % cfetool import temperature_copy --path /my/path --file ./temperature.xml .Ve .PP Create a new weekly database, \f(CW\*(C`temperature_copy\*(C'\fR, in the \f(CW\*(C`/my/path\*(C'\fR directory, and import it's contents from the file \f(CW\*(C`temperature.xml\*(C'\fR in the current working directory. .SH "AUTHORS" .IX Header "AUTHORS" The code and documentation were contributed by Stanford Linear Accelerator Center, a department of Stanford University. This documentation was written by .IP "Elizabeth Cassell and" 4 .IX Item "Elizabeth Cassell and" .PD 0 .IP "Alf Wachsmann " 4 .IX Item "Alf Wachsmann " .PD .SH "COPYRIGHT AND DISCLAIMER" .IX Header "COPYRIGHT AND DISCLAIMER" .Vb 3 \& Copyright 2004 Alf Wachsmann and \& Elizabeth Cassell \& All rights reserved. .Ve cfengine-2.2.10/doc/version2.texi0000644000175000001440000000014711170173455013504 00000000000000@set UPDATED 24 December 2008 @set UPDATED-MONTH December 2008 @set EDITION 2.2.10 @set VERSION 2.2.10 cfengine-2.2.10/doc/cfetoolupdate.80000644000175000001440000002402210261007231013753 00000000000000.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "CFETOOLUPDATE 1" .TH CFETOOLUPDATE 1 "2004-09-21" "perl v5.8.4" "User Contributed Perl Documentation" .SH "NAME" cfetool update \- Update the database with a new value .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBcfetool\fR \fBupdate\fR \fIname\fR \&\fB\-\-value\fR|\fB\-V\fR\ \fIvalue\fR [\fB\-\-path\fR|\fB\-p\fR\ \fIdirectory\ name\fR] [\fB\-\-time\fR|\fB\-t\fR\ \fIseconds\fR] [\fB\-\-daily\fR|\fB\-d\fR] [\fB\-\-weekly\fR|\fB\-w\fR] [\fB\-\-yearly\fR|\fB\-y\fR] [\fB\-\-cfenvd\fR|\fB\-c\fR] [\fB\-\-histograms\fR|\fB\-H\fR] [\fB\-\-verbose\fR|\fB\-v\fR] [\fB\-\-help\fR|\fB\-h\fR] .SH "DESCRIPTION" .IX Header "DESCRIPTION" Takes a new value and uses it to update the database specified by \fIname\fR, located at the path specified by the \fB\-p\fR argument, or the current working directory if the \fB\-p\fR argument is ommitted. The value will be associated with the current time, unless the \fB\-t\fR option is given. In order for cfetool to function properly, this command should be issued at least once during each interval specified by the \fB\-\-step\fR option of \f(CW\*(C`cfetool create\*(C'\fR. .PP The \fB\-d\fR, \fB\-w\fR and \fB\-y\fR options specify the databases to update. If all three options are omitted, only the weekly database will be updated. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-\-value\fR|\fB\-v\fR \fIvalue\fR" 4 .IX Item "--value|-v value" Specifies a new value to update the database with. .IP "\fB\-\-path\fR|\fB\-p\fR \fIdirectory name\fR" 4 .IX Item "--path|-p directory name" The directory in which the database specified by \fIname\fR can be found. .IP "\fB\-\-time\fR|\fB\-t\fR" 4 .IX Item "--time|-t" The time the value was collected, in seconds since epoch (January 1st, 1970). If this argument is omitted, the current time will be used. .IP "\fB\-\-daily\fR|\fB\-d\fR" 4 .IX Item "--daily|-d" Update the daily averages database. .IP "\fB\-\-weekly\fR|\fB\-w\fR" 4 .IX Item "--weekly|-w" Update the weekly averages database. .IP "\fB\-\-yearly\fR|\fB\-y\fR" 4 .IX Item "--yearly|-y" Update the yearly averages database. .IP "\fB\-\-cfenvd\fR|\fB\-c\fR" 4 .IX Item "--cfenvd|-c" Communicate with cfengine. If this option is specified, cfetool will define classes understandable by cfagent. For more information, refer to the documentation for \fBcfenvd\fR. .IP "\fB\-\-histograms\fR|\fB\-H\fR" 4 .IX Item "--histograms|-H" Collect histogram information about the probability distribiution of fluctuations about the mean value over all times of day. Cfetool won't write anything to this file for the first four weeks, as it has to have reliable mean values in order to accurately calculate it. .IP "\fB\-\-verbose\fR|\fB\-v\fR" 4 .IX Item "--verbose|-v" Print details of the command's execution to the standard output stream. .IP "\fB\-\-help\fR|\fB\-h\fR" 4 .IX Item "--help|-h" Print a short help message and then exit. .SH "OUTPUT" .IX Header "OUTPUT" Before exiting, \f(CW\*(C`cfetool update\*(C'\fR will print one line to the standard output stream in the following format: .PP yrly=\fIynum\fR,wkly=\fIwnum\fR,dly=\fIdnum\fR .PP \&\fIynum\fR, \fIwnum\fR and \fIdnum\fR will be either the number 0 if the corresponding database was not updated, or a code indicating the state of the given statistic, as compared to an average of equivalent earlier times, as specified below: .PP .Vb 27 \& code high|low|normal meaning \& ------------------------------------------------------------- \& -2 - no sigma variation \& ------------------------------------------------------------- \& -4 low within noise threshold, and within \& -5 normal 2 standard deviations from \& -6 high expected value \& ------------------------------------------------------------- \& -14 low microanomaly: within noise \& -15 normal threshold, but 2 or more standard \& -16 high deviations from expected value \& ------------------------------------------------------------- \& -24 low normal; within 1 standard deviation \& -25 normal from the expected value \& -26 high \& ------------------------------------------------------------- \& -34 low dev1; more than 1 standard \& -35 normal deviation from the expected \& -36 high value \& ------------------------------------------------------------ \& -44 low dev2; more than 2 standard \& -45 normal deviations from the expected \& -46 high value \& ------------------------------------------------------------- \& -54 low anomaly; more than 3 standard \& -55 normal deviations from the expected \& -56 high value .Ve .PP Where \*(L"low\*(R" indicates that the current value is below both the expected value for the current time position, and the global average value. \*(L"high\*(R" indicates that the current value is above those values. \*(L"normal\*(R" indicates that the current value is within the range of expected values. .PP \&\f(CW\*(C`cfetool update\*(C'\fR also exits with a code corresponding to the above table. If more than one database is being updated, the most negative result from the updates is returned, and the individual results must be obtained from the standard output stream, as described above. .SH "EXAMPLE" .IX Header "EXAMPLE" .Vb 2 \& % cfetool update temperature --path /my/path --value 14.5 --histograms \& yrly=0,wkly=-6,dly=0 .Ve .PP Updates the weekly temperature database and histogram files located in \&\fB/my/path/\fR with the value 14.5 using the current time as the update time. The output indicates that only a weekly database was updated, and the new value given was within cfetool's noise threshold, and also within 2 standard deviations of the previous average stored in the database. .SH "AUTHORS" .IX Header "AUTHORS" The code and documentation were contributed by Stanford Linear Accelerator Center, a department of Stanford University. This documentation was written by .IP "Elizabeth Cassell and" 4 .IX Item "Elizabeth Cassell and" .PD 0 .IP "Alf Wachsmann " 4 .IX Item "Alf Wachsmann " .PD .SH "COPYRIGHT AND DISCLAIMER" .IX Header "COPYRIGHT AND DISCLAIMER" .Vb 3 \& Copyright 2004 Alf Wachsmann and \& Elizabeth Cassell \& All rights reserved. .Ve cfengine-2.2.10/doc/cfengine.80000644000175000001440000001137610202127305012703 00000000000000.TH cfengine 8 "Maintenance Commands" HiOslo .SH NAME cfengine \- network configuration engine .SH SYNOPSIS /usr/local/sbin/cfagent [options] .PP /usr/local/sbin/cfrun [options] .PP /usr/local/sbin/cfservd .PP /usr/local/sbin/cfexecd .PP /usr/local/sbin/cfenvd .PP /usr/local/sbin/cfkey .PP /usr/local/sbin/cfenvgraph .SH DESCRIPTION .B cfengine is a language based system specifically designed for testing and configuring unix\-like systems attached to a TCP/IP network. You can think of .B cfengine as a very high level language \-\- much higher level than Perl or shell. A single statement can result in many hundreds of links being created, or the permissions of many hundreds of files being set. The idea of .B cfenginge is to create a single file or set of configuration files which will describe the setup of every host on your network. .PP .B cfagent runs on every host and parses one file (or file\-set), the configuration of the host is checked against this file and, if desired, any deviations are fixed. .B cfagent reads a configuration file called cfengine.conf in a directory pointed to by the environment variable CFINPUTS. .B cfagent performs host integrity and security checks as well as installing and repairing system configuration. .SH COMMAND LINE OPTIONS .IP "-a (--sysadm)" 25 Print only the name of the system administrator then quit. .IP "-b (--force-net-copy)" Forces net copy even if remote server is localhost .IP "-c (--no-check-files)" Do not check access rights on file systems .IP "-C (--no-check-mounts)" Check mount points for consistency. If this option is set then directories which lie in the \*(rqmount point\*(lq area are checked to see whether there is anything mounted on them. .IP "-d (--debug)" Enable debugging output. (parsing \-d1,run, \-d2, lite \-d3) .IP "-D (--define)" Define a compound class symbol of the form alpha.beta.gamma. .IP "-e (--no-edits)" Suppress file editing. .IP "-E (--enforce-links)" Globally force links to be created where plain files or links already exist. You have to use this in interactive mode and answer a yes/no query before .B cfagent will run like this. .IP "-f (--file)" Parse filename after this switch. By default .B cfagent looks for a file called cfengine.conf in the current directory. .IP "-h (--help )" Help information. Display version banner and options summary. .IP "-H (--no-hard-classes)" Prevents .B cfagent from generating any internal class name information. Can be used for emulation purposes. .IP "-i (--no-ifconfig)" Do not attempt to configure the local area network interface. .IP "-I (--inform)" Switches on the inform output level, whereby .B cfagent reports everything it changes.. .IP "-k (--no-copy)" Do not copy/image any files. .IP "-K (--no-lock)" Ignore locks when running. .IP "-l (--traverse-links)" Normally .B cfagent does not follow symbolic links when recursively parsing directories. This option will force it to do so. .IP "-L (--delete-stale-links)" Delete links which do not point to existing files (except in user home directories, which are not touched). .IP "-m (--no-mount)" Do not attempt to mount file systems or edit the filesystem table. .IP "-M (--no-modules)" Ignore modules in actionsequence. .IP "-n (--recon,--dry-run,--just-print)" No action. Only print what has to be done without actually doing it. .IP "-N (--negate,--undefine)" Cancel a set of classes, or undefine (set value to false) a compound class of the form alpha.beta.gamma. .IP "-p (--parse-only)" Parse file and then stop. Used for checking the syntax of a program. .IP "-q (--no-splay)" Switch off host splaying (sleeping). .IP "-s (--no-commands)" Do not execute scripts or shell commands. .IP "-S (--silent)" Silence run time warnings. .IP "-t (--no-tidy)" Do not tidy file systems. .IP "-u (--use-env)" Causes .B cfagent to generate an environment variable CFALLCLASSES which can be read by child processes (scripts). This variable contains a summary of all the currently defined classes at any given time. This option causes some system 5 systems to generate a Bus Error or segmentation fault. .IP "-U (--underscore-classes)" When this option is set, .B cfagent adds an underscore to the beginning of all hard system classes (like _sun4, _linux etc.) This can be used to avoid naming conflicts if you are so injudicious as to name a host by the name of a hard class. Other classes are not affected. .IP "-v (--verbose)" Verbose mode. Prints detailed information about actions and state. .IP "-V (--version)" Print only the version string and then quit. .IP "-x (--no-preconf)" Do not execute the cf.preconf net configuration file. .IP "-X (--no-links)" Do not execute the links section of a program. .IP "-w (--no-warn,--quiet)" Do not print warning messages. .SH AUTHOR Mark Burgess, Oslo University College .SH INFORMATION http://www.cfengine.org cfengine-2.2.10/doc/cfagent.80000644000175000001440000001126311122727652012544 00000000000000.TH cfengine 8 "Maintenance Commands" .SH NAME cfagent \- system configuration agent .SH SYNOPSIS /usr/local/sbin/cfagent [options] .SH DESCRIPTION .B cfengine is a language based system specifically designed for testing and configuring unix\-like systems attached to a TCP/IP network. You can think of .B cfengine as a very high level language \-\- much higher level than Perl or shell. A single statement can result in many hundreds of links being created, or the permissions of many hundreds of files being set. The idea of .B cfengine is to create a single file or set of configuration files which will describe the setup of every host on your network. .PP .B cfagent runs on every host and parses one file (or file\-set), the configuration of the host is checked against this file and, if desired, any deviations are fixed. .B cfagent reads a configuration file called cfengine.conf in a directory pointed to by the environment variable CFINPUTS. .B cfagent performs host integrity and security checks as well as installing and repairing system configuration. .SH COMMAND LINE OPTIONS .IP "-a (--sysadm)" 25 Print only the name of the system administrator then quit. .IP "-b (--force-net-copy)" Forces net copy even if remote server is localhost .IP "-c (--no-check-files)" Do not check access rights on file systems .IP "-C (--no-check-mounts)" Check mount points for consistency. If this option is set then directories which lie in the \*(rqmount point\*(lq area are checked to see whether there is anything mounted on them. .IP "-d (--debug)" Enable debugging output. (parsing \-d1,run, \-d2, lite \-d3) .IP "-D (--define)" Define a compound class symbol of the form alpha.beta.gamma. .IP "-e (--no-edits)" Suppress file editing. .IP "-E (--enforce-links)" Globally force links to be created where plain files or links already exist. You have to use this in interactive mode and answer a yes/no query before .B cfagent will run like this. .IP "-f (--file)" Parse filename after this switch. By default .B cfagent looks for a file called cfengine.conf in the current directory. .IP "-h (--help )" Help information. Display version banner and options summary. .IP "-H (--no-hard-classes)" Prevents .B cfagent from generating any internal class name information. Can be used for emulation purposes. .IP "-i (--no-ifconfig)" Do not attempt to configure the local area network interface. .IP "-I (--inform)" Switches on the inform output level, whereby .B cfagent reports everything it changes.. .IP "-k (--no-copy)" Do not copy/image any files. .IP "-K (--no-lock)" Ignore locks when running. .IP "-l (--traverse-links)" Normally .B cfagent does not follow symbolic links when recursively parsing directories. This option will force it to do so. .IP "-L (--delete-stale-links)" Delete links which do not point to existing files (except in user home directories, which are not touched). .IP "-m (--no-mount)" Do not attempt to mount file systems or edit the filesystem table. .IP "-M (--no-modules)" Ignore modules in actionsequence. .IP "-n (--recon,--dry-run,--just-print)" No action. Only print what has to be done without actually doing it. .IP "-N (--negate,--undefine)" Cancel a set of classes, or undefine (set value to false) a compound class of the form alpha.beta.gamma. .IP "-p (--parse-only)" Parse file and then stop. Used for checking the syntax of a program. .IP "-P (--no-processes)" Do not test the existence of processes, signal processes or optionally restart them. .IP "-q (--no-splay)" Switch off host splaying (sleeping). .IP "-s (--no-commands)" Do not execute scripts or shell commands. .IP "-S (--silent)" Silence run time warnings. .IP "-t (--no-tidy)" Do not tidy file systems. .IP "-u (--use-env)" Causes .B cfagent to generate an environment variable CFALLCLASSES which can be read by child processes (scripts). This variable contains a summary of all the currently defined classes at any given time. This option causes some system 5 systems to generate a Bus Error or segmentation fault. .IP "-U (--underscore-classes)" When this option is set, .B cfagent adds an underscore to the beginning of all hard system classes (like _sun4, _linux etc.) This can be used to avoid naming conflicts if you are so injudicious as to name a host by the name of a hard class. Other classes are not affected. .IP "-v (--verbose)" Verbose mode. Prints detailed information about actions and state. .IP "-V (--version)" Print only the version string and then quit. .IP "-x (--no-preconf)" Do not execute the cf.preconf net configuration file. .IP "-X (--no-links)" Do not execute the links section of a program. .IP "-w (--no-warn,--quiet)" Do not print warning messages. .SH AUTHOR Mark Burgess, Oslo University College .SH INFORMATION http://www.cfengine.org cfengine-2.2.10/doc/cfservd.80000644000175000001440000000153710736710270012572 00000000000000.TH cfengine 8 "Maintenance Commands" .SH NAME cfservd \- cfengine server daemon .SH SYNOPSIS /usr/local/sbin/cfservd [options] .SH DESCRIPTION .B cfengine is a language based system specifically designed for testing and configuring unix\-like systems attached to a TCP/IP network. Cfservd is a file server and protective wrapper for starting cfengine remotely. It performs access control based on RSA authentication and IP address. .PP The daemon looks for a configuration file cfservd.conf by default. Cfservd gives little information when it fails to serve. This is by design. More information can be obtained using the debug option -d2 on both client and server ends. .IP "-d (--debug)" Enable debugging output. (parsing \-d1,run, \-d2, lite \-d3) .IP "-h (--help)" .SH AUTHOR Mark Burgess, Oslo University College .SH INFORMATION http://www.cfengine.org cfengine-2.2.10/doc/cfenvgraph.80000644000175000001440000000264110712730003013244 00000000000000.TH cfengine 8 "Maintenance Commands" .SH NAME cfengine \- network configuration engine .SH SYNOPSIS /usr/local/sbin/cfenvgraph [options] .SH COMMAND LINE OPTIONS .IP --help .IP --file .B Override default input database .IP --erasehistory .B Erase machine-learned history of named traces. Comma separated list (no spaces) .IP --outputdir .B override name of output directory .IP --titles .B Generate titles in output data files for traces .IP --timestamps .B Add time stamps to output directory .IP --resolution .B Maximum output resolution (default is smoothed over each hour). .IP --separate .B Plot separate output files for each trace. .IP --no-error-bars .B Do not add uncertainty margins to output. .IP --no-scaling .B Do not renormalize graphs for convenient representation .IP --now .B Show data for last four hours only in high resolution. .IP --verbose .SH DESCRIPTION .B cfengine is a language based system specifically designed for testing and configuring unix\-like systems attached to a TCP/IP network. Cfenvd is part of the anomaly detection subsystem for cfagent. .B cfenvgraph is a research tool for extracting graphs of the learned history of system performance from the learned database. Users are referred to the web page .PP http://www.cfengine.org/confdir/cfenvgraph.html .PP for an explanation of this graphical tool. .SH AUTHOR Mark Burgess, Oslo University College .SH INFORMATION http://www.cfengine.org cfengine-2.2.10/doc/cfengine-Reference.html0000644000175000001440000257403511170173455015420 00000000000000 Cfengine v2 reference

Cfengine v2 reference


Next: , Previous: (dir), Up: (dir)

Cfengine-Reference

COMPLETE TABLE OF CONTENTS

This manual is for version 2.2.10 of cfengine and was last updated on the 21 January 2009.

Summary of contents


Next: , Previous: Top, Up: Top

1 Introduction to reference manual

The purpose of the cfengine reference manual is to collect together and document the raw facts about the different components of cfengine. Once you have become proficient in the use of cfengine, you will no longer have need of the tutorial. The reference manual, on the other hand, changes with each version of cfengine. You will be able to use it online, or in printed form to find out the details you require to implement configurations in practice.

1.1 Installation

In order to install cfengine, you should first ensure that the following packages are installed.

OpenSSL
Open source Secure Sockets Layer for encryption.
URL: http://www.openssl.org
BerkeleyDB (version 3.2 or later)
Light-weight flat-file database system.
URL: http://www.oracle.com/technology/products/berkeley-db/index.html

The preferred method of installation is then

     tar zxf cfengine-x.x.x.tar.gz
     cd cfengine-x.x.x
     ./configure
     make
     make install

This results in binaries being installed in /usr/local/sbin. Since this is not necessarily a local file system on all hosts, users are encouraged to keep local copies of the binaries on each host, inside the cfengine trusted work directory.

1.2 Work directory

In order to achieve the desired simplifications, it was decided to reserve a private work area for the cfengine tool-set. In cfengine 1.x, the administrator could choose the locations of configuration files, locks, and logging data independently. In cfengine 2.x, this diversity has been simplified to a single directory which defaults to /var/cfengine (similar to /var/cron):

     /var/cfengine
     /var/cfengine/bin
     /var/cfengine/inputs
     /var/cfengine/outputs

The installation location /usr/local/sbin is not necessarily a local file system, and cannot therefore be trusted to a) be present, and b) be authentic on an arbitrary system.

Similarly, a trusted cache of the input files must now be maintained in the inputs subdirectory. When cfengine is invoked by the scheduler, it reads only from this directory. It is up to the user to keep this cache updated, on each host. This simplifies and consolidates the cfengine resources in a single place. The environment variable CFINPUTS still overrides this default location, as before, but in its absence or when called from the scheduler, this becomes the location of trusted files. A special configuration file update.conf is parsed and run before the main configuration is parsed, which is used to ensure that the currently caches policy is up-to-date. This has private classes and variables. If no value is set for CFINPUTS, then the default location is the trusted cfengine directory /var/cfengine/inputs.

The outputs directory is now a record of spooled run-reports. These are mailed to the administrator, as previously, or can be copied to another central location and viewed in an alternative browser..

1.3 Cfengine hard classes

A single class can be one of several things:

  • The name of an operating system architecture e.g. ultrix, sun4, etc. This is referred to as a hard class.
  • The unqualified name of a particular host. If your system returns a fully qualified domain name for your host, cfagent truncates it at the first dot.
  • The name of a user-defined group of hosts.
  • A day of the week (in the form Monday, Tuesday, Wednesday, ..).
  • An hour of the day (in the form Hr00, Hr01 ... Hr23).
  • Minutes in the hour (in the form Min00, Min17 ... Min45).
  • A five minute interval in the hour (in the form Min00_05, Min05_10 ... Min55_00)
  • A day of the month (in the form Day1, Day2, ... Day31).
  • A month (in the form January, February, ... December).
  • A year (in the form Yr1997, Yr2004).
  • An arbitrary user-defined string.
  • The IP address octets of any active interface (in the form ipv4_192_0_0_1, ipv4_192_0_0, ipv4_192_0, ipv4_192).
  • The name of all interfaces Cfengine can find, in the form net_iface_eth0.

To see all of the classes define on a particular host, run

     host# cfagent -p -v

as a privileged user. Note that some of the classes are set only if a trusted link can be established with cfenvd, i.e. if both are running with privilege, and the /var/cfengine/state/env_data file is secure. More information about classes can be found in connection with allclasses.

1.4 Filenames and paths

Filenames in Unix-like operating systems use for their directory separator the forward slash '/' character. All references to file locations must be absolute pathnames in cfengine, i.e. they must begin with a complete specification of which directory they are in. For example:

     /etc/passwd
     /usr/local/masterfiles/distfile

The only place where it makes sense to refer to a file without a complete directory specification is when searching through directories for different kinds of file, e.g.

     tidy:
     
       /home/user pattern=core age=0 recurse=inf
     

Here, one can write core without a path, because one is looking for any file of that name in a number of directories.

The Windows operating systems traditionally use a different filename convention. The following are all valid absolute file names under Windows:

      c:\winnt
      c:/winnt
      /var/cfengine/inputs
      //fileserver/share2/dir

The `drive' name “C:” in Windows refers to a partition or device. Unlike Unix, Windows does not integrate these seamlessly into a single file-tree. This is not a valid absolute filename:

     \var\cfengine\inputs

Paths beginning with a backslash are assumed to be win32 paths. They must begin with a drive letter or double-slash server name.

1.5 Debugging with signals

It is possible to turn debugging output on or off on a running cfagent. This is useful for troubleshooting the cause of hangups, or for getting debugging output from a cfagent launched from cfexecd.

A running cfagent process that receives a SIGUSR1 will immediately begin to behave as if it had been invoked with the '-d2' option. A SIGUSR2 will cause a running cfagent to run as if the '-d2' option had not been invoked.

Note that this output is often quite verbose.


Next: , Previous: Reference introduction, Up: Top

2 Cfkey reference

The very first thing you should do on every host is to establish a public-private key pair. To do this, you need to run the program

     everyhost# cfkey

on every host. This program needs to produce random numbers, and needs a source of randomness. A good strategy is to install and run the cfenvd program for a week or two in advance of deploying cfengine 2, since cfenvd collects random events, which are an excellent source of entropy for random number generation. If you get the error message “PRNG not seeded”, it means that insufficient data were found in order to make a random key. In that case, run cfenvd for a few days more and try again.


Next: , Previous: Cfkey, Up: Top

3 Cfshow reference

The cfshow command was introduced in cfengine 2.1.11 in order to provide a simple way to show some of the data stored by cfagent for operational purposes.

     everyhost# cfshow -a
     everyhost# cfshow -l
     everyhost# cfshow -c
     everyhost# cfshow -s
     everyhost# cfshow -p
     everyhost# cfshow -f cfagent.conf -r linux.*

The command line options are

-a --active
This prints a list of any currently active locks, i.e. tasks that cfengine believes it is currently enagaged in.
-A --audit
This prints a history of cfengine's behaviour collected if the Auditing variable is true, See Auditing. The audit data are best viewed in html or parsed with xml, using the --html and --xml options.
-c --checksum
This lists all of the files and their current checksum values in the current checksum database.
-C --classes
This lists all of the classes that have been used on the system over the past year, with frequency probabilities to show their relative occurrance rates and last observed times.
-H --html
Generate output in web browser-friendly html.
-l --locks
This prints a list of the locks and the last times an active lock was secured for each cfengine acivity. This list is potentially very long.
-s --last-seen
This lists the IP addresses of all known peers and the times they were last engaged in communication with the current host. The expected interval between communications is also printed. See FriendStatus. The output format is in a form that can easily be parsed by user scripts. e.g.
          IP + 192.168.1.101 192.168.1.101   [Tue Jan 23 16:13] not seen for (6.42) hrs, Av 0.02 +/- 0.01 hrs
          IP - 192.168.1.101 192.168.1.101   [Tue Jan 23 16:13] not seen for (6.42) hrs, Av 0.02 +/- 0.01 hrs

Lines marked with a + represent successful attempts made by cfagent on the current host to connect to another host. Lines with a - are connections attempted (but not necessarily succeeded) into cfservd from another host's cfagent or cfrun.

-r --regex regex
Search the cfengine policy file (e.g. cfagent.conf) for rules that belong to classes matching the named regular expression. Note that the class "any" is not automatically matched and the search is based on the class text from the file. The output is not related to which classes are currently defined.
-s --performance
Shows the time in seconds required to complete copies and shell executions.
          (0.00 mins  Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfagent > /var/cfengine/bin/cfagent)
          (0.00 mins  Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfenvd > /var/cfengine/bin/cfenvd)
          (0.02 mins  Tue Feb 13 19:05) Av 0.02 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfexecd > /var/cfengine/bin/cfexecd)
          (0.00 mins  Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfservd > /var/cfengine/bin/cfservd)
          (6.41 mins  Tue Feb 13 18:50) Av 0.00 +/- 0.00 for Exec(/usr/bin/updatedb --prunepaths=/media)
          (0.00 mins  Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Exec(/usr/sbin/ntpdate 128.39.74.16 > /dev/null)

-X --xml
Generate output in xml for parsing by scripts etc.


Next: , Previous: Cfshow, Up: Top

4 Cfagent reference

4.1 Cfagent intro

Cfagent is the workhorse of cfengine. It interprets and computes the necessary strategies for implementing convergent maintenance. In order to carry out work efficiently, the agent groups similar actions together. The order of these actions is goverened by a list called the actionsequence.

In many cases, cfagent will be able to complete all its work in a single pass of the actionsequence. However, in complex configurations, it is hard to resolve all of the ordering dependencies automatically in a single pass. Cfagent keeps track both of all actions that have been performed and of those that might still need to be performed (given that some actions depend on the later outcomes of others). If there is a possibility that an action ordering dilemma might occur, it runs a second pass of the actionsequence to more quickly resolve the dependency (avoiding the wait for next scheduled run). No actions are performed twice however, since the agent checks off actions that have already been performed to avoid unnecessary duplication.

4.2 The file cfagent.conf

     
      control:
     
        classes::
     
            domain = ( DNS-domain-name )
     
      classes:
     
        Class/Group definitions
     
      import:
     
        Files to import
     
      # other items
     

4.3 Cfagent runtime options

Note that GNU long options are available with the syntax --longoption. The long names are given in brackets.

-a
(--sysadm) Print only the name of the system administrator then quit.
-A
(--auto) Can be used to signify an automatic run of cfengine, as opposed to a manual run. The distinction is not predetermined. Use of this option currently causes cfengine to ignore locks. This option is reserved for future development.
-b
(--force-net-copy) Normally cfengine detects attempts to copy from a server via the network that will loop back to the localhost. It then avoids using the network to make the copy. This option forces cfengine to copy using the network. Yes, someone thinks this is useful!
-c
(--no-check-files) Do not check file systems for ownership / permissions etc.
-C
(--no-check-mounts) Check mount points for consistency. If this option is specified then directories which lie in the “mount point” area are checked to see whether there is anything mounted on them. Normally this is off since not all machines use mounted file systems in the same way. e.g. HPUX does not generally operate with partitions, but nevertheless one might wish to mimick a partition-like environment there, but it would be irritating to be informed that nothing was mounted on the mount point.
-d
(--debug) Enable debugging output. Normally you will want to send this to a file using the shell script command or a pipe. -d1 shows only parsing output. -d2 shows only runtime action output. -d0 shows both levels. Debugging ouput is intended mainly for the author's convenience and is not a supported feature. The details of this output may change at any time.
-D
(--define) Define a compound class symbol of the form alpha.beta.gamma.
-e
(--no-edits) Suppress file editing.
-E
(--enforce-links) Globally force links to be created where plain files or links already exist. Since this option is a big hammer, you have to use it in interactive mode and answer a yes/no query before cfengine will run like this.
-f
(--file) Parse filename after this switch. By default cfengine looks for a file called cfengine.conf in the current directory.
-h
(--help) Help information. Display version banner and options summary.
-H
(--no-hard-classes). Prevents cfengine from generating any built-in class name information. Can be used for emulation purposes.
-i
(--no-ifconfig) Do not attempt to configure the local area network interface.
-I
(--inform) Switches on the inform output level, whereby cfengine reports everything it changes..
-k
(--no-copy) Do not copy/image any files.
-K
(--no-lock) Ignore locks when running.
-l
(--traverse-links) Normally cfengine does not follow symbolic links when recursively parsing directories. This option will force it to do so.
-L
(--delete-stale-links) Delete links which do not point to existing files (except in user home directories, which are not touched).
-m
(--no-mount) Do not attempt to mount file systems or edit the filesystem table.
-M
(--no-modules) Ignore modules in actionsequence.
-n
(--recon,--dry-run,--just-print) No action. Only print what has to be done without actually doing it.
-N
(--negate,--undefine) Cancel a set of classes, or undefine (set value to false) a compound class of the form alpha.beta.gamma.
-p
(--parse-only) Parse file and then stop. Used for checking the syntax of a program. You do not have to be superuser to use this option.
-P
(--no-processes) Do not execute the processes action.
-q
(--no-splay) Switch off host splaying (sleeping).
-Q
(--quert) Query the values of the comma separated list of variable names.
-s
(--no-commands) Do not execute scripts or shell commands.
-S
(--silent) Silence run time warnings.
-t
(--no-tidy) Do not tidy file systems.
-u
(--use-env) Causes cfengine to generate an environment variable ‘CFALLCLASSES’ which can be read by child processes (scripts). This variable contains a summary of all the currently defined classes at any given time. This option causes some System V systems to generate a Bus Error or segmentation fault. The same information is available from the cfengine built-in variable $(allclasses) and can be passed as a parameter to scripts. When this variable grows too large for embedding one can also access a complete list of current classes in /var/cfengine/state/allclasses.
-U
(--underscore-classes). When this option is set, cfengine adds an underscore to the beginning of the hard system classes (like _sun4, _linux etc. The longer compound classes are not underscored, since these are already complex and would unlikely result in collisions.) This can be used to avoid naming conflicts if you are so unjudicious as to name a host by the name of a hard class. Other classes are not affected.
-v
(--verbose) Verbose mode. Prints detailed information about actions and state.
-V
(--version) Print only the version string and then quit.
-x
(--no-preconf) Do not execute the cf.preconf net configuration file.
-X
(--no-links) Do not execute the links section of a program.
-w
(--no-warn,--quiet) Do not print warning messages.
-z
(--schedule) Print the exec schedule for the LAN (used by cfexecd).

In version 2.0.4, an abbreviation for actionsequence exclusions was added:

     $ cfagent --avoid resolve,copy
     $ cfagent --just tidy --just shellcommands

4.4 Variable expansion and contexts

Variables in cfengine 2 are defined in contexts. Variables in a given context refer to the different phases of execution of cfengine: global, update and main. In the "current" context, variables have the form

     $(variable) ${variable}

and are expanded either on parsing or at execution. Variables that cannot be expanded remain as dollar strings. Variables belonging to a context that is not the current one may be referred to as

     $(context.variable)  or  ${context.variable}

Note carefully that cfengine requires parentheses or braces around variable names. Unlike in the shell, they cannot be omitted. There is no difference between these forms as far as cfengine is concerned. Some authors like to use the () form for cfengine variables, to distinguish them with shell variables in command strings. The () form does not work in function arguments, except inside quoted strings.

Consider the example:

     $(global.env_time)

Some variables in cfengine are associative arrays (as made famous by Perl). Such arrays are referred to by square brackets:

     
     $(array[key])  $(array[$(key)])
     

4.4.1 Setting variables with functions

A number of special functions can be used to set variables in cfengine. You can import values from the execution of a shell command by prefixing a command with the word exec. This method is deprecated as of cfengine version 2; use the ExecResult function instead.

     
       control:
     
        # old method
     
        listing = ( "exec /bin/ls -l" )
     
        # new method
     
        listing = ( ExecResult(/bin/ls -l) )
     

This sets the variable `listing' to the output of the command in the quotes. Some other built-in functions are

A(X,Y)
Makes an associative array entry, associating X and Y. For instance:
          control:
          
           assoc_array = ( A(B,"is for bird") A(C,"is for cat") )
          

results in:

          
          OBJECT: main
             4569 : assoc_array[B]=is for bird
             4630 : assoc_array[C]=is for cat
          

Another example:

          control:
          
           binhost = ( A(linux,machine1) A(solaris,machine2) )
          
          copy:
          
           # Contact machine 1 for linux
           # Contact machine 2 for solaris
          
           /etc/source dest=/etc/receve server=$(binhost[$(class)])
          

ExecResult(command)
Executes the named command without a shell-wrapper and inserts the output into the variable. Note that, when this is used in cfengine built-in list variables, any spaces are interpreted as list separators. In other lists, normal rules for iteration apply.
ExecShellResult(command)
Executes the named command with a shell-wrapper and inserts the output into the variable. Note that, when this is used in cfengine built-in list variables, any spaces are interpreted as list separators. In other lists, normal rules for iteration apply.
RandomInt(a,b)
Generate a random integer between a and b.
ReadArray(filename,fileformat,separator,comment,Max number of bytes)
Reads up to a maximum number of bytes from a properly formatted file into a one-dimensional associated array. File formats are:
autokey
If this format is specified, ReadArray tries to interpret the file as a table of items separated with the separator character. Blank lines and comments (to end of line) are ignored. Items are keyed numerically starting from 1 to the maximum number in the file. The newline $(n) is always considered to be a separator, no matter what the current separator is.
textkey
If this format is specified, ReadArray tries to interpret the file as a list of lines of the form:
                 key,value

ReadFile(filename,Max number of bytes)
Read a maximum number of bytes from a file.
ReadTable(filename,fileformat,separator,comment,Max number of bytes)
Reads up to a maximum number of bytes from a properly formatted file into a two-dimensional associated array.
autokey
If this format is specified, ReadArray tries to interpret the file as a table of items separated with the separator character. Blank lines and comments (to end of line) are ignored. Items are keyed numerically starting from 1 to the maximum number in the file. Any lines that do not contain the correct number of separators cause the function to fail without making any assignment.
textkey
If this format is specified, ReadArray tries to interpret the file as a list of lines of the form:
                 key1,key2,value1
                 key3,key4,value2

This variable would then be references as $(table[key1][key2]).


ReadList(filename,fileformat,comment,Max number of bytes)
Reads up to a maximum number of bytes from a properly formatted file into a listvariable. File formats are:
lines
If this format is specified, ReadList tries to interpret the file as a list of items on separate lines. The value returned is a list formatted by the Split character.
          
          hosts = ( ReadList(/var/cfengine/inputs/datafile,lines,#,1000) )
          

ReadTCP(host/IP,portnumber,send string,Max number of bytes)
Reads up to a maximum number of bytes from a TCP service. Can be used to test whether certain services are responding to queries. It is recommended that this be used primarily to check services running on localhost. Bear in mind that this clause, executed on 100 hosts will produce the effect of a distributed denial of service attack, so the probe should be restricted to a single representative tester-host. For example:
          
          one_host_only::
          
           # USE WITH CAUTION !
          
           probewww = ( ReadTCP(localhost,80,'GET index.html',1000) )
          

Or testing a network service:

          control:
          
           checkhost::
          
           probesmtp = ( ReadTCP(localhost,25,"",1024) )
           probewww  = ( ReadTCP(project.iu.hio.no,80,"GET /viewcvs HTTP/1.0 ${n}${n}",1024) )
          
          classes:
          
            viewcvs_error = ( RegCmp(".*Python Traceback.*","${probewww}") )
          
          alerts:
          
            viewcvs_error::
          
               "Received viewcvs error from web server"

SelectPartitionNeighbours(filename,comment,Policy,group size)
This function is for use in peer to peer monitoring applications. It allows individual hosts to identify themselves as part of a group and find their peers. The function returns a list variable, delimited by the list separation character, for use with Split.
          
           control:
          
             allpeers = ( SelectPartitionNeighbours(/var/cfengine/inputs/cfrun.hosts,#,random,4) )
          
           copy:
          
             /data/file dest=/p2prepository/file server=$(allpeers)
          

SelectPartitionLeader(filename,comment,Policy,group size)
This function is for use in peer to peer monitoring applications. It allows individual hosts to identify themselves as part of a group and select a leader. This function reads a text file of hostnames or IP addresses, one host per line, with blank lines and comments and partitions it into groups of a fixed size. It then returns picks a leader for the the group and returns its name as the value of the function.
          
           control:
          
             leader = ( SelectPartitionLeader(/var/cfengine/inputs/cfrun.hosts,#,random,4) )
          
           copy:
          
             /data/file dest=/p2prepository/file server=$(leader)
          
Note that functions should have no spaces between the function name and the leading parenthesis, but should themselves be surrounded by white space. For example:
     
     control:
     
      variable2 = ( RandomInt(0,23) )
     
      variable3 = ( ExecResult(/bin/ls -a /opt) )
     
      myexcerpt  = ( ReadFile("/etc/services",220) )
     
      listvar = ( ReadArray(/tmp/array,textkey,",","#",100) )
     

In the latter case, the file could look like this:

     host$ more /tmp/array
     one,String to tbe read
     two,Nothing string
     three,Everything comes in threes

and results in the definition of (verify with cfagent -p -d3):

     OBJECT: main
        960 : listvar[one]=String to tbe read
        259 : listvar[two]=Nothing string
        224 : listvar[three]=Everything comes in threes

4.4.2 Special variables

Variables are referred to in either of two different ways, depending on your taste. You can use the forms $(variable) or ${variable}. The variable in braces or parentheses can be the name of any user defined macro, environment variable or one of the following special built-in variables.

AllClasses
A long string in the form ‘CFALLCLASSES=class1:class2...’. This variable is a summary of all the defined classes at any given time. It is always kept up to date so that scripts can make use of cfengine's class data.
arch
The current detailed architecture string—an amalgamation of the information from uname. A constant.
binserver
The default server for binary data. A constant.
cfinputs_version
The version string of the current configuration, used for version control and auditing.
ChecksumDatabase
If set to the name of a file, cfagent will use this to store checksums of important files, and give `tripwire functionality', See ChecksumDatabase in cfagent. This option was deprecated in 2.1.22.
ChecksumUpdates
If set to `on', security information is automatically updated.
class
The currently defined system hard-class (e.g. sun4, hpux). A constant.
date
The current date string. Note that if you use this in a shell command it might be interpreted as a list variable, since it contains the default separator ‘:’.
domain
The currently defined domain.
EmailFrom
The email address from whom email from cfexecd should appear to originate.
EmailMaxLines
Most lines of output to email from a single cfexecd-induced run of cfagent. If undefined, defaults to 100. If set to 0, no email is sent by cfexecd. If set to inf, no maximum is enforced.
EmailTo
The E-mail address to whom mail should be sent (overrides sysadm variable).
faculty
The faculty or site as defined in control (see site).
fqhost
The fully qualified hostname of the system.
host
The hostname of the machine running the program.
ipaddress
The numerical form of the Internet address of the host currently running cfengine found by a reverse lookup in DNS.
ipv4[interface]
The IPv4 address of the named interface as determined from a probe of the interfaces. This variable belongs in the global context and refers to as in the following examples:
          
          ${global.ipv4[hme0]}
          ${global.ipv4[eth0]}
          

MaxCfengines
The maximum number of cfengines which should be allowed to run concurrently on the system. This can prevent excessive load due to unintentional spamming in situations where several cfengines are started independently. The default value is unlimited.
ostype
A short for of $(arch).
OutputPrefix
This quoted string can be used to change the default `cfengine:${hostname}' prefix on output lines to something else. You might wish to shorten the string, or have a different prefix for different hosts. The default is equivalent to,
            OutputPrefix = ( "cfengine:$(host):")


RepChar
The character value of the string used by the file repository in constructing unique filenames from path names. This is the character which replaces ‘/’.
site
This variable is identical to $(faculty) and may be used interchangeably.
smtpserver
The name of the host to which mail output should be sent.
split
The character on which list variables are split.
sysadm
The name or mail address of the system administrator.
timezone
The current timezone as defined in control.
UnderscoreClasses
If this is set to `on' cfengine uses hard classes which begin with an underscore to avoid name collisions, See Cfagent Runtime Options.
version
The current cfengine version string as defined in the code.
year
The current year.

These variables are kept special because they play a special role in setting up a system configuration. You are encouraged to use them to define fully generalized rules in your programs. Variables can be used to advantage in defining filenames, directory names and in passing arguments to shell commands. The judicious use of variables can reduce many definitions to a single one if you plan carefully.

NOTE: the above control variables are not case sensitive, unlike user macros, so you should not define your own macros with these names.

The following variables are also reserved and may be used to produce troublesome special characters in strings.

cr
Expands to the carriage return character.
colon
Expands to the colon ‘:’ character.
dblquote
Expands to a double quote "
dollar
Expands to ‘$’.
lf
Expands to a line-feed character (Unix end of line).
n
Expands to a newline character.
quote
Expands to a single quote '.
spc
Expands simply to a single space. This can be used to place spaces in filenames etc.
tab
Expands to a single tab character.

4.4.3 Iteration over lists

Variables can be used as iterators in some situations. Iteration over lists is currently rather limited in cfengine and is something to be improved on in a future version. When a variable is used as an iterator, a character is chosen to represent a list separator, as in the shell ‘IFS’ variable. The default separator is the colon ‘:’ character:

     control:
     
      listvar = ( one:two:three:four )
     

The action that contains a variable to be interpreted as a list appears as separate actions, one for each case:

     shellcommand:
     
       "/bin/echo $(listvar)"

is equivalent to

     shellcommand:
     
       "/bin/echo one"
       "/bin/echo two"
       "/bin/echo three"
       "/bin/echo four"

If multiple iterators are used, these are handled as nested loops:

     cfengine::/bin/echo one 1:     one 1
     cfengine::/bin/echo one 2:     one 2
     cfengine::/bin/echo one 3:     one 3
     cfengine::/bin/echo one 4:     one 4
     cfengine::/bin/echo two 1:     two 1
     cfengine::/bin/echo two 2:     two 2
     cfengine::/bin/echo two 3:     two 3
     cfengine::/bin/echo two 4:     two 4
     cfengine::/bin/echo three:     three 1
     cfengine::/bin/echo three:     three 2
     cfengine::/bin/echo three:     three 3
     cfengine::/bin/echo three:     three 4
     cfengine::/bin/echo four :     four 1
     cfengine::/bin/echo four :     four 2
     cfengine::/bin/echo four :     four 3
     cfengine::/bin/echo four :     four 4

Where iterators are not allowed, the implied lists are treated as scalars:

     
     alerts:
     
      amnexus::
     
       "do $(list1) $(list2)"

e.g.

     
     cfengine:: do one:two:three:four 1:2:3:4

Iterative expansion is currently restricted to:

  • In the directory field of the admit/deny server access rules,
  • In the `from' field of a copy action,
  • In the server field of the copy action,
  • In the directory field of the disable action,
  • In the directory field of the files action,
  • In the `to' field of a multiple link action,
  • In the directory field of the required/disk action,
  • In a resolve item.
  • In the directory field of a tidy action,
  • In the arguments, replyto and server attributes of methods.
  • Names in the ignore action.
  • A shellcommands body.
  • In admit/deny path and attributes of cfserver.

4.5 Cfengine classes

A cfengine action looks like this:

     
     action-type:
     
        compound-class::
     
            declaration

A single class is an identifier that may consist of any alphanumeric character or the underscore, just like identifiers in ordinary programming languages. Classes that are derived from data like IP addresses or host names convert any other characters (like ‘.’ or ‘-’) into underscores. A single class can be one of several things:

  • The name of an operating system architecture e.g. ultrix, sun4, etc. This is referred to as a hard class.
  • The unqualified name of a particular host. If your system returns a fully qualified domain name for your host, cfagent truncates it at the first dot.
  • The name of a user-defined group of hosts.
  • A day of the week (in the form Monday, Tuesday, Wednesday, ..).
  • An hour of the day (in the form Hr00, Hr01 ... Hr23).
  • Minutes in the hour (in the form Min00, Min17 ... Min45).
  • A five minute interval in the hour (in the form Min00_05, Min05_10 ... Min55_00)
  • A quart hour (in the form Q1, Q2, Q3, Q4)
  • An abbreviated time with quarter hour specified (in the form Hr00_Q1, Hr23_Q4 etc.)
  • A day of the month (in the form Day1 ... Day31).
  • A month (in the form January, February, ... December).
  • A year (in the form Yr1997, Yr2004).
  • An arbitrary user-defined string.
  • The IP address octets of any active interface (in the form ipv4_192_0_0_1, ipv4_192_0_0, ipv4_192_0, ipv4_192).

A compound class is a sequence of simple classes connected by dots or `pipe' symbols (vertical bars). For example:

     
     myclass.sun4.Monday::
     
     sun4|ultrix|osf::
     

A compound class evaluates to `true' if all of the individual classes are separately true, thus in the above example the actions which follow compound_class:: are only carried out if the host concerned is in myclass, is of type sun4 and the day is Monday! In the second example, the host parsing the file must be either of type sun4 or ultrix or osf. In other words, compound classes support two operators: AND and OR, written ‘.’ and ‘|’ respectively. From cfengine version 2.1.1, I bit the bullet and added ‘&’ as a synonym for the AND operator. Cfengine doesn't care how many of these operators you use (since it skips over blank class names), so you could write either

     
     solaris|irix::
     

or

     
     solaris||irix::
     

depending on your taste. On the other hand, the order in which cfengine evaluates AND and OR operations does matter, and the rule is that AND takes priority over OR, so that ‘.’ binds classes together tightly and all AND operations are evaluated before ORing the final results together. This is the usual behaviour in programming languages. You can use round parentheses in cfengine classes to override these preferences.

Cfengine allows you to define switch on and off dummy classes so that you can use them to select certain subsets of action. In particular, note that by defining your own classes, using them to make compound rules of this type, and then switching them on and off, you can also switch on and off the corresponding actions in a controlled way. The command line options -D and -N can be used for this purpose. See also addclasses in the Reference manual. A logical NOT operator has been added to allow you to exclude certain specific hosts in a more flexible way. The logical NOT operator is (as in C and C++) ‘!’. For instance, the following example would allow all hosts except for myhost:

        action:
     
         !myhost::
     
             command

and similarly, so allow all hosts in a user-defined group mygroup, except for myhost, you would write

        action:
     
         mygroup.!myhost::
     
             command

which reads `mygroup AND NOT myhost'. The NOT operator can also be combined with OR. For instance

     
        class1|!class2

would select hosts which were either in class 1, or those which were not in class 2.

Finally, there is a number of reserved classes. The following are hard classes for various operating system architectures. They do not need to be defined because each host knows what operating system it is running. Thus the appropriate one of these will always be defined on each host. Similarly the day of the week is clearly not open to definition, unless you are running cfengine from outer space. The reserved classes are:

     ultrix, sun4, sun3, hpux, hpux10, aix, solaris, osf, irix4, irix, irix64
        sco, freebsd, netbsd, openbsd, bsd4_3, newsos, solarisx86, aos,
               nextstep, bsdos, linux, debian, cray, unix_sv, GnU, NT

If these classes are not sufficient to distinguish the hosts on your network, cfengine provides more specific classes which contain the name and release of the operating system. To find out what these look like for your systems you can run cfengine in `parse-only-verbose' mode:

     
       cfagent -p -v
     

and these will be displayed. For example, Solaris 2.4 systems generate the additional classes sunos_5_4 and sunos_sun4m, sunos_sun4m_5_4.

Cfengine uses both the unqualified and fully host names as classes. Some sites and operating systems use fully qualified names for their hosts. i.e. uname -n returns to full domain qualified hostname. This spoils the class matching algorithms for cfengine, so cfengine automatically truncates names which contain a dot `.' at the first `.' it encounters. If your hostnames contain dots (which do not refer to a domain name, then cfengine will be confused. The moral is: don't have dots in your host names! NOTE: in order to ensure that the fully qualified name of the host becomes a class you must define the domain variable. The dots in this string will be replaced by underscores. In summary, the operator ordering in cfengine classes is as follows:

()
Parentheses override everything.
!
The NOT operator binds tightest.
. &
The AND operator binds more tightly than OR.
|
OR is the weakest operator.

4.5.1 Setting classes with special functions

Cfengine provides a number of built-in functions for evaluating classes, based on file tests. Using these built-in functions is quicker than calling the shell test function. The time functions place their arguments in chronological order.

4.5.2 AccessedBefore

     AccessedBefore(f1,f2)

True if file 1 was accessed more recently than file 2 (UNIX atime)


Next: , Previous: AccessedBefore, Up: Cfengine classes

4.5.3 ChangedBefore

     ChangedBefore(f1,f2)

True if file 1's attributes were changed in any way more recently than file 2's (UNIX ctime)


Next: , Previous: ChangedBefore, Up: Cfengine classes

4.5.4 ClassMatch

     ClassMatch(regexp)

True if the quoted regular expression matches one of the currently defined classes. It is wise to place ClassMatch at the end of your parsing in order to capture as many of the user-defined classes as possible.

     classes:
     
        userdef = ( ClassMatch(.*linux.*) )


Next: , Previous: ClassMatch, Up: Cfengine classes

4.5.5 FileExists

     FileExists(file)

True if the named file object (file/directory or link) exists.


Next: , Previous: FileExists, Up: Cfengine classes

4.5.6 GroupExists

     GroupExists(groupname|gid)

True if the groupname or group id is registered on the system.


Next: , Previous: GroupExists, Up: Cfengine classes

4.5.7 HostRange

     HostRange(basename,start-stop)

True if the current relative domain name begins with basename and ends with an integer between start and stop. Note well: matching is case insensitive (both hostname and basename are converted to all lower case for comparison.)


Next: , Previous: HostRange, Up: Cfengine classes

4.5.8 IsDefined

     IsDefined(variable-id)

True if the named variable is defined. Note well: use the variable name, not its contents (that is, IsDefined(var), and not IsDefined(${var}))


Next: , Previous: IsDefined, Up: Cfengine classes

4.5.9 IsDir

     IsDir(f)

True if the file f is a directory


Next: , Previous: IsDir, Up: Cfengine classes

4.5.10 IsLink

     IsLink(f)

True if the file f is a symbolic link


Next: , Previous: IsLink, Up: Cfengine classes

4.5.11 IsPlain

     IsPlain(f)

True if the file f is a plain file


Next: , Previous: IsPlain, Up: Cfengine classes

4.5.12 IsNewerThan

     IsNewerThan(f1,f2)

True if file 2 was modified more recently than file 1 (UNIX mtime)


Next: , Previous: IsNewerThan, Up: Cfengine classes

4.5.13 IPRange

     IPRange(address-range)

True if the current host lies within the specified IP range


Next: , Previous: IPRange, Up: Cfengine classes

4.5.14 PrepModule

     PrepModule(module,arg1 arg2...)

True if the named module exists and can be executed. The module is assumed to follow the standard programming interface for modules (see Writing plugin modules in tutorial). Unlike actionsequence modules, these modules are evaluated immediately on parsing. Note that the module should be specified relative to the authorized module directory.


Next: , Previous: PrepModule, Up: Cfengine classes

4.5.15 Regcmp

     Regcmp(regexp,string or list separated string)

True if the string matched the regular expression regexp.


Next: , Previous: Regcmp, Up: Cfengine classes

4.5.16 ReturnsZero

     ReturnsZero(command)

True if the named shell command returns with exit code zero (success). The command is executed without a shell wrapper.


Next: , Previous: ReturnsZero, Up: Cfengine classes

4.5.17 ReturnsZeroShell

     ReturnsZeroShell(command)

True if the named shell command returns with exit code zero (success) when executed in the environment of a shell wrapper.


Next: , Previous: ReturnsZeroShell, Up: Cfengine classes

4.5.18 Strcmp

     Strcmp(s1,s2)

True if the string s1 exactly matches s2


Next: , Previous: Strcmp, Up: Cfengine classes

4.5.19 UserExists

     UserExists(username|uid)

True if the username or user id is registered on the system (this does not imply that the user can log in or has a home directory).


Next: , Previous: UserExists, Up: Cfengine classes

4.5.20 IsGreaterThan

     IsGreaterThan(s1,s2)

Returns true if the value of s1 is greater than the value of s2. Note that, if the strings have numerical values, a numerical comparison is performed, otherwise a string comparison is used.

4.5.21 IsLessThan

     IsLessThan(s1,s2)

Returns true if the value of s1 is less than the value of s2. Note that, if the strings have numerical values, a numerical comparison is performed, otherwise a string comparison is used.

     
     	control:
     
       	 actionsequence = ( files )
     
     	 a = ( 2.12 )
      	 b = ( 2.11 )
     
     	classes:
     
     	lt = ( IsLessThan(${a},${b}) )
        	gt = ( IsGreaterThan(${a},${b}) )
     
     	alerts:
     
     	  lt:: "$(a) LESS THAN $(b)"
     	  gt:: "$(a) GREATER THAN $(b)"


Previous: IsLessThan, Up: Cfengine classes

4.5.22 Examples setting classes

For example:

     
     classes:
     
      access_to_dir = ( ReturnsZero(/bin/cd /mydir) )
      compare       = ( ChangedBefore(/etc/passwd_master,/etc/passwd) )
      isplain       = ( IsPlain(/tmp/import) )
      inrange       = ( IPRange(128.39.89.10-15) )
      CIDR          = ( IPRange(128.39.89.10/24) )
      compute_nodes = ( HostRange(cpu-,01-32)
      gotinit       = ( PrepModule(startup2,"arg1 arg2") )
     


Next: , Previous: Cfengine classes, Up: Cfagent reference

4.6 acl

     
        acl:
     
           class::
     
              { acl-alias
     
              action
              }
     

Cfengine's ACL feature is a common interface for managing filesystem access control lists (ACLs). An access control list is an extended file permission. It allows you to open or close a file to a named list of users (without having to create a group for those users); similarly, it allows you to open or close a file for a list of groups. Several operating systems have access control lists, but each typically has a different syntax and different user interface to this facility, making it very awkward to use. This part of a cfengine configuration simplifies the management of ACLs by providing a more convenient user interface for controlling them and—as far as possible—a common syntax.

An ACL may, by its very nature, contain a lot of information. Normally you would set ACLs in a files command, See files, or a copy command, See copy. It would be too cumbersome to repeat all of the information in every command in your configuration, so cfengine simplifies this by first associating an alias together with a complex list of ACL information. This alias is then used to represent the whole bundle of ACL entries in a files or copy command. The form of an ACL is similar to the form of an editfiles command. It is a bundle of information concerning a file's permissions.

     
      { acl-alias
     
       method:overwrite/append
       fstype:posix/solaris/dfs/afs/hpux/nt
     
       acl_type:user/group:permissions
       acl_type:user/group:permissions
       ...
      }
     

The name acl-alias can be any identifier containing alphanumeric characters and underscores. This is what you will use to refer to the ACL entries in practice. The method entry tells cfengine how to interpret the entries: should a file's ACLs be overwritten or only adjusted? Since the filesystems from different developers all use different models for ACLs, you must also tell cfengine what kind of filesystem the file resides on. Currently only Solaris and DCE/DFS ACLs are implemented.

NOTE: if you set both file permissions and ACLs the file permissions override the ACLs.


Next: , Previous: acl, Up: acl

4.6.1 Access control entries

An access control list is build of any number of individual access control entries (ACEs). The ACEs has the following general syntax:

         acl_type:user/group:permissions

The user or group is sometimes referred to as a key. For an explanation of ACL types and their use, refer to your local manual page. However, note that for each type of filesystem, there are certain entries which must exist in an ACL. If you are creating a new ACL from scratch, you must specify these. For example, in Solaris ACLs you must have entries for user, group and other. Under DFS you need what DFS calls a user_obj, group_obj and an other_obj, and in some cases mask_obj. In cfengine syntax these are called user:*:, other:*: and mask:*:, as described below. If you are appending to an existing entry, you do not have to re-specify these unless you want to change them.

Cfengine can overwrite (replace) or append to one or more ACL entries.

overwrite
method:overwrite is the default. This sets the ACL according to the specified entries which follow. The existing ACL will be overwritten completely.
append
method:append adds or modifies one or more specified ACL entries. If an entry already exists for the specified type and user/group, the specified permission bits will be added to the old permissions. If there is no ACL entry for the given type and user/group, a new entry will be appended.
If the new ACL exactly matches the existing ACL, the ACL is not replaced.

The individual bits in an ACE may be either added subtracted or set equal to a specified mask. The ‘+’ symbol means add, the ‘-’ symbol subtract and ‘=’ means set equal to. Here are some examples:

     
       acltype:id/*:mask
     
       user:mark:+rx,-w
       user:ds:=r
       user:jacobs:noaccess
       user:forgiven:default
     
       user:*:rw
       group:*:r
       other:*:r
     

The keyword noaccess means set all access bits to zero for that user, i.e. remove all permissions. The keyword default means remove the named user from the access crontrol list altogether, so that the default permissions apply. A star/asterisk in the centre field indicates that the user or group ID is implicitly specified as of the owner of the file, or that no ID is applicable at all (as is the case for `other').


Next: , Previous: ACEs, Up: acl

4.6.2 Solaris ACLs

Under Solaris, the ACL type can be one of the following:

             user
             group
             mask
             other
             default_user
             default_group
             default_mask
             default_other

A user or group can be specified to the user, group, default_user and default_group types. Solaris ACL permissions are the normal UNIX permissions bits ‘rwx’, where:

         
             r - Grants read privileges.
             w - Grants write privileges.
             x - Grants execute privileges.


Next: , Previous: Solaris ACLs, Up: acl

4.6.3 DFS ACLs

In DCE, the ACL type can be one of the following:

             other
             mask
             any
             unauthenticated
             user
             group
             foreign_other
             foreign_user
             foreign_group

The user, group, foreign_user and foreign_group types require that you specify a user or group. The DCE documentation refers to types user_obj, group_obj and so on. In the cfengine implementation, the ugly ‘_obj’ suffix has been dropped to make these more in keeping with the POSIX names. user_obj::, is equivalent to user:*: is cfengine. The star/asterisk implies that the ACL applies to the owner of the file object.

DFS permissions are comprised of the bits ‘crwxid’, where:

             c - Grants control privileges, to modify an acl.
             r - Grants read  privileges.
             w - Grants write privileges.
             x - Grants execute privileges.
             i - Grants insert privileges.
             d - Grants delete privileges.

See the DCE/DFS documentation for more information about this.

It is not possible to set ACLs in foreign cells currently using cfengine, but you can still have all of your ACL definitions in the same file. You must however arrange for the file to be executed on the server for the cell concerned. Note also that you must perform a DCE login (normally as user ‘cell_admin’) in order to set ACLs on files which are not owned by the owner of the cfengine-process. This is because you must have a valid security ticket.


Next: , Previous: DFS ACLs, Up: acl

4.6.4 NT ACLs

NT ACEs are written as follows:

            acl_type:user/group:permissions:accesstype

The actual change consists of the extra field containing the access type. A star/asterisk in the field for user/group would normally imply that the ACL applies to the owner of the file object. However this functionality is as of today not yet implemented.

In NT, the ACL type can be one of the following:

                user
                group

Both types require that you specify the name of a user or a group.

NT permissions are comprised of the bits ‘rwxdpo’, where:

         r - Read privileges
         w - Write privileges
         x - Execute privileges
         d - Delete privileges
         p - Privileges to change the permissions on the file
         o - Privileges to take ownership of the file

In addition to any combination of these bits, the word noaccess or default can be used as explained in the previous section. NT comes with some standard, predefined permissions. The standards are only a predefined combination of the different bits specified above and are provided with cfengine as well. You can use the standards by setting the permission to read, change or all. The bit implementation of each standard is as on NT:

                read   - rx
                change - rwxd
                all    - rwxdpo

where the bits follow the earlier definition. The keywords mentioned above can only be used alone, and not in combination with ‘+’, ‘-’, ‘=’ and/or other permission bits.

NT defines several different access types, of which only two are used in connection with the ACL type that is implemented in cfengine for NT. The access type can be one of the following:

                allowed
                denied

Intuitively, allowed access grants the specified permissions to the user, whilst denied denies the user the specified permissions. If no access type is specified, the default is allowed. This enables cfengine's behaviour as on UNIX systems without any changes to the configuration file. If the permissions noaccess or default is used, the access type will be irrelevant.


Next: , Previous: NT ACLs, Up: acl

4.6.5 Windows ACL Example

Here is an example of a configuration file for an NT ACL:

     control:
             actionsequence = ( files )
             domain = ( iu.hioslo.no )
     
     files:
             $(HOME)/tt    acl=acl_alias1    action=fixall
     
     acl:
             { acl_alias1
     
             method:overwrite
             fstype:nt
     
             user:gustafb:rwx:allowed
             user:mark:all:allowed
             user:toreo:read:allowed
             user:torej:default:allowed
             user:ds2:+rwx:allowed
     
             group:dummy:all:denied
             group:iu:read:allowed
             group:root:all:allowed
             group:guest:dpo:denied
             }


Previous: Windows ACL Example, Up: acl

4.6.6 Posix ACL Example

Here is an example of a configuration file for one Solaris ACL and one DCE/DFS ACL:

     control:
             actionsequence = ( files )
             domain = ( iu.hioslo.no )
     
     files:
             $(HOME)/tt    acl=acl_alias1    action=fixall
             /:/bigfile    acl=acl_alias2    action=fixall
     
     acl:
             { acl_alias1
     
             method:overwrite
             fstype:posix
     
             user:*:rwx
             user:mark:=rwx
             user:sowille:=rx
             user:toreo:=rx
             user:torej:default
             user:ds2:+rwx
             group:*:rx
             group:iu:r
             group:root:x
             mask:*:rx
             other:*:rx
     
             default_user:*:=rw
             default_user:mark:+rwx
             default_user:ds:=rwx
             default_group::=r
             default_group:iu:+r
             default_mask::w
             default_other::rwx
             }
     
             { acl_alias2
     
             method:overwrite
             fstype:dfs
     
             user:*:rwxcid
             group:*:rxd
             other:*:wxir
             mask:*:rxw
             user:/.../iu.hioslo.no/cell_admin:rc
             group:/.../iu.hioslo.no/acct-admin:rwxcid
             user:/.../iu.hioslo.no/root:rx
             }


Next: , Previous: acl, Up: Cfagent reference

4.7 alerts

Alerts are normally just messages that are printed when classes become activated in order to alert the system administrator to some condition that has arisen. Alerts can also be special functions, like ShowState() that generate system output.

Alerts cannot belong to the class any, that would generate a message from every host. In a huge network this could result in vast amounts of Email. This behaviour can be forced, however, by creating an alias for the class `any' that is defined on the affected hosts.

     
     alerts:
     
        class::
     
           quoted message
     
             ifelapsed=time
             audit=true/false
     
           ShowState(parameter)
           SysLog(priority,message)
           SetState(name,ttl,policy)
           UnSetState(name)
           FriendStatus(hours)
           PrintFile(filename,lines)
     

For example:

     
     alerts:
     
       myclass::
     
       "Reminder: say hello every hour" ifelapsed=60
     
       nfsd_in_high_dev2::
     
       "High NFS server access rate 2dev at $(host) value $(value_nfsd_in) av $(average_nfsd_in) pm $(stddev_nfsd_in)"
       ShowState(incoming.nfs)
     
      # ROOT PROCS
     
       anomaly_hosts.RootProcs_high_dev2::
     
        "RootProc anomaly high 2 dev on $(host) value $(value_rootprocs) av $(average_rootprocs) pm $(stddev_rootprocs)"
       ShowState(rootprocs)
     

The ShowState() function reports on state gathered by the cfenvd daemon.

     ShowState(incoming.tcpsyn)
     ShowState(outgoing.smtp)
     ShowState(incoming.www)
     ShowState(outgoing.www)
     ShowState(procs)
     ShowState(rootprocs)
     ShowState(otherprocs)
     ShowState(users)

To limit the frequency of alerts, you can set locking times:

      # ROOT PROCS
     
       anomaly_hosts.RootProcs_high_dev2::
     
        "RootProc anomaly high 2 dev on $(host) value $(value_rootprocs) av $(average_rootprocs) pm $(stddev_rootprocs)"
     
        ShowState(rootprocs)  ifelapsed=10 expireafter=20
     

Alerts can also be channeled directly to syslog, to avoid extraneous console messages or email.

     
       SysLog(LOG_ERR,"Test syslog message")
     

One application for alerts is to pass signals from one cfengine to another by persistent, shared memory. For example, suppose a short-lived anomaly event triggers a class that relates to a security alert. The event class might be too short-lived to be followed up by cfagent in full. One could thus set a long term class that would trigger up several follow-up checks. A persistent class could also be used to exclude an operation for an interval of time.

Persistent class memory can be added through a system alert functions to give timer behaviour. For example, consider setting a class that acts like a non-resettable timer. It is defined for exactly 10 minutes before expiring.

     
       SetState("preserved_class",10,Preserve)
     

Or to set a class that acts as a resettable timer. It is defined for 60 minutes unless the SetState call is called again to extend its lifetime.

     
       SetState(non_preserved_class,60,Reset)
     

Existing persistent classes can be deleted with:

     
               UnsetState(myclass)
     

The FriendStatus function is available from version 2.1.4 and displays a message if hosts that normally have a cfengine protocol connection with the current host have not connected for more than than specified number of hours. If the number of hours is set to zero, cfengine uses a machine-learned expectation value for the time and uses this to report. The friend status of a host is thus the expectation that there is a problem with a remote peer. Expected contact rates of more than the variable LastSeenExpireAfter are ignored as spurious, See lastseenexpireafter.

The PrintFile function can be used to display short excerpts from text files. The arguments are the filename and a maximum number of lines to be printed.


Next: , Previous: alerts, Up: Cfagent reference

4.8 binservers

The binservers declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of which other hosts on the network possess filesystems containing software (binary files) which client hosts should mount. This includes resources like programs in /usr/local and so on. A host may have several binary servers, since there may be several machines to which disks are physically attached. In most cases, on a well organized network, there will be only one architecture server per UNIX platform type, for instance a SunOS server, an ULTRIX server and so on.

Binary servers are defined as follows:

     
     binservers:
     
        physics.sun4::   sunserver sunserver2
        physics.linux::  linuxserver
     

The meaning of this declaration is the following. All hosts of type sun4 which are members of the group physics should mount any binaries declared in the mountables resource list which belong to hosts sunserver or sunserver2. Similarly all linux machines should mount binary filesystems in the mountables list from linuxserver.

Cfengine knows the difference between binaries and home directories in the mountables list, because home directories match the pattern given by homepattern. See homepattern. See homeservers.

Note that every host is a binary server for itself, so that the first binary server (and that with highest priority) is always the current host. This ensures that local filesystems are always used in preference to NFS mounted filesystems. This is only relevant in connection with the variable $(binserver).


Next: , Previous: binservers, Up: Cfagent reference

4.9 broadcast

This information is used to configure the network interface for each host.

Every local area network has a convention for determining which internet address is used for broadcast requests. Normally this is an address of the form aaa.bbb.ccc.255 or aaa.bbb.ccc.0. The difference between these two forms is whether all of the bits in the last number are ones or zeroes respectively. You must find out which convention is used at your establishment and tell cfengine using a declaration of the form:

     broadcast:
     
       any::
     
          ones     # or zeros, or zeroes
     

In most cases you can use the generic class any, since all of the hosts on the same subnet have to use the same convention. If your configuration file encompasses several different subnets with different conventions then you will need to use a more specific.

Cfengine computes the actual value of the broadcast address using the value specified above and the netmask See netmask.


Next: , Previous: broadcast, Up: Cfagent reference

4.10 control

The fundamental piece of any cfengine script or configuration file is the control section. If you omit this part of a cfengine script, it will not do anything! The control section is used to define certain variables, set default values and define the order in which the various actions you have defined will be carried out. Because cfengine is a declarative or descriptive language, the order in which actions appear in the file does not necessarily reflect the order in which they are executed. The syntax of declarations here is:

       control:
     
          classes::
     
             variable = ( list or value function(args) )
     

The control section is a sequence of declarations which looks something like the following example:

     
     control:
     
       site     = ( univ )
       domain   = ( univ.edu )
       sysadm   = ( admin@computing.univ.edu )
       netmask  = ( 255.255.252.0 )
       timezone = ( EDT )
       nfstype  = ( nfs )
     
       childlibpath = ( /usr/local:/mylibs )
     
       sensiblesize  = ( 1000 )
       sensiblecount = ( 2 )
       editfilesize  = ( 4000 )
     
       actionsequence =
          (
          links.some
          mountall
          links.others
          files
          )
     
       myvariable = ( something )
       mymacro    = ( somethingelse )
       myrandom   = ( RandomInt(3,6) )
       myexcerpt  = ( ReadFile("/etc/services",220))
     

Parentheses are required when making a declaring information in cfengine. Note that a limited number of built-in functions exists:

  • ExecResult(command) Executes the named shell command and inserts the output into the variable. Note that, when this is used in cfengine built-in list variables, any spaces are interpreted as list separators. In other lists, normal rules for iteration apply.
  • RandomInt(a,b) Is substituted for a random number between (a,b).
  • ReadFile(filename,Max number of bytes) A maximum number of bytes is read from the named file and placed in a variable.
For more functions, See Setting variables with functions.

The meaning of each of these lines is described below.


Next: , Previous: control, Up: control

4.10.1 AbortClasses

The AbortClasses list is a list of class identifiers that will result in the abortion of the current cfagent instanitation with an error message containing the name of the offending class.

     
      AbortClasses = ( emergency nologin_exists )
     

This mechanism allows one to make controlled exceptions at the agent level. For example

     control:
     
      actionsequence = ( shellcommands )
     
      AbortClasses = ( danger_will_robinson )
     
     shellcommands:
     
       "shellcom 1"
       "shellcom 2" define=ok elsedefine=danger_will_robinson
     


Next: , Previous: AbortClasses, Up: control

4.10.2 access

The access list is a list of users who are to be allowed to execute a cfengine program. If the list does not exist then all users are allowed to run a program.

        access = ( user1 user2 ...  )

The list may consist of either numerical user identifiers or valid usernames from the password database. For example:

        access = ( mark aurora 22 456 )

would restrict a script to users mark, aurora and user id 22 and 456.


Next: , Previous: access, Up: control

4.10.3 actionsequence

The action sequence determines the order in which collective actions are carried out. Here is an example containing the full list of possibilities:

        actionsequence =
           (
           mountall               # mount filesystems in fstab
           mountinfo              # scan mounted filesystems
           checktimezone          # check timezone
           netconfig              # check net interface config
           resolve                # check resolver setup
           unmount                # unmount any filesystems
           packages               # install/upgrade/remove packages
           shellcommands          # execute shell commands
           editfiles              # edit files
           addmounts              # add new filesystems to system
           directories            # make any directories
           links                  # check and maintain links (single and child)
           mailcheck              # check mailserver
           mountall               # (again)
           required               # check required filesystems
           tidy                   # tidy files
           disable                # disable files
           files                  # check file permissions
           copy                   # make a copy/image of a master file
           processes              # signal / check processes
           module:name            # execute a user-defined module
           )
     

Here is a more complete description of the meaning of these keywords.

addmounts
causes cfengine to compute which NFS filesystems are missing from the current host and add them. This includes editing the filesystem table, creating the mount-directory, if required. This command relies on information provided by mountinfo, so it should normally only be called after mountinfo. If the filesystem already appears to be in the filesystem table, a warning is issued.
checktimezone
runs a check on the timezone defined for the shell running cfengine.
directories
executes all the commands defined under the directories section of the program. It builds new directories.
disable
executes all the commands defined under the disable section of the program.
editfiles
executes all the commands defined under the editfiles section of the program.
files
executes all the commands defined under the files section of the program.
links
executes all the commands defined under the links section of the program.
mailcheck
tests for the presence of the NFS-mounted mail spooling directory on the current host. The name of the mail spool directory is defined in the mailserver section of the cfengine program. If the current host is the same as the mailserver (the host which has the physical spool directory disk) nothing is done. Otherwise the filesystem table is edited so as to include the mail directory.
module
Normally cfengine's ability to detect the system's condition is limited to what it is able to determine while excuting predefined actions. Classes may be switched on as a result of actions cfengine takes to correct a problem. To increase the flexibility of cfengine, a mechanism has been introduced in version 1.5 which allows you to include a module of your own making in order to define or undefine a number of classes. The syntax
            module:mytests
          
            "module:mytests arg1 arg2 .."

declares a user defined module which can potentially set the classes class1 etc. Classes returned by the module must be declared so that cfengine knows to pay attention to rules which use these classes when parsing; this is done using AddInstallable. If arguments are passed to the module, the whole string must be quoted like a shellcommand. See Writing plugin modules. Whether or not these classes become set or not depends on the behaviour of your module. The classes continue to apply for all actions which occur after the module's execution. The module must be owned by the user executing cfengine or root (for security reasons), it must be named module:module-name and must lie in a special directory, See moduledirectory.

mountall
mounts all filesystems defined in the hosts filesystem table. This causes new NFS filesystems added by addmounts and mailcheck to be actually mounted. This should probably be called both before mountinfo and after addmounts etc. A short timeout is placed on this operation to avoid hanging RPC connections when parsing NFS mounted file systems.
mountinfo
builds internal information about which filesystems are presently mounted on the current host. Cfengine assumes that required-filesystems which are not found need to be mounted. A short timeout is placed on this operation to avoid hanging RPC connections when parsing NFS mounted file systems. If this times out, no further mount operations are considered reliable and are summarily cancelled.
netconfig
checks the netmask, hostname, IP address and broadcast address for the current host. The correct values for the netmask and broadcast address are set if there is an error. The defaultroute is matched against the static routing table and added if no default route exists. This does not apply to DHCP clients, which set a default route automatically.
required
executes all the commands defined under the required section of the program. It checks for the absence of important NFS resources.
resolve
checks and corrects the DNS domain name and the order of nameservers in the file /etc/resolv.conf.
packages
executes commands defined under the packages section of the program. This will query the system's package database for the specified packages, at the specified versions, set classes based on whether or not those packages exist, and optionally install, upgrade or remove those packages using a pre-defined package manager command.
shellcommands
executes all the commands defined under the shellcommands section of the program.
tidy
executes all the commands defined under the tidy section of the program.
unmount
executes all the commands defined under the unmount section of the program. The filesystem table is edited so as to remove the unwanted filesystems and the unmount operation is executed.
processes
executes commands defined under the processes section of the program.

Under normal circumstances this coarse ordering is enough to suit most purposes. In some cases you might want to, say, only perform half the link operations before mounting filesystems and then, say, perform the remainder. You can do this (and similar things) by using the idea of defining and undefining classes. See Defining classes.

The syntax

     
     actionsequence =
        (
        links.firstpass.include
        ...
        links.secondpass
        )

means that cfengine first executes links with the classes firstpass and include defined. Later it executes links with secondpass defined. You can use this method of adding classes to distinguish more finely the flow of control in programs.

A note about style: if you define and undefine lots of classes to do what you want to do, you might stop and ask yourself if your groups are defined as well as they should be. See groups. Programming in cfengine is about doing a lot for only a little writing. If you find yourself writing a lot, you are probably not going about things in the right way.


Next: , Previous: actionsequence, Up: control

4.10.4 AddClasses

        AddClasses  = ( list of identifiers )

The AddClasses directive is used to define a list of class attributes for the current host. Normally only the hard classes defined by the system are `true' for a given host. It is convenient though to be able to define classes of your own to label certain actions, mainly so that they can later be excluded so as to cut short or filter out certain actions. This can be done in two ways. See actionsequence.

To define a list of classes for the current session, you write:

     AddClasses = ( exclude shortversion )

This is equivalent to (though more permanent than) defining classes on the command line with the -D option. You can now use these to qualify actions. For example

     
       any.exclude::
           ...

Under normal circumstances exclude is always true — because you have defined it to be so, but you can undefine it in two ways so as to prevent the action from being carried out. One way is to undefine a class on the command line when you invoke cfengine:

     

host# cfengine -N exclude

or

     

host# cfengine -N exclude.shortversion host# cfengine -N a.b.c.d

These commands run cfengine with the named classes undefined. That means that actions labelled with these classes are excluded during that run.

Another way to restrict classes is to add a list of classes to be undefined in the actionsequence. See next section.


Next: , Previous: addclasses, Up: control

4.10.5 AddInstallable

        AddInstallable  = ( list of identifiers )

Some actions in your cfengine program will be labelled by classes which only become defined at run time using a define= option. Cfengine is not always able to see these classes until it meets them and tries to save space by only loading actions for classes which is believes will become defined at some point in the program. This can lead to some actions being missed if the action is parsed before the place where the class gets switched on, since cfengine is a one-pass interpreter,. To help cfengine determine classes which might become defined during a run, you can declare them in this list. It does no harm to declare classes here anyway. Here is an example where you need to declare a class because of the ordering of the actions.

     
     control:
     
         AddInstallable  = ( myclass )
     
     files:
     
        myclass::
     
          /tmp/test mode=644 action=fixall
     
     copy:
     
          /tmp/foo dest=/tmp/test define=myclass
     

If we remove the declaration, then when cfengine meets the files command, it skips it because it knows nothing about the class ‘myclass’—when the copy command follows, it is too late. Remember that imported files are always parsed after the main program so definitions made in imported files always come later than things in the main program.


Next: , Previous: addinstallable, Up: control

4.10.6 AllowRedefinitionOf

Normally cfagent warns about redefinitions of variables during parsing. This is presumed to be a mistake. To avoid this behaviour, add the name of the variable to this list, and the warning disappears.

     control:
     
     actionsequence = ( copy )
     
     AllowRedefinitionOf = ( cfrep )
     
     cfrep = ( bla )
     
     cfrep = ( blo )
     


Next: , Previous: AllowRedefinitionOf, Up: control

4.10.7 Auditing

If this variable is set to true then cfengine conducts extensive auditing of its actions to a database in the work directory. When rules are applied, their locations and policy version are recorded also so that it is possible to see exactly which rule was applied and when. It is assumed that the version is recorded as below:

     
     control:
     
       cfinputs_version = ( 1.2.1 )
       Auditing = true
     

This variable acts as the global default behaviour and may be overriden locally by audit=true/false attributes, where applicable.


Next: , Previous: Auditing, Up: control

4.10.8 AutoDefine

     
     control:
     
        hup_syslogd::
     
          autodefine = ( /etc/syslog.c* )
     

Referring to the class that prefixes the command, autodefine is a list of file patterns that will define the said class, if a named file is copied in any statement. This helps to avoid having to write a large number of file-specific copy: lines with define=class configured. In the example above, the class hup_syslogd would be defined if /etc/syslog.conf is copied at any time.


Next: , Previous: AutoDefine, Up: control

4.10.9 BinaryPaddingChar

     BinaryPaddingChar = ( \0 )

This specifies the type of character used to pad strings of unequal length in editfiles during binary editing. The default value is the space character, since this is normally used to edit filenames or text messages within program code.

4.10.10 BindToInterface in cfagent

If this is set to a specific IP address of an IP configured interface, cfagent will use that address for outgoing connections. On Multi-homed hosts this allows one to restrict the traffic to a known interface. An interface must be configured with an IP address in order to be bound.

This feature is not available for old operating systems.

4.10.11 ChecksumDatabase in cfagent

     ChecksumDatabase = ( /var/cfengine/cfdb )
     

If this filename is defined, cfengine will use it to store message digests (i.e. cryptographic checksums) of files for security purposes, See files, checksum=.

This option was deprecated in 2.1.22.

4.10.12 ChecksumPurge

     ChecksumPurge = ( on )
     

This variable defaults to `off'. If set to true, cfagent will look at all of the registered files in the database and check whether thet still exist. If the file no longer exists, it is removed from the database and a warning is issued.

To purge files now and then, but at no particular time, one could do something like this:

     
     strategies:
     
      { purging
     
      NowAndThen: 1
      ElseWhen:   49
      }
     
     control:
     
      NowAndThen::
     
        ChecksumPurge = ( on )
     
     


Next: , Previous: ChecksumPurge, Up: control

4.10.13 ChecksumUpdates

     ChecksumUpdates = ( on )
     

This variable defaults to `off'. If set to true, cfagent will automatically update the checksum of a file, if it changes on the disk. This means that a security warning will be issued only once about files which have changed, and the changed version will be re-registered as the correct version. This option could be switched on after a system upgrade, for instance, in order to update the database, and then switched to `off' again to reduce the risk of missing a security alert. Alternatively, if you are confident that the first message is sufficient, it can be left as `on' so that only one message is given.


Next: , Previous: ChecksumUpdates, Up: control

4.10.14 CompressCommand

Specified the name of a program that is used in the files action=compress attribute.

     CompressCommand = ( /usr/bin/gzip )
     


Next: , Previous: CompressCommand, Up: control

4.10.15 ChildLibPath

Sets a value for LD_LIBRARY_PATH in child processes:

     
      childlibpath = ( /usr/local/lib:/local/mysql/lib )
     

Note that the variables LD_LIBRARY_PATH is special. This library path is needed to run processes as children of cfengine. Often, if the agent is started from cron (which is started by init), there is no suitable library path set, and shellcommands will fail with strange errors about not being able to load shared objects. Setting a library path here is a useful way of correcting this problem.


Next: , Previous: childlibpath, Up: control

4.10.16 CopyLinks

This list is used to define a global list of names or patterns which are to be copied rather than linked symbolically. For example

     CopyLinks = ( *.config )

The same facility can be specified for each individual link operation using the copy option See links. Copying is performed using a file age comparison.

Note that all entries defined under a specified class are valid only as long as that class is defined. For instance

       class::
     
           CopyLinks = ( pattern )

would define a pattern which was only valid when class is defined.


Next: , Previous: copylinks, Up: control

4.10.17 DefaultCopyType

This parameter determines the default form of copying for all copy operations parsed after this variable. The legal values are ctime (intial default), mtime, checksum and binary. e.g.

     
      DefaultCopyType = ( mtime )
     


Next: , Previous: defaultcopytype, Up: control

4.10.18 DefaultPkgMgr

Sets the default value of the pkgmgr attribute for packages items.

     DefaultPkgMgr = ( rpm )

By default, this variable is not set, meaning there will be no package manager selected, and each item in the packages section must specify its own package manager, or it will not be checked. For information on the values of this variable, See packages.


Next: , Previous: defaultpkgmgr, Up: control

4.10.19 DeleteNonUserFiles

If this parameter is set to true, cfengine will delete files which do not have a name belonging to a known user id.

     DeleteNonUserFiles = ( true )
     
     SpoolDirectories = ( /var/spool/cron/crontabs )

This is an generalization of DeleteNonUserMail and makes it redundant. it is formally executed as a part of the “tidy” action.


Next: , Previous: deletenonuserfiles, Up: control

4.10.20 DeleteNonOwnerFiles

If this parameter is set to true, cfengine will delete files on mailservers whose names do not correspond to a known user name, but might be owned by a known user.

     DeleteNonOwnerFiles = ( true )
     
     SpoolDirectories = ( /var/spool/cron/crontabs )

This is an generalization of DeleteNonOwnerMail and makes it redundant.

4.10.21 DeleteNonUserMail

If this parameter is set to true, cfengine will delete mail files on mailservers which do not have a name belonging to a known user id. This does not include lock files.


Next: , Previous: deletenonusermail, Up: control

4.10.22 DeleteNonOwnerMail

If this parameter is set to true, cfengine will delete files on mailservers whose names do not correspond to a known user name, but might be owned by a known user.


Next: , Previous: deletenonownermail, Up: control

4.10.23 domain

       domain = ( domain name )

This variable defines the domainname for your site. You must define it here, because your system might not know its domainname when you run cfengine for the first time. The domainname can be used as a cfengine variable subsequently by referring to $(domain). The domainname variable is used by the action resolve. The domain is also used implicitly by other matching routines. You should define the domain as early as possible in your configuration file so as to avoid problems, especially if you have the strange practice of naming hosts with their fully qualified host names since groups which use fully qualified names can fail to be defined if cfengine is not able to figure out the domain name.


Next: , Previous: domain, Up: control

4.10.24 DPKGInstallCommand

Sets the command used to install packages that need to be installed under the DPKG package manager.

     DPKGInstallCommand = ( "/usr/bin/pkgmgr %s" )

By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the "'s around the string, and the %s is replaced with the name of the package to be installed.


Next: , Previous: dpkginstallcommand, Up: control

4.10.25 DryRun

     
       DryRun = ( on/off )
     

This variable has the same effect as the command line options --dry-run or -n. It tells cfengine to only report what it should do without actually doing it.

     
      classes::
     
        DryRun = ( on )
     


Next: , Previous: dryrun, Up: control

4.10.26 editbinaryfilesize

        EditBinaryFileSize  = ( size )

Cfengine will refuse to edit a file which is larger than the value of editbinaryfilesize in bytes. This is to prevent possible accidents from occurring. The default value for this variable is 10000000 bytes. If you don't like this feature, simply set the value to be a very large number or to zero. If the value is zero, cfengine will ignore it.


Next: , Previous: editbinaryfilesize, Up: control

4.10.27 editfilesize

        EditfileSize  = ( size )

This variable is used by cfengine every time it becomes necessary to edit a file. Since file editing applies only to text files, the files are probably going to be relatively small in most cases. Asking to edit a very large (perhaps binary) file could therefore be the result of an error.

A check is therefore made as a security feature. Cfengine will refuse to edit a file which is larger than the value of editfilesize in bytes. This is to prevent possible accidents from occurring. The default value for this variable is 10000 bytes. If you don't like this feature, simply set the value to be a very large number or to zero. If the value is zero, cfengine will ignore it.


Next: , Previous: editfilesize, Up: control

4.10.28 EmptyResolvConf

        EmptyResolvConf  = ( true )

Normally cfengine does not tidy up old entries in the /etc/resolv.conf file. This option causes cfengine to remove all existing content from the file.


Next: , Previous: emptyresolvconf, Up: control

4.10.29 Exclamation

This variable defaults to “on”. If set to “off”, no exclamation marks (Br. pling, Am: shriek) are printed during security alerts, e.g. for checksum violations.

        Exclamation  = ( off )


Next: , Previous: exclamation, Up: control

4.10.30 ExcludeCopy

This list is used to define a global list of names or patterns which are to be excluded from copy operations. For example

      ExcludeCopy = ( *~ *% core )

The same facility can be specified for each individual link operation using the exclude option See copy.

Note that all entries defined under a specified class are valid only as long as that class is defined. For instance

       class::
     
           ExcludeCopy = ( pattern )

would define a pattern which was only valid when class is defined.


Next: , Previous: excludecopy, Up: control

4.10.31 ExcludeLink

This list is used to define a global list of names or patterns which are to be excluded from linking operations. For example

      ExcludeLink = ( *~ *% core )

The same facility can be specified for each individual link operation using the exclude option See links.

Note that all entries defined under a specified class are valid only as long as that class is defined. For instance

       class::
     
           ExcludeLink = ( pattern )

would define a pattern which was only valid when class is defined.


Next: , Previous: excludelinks, Up: control

4.10.32 ExpireAfter

If you change the value of this parameter, it should be one of the first things you do in your configuration script.

This parameter controls the global value of the ExpireAfter parameter. See Spamming and security. This parameter controls the maximum time in minutes which a cfengine action is allowed to live. After this time a second cfengine agent will try to kill the cfengine which seems to have hung and attempt to restart the action. This is different from a TimeOut, where an internal alarm interrupt is used.

     
      ExpireAfter = ( time-in-minutes )
     

This parameter may also be set per action in the action sequence by appending a pseudo-class called ExpireAftertime. For instance,

     
      actionsequence = ( copy.ExpireAfter15 )
     

sets the expiry time parameter to 15 minutes for this copy command. This method should be considered old and deprecated however. As of version 2.1.0, you can define the expiry time on a per-command basis, as options of the form expireafter=10.


Next: , Previous: ExpireAfter, Up: control

4.10.33 FreeBSDInstallCommand

Sets the path to `pkg_add' which is used to install packages that need to be installed under FreeBSD.

     
          FreeBSDInstallCommand = ( "/usr/sbin/pkg_add -r %s" )
     

By default, this variable is not set, meaning that any packages with action=install will NOT be installed. Note the quotes around the string, and the %s is replaced with the name of the package to be installed.


Next: , Previous: FreeBSDInstallCommand, Up: control

4.10.34 FreeBSDRemoveCommand

Sets the path to `pkg_delete' which is used to remove packages that need to be uninstalled under FreeBSD.

     
          FreeBSDRemoveCommand = ( "/usr/sbin/pkg_delete %s" )
     

By default, this variable is set to /usr/sbin/pkg_delete, meaning that any packages with action=remove will be removed. Note the quotes around the string, and the %s is replaced with the name of the package to be installed.


Next: , Previous: FreeBSDRemoveCommand, Up: control

4.10.35 FullEncryption

From version 2.1.22. This is false for protocol compatability with older servers.

If this is set to true, directory filenames are encrypted in addition to file contents. If transferred data are not especially secret or travel over public networks this is a waste of CPU time. In high security environments it provides full privacy of data transmission.

     
      FullEncryption = ( true )
     

4.10.36 HomePattern

        HomePattern  = ( list of patterns )

The homepattern variable is used by the cfengine model for mounting nfs filesystems. See NFS resources. It is also used in the evaluation of the pseudo variable home, See files, tidy.

homepattern is in fact a list and is used like a wildcard or pattern to determine which filesystems in the list of mountables are home directories. See mountables. This relies on your sticking to a rigid naming convention as described in the first reference above.

For example, you might wish to mount (or locate directly if you are not using a separate partition for home directories) your home directories under mountpattern in directories u1, u2 and so on. In this case you would define homepattern to match these numbers:

     homepattern = ( u? )

Cfengine now regards any directory matching $(mountpattern)/u? as being a user login directory.

Suppose you want to create mount home directories under $(mountpattern)/home and make subdirectories for staff and students. Then you would be tempted to write:

      HomePattern = ( home/staff home/students )

Unfortunately this is not presently possible. (This is, in principle, a bug which should be fixed in the future.) What you can do instead is to achieve the same this as follows:

      MountPattern = ( /$(site)/$(host) /$(site)/$(host)/home )
      HomePattern = ( staff students )


Next: , Previous: homepattern, Up: control

4.10.37 HostnameKeys in cfagent

If this variable is set to true/on, it causes cfagent to lookup and store trusted public keys according to their DNS fully qualified host name, instead of using the IP address. This can be useful in environments where hosts do not have fixed IP addresses, but do have fixed hostnames.

     
       HostnameKeys = ( on )
     

This method of storing keys is not recommended for sites with fixed IP addresses, since it removes one security barrier from a potential attacker by potentially allowing DNS spoofing.

Note that there is a corresponding variable to be set in cfrun.hosts which must be set for consistency.

4.10.38 IfElapsed in cfagent

If you change the value of this parameter, it should be one of the first things you do in your configuration script.

This parameter controls the global value of the IfElapsed parameter, See Spamming and security. This parameter controls the minimum time which must have elapsed for an action in the action sequence before which it will be executed again.

     
      IfElapsed = ( time-in-minutes )
     

This parameter may also be set per action in the action sequence by appending a pseudo-class called IfElapsedtime. For instance,

     
      ActionSequence = ( copy.IfElapsed15 )
     

sets the elapsed time parameter to 15 minutes for this copy command. This method should be considered old and deprecated however. As of version 2.1.0, you can define the expiry time on a per-command basis, as options of the form ifelapsed=15.

4.10.39 FriendIgnoreRegex

Use this regular expression to suppress FriendStatus warnings for matching hosts. e.g.

     
          IgnoreFriendRegex = ( "2001:700:.*|host1|host2" )
     


Next: , Previous: IgnoreFriendRegex, Up: control

4.10.40 IgnoreInterfaceRegex

Use this regular expression to delete class information about interfaces that you do not want to see on a host. This is useful for tamig virtual machines and their multitudinous interfaces.

     
          IgnoreInterfaceRegex = ( "vm.*" )
     


Next: , Previous: IgnoreInterfaceRegex, Up: control

4.10.41 Inform

     
       Inform = ( on/off )
     

This variable switches on the output level whereby cfengine reports changes it makes during a run. Normally only urgent messages or clear errors are printed. Setting Inform to on makes cfengine report on all actions not explicitly cancelled with a `silent' option. To set this output level one writes:

     
      classes::
     
        Inform = ( on )
     


Next: , Previous: Inform, Up: control

4.10.42 InterfaceName

If you have an operating system which is installed on some non-standard hardware, you might have to specifically set the name of the network interface. For example:

     
       control:
     
         nextstep.some::
     
            InterfaceName = ( en0 )
     
         nextstep.others::
     
            InterfaceName = ( ec0 )
     

It is only necessary to set the interface name in this fashion if you have an operating system which is running on special hardware. Most users will not need this. The choice set here overrides the system defaults and the choices made in the cfrc file, See cfrc resource file.


Next: , Previous: interfacename, Up: control

4.10.43 FileExtensions

This list may be used to define a number of extensions which are regarded as being plain files by the system. As part of the general security checking cfengine will warn about any directories which have names using these extensions. They may be used to conceal directories.

     
       FileExtensions = ( c o gif jpg html )
     


Next: , Previous: fileextension, Up: control

4.10.44 LastSeen

This option is true by default. If set to off or false it prevents cfengine and/or cfservd from learning about last times hosts were observed connecting to one another. Some users with broken resolvers (particularly in view of the change over to IPv6 compatible libraries) might find this useful when processes appear to hang on connecting.

     
       LastSeen = ( off )
     


Next: , Previous: lastseen, Up: control

4.10.45 LastSeenExpireAfter

This value (in days) sets the time after which unseen friend hosts are purged from the `last seen' database, as viewed by the FriendStatus function, See alerts.

     
       LastSeenExpireAfter = ( 2 )
     


Next: , Previous: lastseenexpireafter, Up: control

4.10.46 LinkCopies

This list is used to define a global list of names or patterns which are to be linked symbolically rather than copied. For example

     excludelinks = ( *.gif *.jpg )

The same facility can be specified for each individual link operation using the symlink option See copy.

Note that all entries defined under a specified class are valid only as long as that class is defined. For instance

       class::
     
           LinkCopies = ( pattern )

would define a pattern which was only valid when class is defined.


Next: , Previous: linkcopies, Up: control

4.10.47 LogDirectory

This is now deprecated.

Specify an alternative directory for keeping cfengine's log data. This defaults to /var/run/cfengine or /var/cfengine.

     
       LogDirectory = ( /var/cfengine )
     


Next: , Previous: LogDirectory, Up: control

4.10.48 LogTidyHomeFiles

     
       LogTidyHomeFiles = ( off )
     

If set to “off”, no log is made of user files, in their home directories, of the files which are tidied by cfengine.


Next: , Previous: LogTidyHomeFiles, Up: control

4.10.49 moduledirectory

        moduledirectory  = ( directory for plugin modules )

This is the directory where cfengine will look for plug-in modules for the actionsequence, See actionsequence. Plugin modules may be used to activate classes using special algorithms. See Writing plugin modules. This variable defaults to /var/cfengine/modules for privileged users and to $HOME)/.cfengine/modules for non-privileged users.


Next: , Previous: moduledirectory, Up: control

4.10.50 mountpattern

        mountpattern  = ( mount-point )

The mountpattern list is used by the cfengine model for mounting nfs filesystems. See NFS resources. It is also used in the evaluation of the pseudo variable home, See files, tidy.

It is used together with the value of homepattern to locate and identify what filesystems are local to a given host and which are mounted over the network. For this list to make sense you need to stick to a rigid convention for mounting your filesystems under a single naming scheme as described in the section mentioned above. If you follow the recommended naming scheme then you will want to set the value of mountpattern to

     mountpattern = ( /$(site)/$(host) )

which implies that cfengine will look for local disk partitions under a unique directory given by the name of the host and site. Any filesystems which are physically located on the current host lie in this directory. All mounted filesystems should lie elsewhere. If you insist on keeping mounted file systems in more than one location, you can make a list like this:

     mountpattern = ( /$(site)/users /$(site)/projects )


Next: , Previous: mountpattern, Up: control

4.10.51 netmask

        netmask = ( aaa.bbb.ccc.ddd )

The netmask variable defines the partitioning of the subnet addresses on your network. Its value is defined by your network administrator. On most systems it is likely to be 255.255.255.0. This is used to configure the network interface in netconfig. See actionsequence.

Every host on the internet has its own unique address. The addresses are assigned hierarchically. Each network gets a domain name and can attach something like 65,000 hosts to that network. Since this is usually too many to handle in one go, every such network may be divided up into subnets. The administrator of the network can decide how the division into subnets is made. The decision is a trade-off between having many subnets with few hosts, or many hosts on few subnets. This choice is made by setting the value of a variable called netmask. The netmask looks like an internet address. It takes the form:

     
        aaa.bbb.ccc.mmm
     

The first two numbers ‘aaa.bbb’ are the address of the domain. The remainder ‘ccc.mmm’ specifies both the subnet and the hostname. The value of netmask tells all hosts on the network: how many of the bits in the second half label different subnets and how many label different hosts on each of the subnets?

The most common value for the netmask is ‘255.255.255.0’. It is most helpful to think of the netmask in terms of bits. Each base-10 number between 0-255 represents 8 bits which are either set or not set. Every bit which is set is a network address and every bit which is zero is part of a host address. The first two parts of the address ‘255.255’ always takes these values. If the third number is ‘255’, it means that the domain is divided up into 256 sub networks and then the remaining bits which are zero can be used to give 255 different host addresses on each of the subnets.

If the value had been ‘255.255.255.254’, the network would be divided up into 2^15 subnets, since fifteen of the sixteen bits are one. The remaining bit leaves enough room for two addresses 0 and 1. One of those is reserved for broadcasts to all hosts, the other can be an actual host — there would only be room for one host per subnet. This is a stupid example of course, the main point with the subnet mask is that it can be used to trade subnets for hosts per subnet. A value of ‘255.255.254.0’ would allow 128 different subnets with 2*256-1 = 511 hosts on each.

We needn't be concerned with the details of the netmask here. Suffice it to say that its value is determined for your entire domain by the network administrator and each host has to be told what the value is.

Each host must also know what convention is used for the broadcast address. This is an address which hosts can send to if they wish to send a message to every other host on their subnet simultaneously. It is used a lot by services like NIS to ask if any hosts are willing to perform a particular service. There are two main conventions for the broadcast address: address zero (all host bits are zero) and the highest address on the subnet (all host bits are ones). The convention can be different on every subnet and it is decided by the network administrator. When you write a cfengine program you just specify the convention used on your subnet and cfengine works out the value of the broadcast address from the netmask and the host address See broadcast. Cfengine works out the value of the broadcast address using the value of the netmask.


Next: , Previous: netmask, Up: control

4.10.52 NonAlphaNumFiles

If enabled, this option causes cfengine to detect and disable files which have purely non-alphanumeric filenames, i.e. files which might be accidental or deliberately concealed. The files are then marked with a suffix .cf-nonalpha and are rendered visible.

     
       NonAlphaNumFiles = ( on )
     

These files can then be tidied by searching for the suffix. Note that alphanumeric means ascii codes less than 32 and greater than 126.

4.10.53 nfstype

        nfstype = ( nfs-type )

This variable is included only for future expansion. If you do not define this variable, its value defaults to “nfs”.

At present cfengine operates only with NFS (the network file system). When cfengine looks for network file systems to mount, it adds lines in the filesystem table (‘/etc/fstab’,‘/etc/checklist’ etc.) to try to mount filesystems of type “nfs”. In principle you might want to use a completely different system for mounting filesystems over the network, in which case the `mount type' would not be “nfs” but something else.

At the time of writing certain institutions are replacing NFS with AFS (the Andrew filesystem) and DFS (from the distributed computing environment). The use of these filesystems really excludes the need to use the mount protocol at all. In other words if you are using AFS or DFS, you don't need to use cfengine's mounting commands at all.


Next: , Previous: nfstype, Up: control

4.10.54 PortageInstallCommand

Sets the path to `emerge' which is used to install packages that need to be installed under Gentoo Portage.

     
      gentoo.some::
          DefaultPkgMgr = ( portage )
          PortageInstallCommand = ( "/usr/bin/emerge --nocolor %s" )
     
      gentoo.other::
     
         DefaultPkgMgr = ( portage )
         PortageInstallCommand = ( "/usr/lib/portage/bin/emerge --color=n %s"
     

By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the quotes around the string, and the %s is replaced with the name of the package to be installed.


Next: , Previous: PortageInstallCommand, Up: control

4.10.55 RepChar

        RepChar = ( character )

The value of this variable determines the characters which is used by cfengine in creating the unique filenames in the file repository. Normally, its value is set to ‘_’ and each ‘/’ in the path name of the file is changed to ‘_’ and stored in the repository. If you prefer a different character, define it here. Note that the character can be quoted with either single or double quotes in order to encompass spaces etc.


Next: , Previous: repchar, Up: control

4.10.56 Repository

        Repository  = ( directory )

Defines a special directory where all backup and junk files are collected. Files are assigned a unique filename which identifies the path from which they originate. This affects files saved using disable, copy, links and editfiles See Disabling and the file repository.


Next: , Previous: repository, Up: control

4.10.57 RPMcommand

The default value of the Red Hat Package manager command /bin/rpm can be altered for non-standard systems with this variable.

     RPMcommand = ( /usr/bin/rpm )
     
     


Next: , Previous: RPMcommand, Up: control

4.10.58 RPMInstallCommand

Sets the command used to install packages that need to be installed under the RPM package manager.

     RPMInstallCommand = ( "/usr/bin/pkgmgr %s" )

By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the quotes around the string, and the %s is replaced with the name of the package to be installed.

     control:
       DefaultPkgMgr = ( rpm )
       RPMInstallCommand = ( "/usr/bin/yum -d 0 -e 0 -y install %s" )
     
       # This would remove all dependencies (!)
       #
       # RPMRemoveCommand = ( "/usr/bin/yum -d 0 -e 0 -y remove %s" )
     
       # This might be less drastic
     
        RPMRemoveCommand = ( "/bin/rpm -e --nodeps %s" )
     
     packages:
     
     # this will remove this package regardless of version.
     
       some_rpm_name version=0:0.0 cmp=ge action=remove
     
     


Next: , Previous: rpminstallcommand, Up: control

4.10.59 Schedule

        schedule  = (  Min00_05 Min30_35 time class )

When cfexecd is used in daemon mode, it defaults to running once an hour, on the hour, i.e..

        schedule  = (  Min00_05 )

This can be extended to make the agent run more often. The time specifiers are cfengine classes, and are written as intervals of time rather the precise times. Cfengine's time resolution is purposely limited to five minutes because the auto-correlation time of user resources is generally greater than this. Thus, it is assumed that precision timing is not required and the start time of cfengine, when scheduled in daemon mode, is not better than a few minutes. The daemon does not require precision, but offers many other strategic features for load balancing and security.

Other time classes can be used in the schedule list, but note that cfexecd will not run the agent more than once every five minutes. This is treated as a fundamental granularity.


Next: , Previous: schedule, Up: control

4.10.60 SecureInput

        SecureInput = ( on )

If this is set cfengine will not import files which are not owned by the uid running the program, or which are writable by groups or others.


Next: , Previous: secureinput, Up: control

4.10.61 SensibleCount

        SensibleCount  = ( count )

This variable is used by the action required. It defines for cfengine what you consider to be the minimum number of files in a `required' directory. If you declare a directory as being required, cfengine will check to see if it exists. Then, if the directory contains fewer than the value of sensiblecount files, a warning is issued. The default value for this variable is 2.


Next: , Previous: sensiblecount, Up: control

4.10.62 SensibleSize

        SensibleSize  = ( size )

This variable is used by the action required. It defines for cfengine what you consider to be the minimum size for a `required' file. If you declare a file as being required, cfengine will check to see if the file exists. Of course, the file may exist but be empty, so the size of the file is also checked against this constant. If the file is smaller than the value of sensiblesize a warning is issued. The default value for this variable is 1000 bytes.


Next: , Previous: sensiblesize, Up: control

4.10.63 ShowActions

        ShowActions  = ( on )

This causes cfengine to produce detailed output of what action is being carried out as part of the prefix information during output. This is intended only for third party tools which collect and parse the cfengine output. It will be of little interest to humans.


Next: , Previous: showactions, Up: control

4.10.64 SingleCopy

     
     	singlecopy = ( path_and_filename_wildcard )
     

If a singlecopy pattern is defined the behavior of copy: is modified so that a given destination file, matching the pattern, will only be updated once. In other words, if someone tries to copy more then one source file to the same location, the destination will not be overwritten in the same run. If the path name and wildcard is any of '*', 'on' or 'true', then the list applies to all files. For example:

     control:
     
       actionsequence = ( copy )
     
       singlecopy = ( /tmp/* )
     
       addinstallables = ( zzz )
     
      zzz::
     
       autodefine = ( /tmp/* )
     
     copy:
     
      /etc/passwd dest=/tmp/destination type=binary
      /etc/group  dest=/tmp/destination type=binary
     
     alerts:
     
      zzz::
     
       "Copied something in /tmp"
     

Note (Warning) that this feature has several problems. It assumes an order dependence that cfengine generally tries to avoid. The first copy that takes place wins. Also, if files are locked at different times, this can result in oscillations between several different source files. e.g.

     
     copy:
     
      /etc/passwd dest=/tmp/bla type=binary ifelapsed=2
      /etc/group  dest=/tmp/bla type=binary ifelapsed=1
     

In order to avoid explicit looping, cfengine assumes that a file has been copied even if no actual copy took place – i.e. as long as a file is apparently up to date, that counts as a valid copy update and the promise/action is considered done. If this were not the case, then the following promises would still be in line for execution and cfengine would loop between the different versions on subsequent invocations.


Next: , Previous: singlecopy, Up: control

4.10.65 site/faculty

       site    = ( sitename )
       faculty = ( facultyname )

This variable defines a convenient name for your site configuration. It is useful for making generic rules later on, because it means for instance that you can define the name of a directory to be

     /$(site)/$(host)/local

without having to redefine the rule for a specific site. This is a handy trick for making generic rules in your files which can be imported into a configuration for any site.

faculty is a synonym for site. The two names may be used interchangeably.


Next: , Previous: site, Up: control

4.10.66 SkipIdentify

       SkipIdentify = ( true )

This is the client side directive corresponding to the server directive SkipVerify. It tells cfengine not to assume that the client is registered in the Domain Name Service (DNS). Sometimes the assumption of DNS registration can break connectivity between hosts, particularly if firewalls or Network Address Translation is in use.


Next: , Previous: SkipIdentify, Up: control

4.10.67 smtpserver

       smtpserver = ( mailhost )

This variable specified the destination for Email sent by cfexecd.


Next: , Previous: Smtpserver, Up: control

4.10.68 SplayTime

       SplayTime = ( time-in-minutes )

This variable is used to set the maximum time over which cfengine will share its load on a server, See Splaying host times.


Next: , Previous: SplayTime, Up: control

4.10.69 Split

        Split  = ( character )

The value of this variable is used to define the list separator in variables which are expected to be treated as lists. The default value of this variable is the colon ‘:’. Cfengine treats variables containing this character as lists to be broken up and iterated over, See Iteration over lists.

This typically allows communication with PATH-like environment variables in the shell.


Next: , Previous: split, Up: control

4.10.70 SpoolDirectories

A list of additional spool directories for cfengine to police. In these directories, filenames should correspond to existing users of the system. When users lost their accounts, this list plus the mail spool directory will be checked for files owned by deprecated users. See also: DeleteNonOwnerFiles, DeleteNonUserFiles.

       SpoolDirectories = ( /var/spool/cron/crontabs /var/spool/cron/atjobs )


Next: , Previous: spooldirectories, Up: control

4.10.71 SUNInstallCommand

Sets the command used to install packages that need to be installed under the SUN package manager.

     SUNInstallCommand = ( "/usr/bin/pkgmgr %s" )

By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the quotes around the string, and the %s is replaced with the name of the package to be installed.


Next: , Previous: suninstallcommand, Up: control

4.10.72 suspiciousnames

       SuspiciousNames = ( .mo lrk3 )

Filenames in this list are treated as suspicious and generate a warning as cfengine scans directories. This might be used to detect hacked systems or concealed programs. Checks are only made in directories which cfengine scans in connection with a command such as files, tidy or copy.


Next: , Previous: suspiciousnames, Up: control

4.10.73 sysadm

        sysadm = ( mail address )

The mail address of your system administrator should be placed here. This is used in two instances. If cfengine is invoked with the option -a, then it simply prints out this value. This is a handy feature for making scripts.

The administrators mail address is also written into the personal log files which cfengine creates for each user after tidying files, so you should make this an address which users can mail if they have troubles.


Next: , Previous: sysadm, Up: control

4.10.74 Syslog

     
       Syslog = ( on/off )
     

This variable activates syslog logging of cfengine output at the `inform' level.

To set this output level one writes:

     
      classes::
     
        Syslog = ( on )
     


Next: , Previous: Syslog, Up: control

4.10.75 SyslogFacility

     
       SyslogFacility = ( facility )
     

This variable alters the syslog facility level. e.g.

     
        SyslogFacility = ( LOG_LOCAL1 )
     

Valid arguments are

     LOG_USER
     LOG_DAEMON
     LOG_LOCAL0
     LOG_LOCAL1
     LOG_LOCAL2
     LOG_LOCAL3
     LOG_LOCAL4


Next: , Previous: SyslogFacility, Up: control

4.10.76 timezone

        timezone = ( 3-character timezone )

The timezone variable is a list of character strings which define your local timezone. Normally you will only need a single timezone, but sometimes there are several aliases for a given timezone e.g. MET and CET are synonymous. Currently only the first three characters of this string are checked against the timezone which cfengine manages to glean from the system. If a mismatch is detected a warning message is printed. cfengine does not attempt to configure the timezone. This feature works only as a reminder, since the timezone should really be set once and for all at the time the system is installed. On some systems you can set the timezone by editing a file, a procedure which you can automate with cfengine See editfiles.

The value of the timezone can be accessed by variable substitution in the usual way. It expands to the first item in your list.

     shellcommands:
     
            "echo ${timezone} | mail ${sysadm}"
     


Next: , Previous: timezone, Up: control

4.10.77 TimeOut

     
       TimeOut = ( 10 )
     

The default timeout for network connections is 10 seconds. This is too short on some routed networks. It is not permitted to set this variable smaller than 3 seconds or larger than 60 seconds. A timeout is generated by an `alarm' interrupt within an executing agent. This is constrasted with ExpireAfter, in which a second agent is required to interrupt the activity.


Next: , Previous: TimeOut, Up: control

4.10.78 Verbose

     
       Verbose = ( on/off )
     

This variable switches on the output level whereby cfengine reports everything it does during a run in great detail. Normally only urgent messages or clear errors are printed, See Inform. This option is almost equivalent to using the --verbose of -v command-line options. The only difference is that system environment reporting information, which is printed prior to parsing, is not shown. To set this output level on selected hosts one writes:

     
      classes::
     
        Verbose = ( on )
     

For related more limited output, See Inform.


Next: , Previous: Verbose, Up: control

4.10.79 Warnings

     
       Warnings = ( on/off )
     

This variable switches on the parser-output level whereby cfengine reports non-fatal warnings. This is equivalent to setting the command line switch --no-warn, or -w. To set this output level on selected hosts one writes:

     
      classes::
     
        Warnings = ( on )
     


Next: , Previous: Warnings, Up: control

4.10.80 WarnNonUserFiles

If this parameter is set to true, cfengine will warn about files in spool directories which do not have a name belonging to a known user id.

See also DeleteNonUserFiles.


Next: , Previous: warnnonuserfiles, Up: control

4.10.81 WarnNonOwnerFiles

If this parameter is set to true, cfengine will warn about files on mailservers whose names do not correspond to a known user name, but might be owned by a known user.

     
     SpoolDirectories = ( /var/spool/cron/crontabs )
     
     WarnNonOwnerFiles = ( true )
     

See also DeleteNonOwnerFiles. This generalizes and succeeds DeleteNonOwnerMail.


Next: , Previous: warnnonownerfiles, Up: control

4.10.82 WarnNonUserMail

If this parameter is set to true, cfengine will warn about mail files on mailservers which do not have a name belonging to a known user id. This does not include lock files.


Previous: warnnonusermail, Up: control

4.10.83 WarnNonOwnerMail

If this parameter is set to true, cfengine will warn about files on mailservers whose names do not correspond to a known user name, but might be owned by a known user.


Next: , Previous: control, Up: Cfagent reference

4.11 classes

The classes keyword is an alias for groups as of version 1.4.0 of cfengine.


Next: , Previous: classes, Up: Cfagent reference

4.12 copy

Cfengine copies files between locally mounted filesystems and via the network from registered servers. The copy algorithm avoids race-conditions which can occur due to network and system latencies by copying first to a file called file.cfnew on the local filesystem, and then renaming this quickly into place. The aim of this roundabout procedure is to avoid situations where the direct rewriting of a file is interrupted midway, leaving a partially written file to be read by other processes. Cfengine attempts to preserve hard links to non-directory file-objects, but see the caution below. Caution should be exercised in copying files which change rapidly in size. This can lead to file corruption, if the size changes during copying. Cfengine attempts to prevent this during remote copies.

The syntax summary is:

     
     copy:
     
        class::
     
           master-file
                             dest=destination-file
     
                             mode=mode
                             owner=owner
                             group=group
                             action=warn/silent/fix
                             backup=true/false/timestamp
                             repository=backup directory
                             stealth=true/on/false/off
                             checkroot=true/on/false/off
                             timestamps=preserve/keep
                             symlink=pattern
     
                             include=pattern
                             exclude=pattern
                             ignore=pattern
                             filter=filteralias
                             xdev=true/on/false/off
     
                             recurse=number/inf/0
                             type=ctime/mtime/checksum/sum/byte/binary/any
                             linktype=absolute/symbolic/relative/hard/none/copy
                             typecheck=true/on/false/off
                             define=class-list(,:.)
                             elsedefine=class-list(,:.)
     
                             force=true/on/false/off
                             forcedirs=true/on/false/off
                             forceipv4=true/on/false/off
                             size=size limits
                             server=server-host
                             failover=classes
     
                             trustkey=true/false
                             secure=[deprecated]
                             encrypt=true/false
                             verify=true/false
                             oldserver=true/false
     
                             purge=true/false
     
                             syslog=true/on/false/off
                             inform=true/on/false/off
                             audit=true/false
     
                             findertype=MacOSX finder type
     

Note that the $(this) contains the name of the server used. This variable may be used in the source and destination strings in order to tailor the filename when downloading from multiple sources (see below).

dest
The destination file is the only obligatory item. This must be the name of an object which matches the type of the master object i.e. if the master is a plain file, the destination must also be the explicit name of a plain file. An implicit `copy file to directory' syntax is not allowed. Symbolic links are copied as symbolic links, plain files are copied as plain files and special files are copied as special files. The recurse option is required to copy the contents of subdirectories.

If the destination file name is of the form filename/..namedfork/rsrc, then it is assumed that you are copying the resource fork of a file to an HFS+ file system on OS X Jaguar. In the absence of the destination file being in this form (just dest=filename), cfengine will assume that you are working with the data fork of the file. See dest.

For a resource fork copy to properly work, the data fork must have already been copied. Ie the OS will not allow you to copy the resource fork for a file that does not exist. And, copying a data fork after the resource fork will overwrite the resource fork. So, order is important. Copy the data fork, first. Then, copy the resource fork.

To split the data and resource forks of a file into two parts, open up a terminal. The following commands will copy MyFile 's data and resource forks into two separate files which can then be recombined by cfengine:

          	cp MyFile MyFile-datafork
          	cp MyFile/..namedfork/rsrc MyFile-rsrcfork

mode, owner, group
The file mode, owner and group of the images are specified as in the files function See files.


action
The action may take the values warn, silent or fix. The default action is fix, i.e. copy files. If warn is specified, only a warning is issued about files which require updating. If silent is given, then cfengine will copy the files but not report the fact.


force
If set to `true', this option causes cfengine to copy files regardless of whether it is up to date.


forceipv4
If you are working on an ipv6 enabled pair of hosts, cfengine will normally select ipv6 for communication between them. If you wish to force the use of ipv4 for some reason, set this option to true.


forcedirs
If set to `true', this option causes files or links which block the creation of directories, during recursive copying, to be moved aside forcably. A single non-supressable warning is given when this occurs; the file is moved to filename.cf-moved.


backup
If the backup option is set to “false”, cfengine will not make a backup copy of the file before copying. The default value is “true”. If the option “timestamp” is chosen, a unique timestamp will be appended to the saved filename.
repository
This allows a local override of the Repository variable, on an item by item basis. If set to “off” or “none” it cancels the value of a global repository.

Copy makes a literal image of the master file at the destination, checking whether the master is newer than the image. If the image needs updating it is copied. Existing files are saved by appending .cfsaved to the filename.


stealth
If set to `on' causes cfengine to preserve atime and mtime on the source files during local file copies. File times cannot be preserved on remote copies. This option should normally only be used together with a checksum copy, since preserving atime and mtime implies changing ctime which will force continual copying. This is a weakness in the Unix file system. Ctime cannot be preserved. Before version 1.5.0, there was a typo which made this option active on many file copies.
checkroot
Default value false, this option causes cfengine to check the permissions of the root directory during recursive directory copies. If not true, cfengine sets its own permissions on the root.


timestamps
If this is set to `preserve' or `keep', the times of the source files are inherited by the destination files during copying. This is like the `p' option of the tar command.
recurse
Specifies the depth of recursion when copying whole file-trees recursively. The value may be a number or the keyword inf. Cfengine crosses device boundaries or mounted filesystems when descending recursively through file trees. To prevent this it is simplest to specify a maximum level of recursion.
symlink
This option may be repeated a number of times to specify the names of files, or wildcards which match files which are to be symbolically linked instead of copied. A global list of patterns can also be defined in the control section of the program See linkcopies.


ignore
This works like the global ignore directive but here you may provide a private list of ignorable directories and files. Unlike include, exclude this affects the way cfengine parses directory trees.


include
This option may be repeated a number of times to specify the names of files, or wildcards which match files which are to be included in a copy operation. Specifying one of these automatically excludes everything else except further include patterns. A global list of patterns can also be defined in the control section of the program.

If the purge option is used in copying, then the ignore option has the effect of the excluding files from the purge, i.e. ignore means `keep' the named files.


exclude
This option may be repeated a number of times to specify the names of files, or wildcards which match files which are to be excluded from a copy operation. A global list of patterns can also be defined in the control section of the program `excludes' override `includes'. See excludelinks.


xdev
Prevents cfengine from descending into file systems that are not on the same device as the root of the rescurion path.
type
Normally cfengine uses the ctime date-stamps on files to determine whether a file needs to be copied: a file is only copied if the master is newer than the copy or if the copy doesn't exist. If the type is set to ‘checksum’ or ‘sum’, then a secure MD5 checksum is used to determine whether the source and destination files are identical. If ‘byte’ or ‘binary’ is specified, a byte by byte comparison is initiated. An ‘mtime’ comparison does not take into account changes of file permissions, only modifications to the contents of the files.


findertype
Sets the four letter file type code in an HFS+ file system on Mac OS X Jaguar. For example, the four letter code APPL indicates the file is an Application (and will be executed when double-clicked). The four letter code TEXT indicates the file is a text file and will be opened by the default text editor.

If the file also has an extension (for example .txt), then if setting the finder type code, you should make sure your finder type code does not conflict with the file extension.

Files both without extensions and finder type codes are mostly useless to OS X, so be sure to do one or the other!

Also note that finder type codes should not be applied to the resource forks of files.


server
If you want to copy a file remotely from a server, you specify the name of the server here. This must be the name of a host which is running the cfservd daemon, and you must make sure that you have defined the variable domain in the control section of the cfagent.conf file. If you don't define a domain you will probably receive an error of the form `cfengine: Hey! cannot stat file'. If the server name is `localhost', cfengine will perform a local copy, without using a connection to cfservd.
failover
If a file copy fails due to an error, the classes in this assignment will become active, allowing failover rules to become active.
oldserver
If this is true, cfengine uses the old protocol specification for temporary compatibility with early version 2 alphas.


trustkey
This option defaults to 'no' or 'false'. If set to true, cfagent will accept a public key from a server whose public key is presently unknown to the agent, on trust. This option should be used to bootstrap public key transfer between hosts. Once a public key has been accepted, it will not be replaced automatically. Dated public keys must be removed by hand.
encrypt
Has an effect only when used in conjuction with copy from a remote file server. This causes cfengine to use encryption and one-time keys on transferred data. (This requires RSA keys to be installed on both client and server hosts, and provides strong authentication and encryption, using random session keys.) The preferred algorithm is Blowfish, with a 128 bit key. Generally speaking the only case in which this function makes sense is in transferring shadow password files. Encrypting the transfer of system binaries makes little sense. Note: the encryption keys required to get files from cfservd are those for the user under which cfservd is running (normally root).


verify
If verify is true, cfagent attempts to verify the integrity of a remote file transfer before the new file is installed. This takes time, since an MD5 computation and transaction must take place.


size
With this option you can specify that a file is only to be copied if the source file meets a size critereon. This could be used to avoid installing a corrupted file (the copying of an empty password file, for instance). Sizes are in bytes by default, but may also be quoted in kilobytes or megabytes using the notation:
          
          numberbytes
          numberkbytes
          numbermbytes
          

Only the first characters of these strings are significant, so they may be written however is convenient: e.g. 14kB, 14k, 14kilobytes etc. Examples are:

          
             size=<400  # copy if file size is < 400 bytes
             size=400   # copy if file size is equal to 400 bytes
             size=>400  # copy if file size > 400 bytes
          


linktype
This option determines the type of link used to make links. This only applies if the file is linked rather than copied because it matches a pattern set by symlink. The default type is a direct symbolic link. The values ‘relative’ or ‘absolute’ may be used, but hard links may not be created in place of copied files, since hard links must normally reside on the same filesystem as their files, and it is assumed that most links will be between filesystems. If this value is set to copy or none, symbolic links will be replaced by actual copies of the files they point to. Note that for directories, this option is ignored.


typecheck
Controls whether cfengine allows files of one type to overwrite files of another type, i.e. switches on/off errors if source and existing destination files do not match in type, e.g. if a file would overwrite a directory or link. The default is on for safety reasons.


define
This option is followed by a list of classes which are to be `switched on' if and only if the named file was copied. In multiple (recursive) copy operations the classes become defined if any of the files in the file tree were copied. This feature is useful for switching on other actions which are to be performed after the installation of key files (e.g. package installation scripts etc).


purge
If this option is set to true, cfengine will remove files in the destination directory which are not also in the source directory. This allows exact images of filesystems to be mantained. Note that if the copy command has includes or excludes or ignored files, cfengine will purge only those files on the client machine which are also on the server. Included files are not purged. This means that some files (such as system specific work files) can be excluded from copies without them being destroyed. Note that purging is disallowed if contact with a remote server fails. This means that local files will not be destroyed by a denial of service attack. You should not use this option to synchronize NFS mounted file systems. If the NFS server goes down, cfengine cannot then tell the difference between a valid empty directory and a missing NFS file system. If you use purge, use a remote copy also. If we specify purge, then the following options will also be set and cannot be altered: forcedirs=true, typecheck=false, since other defaults could be very destructive.


Next: , Previous: copy, Up: copy

4.12.1 copy example

Example:

     
     copy:
     
           /local/etc/aliases dest=/etc/aliases m=644 o=root g=other
           /local/backup-etc  dest=/etc
     
        solaris::
     
           /local/etc/nsswitch.conf dest=/etc/nsswitch.conf
     

In the first example, a global aliases file is copied from the master site file /local/etc/aliases to /etc/aliases, setting the owner and protection as specified. The file gets installed if /etc/aliases doesn't exist and updated if /local/etc/aliases is newer than /etc/aliases. In the second example, backup-etc is a directory containing master configuration files (for instance, services, aliases, passwd...). Each of the files in backup-etc is installed or updated under /etc. Finally, a global nsswitch.conf file is kept up to date for Solaris systems.

The home directive can be used as a destination, in which case cfengine will copy files to every user on the system. This is handy for distributing setup files and keeping them updated:

     
     copy:
     
        /local/masterfiles/.cshrc  dest=home/.cshrc mode=0600
     

You can force the copying of files, regardless of the date stamps by setting the option force=true or force=on. The default is force=false or force=off.


Next: , Previous: copy example, Up: copy

4.12.2 Hard links in copying

Hard links are not like symbolic links, they are not merely pointers to other files, but alternative names for the same file. The name of every file is a hard link, the first so to speak. You can add additional names which really are the file, they are not just pointers. For the technically minded, they are not separate inodes, they are additional directory references to the same inode. When you perform a copy operation on multiple files, cfengine attempts to preserve hard links but this is a difficult task.

Because a hard link just looks like an ordinary file (it cannot be distingiushed from the original, the way a symbolic link can) there is a danger that any copy operation will copy two hard links to the same file as two separate copies of the same file. The difference is that changes a hard-linked file propagate to the links, whereas two copies of a file are completely independent thereafter. In order to faithfully reproduce all hardlinks to all files, cfengine needs to examine every file on the same filesystem and check whether they have the same inode-number. This would be an enourmous overhead, so it is not done. Instead what happens is that cfengine keeps track of only the files which it is asked to examine, for each atomic copy-command, and makes a note of any repeated inodes within this restricted set. It does not try to go off, wandering around file systems looking to other files which might be hardlinks.

To summarize, cfengine preserves hardlinks during copying, only within the scope of the present search. No backups are made of hard links, only of the first link or name of the file is backed up. This is a necessary precaution to avoid dangling references in the inode table. As a general rule, hard links are to be avoided because they are difficult to keep track of.


Previous: hard links in copy, Up: copy

4.12.3 Too many open files

In long recursive copies, where you descend into many levels of diretories, you can quickly run out of file descriptors. The number of file descriptors is a resource which you can often set in the shell. It is a good idea to set this limit to a large number on a host which will be copying a lot of files. For instance, in the C shell you would write,

     
     limit descriptors 1024
     

Most systems should have adequate defaults for this parameter, but on some systems it appears to be set to a low value such as 64, which is not sufficient for large recursive tree searches.


Next: , Previous: copy, Up: Cfagent reference

4.13 defaultroute

Dynamical routing is not configurable in cfengine, but for machines with static routing tables it is useful to check that a default route is configured to point to the nearest gateway or router. The syntax for this statement is simply:

     
     defaultroute:
     
        class::
     
           my_gateway
     

For example:

     
     defaultroute:
     
       most::
     
          129.240.22.1
     
       rest::
     
          small_gw
     
       no_default_route::
     
          192.168.1.1
     

Gateways and routers usually have internet address aaa.bbb.ccc.1 — i.e. the first address on the subnet. You may use the numerical form or a hostname for the gateway.

The class no_default_route is defined if the current host does not have a currently defined default route, but specifies one in its configuration.


Next: , Previous: defaultroute, Up: Cfagent reference

4.14 disks

This is a synonyn for required, See required. This action tests for the existence of a file or filesystem. It should be called after all NFS filesystems have been mounted. You may use the special variable $(binserver) here.

     
       disks:
     
         /filesystem freespace=size-limit define=class-list(,:.)
     
          inform=true
          log=true
          audit=true/false
     
          scanarrivals=true
          force=true
     
          ifelapsed=mins
          expireafter=mins
     

Files or filesystems which you consider to be essential to the operation of the system can be declared as `required'. Cfengine will warn if such files are not found, or if they look funny.

Suppose you mount your filesystem /usr/local via NFS from some binary server. You might want to check that this filesystem is not empty! This might occur if the filesystem was actually not mounted as expected, but failed for some reason. It is therefore not enough to check whether the directory /usr/local exists, one must also check whether it contains anything sensible.

Cfengine uses two variables: sensiblesize and sensiblecount to figure out whether a file or filesystem is sensible or not. You can change the default values of these variables (which are 1000 and 2 respectively) in the control section. See control.

If a file is smaller than sensiblesize or does not exist, it fails the `required' test. If a directory does not exist, or contains fewer than sensiblecount files, then it also fails the test and a warning is issued.

     
     disks:
     
        any::
     
           /$(site)/$(binserver)/local
     

If you set the freespace variable to a value and set inform=true, cfagent issues warnings when free disk space falls below this threshold. Any define-classes also become defined in this instance. (the default units are kilobytes, but you may specify bytes or megabytes), e.g.

     
     required:
     
       /site/host/home1 freespace=50mb define=dotidy
       /site/host/home2 freespace=10% define=dotidy
     

then cfengine will warn when the filesystem concerned has less than this amount of free space. By adding a define tag, you can switch on any number of classes if this happens. This allows you to activate special measures for dealing with a filesystem which is in danger of becoming full.

If the option force=true is used, cfengine will parse filesystems even on NFS mounted filesystems. Normally it does not make sense to check filesystems that are not native to the local host, but occasionally ne would like to force such a check in order to set a class, based on the result, for instance. If the scanarrivals option is set, the agent will recursively descend through the file system building a database of file modification times. This data is used for research purposes and will eventually be used to trigger classes that determine optimal times for backup of filesystem.


Next: , Previous: disks, Up: Cfagent reference

4.15 directories

Directories declarations consist of a number of directories to be created. Directories and files may also be checked and created using the touch option in the files actions. See files.

The form of a declaration is:

     
       directories:
     
          classes::
     
              /directory
                              mode=mode
                              owner=uid
                              group=gid
                              rxdirs=true/on/false/off
     
                              define=classlist
                              elsedefine=classlist
                              syslog=true/on/false/off
                              inform=true/on/false/off
                              audit=true/on/false/off
     
                              ifelapsed=mins
                              expireafter=mins

For example

     
     directories:
     
       class::
     
          /usr/local/bin  mode=755 owner=root group=wheel
     

The form of the command is similar to that of files but this command is only used to create new directories. Valid options are mode, owner, group and rxdirs; these are described under files See files. This interface is only for convenience. It is strictly a part of the `files' functionality and is performed together with other `files' actions at run time.

The creation of a path will fail if one of the links in the path is a plain file or device node. A list of classes may optionally be defined here if a directory is created.

If the owner value is set to the literal "LastNode", then the owner will be exchanged for the last node of the path. This allows the creation of home directories owned by users.

     
     control:
     
       homedirs = ( mark:simen:luke:aeleen )
     
     directories:
     
       /home/$(listcontent) owner=LastNode
     
     


Next: , Previous: directories, Up: Cfagent reference

4.16 disable

Disabling a file means renaming it so that it becomes harmless. This feature is useful if you want to prevent certain dangerous files from being around, but you don't want to delete them— a deleted file cannot be examined later. The syntax is

     
      disable:
     
        class::
     
           /filename
                           dest=filename
     
                           type=plain/file/link/links
                           rotate=empty/truncate/numerical-value
                           size=numerical-value
                           define=classlist
                           syslog=true/on/false/off
                           inform=true/on/false/off
                           audit=true/on/false/off
     
                           repository=destination directory
                           action=disable/warn
     
                           ifelapsed=mins
                           expireafter=mins
     

If a destination filename is specified, cfagent renames the source file to the destination, where possible (renaming across filesystems is not allowed). If no destination is given, cfagent renames a given file by appending the name of the file with the suffix .cfdisabled. Note that directories are only renamed if they have a specific destination specified.

A typical example of a file you would probably want to disable would be the /etc/hosts.equiv file which is often found with the ‘+’ symbol written in it, opening the system concerned to the entire NIS universe without password protection! Here is an example:

     
     disable:
     
           /etc/hosts.equiv
           /etc/nologin
           /usr/lib/sendmail.fc
     
        sun4::
     
           /var/spool/cron/at.allow
     

Hint: The last example disables a file which restricts access to the at utility. Such a command could be followed by a file action, See files,

     files:
     
        some::
     
           /var/spool/cron/at.allow =0644 N owner=root group=wheel touch
     

which would create an empty security file at.allow. See also your system manual pages for the at command if you don't understand why this could be useful.

Disabling a link deletes the link. If you wish you may use the optional syntax

     
     disable:
     
         /directory/name type=file
     

to specify that a file object should only be disabled if it is a plain file. The optional element type= can take the values plain, file, link or links. If one of these is specified, cfengine checks the type and only disables the object if there is a match. This allows you to disable a file and replace it by a link to another file for instance. NOTE that if you regularly disable a file which then gets recreated by some process, the disabled file filename.cfdisabled will be overwritten each time cfengine disables the file and therefore the contents of the original are lost each time. The rotate facility was created for just this contingency. The disable feature can be used to control the size of system log files, such as /var/adm/messages using a further option rotate. If the value rotate is set to 4, say,

     
      disable:
     
         filename  rotate=4
     

then cfengine renames the file concerned by appending `.1' to it and a new, empty file is created in its place with the same owner and permissions. The next time disable is executed `.1' is renamed to `.2' and the file is renamed `.1' and a new empty file is created with the same permissions. Cfengine continues to rotate the files like this keeping a maximum of four files. This is similar to the behaviour of syslog.

If you simply want to empty the contents of a log file, without retaining a copy then you can use rotate=empty or rotate=truncate. For instance, to keep control of your World Wide Web server logs:

     disable:
     
        Sunday|Wednesday::
     
            /usr/local/httpd/logs/access_log  rotate=empty

This keeps a running log which is emptied each Sunday and Wednesday. The size= option in disable allows you to carry out a disable operation only if the size of the file is less than, equal to or greater than some specified size. Sizes are in bytes by default, but may also be quoted in kilobytes or megabytes using the notation:

     
     numberbytes
     numberkbytes
     numbermbytes
     

Only the first characters of these strings are significant, so they may be written however is convenient: e.g. 14kB, 14k, 14kilobytes etc. Examples are:

     
        size=<400  # disable if file size is < 400 bytes
        size=400   # disable if file size is equal to 400 bytes
        size=>400  # disable if file size > 400 bytes
     

This options works with rotate or normal disabling; it is just an extra condition which must be satisfied. If a disable command results in action being taken by cfengine, an optional list of classes becomes can be switched on with the aid of a statement define=classlist in order to trigger knock-on actions.

The repository declaration allows a local override of the Repository variable, on an item by item basis. If set to “off” or “none” it cancels the value of a global repository and leaves the disabled file in the same directory.

4.17 editfiles

Performs ascii (line-based) editing on text-files or limited binary editing of files. If editing a file which has hard links to it, be aware that editing the file will destroy the hard link references. This is also the case with shell commands. You should avoid hard links whenever possible. The form of an editing command is editfiles can also search directories recursively through directories and edit all files matching a pattern, using Include, Exclude, and Ignore (see Recursive File Sweeps in the tutorial).

     
     editfiles:
     
        class::
     
           { file-to-be-edited
     
           action "quoted-string..."
           }
     
           { directory-to-be-edited
     
           Recurse "inf"          # iterated over all files
           Filter  "filteralias"
           Include ".cshrc"
           Ignore  "bin"
           Ignore  ".netscape"
           action "quoted-string..."
           }
     

Here are some examples:

     editfiles:
     
        sun4::
     
           { /etc/netmasks
     
           DeleteLinesContaining "255.255.254.0"
           AppendIfNoSuchLine "128.39  255.255.255.0"
           }
     
        PrintServers::
           { /etc/hosts.lpd
     
           AppendIfNoSuchLine "tor"
           AppendIfNoSuchLine "odin"
           AppendIfNoSuchLine "borg"
           }
     

The first of these affects the file /etc/netmasks on all SunOS 4 systems, deleting any lines containing the string “255.255.254.0” and Appending a single line to the file containing “128.39 255.255.255.0” if none exists already. The second affects only hosts in the class `PrintServers' and adds the names of three hosts: tor, odin and borg to the file /etc/hosts.lpd which specifies that they are allowed to connect to the printer services on any host in the class `PrintServers'.

Note that single or double quotes may be used to enclose strings in cfengine. If you use single quotes, your strings may contain double quotes and vice-versa. Otherwise a double quoted string may not currently contain double quotes and likewise for single quoted strings.

As of version 2.0.6 quoted strings may contain escaped quotes using \".

As of version 1.3.0, you can use the ‘home’ directive in edit filenames, enabling you to edit files for every user on the system, provided they exist. For example, to edit every user's login files, you would write

     
       { home/.cshrc
     
        AppendIfNoSuchLine "setenv PRINTER default-printer"
        AppendIfNoSuchLine "set path = ( $path /new/directory )"
       }
     

If a user does not possess the named file, cfengine just skips that user. A new file is not created.

The meanings of the file-editing actions should be self-explanatory. Commands containing the word 'comment' are used to `comment out' certain lines in a file rather than deleting them. Hash implies a shell comment of the type

     # comment

Slash implies a comment of the C++ type:

     // comment

Percent implies a comment of the type:

     % comment

More general comment types may be defined using the SetCommentStart, SetCommentEnd and CommentLinesMatching, CommentLinesStarting functions.

A special group of editing commands is based on the POSIX Regular Expression package. These use regular expressions to search line by line through text and perform various editing functions. Searches are of two different types: “LineMatching” and “LineContaining”. In the first case the regular expression must match the entire line exactly; in the latter, a substring is searched for in the file.

Some of these commands are based on the concept of a file pointer. The pointer starts at line one of the file and can be reset by 'locating' a certain line, or by using the reset-pointer commands. The current position of the pointer is used by commands such as InsertLine to allow a flexible way of editing the middle of files.

A simple decision mechanism is incorporated to allow certain editing actions to be excluded. For instance, to insert a number of lines in a file once only, you could write:

     
        { file
     
         LocateLineMatching "insert point..."
         IncrementPointer   "1"
     
         BeginGroupIfNoMatch "# cfengine - 2/Jan/95"
           IncrementPointer "-1"
           InsertLine "# cfengine - 2/Jan/95"
           InsertLine "/local/bin/start-xdm"
           DefineInGroup "AddedXDM"
         EndGroup
        }
     

Since the first inserted line matches the predicate on subsequent calls, the grouped lines will only be carried out once. When the grouped lines are run, the ‘AddedXDM’ class will be activated for use by a later part of the script.

The full list of editing actions is given below in alphabetical order. Note that some commands refer to regular expressions and some refer to 'literal strings' (i.e. any string which is not a regular expression). Variable substitution is performed on all strings. Be aware that symbols such as ‘.’, ‘*’ and so on are meta-characters in regular expressions and a backslash must be used to make them literal. The regular expression matching functions are POSIX extended regular expressions. See Regular expressions.

Editfile caution. It is suggested that you use these editing functions with caution. Although all possible safeguards have been incorporated into them, it is still possible through carelessness to do damage to important files on your system. Always test editing programs carefully before committing them to your global site configuration.


Next: , Previous: editfiles, Up: editfiles

4.17.1 AbortAtLineMatching

     
      AbortAtLineMatching quoted-regex
     

This command sets the value of a regular expression. In all editing operations (except FixEndOfLine and GotoLastLine) which involve multiple replacements and searches, this expression marks a boundary beyond which cfengine will cease to look any further. In other words, if cfengine encounters a line matching this regular expression, it aborts the current action. BE CAREFUL with this feature: once set, the string remains set for the remainder of the current file. It might therefore interact in unsuspected ways with other search parameters. Editing actions are always aborted as soon as the abort expression is matched. Use UnsetAbort to unset the feature.

4.17.2 Append

     
      Append quoted-regex
     

Add a line containing the quoted string to the end of the file. This should be used in conjunction with the decision structures BeginGroupIfNoLineMatching and BreakIfLineMatches.


Next: , Previous: Append, Up: editfiles

4.17.3 AppendIfNoLineMatching

     
       AppendIfNoLineMatching  quoted-regex/ ``ThisLine''
     

A new version of the older AppendIfNoSuchLine which uses a regular expression instead of a literal string. The line which gets appended must be set previously using SetLine. If ``ThisLine'' is given as the argument, the current value of then line buffer is assumed. This allows constructions for merging files on a convergent line-by-line basis:

     
     editfiles:
     
      { /tmp/bla
     
      ForEachLineIn "/tmp/in"
         AppendIfNoLineMatching "ThisLine"
      EndLoop
      }
     

4.17.4 AppendIfNoSuchLine

     
       AppendIfNoSuchLine quoted-string
     

Add a line containing the quoted string to the end of the file if the file doesn't contain the exact line already.

4.17.5 AppendIfNoSuchLinesFromFile

     
       AppendIfNoSuchLinesFromFile filename
     

For each line in the named file, call AppendIfNoSuchLine. This adds lines containing the strings listed in the named file to the end of the current file if the file doesn't contain the exact line already.


Next: , Previous: AppendIfNoSuchLinesFromFile, Up: editfiles

4.17.6 AppendToLineIfNotContains

     
      AppendToLineIfNotContains quoted-string
     

This commands looks for an exact match of the quoted string in the current line. If the quoted string is not contained in the line, it is appended. This may be used for adding entries to a list.

4.17.7 Audit in editfiles

     
      Audit true/false
     

Local decision about whether this edit stanza will be audited. Requires auditing to be on globally for this to have an effect.


Next: , Previous: Audit, Up: editfiles

4.17.8 AutoCreate

If this command is listed anywhere in the file action list, cfengine will create the named file if it doesn't exist. Normally cfengine issues an error if the named file does not exist, but if this is set, notification of the file's absence is only in verbose output. New files are created with mode 644 (see also Umask), read access for everyone and write access for the cfengine user (normally root). Note that if you set this, BeginGroupIfFileIsNewer will always be true.


Next: , Previous: AutoCreate, Up: editfiles

4.17.9 AutomountDirectResources

     
     AutomountDirectResources quoted-string
     

This command is designed to assist with automounter configuration for users wishing to use the automounter for NFS filesystems, but still use the cfengine mount model. Applied to the current file, it is equivalent to saying: for each of the mountable resources in the list See mountables, append if not found a line for a direct automount map command, to the current file. The string which follows can be used to specify any special mount options e.g. ``-nosuid'' for non setuid mounting (of all the mountables). Note that this is added to the current file and not to a file named /etc/auto_direct.

4.17.10 Backup in editfiles

     
      Backup quoted-string
     

Set to true or false, on or off to set backup policy for this file. Default is on. The default is to produce time-stamped backups of files; this may be coded explicitly by setting to “timestamp” or “stamp”. If set to “false” or “off”, no backup is kept of the edited file. If the value is set to “single” or “one” then only the last version of the file is kept, overwriting any previously saved versions.

See copybackup.

        Backup "single"

4.17.11 BeginGroupIfDefined

     
     BeginGroupIfDefined quoted-string
     

The lines following, up to the first EndGroup are executed if the quoted class is defined. Edit groups may be nested.

4.17.12 BeginGroupIfNotDefined

     
     BeginGroupIfNotDefined quoted-string
     

The lines following, up to the first EndGroup are executed if the quoted class is not defined. Edit groups may be nested.

4.17.13 BeginGroupIfFileExists

     
      BeginGroupIfFileExists quoted-string
     

The lines following, up to the first EndGroup are executed if the quoted filename exists (can be statted). Files which are not readable by the running process are for all intents and purposes non-existent. Edit groups may be nested.

4.17.14 BeginGroupIfFileIsNewer

     
      BeginGroupIfFileIsNewer quoted-string
     

The lines following, up to the first EndGroup are executed if the quoted filename is newer than the file being edited. Edit groups may be nested.

4.17.15 BeginGroupIfLineContaining

     
     BeginGroupIfLineContaining quoted-string
     

The lines following, up to the first EndGroup are executed if the quoted string appears in any line in the file. Edit groups may be nested.

4.17.16 BeginGroupIfLineMatching

     
     BeginGroupIfLineMatching quoted-regex
     

The lines following, up to the first EndGroup are executed if the quoted regular expression matches any line in the file. Edit groups may be nested.

4.17.17 BeginGroupIfMatch

     
      BeginGroupIfMatch quoted-regex
     

The lines following, up to the first EndGroup are executed if the quoted regular expression matches the current line. Edit groups may be nested.

4.17.18 BeginGroupIfNoLineContaining

     
     BeginGroupIfNoLineContaining quoted-string
     

The lines following, up to the first EndGroup are executed if the quoted string does not appear in any line in the file. Edit groups may be nested.

4.17.19 BeginGroupIfNoLineMatching

     
     BeginGroupIfNoLineMatching quoted-regex
     

The lines following, up to the first EndGroup are executed if the quoted regular expression does not match any line in the file. Edit groups may be nested.

4.17.20 BeginGroupIfNoMatch

     
     BeginGroupIfNoMatch quoted-regex
     

The lines following, up to the first EndGroup are executed if the quoted regular expression does not match the current line. Edit groups may be nested.

4.17.21 BeginGroupIfNoSuchLine

     
      BeginGroupIfNoSuchLine quoted-string
     

The lines following, up to the first EndGroup are executed if the quoted literal string does not match any line in the file. Edit groups may be nested.


Next: , Previous: BeginGroupIfNoSuchLine, Up: editfiles

4.17.22 BreakIfLineMatches

     
     BreakIfLineMatches  quoted-regex
     

Terminates further editing of the current file if the current line matches the quoted regular expression.

4.17.23 CatchAbort

Edit actions which abort on failure (such as LocateLineMatching) will jump to the first instance of this marker instead of completely aborting an edit if this keyword occurs in an editing script. You can catch the exceptions thrown by the following commands: CommentNLines,CommentToLineMatching,DeleteNLines,DeleteToLineMatching, HashCommentToLineMatching,IncrementPointer, LocateLineMatching,PercentCommentToLineMatching, RunScriptIf(No)LineMatching,UnCommentNLines.


Next: , Previous: CatchAbort, Up: editfiles

4.17.24 CommentLinesMatching

     
     CommentLinesMatching  quoted-regex
     

Use the current value of the comment delimiters set using SetCommentStart and SetCommentEnd to comment out lines matching the given regular expression in quotes.


Next: , Previous: CommentLinesMatching, Up: editfiles

4.17.25 CommentLinesStarting

     
     CommentLinesStarting  quoted-string
     

Use the current value of the comment delimiters set using SetCommentStart and SetCommentEnd to comment out lines starting with the quoted literal string.

4.17.26 CommentNLines

     
     CommentNLines quoted-string
     

Comments up to N lines from the current file, starting from the location of the current line pointer. If the end of the file is reached and less than N lines are deleted, a warning is issued, but editing continues. The current value of the comment delimiters is used to determine the method of commenting, (see SetCommentStart). After the operation the pointer points to the line after the commented lines.


Next: , Previous: CommentNLines, Up: editfiles

4.17.27 CommentToLineMatching

     
     CommentToLineMatching  quoted-regex
     

Use the current value of the comment delimiters set using SetCommentStart and SetCommentEnd to comment out lines from the current position in a file to a line matching the given regular expression in quotes.


Next: , Previous: CommentToLineMatching, Up: editfiles

4.17.28 DefineClasses

     
     DefineClasses "class1:class2:..."
     

Activate the following colon, comma or dot-separated list of classes if and only if the file is edited.

4.17.29 DefineInGroup

     
     DefineInGroup "class1:class2:..."
     

Activate the following colon, comma or dot-separated list of classes if the edit group is entered. This can be combined with other classes to identify what particular edits took place. Use DefineInGroup if you want to define a class or list of classes conditional on entry to a BeginGroup ... EngGroup block. For example,

     editfiles:
         { /etc/inetd.conf
           BeginGroupIfNoSuchLine "$(myservice1)"
             Append "$(myservice1)"
     	DefineInGroup "myservice1_added"
           EndGroup
     
           BeginGroupIfNoSuchLine "$(myservice2)"
             Append "$(myservice2)"
     	DefineInGroup "myservice2_added"
           EndGroup
         }

This will define service_added and service_added_another_way if either line is added, but additionally myservice1_added if myservice1 was added and likewise for myservice2_added.

Activate the following colon, comma or dot-separated list of classes if execution reaches the BeginGroup ... EndGroup section(s) containing this command. If you think you want to put DefineClasses within a BeginGroup ... EndGroup section, you actually want this.


Next: , Previous: DefineInGroup, Up: editfiles

4.17.30 DeleteLinesAfterThisMatching

     
      DeleteLinesAfterThisMatching quoted-regex
     

Delete lines after the current position which match the quoted expression.

4.17.31 DeleteLinesContaining/DeleteLinesNotContaining

     
      DeleteLinesContaining quoted-string
      DeleteLinesNotContaining quoted-string
     

Delete all lines (not) containing the exact string quoted.

4.17.32 DeleteLinesMatching/DeleteLinesNotMatching

     
        DeleteLinesMatching quoted-regex
        DeleteLinesNotMatching quoted-regex
     

Delete all lines (not) fully matching the tied quoted regular expression.

4.17.33 DeleteLinesStarting/DeleteLinesNotStarting

     
        DeleteLinesStarting quoted-string
        DeleteLinesNotStarting quoted-string
     

Delete all lines (not) beginning with the exact string quoted.

4.17.34 DeleteLinesNotContainingFileItems

     
     DeleteLinesNotContainingFileItems filename
     

Delete lines in the file that do not contain the any of the substrings in the file.

4.17.35 DeleteLinesNotMatchingFileItems

     
      DeleteLinesNotMatchingFileItems filename
     

Delete lines in the file that do not match the any of the regular expressions in the file.

4.17.36 DeleteLinesNotStartingFileItems

     
     DeleteLinesNotStartingFileItems filename
     

Delete lines in the file that do not start with any of the substrings in the file.

4.17.37 DeleteNLines

     
     DeleteNLines quoted-string
     

Deletes up to N lines from the current file, starting from the location of the current line pointer. If the end of the file is reached and less than N lines are deleted, a warning is issued, but editing continues.


Next: , Previous: DeleteNLines, Up: editfiles

4.17.38 DeleteToLineMatching

     
     DeleteToLineMatching quoted-regex
     

Delete lines from the current position, up to but not including a line matching the regular expression in the quoted string. If no line matches the given expression, a warning is only printed in verbose mode, but all edits are immediately abandoned.


Next: , Previous: DeleteToLineMatching, Up: editfiles

4.17.39 EditMode and binary editing

If set to binary, the file will be edited as if it were a non-ASCII file. See discussion below.

     
        EditMode "Binary"
     

4.17.40 EditSplit

Editfiles treats lists as private interpretations, since iteration over lists could lead to unpredictable behaviour if text variables accidentally contain the list separator. The control option Split therefore has no effect on editfiles. This definition makes list expansion work in editfiles.

     
        EditSplit ","
     

Be careful not to confuse this with the SplitOn character.

     
     editfiles:
     
      { /tmp/bla1
     
      EditSplit "!"
      AppendIfNoSuchLine "alpha1!beta1"
      EditSplit ":"
      AppendIfNoSuchLine "alpha2!beta2"
      EditSplit "@"
      AppendIfNoSuchLine "alpha3@beta3"
      }
     
      { /tmp/bla2
     
      AppendIfNoSuchLine "new1@new2"
      }
     


Next: , Previous: EditSplit, Up: editfiles

4.17.41 EmptyEntireFilePlease

Deletes all lines from the current file.


Next: , Previous: EmptyEntireFilePlease, Up: editfiles

4.17.42 ElseDefineClasses

See DefineClasses


Next: , Previous: ElseDefineClasses, Up: editfiles

4.17.43 EndGroup

Terminates a begin-end conditional structure.


Next: , Previous: EndGroup, Up: editfiles

4.17.44 EndLoop

Terminates a loop. See ForEachLineIn


Next: , Previous: EndLoop, Up: editfiles

4.17.45 ExpandVariables

This causes cfengine to run through the contents of the file and expand any recognisable editfile strings in the file, if they are defined within the scope of the cfagent script. This gives cfengine an m4 like capacity.


Next: , Previous: ExpandVariables, Up: editfiles

4.17.46 ExpireAfter editfiles

     
     ExpireAfter mins
     


Next: , Previous: ExpireAfter editfiles, Up: editfiles

4.17.47 Filter

Name a fiter for pruning file searches.

     
     Filter filteralias
     


Next: , Previous: Filter, Up: editfiles

4.17.48 FixEndOfLine

The quoted string which follows may be either ‘dos’ or ‘Unix’ to fix the end of line character conventions to match these systems. This command should be executed last of all, since cfengine appends new lines with the conventions of the system on which is was complied during edit operations.


Next: , Previous: FixEndOfLine, Up: editfiles

4.17.49 ForEachLineIn quoted-filename

     
     ForEachLineIn quoted-filename
     

This marks the beginning of a for-loop which reads successive lines from a named file. The result is like using SetLine for each line in the file. Nested loops are not permitted.

4.17.50 GotoLastLine

Moves the file pointer to the last line in the current file.

4.17.51 HashCommentLinesContaining

Add a ‘#’ to the start of any line containing the quoted string.

     
       HashCommentLinesContaining quoted-string
     

4.17.52 HashCommentLinesMatching

Add a ‘#’ to the start of any line exactly matching the quoted regular expression.

     
      HashCommentLinesMatching quoted-regex
     

4.17.53 HashCommentLinesStarting

Add a ‘#’ to the start of any line starting with the quoted string.

     
      HashCommentLinesStarting quoted-string
     

4.17.54 IfElapsed

     
     ExpireAfter mins
     

4.17.55 IncrementPointer quoted-number

     
      IncrementPointer quoted-number
     

Increments the value (in lines) of the file pointer by the number of lines specified in the quoted string (as a denary number). e.g. ‘``4''’. Negative values are equivalent to decrementing the pointer. If a request is made to increment/decrement outside of the file boundaries the pointer `bumps' into the boundary and remains there, i.e. either at start of file or end of file.


Next: , Previous: IncrementPointer, Up: editfiles

4.17.56 Inform editfiles

     
      Inform quoted-string
     

Set to true or false, on or off to set the inform level for this file. Default is off. Note that, owing to the way that cfengine re-uses code, this feature does not work very well. Detailed messages are not available, only a summary of whether or not the file changed.


Next: , Previous: Inform (editing), Up: editfiles

4.17.57 InsertFile

     
      InsertFile quoted-string
     

Inserts the named file after the current line position in the file. This should be used in conjunction with a begin-end construction in order to avoid including the file every time cfengine is run. If the file does not exist, or cannot be opened, there is only a warning issued in verbose mode. Note if the file is empty, or if the current line pointer is not set, the file is inserted at the start of the file.


Next: , Previous: InsertFile, Up: editfiles

4.17.58 InsertLine

     
      InsertFile quoted-string
     

Inserts the quoted string as a line after the current line pointer in the file. After the insert, the line pointer is incremented by one so that subsequent inserted lines are placed after the first. This should probably be used in conjunction with the conditional begin-end tests to avoid lines being inserted on every run.

4.17.59 LocateLineMatching

     
     LocateLineMatching quoted-regex
     

Moves the current line pointer to the line matching the quoted regular expression. If there is no match, a warning is only issued in verbose mode, but all editing is immediately aborted. See also WarnIfNoLineMatching so that you can get an explicit warning, even out of verbose mode.

4.17.60 PercentCommentLinesContaining

     
       PercentCommentLinesContaining quoted-string
     

Add a ‘%’ to the start of any line containing the quoted string.

4.17.61 PercentCommentLinesMatching

     
       PercentCommentLinesMatching quoted-regex
     

Add a ‘%’ to the start of any line exactly matching the quoted regular.

4.17.62 PercentCommentLinesStarting

     
        PercentCommentLinesStarting quoted-string
     

Add a ‘%’ to the start of any line starting with the quoted string.

4.17.63 Prepend

     
      Prepend quoted-string
     

Add a line containing the quoted string to the start of the file. This should be used in conjunction with the decision structures BeginGroupIfNoLineMatching and BreakIfLineMatches.

4.17.64 PrependIfNoLineMatching

     
     PrependIfNoLineMatching quoted-regex
     

A new version of the older PrependIfNoSuchLine with uses a regular expression instead of a literal string. The string prepended is the one set using SetLine.

4.17.65 PrependIfNoSuchLine

     
       PrependIfNoSuchLine quoted-string
     

Add a line containing the quoted string to the start of the file if the file doesn't contain the exact line already.


Next: , Previous: PrependIfNoSuchLine, Up: editfiles

4.17.66 Recurse

     
      Recurse digit/inf
     

For recursive descents when editing whole file trees.


Next: , Previous: Recurse (editing), Up: editfiles

4.17.67 ReplaceLineWith

     
      ReplaceLineWith quoted-string
     

Replace the line at the current position with the text in the quoted string. The file pointer remains pointing to this line after the change.


Next: , Previous: ReplaceLineWith, Up: editfiles

4.17.68 ReplaceAll/With

     
      ReplaceAll quoted-regex With quoted-string
     

Replace all instances of strings matching the regular expression in the first quotes with the exact string in the second set of quotes, throughout the current file. Note that cfengine matches on a left to right basis, with the first match taking precedence, so if your regular expression matches text ambiguously it is the first occurrence which is replaced. For example, if you replace ‘cf.*’ with ‘CFENGINE’ and cfengine encounters a line ‘hello cfengine cfengine’, then this will be replaced with ‘hello CFENGINE’ even though two possible strings match the regular expression. On the other hand if the expression is not ambiguous, say replacing ‘cfengine’ with ‘CFENGINE’, then the result would be ‘hello CFENGINE CFENGINE’.

4.17.69 ReplaceFirst/With

     
      ReplaceFirst quoted-regex With quoted-string
     

For each line of the current file, replace the first string matching the regular expression in the first quotes (quoted-regex) with the string given in the second set of quotes (quoted-string). Matching is done left to right. For example, if you replace ‘``YY = [[:digit:]][[:digit:]]''’ with ‘``YY = 04''’ and cfengine encounters ‘``YY = 03 but old YY = 70''’ then it will be replaced with ‘``YY = 04 but old YY = 70''


Next: , Previous: ReplaceFirst, Up: editfiles

4.17.70 ReplaceLinesMatchingField

     
     ReplaceLinesMatchingField quoted-number
     

This command replaces any lines in the current file with the current line set by SetLine or ForEachLineIn, if the lines are split into fields (e.g. the password file) separated by the SplitOn character (':' by default), and the corresponding fields match.

The idea behind this command was to be able to override global passwords (from a file which gets distributed) by new passwords in a local file. Rather than maintaining the files separately, this simply overrides the entries with the new ones.

4.17.71 Repository editfiles

     
     Repository quoted string
     

This allows a local override of the Repository variable, on an item by item basis. If set to “off” or “none” it cancels the value of a global repository.

See copybackup. See Backup in editfiles.


Next: , Previous: Repository, Up: editfiles

4.17.72 ResetSearch

     
      ResetSearch quoted-string
     

Sets the current-position pointer to the line number in the quoted string. ‘EOF’ indicates the end of the file.


Next: , Previous: ResetSearch, Up: editfiles

4.17.73 RunScript

     
     RunScript quoted-string
     

Executes the named script command. Before executing the script any edits are saved to disk. After the script has executed, cfengine reloads the file for any further editing operations. The script (which may be any executable program) is appended with two arguments: the name of the file which is being edited and the system hard class (e.g. sun4, ultrix etc.) of the system executing the script.

CAUTION: cfengine knows nothing about the success or failure of anything that is done during the execution of user scripts. This feature is to be used at the users own peril!


Next: , Previous: RunScript, Up: editfiles

4.17.74 RunScriptIfLineMatching

     
     RunScriptIfLineMatching quoted-string
     

Executes the script named with the SetScript command only if the current file contains a line matching the quoted regular expression.

CAUTION: cfengine knows nothing about the success or failure of anything that is done during the execution of user scripts. This feature is to be used at the users own peril!

4.17.75 RunScriptIfNoLineMatching

     
     RunScriptIfNoLineMatching quoted-regex
     

Executes the script named with the SetScript command if the current file contains no line matching the quoted regular expression.

CAUTION: cfengine knows nothing about the success or failure of anything that is done during the execution of user scripts. This feature is to be used at the users own peril!

4.17.76 SetCommentStart

     
      SetCommentStart quoted-string
     

Specify which string should be used for starting a comment using the commands CommentLineMatching and CommentLineStarting. The default is the hash symbol ‘#’ followed by a single space.


Next: , Previous: SetCommentStart, Up: editfiles

4.17.77 SetCommentEnd

     
      SetCommentEnd  quoted-string
     

Specify which string should be used for ending a comment using the commands CommentLineMatching and CommentLineStarting. The default is the empty string. For example, you could make C style comments by setting CommentStart to ‘/*’ and comment end to ‘*/’.


Next: , Previous: SetCommentEnd, Up: editfiles

4.17.78 SetLine

     
      SetLine quoted-string
     

Sets a current line value which can be appended using AppendIfNoLineMatching using a regular expression.


Next: , Previous: SetLine, Up: editfiles

4.17.79 SetScript

     
      SetScript quoted-string
     

Sets the name of a user-supplied script for editing the current file.


Next: , Previous: SetScript, Up: editfiles

4.17.80 SlashCommentLinesContaining

     
       SlashCommentLinesContaining quoted-string
     

Add a ‘//’ to the start of any line containing the quoted string.

4.17.81 SlashCommentLinesMatching

     
       SlashCommentLinesMatching quoted-regex
     

Add a ‘//’ to the start of any line exactly matching the quoted regular expression.


Next: , Previous: SlashCommentLinesMatching, Up: editfiles

4.17.82 SlashCommentLinesStarting

     
       SlashCommentLinesStarting quoted-string
     

Add a ‘//’ to the start of any line starting with the quoted string.


Next: , Previous: SlashCommentLinesStarting, Up: editfiles

4.17.83 SplitOn

     
      SplitOn quoted-string
     

This defines a single character which is to be interpreted as a field separator for editing files with columns. The default value for this is ‘:’, as is used in the password and group files. It is used in conjunction with ReplaceLinesMatchingField. Note, be careful not to confuse this with the EditSplit character.


Next: , Previous: SplitOn, Up: editfiles

4.17.84 Syslog editfiles

Set to true or false, on or off to set inform level for this file. Default is off.

     
     Syslog quoted-string
     


Next: , Previous: SysLog, Up: editfiles

4.17.85 Umask

     
      quote mode
     

Set local umask for file creation and script execution.


Next: , Previous: Umask, Up: editfiles

4.17.86 UnCommentLinesContaining

      UnCommentLinesContaining  quoted-string
     

Uncomment all lines in file containing the quoted string as a substring. The comment delimiters are assumed to be those set using SetCommentStart and SetCommentEnd.

4.17.87 UnCommentLinesMatching

     
     UnCommentLinesMatching  quoted-regex
     

Uncomment all lines in file matching the quoted regular expression. The comment delimiters are assumed to be those set using SetCommentStart and SetCommentEnd.

4.17.88 UnCommentNLines

     
      UnCommentNLines quoted-string
     

Uncomments N lines starting from the current position, using the currently defined method for commenting. Note that the comment start and end symbols are removed independently, i.e. they are not matched, so that a comment may be spread over several lines. e.g. If using C style ‘/*’ and ‘*/’ comments, the command UnCommentNLines "3" would uncomment

      /* 1 */
      /* 2 */
      /* 3 */

and also

      /* 1
         2
         3 */


Next: , Previous: UnCommentsNLines, Up: editfiles

4.17.89 UnCommentToLineMatching

     
     UnCommentToLineMatching quoted-string
     

Uncomments from the current position up to and including the first line matching the named regular expression.


Next: , Previous: UnCommentToLineMatching, Up: editfiles

4.17.90 UnsetAbort

Switches off the feature AbortAtLineMatching.

     
      UnsetAbort  quoted-string
     


Next: , Previous: UnsetAbort, Up: editfiles

4.17.91 UseShell

Normally cfengine uses a shell based exec function to run scripts during editing. This involves the inheritance of environment variables and path, which carries with it an inherent security risk. Setting this value to false causes execution to execute without an encapsulating shell.


Next: , Previous: UseShell, Up: editfiles

4.17.92 WarnIfFileMissing

If the file to be edited does not exist, a visible alert is issued.

     
       WarnIfFileMissing quoted-string
     

4.17.93 WarnIfLineContaining

Issue a warning if the quoted string is found as a substring of one or more lines in the file.

     
        WarnIfLineContaining quoted-string
     

4.17.94 WarnIfLineMatching

     
       WarnIfLineMatching quoted-regex
     

Issue a warning if the quoted regular expression matches one or more lines in the file.

4.17.95 WarnIfLineStarting

     
       WarnIfLineStarting quoted-string
     

Issue a warning if the quoted string matches the start of one or more lines in the file.

4.17.96 WarnIfNoLineContaining

     
       WarnIfNoLineContaining quoted-string
     

Issue a warning if the quoted string is not contained in one or more lines in the file.

4.17.97 WarnIfNoLineMatching

     
       WarnIfNoLineMatching reg-ex
     

Issue a warning if the quoted regular expression does not match one or more lines in the file.

4.17.98 WarnIfNoLineStarting

     
     WarnIfNoLineStarting quoted-string
     

Issue a warning if the quoted string is not found at the start of one or more lines in the file.


Previous: WarnIfNoLineStarting, Up: editfiles

4.17.99 WarnIfNoSuchLine

     
     WarnIfNoSuchLine quoted-regex
     

Issue a warning if the quoted regular expression does not match one or more lines in the file.


Next: , Previous: editfiles, Up: Cfagent reference

4.18 Editfiles on Binary Files

A limited number of operations can also be performed on purely binary files, e.g. compiled programs, in order to search for strings or viral code, or to modify strings within a program. Binary mode is a mutually exclusive, separate mode to normal editing. The limit on the size of binary files is set by editbinaryfilesize in control.

  • ReplaceAll regex With literal

    Replaces occurrences of the matched regular expression with\ the provided literal text, only if the length of the literal substitute is less than or equal to the length of the located string. If the replacement string is shorter, it is padded with ascii spaces (character 32) by default. The padding character can be changed by setting BinaryPaddingChar in control. Padding with a null byte would lead to corruption of text within a program.

  • WarnIfContainsString regex/literal Yields a warning if the literal string or regular expression matches. Cfengine first attempts a literal match and then a regular expression match.
  • WarnIfContainsFile filename Yields a warning if the contents of the named file exactly match part of the file which is being edited. This can be used to search for binary data which cannot be typed directly into the cfengine program, e.g. virus signatures.

4.19 files

The files facility allows you to touch (create), check for the existence, owner and permissions of files, change the permissions and test for setuid root programs.


Next: , Previous: files, Up: files

4.19.1 Syntax

A files-statement can have several options. We can begin by examining the form of the statement in pseudo-code:

       files:
     
          classes::
     
             /file-object
                               mode=mode
                               owner=uid-list
                               group=gid-list
                               action=fixall/other-options/warnall
                               links=false/stop/traverse/follow/tidy
                               rxdirs=true/on/false/off
     
                               ignore=pattern
                               include=pattern
                               exclude=pattern
                               filter=filter alias
                               xdev=true/on/false/off
     
                               define=classlist
                               elsedefine=classlist
     
                               checksum=md5/sha/best
                               syslog=true/on/false/off
                               inform=true/on/false/off
     
                               audit=true/on/false/off
     
                               ifelapsed=mins
                               expireafter=mins
     
          Special OS flags:
                               flags=BSD flags
     
     

An example would be the following:

        any::
     
           /var/spool/printQ  mode=0775  r=0 o=daemon g=daemon  act=fixdirs
     

The meaning of these item is sketched out below and becomes clearer on looking at a number of examples. Note that, each of the options below can be written in either upper or lower case and abbreviated by any unique abbreviation.

/file-object
This is the only obligatory part of a file action. This may be a single file or a directory. If it is a directory then it indicates where does the file search should begin. The recursion specifier may be used to force cfengine to descend into subdirectories in a controlled fashion, starting from this point, checking files there also. The wildcard home may also be used. See home directive.

A file object is interpreted as a directory if you write it in the following form: /directory-path/.. i.e. a trailing dot signifies a directory. This then becomes the same as the directory command.

mode=modestring
Specifies what the allowed permissions for files are. If cfengine finds that a file's mode is incorrect, the value of the action option determines what will be done about it. The modestring should consist of either a three digit octal numbers with ‘+’, ‘-’ or ‘=’ symbols, or a text string like that used by the command chmod. For instance: mode=u=rwx,og+rx would mean set the read/write and execute flags for the user (file owner) and add the read/execute flags for others and group bits. An example of the numerical form might be -002 which would mean that the read-for-others flag should either not be set or should be unset, depending on the action you choose. +2000 would mean that the setgid flag should be present or set, depending on the action. +2000,-002 would be a combination of these. The ‘=’ sign sets to an absolute value, so =755 would set the file mode to mode 755.
flags=BSD flags
The free BSD Unices have additional filesystem flags which can be seton files. Refer to the BSD chflags documentation for this. For example,
          
             /tmp/flags.01  mode=0600 owner=0 group=0
                            flags=uappnd,uchg,uunlnk,nodump,opaque,sappnd,schg,sunlnk
                            action=touch
          
          

recurse=number/inf
This specifier tells cfengine whether or not to recurse into subdirectories. If the value is zero, only the named file or directory is affected. If the value is 1, it will open at most one level of subdirectory and affect the files within this scope. If the value is inf then cfengine opens all subdirectories and files beginning from the specified filename.See Recursion.
owner=owner list
This is a list of allowed owners, or uids by number, separated by commas. For example root,2,3,sysadm. In cases where you ask cfengine to fix the ownership automatically, the owner will be set to the first recogized owner in the list if and only if it is not one of the named uids in the list.
group=group list
This is a list of allowed groups, or gids by number, separated by commas. For example wheel,2,3,sysadm. In cases where you ask cfengine to fix the ownership automatically, the group will be set to the first recognized group in the list if and only if it is not one of the named gids in the list.
action=action
The action is one of the following keywords.
          warnall warndirs warnplain
           fixall fixdirs fixplain
          touch linkchildren create compress alert

The upper line results only in warnings being issued. The actions beginning `fix' prompt cfengine to fix encountered problems without bothering the user. No message is issued unless in verbose mode. The special features on the third line will be explained separately. Alert is like -print in the find command, it triggers on the existence of files which have not been ignored, excluded or filtered. This should normally be used together filter, in order to locate files of particular types.

include=wildcard/pattern
You can include this option several times to specify specific patterns which are to be included in the search. Once you specify one pattern you exclude all files not matching at least one of the patterns. The case be useful for restricting a search, or for modifying the permissions of only certain files.
exclude=wildcard/pattern
You can include this option several times to specify specific patterns which are to be excluded from the search. This overrides any patterns given in the include= list.
ignore
This works like the global ignore directive but here you may provide a private list of ignorable directories and files. Unlike include, exclude this affects the way cfengine parses directory trees.
links=stop/traverse/tidy
Normally cfengine does not descend into subdirectories which are pointed to by symbolic links. If you wish to force it to do so (without using the -l command line option) you may give this option the value true, or traverse, or follow. To specify no recursion you set the value false or stop. Note that the value set here in the cfengine program always overrides the value set by the -l command line option, so you can protect certain actions from this command line option by specifying a negative value here. If you specify no value here, the behaviour is determined by what you specify on the command line.

The value links=tidy has the same effect as the ‘-L’ command line option except that here it may be specified per item rather than globally. Setting this value causes links which point to non-existent files to be deleted. If the warn directive is used (for directories, plain files or both) then only a warning message is issued if the file being tested does not match the specification given. If the fix directives are used then cfengine does not issue a warning, it simply fixes the value silently. Non-existent files are created by the touch command. A directory may be touched (created) by writing the filename /a/b/c/. with a dot as the last character. (This may also be achieved with the directories directive, See directories.)

define=classlist
If a file operation results in action being taken to fix a file, the colon, comma or dot separated list of classes becomes defined. Warnings do not activate the classes.
checksum=md5/sha/best
If set this option causes cfengine to add a checksum for the named file to a database. Changes in the value of this checksum are then warned as a security issue. This should normally only be used to monitor binary files which one would not expect to change often. Note also that the use of this option can mean a significant performance penalty. If the value best is used for this option then the best known pair of checksum methods are cross-checked for each file. (The best value are determined by the algorithms supported in the OpenSSL interfaces used to compile the program).

If ChecksumUpdates is set, then security warning messages are issued only once and the value in the database is then changed to the new value of the file automatically i.e. the behaviour is similar to that of setuid root program detection, See ChecksumPurge. Also, See ChecksumUpdates.

xdev
Prevents cfengine from descending into file systems that are not on the same device as the root of the rescurion path.
rxdirs
If true (the default) cfengine assumes that a directory that is readable should also have its execute flag set, allowing users to enter it and perform directory browsing. If false, cfengine will not make this assumption. Note that if set to false, it will affect recursive file checks. Thus setting to false with mode=644 recurse=true could lead to unintended permissions on directories.

The default values are mode=+000, recurse=0, action=warnall and any owner or group is acceptable. The default for links is to not traverse links unless the -l option is set on the command line.


Next: , Previous: Syntax, Up: files

4.19.2 Recursion

The recursion specifier tells cfengine what to do, starting from /directory name. A value of r=0 means `no recursion' and any checking is limited only to the named file or directory. A value of r=inf implies unlimited recursion. Cfengine then descends into all subdirectories checking or setting the permissions of files until it `bottoms out' at a plain file. A value such as R=4 means descend recursively into subdirectories, but no more than four levels. This is a useful safety net in preventing unforeseen accidents. A recursive search also bottoms out on device boundaries and symbolic links (provided the -l option is not used).

4.19.3 Directory permissions

When you specify the permissions for a whole file tree, using the recursion specifier it is awkward to have to remember that directories must be executable. cfengine will do this for you automatically. If you specify that a file tree is to have a read flag set, cfengine will ensure that the corresponding execute flag is also set for directories which live in the tree. So the command

     files:
     
       myclass::
     
           /dir  mode=a+rw r=inf fixall
     

would set all plain files to mode 644 and all directories to 755, that is read/write for everyone on plain files and read/write/execute for everyone on directories.


Next: , Previous: Directory permissions, Up: files

4.19.4 Checksums and change management

Integrity checks are a good way of detecting tampering with a system, or simply for monitoring upgrades that happen as a result of software unrelated to cfengine. The checksum option asks cfengine to compute and cache the value of the cryptographic checksum of the named file.

     files:
     
       /my/file
     
        checksum=best
        action=warnall
     

The checksum type can be md5, sha or best. The option best cross checks the best two available algorithms. At present cfengine is waiting for improvements to the OpenSSL library supporting sha2 algorithms.

Once a value has been computed and placed in the database each new computation will be checked against the old one. Any change will lead to a mismatch and the following will happen:

  • A warning is printed about the change
  • As of 2.2.8 a class called checksum_alerts will be defined, indicating that a change has occurred. This can be used to trigger followup actions. The class is a persistant class that lasts for 60 minutes.
  • If ChecksumUpdates is set to true, the new value will replace the old in the database

4.19.5 home directive

If you want to check the files of all the users who have their login areas on the current host, you can use a wildcard directive home instead of a directory name. In this case the file action iterates over all home directories physically on the current host. The home directories are, of course, located by searching for files which match

     $(mountpattern)/$(homepattern)

i.e. the values which are specified in the control part of the program. For example the following line is a very useful service to ignorant users.

     files:
     
       any::
     
         home mode=o-w r=inf act=fixall
     

It ensures automatically that no user has files which can be written to by other arbitrary users.

As a corollary to this, you may write something like

     
       any::
     
          home/www mode=a+r fixall
     

to specify a special subdirectory of every users' home directory. This statement would check that all of the files in users' world wide web directories were readable for everyone.


Next: , Previous: home directive, Up: files

4.19.6 Owner and group wildcards

If you do not want to explicitly state the owner or group of a file you may simply omit the group or owner options.

     
       /file-object m=0664 r=inf
     

This example generate a warning if any files under the named directory do not have permission read/write for all users.


Next: , Previous: Owner and group wildcards, Up: files

4.19.7 Files linkchildren

The linkchildren facility is almost identical to that already described under links. See Link Children. The only difference here is that the ownership and permissions on the links are set all in one operation. For example:

     myclass::
     
        /local/lib/emacs m=0770 o=me g=mygroup act=linkchildren
     


Next: , Previous: Files linkchildren, Up: files

4.19.8 touch

The touch facility creates a new file with the specified permissions and ownership, or corrects the permissions and ownership of an existing file, in addition to updating the time stamps.

     myclass::
     
        /newfile mode=0644 action=touch
     


Previous: touch, Up: files

4.19.9 create

This is like touch except that an existing file's time stamps, permissions and ownership will not be modified if the file already exists. If the file does not exist, the attributes are set to the values specified, or to the default values of 0644.


Next: , Previous: files, Up: Cfagent reference

4.20 filters

A filter is a way of selecting or pruning during a search over files or processes. Since filter rules could apply to several objects, cfengine allows you to define filter conditions as separate objects to be applied in different contexts.

Filter objects can be used in copy, editfiles, files, tidy and processes. In most cases one writes

     .. filter=<i>filteralias</i>

in the appropriate command. The exception is editfiles, where the syntax is

     {
     ..
     Filter "filteralias"
     ..
     }

Example:

     
     files:
     
      /tmp filter=testfilteralias action=alert r=inf
     

Filters are defined in a separate section. Filters for files and processes are defined together. They differ only in the criteria they contain. Here is are examples of file filters:

     Filters:
     
       { filteralias1
     
       Owner:     "mark|cell|motd"
       Group:     "ecg|mark"
       Mode:      "700"
     
       FromCtime: "date(2000,1,1,0,0,0)"    # absolute date
       ToCtime:   "now"
     
       FromMtime: "tminus(1,0,0,2,30,0)"    # relative "ago" from now
       ToMtime:   "inf"                     # end of time
     
       FromAtime: "date(1997,2,22,0,0,0)"
       ToAtime:   "inf"
     
       FromSize:  "10000"                   # File size interval
       ToSize:    "10mb"
     
       ExecRegex: "/usr/bin/file $(this) (.*ascii.*)"# Result from "files" command
     
       Type:      "dir|link"                # reg|link|dir|socket|fifo|door|char|block
     
       NameRegex: ".*.asc"                  # regex matching file name
     
       IsSymLinkTo: "/dev/null"             # True if file is a link to object name regex
     
       Result:    "Type"                    # Result which shouldbe returned
     
       }
     
      #########################################
     
       { testfilteralias2
     
       ExecProgram: "/bin/ls $(this)"       # True if the program returns true. $(this) is the current object
       }
     
      #########################################
     
       { testfilteralias3
     
       Owner: "mark"
       }

Filters are evaluated like classes. In fact, the filtering works by evaluating the class attributes for each file.

File filters:

Owner:
and Group can use numerical id's or names, or ``none'' for users or groups which are undefined in the system passwd/group file.
Mode: applies only to file objects. It shares syntax with the mode= strings in the files command. This test returns true if the bits which are specified as `should be set' are indeed set, and those which are specified as `should not be set' are not set.
Atime:,Ctime:,Mtime:
apply only to file objects. These specify ranges From and To. If the file's time stamps lie in the specified range, this returns true. Times are specfied by a six component vector
          (year,month,day,hour,minutes,seconds)

This may be evaluated as two functions: date() or tminus() which give absolute times and times relative to the current time respectively. In addition, the words now and inf may be used. e.g.

            FromCtime: "date(2000,1,1,0,0,0)"   # absolute date
            ToCtime:   "now"
          
            FromMtime: "tminus(1,0,0,2,30,0)"     # relative "ago" from now
            ToMtime:   "inf"                     # end of time

Type:
applies only to file objects may be a list of file types which are to be matched. The list should be separated by the OR symbol `|', since these types are mutually exclusive. The possible values are currently
          file|reg|link|dir|socket|fifo|door|char|block

Note that file and reg are synonymous.

ExecRegex:
matches the test string against the output of the specified command.
NameRegex:
matches the name of the file with a regular expression.
IsSymLinkTo:
applies only when the file object $(this) is a symbolic link. It is true if the regular expression matches the contents of the link.
ExecProgram:
matches if the command returns successfully (with return code 0). Note that this feature introduces an implicit dependency on the command being called. This might be exploitable as a security weakness by advanced intruders.
Result:
specifies the way in which the above elements are combined into a single filter.

Process filters:

Owner
process owner UID (quoted regex)
PID:
process ID (quoted regex)
PPID:
parent process ID (quoted regex)
PGID:
process group ID (quoted regex)
RSize:
resident size (quoted regex)
VSize:
virtual memory size (quoted regex)
Status:
status (quoted regex)
Command:
CMD or COMMAND fields (quoted regex)
(From/To)TTime:
Total elasped time in TIME field (accumulated time)
(From/To)STime:
Starting time for process in STIME or START field (accumulated time)
TTY:
terminal type, or none (quoted regex)
Priority:
PRI or NI field (quoted regex)
Threads:
NLWP field for SVR4 (quoted regex)
Result:
logical combination of above returned by filter (quoted regex)
Examples: processes started between 18th Nov 2000 and now.
       { filteralias
     
       FromSTime: "date(2000,11,18,0,0,0)"
       ToSTime:   "now"
       }

All processes which have accumulated between 1 and 20 hours of CPU time.

       { filteralias
     
       FromTTime:  "accumulated(0,0,0,1,0,0)"
       ToTTime:    "accumulated(0,0,0,20,0,0)"
       }


Previous: filters, Up: filters

4.20.1 Complete filter examples

Here is an example filter to search for all files which are either directories or links, or any kind of file owned by mark, in group cfengine.

     
     control:
     
      actionsequence = ( files )
     
     files:
     
      /tmp       filter=testfilteralias action=alert r=inf
      /cfengine  filter=testfilteralias action=fixall r=inf mode=644
     
     filters:
     
       { testfilteralias
     
       Owner:     "mark"
       Group:     "cfengine"
       Type:      "dir|link"
     
       Result:    "Type|(Owner.Group)"  # Both owner AND group required correct
       }
     

Find all ELF executables using data from the Unix file command. Caution, this takes a long time if used indescriminately.

     
     control:
     
      actionsequence = ( files )
     
     files:
     
      /tmp       filter=testfilteralias action=alert r=inf
      /cfengine  filter=testfilteralias action=fixall r=inf mode=644
     
     filters:
     
       { testfilteralias
     
       ExecRegex: "/bin/file (.*ELF.*)"
     
       Result: "ExecRegex"
       }

Here is an example which warns of any process coupled to a terminal started in November:

     control:
     
      actionsequence = ( processes )
     
     filters:
     
       { filteralias
       FromSTime: "date(2000,11,0,0,0,0)"
       ToSTime:   "date(2000,11,30,0,0,0)"
       TTY: ".*pt.*"
       Result: "TTY.STime"
       }
     
     processes:
     
      "." filter=filteralias action=warn
     


Next: , Previous: filters, Up: Cfagent reference

4.21 groups/classes

The groups action (equivalently referred to as classes as of version 1.4.0) is used to define classes which stand for groups of hosts. If you use the NIS (network information service) facility for defining netgroups then this idea will already be familiar to you and you can probably use your already-defined netgroups in cfengine. To define a group, you simply make a list and assign it a name. Here is an example of the syntax:

     
     groups:
     
       ANDed_class::
     
         science = ( saga tor odin )
     
         packages = ( saga )
     
         AllHomeServers   = ( saga )
         AllBinaryServers = ( saga )
     
         OIH_servers = ( saga )
         OIH_clients = ( tor odin )
     
         notthis = ( !this )
     
         ip_in_range = ( IPRange(129.0.0.1-15) )  # host is in ip address range
         ip_in_range = ( IPRange(129.0.0.1/24) )  # host is in ip address range (CIDR notation)
     
         compute_nodes = ( HostRange(cpu-,1-32) ) # host name in the cpu-01 through cpu-32 range
     

To include a list of hosts from a NIS netgroup, you use the ‘+’ symbol, or the ‘+@’ construction. For example:

     
     groups:
     
        science = ( +science-allhosts )
     
        physics = ( +physics-allhosts )
     
        physics_theory = ( +@physics-theory-sun4 dirac feynman schwinger )
     

Using an enormous netgroup does not use up any space. A group declaration results in the storage of only the class name regardless of how many hosts are in the list. The rule is that the left hand side of the assignment becomes defined (true) if the list on the right hand side includes the host which is parsing the file — i.e. $(host).

In some cases your netgroups will not correspond exactly to the list you want, but it might be more convenient to use a netgroup except for certain hosts. You can `undefine' or remove hosts from the netgroup list by using the minus `-' symbol. For example:

     
     group = ( +mynetgroup -specialhost -otherhost )
     

which means, of course, all hosts in netgroup mynetgroup except for specialhost and otherhost. Finally, you may also subtract two netgroups in the following manner.

     group = ( +bignetgroup -smallnetgroup )

The `minus' command effectively eliminates its members from bignetgroup if they exist within that group. If none of the hosts in smallnetgroup exist in bignetgroup then the command has no effect.

Groups may contain previously defined cfengine groups too. This allows one class to inherit the attributes of another class, for instance:

     
       AllSun4Hosts   = ( sonny sunny solar stella )
       AllUltrixHosts = ( ully olly wally golly )
     
       AllBSD = ( AllSun4Hosts AllUltrixHosts )
     

The classes on the right hand side are effectively ORed together into the left hand side. This enables complex classes to be constructed from several other basic classes, e.g.

     
       SpecialTimes = ( Hr00 Monday Day1 )
     

which evaluates to true every day when it between 00:00 hours and 00:59, all day Monday and all day on the first day of every month.

If you apply a class predicate before a definition then the result is effectively the AND of the classes:

     
      Hr00::
     
       SpecialTime = ( Monday Tuesday )
     

defines SpecialTime at Hr00 on Monday or Tuesday.

Finally, you can define groups (strictly classes) by the result of a shell command. A shell command or program is deemed to be `true' if it exits with a status of zero, i.e. it calls exit(0). Any other value is taken to be false. You can include shell commands as the members of groups in order to define classes based on the outcomes of your own scripts by enclosing the script in single or double quotes:

     
        have_cc = ( '/bin/test -f /usr/ucb/cc' )
     

The class have_cc will then be defined if the shell command returns true. Of course, you can put any script or program in the single quotes as long as they adhere to the convention that zero exit status means true. If you have several members which are shell commands, then the effect is to make the class the logical OR of the scripts' results.


Next: , Previous: groups, Up: Cfagent reference

4.22 homeservers

The homeservers declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of which other hosts on the network possess filesystems containing home directories (login areas) which client hosts should mount.

A sample homeserver declaration looks like this:

     
     homeservers:
     
        Physics::  einstein
        Math::     riemann euler
     

The meaning of this declaration is the following. Any host which finds itself to be a member of the classes on the left hand side of the assignment need to mount all home directory resources from the hosts on the right hand side of the assignment. The pattern variable homepattern is used to determine which resources are home directories in the list of mountables. See mountables.

Let us consider an example in which homepattern is set to the wildcard value ‘home?’ and the mountables list is given by

     mountables:
     
        einstein:/mysite/einstein/home1
        einstein:/mysite/einstein/home2  mountoptions=soft,bg,intr,rsize=8192,wsize=8192
        riemann:/mysite/riemann/local    readonly=true
        euler:/mysite/euler/home1
     

Any host in the group Physics would now want to mount all home directories from the host einstein. There are two of these. Both the filesystems listed for einstein match the homepattern variable since they end in ‘home?’. cfengine would therefore take this to mean that all hosts in Physics should mount both of these filesystems.

Hosts in Math, on the other hand, should mount only homedirectories from the hosts riemann and euler. There is only a single filesystem on riemann and it does not match homepattern, so it is not mounted. On euler there is a match, so this filesystem will be added to the appropriate hosts.

Cfengine picks out home directory resources from the mountables list by trying to match the homepattern variable, starting from the end of the directory name. You do not therefore have to use the designation /site/host/home? but this is a simple choice and is highly recommended.


Next: , Previous: homeservers, Up: Cfagent reference

4.23 ignore

When you specify a recursive search as part of a files, tidy or copy action, you would sometimes like to exclude certain directories from the list of sub directories. In most cases you will want to do this on a per-command basis (see the pages for these actions separately), but you can also make a global ignore list. This can be accomplished by adding the directory to the ignore-list. The syntax is

     
       ignore:
     
          wildcards/directories/filenames
     

For example:

     
     ignore:
     
        any::
     
           #
           # Prevent tidying .X11 directories in /tmp where
           # window managers write semaphores
           #
     
           .X11
     
           #
           # Don't tidy emacs locks
           #
     
           !*
           /local/lib/gnu/emacs/lock/
           /local/tmp
           /local/bin/top
           /local/lib/tex/fonts
           /local/etc
           /local/www
           /local/mutils/etc/finger.log
     
     

None of the above directories will be checked or entered during recursive descents unless a specific command is initiated to search those directories with their names as the top of the search tree. A handy tip if you are tidying /tmp recursively is to include the directory .X11 here. This directory is used by the X-windows system and deleting it while a window manager has an open session can cause the user some trouble.

Ignore refers to all recursive searches in tidy, files, copy and links.


Next: , Previous: ignore, Up: Cfagent reference

4.24 import

To break up a large configuration file into smaller files you can use the include directive. This conditionally reads in files if the class on the left hand side of the assignment matches the host parsing the file. This enables also a variety of cfengine configuration scripts to read in a standard set of default settings. The syntax of the statement is:

     
     import:
     
        any::
     
           cf.global_classes
     
     
        linux::
     
           cf.linux_classes
     
     

Note that, if you define variables in an imported file they will not be defined for operations in their parent files. This because cfengine reads in all the import files after the main file has been parsed—not at the place where you call import in your script. This means that variables or macros defined in imported files are only defined after the main program. Variables from earlier files are inherited by later includes, but not vice-versa.


Next: , Previous: import, Up: Cfagent reference

4.25 interfaces

     
      interfaces:
     
        classes::
     
          interfacename netmask=netmask broadcast=broadcast
     

If you have more than one network interface, or you do not wish to use the default interface name, this section may be used to define further interfaces to be checked. This feature can replace the older method of setting netmask and broadcast address in control:. If the netmask variable is not set, cfengine ignores the default interface configuration. Example:

     
       interfaces:
     
         "le1" netmask=255.255.255.0 broadcast=ones
         "le2" netmask=255.255.255.0 broadcast=ones
     


Next: , Previous: interfaces, Up: Cfagent reference

4.26 links

The symbolic links function is one of the greatest plusses in cfengine as a system administration tool. It allows you to do two things: check single links for correctness and consistency (or make them if they do not exist), and check or make links to every file in a designated directory. This latter feature is called multiple linking or linking children. The linkchildren feature is also available from the files action See files. The syntax of a link item is:

     
       from-link ->[!] to-object
      or
       from-link +>[!] to-object
     
                 type=symbolic/absolute/abs/hard/relative/rel
                 copy=pattern
                 recurse=number/inf/0
                 copytype=checksum/ctime
                 include=pattern
                 exclude=pattern
                 ignore=pattern
                 action=silent
                 deadlinks=kill/force
                 define=classlist
                 nofile=kill/force
                 syslog=true/on/false/off
     
                 inform=true/on/false/off
                 audit=true/on/false/off
     
                 ifelapsed=mins
                 expireafter=mins

The special variable $(binserver) can be used in links.


Next: , Previous: links, Up: links

4.26.1 Single links

To define a single link, you create an entry of the following form:

     
     links:
     
       class::
     
          linkname -> object_to_link_to
          linkname -> ./relative_link
          linkname -> ../relative_link
     

If links exists and point to their intended destinations then no action is taken. If a link exists but points incorrectly then a warning is issued, unless the pling operator ‘!’ is given, in which case the correct value is forced. If the link exists and points to a file which does not exist a warning is issued unless the command line option -L is used, in which case the link is deleted. Here is an example of some valid link statements.

     
     links:
     
       Physics.sun4::
     
        /usr/local       -> /$(site)/$(host)/local
        /home            -> /$(site)/$(host)/u1
        /etc/sendmail.cf -> /usr/local/mail/etc/global-sendmail.cf
     
        /usr/lib/sendmail ->! /local/lib/sendmail
     

cfengine makes any directories which are required leading up to the link name on the left hand side of the arrow automatically. In the last example the `pling' forces cfengine to make the link even if a file for link exists previously. Plain files are saved by appending .cfsaved to the filename, or by moving to a repository, whereas old links are removed. The same effect can be enforced globally using the -E option, but only if the program is run interactively. (In this case a prompt is issued to make sure that you wish to use such a big hammer on your system!)

The link operation accepts a number of parameters

type=hard/relative/absolute
If the link type is hard, a hard link is created See Hard links. Symbolic links may specify two special types. If relative is selected, and the `to' object is an absolute path name, the link name will be rewritten as a pathname relative to the source file, using ‘.’ and ‘..’ to move relative to the current directory. For instance, a link from /usr/local/file to /usr/file would be linked as ./../file. If the `to' object is already relative, this has no effect.

If absolute is specified, cfengine will try to resolve the true path location of the `to' object, expanding any symbolic links or dots in the path name, up to a maximum of four levels of symbolic links.


copy=pattern
This option can be repeated any number of times to build up a list of filenames or wildcards which are to be copied rather than linked symbolically. The copy is made on an age-comparison basis. A global variable may also be set to invoke this feature See copylinks. Directories cannot be copied in this way.
copytype=checksum/ctime
This specifies the basis for deciding whether to update a file which is to be copied instead of linked See copy.
nofile=kill/force
This decides what happens to links which point to non-existent files. The default action is to remove such links, or refuse to create them. By setting the force option you can force cfengine to make symbolic links to files which do not exist. This is useful for setting up links to filesystems which are not permanently mounted.
exclude=pattern
This option can be repeated any number of times to build up a list of filenames or wildcards which are to be excluded from the linking process. A global variable may also be set to invoke this feature See excludelinks.
ignore
This works like the global ignore directive but here you may provide a private list of ignorable directories and files. Unlike include, exclude this affects the way cfengine parses directory trees.
recurse=number/inf
This option can only be used with multiple link operations See Multiple Links. If this option is specified, cfengine links only non-directory objects. Directories are instead created and links within those directories are also created. The value of this option specifies the maximum number of levels to which cfengine should recursively descend a link tree. inf means infinite recursion. Cfengine also ignores files and directories in the ignore list See ignore.
define=classlist
If a link is created or replaced, the colon, comma or dot separated list of classes becomes defined.

The final feature of the links facility is connected to the use of the cfengine model for mounting NFS filesystems. In particular it concerns the variable $(binserver). The easiest way to understand this feature is to illustrate a couple of examples. Consider the following:

     links:
     
        any::
     
           /local -> /${site}/${binserver}/local
     

The result of this command is quite different depending on which host is executing it. The variable $(site) clearly has a fixed value, but the variable $(binserver) might expand to any valid binary server for the host executing the program. See binservers. The procedure cfengine adopts is to go through its list of mountables, keeping only those mountable resources which belong to defined binary servers for the current host. It then attempts to match a filesystem by substituting $(binserver) with each of its valid binservers in turn and it matches the first one binary server which yields an existing file.

Note that every host is a binary server for itself, so that the value of $(binserver) which has absolute priority is alway the same as the value of $(host). This ensures that the link will always be made to a local filesystem if the rules of the model are upheld.


Next: , Previous: Single links, Up: links

4.26.2 Multiple Links

With the link symbol +>, you opt to link all of the files in a directory to corresponding files in another directory. This procedure is sometimes useful for installing software. In the example

     
     links:
     
       myclass::
     
          /usr/local/bin +>  /usr/local/lib/perl/bin
          /opt           +>! /local
     

every file in the directory /usr/local/lib/perl/bin is linked symbolically to a corresponding file in /usr/local/bin. The `pling' character forces cfengine to replace old links or plain files already existing. Old links are removed, whereas old files are saved by appending .cfsaved to the filename See repository. Each time cfengine runs it goes through all of the files in the directory concerned and checks the appropriate link accordingly. If new files appear, new links will be added. If a file disappears but the link to it remains, a warning will be issued, unless the -L command line option is used, in which case the link is deleted.

4.26.3 Link Children

The linkchildren directive is a closely related to the cfengine model for NFS filesystems. It is a way of making links which embodies a rudimentary kind of `intelligence'.

Consider the following:

     links:
     
        any::
     
           /usr/local/lib/emacs +> linkchildren
     

The word linkchildren automatically tells cfengine that it should look for an appropriate file to link to on a binary server for the current host. The exact meaning of the above statement is as follows. cfengine begins searching though the list of mountable resources, discarding any filesystems which do not belong to valid binary servers. It looks for a filesystem ending in `emacs' (the last link of the left hand side). If all is well, these file systems are already mounted and they can be searched. If no resource is found ending in `emacs', we go to the next link lib and look for a filesystem ending in `lib'. If this is not found we go to local and so on. When a match is made, cfengine then tries to locate the file by checking whether it exists relative to the matched filesystem. For example, suppose `local' matched with host:/site/host/local. It would then try to locate host:/site/host/local/lib/emacs and link all of the children therein to the local file directory /usr/local/lib/emacs.

Here is another example which makes reference to the cfengine model for mounting NFS filesystems. Suppose you have a host with some spare disk space. You want to mount /usr/local from the binary architecture server, but you also want to use the disk you have locally. The following lines

     links:
     
        electron::
     
           /$(site)/electron/local +> linkchildren
     
        any::
     
           /usr/local              -> /$(site)/$(binserver)/local
     

have the effect of creating a directory /$(site)/electron/local and filling it with links to all of the files and directories on the binary server's mounted filesystem. It results in an exact copy (by linkage) on the local disk, but does not use up your local disk space. The space you have remaining could, for example, be used for software with a special license for that host. The second link links /usr/local to the `nearest' binary server. But the nearest binary server is always $(host) which means this evaluates to a file which now exists because of the first command, so on the host `electron' the directory /usr/local ends up being a link to /$(site)/electron/local which is full of links to the binary server.

If you've caught your breath after that mouthful you probably have mixed feelings about creating a bunch of links in this way. What happens if the files they point to are removed? Then you are left with a lot of useless links. Actually this is no problem for cfengine, since you can ask cfengine to simply remove links which point to non-existent files See files. Nevertheless, this feature clearly requires some caution and is mainly a spice for advanced users of the cfengine model.


Next: , Previous: Link Children, Up: links

4.26.4 Relative and absolute links

When specifying symbolic linking, you can ask cfengine to change the link type to be either relative to the source or to be an absolute path. What this means is the following. Consider the following link:

     
        /var/tmp/cfengine -> /local/cfengine
     

If we add the option type=relative, then instead of creating a link which points to /local/cfengine, the link is created pointing to the location

       ./../../local/cfengine

In other words, the link is relative to the calling directory /var/tmp.

If a link is specified as being absolute with the option type=absolute, then cfengine attempts to resolve to value of the link so as to be the true path of the target. If the target name contains a symbolic link, then this is expanded as far as possible to give the true path to the file. For example, if /local is really a link to /site/myhost/local then the link would point to /site/myhost/local/cfengine.

4.26.5 Hard Links

Cfengine will also allow you to create hard links to regular files. A hard link is in every way identical to the original file, it merely has a different name (technically, it is a duplicate inode). To create a hard link you use the link-option type=hard. For example:

     
     links:
     
        /directory/newname -> /directory/othername type=hard
     

Cfengine will not create hard links to directories or other special files. This is always a slightly dubious practice and is best avoided anyway. POSIX says that the hard link can be on a different device to the file it points to, but both BSD and System V restrict hard links to be on the same device as their predecessors. Cfengine has no policy on this, but—in the theoretical case in which the hard link and the predecessor were on different file systems—it becomes near impossible to determine with certainly between a hard link and a very similar regular file, and thus cfengine issues a warning in verbose mode about this eventuality. Provided both link and predecessor are on the same filesystem cfengine determines the status of hard links by comparing the device and inode numbers of the file pointed to.


Next: , Previous: links, Up: Cfagent reference

4.27 mailserver

The mailserver declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of which NFS filesystem contains mail for its users. All hosts apart from the mail-host itself must then mount the mail spool directory across the network. The declaration looks like this:

     
     mailserver:
     
        class::      mailhost:/var/spool/mail
     

The result of the mailcheck command in the action-sequence is now to mount the filesystem /var/spool/mail on the host mailhost. This action is carried out on any machine which does not already have that filesystem mounted. The mail spool directory is mounted, by default, onto the official mail spool directory for the system which is parsing the program. In other words, on an HPUX system, the spool directory is mounted on /usr/mail by default, whereas on a Sun system it would be mounted on /var/spool/mail. The default location can be changed by using the resource file. See cfrc resource file.


Next: , Previous: mailserver, Up: Cfagent reference

4.28 methods

From version 2.1.0, cfagent provides for the execution of closed functions or "methods". Methods are similar to the old idea of modules, but they are implemented in a way that allows collaboration between different hosts within a network, using a common standard. Methods must be cfengine programs however, wheras the module interface can be written in any script language.

Methods are designed to offer a firewall-like proxy interface for remote method execution. We can call methods a form of `voluntary RPC', in which hosts execute methods for one another on a purely voluntary basis. This builds in anti-spamming protection. The principle used is that hosts should be immune to Denial of Service attacks; they should only be able to disadvanatge themselves with the attempt.

(Remote method execution was not implemented until version 2.1.3. It is still considered experimental and should be tested carefully for production environments with at least version 2.2.2. List expansion is particularly fragile in cfengine 2. This problem cannot be resolved in version 2, so this should not be reported as a bug. )

Methods allow you to call an independent cfengine program, pass it arguments and classes, and collect the results for use in your main program. It thus introduces parent-child semantics into cfengine "imports". A method is more than an import. (Import is analagous to a C #include, while a method is like a C function.) Communication is peer to peer, by mutual consent. There is no "method server" that executes methods on remote hosts. Hosts exchange information by invitation only. This is an unreliable service (in the sense of UDP).

The order of method exeuction is not guaranteed. This results from the decoupling between client request and service provision.

     
       methods:
     
          class::
     
     
           function_name(parameters or none)
     
           action=filename
     
           sendclasses=comma separated class list
     
           returnvars=comma separated variable list or void
           returnclasses=comma separated class list
     
           server=ip-host/localhost/none
     
           forcereplyto=ip address
     
           owner=setuid
           group=setgid
           chdir=cd for child
           chroot=sandbox directory
     
Most of these functions will be familiar from other cfengine commands. Some special ones are noted below:

action
The name of the method file that should be defined in the modules directory of the server host.
forcereplyto
Sometimes nameservice problems (especially with remote devices) can lead to confusion about where a method should be sent. The caller can therefore declare to the server which address it wants the reply to be marked for.
returnvars
Returns the values of the variables to the parent process. This acts as an access control list for variable names transmitted by the child process. The names returned by the child must match this list.
returnclasses
Returns the classes to the parent process, if and only if they are defined at the end of the current method. This acts as an access control list for class names transmitted by the child process. The names returned by the child must match this list.
sendclasses
Transmits the current status of the named classes to the child process. In other words, if the listed classes are defined, they become defined in the child process, else they remain undefined. The class may still be defined in the child by independent local definitions.

If the server is set to localhost, the method will be evaluated on the local machine. If the server is set of none, the method will not be executed at all. The function arguments may not be empty, but a null value can be transmitted with a dummy value, e.g. Function(null) or function(void). Here is an example method call.

     
      # cfagent.conf
     
     control:
     
        actionsequence = ( methods )
     
     #################################################
     
     methods:
     
      any::
     
        SimpleMethod(null)
     
           action=cf.simple
           returnvars=null
           returnclasses=null
           server=localhost
     
     

With method file (located in the ModulesDirectory),

     
      # cf.simple
     
       control:
     
         MethodName       = ( SimpleMethod )
         MethodParameters = ( null )
         actionsequence   = ( timezone )
     
     
       classes:
     
          dummy = ( any )
     
     ####################################################
     
     alerts:
     
      dummy::
     
       "This simple method does nothing"
     
       ReturnVariables(void)
       ReturnClasses(void)
     

On executing this example, the output is:

     nexus$ ./cfagent -f ./cftest
     cfengine:myhost:SimpleMethod: cfengine:nexus: This simple method does nothing
     

If the server name is a wildcard, e.g. * then this acts as a multicast or broadcast.


Next: , Previous: methods, Up: methods

4.28.1 Localhost examples

The following example collects the tar file, unpacks it, configures and compiles it, then tidies its files.

     ####################################################
     #
     # This is a cfengine file that calls a method.
     # It should be in the usual place for cfinputs
     #
     ####################################################
     
     control:
     
        actionsequence = ( methods )
     
     #####################################################
     
     methods:
     
        InstallTar(cfengine-2.1.0b7,/local/gnu)
     
           action=cf.install
           returnvars=null
           returnclasses=null
           server=localhost
     

We must install the method in the trusted modules directory (normally /var/cfengine/modules or WORKDIR/modules).

     ####################################################
     #
     # This is an example method file, that needs to be
     # in the module directory /var/cfengine/modules
     # since this is the trusted directory
     #
     # e.g. InstallFromTar(cfengine-2.1.0,/usr/local/gnu)
     #
     ####################################################
     
     control:
     
     
      MethodName       = ( InstallTar )
      MethodParameters = ( filename gnuprefix )
     
      path = ( /usr/local/gnu/bin )
     
     
      TrustedWorkDir = ( /tmp )
     
      TrustedSources = ( /iu/nexus/ud/mark/tmp )
      TrustedSourceServer = ( localhost )
     
      actionsequence = ( copy editfiles shellcommands tidy )
     
     ####################################################
     
     classes:
     
       Force = ( any )
     
     ####################################################
     
     copy:
     
      $(TrustedSources)/$(filename).tar.gz
     
         dest=$(TrustedWorkDir)/$(filename).tar.gz
         server=$(TrustedSourceServer)
     
     ####################################################
     
     shellcommands:
     
      "$(path)/tar zxf $(filename).tar.gz"
     
          chdir=$(TrustedWorkDir)
     
      "$(TrustedWorkDir)/$(filename)/configure --prefix=$(gnuprefix)"
     
         chdir=$(TrustedWorkDir)/$(filename)
         define=okay
     
      okay::
     
      "$(path)/make"
     
          chdir=$(TrustedWorkDir)/$(filename)
     
     ####################################################
     
     tidy:
     
       $(TrustedWorkDir) pattern=$(filename) r=inf rmdirs=true age=0
     
     
     ####################################################
     
     #editfiles:
     #
     #{ $(TrustedWorkDir)/$(filename)/configure-opts
     #
     #AppendIfNoSuchLine "Something ???"
     #}
     
     ####################################################
     
     alerts:
     
      Force::
     
       ReturnVariables(none)
       ReturnClasses(success)
     

A more complex example is given below:

       GetAnalysis("${parent1}",param2,ReadFile("/etc/passwd",300))
     
         # The name of the method that is in modulesdir
     
         action=cf.methodtest
     
         # The variables that we get back should be called these names
         # with method name prefix
     
         returnvars=a,b,c,d
     
         # This is an access list for returned classes. Classes will
         # only be handed back if they are included here
     
         returnclasses=define1,define2,class1
     
         # The host(s) that should execute the method
     
         server=localhost
     
         # Only localhost can decide these - not a remote caller
         #    owner=25
         #    group=root
         #    chdir=/var/cfengine
         #    chroot=/tmp
     

Here the function being called is the cfengine program cf.methodtest. It is passed three arguments: the contents of variable parent1, the literal string "param2" and the first 300 bytes of the file /etc/passwd. On return, if the method gets executed, the values will be placed in the four variables:

     $(GetAnalysis.a) $(GetAnalysis.b) $(GetAnalysis.c) $(GetAnalysis.d)

If the classes define1 etc, are returned by the method, then we set them also in the main program as

     GetAnalysis_define::

In other words, the class name is also prefixed with the method name to distinguish it. (returnclasses works like an access control list for setting classes, deciding whether or not the main script should accept the results from the child method.). The remaining options are as those for executing shell commands, and apply only on the host that executes the function.

Both the client and server hosts must have a copy of the same method declaration. The client should have a non-empty server= declaration. The server side should have no server= declaration unless it is sending the request on recursively to other hosts. At present only requests to localhost are allowed, so only there is automatic access to the rule.

The cfagent file that contains the method code must have the following declarations:

control:

MethodName = ( identifier ) MethodParameters = ( spaced list of recipient variables or files )

# ....

alerts:

# Return variables are alerts to parent

ReturnVariables(comma separated list of variables or functions or void) ReturnClasses(comma separated list of classes)

e.g.

     control:
     
      MethodName       = ( GetAnalysis )
      MethodParameters = ( value1 value2 /tmp/file1 )
     
      # ....
     
     alerts:
     
       # Return variables are alerts to parent
     
       ReturnVariables("${var1}","${var2}","var3",literal_value)
       ReturnClasses(class1,class2)
     

The parameters transmitted by the parent are read into the formal parameters value1, value2 and the the file excerpt is placed in the temporary file /tmp/file1.

The return classes are passed in their current state to the parent; i.e. if class1 is defined then it is offered to the parent, but if it is not defined in the method, it is not passed on. The parent can then choose to accept or ignore the value.


Previous: localhost examples, Up: methods

4.28.2 Remote host examples

Methods can also be scheduled for execution on remote hosts.

  • Both hosts must have an identical copy of the method stanza
  • Public keys must be exchanged between the cooperating hosts
  • Access must be granted to /var/cfengine/rpc_out in cfservd.

Remote method execution is the same as local method execution except for some additional requirements. A list of collaborating peers must be added to the control section of update.conf. In order the the requests to be collected automatically, you must have copy in the action sequence of the update.conf file.

     control:
     
      MethodPeers = ( hostname list ) # Must have copy in actionsequence
     

This list tells the agent which remote hosts to collaborate with, i.e. whom should we contact to look for work that we have promised to perform? In order the the requests to be collected automatically, you must have copy in the action sequence of the update.conf file.

For example, to make two hosts collaborate:

     methods:
     
      host1|host2::
     
       MethodTest("my test!")
     
       action=cf.methodtest
       server=host2.iu.hio.no
       returnclasses=null
       returnvars=retval
       ifelapsed=120

Note that an important aspect of remote method invocation is that there is only voluntary cooperation between the parties. A reply bundle from a finished method can collected from a server by the client many times, causing the classes and variables associated with it to be defined at regular intervals, controlled by the ifelapsed time. To avoid multiple actions, you should lock methods or their follow-up actions with long ifelapsed times. This is a fundamental `feature' of voluntary cooperation: each party must take responsibilty for the sense of what it receives from the other. This feature will not be to everyone's taste, and it is unconventional. However, voluntary cooperation provides a way of collaborating without trust in a framework that forces us to confront the security issues directly. As such, it is a successful experiment.


Next: , Previous: methods, Up: Cfagent reference

4.29 miscmounts

If you do not use the cfengine model for statically mounting NFS filesystems (or if there are filesystems which do not naturally fall into the bounds of that model) then you can still statically mount miscellaneous filesystems using a statement of the form:

     
     miscmounts:
     
        class::
     
           infohost:source-directory destination mode
     
           infohost:source-directory destination mode=mode
     
          ifelapsed=mins expireafter=mins
     

For example

     
        physics::
     
         # old syntax
     
           libraryserver:/$(site)/libraryserver/data1
                               /$(site)/libraryserver/data1 ro
     
         # consistent syntax
     
           libraryserver:/$(site)/libraryserver/data2
                               /$(site)/libraryserver/data2 mode=ro
     
           host:/foo /foo mode=rw,bg,hard,intr
     

This statement would mount the directory /$(site)/libraryserver/data physically attached to host libraryserver onto a directory of the same name on all hosts in the group physics. The modes ro and rw signify read-only and read-write respectively. If no mode is given, read-write is assumed.


Next: , Previous: miscmounts, Up: Cfagent reference

4.30 mountables

The mountables declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of what filesystem resources are available for mounting. This list is used in conjunction with binservers and homeservers to determine which filesystems a given host should mount, according to the cfengine model.

The syntax of the list is:

     mountables:
     
        class::
            "filesystem to mount"
     	   readonly=false/off/true/on
     	   mountoptions=nfs-options
     

e.g.

     
     mountables:
     
        class::
     
        server:/site/server/u1
        server:/site/server/local
        linuxhost:/site/linuxhost/local
        linuxhost:/site/linuxhost/u1
     
     

Notice that binary and home-directory filesystems are mixed freely here. Cfengine determines which of the entries are homedirectories using the homepattern variable. Every time you add a disk or a mountable partition to your network, you should add the partition to the list of mountables.

NOTE: This list is read in order, top down. Cfengine looks for the first filesystem matching a given binary server when expanding the variable $(binserver), so sometimes the ordering of filesystems matters.

This list can be accessed in editfiles, to allow straightforward configuration of the automounter, using the command AutomountDirectResources.


Next: , Previous: mountables, Up: Cfagent reference

4.31 processes

Using the processes facility, you can test for the existence of processes, signal (kill) processes and optionally restart them again. Cfengine opens a pipe from the system ps command and searches through the output from this command using regular expressions to match the lines of output from ‘ps’. The regular expression does not have to be an exact match, only a substring of the process line. The form of a process command is

     processes:
     
       class::
     
         "quoted regular expression"
     
                             restart "shell command"
                             useshell=true/false/dumb
                             owner=restart-uid
                             group=restart-gid
                             chroot=directory
                             chdir=directory
                             umask=mask
     
                             signal=signal name
                             matches=number
                             define=classlist
                             elsedefine=classlist
     
                             action=signal/do/warn/bymatch
                             include=literal
                             exclude=literal
                             filter=filter_name
     
                             syslog=true/on/false/off
                             inform=true/on/false/off
                             audit=true/on/false/off
     
                             ifelapsed=mins
                             expireafter=mins
     
         SetOptionString "quoted option string"
     
By default, the options sent to ps are "-aux" for BSD systems and "-ef" for System V. You can use the SetOptionString command to redefine the option string. Cfengine assumes only that the first identifiable number on each line is the process identifier for the processes, so you must not choose options for ps which change this basic requirement (this is not a problem in practice). Cfengine reads the output of the ps-command normally only once, and searches through it in memory. The process table is only re-consulted if SetOptionString is called. The options have the following meanings:

signal=signal name
This option defines the name of a signal which is to be sent to all processes matching the quoted regular expression. If this option is omitted, no signal is sent. The signal names have the usual meanings. The full list, with largely standardized meanings, is
             hup       1   hang-up
             int       2   interrupt
             quit      3   quit
             ill       4   illegal instruction
             trap      5   trace trap
             iot       6   iot instruction
             emt       7   emt instruction
             fpe       8   floating point exception
             kill      9   kill signal
             bus      10   bus error
             segv     11   segmentation fault
             sys      12   bad argument to system call
             pipe     13   write to non existent pipe
             alrm     14   alarm clock
             term     15   software termination signal
             urg      16   urgent condition on I/O channel
             stop     17   stop signal (not from tty)
             tstp     18   stop from tty
             cont     19   continue
             chld     20   to parent on child exit/stop
             gttin    21   to readers pgrp upon background tty read
             gttou    22   like TTIN for output if (tp->t_local&LTOSTOP)
             io       23   input/output possible signal
             xcpu     24   exceeded CPU time limit
             xfsz     25   exceeded file size limit
             vtalrm   26   virtual time alarm
             prof     27   profiling time alarm
             winch    28   window changed
             lost     29   resource lost (eg, record-lock lost)
             usr1     30   user defined signal 1
             usr2     31   user defined signal 2
          

Note that cfengine will not attempt to signal or restart processes 0 to 3 on any system since such an attempt could bring down the system. The only exception is that the hangup (hup) signal may be sent to process 1 (init) which normally forces init to reread its terminal configuration files.

restart "shell command"
Note the syntax: there is no equals sign here. If the keyword `restart' appears, then the next quoted string is interpreted as a shell command which is to be executed after any signals have been sent. This command is only issued if the number of processes matching the specified regular expression is zero, or if the signal sent was signal 9 (sigkill) or 15 (sigterm) , i.e. the normal termination signals. This could be used to restart a daemon for instance. Cfengine executes this command and waits for its completion so you should normally only use this feature to execute non-blocking commands, such as daemons which dissociate themselves from the I/O stream and place themselves in the background. Some unices leave a hanging pipe on restart (they never manage to detect the end of file condition). This occurs on POSIX.1 and SVR4 popen calls which use wait4. For some reason they fail to find and end-of-file for an exiting child process and go into a deadlock trying to read from an already dead process. This leaves a zombie behind (the parent daemon process which forked and was supposed to exit) though the child continues. A way around this is to use a wrapper script which prints the line "cfengine-die" to STDOUT after restarting the process. This causes cfengine to close the pipe forcibly and continue. Cfengine places a timeout on the restart process and attempts to clean up zombies, but you should be aware of this possibility.
owner=,group=
Sets the process uid and gid (setuid,gid) for processes which are restarted. This applies only to cfengine run by root.
chroot
Changes the process root directory of the restarted process, creating a `sandbox' which the process cannot escape from. Best used together with a change of owner, since a root process can break out of such a confinement in principle.
chdir
Change the current working directory of the restarted process.
useshell=true/false/dumb
When restarting processes, cfengine normally uses a shell to interpret and execute the restart command. This has inherent security problems associated with it. If you set this option to false, cfengine executes restart commands without using a shell. This is recommended, but it does mean that you cannot use any shell operators or features in the restart command-line.

Some programs (like cron) do not handle I/O properly when they fork their daemon parts, this causes a zombie process and normally hangs cfengine. By choosing the value `dumb' for this, cfengine ignores all output from a program and does not use a startup shell. This prevents programs like cron from hanging cfengine.

matches=number
This option may be used to set a maximum, minimum or exact number of matches. If cfengine doesn't find a number of matches to the regular expression which is in accordance with this value it signals a warning. The ‘<’, ‘>’ symbols are used to specify upper and lower limits. For example,
            matches=>6  # warn number of matches is greater than or equal to 6
            matches=1   # warn if not exactly 1 matching process
            matches=<2  # warn if there are less than or equal to 2 matching processes


include=literal
Items listed as includes provide an extra level of selection after the regular expression matches have been expanded. If you include one include option, then only lines containing one or more of the literal strings or wildcards will be matched.
exclude=literal
Process lines containing literal strings or wildcards in exclude statements are not matched. Excludes are processed after regular expression matching and after includes.
define=classlist
The colon, comma or dot separated list of classes becomes activated if the number of regular expression matches is non-zero.
elsedefine=classlist
The colon, comma or dot separated list of classes becomes activated if the number of regular expression matches is zero.


action=signal/do/warn/bymatch
The default value of this option is to silently send a signal (if one was defined using the signal option) to matching processes. This is equivalent to setting the value of this parameter to ‘signal’ or ‘do’. If you set this option to ‘warn’, cfengine sends no signal, but prints a message detailing the processes which match the regular expression. If the option is set to bymatch, then signals are only sent to the processes if the matches criteria fail.

Here is an example script which sends the hang-up signal to cron, forcing it to reread its crontab files:

     
     processes:
     
        "cron" signal=hup
     

Here is a second example which may be used to restart the nameservice on a Solaris system:

     
     processes:
     
        solaris::
     
            "named" signal=kill restart "/usr/sbin/in.named"
     

A more complex match could be used to look for processes belonging to a particular user. Here is a script which kills ftp related processes belonging to a particular user who is known to spend the whole day FTP-ing files:

     
     control:
     
         actionsequence = ( processes )
     
       #
       # Set a kill signal here for convenience
       #
     
         sig = ( kill )
     
       #
       # Better not find that dumpster here!
       #
     
         matches = ( 1 )
     
     processes:
     
        #
        #  Look for Johnny Mnemonic trying to dump his head, user = jmnemon
        #
     
        ".*jmnemon.*ftp.*" signal=$(sig) matches=<$(matches) action=$(do)
     
        # No mercy!
     

The regular expression ‘.*’ matches any number of characters, so this command searches for a line containing both the username and something to do with ftp and sends these processes the kill signal.

You can arrange for signals to be sent, only if the number of matches fails the test. The action=bymatch option is used for this. For instance, to kill process `XXX' only if the number of matches is greater than 20, one would write:

     
     processes:
     
     "XXX" matches=<20  action=bymatch signal=kill
     

See also filters See filters, for more complex searches.


Next: , Previous: processes, Up: Cfagent reference

4.32 Packages

The packages action allows you to check for the existance of packages on the system, as determined by the package database you select. Optionally, if a package install command was specified, the package can be installed if it is not there.

This operation is set up such that it tries not to make assumptions about the package manager in use. For example, it should be possible to use RPM on a Solaris box.

The syntax summary is:

     
     packages:
     
        class::
     
           package-name
                             pkgmgr=none/rpm/dpkg/sun/aix/portage/freebsd
                             cmp=eq/lt/gt/ge/le/ne
                             version=version-string
                             define=class-list(,:.)
                             elsedefine=class-list(,:.)
                             action=none/install/remove/upgrade/fix
     
                             ifelapsed=mins
                             expireafter=mins
     
                             audit=true/on/false/off
                             inform=true/on/false/off
     
     EXAMPLES:
     packages:
       # install newpackage 1.10 if newpackage 1.0 or greater isn't installed
       newpackage-1.10 action=install
                     cmp=ge
                     version=1.0
     
       # upgrade any installed versions of compromised to at least 1.2
       compromised-1.2 action=upgrade
                     version=1.2
                     cmp=le
     
       # Make sure that version 1.2 is installed
       compromised-1.2 action=fix
                     version=1.2
                     cmp=le
     
       # remove any version of useless
       useless action=remove
                     version=0.1
                     cmp=ge
     

action
Determines the action taken if the comparison matches.
  • install Install this package if the version comparison does not match.
  • upgrade Upgrade this package if the version comparison does match.
  • fix Install or Upgrade this package if the version comparison does match.
  • remove Uninstall this package if the version comparison does match.

cmp
Determines how the version of the installed package will be compared to that specified by the version attribute. Possible values include:
  • eq The version installed must be equal to version
  • lt The version installed must be less than version
  • gt The version installed must be greater than version
  • le The version installed must be less than or equal to version
  • ge The version installed must be creater than or equal to version
  • ne The version installed must not be equal to version

The default value for this attribute is eq.

Note that cmp is used differently for install versus upgrade, fix and remove. The action is performed when false for install, but when true for upgrade, fix or remove.

version
Specifies the package manager specific version string to match. If this is not specified, then any version matches, and the value of the cmp attribute is ignored. See the allowed values of pkgmgr below for an explation of how each package manager will interpret this.
pkgmgr
Selects the package manager database to query. This defaults to either the value of the DefaultPkgMgr variable, or if that is not set, there is no default. In that case, no checking will be done unless pkgmgr is set explicitly for each package. Note that the default value '‘none’' listed is merely a pseudo-value, and cannot actually be used, since it would make no sense anyway.

Each package manager will interpret the version and cmp attributes in its own way. For example, when you use pkgmgr=rpm, the comparison will be done with the same rules that RPM use if it were not being run through cfengine. Freebsd actually invokes the standard system utility to do the comparisons for it, etc.

Currently, the following package managers are supported:

rpm
This uses the rpm command, which cfengine expects to find as /bin/rpm to query the machine's RPM database. The rpm check assumes that you are using a version of RPM that understands the concept of an epoch, which means that you will want to use RPM version 3.0.3 or greater. Versions as early as 2.5.6 may work, but it is doubtful. If multiple packages of the same name are installed (i.e. kernel), then the check considers the package to be installed at the specified version if at least one of them satisifies the criteria specified by cmp and version.

The format of a RPM version string is: [epoch:]version[-release]. The version[-release] can be seen by simply running: rpm -q <pkg>. In order to see the epoch, you must use a query format, like this: rpm -q --queryformat "%{EPOCH}:%{VERSION}-%{RELEASE}\n" <pkg>. Most packages do not have an epoch, and will print ‘(none)’ in the epoch space. In recent incarnations of RPM, the absense of an epoch is interpreted as 0. This is also how cfengine will interpret it. Be careful with this. If the installed version of a package has an epoch greater than 0, and you do not specify the epoch, unexpected results may happen. For example, if you have a package installed, ‘foo-1:2.0-1’, and you specify a version=3.0-1 and a cmp=gt, the check will be true, because the installed version has an epoch of 1, and you did not specify an epoch, which implies you wanted an epoch of 0. The rule here is basically to always check the epoch of the package you really want, and specify it. It may take a few extra extra seconds to check, but it will save you lots of headaches later.

portage
This uses the emerge command to install packages on a Gentoo Linux system. The `portage' Python module is used to query the system and find installed packages. The package_name and version support any package that conforms to the Gentoo package naming specification http://www.gentoo.org/proj/en/devrel/handbook/handbook.xml?part=2&chap=1#doc_chap2_sect2, and even most of those in the Portage tree that do not. Because Gentoo package atoms are flexible, you can use the name of the package, along with a version and the cmp cfengine logic, or you can put the comparison operator and version in the package_name field and leave out the cmp operator. Because cfengine builds the install string out of the package name, and ignores the version you were comparing against, using a package atom with a version is the only way to have a specific version emerged.
               
                packages:
               
                 any::
               
                  # if the version of tar is less than 1.16-r2,
                  # then the *latest* version of tar will be installed:
               
                  app-arch/tar cmp=ge version=1.16-r2 action=install
               
                  # This is equivalent, but uses the package atom to
                  # define the version comparison:
               
                  >=app-arch/tar-1.16-r2 action=install
               

dpkg
Please document me!
sun
Please document me!
freebsd
FreeBSD has fully working install/upgrade/delete management for packages. You can either get the latest version from a package repository, or define the explicit version to install.
               
               # install new package from FreeBSD ports tree
               control:
                 DefaultPkgMgr = ( freebsd )
                 FreeBSDInstallCommand = ( "/usr/sbin/pkg_add -r %s" )
               
               packages:
                 bsdsar action=install
               
               # install a specific version from a local repository
               control:
                 DefaultPkgMgr = ( freebsd )
                 FreeBSDInstallCommand = ( "/usr/sbin/pkg_add http://server/path/%s" )
               
               packages:
                 bsdsar-1.10_2 action=install

Note that specifying the version of the package that is part of the freebsd package filename is required if not using "-r" mode. It does not use this version for comparison, just for the package filename to install.

You can also backgrade if you know that 1.2 is bad for instance.

               packages:
                 bsdsar-1.10_2 action=upgrade
                               version=1.10_2
                               cmp=gt

The only gotcha about FreeBSD installation is trying to specify the package source location. Due to the unfortunate fact that freebsd doesn't provide a command line option – only an environment variable – for specifying the source repository, you have a few options.

Get it from the main FreeBSD binary package home:

                 FreeBSDInstallCommand = ( "/usr/sbin/pkg_add -r %s" )

Get it from a mounted directory or http server

                 FreeBSDInstallCommand = ( "/usr/sbin/pkg_add /nfs/packages/%s" )
                 FreeBSDInstallCommand = ( "/usr/sbin/pkg_add http://server/path/%s" )
               

Or write a script that tells pkg_add where to find it, like so:

                 FreeBSDInstallCommand = ( "/var/cfengine/packages/pkginstall %s" )

such as

               #!/bin/sh
               PACKAGESITE=http://my.local.repository/packages/
               export PACKAGESITE
               /usr/sbin/pkg_add -r $*

define
Specifies the list of classes to define if the specified package/version was installed (prior to actions taken if any)
elsedefine
Specifies the list of classes to define if the specified package/version was not installed (prior to actions taken if any)
action
Specifies whether the packages should actually do anything about the situation it finds. The default for this is to do nothing.

For install, the action will be taken if the comparison returns false.

For upgrade and remove, the action will be taken if the comparison returns false.

The classes in define and elsedefine will always be defined, as applicable, regardless of the action specified.

install
Installs the package using the command associated with the selected package manager, if it is not currently on the system at the requested version, as follows:
  • RPM - RPMInstallCommand
  • DPKG - DPKGInstallCommand
  • SUN - SUNInstallCommand
  • Gentoo - PortageInstallCommand
  • FreeBSD - FreeBSDInstallCommand

Each variable is of the format:

               FOOInstallCommand = ( "/usr/bin/foo --args %s --more-args" )

The —args are of course optional. For FreeBSD and Sun, the %s is replaced with the package name that was checked, and found to not be installed. For all other package managers the %s can have a space separated list of package names.

upgrade
Upgrades the package using the commands associated with the selected package manager, first removal of the old package then installation of the new package. Note that on some package managers this action is unnecessary because the package manager will "do the right thing" when told to install a newer version.
  • FreeBSD - FreeBSDRemoveCommand followed by FreeBSDInstallCommand Portage - Upgrade is generally not necessary since emerge will do the upgrade for you.

remove
Removes the package(s) using the command associated with the selected package manager, if a matching package is found on the system, as follows:
               FOORemoveCommand = ( "/usr/bin/foo --args %s --more-args" )

The —args are of course optional. The %s is replaced with a space-separated list of the package names that were checked, and found to be installed.

NOTE: classes are defined according to the result of the check, not any action performed as a result of that check. In otherwords, if for example you have a situation where a package is not installed, and the action= is set to install, the classes in elsedefine will be defined regardless of whether or not the install was successful. Assuming the package installed, the next run of cfagent will pick up that fact. This has to be done since the package installs are batched, so there is no reliable way to know if a given package was installed successfully.

Examples:

     packages:
     
         redhat_8_0::
             m4  version=0:1.4.1-11 cmp=eq pkgmgr=rpm elsedefine=needsm4

In this first example, we are looking for the m4 package at exactly version 0:1.4.1-11. The installed m4 package on a redhat_8_0 box has no epoch which is the same as zero. Specifying it will keep you out of trouble. This check will cause needsm4 to be defined if the exact version of m4 specified is not installed.

     control:
         redhat:;
             DefaultPkgMgr = ( rpm )
     
         gentoo::
             DefaultPkgMgr = ( portage )
     
     packages:
         redhat_8_0::
             make version=0:4.5-2 cmp=ge define=hasmake elsedefine=needsmake
     

In the second example, we use the DefaultPkgMgr variable to set the default for the pkgmgr attribute to rpm. The actual version of make installed on recent redhat_8_0 machine is 1:3.79.1-14. Since the check is for greater than or equal to this version, the hasmake class will be defined.

     control:
         redhat:;
             DefaultPkgMgr = ( rpm )
             RPMInstallCommand = ( "/usr/sbin/up2date %s" )
     
     packages:
         redhat_8_0::
             make define=hasmake elsedefine=needsmake action=install

This example is much like the second example, except that if the package is not installed, cfengine will attempt to install it using the command in RPMInstallCommand, replacing the %s with the package name, make. If there were multiple packages specified in this way, the package installation would occur at the end of the package checks, and one command would be run, with %s replaced with a list of all package names. In this example we chose not to use a version spec, but it is allowed, and as always, is optional.

NOTE here that if make was not installed when the check is made, needsmake is defined, regardless of whether or not the install succeeds. If the install is successful, the next cfagent run will define hasmake.


Next: , Previous: packages, Up: Cfagent reference

4.33 rename

As of version 2.1.0 rename is a synonym for disable, See disable.


Next: , Previous: rename, Up: Cfagent reference

4.34 required

This is a synonym for disks, See disks.


Next: , Previous: required, Up: Cfagent reference

4.35 resolve

The file /etc/resolv.conf specifies the default nameserver for each host, as well as the local domain name. This file can also contain other information, but these are the only two things cfengine currently cares about. In specifying nameservers you should use the dotted numerical form of the IP addresses since your system may not understand the text form if it is not correctly configured. You may list as many nameservers as you wish, with the default server at the top of the list. The resolver normally ignores entries if you add more than three. The statement:

     
     resolve:
     
       mygroup::
     
          129.240.22.35
          129.240.22.222
          129.240.2.3
     

declares a list of nameservers for hosts in the group or class mygroup. When you add the resolve command to the actionsequence, this declaration together with the domain variable (set here to uio.no) results in a /etc/resolv.conf file of the form:

     
     domain uio.no
     nameserver 129.240.22.35
     nameserver 129.240.22.222
     nameserver 129.240.2.3
     

Note that the resolve action does not delete anything from the file /etc/resolv.conf unless the EmptyResolvConf variable is set to 'true' . It adds nameservers which do not previously exist and reorders the lines of servers which do exist.

As of version 1.3.11, you may use a quoted string to add non-nameserver lines to this file. For example:

     
     resolve:
     
       mygroup::
     
          129.240.22.35
          129.240.22.222
          "# Comment line"
          "order bind, files"
     

If the line begins with a non-numeric character, the word `nameserver' is not added to the line.


Next: , Previous: resolve, Up: Cfagent reference

4.36 scli

SCLI is an SNMP command line interpreter written by Jürgen Schönwaelder of the Jacobs University of Bremen. It is a command interpreter used to simplify the interaction with SNMP enabled devices. SNMP is a stateless, UDP based network protocol for communicating with supporting hardware. The SNMP model does not fit very comfortably with the cfengine “responsibility for self” paradigm, but at some level SCLI can be viewed as just another form of interpreted script. SCLI adds a level of user friendliness and stateful behaviour to SNMP through its shell-like interface. This turns out to be both a help and a hindrance to cfagent.

The intermingling of stateful and stateless processes in the dialogue between cfengine and scli makes their integration non-trivial. Several compromises have to be made to aid usability and these could lead to difficulties in the practical use of the tools later.

The scli section of a cfagent configuration is a single script. The lines are passed as a collective object to the scli interpreter, not line-by-line as in other cases.

The basic approach is to open a pipe for the reading and writing of dialogue with the interpreter. There are some limitations to Unix pipes however, in particular input and output are separated which makes per-transaction error control essentially impossible. A work-around for this has been used in the test phase.

The cfengine interface is a special case of the shellcommands interface, passing commands to SCLI instead of to /bin/sh. The command options are the same as those below for shellcommands.

     shellcommands:
     
       class::
     
         "scli-string"  shellcommand options
         "scli-string"
     

This integration was funded by the IST-EMANICS Network of Excellence in Network and Service Management, of which Oslo University College and the Jacobs University of Bremen are members.


Next: , Previous: scli, Up: Cfagent reference

4.37 shellcommands

Cfengine focuses on fairly simple-minded tasks in order to be as general as possible. In many cases, you will therefore want to write a script to do something special on your system. You can still take advantage of the classes you have defined by executing these scripts or shell commands from this section.

The syntax is simply to quote the command you wish to be executed.

     shellcommands:
     
       class::
     
         "command-string"
     
               timeout=seconds
               useshell=true/false
               umask=octal number
               owner=uid
               group=gid
     
               background=false/true
               chdir=directory
               chroot=directory
               preview=true/false
               inform=false/true
               audit=true/on/false/off
     
               noabspath=false/true
     
               ifelapsed=mins
               expireafter=mins
     
               define=class-list
               elsedefine=class-list
     

command-string
This is the command to be executed.
timeout
If you set the optional timeout parameter, then cfengine will abort the specified shellcommand if it exceeds the given time-limit (specified in seconds). This can be useful for avoiding hung programs caused by hung network connections, etc. Timeouts are generated by alarm interrupts within a single agent. This can be contrasted with expireafter in which a second agent is required to interrupt a command.
useshell
Some program lines, especially those that do not use any shell-specific capabilities (such as redirection and wildcard expansion) can be run without the shell. This is typically more secure, as the command line is not altered by the user or by the system. It is also faster, as the shell does not have to be spawned in order to run the given command. Use the useshell parameter to tell cfengine to not use the shell to run this shellcommand.
umask
The umask affects the permissions given to a file created by this shellcommand. The umask specifies, specifically, the permissions that are to be taken away.
owner
group
The user and group ID's of the process can be set (using the owner and group parameters respectively) to restrict the permissions of the shellcommand. This can only be done if cfengine is executed by root; otherwise, the user and group will remain that of the the user who started cfengine.
background
Run this command in the background if this is specified true. This will make cfengine run faster, but no tests can be made (at least directly) on the results of this command. Also when jobs are backgrounded, the output in verbose mode can be somewhat erratic due to the unsychnronized streams.
chdir
Change to the specified directory before running this command.
chroot
The chroot option changes the process root directory of the command, creating a `sandbox' which the process cannot escape from. Best used together with a change of owner (using the owner parameter), since a root process can break out of a chrooted environment.
preview
The preview option means that the shellcommand will also be executed during the --dry-run (-n) options. This allows cfengine to be more aware of the results of scripts which define classes. This option should be used with care.

Scripts should conform to the protocol of not executing unnecessary commands when the classes opt_dry_run is defined.

inform
noabspath
Normally, cfagent requires the command string to begin with a ‘/’ since it is dangerous to rely on an implicit path. However, sometimes it it is appropriate to override this. This behavior can be overridden using the noabspath parameter.
ifelapsed
The shellcommand specified will not be run unless the specified amount of time (in minutes) has elapsed since the command was previously run.
expireafter
If this amount of time (in minutes) has elapsed since the command started, then the command is aborted by a second agent that is patrolling the system.
define
Define the specified classes if the command finishes successfully.
elsedefine
Define the specified classes if the command does not finish successfully.

Variable substitution works within the strings. Here are some examples.

     
     shellcommands:
     
        sun4::
     
            "/usr/lib/find/updatedb"
     
        AllHomeServers.Sunday::
     
            "/dir/noseyparker /$(site)/$(host)/u1 $(sysadm) nomail"
     
        AllBinaryServers.sun4.Saturday::
     
           "/usr/etc/catman -w -M /usr/local/man"
           "/usr/etc/catman -w -M /usr/local/X11R5/man"
           "/usr/etc/catman -w -M /usr/man"
           "/usr/etc/catman -w -M /usr/local/gnu/man"
     

If you need to write more advanced scripts which make detailed use of the classes defined by cfengine, use the $(allclasses) variable to send a complete list of classes to your script. An enviornment variable, CFALLCLASSES, is set and is in the format

     
     CFALLCLASSES=class1:class2:class3...
     

This variable is kept up-to-date at any given time with only the classes which are defined. The command line option ‘-u’ or ‘--use-env’ can be used to define an environment variable which will be inherited by all scripts and contains the same information. This is not the standard approach, since some systems cannot cope with this rapid change of environment and generate a Bus Error. Commands can be iterated over variable lists, provided there is at least one space between each variable. For example:

     
     control:
     
           actionsequence =
              (
              shellcommands
              )
     
      var1 = ( a:b:c )
      var2 = ( x:y:z )
     
     shellcommands:
     
        "/bin/echo $(var1) $(var2)"
     

This iterates over all values of the list variables. See Iteration over lists. If you are iterating over a list, the time limit (in seconds) which is specified in the timeout parameter applies to each separate iteration, not to the sum total of all the iterations.


Next: , Previous: shellcommands, Up: Cfagent reference

4.38 strategies

Strategies (introduced in cfengine version 2.0) are a way of picking from a set of classes randomly. Each class is a possible course of action. A strategy group (of classes) is defined as follows:

     strategies:
     
       { my_strategy_alias
     
       class1: "2"
       class2: "3"
       class3: "$(value)"
       class4: "6"
       class5: "1"
       }
     
     tidy:
     
      class1.Hr00::
     
        /home pat=*.mp3 age=0
     
      class2.Hr02::
     
        /home pat=*.wav age=0

The idea here is to randomly pick from a selected set of classes.

Specifically, each strategy is a class which is defined with a certain probability. An integer weight is provided in quotes to represent the probability weight of the associated class. When cfengine is run, it randomly picks one of the classes from each strategy. Using strategies, you can choose different ways of configuring or protecting a system, at random, thus confounding environmental attempts to break into the system.

Note that each strategy has a formal name (such as ‘my_strategy_alias’ in the example), but this name is not used to attach a strategy to an action the same way that filters or ACLs are.


Next: , Previous: strategies, Up: Cfagent reference

4.39 tidy

The tidy function is used to delete (remove permanently) unwanted files from a system. It is useful for tidying up in /tmp or cleaning out core files from users' home directories. The form of an entry is:

     tidy:
     
       class::
     
           /directory
                            pattern/include=wildcard
     
                            recurse=number/inf
                            age=days
                            size=number/empty
                            type=ctime/mtime/atime
                            dirlinks=keep/tidy/delete
                            rmdirs=[true/all]/[false/none]/sub
                            links=stop/keep/traverse/tidy
                            compress=true/on/false/off
     
                            define=classlist
                            elsedefine=classlist
     
                            syslog=true/on/false/off
                            inform=true/on/false/off
                            audit=true/on/false/off
     
                            ifelapsed=mins
                            expireafter=mins
     
                            filter=filter alias
                            ignore=pattern
                            exclude=pattern
                            xdev=true/on/false/off
     

Note that, each of the options below can be written in either upper or lower case and abbreviated by any unique abbreviation.

/directory
This is the directory name to directories which mark the start of a search for files matching certain wildcards. The wildcard home may be used instead of an explicit directory, in which case cfengine iterates over all home directories. It is compulsory to specify a directory.
pattern=wildcard or include=wildcard
A wildcard or filename to match the files you wish to be deleted. The pattern may contain the special symbols ‘?’ which matches a single character and ‘*’ which matches any number of characters as in the shell. These two options are synonymous, as of version 2.0.x. Note that, this pattern is processed as a filter before any other filter and, for safety reasons, it defaults to nothing. Thus, if you want to use a filter to select the files, you should set ‘pattern=*’, else the filter will not see any files at all.
exclude=wildcard
This does not work for the home directive; use the global ignore list for this.
ignore=wildcard
This does not work for the home directive; use the global ignore list for this.
recurse=number/inf
This specifier tells cfengine whether or not to recurse into subdirectories. If the value is zero, only the named file or directory is affected. If the value is 1, it will open at most one level of subdirectory and affect the files within this scope. If the value is inf then cfengine opens all subdirectories and files beginning from the specified filename. See Recursion.
age=days
The age of a file in days represents a minimum access time elapsed before the file will be deleted. In other word a file will be deleted if it has not been accessed for days days.
links=stop/traverse/tidy
Normally cfengine does not descend into subdirectories which are pointed to by symbolic links. If you wish to force it to do so (without using the -l command line option) you may give this option the value true, or traverse, or follow. To specify no recursion you set the value false or stop. Note that the value set here in the cfengine program always overrides the value set by the -l command line option, so you can protect certain actions from this command line option by specifying a negative value here. If you specify no value here, the behaviour is determined by what you specify on the command line.

The value links=tidy has the same effect as the ‘-L’ command line option except that here it may be specified per item rather than globally. Setting this value causes links which point to non-existent files to be deleted. This feature will not work on commands with the ‘home’ wildcard feature. If you want to clean up old links you should either user a files command or the command line option which sets the tidy feature globally.

size=>number/empty
Old syntax size=number/empty. The value of this parameter decides the size of files to be deleted. Files larger than this value will be deleted if they also are older than the time specified in age. The default size is zero so that any file which gets matched by another critereon is deleted. However, if you want to single out only totally empty files, the empty may be used. With this option only empty files, nevery files with anything in them, will be deleted, if older than age. By default, the filesizes are in kilobytes, but kilobytes and megabytes may also be specified by appending b,k,m to the numbers. Only the first character after the number is significant so you may write the numbers however it might be convenient, e.g. 14k, 14kB, 14kilobytes, the same as for disable.
type=ctime/mtime/atime
This value is used to set the type of time comparison made using age. The default is to compare access times (atime) or the last time the file was read. A comparison by modification time (mtime) uses the last time the contents of the file was changed. The ctime parameter is the last time the contents, owner or permissions of the file were changed. Note that on directories, mtime is always used for comparisons, since the very act of stat'ing alters atime and makes this comparison meaningless.
dirlinks=keep/tidy/delete
This value is used to decide whether cfengine will delete links which point to directories. The default value is to keep the links. Note that, if the travlinks option is switched on, cfengine will not tidy or delete links which point to directories, instead it follows them into the subdirectory. This is a supplement to the rmdirs option. You need both to make links to directories disappear. Note that, even if travlinks is set to true, cfagent will not follow symbolic links that are not owned by the agent user ID; this is to prevent link race attacks, in which users with write access could divert the agent to another part of the filesystem,
rmdirs=true/false/all/sub
Normally cfengine will not delete directories. If this option is set to `true' then cfengine will delete any directories which are empty. Non-empty directories will not be touched and no message will be given unless in verbose mode. Note that this option overrides the above option dirlinks, so that even links which point to empty directories will be removed. If this is set to `sub' then the topmost directory will not be removed, only sub-directories.


define=classlist
The colon, comma or dot separated list of classes becomes defined if any file matching the specified pattern is deleted.
xdev
Prevents cfengine from descending into file systems that are not on the same device as the root of the rescurion path.
Take a look at the following example:
     tidy:
     
        AllHomeServers::
     
            home     pattern=core   R=inf age=0
            home     pattern=*~     R=inf age=7
            home     pattern=#*     R=inf age=30
     
     
        any::
     
            /tmp/    pat=*            R=inf   age=1
            /        pat=core         R=2     age=0
            /etc     pat=hosts.equiv  r=0     age=0
     

In the first example, all hosts in the group AllHomeServers iterate a search over all user home directories looking for `core' files (older than zero days) and emacs backup files ‘*~’, ‘#*’ older than seven days.

The default values for these options are the empty string for the wildcard pattern, zero for the recursion and a specification of the age is compulsory.

When cfengine tidies users' home directories, it keeps a log of all the files it deletes each time it is run. This means that, in case of accidents, the user can see that the file has been deleted and restore it from backup. The log file is called .cfengine.rm and it is placed in the home directory of each user. The file is owned by root, but is readable to the user concerned.


Previous: tidy, Up: Cfagent reference

4.40 unmount

The unmount function unmounts non-required filesystems and removes the appropriate entry from the filesystem table (/etc/fstab or equivalent). The syntax is simply

     unmount:
     
        class::
     
           mounthost:filesystem
     
             deletedir=true/false
             deletefstab=true/false
             force=true/false
             ifelapsed=mins
             expireafter=mins
     

The options allow you to temporarily unmount a directory without actually removing it from the filesystem table. The option force is not currently implemented and will likely have to be system dependent. For example:

     unmount:
     
        physics::
     
           libraryserver:/$(site)/libraryserver/data
     

If the device is busy then the actual unmount will not take place until it becomes free, or the machine is rebooted. This feature should work on AIX systems, in spite of these machines inherent peculiarities in the form of the filesystem table.

Some users do not mount filesystems on a directory of the same name as the source directory. This can lead to confusion. Note, if you have problems removing a mounted filesystem, try using the mountpoint of the filesystem, rather than the name of the filesystem itself, in the unmount command.


Next: , Previous: Cfagent reference, Up: Top

5 Cfservd and cfrun reference

The server daemon is controlled by a file called cfservd.conf. The syntax of this configuration file is deliberately modelled on cfengine's own configuration file, but despite the similarities, they are separate.

You can use groups and import in both files to break up files into convenient modules and to import common resources, such as lists of groups.

Note that the classes in the cfservd.conf file do not tell you the classes of host which have access to files and directories, but rather which classes of host pay attention to the access and deny commands when the file is parsed.

Authentication is not by class or group but by hostname, like the /etc/exports file on most Unix systems. The syntax for the file is as follows:

     
      control:
     
        classes::
     
            domain = ( DNS-domain-name )
     
            cfrunCommand = ( "script/filename" )  # Quoted
     
            MaxConnections = ( maximum number of forked daemons )
     
            # ChecksumDatabase = ( filename ) - deprecated
     
            IfElapsed = ( time-in-minutes )
     
            DenyBadClocks = ( false )
     
            AllowConnectionsFrom = ( IP numbers )
     
            DenyConnectionsFrom = ( IP numbers )
     
            AllowMultipleConnectionsFrom = ( IP numbers )
     
            TrustKeysFrom  = ( IP numbers )
     
            AllowUsers = ( mark systemuser )
     
            LogAllConnections = ( false/true )
     
            LogEncryptedTransfers = ( false/true )
     
            SkipVerify = ( IP numbers )
     
            DynamicAddresses = ( IP numbers )
     
            BindToInterface = ( IP number/hostname )
     
            HostnameKeys = ( true/false )
     
      groups:
     
        Group definitions
     
      import:
     
        Files to import
     
      admit: | grant:
     
        classes::
     
           /file-or-directory
     
             wildcards/hostnames
     
      deny:
     
        classes::
     
           /file-or-directory
     
             wildcards/hostnames root=hostlist encrypt=true/on
     

Iteration of variables is allowed, hence:

     	control:
     	  Split = ( " " )
     	  hostlist = ( "10.10.10.1 10.10.10.2 10.10.10.3" )
     	  dirs =  ( "bin etc lib" )
     	  base = ( /usr )
     
     	#########################################################
     
     	admit:
     	   $(base)/$(dirs)   $(hostlist)

results in:

     	Path: /usr/bin (encrypt=0)
     	   Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root=
     	Path: /usr/etc (encrypt=0)
     	   Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root=
     	Path: /usr/lib (encrypt=0)
     	   Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root=

The file consists of a control section and access information.

5.1 control cfservd

5.1.1 IP address ranges

In the access control lists below, host ranges can be specified in a number of ways i) as substrings, ii) as address ranges denoted by the "-" hyphen, or iii) as CIDR (Classless Inter Domain Routing) notation. For example

     128.39.73
     128.39.74.10/23
     128.39.74-75.10-22
     2001:700:700:3:290:27ff:fea2:4730-4790
     2001:700:700:3:290:27ff:fea2:4730/64

In the CIDR notation, the slash followed by a number indicates the netmask, or the number of bits which are common to a group of hosts. Normally, this is connected to a specific subnet, but here it simply represents the number of bits from the left which are fixed for matching; all remaining bits are wildcards. The following forms are equivalent:

     128.39.74.
     128.39.74.10/24
     128.39.74.1-254

5.1.2 AllowConnectionsFrom

This variable allows a list of numerical IP masks to be specified, which cfservd will allow connections from. If the list is not empty and a host whose IP address is not specified attempts to connect to the daemon, its connection will be closed immediately. This can be used to prevent hanging connection attacks from malicous hosts and other denial of service attacks which would bind thread resources.

          control:
     
           AllowConnectionsFrom = ( 128.39.89  192.2.0.10 )
     

5.1.3 AllowMultipleConnectionsFrom

This variable should contain a list of IP wildcards to hosts which are allowed simultaneous sessions on the server. Hosts which are not in this list are allowed to connect only once, i.e. they must terminate and reconnect in order to establish a new session. This is to prevent a possible attacker from opening multiple sockets and never closing them, resulting in a denial of service attack. Hosts IP's can be placed here if they could have overlapping copy sessions (e.g. long backup transfers which can run over time). This prevents the error message "Multiple connections denied/spam shield".

5.1.4 AllowUsers

This list determines which users are to be allowed to connect to the daemon. Note that there is no way of identifying users except by their public keys. If a malicious asserts their identity, when no public key for the named user is known to the server, then they could spoof the identity of that user. All users who should be allowed to connect need to be here. This applies to use of cfrun.

     
     AllowUsers = ( mark root )
     

In other words, this is a "security by obscurity" first defence against picking up bad keys, when the server is in trust mode, with respect to a host. The attacker must know a valid user name in order to even try their luck entering into a key dialogue.

This reduces the probability that spoofing can be successful. The only real defence against spoofing is to make sure that all required public keys are installed in advance, and to switch off trust.


Next: , Previous: AllowUsers, Up: cfservd control

5.1.5 AutoExecCommand

This variable no longer exists in cfengine version 2.

5.1.6 AutoExecInterval

This variable no longer exists in version 2 of cfengine.

5.1.7 BindToInterface in cfservd

If this is set to a specific IP address of an IP configured interface, cfservd will listen for connections only on that interface. On Multi-homed hosts this allows one to restrict the traffic to one interface. Note, Unix only allows one or all interfaces to be selected. An interface must be configured with an IP address in order to be bound.

5.1.8 ChecksumDatabase in cfservd

(This variable is deprecated as of version 2.1.21. The location of the database will be fixed internally.)

This is the path and filename to a database which will cache MD5 checksum values server-side. This optimization is only available if you have the Berkeley database library ‘libdb’ on your system. If this variable is not defined, no database caching will be used and checksum values will be computed directly on request. The utility of this solution is a trade-off between the time it takes to compute the checksum versus the time for a disk-based lookup.

5.1.9 cfrunCommand

This string is the command which you would like to be executed remotely by the cfrun command. Note that you must, in addition, authorize access to this file in the admit section. The access rule should (as usual) be to the actual file object path, not including any symbolic links.

5.1.10 DenyBadClocks

If this is set to off, cfservd will not deny access to clients whose clocks are off by more than one hour. The default is to deny access to systems whose clocks differ by more than one hour. This can prevent messages of the form `Can't stat' file when remote copying.

5.1.11 DenyConnectionsFrom

Hosts which are included by the allow-list above can be explicitly denied access using this list.

          control:
     
           DenyConnectionsFrom = ( 128.39.89.76 )  # rogue host
     

5.1.12 HostnameKeys in cfservd

If this variable is set to true/on, it causes cfservd to lookup and store trusted public keys according to their DNS fully qualified host name, instead of using the IP address. This can be useful in environments where hosts do not have fixed IP addresses, but do have fixed hostnames.

     
       HostnameKeys = ( on )
     

This method of storing keys is not recommended for sites with fixed IP addresses, since it removes one security barrier from a potential attacker by potentially allowing DNS spoofing.

5.1.13 IfElapsed in cfservd

The IfElapsed anti-spamming filter is also built into cfservd so that a remote user cannot even get as far as causing cfengine to parse its input files (which could be used for spamming in itself). The time is in minutes, the default is one hour.

5.1.14 LogAllConnections

If set to true, every successful connection will be logged to syslog. This could be useful for identifying abuses of the service, if the server should come under attack, e.g. a denial of service attack. The IP address can then be excluded from the allowed connections list.

5.1.15 LogEncryptedTransfers

If set to true, every successful request for a file that is granted access only with an encrypted connection is logged in syslog.

5.1.16 MaxConnections

This integer value sets a limit on the maximum number of child daemon threads which cfservd will `fork' in order to handle remote requests. The default value is ten.

5.1.17 TrustKeysFrom

Hosts which are included in this list are automatically trusted, if cfservd does not know their public key. This allows public keys to be exchanged. Cfservd will not automatically accept a public key from a host it does not know, since the key will be used to assert strong authentication later. Once a public key has been associated with an IP address, it will never be updated, unless the existing key is deleted by hand.

          control:
     
           TrustKeysFrom = ( 128.39.89.76 )     # trusted host
           TrustKeysFrom = ( 128.39.89.76/24 )  # trusted subnet
     


Previous: TrustKeysFrom, Up: cfservd control

5.1.18 DynamicAddresses

Hosts which are included in this list are assumed to have IP addresses which can change with time, e.g. hosts which are given IP addresses by DHCP or a BOOTP like protocol.

          control:
     
           DynamicAddresses = ( 128.39.74.100-200 )  # DHCP range
     

If cfservd receives a connection from an IP address that is in this list, and trustkey is true, the existing key for that IP address can be replaced with a new key, and the old key is recorded in a "used keys" list, access is granted. If trust is switched off, the server looks in the "used key list" to see if the key has been seen before. If not access is refused. If it has been seen before – it uses this earlier trust to accept the connection and replace the IP-key binding. Note that used keys are kept in a database for easy lookup, whereas fixed keys are kept in files for easy administration. If host keys change or are reinstalled on the dynamically allocated hosts, then this database should probably be deleted to purge keys that become illegal.

DHCP addresses have no effect on hosts that use IPV6, since IPV6 addresses are generally issued based on an interface MAC address and do not therefore change.

5.2 admit, grant and deny

5.2.1 root=

This list specifies the names of hosts which are to have read access to files, regardless of the owner of the file. This effectively gives root users on connecting hosts privileges to non-root owned files on the server, but not vice-versa, similar to the NFS root mapping, except that there is no question of a client being able to modify files on the server. Caution: cfservd trusts the DNS service, so be aware that cache poisoning attacks are a possible way of bypassing access controls.

Cfservd requires you to grant access to files without following any symbolic links. You must grant access to the real file or directory in order to access the file object. This is a security feature in case parties with login access to the server could grant access to additional files by having the permission to create symbolic links in a transitory directory, e.g. /tmp. As of version 2.0.4: Once a verified host address has been identified with a functioning public/private key authentication, the IP address is added to the SkipVerify list, so that time is not wasted in verifying reverse lookups, when the identify can be verified more efficiently and securely by a key mechanism.


Next: , Previous: root=, Up: admit grant and deny

5.2.2 encrypt=true

If this option is set, cfservd will only serve the named files if the copy access type is secure, i.e. on an encrypted link. This presupposes that cfengine has been compiled with a working OpenSSL library.


Previous: encrypt=, Up: admit grant and deny

5.2.3 SkipVerify

If connecting hosts use a Network Address Translator in order to share an IP address, reverse lookup will fail to give a correct verification of host identity. You can switch off cfservd's verification of IP host identity for specific IP addresses or patterns using this command. E.g.

     
     SkipVerify = ( 192.0.0.10  192.0.2.  )
     

This does not affect key verification.

NOTE!! This is a security risk because it means that cfservd implicitly trusts the connecting hosts! You should be very careful in using Network Address Translators in a secure environment. It is not recommended for sites which require a high level of security.

5.3 cfrun

The general syntactic form of the cfrun command is

     
       cfrun -option --longoption class1 class2 ...
     

Since cfrun addresses remote hosts, there is an ambiguity in whether options are intended for the cfrun command itself, on the local host, or whether they are to be passed on to the agent on the remote hosts. To clarify this distinction, the arguments are organized as follows:

     
       cfrun -local options -- remote options -- remote classes
     

Local options are processed by cfrun on the local host; remote options are passed on as options to the remote cfagent (actually to the command defined in cfrunCommand in the file cfservd.conf; remote classes are processed by the remote cfservd service, and specifiy classes which must be satisfied by the remote host in order to invoke the remote command.

The ‘-q’ and ‘-I’ options are always assumed when executing cfengine remotely, so that SplayTime is effectively zero when polling hosts serially, and the output always shows what is happening on the remote hosts. On connecting to a remote host, cfengine attempts to obtain credentials by exchanging keys. Unknown keys, in a key exchange, need to be explicitly accepted on trust. Normally, the interactive cfrun program prompts the user explicitly, (like in the secure shell, ssh, connections). This can be annoying if there are many hosts to connect to. The ‘-T’ option tells cfengine to trust all new keys. This option should be used with caution, and only at times when one is sure that the hosts one is connecting to are trustworthy.

Each host evaluates the classes sent by cfrun and decides whether cfengine should be invoked. Only hosts which belong to the classes defined on the cfrun command line are executed. This allows you to single out groups of hosts which should execute cfengine, based on the very classes which you have defined for your configuration. If no classes are sent on the command line, then all hosts are run.

cfrun uses a configuration file which is located under the CFINPUTS directory in order to determine which hosts and in which order it should try to connect. Because cfengine always uses a reliable TCP protocol for connections, it verifies each connection rather than simply broadcasting openly. Using this file you can even simulate broadcasting to hosts outside your subnet. This file should contain every host name you ever want to configure remotely, because you can still select subsets of the file by specifying classes which the remote host will understand. If the remote host is not in one of the classes you specify when you run cfrun, then it will simply ignore the request. Conversely, if you do not place a host in this file, it will never be contacted when you use the cfrun command. The format of the file is as follows

     
      #
      # Comment ..
      #
      domain=my.domain
      access=user1,user2
      outputdir=directory
      maxchild=number limit
      hostnamekeys=true/false
      bindtointerface=IP address
     
      hostname1            options
      hostname2:port options
      ...
      include=cfrun.site1.external.hosts
      include=cfrun.site1.internal.hosts
      include=cfrun.site2.private.hosts
      include=cfrun.site2.shared.hosts
     
If the option outputdir is present, cfrun forks a separate process for each host and passes the output to files in a named directory. The maxchild line limits the number of forked processes.

It is important to add the domain-name to this file. The options you specifiy in this file, per host, are added to those you might specify on the command line when invoking cfengine remotely. For instance, you might know of a bug on one host and decide not to perform interface configuration on that one machine. You would write a line like this:

     
       funny.domain -- -i  # problem host
     

You could use cfrun inside one of your cfengine configuration files in order to remotely execute cfengine on all of the other network machines, by setting up a host list. The disadvantage however is that cfengine has to poll the systems on the network, which means that cfengine cannot be working in parallel on all hosts.

Some other examples:

     
     e.g.  cfrun -- -- linux          Run on all linux machines
           cfrun -- -p                Ping and parse on all hosts
           cfrun -v -- -p             Ping all, local verbose
           cfrun -v -- -k -- solaris  Local verbose, all solaris, but no copy
     

Amongst the local options, one may specify a subset of the hosts which are to be contacted by cfrun, i.e. to avoid processing the entire list of hosts. For example, to contact only host1 and host2, given that they are already in the list of hosts.

     
     cfrun -v host1 host2
     cfrun -v host1 host2 -- -p
     

5.4 Firewalls and NATs

Firewalls and Network Address Translators (NAT) can be a problem for addressing. Suppose you have a firewall and with a private IP-range behind the firewall. You want to update the nodes from a central host. You can do a two stage configuration: first update the firewall and then update from the firewall to the nodes.

But suppose you already use SNAT (Source Network Address Translation) and DNAT (Destination ...) for the nodes. With DNAT you can say that socket 22000 on the firewall is routed to host-name:5308. DNAT gives us the possibilty to update the nodes from a central server in one step instead of two.

If the port command is given cfrun uses this to connect to the client instead of the default (5308) one. Here is an example (cfrun.hosts):

     domain=example.org
     access=mark,sigmund
     hostnamekeys=true
     
     node1.example.org
     node2.example.org:22000 -DNis
     node2.example.org:22001
     

This connects to: 1) node1 with standard port, 2) node2 with port 22000 and extra options -DNis and, 3) node2 with port 22000.

6 Cfexecd reference

In wrapper mode (non-forking, non-daemon mode), cfagent is run by adding a line to the root crontab file of each system:

     0,30 * * * * /usr/local/sbin/cfexecd -F

This is enough to ensure that cfengine will get run. Any output generated by this job, will be stored in /var/cfengine/outputs.

The program cfexecd operates as a wrapper for cfagent. It has the following options:

     -h (--help)
     -d (--debug)
     -v (--verbose)
     -q (--no-splay)
     -F (--no-fork)
     -1 (--once)
     -g (--foreground)
     -p (--parse-only)
     -L (--ld-library-path)

In addition, if you add the following to the file cfagent.conf, the system administrator will be emailed a summary of any output:

     
     control:
     
     smtpserver    = ( mailhub.example.org ) # site MTA which can talk smtp
     sysadm        = ( mark@example.org )   # mail address of sysadm
     EmailMaxLines = ( n )             # max lines of output to email
     OutputPrefix  = ( "!" )                 # Line prefix
     

Fill in suitable values for these variables. EmailMaxLines may be set to 0 to disable email output, a postive integer to set a limit, or inf to email the whole output regardless of its size. If undefined, EmailMaxLines defaults to 100.

An alternative, or additional way to run cfengine, is to run the cfexecd program is daemon mode (without the ‘-F’) option. In this mode, the daemon lives in the background and sleeps, activating only in accordance with a scheduling policy. The default policy is to run once every hour (equivalent to Min00_05). Here is how you would modify cfagent.conf in order to make the daemon execute cfagent every half-hour:

       control:
     
        # When should cfexecd in daemon mode wake up the agent?
     
        schedule   = ( Min00_05 Min30_35 )

Note that the time specifications are the basic cfengine time classes. Although one of these methods should suffice, no harm will arise from running both cron and the cfexecd side-by-side. Locking mechanisms are used by cfagent to ensure that no contention will occur. Note, that if problems with library path for compiled-in libraries occur, an explicit library path can be specified with the ‘-L’ option.

     0,30 * * * * /usr/local/sbin/cfexecd -F -L /local/iu/lib:/local/lib:/local/gnu/lib

The output generated by a cfagent run is collected and stored with date stamps in the outputs subdirectory of the work directory (usually /var/cfengine/outputs). If cfengine has a valid smtp server configured it will attempt to E-mail new reports to the system administrator. Duplicate reports are suppressed however for a period of one day. Thus, if one has a repeating message, then it will only be sent by E-mail once per day – this feature is meant to prevent cfagent from spamming administators with multiple, indentical reports. As soon a report different from the previous one is received, the memory is reset.

Note: this repeated message suppression feature cannot work if you include time dependent data in messages, i.e. if you include the date or time in an alert, then clearly the message will be a different message each time. Output from cfengine should not contain the time or date, except in the E-mail header.

7 Problem solving

7.1 cf.preconf bootstrap file

In some cases you will want to run cfengine on a system to configure it from scratch. If the system is in a very bad way, it might not even be able to parse the cfengine configuration file, perhaps because the network was not properly configured or the DNS (Domain Name Service) was out of action. To help prevent this situation, cfengine looks for a script called cf.preconf which gets executed prior to parsing and can be used to perform any emergency tests. This file needs only contain enough to get the system to parse the configuration files.

cf.preconf may be any script in any language. It need not exist at all! It is fed one argument by cfengine, namely the system hard-class for the current system (e.g. ultrix). Here is an example:

     #!/bin/sh
     #
     # cf.preconf is an emergency/bootstrap file to get things going
     # in case cfengine is unable to parse its config file
     #
     
     backupdir=/iu/nexus/local/iu/etc
     
      #
      # If these files don't exist, you might not be able to parse cfagent.conf
      #
     
     if [ ! -s /etc/resolv.conf ]; then
     
      echo Patching basics resolv.conf file
      cat > /etc/resolv.conf << XX
     domain iu.hioslo.no
     nameserver 128.39.89.10
     XX
     
     fi
     
     #
     # SVR4
     #
     
     if [ "$1" = "solaris" ]; then
     
       if [ ! -s "/etc/passwd" ]; then
     
       echo Patching missing passwd file
         /bin/cp $backupdir/passwd /etc/passwd
       fi
     
       if [ ! -s "/etc/shadow" ]; then
     
        echo Patching missing passwd file
        /bin/cp $backupdir/shadow /etc/shadow
       fi
     fi
     
     #
     # BSD 4.3
     #
     
     if [ "$1" = "linux" ]; then
     
        if [ ! -s "/etc/passwd"  ]
        then
     
         echo Patching missing passwd file
         /bin/cp $backupdir/passwd.linux /etc/passwd
        fi
     fi
     

Note - in some circumstances, it might be appropriate to exit cfengine altogether after this script. If the script outputs a string containing the text "cfengine-preconf-abort", then cfagent will abort execution immediately after this.

7.2 cfrc resource file

If, for some reason you are not satisfied with the defaults which cfengine uses, then you can change them by making an entry in the resource file. The default values are defined in the source code file classes.c in the distribution. The format of the resource file is:

     hardclass.variable: value

For example, you might want to forget about where your HPUX system mounts its mail directory and mount it under /usr/spool/mail. In this case you would add the line:

     hpux.maildir: /usr/spool/mail

To redefine the filesystem table for GNU/linux, you would write:

     linux.fstab: /etc/linuxfstab

The full list of re-definable resources is:

        mountcomm       # command used to mount filesystems
        unmountcomm     # command used to unmount filesystems
        ethernet        # name of the ethernet device
        mountopts       # options to above mount command
        fstab           # the name of the filesystemtable
        maildir         # the location of the mail directory
        netstat         # the full path to netstat and options
        pscomm          # the path to the system's ps command
        psopts          # the options used by ps (default aux/ef)

You should never need to redefine resources unless you decide to do something non-standard. Interested readers are referred to the values in classes.c.

Cfengine is easily extensible so as to support a variety of architectures. You can even add your own. To do so you need, first of all, to define a new class for the operating system concerned. The file classes.c has been separated off from the remainder of the source code so that you can easily see which data structures need to be extended.

To make life as straightforward as possible, three unused classes have been defined. They are called (unremarkably) unused1, unused2 and unused3. If you add any further classes, it will be necessary to increase the constant clssattr defined in cf.defs.h by one for every new addition. You do not need to change clssattr if you simple replace one of the unused classes by a real class.

To see fully the impact of what you need to do, you should make a search for the strings unused? in all of the source files. Certain special cases need to be handled for each operating system. For example, the form of the filesystem table is quite radically different on some systems such as AIX. One thing you must do is to fill in the default values for the new operating system in the file classes.c.

If you fill in the details for a new operating system before it finds its way into a new release, you might consider sending the details to the bug list in the next paragraph.


Next: , Previous: Problem solving, Up: Top

8 Example configuration files

Here is a sample from a large configuration file, just to give you some ideas. The file is broken up into manageable pieces for convenience.

8.1 cfagent.conf

     #####################################################################
     #
     #  CFENGINE CONFIGURATION FOR site = iu.hioslo.no
     #
     #  This file is for root only.
     #
     ######################################################################
     
     ###
     #
     # BEGIN cfagent.conf
     #
     ###
     
     import:
     
        #
        # Split things up to keep things tidy
        #
     
        any::
                         cf.groups
                         cf.main
                         cf.site
                         cf.motd
     
        hpux::           cf.hpux
        linux::          cf.linux
        solaris::        cf.solaris
        sun4::           cf.sun4
        ultrix::         cf.ultrix
        freebsd::        cf.freebsd
     
        #
        # Do you want to do this ?
        #
     
        AllHomeServers:: cf.users
     
     
     ###
     #
     # END cfengine.conf
     #
     ###

8.2 cf.groups

     ##############################################################
     #
     # cf.groups - for iu.hioslo.no
     #
     # This file contains  all group/class definitions
     #
     #################################################################
     
     ###
     #
     # BEGIN cf.groups
     #
     ###
     
     groups:
     
        #
        # Define some groups
        #
     
        iu = ( nexus ferengi regula borg dax lore axis worf daystrom voyager
               aud1 aud2 aud3 aud4 bajor ds9 takpah takpeh nostromo galron
               thistledown rama chaos pc-steinarj pc-hildeh way jart kosh )
     
        diskless   = ( regula ferengi lore )
     
        standalone = ( nexus axis dax borg worf daystrom voyager
                       aud1 aud2 aud3 aud4 bajor ds9 takpah takpeh
                       nostromo galron thistledown rama pc-torejo
                       pc-steinarj pc-hildeh )
     
        AllHomeServers   = ( nexus )
        AllBinaryServers = ( nexus borg )
     
        XBootServer  = ( nexus )
        WWWServers   = ( nexus )
        FTPserver    = ( nexus )
        NameServers  = ( nexus )
        PasswdServer = ( nexus )
        BackupHost   = ( nexus )
     
        MailHub      = ( nexus )
        MailClients  = ( iu -nexus )
     
     ###
     #
     # END cf.groups
     #
     ###
     


Next: , Previous: cf.groups, Up: Example configuration file

8.3 cf.main

     ##############################################################
     #
     # cf.main - for iu.hioslo.no
     #
     # This file contains generic config stuff
     #
     #################################################################
     
     ###
     #
     # BEGIN cf.main
     #
     ###
     
     control:
     
        access    = ( root )        # Only root should run this
     
        site      = ( iu )
        domain    = ( iu.hioslo.no )
        sysadm    = ( drift@iu.hioslo.no )
     
        repository = ( /var/spool/cfengine )
     
        netmask   = ( 255.255.255.0 )
        timezone  = ( MET )
        nfstype   = ( nfs )
     
        sensiblesize  = ( 1000 )
        sensiblecount = ( 2 )
        editfilesize  = ( 20000 )
     
        mountpattern = ( /$(site)/$(host) )
        homepattern  = ( u? )
     
        #
        # If we undefine this with cfengine -N longjob
        # then we switch off all jobs labelled with this class
        #
     
        addclasses = ( longjob )
     
        #
        # Macros & constants are inherited downwards in imports
        # but are not passed up to parent files. Good idea to
        # define them all here
        #
     
        masterfiles = ( /iu/nexus/local/iu )
        main_server = ( nexus )
        cfbin       = ( /iu/nexus/local/gnu/lib/cfengine/bin )
        gnu         = ( /local/gnu )
        ftp         = ( /local/iu/ftp )
        nisslave    = ( dax )
        nisfiles    = ( /iu/nexus/local/iu/etc )
     
        #
        # The action sequence for daily (full) runs and
        # for hourly updates (called with -DHourly)
        #
     
        Hr00::
     
           actionsequence =
              (
              copy
              mountall
              mountinfo
              checktimezone
              netconfig
              resolve
              unmount
              shellcommands
              addmounts
              links.Prepare
              files.Prepare
              directories
              links.Rest
              mailcheck
              mountall
              required
              tidy
              disable
              editfiles
              files.Rest
              processes
              )
     
        !Hr00::
     
           actionsequence =
              (
              resolve
              shellcommands
              copy
              editfiles
              processes
     	 links
              )
     
        force::
     
           actionsequence =
              (
              files.Prepare.Rest
              tidy
              )
     
     ######################################################################
     
     homeservers:
     
        iu:: nexus
     
     binservers:
     
        iu.solaris::                 nexus
        iu.linux::                   borg
     
     mailserver:
     
        any:: nexus:/var/mail
     
     mountables:
     
        any::
              nexus:/iu/nexus/u1
              nexus:/iu/nexus/u2
              nexus:/iu/nexus/u3
              nexus:/iu/nexus/u4
              nexus:/iu/nexus/u5
              nexus:/iu/nexus/u6
              nexus:/iu/nexus/ua
              nexus:/iu/nexus/ud
              nexus:/iu/nexus/local
              nexus:/opt/NeWSprint
              nexus:/opt/AcroRead
              borg:/iu/borg/local
              dax:/iu/dax/local
     
     miscmounts:
     
        linux||freebsd::   nexus:/iu/nexus/local /iu/nexus/local ro
     
     ######################################################################
     
     broadcast:
     
       ones
     
     defaultroute:
     
        cadeler30-gw
     
     ######################################################################
     
     resolve:
     
           128.39.89.10  # nexus
           158.36.85.10  # samson.hioslo.no
           129.241.1.99
     
     ######################################################################
     
     tidy:
     
        #
        # Some global tidy-ups
        #
     
           /tmp/                    pat=*             r=inf     A=1
           /var/tmp                 pat=*             r=inf     A=1
           /                        pat=core          r=1       A=0
           /etc                     pat=core          r=1       A=0
     
     ######################################################################
     
     ignore:                       # Don't check or tidy these directories
     
           /local/lib/gnu/emacs/lock/
           /local/tmp
           ftp
           projects
           /local/bin/top
           /local/lib/tex/fonts
           /local/iu/etc
           /local/etc
           /local/iu/httpd/conf
           /usr/tmp/locktelelogic
           /usr/tmp/lockIDE
           RootMailLog
     
           #
           # Emacs lock files etc
           #
     
           !*
           /local/lib/xemacs
     
           #
           # X11 keeps X server data in /tmp/.X11
           # better not delete this!
           #
     
           .X11
     
           #
           # Some users like to give a file or two 777 protection here
           # so netsurfers can update a log or counter when running as
           # `nobody'
           #
     
           www
     
     #####################################################################
     
     disable:
     
        /etc/hosts.equiv
        /etc/nologin
        /usr/lib/sendmail.fc
     
     
     ###
     #
     # END cf.main
     #
     ###
     


Next: , Previous: cf.main, Up: Example configuration file

8.4 cf.site

     ##############################################################
     #
     # cf.site - for iu.hioslo.no
     #
     # This file contains site specific data
     #
     #################################################################
     
     ###
     #
     # BEGIN cf.site
     #
     ###
     
     links:
     
        Prepare::
     
           /local     -> /$(site)/$(binserver)/local
           /usr/local -> /local
     
        dax::
     
           /iu/dax/local             +> /iu/nexus/local
           /projects                 -> /iu/dax/local/projects
           /iu/nexus/u1/sowille/data -> /iu/dax/scratch/data
     
        XBootServer::
     
           #
           # Set up a /local/tftpboot area where all X terminal
           # stuff will be kept.
           #
     
           /tftpboot                  -> /local/tftpboot
           /local/tftpboot/td/configs -> /local/tftpboot/td/examples/configs
           /etc/bootptab              -> /tftpboot/bootptab
           /tftpboot/usr/lib/X11/td   -> /tftpboot/td
     
        NameServers::
     
           /etc/named.boot -> /local/iu/named/named.boot
     
        MailHub::
     
           /etc/mail/sendmail.cf ->! /iu/nexus/local/mail/sendmail.cf
     
        MailClients.solaris::
     
           /etc/mail/sendmail.cf ->! /iu/nexus/local/mail/client.cf
     
        nexus::
     
     	/local/bin +> /local/latex/bin
     
     #############################################################
     
     disable:
     
       #
       # We run Berkeley sendmail and the config files are
       # all under /iu/nexus/local/lib/mail
       #
     
         /etc/aliases
     
      WWWServers.Sunday::
     
        #
        # Disabling these log files weekly prevents them from
        # growing so enormous that they fill the disk!
        #
     
        /local/iu/httpd/logs/access_log   rotate=empty
        /local/iu/httpd/logs/agent_log    rotate=empty
        /local/iu/httpd/logs/error_log    rotate=empty
        /local/iu/httpd/logs/referer_log  rotate=empty
     
        #
        # CERT warning, security fix
        #
     
       any::
     
         /usr/lib/expreserve
     
       FTPserver.Sunday.Hr00::
     
        /local/iu/xferlog rotate=3
     
     #################################################################
     
     files:
     
       Prepare::
     
           /etc/motd              m=0644 r=0 o=root act=touch
           /.cshrc                m=0644 r=0 o=root act=touch
     
        PasswdServer::
     
           /local/iu/etc/passwd m=0644 o=root g=other action=fixplain
           /local/iu/etc/shadow m=0644 o=root g=other action=fixplain
     
        WWWServers.Rest::
     
           /local/iu/www                           m=775        g=www act=fixall r=inf
           /local/iu/httpd/conf                    m=664 o=root g=www act=fixall r=inf
           /local/iu/www/cgi-bin-public/count_file m=777 o=root g=www act=fixplain
     
        FTPserver::
     
           #
           # Make sure anonymous ftp areas have the correct
           # protection, or logins won't be able to read
           # files - or perhaps a security risk. This is
           # Solaris 2 specific...
           #
     
           $(ftp)/pub        mode=755 o=ftp  g=ftp  r=inf act=fixall
           $(ftp)/Obin       mode=111 o=root g=other      act=fixall
           $(ftp)/etc        mode=111 o=root g=other      act=fixdirs
           $(ftp)/usr/bin/ls mode=111 o=root g=other      act=fixall
           $(ftp)/dev        mode=555 o=root g=other      act=fixall
           $(ftp)/usr        mode=555 o=root g=other      act=fixdirs
     
        Prepare::
     
           /etc/shells mode=0644 action=touch
     
        AllBinaryServers.Rest.longjob::
     
          /local mode=-0002 r=inf owner=root,bin group=0,1,2,3,4,5,6,7,staff
                 links=tidy action=fixall
     
          /local/iu/RootMailLog  m=0666 action=touch
     
        dax.Rest::
     
         /iu/dax/scratch        r=0 o=root mode=1777 action=fixall
         /iu/dax/local/projects r=0 o=root mode=755  action=fixdirs
     
        nexus::
     
         /local/mail/sendmail.cf o=root m=444 act=fixplain
     
         /iu/nexus/ua/robot/.rhosts o=robot m=600 act=touch
     
         /local/iu/named/pz         o=root  m=644 act=fixall r=1
     
         /local/latex/lib/tex/texmf/fonts  owner=root
                                           mode=1666
                                           recurse=inf
                                           action=fixall
     
     #################################################################
     
     tidy:
     
           #
           # Make sure the file repository doesn't fill up
           #
     
           /var/spool/cfengine pattern=*    age=3
     
           /var                pattern=core age=0  r=inf
           /var/spool/mqueue   pattern=*    age=14 type=mtime
     
        BackupHost::
     
           # Here we tidy old backup tar files from the backup area
           # A special tmp area gets cleared every 4 days. The files
           # are created by Audun's backup help script (see shellcommands)
     
           /iu/nexus/backup1      pat=*  age=7
     
     #################################################################
     
     shellcommands:
     
        PasswdServer::
     
           # Build and install the BSD compatible passwd file
           # from the master passwd/shadow file on Solaris
     
           "/local/iu/bin/BuildPasswdFiles"
           "/local/iu/bin/BuildGroupFiles"
     
       BackupHost.Sunday.Hr00|BackupHost.Wednesday.Hr00::
     
           #
           # Make a system backup of /iu/nexus/u? with Audun's script
           #
     
           "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/ud"
           "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/ua"
           "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/u1"
           "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/u2"
           "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u3"
           "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u4"
           "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u5"
           "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u6"
     
       nexus.Sunday.longjob.Hr00::
     
           #
           # See how much rubbish users have accumulated each Sunday
           #
     
           "$(cfbin)/noseyparker /iu/nexus/u1 $(sysadm) "
           "$(cfbin)/noseyparker /iu/nexus/u2 $(sysadm) "
           "$(cfbin)/noseyparker /iu/nexus/u3 $(sysadm) "
           "$(cfbin)/noseyparker /iu/nexus/u4 $(sysadm) "
           "$(cfbin)/noseyparker /iu/nexus/u5 $(sysadm) "
           "$(cfbin)/noseyparker /iu/nexus/u6 $(sysadm) "
           "$(cfbin)/noseyparker /iu/nexus/ua $(sysadm) nomail"
           "$(cfbin)/noseyparker /iu/nexus/ud $(sysadm) nomail"
     
        nexus.longjob.Hr00::
     
           #
           # Update the GNU find/locate database each night
           #
     
           "$(gnu)/lib/locate/updatedb"
           "/local/iu/bin/newhomepage.sh"
     
     ###############################################################
     
     editfiles:
     
         #
         # cfengine installs itself as a cron job - sneaky! :)
         #
     
         { /var/spool/cron/crontabs/root
     
         AppendIfNoSuchLine "0 * * * * $(cfbin)/cfwrap $(cfbin)/cfhourly"
         }
     
        FTPserver::
     
           { /etc/shells
     
           AppendIfNoSuchLine "/bin/tcsh"
           AppendIfNoSuchLine "/local/gnu/bin/bash"
           }
     
     
        XBootServer::
     
           { /etc/inetd.conf
     
           AppendIfNoSuchLine
               "bootp dgram udp wait root /local/bin/bootpd bootpd -i -d"
           }
     
        nexus::
     
           { /iu/nexus/ua/robot/.rhosts
     
           AppendIfNoSuchLine "borg"
           AppendIfNoSuchLine "borg.iu.hioslo.no"
           AppendIfNoSuchLine "aud4"
           AppendIfNoSuchLine "aud4.iu.hioslo.no"
           }
     
        dax::
     
           { /etc/system
     
           AppendIfNoSuchLine "set pt_cnt=128"
           }
     
     
     ######################################################################
     
     required:
     
        #
        # Any host must have a /local, /usr/local fs. Check that
        # it exists and looks sensible. (i.e. not empty)
        #
     
        /$(site)/$(binserver)/local
     
     
     ######################################################################
     
     copy:
     
        #
        # NIS seems broken at IU, so here we use NFS to fudge
        # a file distribution as a temporary solution. Actually
        # this makes the system work faster without NIS!
        #
     
           $(nisfiles)/services dest=/etc/services o=root g=other mode=0644
           $(nisfiles)/hosts.deny dest=/etc/hosts.deny o=root mode=0644
     
        !debian::
     
           $(nisfiles)/hosts    dest=/etc/hosts o=root g=other mode=0644
     
        PasswdServer::
     
           /etc/passwd dest=$(nisfiles)/passwd o=root g=other mode=0644
           /etc/shadow dest=$(nisfiles)/shadow o=root g=other mode=0644
     
        nexus::
     
           /local/iu/etc/dfstab dest=/etc/dfs/dfstab  o=root  mode=0744
     
        solaris.!PasswdServer::
     
           $(nisfiles)/passwd dest=/etc/passwd o=root g=other mode=0644
           $(nisfiles)/shadow dest=/etc/shadow o=root g=other mode=0600
           $(nisfiles)/group.solaris dest=/etc/group o=root g=other mode=0644
     
        linux::
     
           $(nisfiles)/passwd.linux dest=/etc/passwd o=root g=other mode=0644
           $(nisfiles)/group.linux dest=/etc/group o=root g=other mode=0644
     
     ###############################################################
     
     processes:
     
           "eggdrop"                           signal=kill
           "irc"                               signal=kill
           "ping"                              signal=kill
           "NetXRay"                           signal=kill
           "netxray"                           signal=kill
           "ypserv"                            signal=kill
           "ypbind"                            signal=kill
           "rarpd"                             signal=kill
           "rpc.boot"                          signal=kill
           "README"                            signal=kill # You don't sh README !
     
        !XBootServer::
     
           "bootp"                             signal=kill
     
        #
        # These processes are not killed every hour, but once a day
        # when cfengine runs at night. Note that there are often
        # hanging pine and elm processes. These programs crash and
        # go berserk, using hundreds of hours of CPU time.
        #
     
        Hr00::
     
           "cron"                 signal=hup  # HUP these to update their config
           "inetd"                signal=hup
     
           "/local/sdt/sdt/bin"   signal=term # For those elektro dudes who forget
                                              # to log out
           "netscape"             signal=kill
           "pine"                 signal=kill
           "elm"                  signal=kill
     
     
     ###
     #
     # END cf.site
     #
     ###
     


Next: , Previous: cf.site, Up: Example configuration file

8.5 cf.motd

     
     ##################################################################
     #
     # cf.motd
     #
     # This file is used to set the message of the day file on
     # each host
     #
     ##################################################################
     
      #####
      #
      # BEGIN cf.motd
      #
      #####
     
     
     control:
     
        #
        # This points to the file containing general text
        #
     
        masterfile      = ( /iu/nexus/local/iu/etc/motd-master )
        local_message   = ( /etc/motd.local )
     
     editfiles:
     
           { /etc/motd
     
           BeginGroupIfFileIsNewer "$(masterfile)"
             EmptyEntireFilePlease
             InsertFile "$(masterfile)"
             InsertFile "$(local_message)"
             PrependIfNoSuchLine "This system is running $(class):$(arch)"
           EndGroup
           }
     
      #####
      #
      # BEGIN cf.motd
      #
      #####
     


Next: , Previous: cf.motd, Up: Example configuration file

8.6 cf.users

Whether or not you perform any special services for users, with or without their consent is entirely a matter of local policy. In a school or college situation, users are often uncooperative and some are even irresponsible. This file shows you what you could do in an environment with inexperienced users, but please don't feel as though you have to be this totalitarian.

     #################################################################
     #
     # cf.users - for iu.hioslo.no
     #
     # This file contains user specific actions
     #
     #################################################################
     
     ###
     #
     # BEGIN cf.users
     #
     ###
     
     ignore:
     
         robot
     
     tidy:
     
        longjob::
     
          #
          # Some users just don't understand what they are doing
          # and this is safest, allbeit totalitarian
          #
     
          home                 pat=.rhosts                      age=0
     
          #
          # Tidy up users' home dirs
          #
     
          home                 pat=core             r=inf       age=0
          home                 pat=a.out            r=inf       age=1
          home                 p=*%                 r=inf       age=2
          home                 p=*~                 r=inf       age=2
          home                 p=#*                 r=inf       age=1
          home                 p=*.dvi              r=inf       age=14   type=ctime
          home                 p=*.log              r=inf       age=2
          home                 p=Log.*              r=inf       age=3
          home                 p=CKP                r=inf       age=1
          home                 p=BAK                r=inf       age=1
          home                 p=log                r=inf       age=0
          home                 p=*.o                r=inf       age=0
          home                 p=*.aux              r=inf       age=3
          home                 p=*.zip              r=inf       age=7
          home/.deleted        p=*                  r=inf       age=0
          home/.wastebacket    p=*                  r=inf       age=14
          home/www             p=*~                 r=inf       age=1
     
          #
          # Clear the big cache files netscape creates
          #
     
          home/.netscape-cache  p=cache????*         r=inf       age=0
          home/.MCOM-cache      p=cache????*         r=inf       age=0
          home/.netscape/cache  p=*                  r=inf       age=0
     
     
     #################################################################
     
     files:
     
        AllHomeServers.longjob.rest::
     
          #
          # Check users files are not writable to the world
          # and there are no stale links (pointing nowhere)
          #
     
          home mode=o-w recurse=inf action=fixall # links=tidy
     
          home/.xsession mode=755 action=fixall
          home/.cshrc    mode=755 action=fixall
     
     #################################################################
     
     copy:
     
        Hr00.longjob::
     
        #
        # Make sure each user has an up to date standard
        # setup.  Cshrc just sources in a big standard file
        # which is kept in ~user/../.setupfiles/cshrc
        # to reduce disk wastage
        #
     
        $(masterfiles)/lib/Cshrc   dest=home/.cshrc
        $(masterfiles)/lib/tkgrc   dest=home/.tkgrc
        $(masterfiles)/lib/fvwm2rc dest=home/.fvwm2rc
     
     
     ###
     #
     # END cf.users
     #
     ###


Next: , Previous: cf.users, Up: Example configuration file

8.7 cf.solaris

     #################################################################
     #
     # cf.solaris - for iu.hioslo.no
     #
     # This file contains Solaris specific patches
     #
     #################################################################
     
     ###
     #
     # BEGIN cf.solaris
     #
     ###
     
     directories:
     
          #
          # httpd/netscape want this to exist for some bizarre reason
          #
     
           /usr/lib/X11/nls
     
     ################################################################
     
     tidy:
     
          /var/log  pattern=syslog.* age=0
     
        MailHub::
     
          /var/mail pattern=lp       age=0
     
     #################################################################
     
     files:
     
       #
       # If this doesn't exist fork will not work and the
       # system will not even be able to run the /etc/rc
       # scripts at boottime
       #
     
       /etc/system     o=root g=root m=644 action=touch
     
       /var/log/syslog o=root        m=666 action=touch
     
     #############################################################
     
     copy:
     
        #
        # Some standard setup files, can't link because
        # machine won't boot if their not on / partition.
        #
     
        /local/bin/tcsh dest=/bin/tcsh mode=755
     
        /local/iu/etc/nsswitch.standalone dest=/etc/nsswitch.conf
     
       #
       # Our named server uses a newer BIND
       # Put this here so that it will be preserved under
       # Solaris reinstallation
       #
     
       NameServers::
     
        /local/iu/sbin/in.named         dest=/usr/sbin/in.named         mode=555
        /local/iu/sbin/in.named.reload  dest=/usr/sbin/in.named.reload  mode=555
        /local/iu/sbin/in.named.restart dest=/usr/sbin/in.named.restart mode=555
        /local/iu/sbin/in.ndc           dest=/usr/sbin/in.ndc           mode=555
        /local/iu/sbin/named-xfer       dest=/usr/sbin/named-xfer       mode=555
        /local/iu/lib/nslookup.help     dest=/usr/lib/nslookup.help     mode=444
     
       any::
        /local/iu/lib/libresolv.a        dest=/usr/lib/libresolv.a      mode=444
        /local/iu/lib/libresolv.so.2     dest=/usr/lib/libresolv.so.2   mode=444
        /local/bin/nslookup              dest=/usr/sbin/nslookup        mode=444
     
     ##############################################################
     
     editfiles:
     
           { /etc/netmasks
     
           AppendIfNoSuchLine "128.39  255.255.255.0"
           }
     
           { /etc/defaultrouter
     
           AppendIfNoSuchLine "128.39.89.1"
           }
     
           { /usr/openwin/lib/app-defaults/XConsole
     
           AppendIfNoSuchLine "XConsole.autoRaise: on"
           }
     
        #
        # CERT security patch for vold vulnerability
        #
     
        { /etc/rmmount.conf
     
        HashCommentLinesContaining "action cdrom"
        HashCommentLinesContaining "action floppy"
        }
     
     ##############################################################
     
     disable:
     
         /etc/.login  type=file
         /etc/aliases
     
        #
        # These files are ENORMOUS, don't let them fill the disk
        #
     
        Wednesday::
     
           /var/lp/logs/lpsched rotate=empty
     
           /var/adm/wtmpx       rotate=empty
           /var/adm/wtmp        rotate=empty
     
     ##############################################################
     
     files:
     
         /etc/passwd        m=0644 o=root g=other action=fixplain
         /etc/shadow        m=0600 o=root g=other action=fixplain
         /etc/defaultrouter m=0644 o=root g=other action=touch
         /var/adm/wtmpx     m=0664 o=adm  g=adm   action=touch
         /var/adm/wtmp      m=0644 o=root g=adm   action=touch
         /var/adm/utmp      m=0644 o=root g=adm   action=fixplain
         /var/adm/utmpx     m=0664 o=adm  g=adm   action=fixplain
     
         /tmp m=1777                              action=fixdirs
     
     ##############################################################
     
     disable:
     
        #
        # CERT security patch
        #
     
        /usr/openwin/bin/kcms_calibrate
        /usr/openwin/bin/kcms_configure
        /usr/bin/admintool
     
     ################################################################
     
     shellcommands:
     
        AllBinaryServers.Saturday.longjob.Hr00::
     
           #
           # Make sure the man -k / apropos data are up to date
           #
     
           "/usr/bin/catman  -M /local/man"
           "/usr/bin/catman  -M /local/X11R5/man"
           "/usr/bin/catman  -M /usr/man"
           "/usr/bin/catman  -M /local/gnu/man"
           "/usr/bin/catman  -M /usr/openwin/share/man"
           "/usr/bin/catman  -M /local/X11R5/man"
           "/usr/bin/catman  -M /usr/share/man"
     
     ################################################################
     
     editfiles:
     
     
           #
           # A painless way to add an rc.local script to the rc files
           # under Solaris without having to fight though inittab
           #
     
           { /etc/rc3.d/S15nfs.server
     
           AppendIfNoSuchLine "sh /local/iu/etc/rc.local"
           }
     
           #
           # umask defined when inetd starts is inherited by all subprocesses
           # including ftpd which saves with mode 666 (!) unless we do this
           #
     
           { /etc/rc2.d/S72inetsvc
     
           PrependIfNoSuchLine "umask 022"
           }
     
     
     ###
     #
     # END cf.solaris
     #
     ###
     

8.8 cf.linux

     #################################################################
     #
     # cf.linux - for iu.hioslo.no
     #
     # This file contains debian linux specific patches
     #
     #################################################################
     
     ###
     #
     # BEGIN cf.linux
     #
     ###
     
     files:
     
           /etc/printcap m=644 o=root action=fixplain
     
          #
          # Cert advisories
          #
     
           /bin/mount         m=755 o=root action=fixall
           /bin/umount        m=755 o=root action=fixall
     
     #######################################################################
     
       disable:
     
          #
          # Cert advisories
          #
     
           /sbin/dip-3.3.7n
     
     ########################################################################
     
     links:
     
         /local/bin/tcsh   ->  /bin/tcsh
     
         /local/lib/mail   ->  /$(site)/$(main_server)/local/lib/mail
     
     ########################################################################
     
     editfiles:
     
       #
       # Samba default mode needs to be set...
       #
     
        { /etc/smb.conf
     
        ReplaceAll "700" With "644"
        }
     
       #
       # Linux date is very stupid and needs a very careful
       # TZ definition, otherwise it loses
       #
     
        { /etc/csh.cshrc
     
        AppendIfNoSuchLine "setenv TZ 'MET-1MET DST-2,M3.5.0/2,M10.5.0/3'"
        }
     
       #
       # resolv+ ordering
       #
     
        { /etc/host.conf
     
        PrependIfNoSuchLine "order bind"
        }
     
     
       #
       # Should have been configured already (!)
       #
     
        { /etc/ld.so.conf
     
        AppendIfNoSuchLine "/usr/X11R6/lib"
        }
     
       #
       # Kill annoying messages
       #
     
        { /etc/cron.daily/standard
     
        HashCommentLinesContaining "security"
        }
     
     #########################################################################
     
     shellcommands:
     
       Hr00::
     
          #
          # Find/locate database
          #
     
          "/usr/bin/updatedb"
     
     ###
     #
     # END cf.linux
     #
     ###
     
     

8.9 cf.freebsd / cf.netbsd

FreeBSD, OpenBSD and NetBSD are sufficiently similar to have a single file for all.

     #################################################################
     #
     # cf.bsd - for iu.hioslo.no
     #
     # This file contains bsd specific patches
     #
     #################################################################
     
     ###
     #
     # BEGIN cf.bsd
     #
     ###
     
     links:
     
         /usr/spool        ->  /var/spool
         /local/bin/tcsh   ->  /bin/tcsh
         /local/bin/perl   ->  /usr/bin/perl
         /usr/lib/sendmail ->  /usr/sbin/sendmail
     
     #################################################################
     
     files:
     
        /usr/tmp mode=1777 owner=root action=fixall
     
     #################################################################
     
     editfiles:
     
        #
        # Comment out all lines to shut up this annoying cfengine-like
        # script, which sends mail every day!!!
        #
     
        { /etc/crontab
     
        HashCommentLinesContaining "daily"
        HashCommentLinesContaining "weekly"
        HashCommentLinesContaining "monthly"
        }
     
     #################################################################
     
     copy:
     
           $(masterfiles)/etc/printcap.client      dest=/etc/printcap mode=0644
     
     #########################################################################
     
     shellcommands:
     
       Hr00::
     
         "/usr/libexec/locate.updatedb"
         "/usr/bin/makewhatis /usr/share/man:/usr/X11R6/man"
     
     ###
     #
     # END cf.bsd
     #
     ###
     
     

8.10 cfservd.conf tutorial

     #########################################################
     #
     # This is a cfservd config file
     #
     #########################################################
     
      #
      # Could import cf.groups here and use a structure like
      # in cfengine.conf, cf.main, cf.groups
      #
     
     control:
     
       public = ( /usr/local/publicfiles )
     
       almost_public = ( /usr/local/almostpublicfiles )
     
       cfrunCommand = ( /iu/nexus/ud/mark/comp/Tests/cfrun-command )
     
       MaxConnections = ( 10 )
     
     #########################################################
     
     admit:   # or grant:
     
          $(public) *
     
          $(almost_public) *.iu.hioslo.no *.gnu.ai.mit.edu
     
          /etc/passwd *.iu.hioslo.no
     
          #
          # Who can exec cfengine remotely?
          #
     
          $(cfrunCommand) *.iu.hioslo.no
     
     #########################################################
     
     deny:
     
          $(public)/special *.moneyworld.com
     
     


Next: , Previous: Example configuration file, Up: Top

Variable Index


Next: , Previous: Variable Index, Up: Top

Concept Index


Previous: Concept Index, Up: Top

FAQ Index

Table of Contents

cfengine-2.2.10/doc/cfengine-Reference.info-20000644000175000001440000047424711170173455015550 00000000000000This is cfengine-Reference.info, produced by makeinfo version 4.12 from cfengine-Reference.texinfo. INFO-DIR-SECTION System Utilities START-INFO-DIR-ENTRY * cfengine Reference: (cfengine-Reference.info). Cfengine is a language based tool specifically designed for configuring and maintaining BSD and System-5-like operating systems attached to a TCP/IP network. END-INFO-DIR-ENTRY  File: cfengine-Reference.info, Node: packages, Next: rename, Prev: processes, Up: Cfagent reference 4.32 Packages ============= The packages action allows you to check for the existance of packages on the system, as determined by the package database you select. Optionally, if a package install command was specified, the package can be installed if it is not there. This operation is set up such that it tries not to make assumptions about the package manager in use. For example, it should be possible to use RPM on a Solaris box. The syntax summary is: packages: CLASS:: PACKAGE-NAME pkgmgr=none/RPM/DPKG/SUN/AIX/PORTAGE/FREEBSD cmp=eq/LT/GT/GE/LE/NE version=VERSION-STRING define=CLASS-LIST(,:.) elsedefine=CLASS-LIST(,:.) action=none/INSTALL/REMOVE/UPGRADE/FIX ifelapsed=MINS expireafter=MINS audit=TRUE/ON/FALSE/OFF inform=TRUE/ON/FALSE/OFF EXAMPLES: packages: # install newpackage 1.10 if newpackage 1.0 or greater isn't installed newpackage-1.10 action=install cmp=ge version=1.0 # upgrade any installed versions of compromised to at least 1.2 compromised-1.2 action=upgrade version=1.2 cmp=le # Make sure that version 1.2 is installed compromised-1.2 action=fix version=1.2 cmp=le # remove any version of useless useless action=remove version=0.1 cmp=ge `action' Determines the action taken if the comparison matches. * `install' Install this package if the version comparison does not match. * `upgrade' Upgrade this package if the version comparison does match. * `fix' Install or Upgrade this package if the version comparison does match. * `remove' Uninstall this package if the version comparison does match. `cmp' Determines how the version of the installed package will be compared to that specified by the `version' attribute. Possible values include: * `eq' The version installed must be equal to `version' * `lt' The version installed must be less than `version' * `gt' The version installed must be greater than `version' * `le' The version installed must be less than or equal to `version' * `ge' The version installed must be creater than or equal to `version' * `ne' The version installed must not be equal to `version' The default value for this attribute is `eq'. Note that `cmp' is used differently for install versus upgrade, fix and remove. The action is performed when false for install, but when true for upgrade, fix or remove. `version' Specifies the package manager specific version string to match. If this is not specified, then any version matches, and the value of the `cmp' attribute is ignored. See the allowed values of `pkgmgr' below for an explation of how each package manager will interpret this. `pkgmgr' Selects the package manager database to query. This defaults to either the value of the `DefaultPkgMgr' variable, or if that is not set, there is no default. In that case, no checking will be done unless `pkgmgr' is set explicitly for each package. Note that the default value '`none'' listed is merely a pseudo-value, and cannot actually be used, since it would make no sense anyway. Each package manager will interpret the `version' and `cmp' attributes in its own way. For example, when you use `pkgmgr=rpm', the comparison will be done with the same rules that RPM use if it were not being run through cfengine. Freebsd actually invokes the standard system utility to do the comparisons for it, etc. Currently, the following package managers are supported: `rpm' This uses the rpm command, which cfengine expects to find as `/bin/rpm' to query the machine's RPM database. The `rpm' check assumes that you are using a version of RPM that understands the concept of an epoch, which means that you will want to use RPM version 3.0.3 or greater. Versions as early as 2.5.6 may work, but it is doubtful. If multiple packages of the same name are installed (i.e. kernel), then the check considers the package to be installed at the specified version if at least one of them satisifies the criteria specified by `cmp' and `version'. The format of a RPM version string is: [epoch:]version[-release]. The version[-release] can be seen by simply running: `rpm -q '. In order to see the epoch, you must use a query format, like this: `rpm -q --queryformat "%{EPOCH}:%{VERSION}-%{RELEASE}\n" '. Most packages do not have an epoch, and will print `(none)' in the epoch space. In recent incarnations of RPM, the absense of an epoch is interpreted as 0. This is also how cfengine will interpret it. _Be careful with this. If the installed version of a package has an epoch greater than 0, and you do not specify the epoch, unexpected results may happen._ For example, if you have a package installed, `foo-1:2.0-1', and you specify a `version=3.0-1' and a `cmp=gt', the check will be true, because the installed version has an epoch of 1, and you did not specify an epoch, which implies you wanted an epoch of 0. The rule here is basically to always check the epoch of the package you really want, and specify it. It may take a few extra extra seconds to check, but it will save you lots of headaches later. `portage' This uses the emerge command to install packages on a Gentoo Linux system. The `portage' Python module is used to query the system and find installed packages. The package_name and version support any package that conforms to the Gentoo package naming specification `http://www.gentoo.org/proj/en/devrel/handbook/handbook.xml?part=2&chap=1#doc_chap2_sect2', and even most of those in the Portage tree that do not. Because Gentoo package atoms are flexible, you can use the name of the package, along with a version and the cmp cfengine logic, or you can put the comparison operator and version in the package_name field and leave out the cmp operator. Because cfengine builds the install string out of the package name, and ignores the version you were comparing against, using a package atom with a version is the only way to have a specific version emerged. packages: any:: # if the version of tar is less than 1.16-r2, # then the *latest* version of tar will be installed: app-arch/tar cmp=ge version=1.16-r2 action=install # This is equivalent, but uses the package atom to # define the version comparison: >=app-arch/tar-1.16-r2 action=install `dpkg' Please document me! `sun' Please document me! `freebsd' FreeBSD has fully working install/upgrade/delete management for packages. You can either get the latest version from a package repository, or define the explicit version to install. # install new package from FreeBSD ports tree control: DefaultPkgMgr = ( freebsd ) FreeBSDInstallCommand = ( "/usr/sbin/pkg_add -r %s" ) packages: bsdsar action=install # install a specific version from a local repository control: DefaultPkgMgr = ( freebsd ) FreeBSDInstallCommand = ( "/usr/sbin/pkg_add http://server/path/%s" ) packages: bsdsar-1.10_2 action=install Note that specifying the version of the package that is part of the freebsd package filename is required if not using "-r" mode. It does not use this version for comparison, just for the package filename to install. You can also backgrade if you know that 1.2 is bad for instance. packages: bsdsar-1.10_2 action=upgrade version=1.10_2 cmp=gt The only gotcha about FreeBSD installation is trying to specify the package source location. Due to the unfortunate fact that freebsd doesn't provide a command line option - only an environment variable - for specifying the source repository, you have a few options. Get it from the main FreeBSD binary package home: FreeBSDInstallCommand = ( "/usr/sbin/pkg_add -r %s" ) Get it from a mounted directory or http server FreeBSDInstallCommand = ( "/usr/sbin/pkg_add /nfs/packages/%s" ) FreeBSDInstallCommand = ( "/usr/sbin/pkg_add http://server/path/%s" ) Or write a script that tells pkg_add where to find it, like so: FreeBSDInstallCommand = ( "/var/cfengine/packages/pkginstall %s" ) such as #!/bin/sh PACKAGESITE=http://my.local.repository/packages/ export PACKAGESITE /usr/sbin/pkg_add -r $* `define' Specifies the list of classes to define if the specified package/version was installed (prior to actions taken if any) `elsedefine' Specifies the list of classes to define if the specified package/version was not installed (prior to actions taken if any) `action' Specifies whether the packages should actually do anything about the situation it finds. The default for this is to do nothing. For `install', the action will be taken if the comparison returns false. For `upgrade' and `remove', the action will be taken if the comparison returns false. The classes in `define' and `elsedefine' will always be defined, as applicable, regardless of the action specified. `install' Installs the package using the command associated with the selected package manager, if it is not currently on the system at the requested version, as follows: * RPM - RPMInstallCommand * DPKG - DPKGInstallCommand * SUN - SUNInstallCommand * Gentoo - PortageInstallCommand * FreeBSD - FreeBSDInstallCommand Each variable is of the format: FOOInstallCommand = ( "/usr/bin/foo --args %s --more-args" ) The --args are of course optional. For FreeBSD and Sun, the %s is replaced with the package name that was checked, and found to not be installed. For all other package managers the %s can have a space separated list of package names. `upgrade' Upgrades the package using the commands associated with the selected package manager, first removal of the old package then installation of the new package. Note that on some package managers this action is unnecessary because the package manager will "do the right thing" when told to install a newer version. * FreeBSD - FreeBSDRemoveCommand followed by FreeBSDInstallCommand Portage - Upgrade is generally not necessary since emerge will do the upgrade for you. `remove' Removes the package(s) using the command associated with the selected package manager, if a matching package is found on the system, as follows: FOORemoveCommand = ( "/usr/bin/foo --args %s --more-args" ) The --args are of course optional. The %s is replaced with a space-separated list of the package names that were checked, and found to be installed. NOTE: classes are defined according to the result of the check, not any action performed as a result of that check. In otherwords, if for example you have a situation where a package is not installed, and the action= is set to install, the classes in `elsedefine' will be defined regardless of whether or not the install was successful. Assuming the package installed, the next run of cfagent will pick up that fact. This has to be done since the package installs are batched, so there is no reliable way to know if a given package was installed successfully. Examples: packages: redhat_8_0:: m4 version=0:1.4.1-11 cmp=eq pkgmgr=rpm elsedefine=needsm4 In this first example, we are looking for the m4 package at exactly version 0:1.4.1-11. The installed m4 package on a redhat_8_0 box has no epoch which is the same as zero. Specifying it will keep you out of trouble. This check will cause `needsm4' to be defined if the exact version of m4 specified is not installed. control: redhat:; DefaultPkgMgr = ( rpm ) gentoo:: DefaultPkgMgr = ( portage ) packages: redhat_8_0:: make version=0:4.5-2 cmp=ge define=hasmake elsedefine=needsmake In the second example, we use the DefaultPkgMgr variable to set the default for the `pkgmgr' attribute to `rpm'. The actual version of make installed on recent redhat_8_0 machine is 1:3.79.1-14. Since the check is for greater than or equal to this version, the hasmake class will be defined. control: redhat:; DefaultPkgMgr = ( rpm ) RPMInstallCommand = ( "/usr/sbin/up2date %s" ) packages: redhat_8_0:: make define=hasmake elsedefine=needsmake action=install This example is much like the second example, except that if the package is not installed, cfengine will attempt to install it using the command in RPMInstallCommand, replacing the %s with the package name, `make'. If there were multiple packages specified in this way, the package installation would occur at the end of the package checks, and one command would be run, with %s replaced with a list of all package names. In this example we chose not to use a version spec, but it is allowed, and as always, is optional. NOTE here that if make was not installed when the check is made, `needsmake' is defined, regardless of whether or not the install succeeds. If the install is successful, the next cfagent run will define `hasmake'.  File: cfengine-Reference.info, Node: rename, Next: required, Prev: packages, Up: Cfagent reference 4.33 rename =========== As of version 2.1.0 rename is a synonym for disable, *Note disable::.  File: cfengine-Reference.info, Node: required, Next: resolve, Prev: rename, Up: Cfagent reference 4.34 required ============= This is a synonym for disks, *Note disks::.  File: cfengine-Reference.info, Node: resolve, Next: scli, Prev: required, Up: Cfagent reference 4.35 resolve ============ The file `/etc/resolv.conf' specifies the default nameserver for each host, as well as the local domain name. This file can also contain other information, but these are the only two things cfengine currently cares about. In specifying nameservers you should use the dotted numerical form of the IP addresses since your system may not understand the text form if it is not correctly configured. You may list as many nameservers as you wish, with the default server at the top of the list. The resolver normally ignores entries if you add more than three. The statement: resolve: mygroup:: 129.240.22.35 129.240.22.222 129.240.2.3 declares a list of nameservers for hosts in the group or class `mygroup'. When you add the `resolve' command to the `actionsequence', this declaration together with the `domain' variable (set here to `uio.no') results in a `/etc/resolv.conf' file of the form: domain uio.no nameserver 129.240.22.35 nameserver 129.240.22.222 nameserver 129.240.2.3 Note that the `resolve' action does not delete anything from the file `/etc/resolv.conf' unless the `EmptyResolvConf' variable is set to 'true' . It adds nameservers which do not previously exist and reorders the lines of servers which do exist. As of version 1.3.11, you may use a quoted string to add non-nameserver lines to this file. For example: resolve: mygroup:: 129.240.22.35 129.240.22.222 "# Comment line" "order bind, files" If the line begins with a non-numeric character, the word `nameserver' is not added to the line.  File: cfengine-Reference.info, Node: scli, Next: shellcommands, Prev: resolve, Up: Cfagent reference 4.36 scli ========= SCLI is an SNMP command line interpreter written by Ju"rgen Scho"nwaelder of the Jacobs University of Bremen. It is a command interpreter used to simplify the interaction with SNMP enabled devices. SNMP is a stateless, UDP based network protocol for communicating with supporting hardware. The SNMP model does not fit very comfortably with the cfengine "responsibility for self" paradigm, but at some level SCLI can be viewed as just another form of interpreted script. SCLI adds a level of user friendliness and stateful behaviour to SNMP through its shell-like interface. This turns out to be both a help and a hindrance to cfagent. The intermingling of stateful and stateless processes in the dialogue between cfengine and scli makes their integration non-trivial. Several compromises have to be made to aid usability and these could lead to difficulties in the practical use of the tools later. The scli section of a cfagent configuration is a single script. The lines are passed as a collective object to the scli interpreter, not line-by-line as in other cases. The basic approach is to open a pipe for the reading and writing of dialogue with the interpreter. There are some limitations to Unix pipes however, in particular input and output are separated which makes per-transaction error control essentially impossible. A work-around for this has been used in the test phase. The cfengine interface is a special case of the `shellcommands' interface, passing commands to SCLI instead of to `/bin/sh'. The command options are the same as those below for `shellcommands'. shellcommands: CLASS:: "SCLI-STRING" SHELLCOMMAND OPTIONS "SCLI-STRING" This integration was funded by the IST-EMANICS Network of Excellence in Network and Service Management, of which Oslo University College and the Jacobs University of Bremen are members.  File: cfengine-Reference.info, Node: shellcommands, Next: strategies, Prev: scli, Up: Cfagent reference 4.37 shellcommands ================== Cfengine focuses on fairly simple-minded tasks in order to be as general as possible. In many cases, you will therefore want to write a script to do something special on your system. You can still take advantage of the classes you have defined by executing these scripts or shell commands from this section. The syntax is simply to quote the command you wish to be executed. shellcommands: CLASS:: "COMMAND-STRING" timeout=SECONDS useshell=true/FALSE umask=OCTAL NUMBER owner=UID group=GID background=false/TRUE chdir=DIRECTORY chroot=DIRECTORY preview=TRUE/false inform=false/TRUE audit=TRUE/ON/FALSE/OFF noabspath=false/TRUE ifelapsed=MINS expireafter=MINS define=CLASS-LIST elsedefine=CLASS-LIST `COMMAND-STRING' This is the command to be executed. `TIMEOUT' If you set the optional TIMEOUT parameter, then cfengine will abort the specified shellcommand if it exceeds the given time-limit (specified in seconds). This can be useful for avoiding hung programs caused by hung network connections, etc. Timeouts are generated by alarm interrupts within a single agent. This can be contrasted with `expireafter' in which a second agent is required to interrupt a command. `USESHELL' Some program lines, especially those that do not use any shell-specific capabilities (such as redirection and wildcard expansion) can be run without the shell. This is typically more secure, as the command line is not altered by the user or by the system. It is also faster, as the shell does not have to be spawned in order to run the given command. Use the USESHELL parameter to tell cfengine to not use the shell to run this shellcommand. `UMASK' The umask affects the permissions given to a file created by this shellcommand. The umask specifies, specifically, the permissions that are to be taken away. `OWNER' `GROUP' The user and group ID's of the process can be set (using the OWNER and GROUP parameters respectively) to restrict the permissions of the shellcommand. This can only be done if cfengine is executed by root; otherwise, the user and group will remain that of the the user who started cfengine. `BACKGROUND' Run this command in the background if this is specified true. This will make cfengine run faster, but no tests can be made (at least directly) on the results of this command. Also when jobs are backgrounded, the output in verbose mode can be somewhat erratic due to the unsychnronized streams. `CHDIR' Change to the specified directory before running this command. `CHROOT' The `chroot' option changes the process root directory of the command, creating a `sandbox' which the process cannot escape from. Best used together with a change of owner (using the `owner' parameter), since a root process can break out of a chrooted environment. `PREVIEW' The `preview' option means that the shellcommand will also be executed during the `--dry-run' (`-n') options. This allows cfengine to be more aware of the results of scripts which define classes. This option should be used with care. Scripts should conform to the protocol of not executing unnecessary commands when the classes `opt_dry_run' is defined. `INFORM' `NOABSPATH' Normally, cfagent requires the command string to begin with a `/' since it is dangerous to rely on an implicit path. However, sometimes it it is appropriate to override this. This behavior can be overridden using the NOABSPATH parameter. `IFELAPSED' The shellcommand specified will not be run unless the specified amount of time (in minutes) has elapsed since the command was previously run. `EXPIREAFTER' If this amount of time (in minutes) has elapsed since the command started, then the command is aborted by a second agent that is patrolling the system. `DEFINE' Define the specified classes if the command finishes successfully. `ELSEDEFINE' Define the specified classes if the command does not finish successfully. Variable substitution works within the strings. Here are some examples. shellcommands: sun4:: "/usr/lib/find/updatedb" AllHomeServers.Sunday:: "/dir/noseyparker /$(site)/$(host)/u1 $(sysadm) nomail" AllBinaryServers.sun4.Saturday:: "/usr/etc/catman -w -M /usr/local/man" "/usr/etc/catman -w -M /usr/local/X11R5/man" "/usr/etc/catman -w -M /usr/man" "/usr/etc/catman -w -M /usr/local/gnu/man" If you need to write more advanced scripts which make detailed use of the classes defined by cfengine, use the `$(allclasses)' variable to send a complete list of classes to your script. An enviornment variable, CFALLCLASSES, is set and is in the format CFALLCLASSES=class1:class2:class3... This variable is kept up-to-date at any given time with only the classes which are defined. The command line option `-u' or `--use-env' can be used to define an environment variable which will be inherited by all scripts and contains the same information. This is not the standard approach, since some systems cannot cope with this rapid change of environment and generate a Bus Error. Commands can be iterated over variable lists, provided there is at least one space between each variable. For example: control: actionsequence = ( shellcommands ) var1 = ( a:b:c ) var2 = ( x:y:z ) shellcommands: "/bin/echo $(var1) $(var2)" This iterates over all values of the list variables. *Note Iteration over lists::. If you are iterating over a list, the time limit (in seconds) which is specified in the TIMEOUT parameter applies to each separate iteration, not to the sum total of all the iterations.  File: cfengine-Reference.info, Node: strategies, Next: tidy, Prev: shellcommands, Up: Cfagent reference 4.38 strategies =============== Strategies (introduced in cfengine version 2.0) are a way of picking from a set of classes randomly. Each class is a possible course of action. A strategy group (of classes) is defined as follows: strategies: { my_strategy_alias class1: "2" class2: "3" class3: "$(value)" class4: "6" class5: "1" } tidy: class1.Hr00:: /home pat=*.mp3 age=0 class2.Hr02:: /home pat=*.wav age=0 The idea here is to randomly pick from a selected set of classes. Specifically, each strategy is a class which is defined with a certain probability. An integer weight is provided in quotes to represent the probability weight of the associated class. When cfengine is run, it randomly picks one of the classes from each strategy. Using strategies, you can choose different ways of configuring or protecting a system, at random, thus confounding environmental attempts to break into the system. Note that each strategy has a formal name (such as `my_strategy_alias' in the example), but this name is not used to attach a strategy to an action the same way that filters or ACLs are.  File: cfengine-Reference.info, Node: tidy, Next: unmount, Prev: strategies, Up: Cfagent reference 4.39 tidy ========= The tidy function is used to delete (remove permanently) unwanted files from a system. It is useful for tidying up in `/tmp' or cleaning out `core' files from users' home directories. The form of an entry is: tidy: CLASS:: /DIRECTORY pattern/include=WILDCARD recurse=NUMBER/INF age=DAYS size=NUMBER/EMPTY type=CTIME/MTIME/atime dirlinks=KEEP/TIDY/DELETE rmdirs=[TRUE/ALL]/[FALSE/NONE]/SUB links=stop/keep/TRAVERSE/TIDY compress=TRUE/ON/false/off define=CLASSLIST elsedefine=CLASSLIST syslog=TRUE/ON/FALSE/OFF inform=TRUE/ON/FALSE/OFF audit=TRUE/ON/FALSE/OFF ifelapsed=MINS expireafter=MINS filter=FILTER ALIAS ignore=PATTERN exclude=PATTERN xdev=TRUE/ON/false/off Note that, each of the options below can be written in either upper or lower case and abbreviated by any unique abbreviation. `/DIRECTORY' This is the directory name to directories which mark the start of a search for files matching certain wildcards. The wildcard `home' may be used instead of an explicit directory, in which case cfengine iterates over all home directories. It is compulsory to specify a directory. `pattern=WILDCARD or include=WILDCARD' A wildcard or filename to match the files you wish to be deleted. The pattern may contain the special symbols `?' which matches a single character and `*' which matches any number of characters as in the shell. These two options are synonymous, as of version 2.0.x. Note that, this pattern is processed as a filter before any other filter and, for safety reasons, it defaults to nothing. Thus, if you want to use a filter to select the files, you should set `pattern=*', else the filter will not see any files at all. `exclude=WILDCARD' This does not work for the home directive; use the global ignore list for this. `ignore=WILDCARD' This does not work for the home directive; use the global ignore list for this. `recurse=NUMBER/INF' This specifier tells cfengine whether or not to recurse into subdirectories. If the value is zero, only the named file or directory is affected. If the value is 1, it will open at most one level of subdirectory and affect the files within this scope. If the value is `inf' then cfengine opens all subdirectories and files beginning from the specified filename. *Note Recursion::. `age=DAYS' The age of a file in days represents a minimum _access_ time elapsed before the file will be deleted. In other word a file will be deleted if it has not been accessed for DAYS days. `links=STOP/TRAVERSE/TIDY' Normally cfengine does not descend into subdirectories which are pointed to by symbolic links. If you wish to force it to do so (without using the `-l' command line option) you may give this option the value `true', or `traverse', or `follow'. To specify no recursion you set the value `false' or `stop'. Note that the value set here in the cfengine program _always overrides_ the value set by the `-l' command line option, so you can protect certain actions from this command line option by specifying a negative value here. If you specify no value here, the behaviour is determined by what you specify on the command line. The value `links=tidy' has the same effect as the `-L' command line option except that here it may be specified per item rather than globally. Setting this value causes links which point to non-existent files to be deleted. This feature will not work on commands with the `home' wildcard feature. If you want to clean up old links you should either user a `files' command or the command line option which sets the tidy feature globally. `size=>NUMBER/EMPTY' Old syntax `size=NUMBER/EMPTY'. The value of this parameter decides the size of files to be deleted. Files larger than this value will be deleted if they also are older than the time specified in `age'. The default size is zero so that any file which gets matched by another critereon is deleted. However, if you want to single out only totally empty files, the `empty' may be used. With this option only empty files, nevery files with anything in them, will be deleted, if older than `age'. By default, the filesizes are in kilobytes, but kilobytes and megabytes may also be specified by appending b,k,m to the numbers. Only the first character after the number is significant so you may write the numbers however it might be convenient, e.g. `14k', `14kB', `14kilobytes', the same as for `disable'. `type=CTIME/MTIME/ATIME' This value is used to set the type of time comparison made using `age'. The default is to compare access times (atime) or the last time the file was read. A comparison by modification time (mtime) uses the last time the contents of the file was changed. The ctime parameter is the last time the contents, owner or permissions of the file were changed. Note that on directories, mtime is always used for comparisons, since the very act of stat'ing alters atime and makes this comparison meaningless. `dirlinks=KEEP/TIDY/DELETE' This value is used to decide whether cfengine will delete links which point to directories. The default value is to keep the links. Note that, if the `travlinks' option is switched on, cfengine will not tidy or delete links which point to directories, instead it follows them into the subdirectory. This is a supplement to the `rmdirs' option. You need both to make links to directories disappear. Note that, even if `travlinks' is set to true, cfagent will not follow symbolic links that are not owned by the agent user ID; this is to prevent link race attacks, in which users with write access could divert the agent to another part of the filesystem, `rmdirs=TRUE/FALSE/ALL/SUB' Normally cfengine will not delete directories. If this option is set to `true' then cfengine will delete any directories which are _empty_. Non-empty directories will not be touched and no message will be given unless in verbose mode. Note that this option overrides the above option `dirlinks', so that even links which point to empty directories will be removed. If this is set to `sub' then the topmost directory will not be removed, only sub-directories. `define=CLASSLIST' The colon, comma or dot separated list of classes becomes defined if any file matching the specified pattern is deleted. `xdev' Prevents cfengine from descending into file systems that are not on the same device as the root of the rescurion path. Take a look at the following example: tidy: AllHomeServers:: home pattern=core R=inf age=0 home pattern=*~ R=inf age=7 home pattern=#* R=inf age=30 any:: /tmp/ pat=* R=inf age=1 / pat=core R=2 age=0 /etc pat=hosts.equiv r=0 age=0 In the first example, all hosts in the group `AllHomeServers' iterate a search over all user home directories looking for `core' files (older than zero days) and `emacs' backup files `*~', `#*' older than seven days. The default values for these options are the empty string for the wildcard pattern, zero for the recursion and a specification of the age is compulsory. When cfengine tidies users' home directories, it keeps a log of all the files it deletes each time it is run. This means that, in case of accidents, the user can see that the file has been deleted and restore it from backup. The log file is called `.cfengine.rm' and it is placed in the home directory of each user. The file is owned by root, but is readable to the user concerned.  File: cfengine-Reference.info, Node: unmount, Prev: tidy, Up: Cfagent reference 4.40 unmount ============ The unmount function unmounts non-required filesystems and removes the appropriate entry from the filesystem table (`/etc/fstab' or equivalent). The syntax is simply unmount: CLASS:: MOUNTHOST:FILESYSTEM deletedir=TRUE/FALSE deletefstab=TRUE/FALSE force=TRUE/FALSE ifelapsed=MINS expireafter=MINS The options allow you to temporarily unmount a directory without actually removing it from the filesystem table. The option `force' is not currently implemented and will likely have to be system dependent. For example: unmount: physics:: libraryserver:/$(site)/libraryserver/data If the device is busy then the actual unmount will not take place until it becomes free, or the machine is rebooted. This feature should work on AIX systems, in spite of these machines inherent peculiarities in the form of the filesystem table. Some users do not mount filesystems on a directory of the same name as the source directory. This can lead to confusion. Note, if you have problems removing a mounted filesystem, try using the mountpoint of the filesystem, rather than the name of the filesystem itself, in the unmount command.  File: cfengine-Reference.info, Node: Cfservd.conf and cfrun reference, Next: Cfexecd reference, Prev: Cfagent reference, Up: Top 5 Cfservd and cfrun reference ***************************** * Menu: * cfservd control:: * admit grant and deny:: * cfrun:: * Firewalls and NATs:: The server daemon is controlled by a file called `cfservd.conf'. The syntax of this configuration file is deliberately modelled on cfengine's own configuration file, but despite the similarities, they are separate. You can use `groups' and `import' in both files to break up files into convenient modules and to import common resources, such as lists of groups. Note that the classes in the `cfservd.conf' file do not tell you the classes of host which have access to files and directories, but rather which classes of host pay attention to the access and deny commands when the file is parsed. Authentication is not by class or group but by hostname, like the `/etc/exports' file on most Unix systems. The syntax for the file is as follows: control: CLASSES:: domain = ( DNS-DOMAIN-NAME ) cfrunCommand = ( "SCRIPT/FILENAME" ) # Quoted MaxConnections = ( MAXIMUM NUMBER OF FORKED DAEMONS ) # ChecksumDatabase = ( FILENAME ) - deprecated IfElapsed = ( TIME-IN-MINUTES ) DenyBadClocks = ( FALSE ) AllowConnectionsFrom = ( IP NUMBERS ) DenyConnectionsFrom = ( IP NUMBERS ) AllowMultipleConnectionsFrom = ( IP NUMBERS ) TrustKeysFrom = ( IP NUMBERS ) AllowUsers = ( mark systemuser ) LogAllConnections = ( FALSE/TRUE ) LogEncryptedTransfers = ( FALSE/TRUE ) SkipVerify = ( IP NUMBERS ) DynamicAddresses = ( IP NUMBERS ) BindToInterface = ( IP NUMBER/HOSTNAME ) HostnameKeys = ( TRUE/FALSE ) groups: GROUP DEFINITIONS import: FILES TO IMPORT admit: | grant: CLASSES:: /FILE-OR-DIRECTORY WILDCARDS/HOSTNAMES deny: CLASSES:: /FILE-OR-DIRECTORY WILDCARDS/HOSTNAMES root=HOSTLIST encrypt=TRUE/ON Iteration of variables is allowed, hence: control: Split = ( " " ) hostlist = ( "10.10.10.1 10.10.10.2 10.10.10.3" ) dirs = ( "bin etc lib" ) base = ( /usr ) ######################################################### admit: $(base)/$(dirs) $(hostlist) results in: Path: /usr/bin (encrypt=0) Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root= Path: /usr/etc (encrypt=0) Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root= Path: /usr/lib (encrypt=0) Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root= The file consists of a control section and access information.  File: cfengine-Reference.info, Node: cfservd control, Next: admit grant and deny, Prev: Cfservd.conf and cfrun reference, Up: Cfservd.conf and cfrun reference 5.1 control cfservd =================== * Menu: * IP address ranges:: * AllowConnectionsFrom:: * AllowMultipleConnectionsFrom:: * AllowUsers:: * AutoExecCommand:: * AutoExecInterval:: * BindToInterface in cfservd:: * ChecksumDatabase in cfservd:: * cfrunCommand:: * DenyBadClocks:: * DenyConnectionsFrom:: * cfservd HostnameKeys:: * cfservd IfElapsed:: * LogAllConnections:: * LogEncryptedTransfers:: * MaxConnections:: * TrustKeysFrom:: * DynamicAddresses::  File: cfengine-Reference.info, Node: IP address ranges, Next: AllowConnectionsFrom, Prev: cfservd control, Up: cfservd control 5.1.1 IP address ranges ----------------------- In the access control lists below, host ranges can be specified in a number of ways i) as substrings, ii) as address ranges denoted by the "-" hyphen, or iii) as CIDR (Classless Inter Domain Routing) notation. For example 128.39.73 128.39.74.10/23 128.39.74-75.10-22 2001:700:700:3:290:27ff:fea2:4730-4790 2001:700:700:3:290:27ff:fea2:4730/64 In the CIDR notation, the slash followed by a number indicates the netmask, or the number of bits which are common to a group of hosts. Normally, this is connected to a specific subnet, but here it simply represents the number of bits from the left which are fixed for matching; all remaining bits are wildcards. The following forms are equivalent: 128.39.74. 128.39.74.10/24 128.39.74.1-254  File: cfengine-Reference.info, Node: AllowConnectionsFrom, Next: AllowMultipleConnectionsFrom, Prev: IP address ranges, Up: cfservd control 5.1.2 AllowConnectionsFrom -------------------------- This variable allows a list of numerical IP masks to be specified, which cfservd will allow connections from. If the list is not empty and a host whose IP address is not specified attempts to connect to the daemon, its connection will be closed immediately. This can be used to prevent hanging connection attacks from malicous hosts and other denial of service attacks which would bind thread resources. control: AllowConnectionsFrom = ( 128.39.89 192.2.0.10 )  File: cfengine-Reference.info, Node: AllowMultipleConnectionsFrom, Next: AllowUsers, Prev: AllowConnectionsFrom, Up: cfservd control 5.1.3 AllowMultipleConnectionsFrom ---------------------------------- This variable should contain a list of IP wildcards to hosts which are allowed simultaneous sessions on the server. Hosts which are not in this list are allowed to connect only once, i.e. they must terminate and reconnect in order to establish a new session. This is to prevent a possible attacker from opening multiple sockets and never closing them, resulting in a denial of service attack. Hosts IP's can be placed here if they could have overlapping copy sessions (e.g. long backup transfers which can run over time). This prevents the error message "Multiple connections denied/spam shield".  File: cfengine-Reference.info, Node: AllowUsers, Next: AutoExecCommand, Prev: AllowMultipleConnectionsFrom, Up: cfservd control 5.1.4 AllowUsers ---------------- This list determines which users are to be allowed to connect to the daemon. Note that there is no way of identifying users except by their public keys. If a malicious asserts their identity, when no public key for the named user is known to the server, then they could spoof the identity of that user. All users who should be allowed to connect need to be here. This applies to use of cfrun. AllowUsers = ( mark root ) In other words, this is a "security by obscurity" first defence against picking up bad keys, when the server is in trust mode, with respect to a host. The attacker must know a valid user name in order to even try their luck entering into a key dialogue. This reduces the probability that spoofing can be successful. The only real defence against spoofing is to make sure that all required public keys are installed in advance, and to switch off trust.  File: cfengine-Reference.info, Node: AutoExecCommand, Next: AutoExecInterval, Prev: AllowUsers, Up: cfservd control 5.1.5 AutoExecCommand --------------------- This variable no longer exists in cfengine version 2.  File: cfengine-Reference.info, Node: AutoExecInterval, Next: BindToInterface in cfservd, Prev: AutoExecCommand, Up: cfservd control 5.1.6 AutoExecInterval ---------------------- This variable no longer exists in version 2 of cfengine.  File: cfengine-Reference.info, Node: BindToInterface in cfservd, Next: ChecksumDatabase in cfservd, Prev: AutoExecInterval, Up: cfservd control 5.1.7 BindToInterface in cfservd -------------------------------- If this is set to a specific IP address of an IP configured interface, cfservd will listen for connections only on that interface. On Multi-homed hosts this allows one to restrict the traffic to one interface. Note, Unix only allows one or all interfaces to be selected. An interface must be configured with an IP address in order to be bound.  File: cfengine-Reference.info, Node: ChecksumDatabase in cfservd, Next: cfrunCommand, Prev: BindToInterface in cfservd, Up: cfservd control 5.1.8 ChecksumDatabase in cfservd --------------------------------- (This variable is deprecated as of version 2.1.21. The location of the database will be fixed internally.) This is the path and filename to a database which will cache MD5 checksum values server-side. This optimization is only available if you have the Berkeley database library `libdb' on your system. If this variable is not defined, no database caching will be used and checksum values will be computed directly on request. The utility of this solution is a trade-off between the time it takes to compute the checksum versus the time for a disk-based lookup.  File: cfengine-Reference.info, Node: cfrunCommand, Next: DenyBadClocks, Prev: ChecksumDatabase in cfservd, Up: cfservd control 5.1.9 cfrunCommand ------------------ This string is the command which you would like to be executed remotely by the `cfrun' command. Note that you must, in addition, authorize access to this file in the `admit' section. The access rule should (as usual) be to the actual file object path, not including any symbolic links.  File: cfengine-Reference.info, Node: DenyBadClocks, Next: DenyConnectionsFrom, Prev: cfrunCommand, Up: cfservd control 5.1.10 DenyBadClocks -------------------- If this is set to `off', cfservd will not deny access to clients whose clocks are off by more than one hour. The default is to deny access to systems whose clocks differ by more than one hour. This can prevent messages of the form `Can't stat' file when remote copying.  File: cfengine-Reference.info, Node: DenyConnectionsFrom, Next: cfservd HostnameKeys, Prev: DenyBadClocks, Up: cfservd control 5.1.11 DenyConnectionsFrom -------------------------- Hosts which are included by the allow-list above can be explicitly denied access using this list. control: DenyConnectionsFrom = ( 128.39.89.76 ) # rogue host  File: cfengine-Reference.info, Node: cfservd HostnameKeys, Next: cfservd IfElapsed, Prev: DenyConnectionsFrom, Up: cfservd control 5.1.12 HostnameKeys in cfservd ------------------------------ If this variable is set to true/on, it causes cfservd to lookup and store trusted public keys according to their DNS fully qualified host name, instead of using the IP address. This can be useful in environments where hosts do not have fixed IP addresses, but do have fixed hostnames. HostnameKeys = ( on ) This method of storing keys is not recommended for sites with fixed IP addresses, since it removes one security barrier from a potential attacker by potentially allowing DNS spoofing.  File: cfengine-Reference.info, Node: cfservd IfElapsed, Next: LogAllConnections, Prev: cfservd HostnameKeys, Up: cfservd control 5.1.13 IfElapsed in cfservd --------------------------- The `IfElapsed' anti-spamming filter is also built into `cfservd' so that a remote user cannot even get as far as causing cfengine to parse its input files (which could be used for spamming in itself). The time is in minutes, the default is one hour.  File: cfengine-Reference.info, Node: LogAllConnections, Next: LogEncryptedTransfers, Prev: cfservd IfElapsed, Up: cfservd control 5.1.14 LogAllConnections ------------------------ If set to true, every successful connection will be logged to syslog. This could be useful for identifying abuses of the service, if the server should come under attack, e.g. a denial of service attack. The IP address can then be excluded from the allowed connections list.  File: cfengine-Reference.info, Node: LogEncryptedTransfers, Next: MaxConnections, Prev: LogAllConnections, Up: cfservd control 5.1.15 LogEncryptedTransfers ---------------------------- If set to true, every successful request for a file that is granted access only with an encrypted connection is logged in syslog.  File: cfengine-Reference.info, Node: MaxConnections, Next: TrustKeysFrom, Prev: LogEncryptedTransfers, Up: cfservd control 5.1.16 MaxConnections --------------------- This integer value sets a limit on the maximum number of child daemon threads which cfservd will `fork' in order to handle remote requests. The default value is ten.  File: cfengine-Reference.info, Node: TrustKeysFrom, Next: DynamicAddresses, Prev: MaxConnections, Up: cfservd control 5.1.17 TrustKeysFrom -------------------- Hosts which are included in this list are automatically trusted, if cfservd does not know their public key. This allows public keys to be exchanged. Cfservd will not automatically accept a public key from a host it does not know, since the key will be used to assert strong authentication later. Once a public key has been associated with an IP address, it will never be updated, unless the existing key is deleted by hand. control: TrustKeysFrom = ( 128.39.89.76 ) # trusted host TrustKeysFrom = ( 128.39.89.76/24 ) # trusted subnet  File: cfengine-Reference.info, Node: DynamicAddresses, Prev: TrustKeysFrom, Up: cfservd control 5.1.18 DynamicAddresses ----------------------- Hosts which are included in this list are assumed to have IP addresses which can change with time, e.g. hosts which are given IP addresses by DHCP or a BOOTP like protocol. control: DynamicAddresses = ( 128.39.74.100-200 ) # DHCP range If cfservd receives a connection from an IP address that is in this list, and trustkey is _true_, the existing key for that IP address can be replaced with a new key, and the old key is recorded in a "used keys" list, access is granted. If trust is switched off, the server looks in the "used key list" to see if the key has been seen before. If not access is refused. If it has been seen before - it uses this earlier trust to accept the connection and replace the IP-key binding. Note that used keys are kept in a database for easy lookup, whereas fixed keys are kept in files for easy administration. If host keys change or are reinstalled on the dynamically allocated hosts, then this database should probably be deleted to purge keys that become illegal. DHCP addresses have no effect on hosts that use IPV6, since IPV6 addresses are generally issued based on an interface MAC address and do not therefore change.  File: cfengine-Reference.info, Node: admit grant and deny, Next: cfrun, Prev: cfservd control, Up: Cfservd.conf and cfrun reference 5.2 admit, grant and deny ========================= * Menu: * root=:: * encrypt=:: * SkipVerify::  File: cfengine-Reference.info, Node: root=, Next: encrypt=, Prev: admit grant and deny, Up: admit grant and deny 5.2.1 `root=' ------------- This list specifies the names of hosts which are to have read access to files, regardless of the owner of the file. This effectively gives root users on connecting hosts privileges to non-root owned files on the server, but not vice-versa, similar to the NFS root mapping, except that there is no question of a client being able to modify files on the server. Caution: cfservd trusts the DNS service, so be aware that cache poisoning attacks are a possible way of bypassing access controls. Cfservd requires you to grant access to files without following any symbolic links. You must grant access to the real file or directory in order to access the file object. This is a security feature in case parties with login access to the server could grant access to additional files by having the permission to create symbolic links in a transitory directory, e.g. `/tmp'. As of version 2.0.4: Once a verified host address has been identified with a functioning public/private key authentication, the IP address is added to the SkipVerify list, so that time is not wasted in verifying reverse lookups, when the identify can be verified more efficiently and securely by a key mechanism.  File: cfengine-Reference.info, Node: encrypt=, Next: SkipVerify, Prev: root=, Up: admit grant and deny 5.2.2 `encrypt=true' -------------------- If this option is set, cfservd will only serve the named files if the copy access type is `secure', i.e. on an encrypted link. This presupposes that cfengine has been compiled with a working OpenSSL library.  File: cfengine-Reference.info, Node: SkipVerify, Prev: encrypt=, Up: admit grant and deny 5.2.3 SkipVerify ---------------- If connecting hosts use a Network Address Translator in order to share an IP address, reverse lookup will fail to give a correct verification of host identity. You can switch off cfservd's verification of IP host identity for specific IP addresses or patterns using this command. E.g. SkipVerify = ( 192.0.0.10 192.0.2. ) This does not affect key verification. NOTE!! This is a security risk because it means that cfservd implicitly trusts the connecting hosts! You should be very careful in using Network Address Translators in a secure environment. It is not recommended for sites which require a high level of security.  File: cfengine-Reference.info, Node: cfrun, Next: Firewalls and NATs, Prev: admit grant and deny, Up: Cfservd.conf and cfrun reference 5.3 `cfrun' =========== The general syntactic form of the `cfrun' command is cfrun -OPTION --LONGOPTION CLASS1 CLASS2 ... Since `cfrun' addresses remote hosts, there is an ambiguity in whether options are intended for the `cfrun' command itself, on the local host, or whether they are to be passed on to the agent on the remote hosts. To clarify this distinction, the arguments are organized as follows: cfrun -LOCAL OPTIONS -- REMOTE OPTIONS -- REMOTE CLASSES Local options are processed by `cfrun' on the local host; remote options are passed on as options to the remote `cfagent' (actually to the command defined in `cfrunCommand' in the file `cfservd.conf'; remote classes are processed by the remote `cfservd' service, and specifiy classes which must be satisfied by the remote host in order to invoke the remote command. The `-q' and `-I' options are always assumed when executing cfengine remotely, so that `SplayTime' is effectively zero when polling hosts serially, and the output always shows what is happening on the remote hosts. On connecting to a remote host, cfengine attempts to obtain credentials by exchanging keys. Unknown keys, in a key exchange, need to be explicitly accepted on trust. Normally, the interactive `cfrun' program prompts the user explicitly, (like in the secure shell, `ssh', connections). This can be annoying if there are many hosts to connect to. The `-T' option tells cfengine to trust all new keys. This option should be used with caution, and only at times when one is sure that the hosts one is connecting to are trustworthy. Each host evaluates the classes sent by `cfrun' and decides whether cfengine should be invoked. Only hosts which belong to the classes defined on the `cfrun' command line are executed. This allows you to single out groups of hosts which should execute cfengine, based on the very classes which you have defined for your configuration. If no classes are sent on the command line, then all hosts are run. `cfrun' uses a configuration file which is located under the `CFINPUTS' directory in order to determine which hosts and in which order it should try to connect. Because cfengine always uses a reliable TCP protocol for connections, it verifies each connection rather than simply broadcasting openly. Using this file you can even simulate broadcasting to hosts outside your subnet. This file should contain every host name you ever want to configure remotely, because you can still select subsets of the file by specifying classes which the remote host will understand. If the remote host is not in one of the classes you specify when you run `cfrun', then it will simply ignore the request. Conversely, if you do not place a host in this file, it will never be contacted when you use the `cfrun' command. The format of the file is as follows # # Comment .. # domain=MY.DOMAIN access=USER1,USER2 outputdir=DIRECTORY maxchild=NUMBER LIMIT hostnamekeys=TRUE/FALSE bindtointerface=IP ADDRESS HOSTNAME1 OPTIONS HOSTNAME2:PORT OPTIONS ... include=cfrun.site1.external.hosts include=cfrun.site1.internal.hosts include=cfrun.site2.private.hosts include=cfrun.site2.shared.hosts If the option `outputdir' is present, cfrun forks a separate process for each host and passes the output to files in a named directory. The `maxchild' line limits the number of forked processes. It is important to add the domain-name to this file. The options you specifiy in this file, per host, are added to those you might specify on the command line when invoking cfengine remotely. For instance, you might know of a bug on one host and decide not to perform interface configuration on that one machine. You would write a line like this: funny.domain -- -i # problem host You could use `cfrun' inside one of your cfengine configuration files in order to remotely execute cfengine on all of the other network machines, by setting up a host list. The disadvantage however is that cfengine has to poll the systems on the network, which means that cfengine cannot be working in parallel on all hosts. Some other examples: e.g. cfrun -- -- linux Run on all linux machines cfrun -- -p Ping and parse on all hosts cfrun -v -- -p Ping all, local verbose cfrun -v -- -k -- solaris Local verbose, all solaris, but no copy Amongst the local options, one may specify a subset of the hosts which are to be contacted by cfrun, i.e. to avoid processing the entire list of hosts. For example, to contact only host1 and host2, given that they are already in the list of hosts. cfrun -v host1 host2 cfrun -v host1 host2 -- -p  File: cfengine-Reference.info, Node: Firewalls and NATs, Prev: cfrun, Up: Cfservd.conf and cfrun reference 5.4 Firewalls and NATs ====================== Firewalls and Network Address Translators (NAT) can be a problem for addressing. Suppose you have a firewall and with a private IP-range behind the firewall. You want to update the nodes from a central host. You can do a two stage configuration: first update the firewall and then update from the firewall to the nodes. But suppose you already use SNAT (Source Network Address Translation) and DNAT (Destination ...) for the nodes. With DNAT you can say that socket 22000 on the firewall is routed to HOST-NAME:5308. DNAT gives us the possibilty to update the nodes from a central server in one step instead of two. If the port command is given cfrun uses this to connect to the client instead of the default (5308) one. Here is an example (`cfrun.hosts'): domain=example.org access=mark,sigmund hostnamekeys=true node1.example.org node2.example.org:22000 -DNis node2.example.org:22001 This connects to: 1) node1 with standard port, 2) node2 with port 22000 and extra options -DNis and, 3) node2 with port 22000.  File: cfengine-Reference.info, Node: Cfexecd reference, Next: Problem solving, Prev: Cfservd.conf and cfrun reference, Up: Top 6 Cfexecd reference ******************* In wrapper mode (non-forking, non-daemon mode), cfagent is run by adding a line to the root crontab file of each system: 0,30 * * * * /usr/local/sbin/cfexecd -F This is enough to ensure that cfengine will get run. Any output generated by this job, will be stored in `/var/cfengine/outputs'. The program `cfexecd' operates as a wrapper for cfagent. It has the following options: -h (--help) -d (--debug) -v (--verbose) -q (--no-splay) -F (--no-fork) -1 (--once) -g (--foreground) -p (--parse-only) -L (--ld-library-path) In addition, if you add the following to the file `cfagent.conf', the system administrator will be emailed a summary of any output: control: smtpserver = ( mailhub.example.org ) # site MTA which can talk smtp sysadm = ( mark@example.org ) # mail address of sysadm EmailMaxLines = ( N ) # max lines of output to email OutputPrefix = ( "!" ) # Line prefix Fill in suitable values for these variables. `EmailMaxLines' may be set to 0 to disable email output, a postive integer to set a limit, or `inf' to email the whole output regardless of its size. If undefined, `EmailMaxLines' defaults to 100. An alternative, or additional way to run cfengine, is to run the `cfexecd' program is daemon mode (without the `-F') option. In this mode, the daemon lives in the background and sleeps, activating only in accordance with a scheduling policy. The default policy is to run once every hour (equivalent to `Min00_05'). Here is how you would modify `cfagent.conf' in order to make the daemon execute cfagent every half-hour: control: # When should cfexecd in daemon mode wake up the agent? schedule = ( Min00_05 Min30_35 ) Note that the time specifications are the basic cfengine _time classes_. Although one of these methods should suffice, no harm will arise from running both cron and the cfexecd side-by-side. Locking mechanisms are used by `cfagent' to ensure that no contention will occur. Note, that if problems with library path for compiled-in libraries occur, an explicit library path can be specified with the `-L' option. 0,30 * * * * /usr/local/sbin/cfexecd -F -L /local/iu/lib:/local/lib:/local/gnu/lib The output generated by a cfagent run is collected and stored with date stamps in the `outputs' subdirectory of the work directory (usually `/var/cfengine/outputs'). If cfengine has a valid smtp server configured it will attempt to E-mail new reports to the system administrator. Duplicate reports are suppressed however for a period of one day. Thus, if one has a repeating message, then it will only be sent by E-mail once per day - this feature is meant to prevent cfagent from spamming administators with multiple, indentical reports. As soon a report different from the previous one is received, the memory is reset. Note: this repeated message suppression feature cannot work if you include time dependent data in messages, i.e. if you include the date or time in an alert, then clearly the message will be a different message each time. Output from cfengine should not contain the time or date, except in the E-mail header.  File: cfengine-Reference.info, Node: Problem solving, Next: Example configuration file, Prev: Cfexecd reference, Up: Top 7 Problem solving ***************** * Menu: * cf.preconf bootstrap file:: * cfrc resource file::  File: cfengine-Reference.info, Node: cf.preconf bootstrap file, Next: cfrc resource file, Prev: Problem solving, Up: Problem solving 7.1 cf.preconf bootstrap file ============================= In some cases you will want to run cfengine on a system to configure it from scratch. If the system is in a very bad way, it might not even be able to parse the cfengine configuration file, perhaps because the network was not properly configured or the DNS (Domain Name Service) was out of action. To help prevent this situation, cfengine looks for a script called `cf.preconf' which gets executed prior to parsing and can be used to perform any emergency tests. This file needs only contain enough to get the system to parse the configuration files. `cf.preconf' may be any script in any language. It need not exist at all! It is fed one argument by cfengine, namely the system hard-class for the current system (e.g. `ultrix'). Here is an example: #!/bin/sh # # cf.preconf is an emergency/bootstrap file to get things going # in case cfengine is unable to parse its config file # backupdir=/iu/nexus/local/iu/etc # # If these files don't exist, you might not be able to parse cfagent.conf # if [ ! -s /etc/resolv.conf ]; then echo Patching basics resolv.conf file cat > /etc/resolv.conf << XX domain iu.hioslo.no nameserver 128.39.89.10 XX fi # # SVR4 # if [ "$1" = "solaris" ]; then if [ ! -s "/etc/passwd" ]; then echo Patching missing passwd file /bin/cp $backupdir/passwd /etc/passwd fi if [ ! -s "/etc/shadow" ]; then echo Patching missing passwd file /bin/cp $backupdir/shadow /etc/shadow fi fi # # BSD 4.3 # if [ "$1" = "linux" ]; then if [ ! -s "/etc/passwd" ] then echo Patching missing passwd file /bin/cp $backupdir/passwd.linux /etc/passwd fi fi Note - in some circumstances, it might be appropriate to exit cfengine altogether after this script. If the script outputs a string containing the text "cfengine-preconf-abort", then cfagent will abort execution immediately after this.  File: cfengine-Reference.info, Node: cfrc resource file, Prev: cf.preconf bootstrap file, Up: Problem solving 7.2 cfrc resource file ====================== If, for some reason you are not satisfied with the defaults which cfengine uses, then you can change them by making an entry in the resource file. The default values are defined in the source code file `classes.c' in the distribution. The format of the resource file is: hardclass.variable: value For example, you might want to forget about where your HPUX system mounts its mail directory and mount it under `/usr/spool/mail'. In this case you would add the line: hpux.maildir: /usr/spool/mail To redefine the filesystem table for GNU/linux, you would write: linux.fstab: /etc/linuxfstab The full list of re-definable resources is: mountcomm # command used to mount filesystems unmountcomm # command used to unmount filesystems ethernet # name of the ethernet device mountopts # options to above mount command fstab # the name of the filesystemtable maildir # the location of the mail directory netstat # the full path to netstat and options pscomm # the path to the system's ps command psopts # the options used by ps (default aux/ef) You should never need to redefine resources unless you decide to do something non-standard. Interested readers are referred to the values in `classes.c'. Cfengine is easily extensible so as to support a variety of architectures. You can even add your own. To do so you need, first of all, to define a new class for the operating system concerned. The file _classes.c_ has been separated off from the remainder of the source code so that you can easily see which data structures need to be extended. To make life as straightforward as possible, three unused classes have been defined. They are called (unremarkably) _unused1_, _unused2_ and _unused3_. If you add any further classes, it will be necessary to increase the constant _clssattr_ defined in _cf.defs.h_ by one for every new addition. You do not need to change _clssattr_ if you simple replace one of the unused classes by a real class. To see fully the impact of what you need to do, you should make a search for the strings _unused?_ in all of the source files. Certain special cases need to be handled for each operating system. For example, the form of the filesystem table is quite radically different on some systems such as AIX. One thing you must do is to fill in the default values for the new operating system in the file _classes.c_. If you fill in the details for a new operating system before it finds its way into a new release, you might consider sending the details to the bug list in the next paragraph.  File: cfengine-Reference.info, Node: Example configuration file, Next: Variable Index, Prev: Problem solving, Up: Top 8 Example configuration files ***************************** Here is a sample from a large configuration file, just to give you some ideas. The file is broken up into manageable pieces for convenience. * Menu: * cfagent.conf:: * cf.groups:: * cf.main:: * cf.site:: * cf.motd:: * cf.users:: * cf.solaris:: * cf.linux:: * cf.freebsd:: * cfservd.conf::  File: cfengine-Reference.info, Node: cfagent.conf, Next: cf.groups, Prev: Example configuration file, Up: Example configuration file 8.1 cfagent.conf ================ ##################################################################### # # CFENGINE CONFIGURATION FOR site = iu.hioslo.no # # This file is for root only. # ###################################################################### ### # # BEGIN cfagent.conf # ### import: # # Split things up to keep things tidy # any:: cf.groups cf.main cf.site cf.motd hpux:: cf.hpux linux:: cf.linux solaris:: cf.solaris sun4:: cf.sun4 ultrix:: cf.ultrix freebsd:: cf.freebsd # # Do you want to do this ? # AllHomeServers:: cf.users ### # # END cfengine.conf # ###  File: cfengine-Reference.info, Node: cf.groups, Next: cf.main, Prev: cfagent.conf, Up: Example configuration file 8.2 cf.groups ============= ############################################################## # # cf.groups - for iu.hioslo.no # # This file contains all group/class definitions # ################################################################# ### # # BEGIN cf.groups # ### groups: # # Define some groups # iu = ( nexus ferengi regula borg dax lore axis worf daystrom voyager aud1 aud2 aud3 aud4 bajor ds9 takpah takpeh nostromo galron thistledown rama chaos pc-steinarj pc-hildeh way jart kosh ) diskless = ( regula ferengi lore ) standalone = ( nexus axis dax borg worf daystrom voyager aud1 aud2 aud3 aud4 bajor ds9 takpah takpeh nostromo galron thistledown rama pc-torejo pc-steinarj pc-hildeh ) AllHomeServers = ( nexus ) AllBinaryServers = ( nexus borg ) XBootServer = ( nexus ) WWWServers = ( nexus ) FTPserver = ( nexus ) NameServers = ( nexus ) PasswdServer = ( nexus ) BackupHost = ( nexus ) MailHub = ( nexus ) MailClients = ( iu -nexus ) ### # # END cf.groups # ###  File: cfengine-Reference.info, Node: cf.main, Next: cf.site, Prev: cf.groups, Up: Example configuration file 8.3 cf.main =========== ############################################################## # # cf.main - for iu.hioslo.no # # This file contains generic config stuff # ################################################################# ### # # BEGIN cf.main # ### control: access = ( root ) # Only root should run this site = ( iu ) domain = ( iu.hioslo.no ) sysadm = ( drift@iu.hioslo.no ) repository = ( /var/spool/cfengine ) netmask = ( 255.255.255.0 ) timezone = ( MET ) nfstype = ( nfs ) sensiblesize = ( 1000 ) sensiblecount = ( 2 ) editfilesize = ( 20000 ) mountpattern = ( /$(site)/$(host) ) homepattern = ( u? ) # # If we undefine this with cfengine -N longjob # then we switch off all jobs labelled with this class # addclasses = ( longjob ) # # Macros & constants are inherited downwards in imports # but are not passed up to parent files. Good idea to # define them all here # masterfiles = ( /iu/nexus/local/iu ) main_server = ( nexus ) cfbin = ( /iu/nexus/local/gnu/lib/cfengine/bin ) gnu = ( /local/gnu ) ftp = ( /local/iu/ftp ) nisslave = ( dax ) nisfiles = ( /iu/nexus/local/iu/etc ) # # The action sequence for daily (full) runs and # for hourly updates (called with -DHourly) # Hr00:: actionsequence = ( copy mountall mountinfo checktimezone netconfig resolve unmount shellcommands addmounts links.Prepare files.Prepare directories links.Rest mailcheck mountall required tidy disable editfiles files.Rest processes ) !Hr00:: actionsequence = ( resolve shellcommands copy editfiles processes links ) force:: actionsequence = ( files.Prepare.Rest tidy ) ###################################################################### homeservers: iu:: nexus binservers: iu.solaris:: nexus iu.linux:: borg mailserver: any:: nexus:/var/mail mountables: any:: nexus:/iu/nexus/u1 nexus:/iu/nexus/u2 nexus:/iu/nexus/u3 nexus:/iu/nexus/u4 nexus:/iu/nexus/u5 nexus:/iu/nexus/u6 nexus:/iu/nexus/ua nexus:/iu/nexus/ud nexus:/iu/nexus/local nexus:/opt/NeWSprint nexus:/opt/AcroRead borg:/iu/borg/local dax:/iu/dax/local miscmounts: linux||freebsd:: nexus:/iu/nexus/local /iu/nexus/local ro ###################################################################### broadcast: ones defaultroute: cadeler30-gw ###################################################################### resolve: 128.39.89.10 # nexus 158.36.85.10 # samson.hioslo.no 129.241.1.99 ###################################################################### tidy: # # Some global tidy-ups # /tmp/ pat=* r=inf A=1 /var/tmp pat=* r=inf A=1 / pat=core r=1 A=0 /etc pat=core r=1 A=0 ###################################################################### ignore: # Don't check or tidy these directories /local/lib/gnu/emacs/lock/ /local/tmp ftp projects /local/bin/top /local/lib/tex/fonts /local/iu/etc /local/etc /local/iu/httpd/conf /usr/tmp/locktelelogic /usr/tmp/lockIDE RootMailLog # # Emacs lock files etc # !* /local/lib/xemacs # # X11 keeps X server data in /tmp/.X11 # better not delete this! # .X11 # # Some users like to give a file or two 777 protection here # so netsurfers can update a log or counter when running as # `nobody' # www ##################################################################### disable: /etc/hosts.equiv /etc/nologin /usr/lib/sendmail.fc ### # # END cf.main # ###  File: cfengine-Reference.info, Node: cf.site, Next: cf.motd, Prev: cf.main, Up: Example configuration file 8.4 cf.site =========== ############################################################## # # cf.site - for iu.hioslo.no # # This file contains site specific data # ################################################################# ### # # BEGIN cf.site # ### links: Prepare:: /local -> /$(site)/$(binserver)/local /usr/local -> /local dax:: /iu/dax/local +> /iu/nexus/local /projects -> /iu/dax/local/projects /iu/nexus/u1/sowille/data -> /iu/dax/scratch/data XBootServer:: # # Set up a /local/tftpboot area where all X terminal # stuff will be kept. # /tftpboot -> /local/tftpboot /local/tftpboot/td/configs -> /local/tftpboot/td/examples/configs /etc/bootptab -> /tftpboot/bootptab /tftpboot/usr/lib/X11/td -> /tftpboot/td NameServers:: /etc/named.boot -> /local/iu/named/named.boot MailHub:: /etc/mail/sendmail.cf ->! /iu/nexus/local/mail/sendmail.cf MailClients.solaris:: /etc/mail/sendmail.cf ->! /iu/nexus/local/mail/client.cf nexus:: /local/bin +> /local/latex/bin ############################################################# disable: # # We run Berkeley sendmail and the config files are # all under /iu/nexus/local/lib/mail # /etc/aliases WWWServers.Sunday:: # # Disabling these log files weekly prevents them from # growing so enormous that they fill the disk! # /local/iu/httpd/logs/access_log rotate=empty /local/iu/httpd/logs/agent_log rotate=empty /local/iu/httpd/logs/error_log rotate=empty /local/iu/httpd/logs/referer_log rotate=empty # # CERT warning, security fix # any:: /usr/lib/expreserve FTPserver.Sunday.Hr00:: /local/iu/xferlog rotate=3 ################################################################# files: Prepare:: /etc/motd m=0644 r=0 o=root act=touch /.cshrc m=0644 r=0 o=root act=touch PasswdServer:: /local/iu/etc/passwd m=0644 o=root g=other action=fixplain /local/iu/etc/shadow m=0644 o=root g=other action=fixplain WWWServers.Rest:: /local/iu/www m=775 g=www act=fixall r=inf /local/iu/httpd/conf m=664 o=root g=www act=fixall r=inf /local/iu/www/cgi-bin-public/count_file m=777 o=root g=www act=fixplain FTPserver:: # # Make sure anonymous ftp areas have the correct # protection, or logins won't be able to read # files - or perhaps a security risk. This is # Solaris 2 specific... # $(ftp)/pub mode=755 o=ftp g=ftp r=inf act=fixall $(ftp)/Obin mode=111 o=root g=other act=fixall $(ftp)/etc mode=111 o=root g=other act=fixdirs $(ftp)/usr/bin/ls mode=111 o=root g=other act=fixall $(ftp)/dev mode=555 o=root g=other act=fixall $(ftp)/usr mode=555 o=root g=other act=fixdirs Prepare:: /etc/shells mode=0644 action=touch AllBinaryServers.Rest.longjob:: /local mode=-0002 r=inf owner=root,bin group=0,1,2,3,4,5,6,7,staff links=tidy action=fixall /local/iu/RootMailLog m=0666 action=touch dax.Rest:: /iu/dax/scratch r=0 o=root mode=1777 action=fixall /iu/dax/local/projects r=0 o=root mode=755 action=fixdirs nexus:: /local/mail/sendmail.cf o=root m=444 act=fixplain /iu/nexus/ua/robot/.rhosts o=robot m=600 act=touch /local/iu/named/pz o=root m=644 act=fixall r=1 /local/latex/lib/tex/texmf/fonts owner=root mode=1666 recurse=inf action=fixall ################################################################# tidy: # # Make sure the file repository doesn't fill up # /var/spool/cfengine pattern=* age=3 /var pattern=core age=0 r=inf /var/spool/mqueue pattern=* age=14 type=mtime BackupHost:: # Here we tidy old backup tar files from the backup area # A special tmp area gets cleared every 4 days. The files # are created by Audun's backup help script (see shellcommands) /iu/nexus/backup1 pat=* age=7 ################################################################# shellcommands: PasswdServer:: # Build and install the BSD compatible passwd file # from the master passwd/shadow file on Solaris "/local/iu/bin/BuildPasswdFiles" "/local/iu/bin/BuildGroupFiles" BackupHost.Sunday.Hr00|BackupHost.Wednesday.Hr00:: # # Make a system backup of /iu/nexus/u? with Audun's script # "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/ud" "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/ua" "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/u1" "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/u2" "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u3" "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u4" "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u5" "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u6" nexus.Sunday.longjob.Hr00:: # # See how much rubbish users have accumulated each Sunday # "$(cfbin)/noseyparker /iu/nexus/u1 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/u2 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/u3 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/u4 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/u5 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/u6 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/ua $(sysadm) nomail" "$(cfbin)/noseyparker /iu/nexus/ud $(sysadm) nomail" nexus.longjob.Hr00:: # # Update the GNU find/locate database each night # "$(gnu)/lib/locate/updatedb" "/local/iu/bin/newhomepage.sh" ############################################################### editfiles: # # cfengine installs itself as a cron job - sneaky! :) # { /var/spool/cron/crontabs/root AppendIfNoSuchLine "0 * * * * $(cfbin)/cfwrap $(cfbin)/cfhourly" } FTPserver:: { /etc/shells AppendIfNoSuchLine "/bin/tcsh" AppendIfNoSuchLine "/local/gnu/bin/bash" } XBootServer:: { /etc/inetd.conf AppendIfNoSuchLine "bootp dgram udp wait root /local/bin/bootpd bootpd -i -d" } nexus:: { /iu/nexus/ua/robot/.rhosts AppendIfNoSuchLine "borg" AppendIfNoSuchLine "borg.iu.hioslo.no" AppendIfNoSuchLine "aud4" AppendIfNoSuchLine "aud4.iu.hioslo.no" } dax:: { /etc/system AppendIfNoSuchLine "set pt_cnt=128" } ###################################################################### required: # # Any host must have a /local, /usr/local fs. Check that # it exists and looks sensible. (i.e. not empty) # /$(site)/$(binserver)/local ###################################################################### copy: # # NIS seems broken at IU, so here we use NFS to fudge # a file distribution as a temporary solution. Actually # this makes the system work faster without NIS! # $(nisfiles)/services dest=/etc/services o=root g=other mode=0644 $(nisfiles)/hosts.deny dest=/etc/hosts.deny o=root mode=0644 !debian:: $(nisfiles)/hosts dest=/etc/hosts o=root g=other mode=0644 PasswdServer:: /etc/passwd dest=$(nisfiles)/passwd o=root g=other mode=0644 /etc/shadow dest=$(nisfiles)/shadow o=root g=other mode=0644 nexus:: /local/iu/etc/dfstab dest=/etc/dfs/dfstab o=root mode=0744 solaris.!PasswdServer:: $(nisfiles)/passwd dest=/etc/passwd o=root g=other mode=0644 $(nisfiles)/shadow dest=/etc/shadow o=root g=other mode=0600 $(nisfiles)/group.solaris dest=/etc/group o=root g=other mode=0644 linux:: $(nisfiles)/passwd.linux dest=/etc/passwd o=root g=other mode=0644 $(nisfiles)/group.linux dest=/etc/group o=root g=other mode=0644 ############################################################### processes: "eggdrop" signal=kill "irc" signal=kill "ping" signal=kill "NetXRay" signal=kill "netxray" signal=kill "ypserv" signal=kill "ypbind" signal=kill "rarpd" signal=kill "rpc.boot" signal=kill "README" signal=kill # You don't sh README ! !XBootServer:: "bootp" signal=kill # # These processes are not killed every hour, but once a day # when cfengine runs at night. Note that there are often # hanging pine and elm processes. These programs crash and # go berserk, using hundreds of hours of CPU time. # Hr00:: "cron" signal=hup # HUP these to update their config "inetd" signal=hup "/local/sdt/sdt/bin" signal=term # For those elektro dudes who forget # to log out "netscape" signal=kill "pine" signal=kill "elm" signal=kill ### # # END cf.site # ###  File: cfengine-Reference.info, Node: cf.motd, Next: cf.users, Prev: cf.site, Up: Example configuration file 8.5 cf.motd =========== ################################################################## # # cf.motd # # This file is used to set the message of the day file on # each host # ################################################################## ##### # # BEGIN cf.motd # ##### control: # # This points to the file containing general text # masterfile = ( /iu/nexus/local/iu/etc/motd-master ) local_message = ( /etc/motd.local ) editfiles: { /etc/motd BeginGroupIfFileIsNewer "$(masterfile)" EmptyEntireFilePlease InsertFile "$(masterfile)" InsertFile "$(local_message)" PrependIfNoSuchLine "This system is running $(class):$(arch)" EndGroup } ##### # # BEGIN cf.motd # #####  File: cfengine-Reference.info, Node: cf.users, Next: cf.solaris, Prev: cf.motd, Up: Example configuration file 8.6 cf.users ============ Whether or not you perform any special services for users, with or without their consent is entirely a matter of local policy. In a school or college situation, users are often uncooperative and some are even irresponsible. This file shows you what you could do in an environment with inexperienced users, but please don't feel as though you have to be this totalitarian. ################################################################# # # cf.users - for iu.hioslo.no # # This file contains user specific actions # ################################################################# ### # # BEGIN cf.users # ### ignore: robot tidy: longjob:: # # Some users just don't understand what they are doing # and this is safest, allbeit totalitarian # home pat=.rhosts age=0 # # Tidy up users' home dirs # home pat=core r=inf age=0 home pat=a.out r=inf age=1 home p=*% r=inf age=2 home p=*~ r=inf age=2 home p=#* r=inf age=1 home p=*.dvi r=inf age=14 type=ctime home p=*.log r=inf age=2 home p=Log.* r=inf age=3 home p=CKP r=inf age=1 home p=BAK r=inf age=1 home p=log r=inf age=0 home p=*.o r=inf age=0 home p=*.aux r=inf age=3 home p=*.zip r=inf age=7 home/.deleted p=* r=inf age=0 home/.wastebacket p=* r=inf age=14 home/www p=*~ r=inf age=1 # # Clear the big cache files netscape creates # home/.netscape-cache p=cache????* r=inf age=0 home/.MCOM-cache p=cache????* r=inf age=0 home/.netscape/cache p=* r=inf age=0 ################################################################# files: AllHomeServers.longjob.rest:: # # Check users files are not writable to the world # and there are no stale links (pointing nowhere) # home mode=o-w recurse=inf action=fixall # links=tidy home/.xsession mode=755 action=fixall home/.cshrc mode=755 action=fixall ################################################################# copy: Hr00.longjob:: # # Make sure each user has an up to date standard # setup. Cshrc just sources in a big standard file # which is kept in ~user/../.setupfiles/cshrc # to reduce disk wastage # $(masterfiles)/lib/Cshrc dest=home/.cshrc $(masterfiles)/lib/tkgrc dest=home/.tkgrc $(masterfiles)/lib/fvwm2rc dest=home/.fvwm2rc ### # # END cf.users # ###  File: cfengine-Reference.info, Node: cf.solaris, Next: cf.linux, Prev: cf.users, Up: Example configuration file 8.7 cf.solaris ============== ################################################################# # # cf.solaris - for iu.hioslo.no # # This file contains Solaris specific patches # ################################################################# ### # # BEGIN cf.solaris # ### directories: # # httpd/netscape want this to exist for some bizarre reason # /usr/lib/X11/nls ################################################################ tidy: /var/log pattern=syslog.* age=0 MailHub:: /var/mail pattern=lp age=0 ################################################################# files: # # If this doesn't exist fork will not work and the # system will not even be able to run the /etc/rc # scripts at boottime # /etc/system o=root g=root m=644 action=touch /var/log/syslog o=root m=666 action=touch ############################################################# copy: # # Some standard setup files, can't link because # machine won't boot if their not on / partition. # /local/bin/tcsh dest=/bin/tcsh mode=755 /local/iu/etc/nsswitch.standalone dest=/etc/nsswitch.conf # # Our named server uses a newer BIND # Put this here so that it will be preserved under # Solaris reinstallation # NameServers:: /local/iu/sbin/in.named dest=/usr/sbin/in.named mode=555 /local/iu/sbin/in.named.reload dest=/usr/sbin/in.named.reload mode=555 /local/iu/sbin/in.named.restart dest=/usr/sbin/in.named.restart mode=555 /local/iu/sbin/in.ndc dest=/usr/sbin/in.ndc mode=555 /local/iu/sbin/named-xfer dest=/usr/sbin/named-xfer mode=555 /local/iu/lib/nslookup.help dest=/usr/lib/nslookup.help mode=444 any:: /local/iu/lib/libresolv.a dest=/usr/lib/libresolv.a mode=444 /local/iu/lib/libresolv.so.2 dest=/usr/lib/libresolv.so.2 mode=444 /local/bin/nslookup dest=/usr/sbin/nslookup mode=444 ############################################################## editfiles: { /etc/netmasks AppendIfNoSuchLine "128.39 255.255.255.0" } { /etc/defaultrouter AppendIfNoSuchLine "128.39.89.1" } { /usr/openwin/lib/app-defaults/XConsole AppendIfNoSuchLine "XConsole.autoRaise: on" } # # CERT security patch for vold vulnerability # { /etc/rmmount.conf HashCommentLinesContaining "action cdrom" HashCommentLinesContaining "action floppy" } ############################################################## disable: /etc/.login type=file /etc/aliases # # These files are ENORMOUS, don't let them fill the disk # Wednesday:: /var/lp/logs/lpsched rotate=empty /var/adm/wtmpx rotate=empty /var/adm/wtmp rotate=empty ############################################################## files: /etc/passwd m=0644 o=root g=other action=fixplain /etc/shadow m=0600 o=root g=other action=fixplain /etc/defaultrouter m=0644 o=root g=other action=touch /var/adm/wtmpx m=0664 o=adm g=adm action=touch /var/adm/wtmp m=0644 o=root g=adm action=touch /var/adm/utmp m=0644 o=root g=adm action=fixplain /var/adm/utmpx m=0664 o=adm g=adm action=fixplain /tmp m=1777 action=fixdirs ############################################################## disable: # # CERT security patch # /usr/openwin/bin/kcms_calibrate /usr/openwin/bin/kcms_configure /usr/bin/admintool ################################################################ shellcommands: AllBinaryServers.Saturday.longjob.Hr00:: # # Make sure the man -k / apropos data are up to date # "/usr/bin/catman -M /local/man" "/usr/bin/catman -M /local/X11R5/man" "/usr/bin/catman -M /usr/man" "/usr/bin/catman -M /local/gnu/man" "/usr/bin/catman -M /usr/openwin/share/man" "/usr/bin/catman -M /local/X11R5/man" "/usr/bin/catman -M /usr/share/man" ################################################################ editfiles: # # A painless way to add an rc.local script to the rc files # under Solaris without having to fight though inittab # { /etc/rc3.d/S15nfs.server AppendIfNoSuchLine "sh /local/iu/etc/rc.local" } # # umask defined when inetd starts is inherited by all subprocesses # including ftpd which saves with mode 666 (!) unless we do this # { /etc/rc2.d/S72inetsvc PrependIfNoSuchLine "umask 022" } ### # # END cf.solaris # ###  File: cfengine-Reference.info, Node: cf.linux, Next: cf.freebsd, Prev: cf.solaris, Up: Example configuration file 8.8 cf.linux ============ ################################################################# # # cf.linux - for iu.hioslo.no # # This file contains debian linux specific patches # ################################################################# ### # # BEGIN cf.linux # ### files: /etc/printcap m=644 o=root action=fixplain # # Cert advisories # /bin/mount m=755 o=root action=fixall /bin/umount m=755 o=root action=fixall ####################################################################### disable: # # Cert advisories # /sbin/dip-3.3.7n ######################################################################## links: /local/bin/tcsh -> /bin/tcsh /local/lib/mail -> /$(site)/$(main_server)/local/lib/mail ######################################################################## editfiles: # # Samba default mode needs to be set... # { /etc/smb.conf ReplaceAll "700" With "644" } # # Linux date is very stupid and needs a very careful # TZ definition, otherwise it loses # { /etc/csh.cshrc AppendIfNoSuchLine "setenv TZ 'MET-1MET DST-2,M3.5.0/2,M10.5.0/3'" } # # resolv+ ordering # { /etc/host.conf PrependIfNoSuchLine "order bind" } # # Should have been configured already (!) # { /etc/ld.so.conf AppendIfNoSuchLine "/usr/X11R6/lib" } # # Kill annoying messages # { /etc/cron.daily/standard HashCommentLinesContaining "security" } ######################################################################### shellcommands: Hr00:: # # Find/locate database # "/usr/bin/updatedb" ### # # END cf.linux # ###  File: cfengine-Reference.info, Node: cf.freebsd, Next: cfservd.conf, Prev: cf.linux, Up: Example configuration file 8.9 cf.freebsd / cf.netbsd ========================== FreeBSD, OpenBSD and NetBSD are sufficiently similar to have a single file for all. ################################################################# # # cf.bsd - for iu.hioslo.no # # This file contains bsd specific patches # ################################################################# ### # # BEGIN cf.bsd # ### links: /usr/spool -> /var/spool /local/bin/tcsh -> /bin/tcsh /local/bin/perl -> /usr/bin/perl /usr/lib/sendmail -> /usr/sbin/sendmail ################################################################# files: /usr/tmp mode=1777 owner=root action=fixall ################################################################# editfiles: # # Comment out all lines to shut up this annoying cfengine-like # script, which sends mail every day!!! # { /etc/crontab HashCommentLinesContaining "daily" HashCommentLinesContaining "weekly" HashCommentLinesContaining "monthly" } ################################################################# copy: $(masterfiles)/etc/printcap.client dest=/etc/printcap mode=0644 ######################################################################### shellcommands: Hr00:: "/usr/libexec/locate.updatedb" "/usr/bin/makewhatis /usr/share/man:/usr/X11R6/man" ### # # END cf.bsd # ###  File: cfengine-Reference.info, Node: cfservd.conf, Prev: cf.freebsd, Up: Example configuration file 8.10 cfservd.conf tutorial ========================== ######################################################### # # This is a cfservd config file # ######################################################### # # Could import cf.groups here and use a structure like # in cfengine.conf, cf.main, cf.groups # control: public = ( /usr/local/publicfiles ) almost_public = ( /usr/local/almostpublicfiles ) cfrunCommand = ( /iu/nexus/ud/mark/comp/Tests/cfrun-command ) MaxConnections = ( 10 ) ######################################################### admit: # or grant: $(public) * $(almost_public) *.iu.hioslo.no *.gnu.ai.mit.edu /etc/passwd *.iu.hioslo.no # # Who can exec cfengine remotely? # $(cfrunCommand) *.iu.hioslo.no ######################################################### deny: $(public)/special *.moneyworld.com  File: cfengine-Reference.info, Node: Variable Index, Next: Concept Index, Prev: Example configuration file, Up: Top Variable Index ************** [index] * Menu: * !: Cfengine classes. (line 98) * $(arch): Special variables. (line 20) * $(binserver): Special variables. (line 23) * $(class): Special variables. (line 40) * $(colon): Special variables. (line 151) * $(cr): Special variables. (line 148) * $(date): Special variables. (line 45) * $(dblquote): Special variables. (line 154) * $(dollar): Special variables. (line 157) * $(domain): Special variables. (line 48) * $(faculty): Special variables. (line 64) * $(fqhost): Special variables. (line 67) * $(host): Special variables. (line 70) * $(ipaddress): Special variables. (line 74) * $(lf): Special variables. (line 160) * $(n): Special variables. (line 163) * $(quote): Special variables. (line 166) * $(site): Special variables. (line 109) * $(spc): Special variables. (line 170) * $(sysadm): Special variables. (line 118) * $(tab): Special variables. (line 173) * $(timezone): Special variables. (line 121) * $(version): Special variables. (line 129) * $(year): Special variables. (line 132) * ${EmailMaxLines}: Special variables. (line 57) * +: groups. (line 40) * -D option <1>: addclasses. (line 20) * -D option: Cfengine classes. (line 96) * -l: tidy. (line 87) * -L: Single links. (line 22) * -l: Syntax. (line 154) * -N option <1>: addclasses. (line 30) * -N option: Cfengine classes. (line 96) * -x option: cf.preconf bootstrap file. (line 74) * .cfengine.rm: tidy. (line 184) * /etc/host.conf: cf.preconf bootstrap file. (line 74) * /var/cfengine/output: Cfexecd reference. (line 27) * a= <1>: tidy. (line 42) * a=: Syntax. (line 51) * AbortClasses: control. (line 66) * AccessedBefore(): Examples setting classes. (line 18) * action: Syntax. (line 51) * action=: packages. (line 59) * actionsequence <1>: actionsequence. (line 6) * actionsequence: control. (line 66) * AddClasses: addclasses. (line 6) * AddInstallable: addinstallable. (line 6) * addmounts: actionsequence. (line 35) * age: tidy. (line 42) * alerts: alerts. (line 6) * AllowUsers: AllowUsers. (line 25) * Auditing: Auditing. (line 6) * backup=: copy. (line 141) * BindToInterface <1>: BindToInterface in cfservd. (line 10) * BindToInterface: BindToInterface in cfagent. (line 11) * binserver <1>: Link Children. (line 10) * binserver: Single links. (line 110) * binservers: binservers. (line 6) * broadcast: broadcast. (line 6) * bymatch: processes. (line 183) * cf.preconf: cf.preconf bootstrap file. (line 6) * CFALLCLASSES <1>: Special variables. (line 16) * CFALLCLASSES: Cfagent Runtime Options. (line 145) * cfinputs_version: Special variables. (line 27) * cfrc: cfrc resource file. (line 6) * ChangedBefore(): Examples setting classes. (line 18) * ChecksumDatabase: ChecksumDatabase in cfagent. (line 8) * ChecksumPurge: ChecksumPurge. (line 8) * ChecksumUpdates: ChecksumUpdates. (line 8) * checktimezone: actionsequence. (line 35) * childlinks: actionsequence. (line 35) * cmp=: packages. (line 74) * CompressCommand: CompressCommand. (line 11) * control: control. (line 6) * create: create. (line 6) * directories: actionsequence. (line 35) * disable <1>: disable. (line 6) * disable: actionsequence. (line 35) * domain <1>: domain. (line 6) * domain: control. (line 66) * DryRun: dryrun. (line 6) * editbinaryfilesize: editbinaryfilesize. (line 6) * editfiles: actionsequence. (line 35) * editfilesize <1>: editfilesize. (line 6) * editfilesize: control. (line 66) * EditSplit: EditSplit. (line 14) * EmailMaxLines: Cfexecd reference. (line 43) * empty: disable. (line 91) * EmptyResolvConf: emptyresolvconf. (line 6) * Exclamation: exclamation. (line 12) * exclude=: Syntax. (line 141) * exec: Setting variables with functions. (line 11) * FileExtensions: fileextension. (line 13) * files <1>: files. (line 6) * files: actionsequence. (line 35) * filter: filters. (line 6) * force= <1>: disks. (line 75) * force=: copy example. (line 39) * freespace=: disks. (line 57) * g=: Syntax. (line 51) * group: Syntax. (line 51) * groups: groups. (line 6) * home: Syntax. (line 64) * homepattern: mountables. (line 35) * HomePattern: homepattern. (line 6) * homeservers: homeservers. (line 6) * IgnoreInterfaceRegex: IgnoreInterfaceRegex. (line 12) * import: import. (line 6) * include=: Syntax. (line 136) * interface configuration: interfaces. (line 6) * InterfaceName: interfacename. (line 6) * IsDir(): Examples setting classes. (line 18) * IsLink(): Examples setting classes. (line 18) * IsNewerThan(): Examples setting classes. (line 18) * IsPlain(): Examples setting classes. (line 18) * l=: Syntax. (line 51) * LastSeen: lastseen. (line 14) * LastSeenExpireAfter: lastseenexpireafter. (line 12) * LD_LIBRARY_PATH: control. (line 66) * link: Syntax. (line 51) * linkchildren <1>: Link Children. (line 6) * linkchildren: Files linkchildren. (line 6) * links <1>: links. (line 6) * links: actionsequence. (line 35) * m=: Syntax. (line 51) * mailcheck <1>: mailserver. (line 20) * mailcheck: actionsequence. (line 35) * mailserver: mailserver. (line 6) * MaxCfengines: Special variables. (line 89) * methods: methods. (line 6) * miscmounts: miscmounts. (line 6) * mode: Syntax. (line 51) * module: actionsequence. (line 35) * moduledirectory: moduledirectory. (line 6) * mountables <1>: mountables. (line 6) * mountables: homeservers. (line 35) * mountall: actionsequence. (line 35) * mountinfo: actionsequence. (line 35) * mountpattern: mountpattern. (line 6) * netconfig: actionsequence. (line 35) * netmask <1>: netmask. (line 6) * netmask: control. (line 66) * nfstype <1>: nfstype. (line 6) * nfstype: control. (line 66) * noabspath: shellcommands. (line 110) * none: methods. (line 95) * o=: Syntax. (line 51) * ones: broadcast. (line 22) * OutputPrefix: Special variables. (line 101) * owner: Syntax. (line 51) * p=: tidy. (line 42) * packages: actionsequence. (line 35) * pattern: tidy. (line 42) * pkgmgr=: packages. (line 106) * processes: actionsequence. (line 35) * purge=: copy. (line 345) * r= <1>: tidy. (line 42) * r=: Syntax. (line 51) * Randomizing strategy: strategies. (line 6) * recurse <1>: tidy. (line 42) * recurse: Syntax. (line 51) * RepChar: repchar. (line 14) * repchar: Special variables. (line 105) * required: actionsequence. (line 35) * resolve <1>: resolve. (line 6) * resolve: actionsequence. (line 35) * Restricting access: access. (line 6) * ReturnsZero(): Examples setting classes. (line 18) * rotate=: disable. (line 91) * rxdirs: Syntax. (line 51) * scanarrivals=: disks. (line 77) * scheduling: schedule. (line 6) * scli command interpreter: scli. (line 43) * SecureInput: secureinput. (line 6) * SensibleCount: sensiblecount. (line 6) * sensiblecount: control. (line 66) * SensibleSize: sensiblesize. (line 6) * sensiblesize: control. (line 66) * shellcommands: actionsequence. (line 35) * ShowActions: showactions. (line 6) * signal: processes. (line 183) * singlelinks: actionsequence. (line 35) * site <1>: site. (line 6) * site: control. (line 66) * SkipVerify: root=. (line 25) * smtpserver: Cfexecd reference. (line 43) * SNMP: scli. (line 43) * Split: EditSplit. (line 14) * split <1>: split. (line 15) * split <2>: Iteration over lists. (line 89) * split: Special variables. (line 115) * SpoolDirectories: spooldirectories. (line 6) * SuspiciousNames: suspiciousnames. (line 6) * sysadm <1>: Cfexecd reference. (line 43) * sysadm <2>: sysadm. (line 6) * sysadm: control. (line 66) * tidy <1>: tidy. (line 6) * tidy: actionsequence. (line 35) * timezone: control. (line 66) * touch: touch. (line 6) * truncate: disable. (line 91) * type= <1>: Hard links. (line 6) * type=: disable. (line 82) * underscoreclasses: Special variables. (line 126) * unmount <1>: unmount. (line 6) * unmount: actionsequence. (line 35) * version=: packages. (line 99) * Wildcards: tidy. (line 59) * zeroes: broadcast. (line 22) * zeros: broadcast. (line 22)  File: cfengine-Reference.info, Node: Concept Index, Next: FAQ Index, Prev: Variable Index, Up: Top Concept Index ************* [index] * Menu: * !: Cfengine classes. (line 98) * --dry-run option: shellcommands. (line 102) * -D option: addclasses. (line 20) * -l option: tidy. (line 87) * -L option: Single links. (line 22) * -l option: Syntax. (line 154) * -T in cfrun.: cfrun. (line 31) * -x option: cf.preconf bootstrap file. (line 74) * .cfdisabled: disable. (line 43) * .cfengine.rm: tidy. (line 184) * .cfnew files: copy. (line 14) * .cfsaved files: Multiple Links. (line 22) * .X11 directory: ignore. (line 47) * /etc/host.conf: cf.preconf bootstrap file. (line 74) * /etc/hosts.equiv: disable. (line 43) * /var/cfengine/output: Cfexecd reference. (line 27) * <: UserExists. (line 10) * >: UserExists. (line 10) * Abort cfengine after cf.preconf: cf.preconf bootstrap file. (line 79) * AbortClasses: AbortClasses. (line 12) * Aborting cfagent: AbortClasses. (line 12) * Absolute links: Single links. (line 64) * Access control: access. (line 6) * Access control and symlinks: root=. (line 19) * Access control by directory: root=. (line 19) * Access control lists: acl. (line 6) * ACL key: ACEs. (line 11) * ACLs: acl. (line 6) * action sequence: actionsequence. (line 6) * Adding defined classes: addclasses. (line 6) * Adding new classes: cfrc resource file. (line 39) * AFS: nfstype. (line 22) * Alerts: alerts. (line 6) * allclasses file: Cfagent Runtime Options. (line 145) * allclasses variable: shellcommands. (line 164) * AllowConnectionsFrom variable: AllowConnectionsFrom. (line 16) * AllowUsers in cfservd: AllowUsers. (line 25) * Andrew filesystem: nfstype. (line 22) * AppendIfNoSuchLinesFromFile: AppendIfNoSuchLinesFromFile. (line 11) * Array example: Setting variables with functions. (line 217) * Array from file: Setting variables with functions. (line 217) * Associative arrays.: Setting variables with functions. (line 40) * atime tidies: tidy. (line 140) * Audit log: Auditing. (line 6) * Auditing: Special variables. (line 27) * AutoCreate: AutoCreate. (line 12) * AutoExecInterval variable: AutoExecInterval. (line 6) * automounter: AutomountDirectResources. (line 11) * awk, editing: editfiles. (line 10) * Backup: Backup in editfiles. (line 19) * Backup of files in copy: copy. (line 141) * BeginGroupIfDefined: BeginGroupIfDefined. (line 10) * BeginGroupIfFileExists: BeginGroupIfFileExists. (line 12) * BeginGroupIfFileIsNewer: BeginGroupIfFileIsNewer. (line 11) * BeginGroupIfNotDefined: BeginGroupIfNotDefined. (line 10) * Binary servers and links <1>: Link Children. (line 10) * Binary servers and links: Single links. (line 110) * Binary servers, defining: binservers. (line 6) * Binary servers, priority <1>: Single links. (line 133) * Binary servers, priority: binservers. (line 39) * Binding to one interface only <1>: BindToInterface in cfservd. (line 10) * Binding to one interface only: BindToInterface in cfagent. (line 11) * Bootstrap file: cf.preconf bootstrap file. (line 6) * Broadcast address: broadcast. (line 6) * Broadcasts to the cfengine service.: cfrun. (line 52) * Broken resolver: lastseen. (line 10) * Built-in functions: Setting variables with functions. (line 23) * Caching of reverse lookups: root=. (line 25) * CatchAbort: CatchAbort. (line 6) * cf.groups: cf.groups. (line 6) * cf.main: cf.main. (line 6) * cf.motd: cf.motd. (line 6) * cf.preconf bootstrap file: cf.preconf bootstrap file. (line 6) * cf.site <1>: cfservd.conf. (line 6) * cf.site: cf.site. (line 6) * cfagent.conf: cfagent.conf. (line 6) * CFALLCLASSES <1>: shellcommands. (line 164) * CFALLCLASSES: Special variables. (line 16) * CFALLCLASSES in a file: Cfagent Runtime Options. (line 145) * cfenvd and key entropy: Cfkey. (line 14) * cfexecd: Cfexecd reference. (line 43) * cfrc resource file: cfrc resource file. (line 6) * cfrun, limiting users on server: AllowUsers. (line 11) * cfrunCommand variable: cfrunCommand. (line 12) * cfservd.conf file: Cfservd.conf and cfrun reference. (line 13) * cfservd.conf iteration: Cfservd.conf and cfrun reference. (line 95) * Changing cfengine port: Firewalls and NATs. (line 32) * Checking for installed packages: packages. (line 6) * Checksum warning, turning off exclamation: exclamation. (line 12) * ChecksumDatabase: ChecksumDatabase in cfagent. (line 8) * ChecksumDatabase variable: ChecksumDatabase in cfservd. (line 15) * ChecksumPurge: ChecksumPurge. (line 8) * Checksums: Checksums and change management. (line 6) * ChecksumUpdates: ChecksumUpdates. (line 8) * CIDR: groups. (line 36) * Class data and scripts: Special variables. (line 16) * Class decided by shell command: groups. (line 102) * Class dependencies: groups. (line 73) * Class information, passing to scripts: shellcommands. (line 164) * classes <1>: groups. (line 10) * classes <2>: classes. (line 6) * classes: Cfengine classes. (line 6) * Classes, adding and defining: addclasses. (line 6) * Classes, built-in functions: Examples setting classes. (line 18) * Classes, compound: Cfengine classes. (line 59) * Classes, defining and undefining: Cfengine classes. (line 96) * Classless IP addresses: groups. (line 36) * Comparing file objects: Examples setting classes. (line 18) * Compound classes: Cfengine classes. (line 59) * compress: tidy. (line 42) * CompressCommand: CompressCommand. (line 11) * Compression during tidy: tidy. (line 42) * Contacting specific hosts with cfrun: cfrun. (line 117) * control section: control. (line 6) * Controlling the size of log files: disable. (line 88) * copy: copy. (line 6) * Copy, exact filetree images: copy. (line 345) * Copying files: copy. (line 6) * Creating files: create. (line 6) * ctime tidies: tidy. (line 140) * DCE key: DFS ACLs. (line 6) * Deadlock: cf.preconf bootstrap file. (line 6) * Deadlock zombie bug in restart: processes. (line 122) * Debian Package Database Queries: packages. (line 187) * Declaring classes: addinstallable. (line 6) * Decrementing line pointer in editfiles: IncrementPointer. (line 14) * Defining a binary server: binservers. (line 6) * Defining a home server: homeservers. (line 6) * Defining a mail server: mailserver. (line 6) * Defining a mountable: mountables. (line 6) * Defining before use: addinstallable. (line 6) * Defining classes <1>: classes. (line 6) * Defining classes: addclasses. (line 6) * Defining groups: groups. (line 6) * DeleteNonOwnerMail: deletenonownerfiles. (line 14) * DeleteNonUserFiles: deletenonownerfiles. (line 14) * DeleteNonUserMail DeleteNonUserFiles: deletenonuserfiles. (line 13) * Deleting directories: tidy. (line 150) * Deleting files: tidy. (line 6) * Deleting stale links <1>: tidy. (line 100) * Deleting stale links: Syntax. (line 164) * DenyBadClocks variable: DenyBadClocks. (line 9) * DenyConnectionsFrom variable: DenyConnectionsFrom. (line 12) * Dependencies: groups. (line 73) * Device boundaries: copy. (line 178) * Device boundaries and files: Recursion. (line 15) * DFS: nfstype. (line 22) * DHCP <1>: DynamicAddresses. (line 20) * DHCP: actionsequence. (line 127) * DHCP addresses: DynamicAddresses. (line 8) * Directories, deleting: tidy. (line 150) * Directories, hidden: fileextension. (line 13) * Directories, making: directories. (line 6) * Directory for cfengine modules: moduledirectory. (line 6) * Directory permissions: Directory permissions. (line 6) * Disabling file types: disable. (line 82) * Disabling files: disable. (line 6) * disks actions: disks. (line 6) * DNS: resolve. (line 6) * domain: domain. (line 6) * Domain name: netmask. (line 14) * Dots in hostnames: Cfengine classes. (line 159) * Double quotes: editfiles. (line 63) * DryRun: dryrun. (line 6) * Dual homed hosts: interfaces. (line 6) * Dynamic addresses: DynamicAddresses. (line 20) * DynamicAddresses variable: DynamicAddresses. (line 13) * Emergency abort: cf.preconf bootstrap file. (line 79) * Empty files: tidy. (line 115) * Emptying old nameservers from /etc/resolv.conf: emptyresolvconf. (line 6) * Environment variable CFALLCLASSES: Cfagent Runtime Options. (line 145) * Example configuration files: Example configuration file. (line 6) * Exclamation marks, turning off: exclamation. (line 12) * Excluding classes: addclasses. (line 30) * Excluding files from a file sweep: Syntax. (line 141) * ExpandVariables: ExpandVariables. (line 9) * failover: copy. (line 257) * Field separator in editfiles: SplitOn. (line 13) * File images (copy): copy. (line 6) * File management: files. (line 6) * File sizes, specifying: tidy. (line 115) * File tree images: copy. (line 345) * File types: Examples setting classes. (line 18) * Files, breaking up into several: import. (line 6) * Files, checking permissions: files. (line 6) * Files, home wildcard: home directive. (line 6) * Files, importing: import. (line 6) * Files, ownership: Owner and group wildcards. (line 6) * Files, recursion: Recursion. (line 6) * Files, setting owner: files. (line 6) * Files, syntax: Syntax. (line 6) * Force copying: copy example. (line 39) * FreeBSD Package Database Queries: packages. (line 193) * freespace=: disks. (line 57) * FriendStatus: alerts. (line 115) * Full disk warnings: disks. (line 57) * Fully qualified names: Cfengine classes. (line 159) * Functions, built-in: Setting variables with functions. (line 23) * Gaming stratgies: strategies. (line 6) * Gentoo Package Database Queries: packages. (line 155) * Group dependencies: groups. (line 73) * Group field, editing: SplitOn. (line 13) * groups <1>: groups. (line 10) * groups: classes. (line 6) * Groups, defining: groups. (line 6) * Hanging processes: lastseen. (line 10) * Hard class name collision: Special variables. (line 126) * Hardlinks: Hard links. (line 6) * Hashes: Checksums and change management. (line 6) * Hashes of files <1>: Syntax. (line 196) * Hashes of files: ChecksumDatabase in cfagent. (line 8) * home directive: home directive. (line 6) * Home directories, creating: directories. (line 56) * Home path: homepattern. (line 6) * Home servers, defining: homeservers. (line 6) * home wildcard: Syntax. (line 64) * Homepattern variable.: mountables. (line 35) * Host name gets truncated: Cfengine classes. (line 159) * Hostname collision: Special variables. (line 126) * HostnameKeys: Firewalls and NATs. (line 28) * hostnamekeys: cfrun. (line 80) * Hung machine: cf.preconf bootstrap file. (line 6) * ignore command: ignore. (line 18) * Import files, variables in: import. (line 33) * Importing files: import. (line 6) * include in cfrun: cfrun. (line 80) * Incrementing line pointer in editfiles: IncrementPointer. (line 14) * Interface classes: IgnoreInterfaceRegex. (line 12) * Interface name, redefining by class: interfacename. (line 6) * InterfaceName: interfacename. (line 6) * Internal classes, switching off: Cfagent Runtime Options. (line 72) * Internet address: netmask. (line 14) * IP address: netmask. (line 14) * IPV6 and DHCP: DynamicAddresses. (line 29) * IsGreatThan: UserExists. (line 10) * IsLessThan: UserExists. (line 10) * Iterating over lists in shellcommands: shellcommands. (line 184) * Iteration in server rules: Cfservd.conf and cfrun reference. (line 95) * Iteration over lists <1>: split. (line 15) * Iteration over lists: Iteration over lists. (line 89) * Iteration over lists (editfiles): EditSplit. (line 14) * Key entropy and cfenvd: Cfkey. (line 14) * Key security of users: AllowUsers. (line 11) * Key, ACL: DFS ACLs. (line 6) * Kilobyte, filesize unit: tidy. (line 115) * Last Seen database <1>: lastseenexpireafter. (line 12) * Last Seen database: alerts. (line 115) * LastNode literal: directories. (line 56) * LastSeen: lastseen. (line 10) * Linkchildren <1>: Link Children. (line 6) * Linkchildren: Files linkchildren. (line 6) * Links and binary servers <1>: Link Children. (line 10) * Links and binary servers: Single links. (line 110) * Links in access control: root=. (line 19) * Links, absolute: Single links. (line 64) * Links, deleting stale <1>: tidy. (line 100) * Links, deleting stale: Syntax. (line 164) * Links, forcing for non-existent files: Single links. (line 81) * Links, making: links. (line 6) * Links, multiple: Multiple Links. (line 6) * Links, removing dead: Single links. (line 81) * Links, single: Single links. (line 6) * Links, traversing in searches <1>: tidy. (line 87) * Links, traversing in searches: Syntax. (line 154) * Local disk space, make use of: Link Children. (line 34) * Log files, controlling the size of: disable. (line 88) * Logical NOT: Cfengine classes. (line 98) * m4 functionality: ExpandVariables. (line 9) * Mail from cfexecd: Cfexecd reference. (line 84) * Mail server, defining: mailserver. (line 6) * Mailhost: Smtpserver. (line 8) * Mailing output: Cfexecd reference. (line 43) * Making directories: directories. (line 6) * Making links: links. (line 6) * Making paths: directories. (line 6) * Making use of local disk space: Link Children. (line 34) * MaxConnections variable: MaxConnections. (line 8) * Megabytes, filesize unit: tidy. (line 115) * Merging files.: AppendIfNoLineMatching. (line 25) * Message digests <1>: Syntax. (line 196) * Message digests: ChecksumDatabase in cfagent. (line 8) * Methods: methods. (line 6) * Methods, remote caution: methods. (line 26) * Miscellaneous mount operations: miscmounts. (line 6) * Module directory <1>: moduledirectory. (line 6) * Module directory: PrepModule. (line 11) * Modules executed immediately: PrepModule. (line 11) * Modules, user defined: actionsequence. (line 79) * Monitoring other hosts: alerts. (line 115) * Mount paths: mountpattern. (line 6) * Mountable resources, defining <1>: mountables. (line 6) * Mountable resources, defining: homeservers. (line 35) * Mounted filesystems: copy. (line 178) * Mounting filesystems.: miscmounts. (line 6) * mtime tidies: tidy. (line 140) * Multihomed hosts <1>: BindToInterface in cfservd. (line 10) * Multihomed hosts: BindToInterface in cfagent. (line 11) * Multiple links: Multiple Links. (line 6) * Name collision: Special variables. (line 126) * NAT: Firewalls and NATs. (line 32) * Negating classes: actionsequence. (line 183) * Negating entries from netgroups: groups. (line 60) * Netgroups: groups. (line 40) * Netgroups, negating entries: groups. (line 60) * Netmask: netmask. (line 14) * netmask: netmask. (line 6) * Network Address Translation: SkipIdentify. (line 14) * Network address translator: Firewalls and NATs. (line 32) * Network Address Translators: SkipVerify. (line 19) * Network interfaces, several: interfaces. (line 6) * New systems, support for: cfrc resource file. (line 39) * nfs: nfstype. (line 6) * NFS filesystems and disk checking: disks. (line 75) * NFS mount model and automounter: AutomountDirectResources. (line 11) * nfstype: nfstype. (line 6) * NIS, netgroup support: groups. (line 40) * no_default_route class: defaultroute. (line 41) * noabspath: shellcommands. (line 110) * none in server: methods. (line 95) * NOT operator: Cfengine classes. (line 98) * NT, ACL: NT ACLs. (line 6) * ones: broadcast. (line 22) * Operator ordering: Cfengine classes. (line 161) * Output logs: Cfexecd reference. (line 27) * Ownership of files: Owner and group wildcards. (line 6) * packages: packages. (line 6) * Password file, editing: SplitOn. (line 13) * Path to home directories: homepattern. (line 6) * Path to mounted filesystems: mountpattern. (line 6) * Paths, making: directories. (line 6) * Pattern matching in file sweeps: Syntax. (line 136) * pattern= and filtering: tidy. (line 59) * Peer to peer methods: Setting variables with functions. (line 161) * Peer watching (FriendStatus): alerts. (line 115) * Percentage disk space: disks. (line 64) * Permissions, directories: Directory permissions. (line 6) * Port, connecting to different: Firewalls and NATs. (line 32) * PrepModule: PrepModule. (line 11) * Preserving file times in copy: copy. (line 171) * Previewing shellcommands: shellcommands. (line 102) * PrintFile: alerts. (line 115) * Private modules: methods. (line 6) * PRNG not seeded: Cfkey. (line 18) * Processes, 0 to 3: processes. (line 99) * Processes, checking existence of: processes. (line 191) * Processes, counting: processes. (line 163) * Processes, signalling: processes. (line 191) * Public keys: copy. (line 269) * Purge, excluding files: copy. (line 201) * Quoted strings: editfiles. (line 63) * Random numbers: Setting variables with functions. (line 23) * RandomInt() function: control. (line 54) * Read array from file: Setting variables with functions. (line 217) * Read array from table: Setting variables with functions. (line 100) * ReadArray: Setting variables with functions. (line 217) * ReadFile: Setting variables with functions. (line 88) * ReadFile() function: control. (line 54) * ReadTable: Setting variables with functions. (line 100) * Recursion in files: Recursion. (line 6) * Redefinition of macros: AllowRedefinitionOf. (line 19) * Relative links: Single links. (line 64) * Removing directories: tidy. (line 150) * Removing entries from netgroups: groups. (line 60) * Renaming files: disable. (line 6) * Replacing file by link: disable. (line 82) * Repository filenames, changing: repchar. (line 14) * resolv.conf: resolve. (line 6) * Resolver configuration: resolve. (line 6) * Resource file: cfrc resource file. (line 6) * Restart zombie deadlock bug: processes. (line 122) * Restricting the size of binary files to be edited: editbinaryfilesize. (line 6) * Restricting the size of files to be edited: editfilesize. (line 6) * Reverse lookup and SkipVerify: root=. (line 25) * rmdirs: tidy. (line 150) * Rotating log files: disable. (line 88) * RPM Database Queries: packages. (line 123) * Running cfengine from a single master host: cfrun. (line 95) * Running cfrun: cfrun. (line 41) * scanarrivals=: disks. (line 77) * scheduling: schedule. (line 6) * Scripts and class information: shellcommands. (line 164) * Scripts, passing classes to: Special variables. (line 16) * Search patterns in files: Syntax. (line 136) * Searching for home directories: homepattern. (line 23) * Searching, advanced: filters. (line 6) * Secure input: secureinput. (line 6) * Security risk: SkipVerify. (line 19) * Security, link races and travlinks: tidy. (line 138) * sed, editing: editfiles. (line 10) * Selecting files in searches: filters. (line 6) * SelectPartitionGroup: Setting variables with functions. (line 161) * SelectPartitionLeader: Setting variables with functions. (line 179) * Sensible file sizes: sensiblesize. (line 6) * Sensible limits on files in a directory: sensiblecount. (line 6) * SetState(): alerts. (line 32) * Setting classes based on non-local disks: disks. (line 75) * Setting uid on restarted processes: processes. (line 124) * Several files: import. (line 6) * Shell command to decide class: groups. (line 102) * ShowState(): alerts. (line 32) * Single links: Single links. (line 6) * Single quotes: editfiles. (line 63) * site: site. (line 6) * size field in disable: disable. (line 137) * SkipIdentify: SkipIdentify. (line 14) * SkipVerify and public-private keys: root=. (line 25) * smtpserver: Smtpserver. (line 8) * Spam suppression: Cfexecd reference. (line 84) * Specifying file sizes: tidy. (line 115) * SplayTime in cfrun: cfrun. (line 29) * split <1>: split. (line 15) * split: Iteration over lists. (line 89) * Split in editfiles: EditSplit. (line 14) * SplitOn: SplitOn. (line 13) * SpoolDirectories: spooldirectories. (line 6) * Strategy, random: strategies. (line 6) * Subnet mask: netmask. (line 14) * Sun Package Database Queries: packages. (line 190) * Support for new systems: cfrc resource file. (line 39) * suspiciousnames: suspiciousnames. (line 6) * Switching off backup in copy: copy. (line 141) * Switching off built-in classes: Cfagent Runtime Options. (line 72) * Symbolic links in admit: root=. (line 19) * Symbolic links, absolute: Single links. (line 64) * Symbolic links, relative: Single links. (line 64) * sysadm: sysadm. (line 6) * SysLog(): alerts. (line 32) * Templates: ExpandVariables. (line 9) * Testing files: Examples setting classes. (line 18) * Tidy by ctime, mtime, atime: tidy. (line 140) * Tidy log files for users: LogTidyHomeFiles. (line 12) * Tidying empty files: tidy. (line 115) * Tidying files: tidy. (line 6) * timeout= in shellcommands: shellcommands. (line 52) * Timeouts during iterations: shellcommands. (line 186) * Too many open files error: Too many open files. (line 6) * Touching files: touch. (line 6) * travlinks: tidy. (line 138) * Tree copying, exact: copy. (line 345) * Tripwire functionality <1>: Syntax. (line 196) * Tripwire functionality: ChecksumDatabase in cfagent. (line 8) * Truncating log files: disable. (line 88) * Trust, key exchange with cfrun: cfrun. (line 31) * Trusted hosts: copy. (line 269) * TrustKeysFrom variable: TrustKeysFrom. (line 18) * umask <1>: shellcommands. (line 40) * umask <2>: processes. (line 46) * umask: Umask. (line 9) * underscoreclasses: Special variables. (line 126) * Unmounting filesystems: unmount. (line 6) * UnsetState(): alerts. (line 32) * update.conf: Work directory. (line 32) * Variables in import files: import. (line 33) * Variables, setting to result of a shell command: Setting variables with functions. (line 11) * Version control: Special variables. (line 27) * Virtual interfaces: IgnoreInterfaceRegex. (line 12) * Warning about full disks: disks. (line 57) * Warning remote methods: methods. (line 26) * Wildcard home: Syntax. (line 64) * Wildcards in homepattern: homepattern. (line 23) * WWW server logs: disable. (line 117) * xdev <1>: tidy. (line 156) * xdev <2>: Syntax. (line 200) * xdev: copy. (line 214) * xdev (File system boundaries): Recursion. (line 15) * zeros: broadcast. (line 22)  File: cfengine-Reference.info, Node: FAQ Index, Prev: Concept Index, Up: Top FAQ Index ********* [index] * Menu: * Absolute path and shellcommands: shellcommands. (line 110) * Brackets (parentheses) in classes.: Cfengine classes. (line 161) * Can't stat error when remote copying: DenyBadClocks. (line 9) * Changing repository name conventions: repchar. (line 14) * Checksums take too long to compute.: ChecksumDatabase in cfservd. (line 15) * copy doesn't always copy files: copy. (line 161) * ctime copy doesn't always copy files: copy. (line 161) * Denial of service attacks: AllowConnectionsFrom. (line 16) * Hanging commands, timeouts: shellcommands. (line 52) * Hanging connections attacks: AllowConnectionsFrom. (line 16) * Hey! Cannot stat file error: copy. (line 252) * How can I avoid hanging shellcommands?: shellcommands. (line 52) * How can I set a timeout for a shell command?: shellcommands. (line 52) * How to create files while editing: AutoCreate. (line 12) * Iterating over lists <1>: split. (line 15) * Iterating over lists: Iteration over lists. (line 89) * locahost in copy: copy. (line 252) * MD5 checksums take a long time to compute.: ChecksumDatabase in cfservd. (line 15) * Parentheses in classes.: Cfengine classes. (line 161) * Remote copy problems, can't stat: copy. (line 252) * Shellcommands must start with absolute path: shellcommands. (line 110) * Too many open files error: Too many open files. (line 6) cfengine-2.2.10/doc/cfengine-Reference.info-10000644000175000001440000110537711170173455015543 00000000000000This is cfengine-Reference.info, produced by makeinfo version 4.12 from cfengine-Reference.texinfo. INFO-DIR-SECTION System Utilities START-INFO-DIR-ENTRY * cfengine Reference: (cfengine-Reference.info). Cfengine is a language based tool specifically designed for configuring and maintaining BSD and System-5-like operating systems attached to a TCP/IP network. END-INFO-DIR-ENTRY  File: cfengine-Reference.info, Node: Top, Next: Reference introduction, Prev: (dir), Up: (dir) Cfengine-Reference ****************** Copyright (C) 2008 Mark Burgess This manual corresponds to CFENGINE Edition 2.2.10 for version 2.2.10 as last updated 21 January 2009. * Menu: * Reference introduction:: * Cfkey:: * Cfshow:: * Cfagent reference:: * Cfservd.conf and cfrun reference:: * Cfexecd reference:: * Problem solving:: * Example configuration file:: * Variable Index:: * Concept Index:: * FAQ Index::  File: cfengine-Reference.info, Node: Reference introduction, Next: Cfkey, Prev: Top, Up: Top 1 Introduction to reference manual ********************************** The purpose of the cfengine reference manual is to collect together and document the raw facts about the different components of cfengine. Once you have become proficient in the use of cfengine, you will no longer have need of the tutorial. The reference manual, on the other hand, changes with each version of cfengine. You will be able to use it online, or in printed form to find out the details you require to implement configurations in practice. * Menu: * Installation:: * Work directory:: * Hard classes:: * Filenames and paths:: * Debugging with signals::  File: cfengine-Reference.info, Node: Installation, Next: Work directory, Prev: Reference introduction, Up: Reference introduction 1.1 Installation ================ In order to install cfengine, you should first ensure that the following packages are installed. OpenSSL Open source Secure Sockets Layer for encryption. URL: `http://www.openssl.org' BerkeleyDB (version 3.2 or later) Light-weight flat-file database system. URL: `http://www.oracle.com/technology/products/berkeley-db/index.html' The preferred method of installation is then tar zxf cfengine-x.x.x.tar.gz cd cfengine-x.x.x ./configure make make install This results in binaries being installed in `/usr/local/sbin'. Since this is not necessarily a local file system on all hosts, users are encouraged to keep local copies of the binaries on each host, inside the cfengine trusted work directory.  File: cfengine-Reference.info, Node: Work directory, Next: Hard classes, Prev: Installation, Up: Reference introduction 1.2 Work directory ================== In order to achieve the desired simplifications, it was decided to reserve a private work area for the cfengine tool-set. In cfengine 1.x, the administrator could choose the locations of configuration files, locks, and logging data independently. In cfengine 2.x, this diversity has been simplified to a single directory which defaults to `/var/cfengine' (similar to `/var/cron'): /var/cfengine /var/cfengine/bin /var/cfengine/inputs /var/cfengine/outputs The installation location `/usr/local/sbin' is not necessarily a local file system, and cannot therefore be trusted to a) be present, and b) be authentic on an arbitrary system. Similarly, a trusted cache of the input files must now be maintained in the `inputs' subdirectory. When cfengine is invoked by the scheduler, it reads only from this directory. It is up to the user to keep this cache updated, on each host. This simplifies and consolidates the cfengine resources in a single place. The environment variable `CFINPUTS' still overrides this default location, as before, but in its absence or when called from the scheduler, this becomes the location of trusted files. A special configuration file `update.conf' is parsed and run before the main configuration is parsed, which is used to ensure that the currently caches policy is up-to-date. This has private classes and variables. If no value is set for `CFINPUTS', then the default location is the trusted cfengine directory `/var/cfengine/inputs'. The `outputs' directory is now a record of spooled run-reports. These are mailed to the administrator, as previously, or can be copied to another central location and viewed in an alternative browser..  File: cfengine-Reference.info, Node: Hard classes, Next: Filenames and paths, Prev: Work directory, Up: Reference introduction 1.3 Cfengine hard classes ========================= A single class can be one of several things: * The name of an operating system architecture e.g. `ultrix', `sun4', etc. This is referred to as a _hard class_. * The unqualified name of a particular host. If your system returns a fully qualified domain name for your host, cfagent truncates it at the first dot. * The name of a user-defined group of hosts. * A day of the week (in the form `Monday, Tuesday, Wednesday, ..'). * An hour of the day (in the form `Hr00, Hr01 ... Hr23'). * Minutes in the hour (in the form `Min00, Min17 ... Min45'). * A five minute interval in the hour (in the form `Min00_05, Min05_10 ... Min55_00') * A day of the month (in the form `Day1, Day2, ... Day31'). * A month (in the form `January, February, ... December'). * A year (in the form `Yr1997, Yr2004'). * An arbitrary user-defined string. * The IP address octets of any active interface (in the form `ipv4_192_0_0_1', `ipv4_192_0_0', `ipv4_192_0', `ipv4_192'). * The name of all interfaces Cfengine can find, in the form `net_iface_eth0'. To see all of the classes define on a particular host, run host# cfagent -p -v as a privileged user. Note that some of the classes are set only if a trusted link can be established with cfenvd, i.e. if both are running with privilege, and the `/var/cfengine/state/env_data' file is secure. More information about classes can be found in connection with `allclasses'.  File: cfengine-Reference.info, Node: Filenames and paths, Next: Debugging with signals, Prev: Hard classes, Up: Reference introduction 1.4 Filenames and paths ======================= Filenames in Unix-like operating systems use for their directory separator the forward slash '/' character. All references to file locations must be absolute pathnames in cfengine, i.e. they must begin with a complete specification of which directory they are in. For example: /etc/passwd /usr/local/masterfiles/distfile The only place where it makes sense to refer to a file without a complete directory specification is when searching through directories for different kinds of file, e.g. tidy: /home/user pattern=core age=0 recurse=inf Here, one can write `core' without a path, because one is looking for any file of that name in a number of directories. The Windows operating systems traditionally use a different filename convention. The following are all valid absolute file names under Windows: c:\winnt c:/winnt /var/cfengine/inputs //FILESERVER/share2/dir The `drive' name "C:" in Windows refers to a partition or device. Unlike Unix, Windows does not integrate these seamlessly into a single file-tree. This is not a valid absolute filename: \var\cfengine\inputs Paths beginning with a backslash are assumed to be win32 paths. They must begin with a drive letter or double-slash server name.  File: cfengine-Reference.info, Node: Debugging with signals, Prev: Filenames and paths, Up: Reference introduction 1.5 Debugging with signals ========================== It is possible to turn debugging output on or off on a running cfagent. This is useful for troubleshooting the cause of hangups, or for getting debugging output from a cfagent launched from cfexecd. A running cfagent process that receives a SIGUSR1 will immediately begin to behave as if it had been invoked with the '-d2' option. A SIGUSR2 will cause a running cfagent to run as if the '-d2' option had not been invoked. Note that this output is often quite verbose. * Menu: * Cfagent reference:: * Cfservd.conf and cfrun reference:: * Cfexecd reference:: * Problem solving:: * Example configuration file:: * Variable Index:: * Concept Index:: * FAQ Index::  File: cfengine-Reference.info, Node: Cfkey, Next: Cfshow, Prev: Reference introduction, Up: Top 2 Cfkey reference ***************** The very first thing you should do on every host is to establish a public-private key pair. To do this, you need to run the program everyhost# cfkey on every host. This program needs to produce random numbers, and needs a source of randomness. A good strategy is to install and run the `cfenvd' program for a week or two in advance of deploying cfengine 2, since `cfenvd' collects random events, which are an excellent source of entropy for random number generation. If you get the error message "PRNG not seeded", it means that insufficient data were found in order to make a random key. In that case, run `cfenvd' for a few days more and try again. * Menu: * Cfagent reference:: * Cfservd.conf and cfrun reference:: * Cfexecd reference:: * Problem solving:: * Example configuration file:: * Variable Index:: * Concept Index:: * FAQ Index::  File: cfengine-Reference.info, Node: Cfshow, Next: Cfagent reference, Prev: Cfkey, Up: Top 3 Cfshow reference ****************** The `cfshow' command was introduced in cfengine 2.1.11 in order to provide a simple way to show some of the data stored by cfagent for operational purposes. everyhost# cfshow -a everyhost# cfshow -l everyhost# cfshow -c everyhost# cfshow -s everyhost# cfshow -p everyhost# cfshow -f cfagent.conf -r linux.* The command line options are `-a `--active'' This prints a list of any currently active locks, i.e. tasks that cfengine believes it is currently enagaged in. `-A `--audit'' This prints a history of cfengine's behaviour collected if the Auditing variable is true, *Note Auditing::. The audit data are best viewed in html or parsed with xml, using the `--html' and `--xml' options. `-c `--checksum'' This lists all of the files and their current checksum values in the current checksum database. `-C `--classes'' This lists all of the classes that have been used on the system over the past year, with frequency probabilities to show their relative occurrance rates and last observed times. `-H `--html'' Generate output in web browser-friendly html. `-l `--locks'' This prints a list of the locks and the last times an active lock was secured for each cfengine acivity. This list is potentially very long. `-s `--last-seen'' This lists the IP addresses of all known peers and the times they were last engaged in communication with the current host. The expected interval between communications is also printed. See FriendStatus. The output format is in a form that can easily be parsed by user scripts. e.g. IP + 192.168.1.101 192.168.1.101 [Tue Jan 23 16:13] not seen for (6.42) hrs, Av 0.02 +/- 0.01 hrs IP - 192.168.1.101 192.168.1.101 [Tue Jan 23 16:13] not seen for (6.42) hrs, Av 0.02 +/- 0.01 hrs Lines marked with a + represent successful attempts made by cfagent on the current host to connect to another host. Lines with a - are connections attempted (but not necessarily succeeded) into cfservd from another host's cfagent or cfrun. `-r `--regex' REGEX' Search the cfengine policy file (e.g. `cfagent.conf') for rules that belong to classes matching the named regular expression. Note that the class "any" is not automatically matched and the search is based on the class text from the file. The output is not related to which classes are currently defined. `-s `--performance'' Shows the time in seconds required to complete copies and shell executions. (0.00 mins Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfagent > /var/cfengine/bin/cfagent) (0.00 mins Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfenvd > /var/cfengine/bin/cfenvd) (0.02 mins Tue Feb 13 19:05) Av 0.02 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfexecd > /var/cfengine/bin/cfexecd) (0.00 mins Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfservd > /var/cfengine/bin/cfservd) (6.41 mins Tue Feb 13 18:50) Av 0.00 +/- 0.00 for Exec(/usr/bin/updatedb --prunepaths=/media) (0.00 mins Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Exec(/usr/sbin/ntpdate 128.39.74.16 > /dev/null) `-X `--xml'' Generate output in xml for parsing by scripts etc. * Menu: * Cfagent reference:: * Cfservd.conf and cfrun reference:: * Cfexecd reference:: * Problem solving:: * Example configuration file:: * Variable Index:: * Concept Index:: * FAQ Index::  File: cfengine-Reference.info, Node: Cfagent reference, Next: Cfservd.conf and cfrun reference, Prev: Cfshow, Up: Top 4 Cfagent reference ******************* * Menu: * Cfagent intro:: * The file cfagent.conf:: * Cfagent Runtime Options:: * Variable expansion and contexts:: * Cfengine classes:: * acl:: * alerts:: * binservers:: * broadcast:: * control:: * classes:: * copy:: * defaultroute:: * disks:: * directories:: * disable:: * editfiles:: * Editfiles on Binary Files:: * files:: * filters:: * groups:: * homeservers:: * ignore:: * import:: * interfaces:: * links:: * mailserver:: * methods:: * miscmounts:: * mountables:: * processes:: * packages:: * rename:: * required:: * resolve:: * scli:: * shellcommands:: * strategies:: * tidy:: * unmount::  File: cfengine-Reference.info, Node: Cfagent intro, Next: The file cfagent.conf, Prev: Cfagent reference, Up: Cfagent reference 4.1 Cfagent intro ================= Cfagent is the workhorse of cfengine. It interprets and computes the necessary strategies for implementing convergent maintenance. In order to carry out work efficiently, the agent groups similar actions together. The order of these actions is goverened by a list called the actionsequence. In many cases, cfagent will be able to complete all its work in a single pass of the actionsequence. However, in complex configurations, it is hard to resolve all of the ordering dependencies automatically in a single pass. Cfagent keeps track both of all actions that have been performed and of those that might still need to be performed (given that some actions depend on the later outcomes of others). If there is a possibility that an action ordering dilemma might occur, it runs a second pass of the actionsequence to more quickly resolve the dependency (avoiding the wait for next scheduled run). No actions are performed twice however, since the agent checks off actions that have already been performed to avoid unnecessary duplication. * Menu: * The file cfagent.conf:: * Cfagent Runtime Options::  File: cfengine-Reference.info, Node: The file cfagent.conf, Next: Cfagent Runtime Options, Prev: Cfagent intro, Up: Cfagent reference 4.2 The file cfagent.conf ========================= control: CLASSES:: domain = ( DNS-DOMAIN-NAME ) classes: CLASS/GROUP DEFINITIONS import: FILES TO IMPORT # other items  File: cfengine-Reference.info, Node: Cfagent Runtime Options, Next: Variable expansion and contexts, Prev: The file cfagent.conf, Up: Cfagent reference 4.3 Cfagent runtime options =========================== Note that GNU long options are available with the syntax `--longoption'. The long names are given in brackets. `-a' (`--sysadm') Print only the name of the system administrator then quit. `-A' (`--auto') Can be used to signify an automatic run of cfengine, as opposed to a manual run. The distinction is not predetermined. Use of this option currently causes cfengine to ignore locks. This option is reserved for future development. `-b' (`--force-net-copy') Normally cfengine detects attempts to copy from a server via the network that will loop back to the localhost. It then avoids using the network to make the copy. This option forces cfengine to copy using the network. _Yes, someone thinks this is useful!_ `-c' (`--no-check-files') Do not check file systems for ownership / permissions etc. `-C' (`--no-check-mounts') Check mount points for consistency. If this option is specified then directories which lie in the "mount point" area are checked to see whether there is anything mounted on them. Normally this is _off_ since not all machines use mounted file systems in the same way. e.g. HPUX does not generally operate with partitions, but nevertheless one might wish to mimick a partition-like environment there, but it would be irritating to be informed that nothing was mounted on the mount point. `-d' (`--debug') Enable debugging output. Normally you will want to send this to a file using the shell script command or a pipe. -d1 shows only parsing output. -d2 shows only runtime action output. -d0 shows both levels. Debugging ouput is intended mainly for the author's convenience and is not a supported feature. The details of this output may change at any time. `-D' (`--define') Define a compound class symbol of the form _alpha.beta.gamma_. `-e' (`--no-edits') Suppress file editing. `-E' (`--enforce-links') Globally force links to be created where plain files or links already exist. Since this option is a big hammer, you have to use it in interactive mode and answer a yes/no query before cfengine will run like this. `-f' (`--file') Parse filename after this switch. By default cfengine looks for a file called _cfengine.conf_ in the current directory. `-h' (`--help') Help information. Display version banner and options summary. `-H' (`--no-hard-classes'). Prevents cfengine from generating any built-in class name information. Can be used for emulation purposes. `-i' (`--no-ifconfig') Do not attempt to configure the local area network interface. `-I' (`--inform') Switches on the inform output level, whereby cfengine reports everything it changes.. `-k' (`--no-copy') Do not copy/image any files. `-K' (`--no-lock') Ignore locks when running. `-l' (`--traverse-links') Normally cfengine does not follow symbolic links when recursively parsing directories. This option will force it to do so. `-L' (`--delete-stale-links') Delete links which do not point to existing files (except in user home directories, which are not touched). `-m' (`--no-mount') Do not attempt to mount file systems or edit the filesystem table. `-M' (`--no-modules') Ignore modules in actionsequence. `-n' (`--recon',`--dry-run',`--just-print') No action. Only print what has to be done without actually doing it. `-N' (`--negate',`--undefine') Cancel a set of classes, or undefine (set value to _false_) a compound class of the form _alpha.beta.gamma_. `-p' (`--parse-only') Parse file and then stop. Used for checking the syntax of a program. You do not have to be superuser to use this option. `-P' (`--no-processes') Do not execute the processes action. `-q' (`--no-splay') Switch off host splaying (sleeping). `-Q' (`--quert') Query the values of the comma separated list of variable names. `-s' (`--no-commands') Do not execute scripts or shell commands. `-S' (`--silent') Silence run time warnings. `-t' (`--no-tidy') Do not tidy file systems. `-u' (`--use-env') Causes cfengine to generate an environment variable `CFALLCLASSES' which can be read by child processes (scripts). This variable contains a summary of all the currently defined classes at any given time. This option causes some System V systems to generate a Bus Error or segmentation fault. The same information is available from the cfengine built-in variable `$(allclasses)' and can be passed as a parameter to scripts. When this variable grows too large for embedding one can also access a complete list of current classes in `/var/cfengine/state/allclasses'. `-U' (`--underscore-classes'). When this option is set, cfengine adds an underscore to the beginning of the hard system classes (like `_sun4', `_linux' etc. The longer compound classes are not underscored, since these are already complex and would unlikely result in collisions.) This can be used to avoid naming conflicts if you are so unjudicious as to name a host by the name of a hard class. Other classes are not affected. `-v' (`--verbose') Verbose mode. Prints detailed information about actions and state. `-V' (`--version') Print only the version string and then quit. `-x' (`--no-preconf') Do not execute the `cf.preconf' net configuration file. `-X' (`--no-links') Do not execute the `links' section of a program. `-w' (`--no-warn',`--quiet') Do not print warning messages. `-z' (`--schedule') Print the exec schedule for the LAN (used by cfexecd). In version 2.0.4, an abbreviation for actionsequence exclusions was added: $ cfagent --avoid resolve,copy $ cfagent --just tidy --just shellcommands  File: cfengine-Reference.info, Node: Variable expansion and contexts, Next: Cfengine classes, Prev: Cfagent Runtime Options, Up: Cfagent reference 4.4 Variable expansion and contexts =================================== Variables in cfengine 2 are defined in contexts. Variables in a given context refer to the different phases of execution of cfengine: global, update and main. In the "current" context, variables have the form $(variable) ${variable} and are expanded either on parsing or at execution. Variables that cannot be expanded remain as dollar strings. Variables belonging to a context that is not the current one may be referred to as $(CONTEXT.variable) or ${CONTEXT.variable} Note carefully that cfengine requires parentheses or braces around variable names. Unlike in the shell, they cannot be omitted. There is no difference between these forms as far as cfengine is concerned. Some authors like to use the `()' form for cfengine variables, to distinguish them with shell variables in command strings. The `()' form does not work in function arguments, except inside quoted strings. Consider the example: $(global.env_time) Some variables in cfengine are associative arrays (as made famous by Perl). Such arrays are referred to by square brackets: $(array[key]) $(array[$(key)]) * Menu: * Setting variables with functions:: * Special variables:: * Iteration over lists::  File: cfengine-Reference.info, Node: Setting variables with functions, Next: Special variables, Prev: Variable expansion and contexts, Up: Variable expansion and contexts 4.4.1 Setting variables with functions -------------------------------------- A number of special functions can be used to set variables in cfengine. You can import values from the execution of a shell command by prefixing a command with the word `exec'. This method is deprecated as of cfengine version 2; use the `ExecResult' function instead. control: # old method listing = ( "exec /bin/ls -l" ) # new method listing = ( ExecResult(/bin/ls -l) ) This sets the variable `listing' to the output of the command in the quotes. Some other built-in functions are `A(X,Y)' Makes an associative array entry, associating X and Y. For instance: control: assoc_array = ( A(B,"is for bird") A(C,"is for cat") ) results in: OBJECT: main 4569 : assoc_array[B]=is for bird 4630 : assoc_array[C]=is for cat Another example: control: binhost = ( A(linux,machine1) A(solaris,machine2) ) copy: # Contact machine 1 for linux # Contact machine 2 for solaris /etc/source dest=/etc/receve server=$(binhost[$(class)]) `ExecResult(COMMAND)' Executes the named command without a shell-wrapper and inserts the output into the variable. Note that, when this is used in cfengine built-in list variables, any spaces are interpreted as list separators. In other lists, normal rules for iteration apply. `ExecShellResult(COMMAND)' Executes the named command with a shell-wrapper and inserts the output into the variable. Note that, when this is used in cfengine built-in list variables, any spaces are interpreted as list separators. In other lists, normal rules for iteration apply. `RandomInt(A,B)' Generate a random integer between a and b. `ReadArray(FILENAME,FILEFORMAT,SEPARATOR,COMMENT,MAX NUMBER OF BYTES)' Reads up to a maximum number of bytes from a properly formatted file into a one-dimensional associated array. File formats are: `autokey' If this format is specified, `ReadArray' tries to interpret the file as a table of items separated with the separator character. Blank lines and comments (to end of line) are ignored. Items are keyed numerically starting from 1 to the maximum number in the file. The newline `$(n)' is always considered to be a separator, no matter what the current separator is. `textkey' If this format is specified, `ReadArray' tries to interpret the file as a list of lines of the form: key,value `ReadFile(FILENAME,MAX NUMBER OF BYTES)' Read a maximum number of bytes from a file. `ReadTable(FILENAME,FILEFORMAT,SEPARATOR,COMMENT,MAX NUMBER OF BYTES)' Reads up to a maximum number of bytes from a properly formatted file into a two-dimensional associated array. `autokey' If this format is specified, `ReadArray' tries to interpret the file as a table of items separated with the separator character. Blank lines and comments (to end of line) are ignored. Items are keyed numerically starting from 1 to the maximum number in the file. Any lines that do not contain the correct number of separators cause the function to fail without making any assignment. `textkey' If this format is specified, `ReadArray' tries to interpret the file as a list of lines of the form: key1,key2,value1 key3,key4,value2 This variable would then be references as $(table[key1][key2]). `ReadList(FILENAME,FILEFORMAT,COMMENT,MAX NUMBER OF BYTES)' Reads up to a maximum number of bytes from a properly formatted file into a listvariable. File formats are: `lines' If this format is specified, `ReadList' tries to interpret the file as a list of items on separate lines. The value returned is a list formatted by the `Split' character. hosts = ( ReadList(/var/cfengine/inputs/datafile,lines,#,1000) ) `ReadTCP(HOST/IP,PORTNUMBER,SEND STRING,MAX NUMBER OF BYTES)' Reads up to a maximum number of bytes from a TCP service. Can be used to test whether certain services are responding to queries. It is recommended that this be used primarily to check services running on localhost. Bear in mind that this clause, executed on 100 hosts will produce the effect of a distributed denial of service attack, so the probe should be restricted to a single representative tester-host. For example: one_host_only:: # USE WITH CAUTION ! probewww = ( ReadTCP(localhost,80,'GET index.html',1000) ) Or testing a network service: control: checkhost:: probesmtp = ( ReadTCP(localhost,25,"",1024) ) probewww = ( ReadTCP(project.iu.hio.no,80,"GET /viewcvs HTTP/1.0 ${n}${n}",1024) ) classes: viewcvs_error = ( RegCmp(".*Python Traceback.*","${probewww}") ) alerts: viewcvs_error:: "Received viewcvs error from web server" `SelectPartitionNeighbours(FILENAME,COMMENT,POLICY,GROUP SIZE)' This function is for use in peer to peer monitoring applications. It allows individual hosts to identify themselves as part of a group and find their peers. The function returns a list variable, delimited by the list separation character, for use with Split. control: allpeers = ( SelectPartitionNeighbours(/var/cfengine/inputs/cfrun.hosts,#,random,4) ) copy: /data/file dest=/p2prepository/file server=$(allpeers) `SelectPartitionLeader(FILENAME,COMMENT,POLICY,GROUP SIZE)' This function is for use in peer to peer monitoring applications. It allows individual hosts to identify themselves as part of a group and select a leader. This function reads a text file of hostnames or IP addresses, one host per line, with blank lines and comments and partitions it into groups of a fixed size. It then returns picks a leader for the the group and returns its name as the value of the function. control: leader = ( SelectPartitionLeader(/var/cfengine/inputs/cfrun.hosts,#,random,4) ) copy: /data/file dest=/p2prepository/file server=$(leader) Note that functions should have no spaces between the function name and the leading parenthesis, but should themselves be surrounded by white space. For example: control: variable2 = ( RandomInt(0,23) ) variable3 = ( ExecResult(/bin/ls -a /opt) ) myexcerpt = ( ReadFile("/etc/services",220) ) listvar = ( ReadArray(/tmp/array,textkey,",","#",100) ) In the latter case, the file could look like this: host$ more /tmp/array one,String to tbe read two,Nothing string three,Everything comes in threes and results in the definition of (verify with `cfagent -p -d3'): OBJECT: main 960 : listvar[one]=String to tbe read 259 : listvar[two]=Nothing string 224 : listvar[three]=Everything comes in threes * Menu: * Special variables:: * Iteration over lists::  File: cfengine-Reference.info, Node: Special variables, Next: Iteration over lists, Prev: Setting variables with functions, Up: Variable expansion and contexts 4.4.2 Special variables ----------------------- Variables are referred to in either of two different ways, depending on your taste. You can use the forms `$(variable)' or `${variable}'. The variable in braces or parentheses can be the name of any user defined macro, environment variable or one of the following special built-in variables. `AllClasses' A long string in the form `CFALLCLASSES=class1:class2...'. This variable is a summary of all the defined classes at any given time. It is always kept up to date so that scripts can make use of cfengine's class data. `arch' The current detailed architecture string--an amalgamation of the information from _uname_. _A constant_. `binserver' The default server for binary data. _A constant_. `cfinputs_version' The version string of the current configuration, used for version control and auditing. `ChecksumDatabase' If set to the name of a file, cfagent will use this to store checksums of important files, and give `tripwire functionality', *Note ChecksumDatabase in cfagent::. This option was deprecated in 2.1.22. `ChecksumUpdates' If set to `on', security information is automatically updated. `class' The currently defined system hard-class (e.g. `sun4', `hpux'). _A constant_. `date' The current date string. Note that if you use this in a shell command it might be interpreted as a list variable, since it contains the default separator `:'. `domain' The currently defined domain. `EmailFrom' The email address from whom email from cfexecd should appear to originate. `EmailMaxLines' Most lines of output to email from a single cfexecd-induced run of cfagent. If undefined, defaults to 100. If set to 0, no email is sent by cfexecd. If set to `inf', no maximum is enforced. `EmailTo' The E-mail address to whom mail should be sent (overrides `sysadm' variable). `faculty' The faculty or site as defined in control (see `site'). `fqhost' The fully qualified hostname of the system. `host' The hostname of the machine running the program. `ipaddress' The numerical form of the Internet address of the host currently running cfengine found by a reverse lookup in DNS. `ipv4[INTERFACE]' The IPv4 address of the named interface as determined from a probe of the interfaces. This variable belongs in the global context and refers to as in the following examples: ${global.ipv4[hme0]} ${global.ipv4[eth0]} `MaxCfengines' The maximum number of cfengines which should be allowed to run concurrently on the system. This can prevent excessive load due to unintentional spamming in situations where several cfengines are started independently. The default value is unlimited. `ostype' A short for of `$(arch)'. `OutputPrefix' This quoted string can be used to change the default `cfengine:${hostname}' prefix on output lines to something else. You might wish to shorten the string, or have a different prefix for different hosts. The default is equivalent to, OutputPrefix = ( "cfengine:$(host):") `RepChar' The character value of the string used by the file repository in constructing unique filenames from path names. This is the character which replaces `/'. `site' This variable is identical to `$(faculty)' and may be used interchangeably. `smtpserver' The name of the host to which mail output should be sent. `split' The character on which list variables are split. `sysadm' The name or mail address of the system administrator. `timezone' The current timezone as defined in `control'. `UnderscoreClasses' If this is set to `on' cfengine uses hard classes which begin with an underscore to avoid name collisions, *Note Cfagent Runtime Options::. `version' The current cfengine version string as defined in the code. `year' The current year. These variables are kept special because they play a special role in setting up a system configuration. You are encouraged to use them to define fully generalized rules in your programs. Variables can be used to advantage in defining filenames, directory names and in passing arguments to shell commands. The judicious use of variables can reduce many definitions to a single one if you plan carefully. _NOTE: the above control variables are not case sensitive, unlike user macros, so you should not define your own macros with these names._ The following variables are also reserved and may be used to produce troublesome special characters in strings. `cr' Expands to the carriage return character. `colon' Expands to the colon `:' character. `dblquote' Expands to a double quote `"' `dollar' Expands to `$'. `lf' Expands to a line-feed character (Unix end of line). `n' Expands to a newline character. `quote' Expands to a single quote `''. `spc' Expands simply to a single space. This can be used to place spaces in filenames etc. `tab' Expands to a single tab character.  File: cfengine-Reference.info, Node: Iteration over lists, Prev: Special variables, Up: Variable expansion and contexts 4.4.3 Iteration over lists -------------------------- Variables can be used as iterators in some situations. Iteration over lists is currently rather limited in cfengine and is something to be improved on in a future version. When a variable is used as an iterator, a character is chosen to represent a list separator, as in the shell `IFS' variable. The default separator is the colon `:' character: control: listvar = ( one:two:three:four ) The action that contains a variable to be interpreted as a list appears as separate actions, one for each case: shellcommand: "/bin/echo $(listvar)" is equivalent to shellcommand: "/bin/echo one" "/bin/echo two" "/bin/echo three" "/bin/echo four" If multiple iterators are used, these are handled as nested loops: cfengine::/bin/echo one 1: one 1 cfengine::/bin/echo one 2: one 2 cfengine::/bin/echo one 3: one 3 cfengine::/bin/echo one 4: one 4 cfengine::/bin/echo two 1: two 1 cfengine::/bin/echo two 2: two 2 cfengine::/bin/echo two 3: two 3 cfengine::/bin/echo two 4: two 4 cfengine::/bin/echo three: three 1 cfengine::/bin/echo three: three 2 cfengine::/bin/echo three: three 3 cfengine::/bin/echo three: three 4 cfengine::/bin/echo four : four 1 cfengine::/bin/echo four : four 2 cfengine::/bin/echo four : four 3 cfengine::/bin/echo four : four 4 Where iterators are not allowed, the implied lists are treated as scalars: alerts: amnexus:: "do $(list1) $(list2)" e.g. cfengine:: do one:two:three:four 1:2:3:4 Iterative expansion is currently restricted to: * In the directory field of the admit/deny server access rules, * In the `from' field of a copy action, * In the server field of the copy action, * In the directory field of the disable action, * In the directory field of the files action, * In the `to' field of a multiple link action, * In the directory field of the required/disk action, * In a resolve item. * In the directory field of a tidy action, * In the arguments, replyto and server attributes of methods. * Names in the ignore action. * A shellcommands body. * In admit/deny path and attributes of cfserver.  File: cfengine-Reference.info, Node: Cfengine classes, Next: acl, Prev: Variable expansion and contexts, Up: Cfagent reference 4.5 Cfengine classes ==================== A _cfengine action_ looks like this: ACTION-TYPE: COMPOUND-CLASS:: DECLARATION A single class is an identifier that may consist of any alphanumeric character or the underscore, just like identifiers in ordinary programming languages. Classes that are derived from data like IP addresses or host names convert any other characters (like `.' or `-') into underscores. A single class can be one of several things: * The name of an operating system architecture e.g. `ultrix', `sun4', etc. This is referred to as a _hard class_. * The unqualified name of a particular host. If your system returns a fully qualified domain name for your host, cfagent truncates it at the first dot. * The name of a user-defined group of hosts. * A day of the week (in the form `Monday, Tuesday, Wednesday, ..'). * An hour of the day (in the form `Hr00, Hr01 ... Hr23'). * Minutes in the hour (in the form `Min00, Min17 ... Min45'). * A five minute interval in the hour (in the form `Min00_05, Min05_10 ... Min55_00') * A quart hour (in the form `Q1, Q2, Q3, Q4') * An abbreviated time with quarter hour specified (in the form `Hr00_Q1, Hr23_Q4' etc.) * A day of the month (in the form `Day1 ... Day31'). * A month (in the form `January, February, ... December'). * A year (in the form `Yr1997, Yr2004'). * An arbitrary user-defined string. * The IP address octets of any active interface (in the form `ipv4_192_0_0_1', `ipv4_192_0_0', `ipv4_192_0', `ipv4_192'). A compound class is a sequence of simple classes connected by dots or `pipe' symbols (vertical bars). For example: myclass.sun4.Monday:: sun4|ultrix|osf:: A compound class evaluates to `true' if all of the individual classes are separately true, thus in the above example the actions which follow `compound_class::' are only carried out if the host concerned is in `myclass', is of type `sun4' and the day is Monday! In the second example, the host parsing the file must be either of type `sun4' _or_ `ultrix' _or_ `osf'. In other words, compound classes support two operators: AND and OR, written `.' and `|' respectively. From cfengine version 2.1.1, I bit the bullet and added `&' as a synonym for the AND operator. Cfengine doesn't care how many of these operators you use (since it skips over blank class names), so you could write either solaris|irix:: or solaris||irix:: depending on your taste. On the other hand, the order in which cfengine evaluates AND and OR operations _does_ matter, and the rule is that AND takes priority over OR, so that `.' binds classes together tightly and all AND operations are evaluated before ORing the final results together. This is the usual behaviour in programming languages. You can use round parentheses in cfengine classes to override these preferences. Cfengine allows you to define switch on and off dummy classes so that you can use them to select certain subsets of action. In particular, note that by defining your own classes, using them to make compound rules of this type, and then switching them on and off, you can also switch on and off the corresponding actions in a controlled way. The command line options `-D' and `-N' can be used for this purpose. See also `addclasses' in the Reference manual. A logical NOT operator has been added to allow you to exclude certain specific hosts in a more flexible way. The logical NOT operator is (as in C and C++) `!'. For instance, the following example would allow all hosts except for `myhost': ACTION: !myhost:: COMMAND and similarly, so allow all hosts in a user-defined group `mygroup', _except_ for `myhost', you would write ACTION: mygroup.!myhost:: COMMAND which reads `mygroup AND NOT myhost'. The NOT operator can also be combined with OR. For instance CLASS1|!CLASS2 would select hosts which were either in class 1, or those which were not in class 2. Finally, there is a number of reserved classes. The following are hard classes for various operating system architectures. They do not need to be defined because each host knows what operating system it is running. Thus the appropriate one of these will always be defined on each host. Similarly the day of the week is clearly not open to definition, unless you are running cfengine from outer space. The reserved classes are: ultrix, sun4, sun3, hpux, hpux10, aix, solaris, osf, irix4, irix, irix64 sco, freebsd, netbsd, openbsd, bsd4_3, newsos, solarisx86, aos, nextstep, bsdos, linux, debian, cray, unix_sv, GnU, NT If these classes are not sufficient to distinguish the hosts on your network, cfengine provides more specific classes which contain the name and release of the operating system. To find out what these look like for your systems you can run cfengine in `parse-only-verbose' mode: cfagent -p -v and these will be displayed. For example, Solaris 2.4 systems generate the additional classes `sunos_5_4' and `sunos_sun4m', `sunos_sun4m_5_4'. Cfengine uses both the unqualified and fully host names as classes. Some sites and operating systems use fully qualified names for their hosts. i.e. `uname -n' returns to full domain qualified hostname. This spoils the class matching algorithms for cfengine, so cfengine automatically truncates names which contain a dot `.' at the first `.' it encounters. If your hostnames contain dots (which do not refer to a domain name, then cfengine will be confused. The moral is: don't have dots in your host names! _NOTE: in order to ensure that the fully qualified name of the host becomes a class you must define the domain variable._ The dots in this string will be replaced by underscores. In summary, the operator ordering in cfengine classes is as follows: `()' Parentheses override everything. `!' The NOT operator binds tightest. `. &' The AND operator binds more tightly than OR. `|' OR is the weakest operator. * Menu: * Setting classes with special functions:: * AccessedBefore:: * ChangedBefore:: * ClassMatch:: * FileExists:: * GroupExists:: * HostRange:: * IsDefined:: * IsDir:: * IsLink:: * IsPlain:: * IsNewerThan:: * IPRange:: * PrepModule:: * Regcmp:: * ReturnsZero:: * ReturnsZeroShell:: * Strcmp:: * UserExists:: * IsGreaterThan:: * IsLessThan:: * Examples setting classes::  File: cfengine-Reference.info, Node: Setting classes with special functions, Next: AccessedBefore, Prev: Cfengine classes, Up: Cfengine classes 4.5.1 Setting classes with special functions -------------------------------------------- Cfengine provides a number of built-in functions for evaluating classes, based on file tests. Using these built-in functions is quicker than calling the shell `test' function. The time functions place their arguments in chronological order.  File: cfengine-Reference.info, Node: AccessedBefore, Next: ChangedBefore, Prev: Setting classes with special functions, Up: Cfengine classes 4.5.2 AccessedBefore -------------------- AccessedBefore(F1,F2) True if file 1 was accessed more recently than file 2 (UNIX atime)  File: cfengine-Reference.info, Node: ChangedBefore, Next: ClassMatch, Prev: AccessedBefore, Up: Cfengine classes 4.5.3 ChangedBefore ------------------- ChangedBefore(F1,F2) True if file 1's attributes were changed in any way more recently than file 2's (UNIX ctime)  File: cfengine-Reference.info, Node: ClassMatch, Next: FileExists, Prev: ChangedBefore, Up: Cfengine classes 4.5.4 ClassMatch ---------------- ClassMatch(REGEXP) True if the quoted regular expression matches one of the currently defined classes. It is wise to place ClassMatch at the end of your parsing in order to capture as many of the user-defined classes as possible. classes: userdef = ( ClassMatch(.*linux.*) )  File: cfengine-Reference.info, Node: FileExists, Next: GroupExists, Prev: ClassMatch, Up: Cfengine classes 4.5.5 FileExists ---------------- FileExists(FILE) True if the named file object (file/directory or link) exists.  File: cfengine-Reference.info, Node: GroupExists, Next: HostRange, Prev: FileExists, Up: Cfengine classes 4.5.6 GroupExists ----------------- GroupExists(GROUPNAME|GID) True if the groupname or group id is registered on the system.  File: cfengine-Reference.info, Node: HostRange, Next: IsDefined, Prev: GroupExists, Up: Cfengine classes 4.5.7 HostRange --------------- HostRange(BASENAME,START-STOP) True if the current relative domain name begins with basename and ends with an integer between start and stop. Note well: matching is case insensitive (both hostname and basename are converted to all lower case for comparison.)  File: cfengine-Reference.info, Node: IsDefined, Next: IsDir, Prev: HostRange, Up: Cfengine classes 4.5.8 IsDefined --------------- IsDefined(VARIABLE-ID) True if the named variable is defined. Note well: use the variable name, not its contents (that is, `IsDefined(var)', and not `IsDefined(${var})')  File: cfengine-Reference.info, Node: IsDir, Next: IsLink, Prev: IsDefined, Up: Cfengine classes 4.5.9 IsDir ----------- IsDir(F) True if the file f is a directory  File: cfengine-Reference.info, Node: IsLink, Next: IsPlain, Prev: IsDir, Up: Cfengine classes 4.5.10 IsLink ------------- IsLink(F) True if the file f is a symbolic link  File: cfengine-Reference.info, Node: IsPlain, Next: IsNewerThan, Prev: IsLink, Up: Cfengine classes 4.5.11 IsPlain -------------- IsPlain(F) True if the file f is a plain file  File: cfengine-Reference.info, Node: IsNewerThan, Next: IPRange, Prev: IsPlain, Up: Cfengine classes 4.5.12 IsNewerThan ------------------ IsNewerThan(F1,F2) True if file 2 was modified more recently than file 1 (UNIX mtime)  File: cfengine-Reference.info, Node: IPRange, Next: PrepModule, Prev: IsNewerThan, Up: Cfengine classes 4.5.13 IPRange -------------- IPRange(ADDRESS-RANGE) True if the current host lies within the specified IP range  File: cfengine-Reference.info, Node: PrepModule, Next: Regcmp, Prev: IPRange, Up: Cfengine classes 4.5.14 PrepModule ----------------- PrepModule(MODULE,ARG1 ARG2...) True if the named module exists and can be executed. The module is assumed to follow the standard programming interface for modules (see Writing plugin modules in tutorial). Unlike actionsequence modules, these modules are evaluated immediately on parsing. Note that the module should be specified relative to the authorized module directory.  File: cfengine-Reference.info, Node: Regcmp, Next: ReturnsZero, Prev: PrepModule, Up: Cfengine classes 4.5.15 Regcmp ------------- Regcmp(REGEXP,STRING OR LIST SEPARATED STRING) True if the string matched the regular expression regexp.  File: cfengine-Reference.info, Node: ReturnsZero, Next: ReturnsZeroShell, Prev: Regcmp, Up: Cfengine classes 4.5.16 ReturnsZero ------------------ ReturnsZero(COMMAND) True if the named shell command returns with exit code zero (success). The command is executed without a shell wrapper.  File: cfengine-Reference.info, Node: ReturnsZeroShell, Next: Strcmp, Prev: ReturnsZero, Up: Cfengine classes 4.5.17 ReturnsZeroShell ----------------------- ReturnsZeroShell(COMMAND) True if the named shell command returns with exit code zero (success) when executed in the environment of a shell wrapper.  File: cfengine-Reference.info, Node: Strcmp, Next: UserExists, Prev: ReturnsZeroShell, Up: Cfengine classes 4.5.18 Strcmp ------------- Strcmp(S1,S2) True if the string s1 exactly matches s2  File: cfengine-Reference.info, Node: UserExists, Next: IsGreaterThan, Prev: Strcmp, Up: Cfengine classes 4.5.19 UserExists ----------------- UserExists(USERNAME|UID) True if the username or user id is registered on the system (this does not imply that the user can log in or has a home directory).  File: cfengine-Reference.info, Node: IsGreaterThan, Next: IsLessThan, Prev: UserExists, Up: Cfengine classes 4.5.20 IsGreaterThan -------------------- IsGreaterThan(S1,S2) Returns true if the value of s1 is greater than the value of s2. Note that, if the strings have numerical values, a numerical comparison is performed, otherwise a string comparison is used.  File: cfengine-Reference.info, Node: IsLessThan, Next: Examples setting classes, Prev: IsGreaterThan, Up: Cfengine classes 4.5.21 IsLessThan ----------------- IsLessThan(S1,S2) Returns true if the value of s1 is less than the value of s2. Note that, if the strings have numerical values, a numerical comparison is performed, otherwise a string comparison is used. control: actionsequence = ( files ) a = ( 2.12 ) b = ( 2.11 ) classes: lt = ( IsLessThan(${a},${b}) ) gt = ( IsGreaterThan(${a},${b}) ) alerts: lt:: "$(a) LESS THAN $(b)" gt:: "$(a) GREATER THAN $(b)"  File: cfengine-Reference.info, Node: Examples setting classes, Prev: IsLessThan, Up: Cfengine classes 4.5.22 Examples setting classes ------------------------------- For example: classes: access_to_dir = ( ReturnsZero(/bin/cd /mydir) ) compare = ( ChangedBefore(/etc/passwd_master,/etc/passwd) ) isplain = ( IsPlain(/tmp/import) ) inrange = ( IPRange(128.39.89.10-15) ) CIDR = ( IPRange(128.39.89.10/24) ) compute_nodes = ( HostRange(cpu-,01-32) gotinit = ( PrepModule(startup2,"arg1 arg2") )  File: cfengine-Reference.info, Node: acl, Next: alerts, Prev: Cfengine classes, Up: Cfagent reference 4.6 acl ======= acl: CLASS:: { ACL-ALIAS ACTION } Cfengine's `ACL' feature is a common interface for managing filesystem access control lists (ACLs). An access control list is an extended file permission. It allows you to open or close a file to a named list of users (without having to create a group for those users); similarly, it allows you to open or close a file for a list of groups. Several operating systems have access control lists, but each typically has a different syntax and different user interface to this facility, making it very awkward to use. This part of a cfengine configuration simplifies the management of ACLs by providing a more convenient user interface for controlling them and--as far as possible--a common syntax. An ACL may, by its very nature, contain a lot of information. Normally you would set ACLs in a `files' command, *Note files::, or a `copy' command, *Note copy::. It would be too cumbersome to repeat all of the information in every command in your configuration, so cfengine simplifies this by first associating an alias together with a complex list of ACL information. This alias is then used to represent the whole bundle of ACL entries in a `files' or `copy' command. The form of an ACL is similar to the form of an `editfiles' command. It is a bundle of information concerning a file's permissions. { ACL-ALIAS method:overwrite/APPEND fstype:POSIX/SOLARIS/DFS/AFS/HPUX/NT ACL_TYPE:USER/GROUP:PERMISSIONS ACL_TYPE:USER/GROUP:PERMISSIONS ... } The name ACL-ALIAS can be any identifier containing alphanumeric characters and underscores. This is what you will use to refer to the ACL entries in practice. The method entry tells cfengine how to interpret the entries: should a file's ACLs be overwritten or only adjusted? Since the filesystems from different developers all use different models for ACLs, you must also tell cfengine what kind of filesystem the file resides on. Currently only Solaris and DCE/DFS ACLs are implemented. NOTE: if you set both file permissions and ACLs the file permissions override the ACLs. * Menu: * ACEs:: * Solaris ACLs:: * DFS ACLs:: * NT ACLs:: * Windows ACL Example:: * Posix ACL Example::  File: cfengine-Reference.info, Node: ACEs, Next: Solaris ACLs, Prev: acl, Up: acl 4.6.1 Access control entries ---------------------------- An access control list is build of any number of individual access control entries (ACEs). The ACEs has the following general syntax: ACL_TYPE:USER/GROUP:PERMISSIONS The user or group is sometimes referred to as a _key_. For an explanation of ACL types and their use, refer to your local manual page. However, note that for each type of filesystem, there are certain entries which must exist in an ACL. If you are creating a new ACL from scratch, you must specify these. For example, in Solaris ACLs you must have entries for `user', `group' and `other'. Under DFS you need what DFS calls a `user_obj', `group_obj' and an `other_obj', and in some cases `mask_obj'. In cfengine syntax these are called `user:*:', `other:*:' and `mask:*:', as described below. If you are appending to an existing entry, you do not have to re-specify these unless you want to change them. Cfengine can overwrite (replace) or append to one or more ACL entries. `overwrite' `method:overwrite' is the default. This sets the ACL according to the specified entries which follow. The existing ACL will be overwritten completely. `append' `method:append' adds or modifies one or more specified ACL entries. If an entry already exists for the specified type and user/group, the specified permission bits will be added to the old permissions. If there is no ACL entry for the given type and user/group, a new entry will be appended. If the new ACL exactly matches the existing ACL, the ACL is not replaced. The individual bits in an ACE may be either added subtracted or set equal to a specified mask. The `+' symbol means add, the `-' symbol subtract and `=' means set equal to. Here are some examples: ACLTYPE:ID/*:MASK user:mark:+rx,-w user:ds:=r user:jacobs:noaccess user:forgiven:default user:*:rw group:*:r other:*:r The keyword `noaccess' means set all access bits to zero for that user, i.e. remove all permissions. The keyword `default' means remove the named user from the access crontrol list altogether, so that the default permissions apply. A star/asterisk in the centre field indicates that the user or group ID is implicitly specified as of the owner of the file, or that no ID is applicable at all (as is the case for `other').  File: cfengine-Reference.info, Node: Solaris ACLs, Next: DFS ACLs, Prev: ACEs, Up: acl 4.6.2 Solaris ACLs ------------------ Under Solaris, the ACL type can be one of the following: user group mask other default_user default_group default_mask default_other A user or group can be specified to the user, group, default_user and default_group types. Solaris ACL permissions are the normal UNIX permissions bits `rwx', where: R - GRANTS READ PRIVILEGES. W - GRANTS WRITE PRIVILEGES. X - GRANTS EXECUTE PRIVILEGES.  File: cfengine-Reference.info, Node: DFS ACLs, Next: NT ACLs, Prev: Solaris ACLs, Up: acl 4.6.3 DFS ACLs -------------- In DCE, the ACL type can be one of the following: other mask any unauthenticated user group foreign_other foreign_user foreign_group The `user', `group', `foreign_user' and `foreign_group' types require that you specify a user or group. The DCE documentation refers to types `user_obj', `group_obj' and so on. In the cfengine implementation, the ugly `_obj' suffix has been dropped to make these more in keeping with the POSIX names. `user_obj::', is equivalent to `user:*:' is cfengine. The star/asterisk implies that the ACL applies to the owner of the file object. DFS permissions are comprised of the bits `crwxid', where: c - Grants control privileges, to modify an acl. r - Grants read privileges. w - Grants write privileges. x - Grants execute privileges. i - Grants insert privileges. d - Grants delete privileges. See the DCE/DFS documentation for more information about this. It is not possible to set ACLs in foreign cells currently using cfengine, but you can still have all of your ACL definitions in the same file. You must however arrange for the file to be executed on the server for the cell concerned. Note also that you must perform a DCE login (normally as user `cell_admin') in order to set ACLs on files which are not owned by the owner of the cfengine-process. This is because you must have a valid security ticket.  File: cfengine-Reference.info, Node: NT ACLs, Next: Windows ACL Example, Prev: DFS ACLs, Up: acl 4.6.4 NT ACLs ------------- NT ACEs are written as follows: acl_type:user/group:permissions:accesstype The actual change consists of the extra field containing the access type. A star/asterisk in the field for USER/GROUP would normally imply that the ACL applies to the owner of the file object. However this functionality is as of today not yet implemented. In NT, the ACL type can be one of the following: user group Both types require that you specify the name of a user or a group. NT permissions are comprised of the bits `rwxdpo', where: r - Read privileges w - Write privileges x - Execute privileges d - Delete privileges p - Privileges to change the permissions on the file o - Privileges to take ownership of the file In addition to any combination of these bits, the word `noaccess' or `default' can be used as explained in the previous section. NT comes with some standard, predefined permissions. The standards are only a predefined combination of the different bits specified above and are provided with cfengine as well. You can use the standards by setting the permission to `read', `change' or `all'. The bit implementation of each standard is as on NT: read - rx change - rwxd all - rwxdpo where the bits follow the earlier definition. The keywords mentioned above can only be used alone, and not in combination with `+', `-', `=' and/or other permission bits. NT defines several different access types, of which only two are used in connection with the ACL type that is implemented in cfengine for NT. The access type can be one of the following: allowed denied Intuitively, `allowed' access grants the specified permissions to the user, whilst `denied' denies the user the specified permissions. If no access type is specified, the default is `allowed'. This enables cfengine's behaviour as on UNIX systems without any changes to the configuration file. If the permissions `noaccess' or `default' is used, the access type will be irrelevant.  File: cfengine-Reference.info, Node: Windows ACL Example, Next: Posix ACL Example, Prev: NT ACLs, Up: acl 4.6.5 Windows ACL Example ------------------------- Here is an example of a configuration file for an NT ACL: control: actionsequence = ( files ) domain = ( iu.hioslo.no ) files: $(HOME)/tt acl=acl_alias1 action=fixall acl: { acl_alias1 method:overwrite fstype:nt user:gustafb:rwx:allowed user:mark:all:allowed user:toreo:read:allowed user:torej:default:allowed user:ds2:+rwx:allowed group:dummy:all:denied group:iu:read:allowed group:root:all:allowed group:guest:dpo:denied }  File: cfengine-Reference.info, Node: Posix ACL Example, Prev: Windows ACL Example, Up: acl 4.6.6 Posix ACL Example ----------------------- Here is an example of a configuration file for one Solaris ACL and one DCE/DFS ACL: control: actionsequence = ( files ) domain = ( iu.hioslo.no ) files: $(HOME)/tt acl=acl_alias1 action=fixall /:/bigfile acl=acl_alias2 action=fixall acl: { acl_alias1 method:overwrite fstype:posix user:*:rwx user:mark:=rwx user:sowille:=rx user:toreo:=rx user:torej:default user:ds2:+rwx group:*:rx group:iu:r group:root:x mask:*:rx other:*:rx default_user:*:=rw default_user:mark:+rwx default_user:ds:=rwx default_group::=r default_group:iu:+r default_mask::w default_other::rwx } { acl_alias2 method:overwrite fstype:dfs user:*:rwxcid group:*:rxd other:*:wxir mask:*:rxw user:/.../iu.hioslo.no/cell_admin:rc group:/.../iu.hioslo.no/acct-admin:rwxcid user:/.../iu.hioslo.no/root:rx }  File: cfengine-Reference.info, Node: alerts, Next: binservers, Prev: acl, Up: Cfagent reference 4.7 alerts ========== Alerts are normally just messages that are printed when classes become activated in order to alert the system administrator to some condition that has arisen. Alerts can also be special functions, like `ShowState()' that generate system output. Alerts cannot belong to the class `any', that would generate a message from every host. In a huge network this could result in vast amounts of Email. This behaviour can be forced, however, by creating an alias for the class `any' that is defined on the affected hosts. alerts: class:: QUOTED MESSAGE ifelapsed=TIME audit=TRUE/FALSE ShowState(PARAMETER) SysLog(PRIORITY,MESSAGE) SetState(NAME,TTL,POLICY) UnSetState(NAME) FriendStatus(HOURS) PrintFile(`filename',LINES) For example: alerts: myclass:: "Reminder: say hello every hour" ifelapsed=60 nfsd_in_high_dev2:: "High NFS server access rate 2dev at $(host) value $(value_nfsd_in) av $(average_nfsd_in) pm $(stddev_nfsd_in)" ShowState(incoming.nfs) # ROOT PROCS anomaly_hosts.RootProcs_high_dev2:: "RootProc anomaly high 2 dev on $(host) value $(value_rootprocs) av $(average_rootprocs) pm $(stddev_rootprocs)" ShowState(rootprocs) The `ShowState()' function reports on state gathered by the cfenvd daemon. ShowState(incoming.tcpsyn) ShowState(outgoing.smtp) ShowState(incoming.www) ShowState(outgoing.www) ShowState(procs) ShowState(rootprocs) ShowState(otherprocs) ShowState(users) To limit the frequency of alerts, you can set locking times: # ROOT PROCS anomaly_hosts.RootProcs_high_dev2:: "RootProc anomaly high 2 dev on $(host) value $(value_rootprocs) av $(average_rootprocs) pm $(stddev_rootprocs)" ShowState(rootprocs) ifelapsed=10 expireafter=20 Alerts can also be channeled directly to syslog, to avoid extraneous console messages or email. SysLog(LOG_ERR,"Test syslog message") One application for alerts is to pass signals from one cfengine to another by persistent, shared memory. For example, suppose a short-lived anomaly event triggers a class that relates to a security alert. The event class might be too short-lived to be followed up by cfagent in full. One could thus set a long term class that would trigger up several follow-up checks. A persistent class could also be used to exclude an operation for an interval of time. Persistent class memory can be added through a system alert functions to give timer behaviour. For example, consider setting a class that acts like a non-resettable timer. It is defined for exactly 10 minutes before expiring. SetState("preserved_class",10,Preserve) Or to set a class that acts as a resettable timer. It is defined for 60 minutes unless the SetState call is called again to extend its lifetime. SetState(non_preserved_class,60,Reset) Existing persistent classes can be deleted with: UnsetState(myclass) The `FriendStatus' function is available from version 2.1.4 and displays a message if hosts that normally have a cfengine protocol connection with the current host have not connected for more than than specified number of hours. If the number of hours is set to zero, cfengine uses a machine-learned expectation value for the time and uses this to report. The friend status of a host is thus the expectation that there is a problem with a remote peer. Expected contact rates of more than the variable `LastSeenExpireAfter' are ignored as spurious, *Note lastseenexpireafter::. The `PrintFile' function can be used to display short excerpts from text files. The arguments are the filename and a maximum number of lines to be printed.  File: cfengine-Reference.info, Node: binservers, Next: broadcast, Prev: alerts, Up: Cfagent reference 4.8 binservers ============== The `binservers' declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of which other hosts on the network possess filesystems containing software (binary files) which client hosts should mount. This includes resources like programs in `/usr/local' and so on. A host may have several binary servers, since there may be several machines to which disks are physically attached. In most cases, on a well organized network, there will be only one _architecture server_ per UNIX platform type, for instance a SunOS server, an ULTRIX server and so on. Binary servers are defined as follows: binservers: physics.sun4:: sunserver sunserver2 physics.linux:: linuxserver The meaning of this declaration is the following. All hosts of type `sun4' which are members of the group `physics' should mount any binaries declared in the `mountables' resource list which belong to hosts `sunserver' or `sunserver2'. Similarly all `linux' machines should mount binary filesystems in the mountables list from `linuxserver'. Cfengine knows the difference between binaries and home directories in the `mountables' list, because home directories match the pattern given by `homepattern'. *Note homepattern::. *Note homeservers::. Note that every host is a binary server for itself, so that the first binary server (and that with highest priority) is always the current host. This ensures that local filesystems are always used in preference to NFS mounted filesystems. This is only relevant in connection with the variable `$(binserver)'.  File: cfengine-Reference.info, Node: broadcast, Next: control, Prev: binservers, Up: Cfagent reference 4.9 broadcast ============= This information is used to configure the network interface for each host. Every local area network has a convention for determining which internet address is used for broadcast requests. Normally this is an address of the form `aaa.bbb.ccc.255' or `aaa.bbb.ccc.0'. The difference between these two forms is whether all of the bits in the last number are ones or zeroes respectively. You must find out which convention is used at your establishment and tell cfengine using a declaration of the form: broadcast: any:: ones # or zeros, or zeroes In most cases you can use the generic class `any', since all of the hosts on the same subnet have to use the same convention. If your configuration file encompasses several different subnets with different conventions then you will need to use a more specific. Cfengine computes the actual value of the broadcast address using the value specified above and the netmask *Note netmask::.  File: cfengine-Reference.info, Node: control, Next: classes, Prev: broadcast, Up: Cfagent reference 4.10 control ============ The fundamental piece of any cfengine script or configuration file is the control section. If you omit this part of a cfengine script, it will not do anything! The control section is used to define certain variables, set default values and define the order in which the various actions you have defined will be carried out. Because cfengine is a declarative or descriptive language, the order in which actions appear in the file does not necessarily reflect the order in which they are executed. The syntax of declarations here is: control: CLASSES:: VARIABLE = ( LIST OR VALUE FUNCTION(ARGS) ) The control section is a sequence of declarations which looks something like the following example: control: site = ( univ ) domain = ( univ.edu ) sysadm = ( admin@computing.univ.edu ) netmask = ( 255.255.252.0 ) timezone = ( EDT ) nfstype = ( nfs ) childlibpath = ( /usr/local:/mylibs ) sensiblesize = ( 1000 ) sensiblecount = ( 2 ) editfilesize = ( 4000 ) actionsequence = ( links.some mountall links.others files ) myvariable = ( something ) mymacro = ( somethingelse ) myrandom = ( RandomInt(3,6) ) myexcerpt = ( ReadFile("/etc/services",220)) Parentheses are required when making a declaring information in cfengine. Note that a limited number of built-in functions exists: * `ExecResult'(COMMAND) Executes the named shell command and inserts the output into the variable. Note that, when this is used in cfengine built-in list variables, any spaces are interpreted as list separators. In other lists, normal rules for iteration apply. * `RandomInt(a,b)' Is substituted for a random number between (a,b). * `ReadFile'(FILENAME,MAX NUMBER OF BYTES) A maximum number of bytes is read from the named file and placed in a variable. For more functions, *Note Setting variables with functions::. The meaning of each of these lines is described below. * Menu: * AbortClasses:: * access:: * actionsequence:: * addclasses:: * addinstallable:: * AllowRedefinitionOf:: * Auditing:: * AutoDefine:: * BinaryPaddingChar:: * BindToInterface in cfagent:: * ChecksumDatabase in cfagent:: * ChecksumPurge:: * ChecksumUpdates:: * CompressCommand:: * childlibpath:: * copylinks:: * defaultcopytype:: * defaultpkgmgr:: * deletenonuserfiles:: * deletenonownerfiles:: * deletenonusermail:: * deletenonownermail:: * domain:: * dpkginstallcommand:: * dryrun:: * editbinaryfilesize:: * editfilesize:: * emptyresolvconf:: * exclamation:: * excludecopy:: * excludelinks:: * ExpireAfter:: * FreeBSDInstallCommand:: * FreeBSDRemoveCommand:: * FullEncryption:: * homepattern:: * HostnameKeys in cfagent:: * IfElapsed in cfagent:: * IgnoreFriendRegex:: * IgnoreInterfaceRegex:: * Inform:: * interfacename:: * fileextension:: * lastseen:: * lastseenexpireafter:: * linkcopies:: * LogDirectory:: * LogTidyHomeFiles:: * moduledirectory:: * mountpattern:: * netmask:: * nonalphanumfiles:: * nfstype:: * PortageInstallCommand:: * repchar:: * repository:: * RPMcommand:: * rpminstallcommand:: * schedule:: * secureinput:: * sensiblecount:: * sensiblesize:: * showactions:: * singlecopy:: * site:: * SkipIdentify:: * Smtpserver:: * SplayTime:: * split:: * spooldirectories:: * suninstallcommand:: * suspiciousnames:: * sysadm:: * Syslog:: * SyslogFacility:: * timezone:: * TimeOut:: * Verbose:: * Warnings:: * warnnonuserfiles:: * warnnonownerfiles:: * warnnonusermail:: * warnnonownermail::  File: cfengine-Reference.info, Node: AbortClasses, Next: access, Prev: control, Up: control 4.10.1 AbortClasses ------------------- The `AbortClasses' list is a list of class identifiers that will result in the abortion of the current cfagent instanitation with an error message containing the name of the offending class. AbortClasses = ( emergency nologin_exists ) This mechanism allows one to make controlled exceptions at the agent level. For example control: actionsequence = ( shellcommands ) AbortClasses = ( danger_will_robinson ) shellcommands: "shellcom 1" "shellcom 2" define=ok elsedefine=danger_will_robinson  File: cfengine-Reference.info, Node: access, Next: actionsequence, Prev: AbortClasses, Up: control 4.10.2 access ------------- The `access' list is a list of users who are to be allowed to execute a cfengine program. If the list does not exist then all users are allowed to run a program. access = ( USER1 USER2 ... ) The list may consist of either numerical user identifiers or valid usernames from the password database. For example: access = ( mark aurora 22 456 ) would restrict a script to users mark, aurora and user id 22 and 456.  File: cfengine-Reference.info, Node: actionsequence, Next: addclasses, Prev: access, Up: control 4.10.3 actionsequence --------------------- The action sequence determines the order in which collective actions are carried out. Here is an example containing the full list of possibilities: actionsequence = ( mountall # mount filesystems in fstab mountinfo # scan mounted filesystems checktimezone # check timezone netconfig # check net interface config resolve # check resolver setup unmount # unmount any filesystems packages # install/upgrade/remove packages shellcommands # execute shell commands editfiles # edit files addmounts # add new filesystems to system directories # make any directories links # check and maintain links (single and child) mailcheck # check mailserver mountall # (again) required # check required filesystems tidy # tidy files disable # disable files files # check file permissions copy # make a copy/image of a master file processes # signal / check processes module:name # execute a user-defined module ) Here is a more complete description of the meaning of these keywords. `addmounts' causes cfengine to compute which NFS filesystems are missing from the current host and add them. This includes editing the filesystem table, creating the mount-directory, if required. This command relies on information provided by `mountinfo', so it should normally only be called after `mountinfo'. If the filesystem already appears to be in the filesystem table, a warning is issued. `checktimezone' runs a check on the timezone defined for the shell running cfengine. `directories' executes all the commands defined under the `directories' section of the program. It builds new directories. `disable' executes all the commands defined under the `disable' section of the program. `editfiles' executes all the commands defined under the `editfiles' section of the program. `files' executes all the commands defined under the `files' section of the program. `links' executes all the commands defined under the `links' section of the program. `mailcheck' tests for the presence of the NFS-mounted mail spooling directory on the current host. The name of the mail spool directory is defined in the `mailserver' section of the cfengine program. If the current host is the same as the mailserver (the host which has the physical spool directory disk) nothing is done. Otherwise the filesystem table is edited so as to include the mail directory. `module' Normally cfengine's ability to detect the system's condition is limited to what it is able to determine while excuting predefined actions. Classes may be switched on as a result of actions cfengine takes to correct a problem. To increase the flexibility of cfengine, a mechanism has been introduced in version 1.5 which allows you to include a module of your own making in order to define or undefine a number of classes. The syntax module:mytests "module:mytests arg1 arg2 .." declares a user defined module which can potentially set the classes CLASS1 etc. Classes returned by the module must be declared so that cfengine knows to pay attention to rules which use these classes when parsing; this is done using `AddInstallable'. If arguments are passed to the module, the whole string must be quoted like a shellcommand. *Note Writing plugin modules: (cfengine-Tutorial)Writing plugin modules. Whether or not these classes become set or not depends on the behaviour of your module. The classes continue to apply for all actions which occur after the module's execution. The module must be owned by the user executing cfengine or root (for security reasons), it must be named `module:MODULE-NAME' and must lie in a special directory, *Note moduledirectory::. `mountall' mounts all filesystems defined in the hosts filesystem table. This causes new NFS filesystems added by `addmounts' and `mailcheck' to be actually mounted. This should probably be called both before `mountinfo' and after `addmounts' etc. A short timeout is placed on this operation to avoid hanging RPC connections when parsing NFS mounted file systems. `mountinfo' builds internal information about which filesystems are presently mounted on the current host. Cfengine assumes that required-filesystems which are not found need to be mounted. A short timeout is placed on this operation to avoid hanging RPC connections when parsing NFS mounted file systems. If this times out, no further mount operations are considered reliable and are summarily cancelled. `netconfig' checks the netmask, hostname, IP address and broadcast address for the current host. The correct values for the netmask and broadcast address are set if there is an error. The defaultroute is matched against the static routing table and added if no default route exists. This does not apply to DHCP clients, which set a default route automatically. `required' executes all the commands defined under the `required' section of the program. It checks for the absence of important NFS resources. `resolve' checks and corrects the DNS domain name and the order of nameservers in the file `/etc/resolv.conf'. `packages' executes commands defined under the `packages' section of the program. This will query the system's package database for the specified packages, at the specified versions, set classes based on whether or not those packages exist, and optionally install, upgrade or remove those packages using a pre-defined package manager command. `shellcommands' executes all the commands defined under the `shellcommands' section of the program. `tidy' executes all the commands defined under the `tidy' section of the program. `unmount' executes all the commands defined under the `unmount' section of the program. The filesystem table is edited so as to remove the unwanted filesystems and the unmount operation is executed. `processes' executes commands defined under the `processes' section of the program. Under normal circumstances this coarse ordering is enough to suit most purposes. In some cases you might want to, say, only perform half the link operations before mounting filesystems and then, say, perform the remainder. You can do this (and similar things) by using the idea of defining and undefining classes. *Note Defining classes: (cfengine-Tutorial)Defining classes. The syntax actionsequence = ( links.firstpass.include ... links.secondpass ) means that cfengine first executes `links' with the classes `firstpass' and `include' _defined_. Later it executes `links' with `secondpass' defined. You can use this method of adding classes to distinguish more finely the flow of control in programs. A note about style: if you define and undefine lots of classes to do what you want to do, you might stop and ask yourself if your `groups' are defined as well as they should be. *Note groups::. Programming in cfengine is about doing a lot for only a little writing. If you find yourself writing a lot, you are probably not going about things in the right way.  File: cfengine-Reference.info, Node: addclasses, Next: addinstallable, Prev: actionsequence, Up: control 4.10.4 AddClasses ----------------- AddClasses = ( LIST OF IDENTIFIERS ) The `AddClasses' directive is used to define a list of class attributes for the current host. Normally only the hard classes defined by the system are `true' for a given host. It is convenient though to be able to define classes of your own to label certain actions, mainly so that they can later be excluded so as to cut short or filter out certain actions. This can be done in two ways. *Note actionsequence::. To define a list of classes for the current session, you write: AddClasses = ( exclude shortversion ) This is equivalent to (though more permanent than) defining classes on the command line with the `-D' option. You can now use these to qualify actions. For example any.exclude:: ... Under normal circumstances `exclude' is always true -- because you have defined it to be so, but you can _undefine_ it in two ways so as to prevent the action from being carried out. One way is to undefine a class on the command line when you invoke cfengine: host# cfengine -N exclude or host# cfengine -N exclude.shortversion host# cfengine -N a.b.c.d These commands run cfengine with the named classes _undefined_. That means that actions labelled with these classes are excluded during that run. Another way to restrict classes is to add a list of classes to be undefined in the actionsequence. See next section.  File: cfengine-Reference.info, Node: addinstallable, Next: AllowRedefinitionOf, Prev: addclasses, Up: control 4.10.5 AddInstallable --------------------- AddInstallable = ( LIST OF IDENTIFIERS ) Some actions in your cfengine program will be labelled by classes which only become defined at run time using a `define=' option. Cfengine is not always able to see these classes until it meets them and tries to save space by only loading actions for classes which is believes will become defined at some point in the program. This can lead to some actions being missed if the action is parsed before the place where the class gets switched on, since cfengine is a one-pass interpreter,. To help cfengine determine classes which _might become defined_ during a run, you can declare them in this list. It does no harm to declare classes here anyway. Here is an example where you need to declare a class because of the ordering of the actions. control: AddInstallable = ( myclass ) files: myclass:: /tmp/test mode=644 action=fixall copy: /tmp/foo dest=/tmp/test define=myclass If we remove the declaration, then when cfengine meets the files command, it skips it because it knows nothing about the class `myclass'--when the copy command follows, it is too late. Remember that imported files are always parsed after the main program so definitions made in imported files always come later than things in the main program.  File: cfengine-Reference.info, Node: AllowRedefinitionOf, Next: Auditing, Prev: addinstallable, Up: control 4.10.6 AllowRedefinitionOf -------------------------- Normally cfagent warns about redefinitions of variables during parsing. This is presumed to be a mistake. To avoid this behaviour, add the name of the variable to this list, and the warning disappears. control: actionsequence = ( copy ) AllowRedefinitionOf = ( cfrep ) cfrep = ( bla ) cfrep = ( blo )  File: cfengine-Reference.info, Node: Auditing, Next: AutoDefine, Prev: AllowRedefinitionOf, Up: control 4.10.7 Auditing --------------- If this variable is set to true then cfengine conducts extensive auditing of its actions to a database in the work directory. When rules are applied, their locations and policy version are recorded also so that it is possible to see exactly which rule was applied and when. It is assumed that the version is recorded as below: control: cfinputs_version = ( 1.2.1 ) Auditing = true This variable acts as the global default behaviour and may be overriden locally by `audit=true/false' attributes, where applicable.  File: cfengine-Reference.info, Node: AutoDefine, Next: BinaryPaddingChar, Prev: Auditing, Up: control 4.10.8 AutoDefine ----------------- control: hup_syslogd:: autodefine = ( /etc/syslog.c* ) Referring to the class that prefixes the command, `autodefine' is a list of file patterns that will define the said class, if a named file is copied in any statement. This helps to avoid having to write a large number of file-specific copy: lines with define=class configured. In the example above, the class `hup_syslogd' would be defined if `/etc/syslog.conf' is copied at any time.  File: cfengine-Reference.info, Node: BinaryPaddingChar, Next: BindToInterface in cfagent, Prev: AutoDefine, Up: control 4.10.9 BinaryPaddingChar ------------------------ BinaryPaddingChar = ( \0 ) This specifies the type of character used to pad strings of unequal length in `editfiles' during binary editing. The default value is the space character, since this is normally used to edit filenames or text messages within program code.  File: cfengine-Reference.info, Node: BindToInterface in cfagent, Next: ChecksumDatabase in cfagent, Prev: BinaryPaddingChar, Up: control 4.10.10 BindToInterface in cfagent ---------------------------------- If this is set to a specific IP address of an IP configured interface, cfagent will use that address for outgoing connections. On Multi-homed hosts this allows one to restrict the traffic to a known interface. An interface must be configured with an IP address in order to be bound. This feature is not available for old operating systems.  File: cfengine-Reference.info, Node: ChecksumDatabase in cfagent, Next: ChecksumPurge, Prev: BindToInterface in cfagent, Up: control 4.10.11 ChecksumDatabase in cfagent ----------------------------------- ChecksumDatabase = ( /var/cfengine/cfdb ) If this filename is defined, cfengine will use it to store message digests (i.e. cryptographic checksums) of files for security purposes, *Note files::, `checksum='. This option was deprecated in 2.1.22.  File: cfengine-Reference.info, Node: ChecksumPurge, Next: ChecksumUpdates, Prev: ChecksumDatabase in cfagent, Up: control 4.10.12 ChecksumPurge --------------------- ChecksumPurge = ( on ) This variable defaults to `off'. If set to true, cfagent will look at all of the registered files in the database and check whether thet still exist. If the file no longer exists, it is removed from the database and a warning is issued. To purge files now and then, but at no particular time, one could do something like this: strategies: { purging NowAndThen: 1 ElseWhen: 49 } control: NowAndThen:: ChecksumPurge = ( on )  File: cfengine-Reference.info, Node: ChecksumUpdates, Next: CompressCommand, Prev: ChecksumPurge, Up: control 4.10.13 ChecksumUpdates ----------------------- ChecksumUpdates = ( on ) This variable defaults to `off'. If set to true, cfagent will automatically update the checksum of a file, if it changes on the disk. This means that a security warning will be issued only once about files which have changed, and the changed version will be re-registered as the correct version. This option could be switched on after a system upgrade, for instance, in order to update the database, and then switched to `off' again to reduce the risk of missing a security alert. Alternatively, if you are confident that the first message is sufficient, it can be left as `on' so that only one message is given.  File: cfengine-Reference.info, Node: CompressCommand, Next: childlibpath, Prev: ChecksumUpdates, Up: control 4.10.14 CompressCommand ----------------------- Specified the name of a program that is used in the files `action=compress' attribute. CompressCommand = ( /usr/bin/gzip )  File: cfengine-Reference.info, Node: childlibpath, Next: copylinks, Prev: CompressCommand, Up: control 4.10.15 ChildLibPath -------------------- Sets a value for LD_LIBRARY_PATH in child processes: childlibpath = ( /usr/local/lib:/local/mysql/lib ) Note that the variables LD_LIBRARY_PATH is special. This library path is needed to run processes as children of cfengine. Often, if the agent is started from cron (which is started by init), there is no suitable library path set, and shellcommands will fail with strange errors about not being able to load shared objects. Setting a library path here is a useful way of correcting this problem.  File: cfengine-Reference.info, Node: copylinks, Next: defaultcopytype, Prev: childlibpath, Up: control 4.10.16 CopyLinks ----------------- This list is used to define a global list of names or patterns which are to be copied rather than linked symbolically. For example CopyLinks = ( *.config ) The same facility can be specified for each individual link operation using the `copy' option *Note links::. Copying is performed using a file age comparison. Note that all entries defined under a specified class are valid only as long as that class is defined. For instance CLASS:: CopyLinks = ( PATTERN ) would define a pattern which was only valid when CLASS is defined.  File: cfengine-Reference.info, Node: defaultcopytype, Next: defaultpkgmgr, Prev: copylinks, Up: control 4.10.17 DefaultCopyType ----------------------- This parameter determines the default form of copying for all copy operations parsed after this variable. The legal values are `ctime' (intial default), `mtime', `checksum' and `binary'. e.g. DefaultCopyType = ( mtime )  File: cfengine-Reference.info, Node: defaultpkgmgr, Next: deletenonuserfiles, Prev: defaultcopytype, Up: control 4.10.18 DefaultPkgMgr --------------------- Sets the default value of the `pkgmgr' attribute for `packages' items. DefaultPkgMgr = ( rpm ) By default, this variable is not set, meaning there will be no package manager selected, and each item in the `packages' section must specify its own package manager, or it will not be checked. For information on the values of this variable, *Note packages::.  File: cfengine-Reference.info, Node: deletenonuserfiles, Next: deletenonownerfiles, Prev: defaultpkgmgr, Up: control 4.10.19 DeleteNonUserFiles -------------------------- If this parameter is set to true, cfengine will delete files which do not have a name belonging to a known user id. DeleteNonUserFiles = ( true ) SpoolDirectories = ( /var/spool/cron/crontabs ) This is an generalization of DeleteNonUserMail and makes it redundant. it is formally executed as a part of the "tidy" action.  File: cfengine-Reference.info, Node: deletenonownerfiles, Next: deletenonusermail, Prev: deletenonuserfiles, Up: control 4.10.20 DeleteNonOwnerFiles --------------------------- If this parameter is set to true, cfengine will delete files on mailservers whose names do not correspond to a known user name, but might be owned by a known user. DeleteNonOwnerFiles = ( true ) SpoolDirectories = ( /var/spool/cron/crontabs ) This is an generalization of DeleteNonOwnerMail and makes it redundant.  File: cfengine-Reference.info, Node: deletenonusermail, Next: deletenonownermail, Prev: deletenonownerfiles, Up: control 4.10.21 DeleteNonUserMail ------------------------- If this parameter is set to true, cfengine will delete mail files on mailservers which do not have a name belonging to a known user id. This does not include lock files.  File: cfengine-Reference.info, Node: deletenonownermail, Next: domain, Prev: deletenonusermail, Up: control 4.10.22 DeleteNonOwnerMail -------------------------- If this parameter is set to true, cfengine will delete files on mailservers whose names do not correspond to a known user name, but might be owned by a known user.  File: cfengine-Reference.info, Node: domain, Next: dpkginstallcommand, Prev: deletenonownermail, Up: control 4.10.23 domain -------------- domain = ( DOMAIN NAME ) This variable defines the domainname for your site. You must define it here, because your system might not know its domainname when you run cfengine for the first time. The domainname can be used as a cfengine variable subsequently by referring to $(domain). The domainname variable is used by the action `resolve'. The domain is also used implicitly by other matching routines. You should define the domain as early as possible in your configuration file so as to avoid problems, especially if you have the strange practice of naming hosts with their fully qualified host names since groups which use fully qualified names can fail to be defined if cfengine is not able to figure out the domain name.  File: cfengine-Reference.info, Node: dpkginstallcommand, Next: dryrun, Prev: domain, Up: control 4.10.24 DPKGInstallCommand -------------------------- Sets the command used to install packages that need to be installed under the DPKG package manager. DPKGInstallCommand = ( "/usr/bin/pkgmgr %s" ) By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the "'s around the string, and the %s is replaced with the name of the package to be installed.  File: cfengine-Reference.info, Node: dryrun, Next: editbinaryfilesize, Prev: dpkginstallcommand, Up: control 4.10.25 DryRun -------------- DryRun = ( ON/off ) This variable has the same effect as the command line options `--dry-run' or `-n'. It tells cfengine to only report what it should do without actually doing it. CLASSES:: DryRun = ( on )  File: cfengine-Reference.info, Node: editbinaryfilesize, Next: editfilesize, Prev: dryrun, Up: control 4.10.26 editbinaryfilesize -------------------------- EditBinaryFileSize = ( SIZE ) Cfengine will refuse to edit a file which is larger than the value of `editbinaryfilesize' in bytes. This is to prevent possible accidents from occurring. The default value for this variable is 10000000 bytes. If you don't like this feature, simply set the value to be a very large number or to zero. If the value is zero, cfengine will ignore it.  File: cfengine-Reference.info, Node: editfilesize, Next: emptyresolvconf, Prev: editbinaryfilesize, Up: control 4.10.27 editfilesize -------------------- EditfileSize = ( SIZE ) This variable is used by cfengine every time it becomes necessary to edit a file. Since file editing applies only to text files, the files are probably going to be relatively small in most cases. Asking to edit a very large (perhaps binary) file could therefore be the result of an error. A check is therefore made as a security feature. Cfengine will refuse to edit a file which is larger than the value of `editfilesize' in bytes. This is to prevent possible accidents from occurring. The default value for this variable is 10000 bytes. If you don't like this feature, simply set the value to be a very large number or to zero. If the value is zero, cfengine will ignore it.  File: cfengine-Reference.info, Node: emptyresolvconf, Next: exclamation, Prev: editfilesize, Up: control 4.10.28 EmptyResolvConf ----------------------- EmptyResolvConf = ( true ) Normally cfengine does not tidy up old entries in the `/etc/resolv.conf' file. This option causes cfengine to remove all existing content from the file.  File: cfengine-Reference.info, Node: exclamation, Next: excludecopy, Prev: emptyresolvconf, Up: control 4.10.29 Exclamation ------------------- This variable defaults to "on". If set to "off", no exclamation marks (Br. pling, Am: shriek) are printed during security alerts, e.g. for checksum violations. Exclamation = ( off )  File: cfengine-Reference.info, Node: excludecopy, Next: excludelinks, Prev: exclamation, Up: control 4.10.30 ExcludeCopy ------------------- This list is used to define a global list of names or patterns which are to be excluded from copy operations. For example ExcludeCopy = ( *~ *% core ) The same facility can be specified for each individual link operation using the `exclude' option *Note copy::. Note that all entries defined under a specified class are valid only as long as that class is defined. For instance CLASS:: ExcludeCopy = ( PATTERN ) would define a pattern which was only valid when CLASS is defined.  File: cfengine-Reference.info, Node: excludelinks, Next: ExpireAfter, Prev: excludecopy, Up: control 4.10.31 ExcludeLink ------------------- This list is used to define a global list of names or patterns which are to be excluded from linking operations. For example ExcludeLink = ( *~ *% core ) The same facility can be specified for each individual link operation using the `exclude' option *Note links::. Note that all entries defined under a specified class are valid only as long as that class is defined. For instance CLASS:: ExcludeLink = ( PATTERN ) would define a pattern which was only valid when CLASS is defined.  File: cfengine-Reference.info, Node: ExpireAfter, Next: FreeBSDInstallCommand, Prev: excludelinks, Up: control 4.10.32 ExpireAfter ------------------- If you change the value of this parameter, it should be one of the first things you do in your configuration script. This parameter controls the global value of the ExpireAfter parameter. *Note Spamming and security: (cfengine-Tutorial)Spamming and security. This parameter controls the maximum time in minutes which a cfengine action is allowed to live. After this time a second cfengine agent will try to kill the cfengine which seems to have hung and attempt to restart the action. This is different from a TimeOut, where an internal alarm interrupt is used. ExpireAfter = ( TIME-IN-MINUTES ) This parameter may also be set per action in the action sequence by appending a pseudo-class called `ExpireAfterTIME'. For instance, actionsequence = ( copy.ExpireAfter15 ) sets the expiry time parameter to 15 minutes for this copy command. This method should be considered old and deprecated however. As of version 2.1.0, you can define the expiry time on a per-command basis, as options of the form `expireafter=10'.  File: cfengine-Reference.info, Node: FreeBSDInstallCommand, Next: FreeBSDRemoveCommand, Prev: ExpireAfter, Up: control 4.10.33 FreeBSDInstallCommand ----------------------------- Sets the path to `pkg_add' which is used to install packages that need to be installed under FreeBSD. FreeBSDInstallCommand = ( "/usr/sbin/pkg_add -r %s" ) By default, this variable is not set, meaning that any packages with action=install will NOT be installed. Note the quotes around the string, and the `%s' is replaced with the name of the package to be installed.  File: cfengine-Reference.info, Node: FreeBSDRemoveCommand, Next: FullEncryption, Prev: FreeBSDInstallCommand, Up: control 4.10.34 FreeBSDRemoveCommand ---------------------------- Sets the path to `pkg_delete' which is used to remove packages that need to be uninstalled under FreeBSD. FreeBSDRemoveCommand = ( "/usr/sbin/pkg_delete %s" ) By default, this variable is set to /usr/sbin/pkg_delete, meaning that any packages with action=remove will be removed. Note the quotes around the string, and the `%s' is replaced with the name of the package to be installed.  File: cfengine-Reference.info, Node: FullEncryption, Next: homepattern, Prev: FreeBSDRemoveCommand, Up: control 4.10.35 FullEncryption ---------------------- From version 2.1.22. This is false for protocol compatability with older servers. If this is set to true, directory filenames are encrypted in addition to file contents. If transferred data are not especially secret or travel over public networks this is a waste of CPU time. In high security environments it provides full privacy of data transmission. FullEncryption = ( true )  File: cfengine-Reference.info, Node: homepattern, Next: HostnameKeys in cfagent, Prev: FullEncryption, Up: control 4.10.36 HomePattern ------------------- HomePattern = ( LIST OF PATTERNS ) The `homepattern' variable is used by the cfengine model for mounting nfs filesystems. *Note NFS resources: (cfengine-Tutorial)NFS resources. It is also used in the evaluation of the pseudo variable `home', See *note files::, *note tidy::. `homepattern' is in fact a list and is used like a wildcard or _pattern_ to determine which filesystems in the list of mountables are home directories. *Note mountables::. This relies on your sticking to a rigid naming convention as described in the first reference above. For example, you might wish to mount (or locate directly if you are not using a separate partition for home directories) your home directories under `mountpattern' in directories `u1', `u2' and so on. In this case you would define `homepattern' to match these numbers: homepattern = ( u? ) Cfengine now regards any directory matching `$(mountpattern)/u?' as being a user login directory. Suppose you want to create mount home directories under `$(mountpattern)/home' and make subdirectories for staff and students. Then you would be tempted to write: HomePattern = ( home/staff home/students ) Unfortunately this is not presently possible. (This is, in principle, a bug which should be fixed in the future.) What you can do instead is to achieve the same this as follows: MountPattern = ( /$(site)/$(host) /$(site)/$(host)/home ) HomePattern = ( staff students )  File: cfengine-Reference.info, Node: HostnameKeys in cfagent, Next: IfElapsed in cfagent, Prev: homepattern, Up: control 4.10.37 HostnameKeys in cfagent ------------------------------- If this variable is set to true/on, it causes cfagent to lookup and store trusted public keys according to their DNS fully qualified host name, instead of using the IP address. This can be useful in environments where hosts do not have fixed IP addresses, but do have fixed hostnames. HostnameKeys = ( on ) This method of storing keys is not recommended for sites with fixed IP addresses, since it removes one security barrier from a potential attacker by potentially allowing DNS spoofing. Note that there is a corresponding variable to be set in `cfrun.hosts' which must be set for consistency.  File: cfengine-Reference.info, Node: IfElapsed in cfagent, Next: IgnoreFriendRegex, Prev: HostnameKeys in cfagent, Up: control 4.10.38 IfElapsed in cfagent ---------------------------- If you change the value of this parameter, it should be one of the first things you do in your configuration script. This parameter controls the global value of the IfElapsed parameter, *Note Spamming and security: (cfengine-Tutorial)Spamming and security. This parameter controls the minimum time which must have elapsed for an action in the action sequence before which it will be executed again. IfElapsed = ( TIME-IN-MINUTES ) This parameter may also be set per action in the action sequence by appending a pseudo-class called `IfElapsedTIME'. For instance, ActionSequence = ( copy.IfElapsed15 ) sets the elapsed time parameter to 15 minutes for this copy command. This method should be considered old and deprecated however. As of version 2.1.0, you can define the expiry time on a per-command basis, as options of the form `ifelapsed=15'.  File: cfengine-Reference.info, Node: IgnoreFriendRegex, Next: IgnoreInterfaceRegex, Prev: IfElapsed in cfagent, Up: control 4.10.39 FriendIgnoreRegex ------------------------- Use this regular expression to suppress FriendStatus warnings for matching hosts. e.g. IgnoreFriendRegex = ( "2001:700:.*|host1|host2" )  File: cfengine-Reference.info, Node: IgnoreInterfaceRegex, Next: Inform, Prev: IgnoreFriendRegex, Up: control 4.10.40 IgnoreInterfaceRegex ---------------------------- Use this regular expression to delete class information about interfaces that you do not want to see on a host. This is useful for tamig virtual machines and their multitudinous interfaces. IgnoreInterfaceRegex = ( "vm.*" )  File: cfengine-Reference.info, Node: Inform, Next: interfacename, Prev: IgnoreInterfaceRegex, Up: control 4.10.41 Inform -------------- Inform = ( ON/off ) This variable switches on the output level whereby cfengine reports changes it makes during a run. Normally only urgent messages or clear errors are printed. Setting `Inform' to `on' makes cfengine report on all actions not explicitly cancelled with a `silent' option. To set this output level one writes: CLASSES:: Inform = ( on )  File: cfengine-Reference.info, Node: interfacename, Next: fileextension, Prev: Inform, Up: control 4.10.42 InterfaceName --------------------- If you have an operating system which is installed on some non-standard hardware, you might have to specifically set the name of the network interface. For example: control: nextstep.some:: InterfaceName = ( en0 ) nextstep.others:: InterfaceName = ( ec0 ) It is only necessary to set the interface name in this fashion if you have an operating system which is running on special hardware. Most users will not need this. The choice set here overrides the system defaults and the choices made in the `cfrc' file, *Note cfrc resource file::.  File: cfengine-Reference.info, Node: fileextension, Next: lastseen, Prev: interfacename, Up: control 4.10.43 FileExtensions ---------------------- This list may be used to define a number of extensions which are regarded as being plain files by the system. As part of the general security checking cfengine will warn about any directories which have names using these extensions. They may be used to conceal directories. FileExtensions = ( c o gif jpg html )  File: cfengine-Reference.info, Node: lastseen, Next: lastseenexpireafter, Prev: fileextension, Up: control 4.10.44 LastSeen ---------------- This option is true by default. If set to off or false it prevents cfengine and/or cfservd from learning about last times hosts were observed connecting to one another. Some users with broken resolvers (particularly in view of the change over to IPv6 compatible libraries) might find this useful when processes appear to hang on connecting. LastSeen = ( off )  File: cfengine-Reference.info, Node: lastseenexpireafter, Next: linkcopies, Prev: lastseen, Up: control 4.10.45 LastSeenExpireAfter --------------------------- This value (in days) sets the time after which unseen friend hosts are purged from the `last seen' database, as viewed by the `FriendStatus' function, *Note alerts::. LastSeenExpireAfter = ( 2 )  File: cfengine-Reference.info, Node: linkcopies, Next: LogDirectory, Prev: lastseenexpireafter, Up: control 4.10.46 LinkCopies ------------------ This list is used to define a global list of names or patterns which are to be linked symbolically rather than copied. For example excludelinks = ( *.gif *.jpg ) The same facility can be specified for each individual link operation using the `symlink' option *Note copy::. Note that all entries defined under a specified class are valid only as long as that class is defined. For instance CLASS:: LinkCopies = ( PATTERN ) would define a pattern which was only valid when CLASS is defined.  File: cfengine-Reference.info, Node: LogDirectory, Next: LogTidyHomeFiles, Prev: linkcopies, Up: control 4.10.47 LogDirectory -------------------- This is now deprecated. Specify an alternative directory for keeping cfengine's log data. This defaults to `/var/run/cfengine' or `/var/cfengine'. LogDirectory = ( /var/cfengine )  File: cfengine-Reference.info, Node: LogTidyHomeFiles, Next: moduledirectory, Prev: LogDirectory, Up: control 4.10.48 LogTidyHomeFiles ------------------------ LogTidyHomeFiles = ( off ) If set to "off", no log is made of user files, in their home directories, of the files which are tidied by cfengine.  File: cfengine-Reference.info, Node: moduledirectory, Next: mountpattern, Prev: LogTidyHomeFiles, Up: control 4.10.49 moduledirectory ----------------------- moduledirectory = ( DIRECTORY FOR PLUGIN MODULES ) This is the directory where cfengine will look for plug-in modules for the actionsequence, *Note actionsequence::. Plugin modules may be used to activate classes using special algorithms. *Note Writing plugin modules: (cfengine-Tutorial)Writing plugin modules. This variable defaults to `/var/cfengine/modules' for privileged users and to `$HOME)/.cfengine/modules' for non-privileged users.  File: cfengine-Reference.info, Node: mountpattern, Next: netmask, Prev: moduledirectory, Up: control 4.10.50 mountpattern -------------------- mountpattern = ( MOUNT-POINT ) The `mountpattern' list is used by the cfengine model for mounting nfs filesystems. *Note NFS resources: (cfengine-Tutorial)NFS resources. It is also used in the evaluation of the pseudo variable `home', See *note files::, *note tidy::. It is used together with the value of `homepattern' to locate and identify what filesystems are local to a given host and which are mounted over the network. For this list to make sense you need to stick to a rigid convention for mounting your filesystems under a single naming scheme as described in the section mentioned above. If you follow the recommended naming scheme then you will want to set the value of mountpattern to mountpattern = ( /$(site)/$(host) ) which implies that cfengine will look for local disk partitions under a unique directory given by the name of the host and site. Any filesystems which are physically located on the current host lie in this directory. All mounted filesystems should lie elsewhere. If you insist on keeping mounted file systems in more than one location, you can make a list like this: mountpattern = ( /$(site)/users /$(site)/projects )  File: cfengine-Reference.info, Node: netmask, Next: nonalphanumfiles, Prev: mountpattern, Up: control 4.10.51 netmask --------------- netmask = ( AAA.BBB.CCC.DDD ) The netmask variable defines the partitioning of the subnet addresses on your network. Its value is defined by your network administrator. On most systems it is likely to be `255.255.255.0'. This is used to configure the network interface in `netconfig'. *Note actionsequence::. Every host on the internet has its own unique address. The addresses are assigned hierarchically. Each network gets a _domain name_ and can attach something like 65,000 hosts to that network. Since this is usually too many to handle in one go, every such network may be divided up into subnets. The administrator of the network can decide how the division into subnets is made. The decision is a trade-off between having many subnets with few hosts, or many hosts on few subnets. This choice is made by setting the value of a variable called `netmask'. The netmask looks like an internet address. It takes the form: aaa.bbb.ccc.mmm The first two numbers `aaa.bbb' are the address of the domain. The remainder `ccc.mmm' specifies both the subnet and the hostname. The value of `netmask' tells all hosts on the network: how many of the bits in the second half label different subnets and how many label different hosts on each of the subnets? The most common value for the netmask is `255.255.255.0'. It is most helpful to think of the netmask in terms of bits. Each base-10 number between 0-255 represents 8 bits which are either set or not set. Every bit which is set is a network address and every bit which is zero is part of a host address. The first two parts of the address `255.255' always takes these values. If the third number is `255', it means that the domain is divided up into 256 sub networks and then the remaining bits which are zero can be used to give 255 different host addresses on each of the subnets. If the value had been `255.255.255.254', the network would be divided up into 2^15 subnets, since fifteen of the sixteen bits are one. The remaining bit leaves enough room for two addresses 0 and 1. One of those is reserved for _broadcasts_ to all hosts, the other can be an actual host -- there would only be room for one host per subnet. This is a stupid example of course, the main point with the subnet mask is that it can be used to trade subnets for hosts per subnet. A value of `255.255.254.0' would allow 128 different subnets with 2*256-1 = 511 hosts on each. We needn't be concerned with the details of the netmask here. Suffice it to say that its value is determined for your entire domain by the network administrator and each host has to be told what the value is. Each host must also know what convention is used for the _broadcast address_. This is an address which hosts can send to if they wish to send a message to every other host on their subnet simultaneously. It is used a lot by services like NIS to ask if any hosts are willing to perform a particular service. There are two main conventions for the broadcast address: address zero (all host bits are zero) and the highest address on the subnet (all host bits are ones). The convention can be different on every subnet and it is decided by the network administrator. When you write a cfengine program you just specify the convention used on your subnet and cfengine works out the value of the broadcast address from the netmask and the host address *Note broadcast::. Cfengine works out the value of the broadcast address using the value of the netmask.  File: cfengine-Reference.info, Node: nonalphanumfiles, Next: nfstype, Prev: netmask, Up: control 4.10.52 NonAlphaNumFiles ------------------------ If enabled, this option causes cfengine to detect and disable files which have purely non-alphanumeric filenames, i.e. files which might be accidental or deliberately concealed. The files are then marked with a suffix `.cf-nonalpha' and are rendered visible. NonAlphaNumFiles = ( on ) These files can then be tidied by searching for the suffix. Note that alphanumeric means ascii codes less than 32 and greater than 126.  File: cfengine-Reference.info, Node: nfstype, Next: PortageInstallCommand, Prev: nonalphanumfiles, Up: control 4.10.53 nfstype --------------- nfstype = ( NFS-TYPE ) This variable is included only for future expansion. If you do not define this variable, its value defaults to "nfs". At present cfengine operates only with NFS (the network file system). When cfengine looks for network file systems to mount, it adds lines in the filesystem table (`/etc/fstab',`/etc/checklist' etc.) to try to mount filesystems of type "nfs". In principle you might want to use a completely different system for mounting filesystems over the network, in which case the `mount type' would not be "nfs" but something else. At the time of writing certain institutions are replacing NFS with AFS (the Andrew filesystem) and DFS (from the distributed computing environment). The use of these filesystems really excludes the need to use the mount protocol at all. In other words if you are using AFS or DFS, you don't need to use cfengine's mounting commands at all.  File: cfengine-Reference.info, Node: PortageInstallCommand, Next: repchar, Prev: nfstype, Up: control 4.10.54 PortageInstallCommand ----------------------------- Sets the path to `emerge' which is used to install packages that need to be installed under Gentoo Portage. gentoo.some:: DefaultPkgMgr = ( portage ) PortageInstallCommand = ( "/usr/bin/emerge --nocolor %s" ) gentoo.other:: DefaultPkgMgr = ( portage ) PortageInstallCommand = ( "/usr/lib/portage/bin/emerge --color=n %s" By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the quotes around the string, and the `%s' is replaced with the name of the package to be installed.  File: cfengine-Reference.info, Node: repchar, Next: repository, Prev: PortageInstallCommand, Up: control 4.10.55 RepChar --------------- RepChar = ( CHARACTER ) The value of this variable determines the characters which is used by cfengine in creating the unique filenames in the file repository. Normally, its value is set to `_' and each `/' in the path name of the file is changed to `_' and stored in the repository. If you prefer a different character, define it here. Note that the character can be quoted with either single or double quotes in order to encompass spaces etc.  File: cfengine-Reference.info, Node: repository, Next: RPMcommand, Prev: repchar, Up: control 4.10.56 Repository ------------------ Repository = ( DIRECTORY ) Defines a special directory where all backup and junk files are collected. Files are assigned a unique filename which identifies the path from which they originate. This affects files saved using `disable', `copy', `links' and `editfiles' *Note Disabling and the file repository: (cfengine-Tutorial)Disabling and the file repository.  File: cfengine-Reference.info, Node: RPMcommand, Next: rpminstallcommand, Prev: repository, Up: control 4.10.57 RPMcommand ------------------ The default value of the Red Hat Package manager command `/bin/rpm' can be altered for non-standard systems with this variable. RPMcommand = ( /usr/bin/rpm )  File: cfengine-Reference.info, Node: rpminstallcommand, Next: schedule, Prev: RPMcommand, Up: control 4.10.58 RPMInstallCommand ------------------------- Sets the command used to install packages that need to be installed under the RPM package manager. RPMInstallCommand = ( "/usr/bin/pkgmgr %s" ) By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the quotes around the string, and the `%s' is replaced with the name of the package to be installed. control: DefaultPkgMgr = ( rpm ) RPMInstallCommand = ( "/usr/bin/yum -d 0 -e 0 -y install %s" ) # This would remove all dependencies (!) # # RPMRemoveCommand = ( "/usr/bin/yum -d 0 -e 0 -y remove %s" ) # This might be less drastic RPMRemoveCommand = ( "/bin/rpm -e --nodeps %s" ) packages: # this will remove this package regardless of version. some_rpm_name version=0:0.0 cmp=ge action=remove  File: cfengine-Reference.info, Node: schedule, Next: secureinput, Prev: rpminstallcommand, Up: control 4.10.59 Schedule ---------------- schedule = ( Min00_05 Min30_35 TIME CLASS ) When `cfexecd' is used in daemon mode, it defaults to running once an hour, on the hour, i.e.. schedule = ( Min00_05 ) This can be extended to make the agent run more often. The time specifiers are cfengine classes, and are written as intervals of time rather the precise times. Cfengine's time resolution is purposely limited to five minutes because the auto-correlation time of user resources is generally greater than this. Thus, it is assumed that precision timing is not required and the start time of cfengine, when scheduled in daemon mode, is not better than a few minutes. The daemon does not require precision, but offers many other strategic features for load balancing and security. Other time classes can be used in the schedule list, but note that cfexecd will not run the agent more than once every five minutes. This is treated as a fundamental granularity.  File: cfengine-Reference.info, Node: secureinput, Next: sensiblecount, Prev: schedule, Up: control 4.10.60 SecureInput ------------------- SecureInput = ( on ) If this is set cfengine will not import files which are not owned by the uid running the program, or which are writable by groups or others.  File: cfengine-Reference.info, Node: sensiblecount, Next: sensiblesize, Prev: secureinput, Up: control 4.10.61 SensibleCount --------------------- SensibleCount = ( COUNT ) This variable is used by the action `required'. It defines for cfengine what you consider to be the minimum number of files in a `required' directory. If you declare a directory as being required, cfengine will check to see if it exists. Then, if the directory contains fewer than the value of `sensiblecount' files, a warning is issued. The default value for this variable is 2.  File: cfengine-Reference.info, Node: sensiblesize, Next: showactions, Prev: sensiblecount, Up: control 4.10.62 SensibleSize -------------------- SensibleSize = ( SIZE ) This variable is used by the action `required'. It defines for cfengine what you consider to be the minimum size for a `required' file. If you declare a file as being required, cfengine will check to see if the file exists. Of course, the file may exist but be empty, so the size of the file is also checked against this constant. If the file is smaller than the value of `sensiblesize' a warning is issued. The default value for this variable is 1000 bytes.  File: cfengine-Reference.info, Node: showactions, Next: singlecopy, Prev: sensiblesize, Up: control 4.10.63 ShowActions ------------------- ShowActions = ( ON ) This causes cfengine to produce detailed output of what action is being carried out as part of the prefix information during output. This is intended only for third party tools which collect and parse the cfengine output. It will be of little interest to humans.  File: cfengine-Reference.info, Node: singlecopy, Next: site, Prev: showactions, Up: control 4.10.64 SingleCopy ------------------ singlecopy = ( path_and_filename_wildcard ) If a `singlecopy' pattern is defined the behavior of copy: is modified so that a given destination file, matching the pattern, will only be updated once. In other words, if someone tries to copy more then one source file to the same location, the destination will not be overwritten in the same run. If the path name and wildcard is any of '*', 'on' or 'true', then the list applies to all files. For example: control: actionsequence = ( copy ) singlecopy = ( /tmp/* ) addinstallables = ( zzz ) zzz:: autodefine = ( /tmp/* ) copy: /etc/passwd dest=/tmp/destination type=binary /etc/group dest=/tmp/destination type=binary alerts: zzz:: "Copied something in /tmp" Note (Warning) that this feature has several problems. It assumes an order dependence that cfengine generally tries to avoid. The first copy that takes place wins. Also, if files are locked at different times, this can result in oscillations between several different source files. e.g. copy: /etc/passwd dest=/tmp/bla type=binary ifelapsed=2 /etc/group dest=/tmp/bla type=binary ifelapsed=1 In order to avoid explicit looping, cfengine assumes that a file has been copied even if no actual copy took place - i.e. as long as a file is apparently up to date, that counts as a valid copy update and the promise/action is considered done. If this were not the case, then the following promises would still be in line for execution and cfengine would loop between the different versions on subsequent invocations.  File: cfengine-Reference.info, Node: site, Next: SkipIdentify, Prev: singlecopy, Up: control 4.10.65 site/faculty -------------------- site = ( SITENAME ) faculty = ( FACULTYNAME ) This variable defines a convenient name for your site configuration. It is useful for making generic rules later on, because it means for instance that you can define the name of a directory to be /$(site)/$(host)/local without having to redefine the rule for a specific site. This is a handy trick for making generic rules in your files which can be imported into a configuration for any site. `faculty' is a synonym for `site'. The two names may be used interchangeably.  File: cfengine-Reference.info, Node: SkipIdentify, Next: Smtpserver, Prev: site, Up: control 4.10.66 SkipIdentify -------------------- SkipIdentify = ( true ) This is the client side directive corresponding to the server directive `SkipVerify'. It tells cfengine not to assume that the client is registered in the Domain Name Service (DNS). Sometimes the assumption of DNS registration can break connectivity between hosts, particularly if firewalls or Network Address Translation is in use.  File: cfengine-Reference.info, Node: Smtpserver, Next: SplayTime, Prev: SkipIdentify, Up: control 4.10.67 smtpserver ------------------ smtpserver = ( MAILHOST ) This variable specified the destination for Email sent by cfexecd.  File: cfengine-Reference.info, Node: SplayTime, Next: split, Prev: Smtpserver, Up: control 4.10.68 SplayTime ----------------- SplayTime = ( TIME-IN-MINUTES ) This variable is used to set the maximum time over which cfengine will share its load on a server, *Note Splaying host times: (cfengine-Tutorial)Splaying host times.  File: cfengine-Reference.info, Node: split, Next: spooldirectories, Prev: SplayTime, Up: control 4.10.69 Split ------------- Split = ( CHARACTER ) The value of this variable is used to define the list separator in variables which are expected to be treated as lists. The default value of this variable is the colon `:'. Cfengine treats variables containing this character as lists to be broken up and iterated over, *Note Iteration over lists::. This typically allows communication with PATH-like environment variables in the shell.  File: cfengine-Reference.info, Node: spooldirectories, Next: suninstallcommand, Prev: split, Up: control 4.10.70 SpoolDirectories ------------------------ A list of additional spool directories for cfengine to police. In these directories, filenames should correspond to existing users of the system. When users lost their accounts, this list plus the mail spool directory will be checked for files owned by deprecated users. See also: `DeleteNonOwnerFiles', `DeleteNonUserFiles'. SpoolDirectories = ( /var/spool/cron/crontabs /var/spool/cron/atjobs )  File: cfengine-Reference.info, Node: suninstallcommand, Next: suspiciousnames, Prev: spooldirectories, Up: control 4.10.71 SUNInstallCommand ------------------------- Sets the command used to install packages that need to be installed under the SUN package manager. SUNInstallCommand = ( "/usr/bin/pkgmgr %s" ) By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the quotes around the string, and the `%s' is replaced with the name of the package to be installed.  File: cfengine-Reference.info, Node: suspiciousnames, Next: sysadm, Prev: suninstallcommand, Up: control 4.10.72 suspiciousnames ----------------------- SuspiciousNames = ( .mo lrk3 ) Filenames in this list are treated as suspicious and generate a warning as cfengine scans directories. This might be used to detect hacked systems or concealed programs. Checks are only made in directories which cfengine scans in connection with a command such as files, tidy or copy.  File: cfengine-Reference.info, Node: sysadm, Next: Syslog, Prev: suspiciousnames, Up: control 4.10.73 sysadm -------------- sysadm = ( MAIL ADDRESS ) The mail address of your system administrator should be placed here. This is used in two instances. If cfengine is invoked with the option `-a', then it simply prints out this value. This is a handy feature for making scripts. The administrators mail address is also written into the personal log files which cfengine creates for each user after tidying files, so you should make this an address which users can mail if they have troubles.  File: cfengine-Reference.info, Node: Syslog, Next: SyslogFacility, Prev: sysadm, Up: control 4.10.74 Syslog -------------- Syslog = ( ON/off ) This variable activates syslog logging of cfengine output at the `inform' level. To set this output level one writes: CLASSES:: Syslog = ( on )  File: cfengine-Reference.info, Node: SyslogFacility, Next: timezone, Prev: Syslog, Up: control 4.10.75 SyslogFacility ---------------------- SyslogFacility = ( FACILITY ) This variable alters the syslog facility level. e.g. SyslogFacility = ( LOG_LOCAL1 ) Valid arguments are LOG_USER LOG_DAEMON LOG_LOCAL0 LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4  File: cfengine-Reference.info, Node: timezone, Next: TimeOut, Prev: SyslogFacility, Up: control 4.10.76 timezone ---------------- timezone = ( 3-CHARACTER TIMEZONE ) The timezone variable is a list of character strings which define your local timezone. Normally you will only need a single timezone, but sometimes there are several aliases for a given timezone e.g. MET and CET are synonymous. Currently only the first three characters of this string are checked against the timezone which cfengine manages to glean from the system. If a mismatch is detected a warning message is printed. cfengine does not attempt to configure the timezone. This feature works only as a reminder, since the timezone should really be set once and for all at the time the system is installed. On some systems you can set the timezone by editing a file, a procedure which you can automate with cfengine *Note editfiles::. The value of the `timezone' can be accessed by variable substitution in the usual way. It expands to the first item in your list. shellcommands: "echo ${timezone} | mail ${sysadm}"  File: cfengine-Reference.info, Node: TimeOut, Next: Verbose, Prev: timezone, Up: control 4.10.77 TimeOut --------------- TimeOut = ( 10 ) The default timeout for network connections is 10 seconds. This is too short on some routed networks. It is not permitted to set this variable smaller than 3 seconds or larger than 60 seconds. A timeout is generated by an `alarm' interrupt within an executing agent. This is constrasted with ExpireAfter, in which a second agent is required to interrupt the activity.  File: cfengine-Reference.info, Node: Verbose, Next: Warnings, Prev: TimeOut, Up: control 4.10.78 Verbose --------------- Verbose = ( ON/off ) This variable switches on the output level whereby cfengine reports everything it does during a run in great detail. Normally only urgent messages or clear errors are printed, *Note Inform::. This option is almost equivalent to using the `--verbose' of `-v' command-line options. The only difference is that system environment reporting information, which is printed prior to parsing, is not shown. To set this output level on selected hosts one writes: CLASSES:: Verbose = ( on ) For related more limited output, *Note Inform::.  File: cfengine-Reference.info, Node: Warnings, Next: warnnonuserfiles, Prev: Verbose, Up: control 4.10.79 Warnings ---------------- Warnings = ( ON/off ) This variable switches on the parser-output level whereby cfengine reports non-fatal warnings. This is equivalent to setting the command line switch `--no-warn', or `-w'. To set this output level on selected hosts one writes: CLASSES:: Warnings = ( on )  File: cfengine-Reference.info, Node: warnnonuserfiles, Next: warnnonownerfiles, Prev: Warnings, Up: control 4.10.80 WarnNonUserFiles ------------------------ If this parameter is set to true, cfengine will warn about files in spool directories which do not have a name belonging to a known user id. See also `DeleteNonUserFiles'.  File: cfengine-Reference.info, Node: warnnonownerfiles, Next: warnnonusermail, Prev: warnnonuserfiles, Up: control 4.10.81 WarnNonOwnerFiles ------------------------- If this parameter is set to true, cfengine will warn about files on mailservers whose names do not correspond to a known user name, but might be owned by a known user. SpoolDirectories = ( /var/spool/cron/crontabs ) WarnNonOwnerFiles = ( true ) See also `DeleteNonOwnerFiles'. This generalizes and succeeds `DeleteNonOwnerMail'.  File: cfengine-Reference.info, Node: warnnonusermail, Next: warnnonownermail, Prev: warnnonownerfiles, Up: control 4.10.82 WarnNonUserMail ----------------------- If this parameter is set to true, cfengine will warn about mail files on mailservers which do not have a name belonging to a known user id. This does not include lock files.  File: cfengine-Reference.info, Node: warnnonownermail, Prev: warnnonusermail, Up: control 4.10.83 WarnNonOwnerMail ------------------------ If this parameter is set to true, cfengine will warn about files on mailservers whose names do not correspond to a known user name, but might be owned by a known user.  File: cfengine-Reference.info, Node: classes, Next: copy, Prev: control, Up: Cfagent reference 4.11 classes ============ The `classes' keyword is an alias for `groups' as of version 1.4.0 of cfengine.  File: cfengine-Reference.info, Node: copy, Next: defaultroute, Prev: classes, Up: Cfagent reference 4.12 copy ========= Cfengine copies files between locally mounted filesystems and via the network from registered servers. The copy algorithm avoids race-conditions which can occur due to network and system latencies by copying first to a file called `FILE.cfnew' on the local filesystem, and then renaming this quickly into place. The aim of this roundabout procedure is to avoid situations where the direct rewriting of a file is interrupted midway, leaving a partially written file to be read by other processes. Cfengine attempts to preserve hard links to non-directory file-objects, but see the caution below. _Caution should be exercised in copying files which change rapidly in size. This can lead to file corruption, if the size changes during copying. Cfengine attempts to prevent this during remote copies._ The syntax summary is: copy: CLASS:: MASTER-FILE dest=DESTINATION-FILE mode=MODE owner=OWNER group=GROUP action=WARN/SILENT/FIX backup=true/FALSE/TIMESTAMP repository=BACKUP DIRECTORY stealth=TRUE/ON/FALSE/OFF checkroot=TRUE/ON/FALSE/OFF timestamps=preserve/keep symlink=PATTERN include=PATTERN exclude=PATTERN ignore=PATTERN filter=FILTERALIAS xdev=TRUE/ON/false/off recurse=NUMBER/INF/0 type=ctime/MTIME/CHECKSUM/SUM/BYTE/BINARY/ANY linktype=absolute/symbolic/RELATIVE/HARD/NONE/COPY typecheck=true/on/FALSE/OFF define=CLASS-LIST(,:.) elsedefine=CLASS-LIST(,:.) force=TRUE/ON/false/off forcedirs=TRUE/ON/false/off forceipv4=TRUE/ON/false/off size=SIZE LIMITS server=SERVER-HOST failover=CLASSES trustkey=TRUE/false secure=[deprecated] encrypt=TRUE/false verify=TRUE/false oldserver=TRUE/false purge=TRUE/false syslog=TRUE/ON/FALSE/OFF inform=TRUE/ON/FALSE/OFF audit=TRUE/FALSE findertype=MACOSX FINDER TYPE Note that the `$(this)' contains the name of the server used. This variable may be used in the source and destination strings in order to tailor the filename when downloading from multiple sources (see below). `dest' The destination file is the only obligatory item. This must be the name of an object which matches the type of the master object i.e. if the master is a plain file, the destination must also be the explicit name of a plain file. An implicit `copy file to directory' syntax is not allowed. Symbolic links are copied as symbolic links, plain files are copied as plain files and special files are copied as special files. The `recurse' option is required to copy the contents of subdirectories. If the destination file name is of the form `filename/..namedfork/rsrc', then it is assumed that you are copying the resource fork of a file to an HFS+ file system on OS X Jaguar. In the absence of the destination file being in this form (just dest=filename), cfengine will assume that you are working with the data fork of the file. See *note dest::. For a resource fork copy to properly work, the data fork must have already been copied. Ie the OS will not allow you to copy the resource fork for a file that does not exist. And, copying a data fork after the resource fork will overwrite the resource fork. So, order is important. Copy the data fork, first. Then, copy the resource fork. To split the data and resource forks of a file into two parts, open up a terminal. The following commands will copy MyFile 's data and resource forks into two separate files which can then be recombined by cfengine: cp MyFile MyFile-datafork cp MyFile/..namedfork/rsrc MyFile-rsrcfork `mode, owner, group' The file mode, owner and group of the images are specified as in the `files' function *Note files::. `action' The action may take the values `warn', `silent' or `fix'. The default action is `fix', i.e. copy files. If `warn' is specified, only a warning is issued about files which require updating. If `silent' is given, then cfengine will copy the files but not report the fact. `force' If set to `true', this option causes cfengine to copy files regardless of whether it is up to date. `forceipv4' If you are working on an ipv6 enabled pair of hosts, cfengine will normally select ipv6 for communication between them. If you wish to force the use of ipv4 for some reason, set this option to true. `forcedirs' If set to `true', this option causes files or links which block the creation of directories, during recursive copying, to be moved aside forcably. A single non-supressable warning is given when this occurs; the file is moved to filename`.cf-moved'. `backup' If the `backup' option is set to "false", cfengine will not make a backup copy of the file before copying. The default value is "true". If the option "timestamp" is chosen, a unique timestamp will be appended to the saved filename. `repository' This allows a local override of the `Repository' variable, on an item by item basis. If set to "off" or "none" it cancels the value of a global repository. Copy makes a literal image of the master file at the destination, checking whether the master is newer than the image. If the image needs updating it is copied. Existing files are saved by appending `.cfsaved' to the filename. `stealth' If set to `on' causes cfengine to preserve atime and mtime on the source files during _local_ file copies. File times cannot be preserved on remote copies. This option should normally only be used together with a checksum copy, since preserving atime and mtime implies changing ctime which will force continual copying. This is a weakness in the Unix file system. Ctime cannot be preserved. Before version 1.5.0, there was a typo which made this option active on many file copies. `checkroot' Default value `false', this option causes cfengine to check the permissions of the root directory during recursive directory copies. If not true, cfengine sets its own permissions on the root. `timestamps' If this is set to `preserve' or `keep', the times of the source files are inherited by the destination files during copying. This is like the `p' option of the `tar' command. `recurse' Specifies the depth of recursion when copying whole file-trees recursively. The value may be a number or the keyword `inf'. Cfengine crosses device boundaries or mounted filesystems when descending recursively through file trees. To prevent this it is simplest to specify a maximum level of recursion. `symlink' This option may be repeated a number of times to specify the names of files, or wildcards which match files which are to be symbolically linked instead of copied. A global list of patterns can also be defined in the control section of the program *Note linkcopies::. `ignore' This works like the global ignore directive but here you may provide a private list of ignorable directories and files. Unlike include, exclude this affects the way cfengine parses directory trees. `include' This option may be repeated a number of times to specify the names of files, or wildcards which match files which are to be included in a copy operation. Specifying one of these automatically excludes everything else except further include patterns. A global list of patterns can also be defined in the control section of the program. If the `purge' option is used in copying, then the `ignore' option has the effect of the excluding files from the purge, i.e. `ignore' means `keep' the named files. `exclude' This option may be repeated a number of times to specify the names of files, or wildcards which match files which are to be excluded from a copy operation. A global list of patterns can also be defined in the control section of the program `excludes' override `includes'. *Note excludelinks::. `xdev' Prevents cfengine from descending into file systems that are not on the same device as the root of the rescurion path. `type' Normally cfengine uses the ctime date-stamps on files to determine whether a file needs to be copied: a file is only copied if the master is newer than the copy or if the copy doesn't exist. If the type is set to `checksum' or `sum', then a secure MD5 checksum is used to determine whether the source and destination files are identical. If `byte' or `binary' is specified, a byte by byte comparison is initiated. An `mtime' comparison does not take into account changes of file permissions, only modifications to the contents of the files. `findertype' Sets the four letter file type code in an HFS+ file system on Mac OS X Jaguar. For example, the four letter code APPL indicates the file is an Application (and will be executed when double-clicked). The four letter code TEXT indicates the file is a text file and will be opened by the default text editor. If the file also has an extension (for example `.txt'), then if setting the finder type code, you should make sure your finder type code does not conflict with the file extension. Files both without extensions and finder type codes are mostly useless to OS X, so be sure to do one or the other! Also note that finder type codes should not be applied to the resource forks of files. `server' If you want to copy a file remotely from a server, you specify the name of the server here. This must be the name of a host which is running the `cfservd' daemon, and you must make sure that you have defined the variable `domain' in the control section of the `cfagent.conf' file. If you don't define a domain you will probably receive an error of the form `cfengine: Hey! cannot stat file'. If the server name is `localhost', cfengine will perform a local copy, without using a connection to cfservd. `failover' If a file copy fails due to an error, the classes in this assignment will become active, allowing failover rules to become active. `oldserver' If this is true, cfengine uses the old protocol specification for temporary compatibility with early version 2 alphas. `trustkey' This option defaults to 'no' or 'false'. If set to true, cfagent will accept a public key from a server whose public key is presently unknown to the agent, on trust. This option should be used to bootstrap public key transfer between hosts. Once a public key has been accepted, it will not be replaced automatically. Dated public keys must be removed by hand. `encrypt' Has an effect only when used in conjuction with copy from a remote file server. This causes cfengine to use encryption and one-time keys on transferred data. (This requires RSA keys to be installed on both client and server hosts, and provides strong authentication and encryption, using random session keys.) The preferred algorithm is Blowfish, with a 128 bit key. Generally speaking the only case in which this function makes sense is in transferring shadow password files. Encrypting the transfer of system binaries makes little sense. Note: the encryption keys required to get files from cfservd are those for the user under which cfservd is running (normally root). `verify' If verify is true, cfagent attempts to verify the integrity of a remote file transfer before the new file is installed. This takes time, since an MD5 computation and transaction must take place. `size' With this option you can specify that a file is only to be copied if the source file meets a size critereon. This could be used to avoid installing a corrupted file (the copying of an empty password file, for instance). Sizes are in bytes by default, but may also be quoted in kilobytes or megabytes using the notation: NUMBERbytes NUMBERkbytes NUMBERmbytes Only the first characters of these strings are significant, so they may be written however is convenient: e.g. `14kB', `14k', `14kilobytes' etc. Examples are: size=<400 # copy if file size is < 400 bytes size=400 # copy if file size is equal to 400 bytes size=>400 # copy if file size > 400 bytes `linktype' This option determines the type of link used to make links. This only applies if the file is linked rather than copied because it matches a pattern set by `symlink'. The default type is a direct symbolic link. The values `relative' or `absolute' may be used, but hard links may not be created in place of copied files, since hard links must normally reside on the same filesystem as their files, and it is assumed that most links will be between filesystems. If this value is set to `copy' or `none', symbolic links will be replaced by actual copies of the files they point to. Note that for directories, this option is ignored. `typecheck' Controls whether cfengine allows files of one type to overwrite files of another type, i.e. switches on/off errors if source and existing destination files do not match in type, e.g. if a file would overwrite a directory or link. The default is on for safety reasons. `define' This option is followed by a list of classes which are to be `switched on' if and only if the named file was copied. In multiple (recursive) copy operations the classes become defined if any of the files in the file tree were copied. This feature is useful for switching on other actions which are to be performed after the installation of key files (e.g. package installation scripts etc). `purge' If this option is set to true, cfengine will remove files in the destination directory which are not also in the source directory. This allows exact images of filesystems to be mantained. Note that if the copy command has includes or excludes or ignored files, cfengine will purge only those files on the client machine which are also on the server. Included files are not purged. This means that some files (such as system specific work files) can be excluded from copies without them being destroyed. Note that purging is disallowed if contact with a remote server fails. This means that local files will not be destroyed by a denial of service attack. _You should not use this option to synchronize NFS mounted file systems. If the NFS server goes down, cfengine cannot then tell the difference between a valid empty directory and a missing NFS file system. If you use purge, use a remote copy also._ If we specify purge, then the following options will also be set and cannot be altered: `forcedirs=true', `typecheck=false', since other defaults could be very destructive. * Menu: * copy example:: * hard links in copy:: * Too many open files::  File: cfengine-Reference.info, Node: copy example, Next: hard links in copy, Prev: copy, Up: copy 4.12.1 copy example ------------------- Example: copy: /local/etc/aliases dest=/etc/aliases m=644 o=root g=other /local/backup-etc dest=/etc solaris:: /local/etc/nsswitch.conf dest=/etc/nsswitch.conf In the first example, a global aliases file is copied from the master site file `/local/etc/aliases' to `/etc/aliases', setting the owner and protection as specified. The file gets installed if `/etc/aliases' doesn't exist and updated if `/local/etc/aliases' is newer than `/etc/aliases'. In the second example, `backup-etc' is a directory containing master configuration files (for instance, `services', `aliases', `passwd'...). Each of the files in `backup-etc' is installed or updated under `/etc'. Finally, a global `nsswitch.conf' file is kept up to date for Solaris systems. The `home' directive can be used as a destination, in which case cfengine will copy files to every user on the system. This is handy for distributing setup files and keeping them updated: copy: /local/masterfiles/.cshrc dest=home/.cshrc mode=0600 You can force the copying of files, regardless of the date stamps by setting the option `force=true' or `force=on'. The default is `force=false' or `force=off'. * Menu: * hard links in copy:: * Too many open files::  File: cfengine-Reference.info, Node: hard links in copy, Next: Too many open files, Prev: copy example, Up: copy 4.12.2 Hard links in copying ---------------------------- Hard links are not like symbolic links, they are not merely pointers to other files, but alternative names for the same file. The name of every file is a hard link, the first so to speak. You can add additional names which _really are_ the file, they are not just pointers. For the technically minded, they are not separate inodes, they are additional directory references to the same inode. When you perform a copy operation on multiple files, cfengine attempts to preserve hard links but this is a difficult task. Because a hard link just looks like an ordinary file (it cannot be distingiushed from the original, the way a symbolic link can) there is a danger that any copy operation will copy two hard links to the same file as two separate copies of the same file. The difference is that changes a hard-linked file propagate to the links, whereas two copies of a file are completely independent thereafter. In order to faithfully reproduce all hardlinks to all files, cfengine needs to examine every file on the same filesystem and check whether they have the same inode-number. This would be an enourmous overhead, so it is not done. Instead what happens is that cfengine keeps track of only the files which it is asked to examine, for each atomic copy-command, and makes a note of any repeated inodes within this restricted set. It does not try to go off, wandering around file systems looking to other files which might be hardlinks. To summarize, cfengine preserves hardlinks during copying, only within the scope of the present search. No backups are made of hard links, only of the first link or name of the file is backed up. This is a necessary precaution to avoid dangling references in the inode table. As a general rule, hard links are to be avoided because they are difficult to keep track of.  File: cfengine-Reference.info, Node: Too many open files, Prev: hard links in copy, Up: copy 4.12.3 Too many open files -------------------------- In long recursive copies, where you descend into many levels of diretories, you can quickly run out of file descriptors. The number of file descriptors is a resource which you can often set in the shell. It is a good idea to set this limit to a large number on a host which will be copying a lot of files. For instance, in the C shell you would write, limit descriptors 1024 Most systems should have adequate defaults for this parameter, but on some systems it appears to be set to a low value such as 64, which is not sufficient for large recursive tree searches.  File: cfengine-Reference.info, Node: defaultroute, Next: disks, Prev: copy, Up: Cfagent reference 4.13 defaultroute ================= Dynamical routing is not configurable in cfengine, but for machines with static routing tables it is useful to check that a default route is configured to point to the nearest gateway or router. The syntax for this statement is simply: defaultroute: CLASS:: my_gateway For example: defaultroute: most:: 129.240.22.1 rest:: small_gw no_default_route:: 192.168.1.1 Gateways and routers usually have internet address `aaa.bbb.ccc.1' -- i.e. the first address on the subnet. You may use the numerical form or a hostname for the gateway. The class `no_default_route' is defined if the current host does not have a currently defined default route, but specifies one in its configuration.  File: cfengine-Reference.info, Node: disks, Next: directories, Prev: defaultroute, Up: Cfagent reference 4.14 disks ========== This is a synonyn for `required', *Note required::. This action tests for the existence of a file or filesystem. It should be called after all NFS filesystems have been mounted. You may use the special variable `$(binserver)' here. disks: /FILESYSTEM freespace=SIZE-LIMIT define=CLASS-LIST(,:.) inform=TRUE log=TRUE audit=TRUE/FALSE scanarrivals=TRUE force=TRUE ifelapsed=MINS expireafter=MINS Files or filesystems which you consider to be essential to the operation of the system can be declared as `required'. Cfengine will warn if such files are not found, or if they look funny. Suppose you mount your filesystem `/usr/local' via NFS from some binary server. You might want to check that this filesystem is not empty! This might occur if the filesystem was actually _not_ mounted as expected, but failed for some reason. It is therefore not enough to check whether the directory `/usr/local' exists, one must also check whether it contains anything sensible. Cfengine uses two variables: `sensiblesize' and `sensiblecount' to figure out whether a file or filesystem is sensible or not. You can change the default values of these variables (which are 1000 and 2 respectively) in the `control' section. *Note control::. If a file is smaller than `sensiblesize' or does not exist, it fails the `required' test. If a directory does not exist, or contains fewer than `sensiblecount' files, then it also fails the test and a warning is issued. disks: any:: /$(site)/$(binserver)/local If you set the `freespace' variable to a value and set `inform=true', cfagent issues warnings when free disk space falls below this threshold. Any define-classes also become defined in this instance. (the default units are kilobytes, but you may specify bytes or megabytes), e.g. required: /site/host/home1 freespace=50mb define=dotidy /site/host/home2 freespace=10% define=dotidy then cfengine will warn when the filesystem concerned has less than this amount of free space. By adding a `define' tag, you can switch on any number of classes if this happens. This allows you to activate special measures for dealing with a filesystem which is in danger of becoming full. If the option `force=true' is used, cfengine will parse filesystems even on NFS mounted filesystems. Normally it does not make sense to check filesystems that are not native to the local host, but occasionally ne would like to force such a check in order to set a class, based on the result, for instance. If the `scanarrivals' option is set, the agent will recursively descend through the file system building a database of file modification times. This data is used for research purposes and will eventually be used to trigger classes that determine optimal times for backup of filesystem.  File: cfengine-Reference.info, Node: directories, Next: disable, Prev: disks, Up: Cfagent reference 4.15 directories ================ Directories declarations consist of a number of directories to be created. Directories and files may also be checked and created using the `touch' option in the `files' actions. *Note files::. The form of a declaration is: directories: CLASSES:: /DIRECTORY mode=MODE owner=UID group=GID rxdirs=TRUE/ON/FALSE/OFF define=CLASSLIST elsedefine=CLASSLIST syslog=TRUE/ON/FALSE/OFF inform=TRUE/ON/FALSE/OFF audit=TRUE/ON/FALSE/OFF ifelapsed=MINS expireafter=MINS For example directories: CLASS:: /usr/local/bin mode=755 owner=root group=wheel The form of the command is similar to that of `files' but this command is only used to create new directories. Valid options are `mode', `owner', `group' and `rxdirs'; these are described under `files' *Note files::. This interface is only for convenience. It is strictly a part of the `files' functionality and is performed together with other `files' actions at run time. The creation of a path will fail if one of the links in the path is a plain file or device node. A list of classes may optionally be defined here if a directory is created. If the `owner' value is set to the literal "LastNode", then the owner will be exchanged for the last node of the path. This allows the creation of home directories owned by users. control: homedirs = ( mark:simen:luke:aeleen ) directories: /home/$(listcontent) owner=LastNode  File: cfengine-Reference.info, Node: disable, Next: editfiles, Prev: directories, Up: Cfagent reference 4.16 disable ============ Disabling a file means renaming it so that it becomes harmless. This feature is useful if you want to prevent certain dangerous files from being around, but you don't want to delete them-- a deleted file cannot be examined later. The syntax is disable: CLASS:: /FILENAME dest=FILENAME type=PLAIN/FILE/LINK/LINKS rotate=EMPTY/TRUNCATE/NUMERICAL-VALUE size=NUMERICAL-VALUE define=CLASSLIST syslog=TRUE/ON/false/off inform=TRUE/ON/false/off audit=TRUE/ON/FALSE/OFF repository=DESTINATION DIRECTORY action=disable/WARN ifelapsed=MINS expireafter=MINS If a destination filename is specified, cfagent renames the source file to the destination, where possible (renaming across filesystems is not allowed). If no destination is given, cfagent renames a given file by appending the name of the file with the suffix `.cfdisabled'. Note that directories are only renamed if they have a specific destination specified. A typical example of a file you would probably want to disable would be the `/etc/hosts.equiv' file which is often found with the `+' symbol written in it, opening the system concerned to the entire NIS universe without password protection! Here is an example: disable: /etc/hosts.equiv /etc/nologin /usr/lib/sendmail.fc sun4:: /var/spool/cron/at.allow Hint: The last example disables a file which restricts access to the `at' utility. Such a command could be followed by a file action, *Note files::, files: some:: /var/spool/cron/at.allow =0644 N owner=root group=wheel touch which would create an empty security file `at.allow'. See also your system manual pages for the `at' command if you don't understand why this could be useful. Disabling a link deletes the link. If you wish you may use the optional syntax disable: /directory/name type=file to specify that a file object should only be disabled if it is a plain file. The optional element `type=' can take the values `plain', `file', `link' or `links'. If one of these is specified, cfengine checks the type and only disables the object if there is a match. This allows you to disable a file and replace it by a link to another file for instance. NOTE that if you regularly disable a file which then gets recreated by some process, the disabled file `FILENAME.cfdisabled' will be overwritten each time cfengine disables the file and therefore the contents of the original are lost each time. The `rotate' facility was created for just this contingency. The disable feature can be used to control the size of system log files, such as `/var/adm/messages' using a further option `rotate'. If the value rotate is set to 4, say, disable: FILENAME rotate=4 then cfengine renames the file concerned by appending `.1' to it and a new, empty file is created in its place with the same owner and permissions. The next time disable is executed `.1' is renamed to `.2' and the file is renamed `.1' and a new empty file is created with the same permissions. Cfengine continues to rotate the files like this keeping a maximum of four files. This is similar to the behaviour of syslog. If you simply want to empty the contents of a log file, without retaining a copy then you can use `rotate=empty' or `rotate=truncate'. For instance, to keep control of your World Wide Web server logs: disable: Sunday|Wednesday:: /usr/local/httpd/logs/access_log rotate=empty This keeps a running log which is emptied each Sunday and Wednesday. The `size=' option in disable allows you to carry out a disable operation only if the size of the file is less than, equal to or greater than some specified size. Sizes are in bytes by default, but may also be quoted in kilobytes or megabytes using the notation: NUMBERbytes NUMBERkbytes NUMBERmbytes Only the first characters of these strings are significant, so they may be written however is convenient: e.g. `14kB', `14k', `14kilobytes' etc. Examples are: size=<400 # disable if file size is < 400 bytes size=400 # disable if file size is equal to 400 bytes size=>400 # disable if file size > 400 bytes This options works with `rotate' or normal disabling; it is just an extra condition which must be satisfied. If a disable command results in action being taken by cfengine, an optional list of classes becomes can be switched on with the aid of a statement `define=CLASSLIST' in order to trigger knock-on actions. The `repository' declaration allows a local override of the `Repository' variable, on an item by item basis. If set to "off" or "none" it cancels the value of a global repository and leaves the disabled file in the same directory.  File: cfengine-Reference.info, Node: editfiles, Next: Editfiles on Binary Files, Prev: disable, Up: Cfagent reference 4.17 editfiles ============== Performs ascii (line-based) editing on text-files or limited binary editing of files. If editing a file which has hard links to it, be aware that editing the file will destroy the hard link references. This is also the case with shell commands. You should avoid hard links whenever possible. The form of an editing command is `editfiles' can also search directories recursively through directories and edit all files matching a pattern, using `Include', `Exclude', and `Ignore' (see Recursive File Sweeps in the tutorial). editfiles: CLASS:: { FILE-TO-BE-EDITED ACTION "QUOTED-STRING..." } { DIRECTORY-TO-BE-EDITED Recurse "inf" # iterated over all files Filter "filteralias" Include ".cshrc" Ignore "bin" Ignore ".netscape" ACTION "QUOTED-STRING..." } Here are some examples: editfiles: sun4:: { /etc/netmasks DeleteLinesContaining "255.255.254.0" AppendIfNoSuchLine "128.39 255.255.255.0" } PrintServers:: { /etc/hosts.lpd AppendIfNoSuchLine "tor" AppendIfNoSuchLine "odin" AppendIfNoSuchLine "borg" } The first of these affects the file `/etc/netmasks' on all SunOS 4 systems, deleting any lines containing the string "255.255.254.0" and Appending a single line to the file containing "128.39 255.255.255.0" if none exists already. The second affects only hosts in the class `PrintServers' and adds the names of three hosts: tor, odin and borg to the file `/etc/hosts.lpd' which specifies that they are allowed to connect to the printer services on any host in the class `PrintServers'. Note that single or double quotes may be used to enclose strings in cfengine. If you use single quotes, your strings may contain double quotes and vice-versa. Otherwise a double quoted string may not currently contain double quotes and likewise for single quoted strings. As of version 2.0.6 quoted strings may contain escaped quotes using `\"'. As of version 1.3.0, you can use the `home' directive in edit filenames, enabling you to edit files for every user on the system, provided they exist. For example, to edit every user's login files, you would write { home/.cshrc AppendIfNoSuchLine "setenv PRINTER default-printer" AppendIfNoSuchLine "set path = ( $path /new/directory )" } If a user does not possess the named file, cfengine just skips that user. A new file is not created. The meanings of the file-editing actions should be self-explanatory. Commands containing the word 'comment' are used to `comment out' certain lines in a file rather than deleting them. `Hash' implies a shell comment of the type # comment `Slash' implies a comment of the C++ type: // comment `Percent' implies a comment of the type: % comment More general comment types may be defined using the `SetCommentStart', `SetCommentEnd' and `CommentLinesMatching', `CommentLinesStarting' functions. A special group of editing commands is based on the POSIX Regular Expression package. These use regular expressions to search line by line through text and perform various editing functions. Searches are of two different types: "LineMatching" and "LineContaining". In the first case the regular expression must match the entire line exactly; in the latter, a substring is searched for in the file. Some of these commands are based on the concept of a file pointer. The pointer starts at line one of the file and can be reset by 'locating' a certain line, or by using the reset-pointer commands. The current position of the pointer is used by commands such as `InsertLine' to allow a flexible way of editing the middle of files. A simple decision mechanism is incorporated to allow certain editing actions to be excluded. For instance, to insert a number of lines in a file once only, you could write: { FILE LocateLineMatching "INSERT POINT..." IncrementPointer "1" BeginGroupIfNoMatch "# cfengine - 2/Jan/95" IncrementPointer "-1" InsertLine "# cfengine - 2/Jan/95" InsertLine "/local/bin/start-xdm" DefineInGroup "AddedXDM" EndGroup } Since the first inserted line matches the predicate on subsequent calls, the grouped lines will only be carried out once. When the grouped lines are run, the `AddedXDM' class will be activated for use by a later part of the script. The full list of editing actions is given below in alphabetical order. Note that some commands refer to regular expressions and some refer to 'literal strings' (i.e. any string which is not a regular expression). Variable substitution is performed on all strings. Be aware that symbols such as `.', `*' and so on are meta-characters in regular expressions and a backslash must be used to make them literal. The regular expression matching functions are POSIX extended regular expressions. *Note Regular expressions: (cfengine-Tutorial)Regular expressions. Editfile caution. It is suggested that you use these editing functions with caution. Although all possible safeguards have been incorporated into them, it is still possible through carelessness to do damage to important files on your system. Always test editing programs carefully before committing them to your global site configuration. * Menu: * AbortAtLineMatching:: * Append:: * AppendIfNoLineMatching:: * AppendIfNoSuchLine:: * AppendIfNoSuchLinesFromFile:: * AppendToLineIfNotContains:: * Audit:: * AutoCreate:: * AutomountDirectResources:: * Backup in editfiles:: * BeginGroupIfDefined:: * BeginGroupIfNotDefined:: * BeginGroupIfFileExists:: * BeginGroupIfFileIsNewer:: * BeginGroupIfLineContaining:: * BeginGroupIfLineMatching:: * BeginGroupIfMatch:: * BeginGroupIfNoLineContaining:: * BeginGroupIfNoLineMatching:: * BeginGroupIfNoMatch:: * BeginGroupIfNoSuchLine:: * BreakIfLineMatches:: * CatchAbort:: * CommentLinesMatching:: * CommentLinesStarting:: * CommentNLines:: * CommentToLineMatching:: * DefineClasses:: * DefineInGroup:: * DeleteLinesAfterThisMatching:: * DeleteLinesContaining:: * DeleteLinesMatching:: * DeleteLinesStarting:: * DeleteLinesNotContaining:: * DeleteLinesNotMatchingFileItems:: * DeleteLinesNotStartingFileItems:: * DeleteNLines:: * DeleteToLineMatching:: * EditMode (binary):: * EditSplit:: * EmptyEntireFilePlease:: * ElseDefineClasses:: * EndGroup:: * EndLoop:: * ExpandVariables:: * ExpireAfter editfiles:: * Filter:: * FixEndOfLine:: * ForEachLineIn:: * GotoLastLine:: * HashCommentLinesContaining:: * HashCommentLinesMatching:: * HashCommentLinesStarting:: * IfElapsed (editing):: * IncrementPointer:: * Inform (editing):: * InsertFile:: * InsertLine:: * LocateLineMatching:: * PercentCommentLinesContaining:: * PercentCommentLinesMatching:: * PercentCommentLinesStarting:: * Prepend (editing):: * PrependIfNoLineMatching:: * PrependIfNoSuchLine:: * Recurse (editing):: * ReplaceLineWith:: * ReplaceAll With:: * ReplaceFirst:: * ReplaceLinesMatchingField:: * Repository:: * ResetSearch:: * RunScript:: * RunScriptIfLineMatching:: * RunScriptIfNoLineMatching:: * SetCommentStart:: * SetCommentEnd:: * SetLine:: * SetScript:: * SlashCommentLinesContaining:: * SlashCommentLinesMatching:: * SlashCommentLinesStarting:: * SplitOn:: * SysLog:: * Umask:: * UnCommentLinesContaining:: * UnCommentLinesMatching:: * UnCommentsNLines:: * UnCommentToLineMatching:: * UnsetAbort:: * UseShell:: * WarnIfFileMissing:: * WarnIfLineContaining:: * WarnIfLineMatching:: * WarnIfLineStarting:: * WarnIfNoLineContaining:: * WarnIfNoLineMatching:: * WarnIfNoLineStarting:: * WarnIfNoSuchLine::  File: cfengine-Reference.info, Node: AbortAtLineMatching, Next: Append, Prev: editfiles, Up: editfiles 4.17.1 AbortAtLineMatching -------------------------- AbortAtLineMatching QUOTED-REGEX This command sets the value of a regular expression. In all editing operations (except `FixEndOfLine' and `GotoLastLine') which involve multiple replacements and searches, this expression marks a boundary beyond which cfengine will cease to look any further. In other words, if cfengine encounters a line matching this regular expression, it aborts the current action. BE CAREFUL with this feature: once set, the string remains set for the remainder of the current file. It might therefore interact in unsuspected ways with other search parameters. Editing actions are always aborted as soon as the abort expression is matched. Use `UnsetAbort' to unset the feature.  File: cfengine-Reference.info, Node: Append, Next: AppendIfNoLineMatching, Prev: AbortAtLineMatching, Up: editfiles 4.17.2 Append ------------- Append QUOTED-REGEX Add a line containing the quoted string to the end of the file. This should be used in conjunction with the decision structures `BeginGroupIfNoLineMatching' and `BreakIfLineMatches'.  File: cfengine-Reference.info, Node: AppendIfNoLineMatching, Next: AppendIfNoSuchLine, Prev: Append, Up: editfiles 4.17.3 AppendIfNoLineMatching ----------------------------- AppendIfNoLineMatching QUOTED-REGEX/ ``ThisLine'' A new version of the older `AppendIfNoSuchLine' which uses a regular expression instead of a literal string. The line which gets appended must be set previously using `SetLine'. If ```ThisLine''' is given as the argument, the current value of then line buffer is assumed. This allows constructions for merging files on a convergent line-by-line basis: editfiles: { /tmp/bla ForEachLineIn "/tmp/in" AppendIfNoLineMatching "ThisLine" EndLoop }  File: cfengine-Reference.info, Node: AppendIfNoSuchLine, Next: AppendIfNoSuchLinesFromFile, Prev: AppendIfNoLineMatching, Up: editfiles 4.17.4 AppendIfNoSuchLine ------------------------- AppendIfNoSuchLine QUOTED-STRING Add a line containing the quoted string to the end of the file if the file doesn't contain the exact line already.  File: cfengine-Reference.info, Node: AppendIfNoSuchLinesFromFile, Next: AppendToLineIfNotContains, Prev: AppendIfNoSuchLine, Up: editfiles 4.17.5 AppendIfNoSuchLinesFromFile ---------------------------------- AppendIfNoSuchLinesFromFile FILENAME For each line in the named file, call AppendIfNoSuchLine. This adds lines containing the strings listed in the named file to the end of the current file if the file doesn't contain the exact line already.  File: cfengine-Reference.info, Node: AppendToLineIfNotContains, Next: Audit, Prev: AppendIfNoSuchLinesFromFile, Up: editfiles 4.17.6 AppendToLineIfNotContains -------------------------------- AppendToLineIfNotContains QUOTED-STRING This commands looks for an exact match of the quoted string in the current line. If the quoted string is not contained in the line, it is appended. This may be used for adding entries to a list.  File: cfengine-Reference.info, Node: Audit, Next: AutoCreate, Prev: AppendToLineIfNotContains, Up: editfiles 4.17.7 Audit in editfiles ------------------------- Audit TRUE/FALSE Local decision about whether this edit stanza will be audited. Requires auditing to be on globally for this to have an effect.  File: cfengine-Reference.info, Node: AutoCreate, Next: AutomountDirectResources, Prev: Audit, Up: editfiles 4.17.8 AutoCreate ----------------- If this command is listed anywhere in the file action list, cfengine will create the named file if it doesn't exist. Normally cfengine issues an error if the named file does not exist, but if this is set, notification of the file's absence is only in verbose output. New files are created with mode 644 (see also Umask), read access for everyone and write access for the cfengine user (normally root). Note that if you set this, BeginGroupIfFileIsNewer will always be true.  File: cfengine-Reference.info, Node: AutomountDirectResources, Next: Backup in editfiles, Prev: AutoCreate, Up: editfiles 4.17.9 AutomountDirectResources ------------------------------- AutomountDirectResources QUOTED-STRING This command is designed to assist with automounter configuration for users wishing to use the automounter for NFS filesystems, but still use the cfengine mount model. Applied to the current file, it is equivalent to saying: for each of the mountable resources in the list *Note mountables::, append if not found a line for a direct automount map command, to the current file. The string which follows can be used to specify any special mount options e.g. ```-nosuid''' for non setuid mounting (of all the mountables). Note that this is added to the current file and not to a file named `/etc/auto_direct'.  File: cfengine-Reference.info, Node: Backup in editfiles, Next: BeginGroupIfDefined, Prev: AutomountDirectResources, Up: editfiles 4.17.10 Backup in editfiles --------------------------- Backup QUOTED-STRING Set to true or false, on or off to set backup policy for this file. Default is on. The default is to produce time-stamped backups of files; this may be coded explicitly by setting to "timestamp" or "stamp". If set to "false" or "off", no backup is kept of the edited file. If the value is set to "single" or "one" then only the last version of the file is kept, overwriting any previously saved versions. See *note copybackup::. Backup "single"  File: cfengine-Reference.info, Node: BeginGroupIfDefined, Next: BeginGroupIfNotDefined, Prev: Backup in editfiles, Up: editfiles 4.17.11 BeginGroupIfDefined --------------------------- BeginGroupIfDefined QUOTED-STRING The lines following, up to the first `EndGroup' are executed if the quoted class is defined. Edit groups may be nested.  File: cfengine-Reference.info, Node: BeginGroupIfNotDefined, Next: BeginGroupIfFileExists, Prev: BeginGroupIfDefined, Up: editfiles 4.17.12 BeginGroupIfNotDefined ------------------------------ BeginGroupIfNotDefined QUOTED-STRING The lines following, up to the first `EndGroup' are executed if the quoted class is not defined. Edit groups may be nested.  File: cfengine-Reference.info, Node: BeginGroupIfFileExists, Next: BeginGroupIfFileIsNewer, Prev: BeginGroupIfNotDefined, Up: editfiles 4.17.13 BeginGroupIfFileExists ------------------------------ BeginGroupIfFileExists QUOTED-STRING The lines following, up to the first `EndGroup' are executed if the quoted filename exists (can be statted). Files which are not readable by the running process are for all intents and purposes non-existent. Edit groups may be nested.  File: cfengine-Reference.info, Node: BeginGroupIfFileIsNewer, Next: BeginGroupIfLineContaining, Prev: BeginGroupIfFileExists, Up: editfiles 4.17.14 BeginGroupIfFileIsNewer ------------------------------- BeginGroupIfFileIsNewer QUOTED-STRING The lines following, up to the first `EndGroup' are executed if the quoted filename is newer than the file being edited. Edit groups may be nested.  File: cfengine-Reference.info, Node: BeginGroupIfLineContaining, Next: BeginGroupIfLineMatching, Prev: BeginGroupIfFileIsNewer, Up: editfiles 4.17.15 BeginGroupIfLineContaining ---------------------------------- BeginGroupIfLineContaining QUOTED-STRING The lines following, up to the first `EndGroup' are executed if the quoted string appears in any line in the file. Edit groups may be nested.  File: cfengine-Reference.info, Node: BeginGroupIfLineMatching, Next: BeginGroupIfMatch, Prev: BeginGroupIfLineContaining, Up: editfiles 4.17.16 BeginGroupIfLineMatching -------------------------------- BeginGroupIfLineMatching QUOTED-REGEX The lines following, up to the first `EndGroup' are executed if the quoted regular expression matches any line in the file. Edit groups may be nested.  File: cfengine-Reference.info, Node: BeginGroupIfMatch, Next: BeginGroupIfNoLineContaining, Prev: BeginGroupIfLineMatching, Up: editfiles 4.17.17 BeginGroupIfMatch ------------------------- BeginGroupIfMatch QUOTED-REGEX The lines following, up to the first `EndGroup' are executed if the quoted regular expression matches the current line. Edit groups may be nested.  File: cfengine-Reference.info, Node: BeginGroupIfNoLineContaining, Next: BeginGroupIfNoLineMatching, Prev: BeginGroupIfMatch, Up: editfiles 4.17.18 BeginGroupIfNoLineContaining ------------------------------------ BeginGroupIfNoLineContaining QUOTED-STRING The lines following, up to the first `EndGroup' are executed if the quoted string does not appear in any line in the file. Edit groups may be nested.  File: cfengine-Reference.info, Node: BeginGroupIfNoLineMatching, Next: BeginGroupIfNoMatch, Prev: BeginGroupIfNoLineContaining, Up: editfiles 4.17.19 BeginGroupIfNoLineMatching ---------------------------------- BeginGroupIfNoLineMatching QUOTED-REGEX The lines following, up to the first `EndGroup' are executed if the quoted regular expression does not match any line in the file. Edit groups may be nested.  File: cfengine-Reference.info, Node: BeginGroupIfNoMatch, Next: BeginGroupIfNoSuchLine, Prev: BeginGroupIfNoLineMatching, Up: editfiles 4.17.20 BeginGroupIfNoMatch --------------------------- BeginGroupIfNoMatch QUOTED-REGEX The lines following, up to the first `EndGroup' are executed if the quoted regular expression does not match the current line. Edit groups may be nested.  File: cfengine-Reference.info, Node: BeginGroupIfNoSuchLine, Next: BreakIfLineMatches, Prev: BeginGroupIfNoMatch, Up: editfiles 4.17.21 BeginGroupIfNoSuchLine ------------------------------ BeginGroupIfNoSuchLine QUOTED-STRING The lines following, up to the first `EndGroup' are executed if the quoted literal string does not match any line in the file. Edit groups may be nested.  File: cfengine-Reference.info, Node: BreakIfLineMatches, Next: CatchAbort, Prev: BeginGroupIfNoSuchLine, Up: editfiles 4.17.22 BreakIfLineMatches -------------------------- BreakIfLineMatches QUOTED-REGEX Terminates further editing of the current file if the current line matches the quoted regular expression.  File: cfengine-Reference.info, Node: CatchAbort, Next: CommentLinesMatching, Prev: BreakIfLineMatches, Up: editfiles 4.17.23 CatchAbort ------------------ Edit actions which abort on failure (such as `LocateLineMatching') will jump to the first instance of this marker instead of completely aborting an edit if this keyword occurs in an editing script. You can catch the exceptions thrown by the following commands: `CommentNLines',`CommentToLineMatching',`DeleteNLines',`DeleteToLineMatching', `HashCommentToLineMatching',`IncrementPointer', `LocateLineMatching',`PercentCommentToLineMatching', `RunScriptIf(No)LineMatching',`UnCommentNLines'.  File: cfengine-Reference.info, Node: CommentLinesMatching, Next: CommentLinesStarting, Prev: CatchAbort, Up: editfiles 4.17.24 CommentLinesMatching ---------------------------- CommentLinesMatching QUOTED-REGEX Use the current value of the comment delimiters set using `SetCommentStart' and `SetCommentEnd' to comment out lines matching the given regular expression in quotes.  File: cfengine-Reference.info, Node: CommentLinesStarting, Next: CommentNLines, Prev: CommentLinesMatching, Up: editfiles 4.17.25 CommentLinesStarting ---------------------------- CommentLinesStarting QUOTED-STRING Use the current value of the comment delimiters set using `SetCommentStart' and `SetCommentEnd' to comment out lines starting with the quoted literal string.  File: cfengine-Reference.info, Node: CommentNLines, Next: CommentToLineMatching, Prev: CommentLinesStarting, Up: editfiles 4.17.26 CommentNLines --------------------- CommentNLines QUOTED-STRING Comments up to N lines from the current file, starting from the location of the current line pointer. If the end of the file is reached and less than N lines are deleted, a warning is issued, but editing continues. The current value of the comment delimiters is used to determine the method of commenting, (see `SetCommentStart'). After the operation the pointer points to the line after the commented lines.  File: cfengine-Reference.info, Node: CommentToLineMatching, Next: DefineClasses, Prev: CommentNLines, Up: editfiles 4.17.27 CommentToLineMatching ----------------------------- CommentToLineMatching QUOTED-REGEX Use the current value of the comment delimiters set using `SetCommentStart' and `SetCommentEnd' to comment out lines from the current position in a file to a line matching the given regular expression in quotes.  File: cfengine-Reference.info, Node: DefineClasses, Next: DefineInGroup, Prev: CommentToLineMatching, Up: editfiles 4.17.28 DefineClasses --------------------- DefineClasses "CLASS1:CLASS2:..." Activate the following colon, comma or dot-separated list of classes if and only if the file is edited.  File: cfengine-Reference.info, Node: DefineInGroup, Next: DeleteLinesAfterThisMatching, Prev: DefineClasses, Up: editfiles 4.17.29 DefineInGroup --------------------- DefineInGroup "CLASS1:CLASS2:..." Activate the following colon, comma or dot-separated list of classes if the edit group is entered. This can be combined with other classes to identify what particular edits took place. Use DefineInGroup if you want to define a class or list of classes conditional on entry to a BeginGroup ... EngGroup block. For example, editfiles: { /etc/inetd.conf BeginGroupIfNoSuchLine "$(myservice1)" Append "$(myservice1)" DefineInGroup "myservice1_added" EndGroup BeginGroupIfNoSuchLine "$(myservice2)" Append "$(myservice2)" DefineInGroup "myservice2_added" EndGroup } This will define service_added and service_added_another_way if either line is added, but additionally myservice1_added if myservice1 was added and likewise for myservice2_added. Activate the following colon, comma or dot-separated list of classes if execution reaches the `BeginGroup' ... `EndGroup' section(s) containing this command. If you think you want to put DefineClasses within a `BeginGroup' ... `EndGroup' section, you actually want this.  File: cfengine-Reference.info, Node: DeleteLinesAfterThisMatching, Next: DeleteLinesContaining, Prev: DefineInGroup, Up: editfiles 4.17.30 DeleteLinesAfterThisMatching ------------------------------------ DeleteLinesAfterThisMatching QUOTED-REGEX Delete lines after the current position which match the quoted expression.  File: cfengine-Reference.info, Node: DeleteLinesContaining, Next: DeleteLinesMatching, Prev: DeleteLinesAfterThisMatching, Up: editfiles 4.17.31 DeleteLinesContaining/DeleteLinesNotContaining ------------------------------------------------------ DeleteLinesContaining QUOTED-STRING DeleteLinesNotContaining QUOTED-STRING Delete all lines (not) containing the exact string quoted.  File: cfengine-Reference.info, Node: DeleteLinesMatching, Next: DeleteLinesStarting, Prev: DeleteLinesContaining, Up: editfiles 4.17.32 DeleteLinesMatching/DeleteLinesNotMatching -------------------------------------------------- DeleteLinesMatching QUOTED-REGEX DeleteLinesNotMatching QUOTED-REGEX Delete all lines (not) fully matching the tied quoted regular expression.  File: cfengine-Reference.info, Node: DeleteLinesStarting, Next: DeleteLinesNotContaining, Prev: DeleteLinesMatching, Up: editfiles 4.17.33 DeleteLinesStarting/DeleteLinesNotStarting -------------------------------------------------- DeleteLinesStarting QUOTED-STRING DeleteLinesNotStarting QUOTED-STRING Delete all lines (not) beginning with the exact string quoted.  File: cfengine-Reference.info, Node: DeleteLinesNotContaining, Next: DeleteLinesNotMatchingFileItems, Prev: DeleteLinesStarting, Up: editfiles 4.17.34 DeleteLinesNotContainingFileItems ----------------------------------------- DeleteLinesNotContainingFileItems FILENAME Delete lines in the file that do not contain the any of the substrings in the file.  File: cfengine-Reference.info, Node: DeleteLinesNotMatchingFileItems, Next: DeleteLinesNotStartingFileItems, Prev: DeleteLinesNotContaining, Up: editfiles 4.17.35 DeleteLinesNotMatchingFileItems --------------------------------------- DeleteLinesNotMatchingFileItems FILENAME Delete lines in the file that do not match the any of the regular expressions in the file.  File: cfengine-Reference.info, Node: DeleteLinesNotStartingFileItems, Next: DeleteNLines, Prev: DeleteLinesNotMatchingFileItems, Up: editfiles 4.17.36 DeleteLinesNotStartingFileItems --------------------------------------- DeleteLinesNotStartingFileItems FILENAME Delete lines in the file that do not start with any of the substrings in the file.  File: cfengine-Reference.info, Node: DeleteNLines, Next: DeleteToLineMatching, Prev: DeleteLinesNotStartingFileItems, Up: editfiles 4.17.37 DeleteNLines -------------------- DeleteNLines QUOTED-STRING Deletes up to N lines from the current file, starting from the location of the current line pointer. If the end of the file is reached and less than N lines are deleted, a warning is issued, but editing continues.  File: cfengine-Reference.info, Node: DeleteToLineMatching, Next: EditMode (binary), Prev: DeleteNLines, Up: editfiles 4.17.38 DeleteToLineMatching ---------------------------- DeleteToLineMatching QUOTED-REGEX Delete lines from the current position, up to but not including a line matching the regular expression in the quoted string. If no line matches the given expression, a warning is only printed in verbose mode, but all edits are immediately abandoned.  File: cfengine-Reference.info, Node: EditMode (binary), Next: EditSplit, Prev: DeleteToLineMatching, Up: editfiles 4.17.39 EditMode and binary editing ----------------------------------- If set to binary, the file will be edited as if it were a non-ASCII file. See discussion below. EditMode "Binary"  File: cfengine-Reference.info, Node: EditSplit, Next: EmptyEntireFilePlease, Prev: EditMode (binary), Up: editfiles 4.17.40 EditSplit ----------------- Editfiles treats lists as private interpretations, since iteration over lists could lead to unpredictable behaviour if text variables accidentally contain the list separator. The control option `Split' therefore has no effect on editfiles. This definition makes list expansion work in editfiles. EditSplit "," Be careful not to confuse this with the `SplitOn' character. editfiles: { /tmp/bla1 EditSplit "!" AppendIfNoSuchLine "alpha1!beta1" EditSplit ":" AppendIfNoSuchLine "alpha2!beta2" EditSplit "@" AppendIfNoSuchLine "alpha3@beta3" } { /tmp/bla2 AppendIfNoSuchLine "new1@new2" }  File: cfengine-Reference.info, Node: EmptyEntireFilePlease, Next: ElseDefineClasses, Prev: EditSplit, Up: editfiles 4.17.41 EmptyEntireFilePlease ----------------------------- Deletes all lines from the current file.  File: cfengine-Reference.info, Node: ElseDefineClasses, Next: EndGroup, Prev: EmptyEntireFilePlease, Up: editfiles 4.17.42 ElseDefineClasses ------------------------- See `DefineClasses'  File: cfengine-Reference.info, Node: EndGroup, Next: EndLoop, Prev: ElseDefineClasses, Up: editfiles 4.17.43 EndGroup ---------------- Terminates a begin-end conditional structure.  File: cfengine-Reference.info, Node: EndLoop, Next: ExpandVariables, Prev: EndGroup, Up: editfiles 4.17.44 EndLoop --------------- Terminates a loop. See `ForEachLineIn'  File: cfengine-Reference.info, Node: ExpandVariables, Next: ExpireAfter editfiles, Prev: EndLoop, Up: editfiles 4.17.45 ExpandVariables ----------------------- This causes cfengine to run through the contents of the file and expand any recognisable editfile strings in the file, if they are defined within the scope of the cfagent script. This gives cfengine an m4 like capacity.  File: cfengine-Reference.info, Node: ExpireAfter editfiles, Next: Filter, Prev: ExpandVariables, Up: editfiles 4.17.46 ExpireAfter editfiles ----------------------------- ExpireAfter MINS  File: cfengine-Reference.info, Node: Filter, Next: FixEndOfLine, Prev: ExpireAfter editfiles, Up: editfiles 4.17.47 Filter -------------- Name a fiter for pruning file searches. Filter FILTERALIAS  File: cfengine-Reference.info, Node: FixEndOfLine, Next: ForEachLineIn, Prev: Filter, Up: editfiles 4.17.48 FixEndOfLine -------------------- The quoted string which follows may be either `dos' or `Unix' to fix the end of line character conventions to match these systems. This command should be executed last of all, since cfengine appends new lines with the conventions of the system on which is was complied during edit operations.  File: cfengine-Reference.info, Node: ForEachLineIn, Next: GotoLastLine, Prev: FixEndOfLine, Up: editfiles 4.17.49 ForEachLineIn QUOTED-FILENAME ------------------------------------- ForEachLineIn QUOTED-FILENAME This marks the beginning of a for-loop which reads successive lines from a named file. The result is like using `SetLine' for each line in the file. Nested loops are not permitted.  File: cfengine-Reference.info, Node: GotoLastLine, Next: HashCommentLinesContaining, Prev: ForEachLineIn, Up: editfiles 4.17.50 GotoLastLine -------------------- Moves the file pointer to the last line in the current file.  File: cfengine-Reference.info, Node: HashCommentLinesContaining, Next: HashCommentLinesMatching, Prev: GotoLastLine, Up: editfiles 4.17.51 HashCommentLinesContaining ---------------------------------- Add a `#' to the start of any line containing the quoted string. HashCommentLinesContaining QUOTED-STRING  File: cfengine-Reference.info, Node: HashCommentLinesMatching, Next: HashCommentLinesStarting, Prev: HashCommentLinesContaining, Up: editfiles 4.17.52 HashCommentLinesMatching -------------------------------- Add a `#' to the start of any line exactly matching the quoted regular expression. HashCommentLinesMatching QUOTED-REGEX  File: cfengine-Reference.info, Node: HashCommentLinesStarting, Next: IfElapsed (editing), Prev: HashCommentLinesMatching, Up: editfiles 4.17.53 HashCommentLinesStarting -------------------------------- Add a `#' to the start of any line starting with the quoted string. HashCommentLinesStarting QUOTED-STRING  File: cfengine-Reference.info, Node: IfElapsed (editing), Next: IncrementPointer, Prev: HashCommentLinesStarting, Up: editfiles 4.17.54 IfElapsed ----------------- ExpireAfter MINS  File: cfengine-Reference.info, Node: IncrementPointer, Next: Inform (editing), Prev: IfElapsed (editing), Up: editfiles 4.17.55 IncrementPointer QUOTED-NUMBER -------------------------------------- IncrementPointer QUOTED-NUMBER Increments the value (in lines) of the file pointer by the number of lines specified in the quoted string (as a denary number). e.g. ```4'''. Negative values are equivalent to decrementing the pointer. If a request is made to increment/decrement outside of the file boundaries the pointer `bumps' into the boundary and remains there, i.e. either at start of file or end of file.  File: cfengine-Reference.info, Node: Inform (editing), Next: InsertFile, Prev: IncrementPointer, Up: editfiles 4.17.56 Inform editfiles ------------------------ Inform QUOTED-STRING Set to `true' or `false', `on' or `off' to set the inform level for this file. Default is `off'. Note that, owing to the way that cfengine re-uses code, this feature does not work very well. Detailed messages are not available, only a summary of whether or not the file changed.  File: cfengine-Reference.info, Node: InsertFile, Next: InsertLine, Prev: Inform (editing), Up: editfiles 4.17.57 InsertFile ------------------ InsertFile QUOTED-STRING Inserts the named file after the current line position in the file. This should be used in conjunction with a begin-end construction in order to avoid including the file every time cfengine is run. If the file does not exist, or cannot be opened, there is only a warning issued in verbose mode. Note if the file is empty, or if the current line pointer is not set, the file is inserted at the start of the file.  File: cfengine-Reference.info, Node: InsertLine, Next: LocateLineMatching, Prev: InsertFile, Up: editfiles 4.17.58 InsertLine ------------------ InsertFile QUOTED-STRING Inserts the quoted string as a line after the current line pointer in the file. After the insert, the line pointer is incremented by one so that subsequent inserted lines are placed after the first. This should probably be used in conjunction with the conditional begin-end tests to avoid lines being inserted on every run.  File: cfengine-Reference.info, Node: LocateLineMatching, Next: PercentCommentLinesContaining, Prev: InsertLine, Up: editfiles 4.17.59 LocateLineMatching -------------------------- LocateLineMatching QUOTED-REGEX Moves the current line pointer to the line matching the quoted regular expression. If there is no match, a warning is only issued in verbose mode, but all editing is immediately aborted. See also `WarnIfNoLineMatching' so that you can get an explicit warning, even out of verbose mode.  File: cfengine-Reference.info, Node: PercentCommentLinesContaining, Next: PercentCommentLinesMatching, Prev: LocateLineMatching, Up: editfiles 4.17.60 PercentCommentLinesContaining ------------------------------------- PercentCommentLinesContaining QUOTED-STRING Add a `%' to the start of any line containing the quoted string.  File: cfengine-Reference.info, Node: PercentCommentLinesMatching, Next: PercentCommentLinesStarting, Prev: PercentCommentLinesContaining, Up: editfiles 4.17.61 PercentCommentLinesMatching ----------------------------------- PercentCommentLinesMatching QUOTED-REGEX Add a `%' to the start of any line exactly matching the quoted regular.  File: cfengine-Reference.info, Node: PercentCommentLinesStarting, Next: Prepend (editing), Prev: PercentCommentLinesMatching, Up: editfiles 4.17.62 PercentCommentLinesStarting ----------------------------------- PercentCommentLinesStarting QUOTED-STRING Add a `%' to the start of any line starting with the quoted string.  File: cfengine-Reference.info, Node: Prepend (editing), Next: PrependIfNoLineMatching, Prev: PercentCommentLinesStarting, Up: editfiles 4.17.63 Prepend --------------- Prepend QUOTED-STRING Add a line containing the quoted string to the start of the file. This should be used in conjunction with the decision structures `BeginGroupIfNoLineMatching' and `BreakIfLineMatches'.  File: cfengine-Reference.info, Node: PrependIfNoLineMatching, Next: PrependIfNoSuchLine, Prev: Prepend (editing), Up: editfiles 4.17.64 PrependIfNoLineMatching ------------------------------- PrependIfNoLineMatching QUOTED-REGEX A new version of the older `PrependIfNoSuchLine' with uses a regular expression instead of a literal string. The string prepended is the one set using `SetLine'.  File: cfengine-Reference.info, Node: PrependIfNoSuchLine, Next: Recurse (editing), Prev: PrependIfNoLineMatching, Up: editfiles 4.17.65 PrependIfNoSuchLine --------------------------- PrependIfNoSuchLine QUOTED-STRING Add a line containing the quoted string to the start of the file if the file doesn't contain the exact line already.  File: cfengine-Reference.info, Node: Recurse (editing), Next: ReplaceLineWith, Prev: PrependIfNoSuchLine, Up: editfiles 4.17.66 Recurse --------------- Recurse DIGIT/INF For recursive descents when editing whole file trees.  File: cfengine-Reference.info, Node: ReplaceLineWith, Next: ReplaceAll With, Prev: Recurse (editing), Up: editfiles 4.17.67 ReplaceLineWith ----------------------- ReplaceLineWith QUOTED-STRING Replace the line at the current position with the text in the quoted string. The file pointer remains pointing to this line after the change.  File: cfengine-Reference.info, Node: ReplaceAll With, Next: ReplaceFirst, Prev: ReplaceLineWith, Up: editfiles 4.17.68 ReplaceAll/With ----------------------- ReplaceAll QUOTED-REGEX With QUOTED-STRING Replace all instances of strings matching the regular expression in the first quotes with the exact string in the second set of quotes, throughout the current file. Note that cfengine matches on a left to right basis, with the first match taking precedence, so if your regular expression matches text ambiguously it is the first occurrence which is replaced. For example, if you replace `cf.*' with `CFENGINE' and cfengine encounters a line `hello cfengine cfengine', then this will be replaced with `hello CFENGINE' even though two possible strings match the regular expression. On the other hand if the expression is not ambiguous, say replacing `cfengine' with `CFENGINE', then the result would be `hello CFENGINE CFENGINE'.  File: cfengine-Reference.info, Node: ReplaceFirst, Next: ReplaceLinesMatchingField, Prev: ReplaceAll With, Up: editfiles 4.17.69 ReplaceFirst/With ------------------------- ReplaceFirst QUOTED-REGEX With QUOTED-STRING For each line of the current file, replace the first string matching the regular expression in the first quotes (QUOTED-REGEX) with the string given in the second set of quotes (QUOTED-STRING). Matching is done left to right. For example, if you replace ```YY = [[:digit:]][[:digit:]]''' with ```YY = 04''' and cfengine encounters ```YY = 03 but old YY = 70''' then it will be replaced with ```YY = 04 but old YY = 70'''  File: cfengine-Reference.info, Node: ReplaceLinesMatchingField, Next: Repository, Prev: ReplaceFirst, Up: editfiles 4.17.70 ReplaceLinesMatchingField --------------------------------- ReplaceLinesMatchingField QUOTED-NUMBER This command replaces any lines in the current file with the current line set by `SetLine' or `ForEachLineIn', if the lines are split into fields (e.g. the password file) separated by the `SplitOn' character (':' by default), and the corresponding fields match. The idea behind this command was to be able to override global passwords (from a file which gets distributed) by new passwords in a local file. Rather than maintaining the files separately, this simply overrides the entries with the new ones.  File: cfengine-Reference.info, Node: Repository, Next: ResetSearch, Prev: ReplaceLinesMatchingField, Up: editfiles 4.17.71 Repository editfiles ---------------------------- Repository QUOTED STRING This allows a local override of the `Repository' variable, on an item by item basis. If set to "off" or "none" it cancels the value of a global repository. See *note copybackup::. See *note Backup in editfiles::.  File: cfengine-Reference.info, Node: ResetSearch, Next: RunScript, Prev: Repository, Up: editfiles 4.17.72 ResetSearch ------------------- ResetSearch QUOTED-STRING Sets the current-position pointer to the line number in the quoted string. `EOF' indicates the end of the file.  File: cfengine-Reference.info, Node: RunScript, Next: RunScriptIfLineMatching, Prev: ResetSearch, Up: editfiles 4.17.73 RunScript ----------------- RunScript QUOTED-STRING Executes the named script command. Before executing the script any edits are saved to disk. After the script has executed, cfengine reloads the file for any further editing operations. The script (which may be any executable program) is appended with two arguments: the name of the file which is being edited and the system hard class (e.g. sun4, ultrix etc.) of the system executing the script. CAUTION: cfengine knows nothing about the success or failure of anything that is done during the execution of user scripts. This feature is to be used at the users own peril!  File: cfengine-Reference.info, Node: RunScriptIfLineMatching, Next: RunScriptIfNoLineMatching, Prev: RunScript, Up: editfiles 4.17.74 RunScriptIfLineMatching ------------------------------- RunScriptIfLineMatching QUOTED-STRING Executes the script named with the `SetScript' command only if the current file contains a line matching the quoted regular expression. CAUTION: cfengine knows nothing about the success or failure of anything that is done during the execution of user scripts. This feature is to be used at the users own peril!  File: cfengine-Reference.info, Node: RunScriptIfNoLineMatching, Next: SetCommentStart, Prev: RunScriptIfLineMatching, Up: editfiles 4.17.75 RunScriptIfNoLineMatching --------------------------------- RunScriptIfNoLineMatching QUOTED-REGEX Executes the script named with the `SetScript' command if the current file contains no line matching the quoted regular expression. CAUTION: cfengine knows nothing about the success or failure of anything that is done during the execution of user scripts. This feature is to be used at the users own peril!  File: cfengine-Reference.info, Node: SetCommentStart, Next: SetCommentEnd, Prev: RunScriptIfNoLineMatching, Up: editfiles 4.17.76 SetCommentStart ----------------------- SetCommentStart QUOTED-STRING Specify which string should be used for starting a comment using the commands `CommentLineMatching' and `CommentLineStarting'. The default is the hash symbol `#' followed by a single space.  File: cfengine-Reference.info, Node: SetCommentEnd, Next: SetLine, Prev: SetCommentStart, Up: editfiles 4.17.77 SetCommentEnd --------------------- SetCommentEnd QUOTED-STRING Specify which string should be used for ending a comment using the commands `CommentLineMatching' and `CommentLineStarting'. The default is the empty string. For example, you could make C style comments by setting CommentStart to `/*' and comment end to `*/'.  File: cfengine-Reference.info, Node: SetLine, Next: SetScript, Prev: SetCommentEnd, Up: editfiles 4.17.78 SetLine --------------- SetLine QUOTED-STRING Sets a current line value which can be appended using `AppendIfNoLineMatching' using a regular expression.  File: cfengine-Reference.info, Node: SetScript, Next: SlashCommentLinesContaining, Prev: SetLine, Up: editfiles 4.17.79 SetScript ----------------- SetScript QUOTED-STRING Sets the name of a user-supplied script for editing the current file.  File: cfengine-Reference.info, Node: SlashCommentLinesContaining, Next: SlashCommentLinesMatching, Prev: SetScript, Up: editfiles 4.17.80 SlashCommentLinesContaining ----------------------------------- SlashCommentLinesContaining QUOTED-STRING Add a `//' to the start of any line containing the quoted string.  File: cfengine-Reference.info, Node: SlashCommentLinesMatching, Next: SlashCommentLinesStarting, Prev: SlashCommentLinesContaining, Up: editfiles 4.17.81 SlashCommentLinesMatching --------------------------------- SlashCommentLinesMatching QUOTED-REGEX Add a `//' to the start of any line exactly matching the quoted regular expression.  File: cfengine-Reference.info, Node: SlashCommentLinesStarting, Next: SplitOn, Prev: SlashCommentLinesMatching, Up: editfiles 4.17.82 SlashCommentLinesStarting --------------------------------- SlashCommentLinesStarting QUOTED-STRING Add a `//' to the start of any line starting with the quoted string.  File: cfengine-Reference.info, Node: SplitOn, Next: SysLog, Prev: SlashCommentLinesStarting, Up: editfiles 4.17.83 SplitOn --------------- SplitOn QUOTED-STRING This defines a single character which is to be interpreted as a field separator for editing files with columns. The default value for this is `:', as is used in the password and group files. It is used in conjunction with `ReplaceLinesMatchingField'. Note, be careful not to confuse this with the `EditSplit' character.  File: cfengine-Reference.info, Node: SysLog, Next: Umask, Prev: SplitOn, Up: editfiles 4.17.84 Syslog editfiles ------------------------ Set to true or false, on or off to set inform level for this file. Default is off. Syslog QUOTED-STRING  File: cfengine-Reference.info, Node: Umask, Next: UnCommentLinesContaining, Prev: SysLog, Up: editfiles 4.17.85 Umask ------------- QUOTE MODE Set local umask for file creation and script execution.  File: cfengine-Reference.info, Node: UnCommentLinesContaining, Next: UnCommentLinesMatching, Prev: Umask, Up: editfiles 4.17.86 UnCommentLinesContaining -------------------------------- UnCommentLinesContaining QUOTED-STRING Uncomment all lines in file containing the quoted string as a substring. The comment delimiters are assumed to be those set using SetCommentStart and SetCommentEnd.  File: cfengine-Reference.info, Node: UnCommentLinesMatching, Next: UnCommentsNLines, Prev: UnCommentLinesContaining, Up: editfiles 4.17.87 UnCommentLinesMatching ------------------------------ UnCommentLinesMatching QUOTED-REGEX Uncomment all lines in file matching the quoted regular expression. The comment delimiters are assumed to be those set using SetCommentStart and SetCommentEnd.  File: cfengine-Reference.info, Node: UnCommentsNLines, Next: UnCommentToLineMatching, Prev: UnCommentLinesMatching, Up: editfiles 4.17.88 UnCommentNLines ----------------------- UnCommentNLines QUOTED-STRING Uncomments N lines starting from the current position, using the currently defined method for commenting. Note that the comment start and end symbols are removed independently, i.e. they are not matched, so that a comment may be spread over several lines. e.g. If using C style `/*' and `*/' comments, the command `UnCommentNLines "3"' would uncomment /* 1 */ /* 2 */ /* 3 */ and also /* 1 2 3 */  File: cfengine-Reference.info, Node: UnCommentToLineMatching, Next: UnsetAbort, Prev: UnCommentsNLines, Up: editfiles 4.17.89 UnCommentToLineMatching ------------------------------- UnCommentToLineMatching QUOTED-STRING Uncomments from the current position up to and including the first line matching the named regular expression.  File: cfengine-Reference.info, Node: UnsetAbort, Next: UseShell, Prev: UnCommentToLineMatching, Up: editfiles 4.17.90 UnsetAbort ------------------ Switches off the feature `AbortAtLineMatching'. UnsetAbort QUOTED-STRING  File: cfengine-Reference.info, Node: UseShell, Next: WarnIfFileMissing, Prev: UnsetAbort, Up: editfiles 4.17.91 UseShell ---------------- Normally cfengine uses a shell based exec function to run scripts during editing. This involves the inheritance of environment variables and path, which carries with it an inherent security risk. Setting this value to false causes execution to execute without an encapsulating shell.  File: cfengine-Reference.info, Node: WarnIfFileMissing, Next: WarnIfLineContaining, Prev: UseShell, Up: editfiles 4.17.92 WarnIfFileMissing ------------------------- If the file to be edited does not exist, a visible alert is issued. WarnIfFileMissing QUOTED-STRING  File: cfengine-Reference.info, Node: WarnIfLineContaining, Next: WarnIfLineMatching, Prev: WarnIfFileMissing, Up: editfiles 4.17.93 WarnIfLineContaining ---------------------------- Issue a warning if the quoted string is found as a substring of one or more lines in the file. WarnIfLineContaining QUOTED-STRING  File: cfengine-Reference.info, Node: WarnIfLineMatching, Next: WarnIfLineStarting, Prev: WarnIfLineContaining, Up: editfiles 4.17.94 WarnIfLineMatching -------------------------- WarnIfLineMatching QUOTED-REGEX Issue a warning if the quoted regular expression matches one or more lines in the file.  File: cfengine-Reference.info, Node: WarnIfLineStarting, Next: WarnIfNoLineContaining, Prev: WarnIfLineMatching, Up: editfiles 4.17.95 WarnIfLineStarting -------------------------- WarnIfLineStarting QUOTED-STRING Issue a warning if the quoted string matches the start of one or more lines in the file.  File: cfengine-Reference.info, Node: WarnIfNoLineContaining, Next: WarnIfNoLineMatching, Prev: WarnIfLineStarting, Up: editfiles 4.17.96 WarnIfNoLineContaining ------------------------------ WarnIfNoLineContaining QUOTED-STRING Issue a warning if the quoted string is not contained in one or more lines in the file.  File: cfengine-Reference.info, Node: WarnIfNoLineMatching, Next: WarnIfNoLineStarting, Prev: WarnIfNoLineContaining, Up: editfiles 4.17.97 WarnIfNoLineMatching ---------------------------- WarnIfNoLineMatching REG-EX Issue a warning if the quoted regular expression does not match one or more lines in the file.  File: cfengine-Reference.info, Node: WarnIfNoLineStarting, Next: WarnIfNoSuchLine, Prev: WarnIfNoLineMatching, Up: editfiles 4.17.98 WarnIfNoLineStarting ---------------------------- WarnIfNoLineStarting QUOTED-STRING Issue a warning if the quoted string is not found at the start of one or more lines in the file.  File: cfengine-Reference.info, Node: WarnIfNoSuchLine, Prev: WarnIfNoLineStarting, Up: editfiles 4.17.99 WarnIfNoSuchLine ------------------------ WarnIfNoSuchLine QUOTED-REGEX Issue a warning if the quoted regular expression does not match one or more lines in the file.  File: cfengine-Reference.info, Node: Editfiles on Binary Files, Next: files, Prev: editfiles, Up: Cfagent reference 4.18 Editfiles on Binary Files ============================== A limited number of operations can also be performed on purely binary files, e.g. compiled programs, in order to search for strings or viral code, or to modify strings within a program. Binary mode is a mutually exclusive, separate mode to normal editing. The limit on the size of binary files is set by `editbinaryfilesize' in `control'. * ReplaceAll REGEX With LITERAL Replaces occurrences of the matched regular expression with\ the provided literal text, only if the length of the literal substitute is less than or equal to the length of the located string. If the replacement string is shorter, it is padded with ascii spaces (character 32) by default. The padding character can be changed by setting `BinaryPaddingChar' in `control'. Padding with a null byte would lead to corruption of text within a program. * WarnIfContainsString REGEX/LITERAL Yields a warning if the literal string or regular expression matches. Cfengine first attempts a literal match and then a regular expression match. * WarnIfContainsFile FILENAME Yields a warning if the contents of the named file exactly match part of the file which is being edited. This can be used to search for binary data which cannot be typed directly into the cfengine program, e.g. virus signatures.  File: cfengine-Reference.info, Node: files, Next: filters, Prev: Editfiles on Binary Files, Up: Cfagent reference 4.19 files ========== The `files' facility allows you to touch (create), check for the existence, owner and permissions of files, change the permissions and test for setuid root programs. * Menu: * Syntax:: * Recursion:: * Directory permissions:: * Checksums and change management:: * home directive:: * Owner and group wildcards:: * Files linkchildren:: * touch:: * create::  File: cfengine-Reference.info, Node: Syntax, Next: Recursion, Prev: files, Up: files 4.19.1 Syntax ------------- A files-statement can have several options. We can begin by examining the form of the statement in pseudo-code: files: CLASSES:: /FILE-OBJECT mode=MODE owner=UID-LIST group=GID-LIST action=FIXALL/OTHER-OPTIONS/warnall links=false/stop/TRAVERSE/FOLLOW/TIDY rxdirs=true/on/FALSE/OFF ignore=PATTERN include=PATTERN exclude=PATTERN filter=FILTER ALIAS xdev=TRUE/ON/false/off define=CLASSLIST elsedefine=CLASSLIST checksum=MD5/SHA/BEST syslog=TRUE/ON/false/off inform=TRUE/ON/false/off audit=TRUE/ON/FALSE/OFF ifelapsed=MINS expireafter=MINS SPECIAL OS FLAGS: flags=BSD FLAGS An example would be the following: any:: /var/spool/printQ mode=0775 r=0 o=daemon g=daemon act=fixdirs The meaning of these item is sketched out below and becomes clearer on looking at a number of examples. Note that, each of the options below can be written in either upper or lower case and abbreviated by any unique abbreviation. `/FILE-OBJECT' This is the only obligatory part of a file action. This may be a single file or a directory. If it is a directory then it indicates where does the file search should begin. The recursion specifier may be used to force cfengine to descend into subdirectories in a controlled fashion, starting from this point, checking files there also. The wildcard `home' may also be used. *Note home directive::. A file object is interpreted as a directory if you write it in the following form: `/directory-path/.'. i.e. a trailing dot signifies a directory. This then becomes the same as the `directory' command. `mode=MODESTRING' Specifies what the allowed permissions for files are. If cfengine finds that a file's mode is incorrect, the value of the `action' option determines what will be done about it. The modestring should consist of either a three digit octal numbers with `+', `-' or `=' symbols, or a text string like that used by the command `chmod'. For instance: `mode=u=rwx,og+rx' would mean set the read/write and execute flags for the user (file owner) and add the read/execute flags for others and group bits. An example of the numerical form might be `-002' which would mean that the read-for-others flag should either not be set or should be unset, depending on the action you choose. `+2000' would mean that the setgid flag should be present or set, depending on the action. `+2000,-002' would be a combination of these. The `=' sign sets to an absolute value, so `=755' would set the file mode to mode 755. `flags=BSD FLAGS' The free BSD Unices have additional filesystem flags which can be seton files. Refer to the BSD `chflags' documentation for this. For example, /tmp/flags.01 mode=0600 owner=0 group=0 flags=uappnd,uchg,uunlnk,nodump,opaque,sappnd,schg,sunlnk action=touch `recurse=NUMBER/INF' This specifier tells cfengine whether or not to recurse into subdirectories. If the value is zero, only the named file or directory is affected. If the value is 1, it will open at most one level of subdirectory and affect the files within this scope. If the value is `inf' then cfengine opens all subdirectories and files beginning from the specified filename.*Note Recursion::. `owner=OWNER LIST' This is a list of allowed owners, or uids by number, separated by commas. For example `root,2,3,sysadm'. In cases where you ask cfengine to fix the ownership automatically, the owner will be set to the first recogized owner in the list if and only if it is not one of the named uids in the list. `group=GROUP LIST' This is a list of allowed groups, or gids by number, separated by commas. For example `wheel,2,3,sysadm'. In cases where you ask cfengine to fix the ownership automatically, the group will be set to the first recognized group in the list if and only if it is not one of the named gids in the list. `action=ACTION' The action is one of the following keywords. warnall warndirs warnplain fixall fixdirs fixplain touch linkchildren create compress alert The upper line results only in warnings being issued. The actions beginning `fix' prompt cfengine to fix encountered problems without bothering the user. No message is issued unless in verbose mode. The special features on the third line will be explained separately. Alert is like `-print' in the find command, it triggers on the existence of files which have not been ignored, excluded or filtered. This should normally be used together `filter', in order to locate files of particular types. `include=WILDCARD/PATTERN' You can include this option several times to specify specific patterns which are to be included in the search. Once you specify one pattern you exclude all files not matching at least one of the patterns. The case be useful for restricting a search, or for modifying the permissions of only certain files. `exclude=WILDCARD/PATTERN' You can include this option several times to specify specific patterns which are to be excluded from the search. This overrides any patterns given in the `include=' list. `ignore' This works like the global ignore directive but here you may provide a private list of ignorable directories and files. Unlike include, exclude this affects the way cfengine parses directory trees. `links=STOP/TRAVERSE/TIDY' Normally cfengine does not descend into subdirectories which are pointed to by symbolic links. If you wish to force it to do so (without using the `-l' command line option) you may give this option the value `true', or `traverse', or `follow'. To specify no recursion you set the value `false' or `stop'. Note that the value set here in the cfengine program _always overrides_ the value set by the `-l' command line option, so you can protect certain actions from this command line option by specifying a negative value here. If you specify no value here, the behaviour is determined by what you specify on the command line. The value `links=tidy' has the same effect as the `-L' command line option except that here it may be specified per item rather than globally. Setting this value causes links which point to non-existent files to be deleted. If the warn directive is used (for directories, plain files or both) then only a warning message is issued if the file being tested does not match the specification given. If the fix directives are used then cfengine does not issue a warning, it simply fixes the value silently. Non-existent files are created by the `touch' command. A directory may be touched (created) by writing the filename `/a/b/c/.' with a dot as the last character. (This may also be achieved with the `directories' directive, *Note directories::.) `define=CLASSLIST' If a file operation results in action being taken to fix a file, the colon, comma or dot separated list of classes becomes defined. Warnings do not activate the classes. `checksum=MD5/SHA/BEST' If set this option causes cfengine to add a checksum for the named file to a database. Changes in the value of this checksum are then warned as a security issue. This should normally only be used to monitor binary files which one would not expect to change often. Note also that the use of this option can mean a significant performance penalty. If the value `best' is used for this option then the best known pair of checksum methods are cross-checked for each file. (The best value are determined by the algorithms supported in the OpenSSL interfaces used to compile the program). If `ChecksumUpdates' is set, then security warning messages are issued only once and the value in the database is then changed to the new value of the file automatically i.e. the behaviour is similar to that of setuid root program detection, *Note ChecksumPurge::. Also, *Note ChecksumUpdates::. `xdev' Prevents cfengine from descending into file systems that are not on the same device as the root of the rescurion path. `rxdirs' If true (the default) cfengine assumes that a directory that is readable should also have its execute flag set, allowing users to enter it and perform directory browsing. If false, cfengine will not make this assumption. Note that if set to false, it will affect recursive file checks. Thus setting to false with `mode=644 recurse=true' could lead to unintended permissions on directories. The default values are `mode=+000', `recurse=0', `action=warnall' and any owner or group is acceptable. The default for `links' is to not traverse links unless the `-l' option is set on the command line.  File: cfengine-Reference.info, Node: Recursion, Next: Directory permissions, Prev: Syntax, Up: files 4.19.2 Recursion ---------------- The recursion specifier tells cfengine what to do, starting from `/directory name'. A value of `r=0' means `no recursion' and any checking is limited only to the named file or directory. A value of `r=inf' implies unlimited recursion. Cfengine then descends into all subdirectories checking or setting the permissions of files until it `bottoms out' at a plain file. A value such as `R=4' means descend recursively into subdirectories, but no more than four levels. This is a useful safety net in preventing unforeseen accidents. A recursive search also bottoms out on device boundaries and symbolic links (provided the `-l' option is not used).  File: cfengine-Reference.info, Node: Directory permissions, Next: Checksums and change management, Prev: Recursion, Up: files 4.19.3 Directory permissions ---------------------------- When you specify the permissions for a whole file tree, using the recursion specifier it is awkward to have to remember that directories must be executable. cfengine will do this for you automatically. If you specify that a file tree is to have a read flag set, cfengine will ensure that the corresponding execute flag is also set for directories which live in the tree. So the command files: myclass:: /dir mode=a+rw r=inf fixall would set all plain files to mode 644 and all directories to 755, that is read/write for everyone on plain files and read/write/execute for everyone on directories.  File: cfengine-Reference.info, Node: Checksums and change management, Next: home directive, Prev: Directory permissions, Up: files 4.19.4 Checksums and change management -------------------------------------- Integrity checks are a good way of detecting tampering with a system, or simply for monitoring upgrades that happen as a result of software unrelated to cfengine. The `checksum' option asks cfengine to compute and cache the value of the cryptographic checksum of the named file. files: /my/file checksum=best action=warnall The checksum type can be `md5', `sha' or `best'. The option best cross checks the best two available algorithms. At present cfengine is waiting for improvements to the OpenSSL library supporting sha2 algorithms. Once a value has been computed and placed in the database each new computation will be checked against the old one. Any change will lead to a mismatch and the following will happen: * A warning is printed about the change * As of 2.2.8 a class called `checksum_alerts' will be defined, indicating that a change has occurred. This can be used to trigger followup actions. The class is a persistant class that lasts for 60 minutes. * If ChecksumUpdates is set to true, the new value will replace the old in the database  File: cfengine-Reference.info, Node: home directive, Next: Owner and group wildcards, Prev: Checksums and change management, Up: files 4.19.5 `home' directive ----------------------- If you want to check the files of all the users who have their login areas on the current host, you can use a wildcard directive `home' instead of a directory name. In this case the file action iterates over all home directories physically on the current host. The home directories are, of course, located by searching for files which match $(mountpattern)/$(homepattern) i.e. the values which are specified in the `control' part of the program. For example the following line is a very useful service to ignorant users. files: any:: home mode=o-w r=inf act=fixall It ensures automatically that no user has files which can be written to by other arbitrary users. As a corollary to this, you may write something like any:: home/www mode=a+r fixall to specify a special subdirectory of every users' home directory. This statement would check that all of the files in users' world wide web directories were readable for everyone.  File: cfengine-Reference.info, Node: Owner and group wildcards, Next: Files linkchildren, Prev: home directive, Up: files 4.19.6 Owner and group wildcards -------------------------------- If you do not want to explicitly state the owner or group of a file you may simply omit the group or owner options. /FILE-OBJECT m=0664 r=inf This example generate a warning if any files under the named directory do not have permission read/write for all users.  File: cfengine-Reference.info, Node: Files linkchildren, Next: touch, Prev: Owner and group wildcards, Up: files 4.19.7 Files linkchildren ------------------------- The `linkchildren' facility is almost identical to that already described under `links'. *Note Link Children::. The only difference here is that the ownership and permissions on the links are set all in one operation. For example: MYCLASS:: /local/lib/emacs m=0770 o=me g=mygroup act=linkchildren  File: cfengine-Reference.info, Node: touch, Next: create, Prev: Files linkchildren, Up: files 4.19.8 touch ------------ The `touch' facility creates a new file with the specified permissions and ownership, or corrects the permissions and ownership of an existing file, in addition to updating the time stamps. MYCLASS:: /NEWFILE mode=0644 action=touch  File: cfengine-Reference.info, Node: create, Prev: touch, Up: files 4.19.9 create ------------- This is like `touch' except that an existing file's time stamps, permissions and ownership will not be modified if the file already exists. If the file does not exist, the attributes are set to the values specified, or to the default values of `0644'.  File: cfengine-Reference.info, Node: filters, Next: groups, Prev: files, Up: Cfagent reference 4.20 filters ============ A filter is a way of selecting or pruning during a search over files or processes. Since filter rules could apply to several objects, cfengine allows you to define filter conditions as separate objects to be applied in different contexts. Filter objects can be used in `copy', `editfiles', `files', `tidy' and `processes'. In most cases one writes .. filter=filteralias in the appropriate command. The exception is `editfiles', where the syntax is { .. Filter "filteralias" .. } Example: files: /tmp filter=testfilteralias action=alert r=inf Filters are defined in a separate section. Filters for files and processes are defined together. They differ only in the criteria they contain. Here is are examples of file filters: Filters: { filteralias1 Owner: "mark|cell|motd" Group: "ecg|mark" Mode: "700" FromCtime: "date(2000,1,1,0,0,0)" # absolute date ToCtime: "now" FromMtime: "tminus(1,0,0,2,30,0)" # relative "ago" from now ToMtime: "inf" # end of time FromAtime: "date(1997,2,22,0,0,0)" ToAtime: "inf" FromSize: "10000" # File size interval ToSize: "10mb" ExecRegex: "/usr/bin/file $(this) (.*ascii.*)"# Result from "files" command Type: "dir|link" # reg|link|dir|socket|fifo|door|char|block NameRegex: ".*.asc" # regex matching file name IsSymLinkTo: "/dev/null" # True if file is a link to object name regex Result: "Type" # Result which shouldbe returned } ######################################### { testfilteralias2 ExecProgram: "/bin/ls $(this)" # True if the program returns true. $(this) is the current object } ######################################### { testfilteralias3 Owner: "mark" } Filters are evaluated like classes. In fact, the filtering works by evaluating the class attributes for each file. File filters: `Owner:' and Group can use numerical id's or names, or ```none''' for users or groups which are undefined in the system passwd/group file. `' Mode: applies only to file objects. It shares syntax with the `mode=' strings in the files command. This test returns true if the bits which are specified as `should be set' are indeed set, and those which are specified as `should not be set' are not set. `Atime:,Ctime:,Mtime:' apply only to file objects. These specify ranges From and To. If the file's time stamps lie in the specified range, this returns true. Times are specfied by a six component vector (year,month,day,hour,minutes,seconds) This may be evaluated as two functions: date() or tminus() which give absolute times and times relative to the current time respectively. In addition, the words now and inf may be used. e.g. FromCtime: "date(2000,1,1,0,0,0)" # absolute date ToCtime: "now" FromMtime: "tminus(1,0,0,2,30,0)" # relative "ago" from now ToMtime: "inf" # end of time `Type:' applies only to file objects may be a list of file types which are to be matched. The list should be separated by the OR symbol `|', since these types are mutually exclusive. The possible values are currently file|reg|link|dir|socket|fifo|door|char|block Note that `file' and `reg' are synonymous. `ExecRegex:' matches the test string against the output of the specified command. `NameRegex:' matches the name of the file with a regular expression. `IsSymLinkTo:' applies only when the file object $(this) is a symbolic link. It is true if the regular expression matches the contents of the link. `ExecProgram:' matches if the command returns successfully (with return code 0). Note that this feature introduces an implicit dependency on the command being called. This might be exploitable as a security weakness by advanced intruders. `Result:' specifies the way in which the above elements are combined into a single filter. Process filters: `Owner' process owner UID (quoted regex) `PID:' process ID (quoted regex) `PPID:' parent process ID (quoted regex) `PGID:' process group ID (quoted regex) `RSize:' resident size (quoted regex) `VSize:' virtual memory size (quoted regex) `Status:' status (quoted regex) `Command:' CMD or COMMAND fields (quoted regex) `(From/To)TTime:' Total elasped time in TIME field (accumulated time) `(From/To)STime:' Starting time for process in STIME or START field (accumulated time) `TTY:' terminal type, or none (quoted regex) `Priority:' PRI or NI field (quoted regex) `Threads:' NLWP field for SVR4 (quoted regex) `Result:' logical combination of above returned by filter (quoted regex) Examples: processes started between 18th Nov 2000 and now. { filteralias FromSTime: "date(2000,11,18,0,0,0)" ToSTime: "now" } All processes which have accumulated between 1 and 20 hours of CPU time. { filteralias FromTTime: "accumulated(0,0,0,1,0,0)" ToTTime: "accumulated(0,0,0,20,0,0)" } * Menu: * Complete filter examples::  File: cfengine-Reference.info, Node: Complete filter examples, Prev: filters, Up: filters 4.20.1 Complete filter examples ------------------------------- Here is an example filter to search for all files which are either directories or links, or any kind of file owned by mark, in group cfengine. control: actionsequence = ( files ) files: /tmp filter=testfilteralias action=alert r=inf /cfengine filter=testfilteralias action=fixall r=inf mode=644 filters: { testfilteralias Owner: "mark" Group: "cfengine" Type: "dir|link" Result: "Type|(Owner.Group)" # Both owner AND group required correct } Find all ELF executables using data from the Unix `file' command. Caution, this takes a long time if used indescriminately. control: actionsequence = ( files ) files: /tmp filter=testfilteralias action=alert r=inf /cfengine filter=testfilteralias action=fixall r=inf mode=644 filters: { testfilteralias ExecRegex: "/bin/file (.*ELF.*)" Result: "ExecRegex" } Here is an example which warns of any process coupled to a terminal started in November: control: actionsequence = ( processes ) filters: { filteralias FromSTime: "date(2000,11,0,0,0,0)" ToSTime: "date(2000,11,30,0,0,0)" TTY: ".*pt.*" Result: "TTY.STime" } processes: "." filter=filteralias action=warn  File: cfengine-Reference.info, Node: groups, Next: homeservers, Prev: filters, Up: Cfagent reference 4.21 groups/classes =================== The `groups' action (equivalently referred to as `classes' as of version 1.4.0) is used to define classes which stand for groups of hosts. If you use the NIS (network information service) facility for defining _netgroups_ then this idea will already be familiar to you and you can probably use your already-defined netgroups in cfengine. To define a group, you simply make a list and assign it a name. Here is an example of the syntax: groups: ANDed_class:: science = ( saga tor odin ) packages = ( saga ) AllHomeServers = ( saga ) AllBinaryServers = ( saga ) OIH_servers = ( saga ) OIH_clients = ( tor odin ) notthis = ( !this ) ip_in_range = ( IPRange(129.0.0.1-15) ) # host is in ip address range ip_in_range = ( IPRange(129.0.0.1/24) ) # host is in ip address range (CIDR notation) compute_nodes = ( HostRange(cpu-,1-32) ) # host name in the cpu-01 through cpu-32 range To include a list of hosts from a NIS netgroup, you use the `+' symbol, or the `+@' construction. For example: groups: science = ( +science-allhosts ) physics = ( +physics-allhosts ) physics_theory = ( +@physics-theory-sun4 dirac feynman schwinger ) Using an enormous netgroup does not use up any space. A group declaration results in the storage of only the class name regardless of how many hosts are in the list. The rule is that the left hand side of the assignment becomes defined (true) if the list on the right hand side includes the host which is parsing the file -- i.e. `$(host)'. In some cases your netgroups will not correspond exactly to the list you want, but it might be more convenient to use a netgroup _except_ for certain hosts. You can `undefine' or remove hosts from the netgroup list by using the minus `-' symbol. For example: group = ( +mynetgroup -specialhost -otherhost ) which means, of course, all hosts in netgroup `mynetgroup' except for `specialhost' and `otherhost'. Finally, you may also subtract two netgroups in the following manner. group = ( +bignetgroup -smallnetgroup ) The `minus' command effectively eliminates its members from `bignetgroup' if they exist within that group. If none of the hosts in `smallnetgroup' exist in `bignetgroup' then the command has no effect. Groups may contain previously defined cfengine groups too. This allows one class to inherit the attributes of another class, for instance: AllSun4Hosts = ( sonny sunny solar stella ) AllUltrixHosts = ( ully olly wally golly ) AllBSD = ( AllSun4Hosts AllUltrixHosts ) The classes on the right hand side are effectively ORed together into the left hand side. This enables complex classes to be constructed from several other basic classes, e.g. SpecialTimes = ( Hr00 Monday Day1 ) which evaluates to true every day when it between 00:00 hours and 00:59, all day Monday and all day on the first day of every month. If you apply a class predicate before a definition then the result is effectively the AND of the classes: Hr00:: SpecialTime = ( Monday Tuesday ) defines `SpecialTime' at Hr00 on Monday or Tuesday. Finally, you can define groups (strictly classes) by the result of a shell command. A shell command or program is deemed to be `true' if it exits with a status of zero, i.e. it calls `exit(0)'. Any other value is taken to be false. You can include shell commands as the members of groups in order to define classes based on the outcomes of your own scripts by enclosing the script in single or double quotes: have_cc = ( '/bin/test -f /usr/ucb/cc' ) The class `have_cc' will then be defined if the shell command returns true. Of course, you can put any script or program in the single quotes as long as they adhere to the convention that zero exit status means true. If you have several members which are shell commands, then the effect is to make the class the logical OR of the scripts' results.  File: cfengine-Reference.info, Node: homeservers, Next: ignore, Prev: groups, Up: Cfagent reference 4.22 homeservers ================ The `homeservers' declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of which other hosts on the network possess filesystems containing home directories (login areas) which client hosts should mount. A sample homeserver declaration looks like this: homeservers: Physics:: einstein Math:: riemann euler The meaning of this declaration is the following. Any host which finds itself to be a member of the classes on the left hand side of the assignment need to mount all home directory resources from the hosts on the right hand side of the assignment. The pattern variable `homepattern' is used to determine which resources are home directories in the list of `mountables'. *Note mountables::. Let us consider an example in which `homepattern' is set to the wildcard value `home?' and the mountables list is given by mountables: einstein:/mysite/einstein/home1 einstein:/mysite/einstein/home2 mountoptions=soft,bg,intr,rsize=8192,wsize=8192 riemann:/mysite/riemann/local readonly=true euler:/mysite/euler/home1 Any host in the group `Physics' would now want to mount all home directories from the host `einstein'. There are two of these. Both the filesystems listed for `einstein' match the `homepattern' variable since they end in `home?'. cfengine would therefore take this to mean that all hosts in `Physics' should mount both of these filesystems. Hosts in `Math', on the other hand, should mount only homedirectories from the hosts `riemann' and `euler'. There is only a single filesystem on `riemann' and it does not match `homepattern', so it is not mounted. On `euler' there is a match, so this filesystem will be added to the appropriate hosts. _Cfengine picks out home directory resources from the `mountables' list by trying to match the `homepattern' variable, starting from the end of the directory name. You do not therefore have to use the designation `/site/host/home?' but this is a simple choice and is highly recommended._  File: cfengine-Reference.info, Node: ignore, Next: import, Prev: homeservers, Up: Cfagent reference 4.23 ignore =========== When you specify a recursive search as part of a `files', `tidy' or `copy' action, you would sometimes like to exclude certain directories from the list of sub directories. In most cases you will want to do this on a per-command basis (see the pages for these actions separately), but you can also make a global ignore list. This can be accomplished by adding the directory to the ignore-list. The syntax is ignore: WILDCARDS/DIRECTORIES/FILENAMES For example: ignore: any:: # # Prevent tidying .X11 directories in /tmp where # window managers write semaphores # .X11 # # Don't tidy emacs locks # !* /local/lib/gnu/emacs/lock/ /local/tmp /local/bin/top /local/lib/tex/fonts /local/etc /local/www /local/mutils/etc/finger.log None of the above directories will be checked or entered during recursive descents unless a specific command is initiated to search those directories with their names as the top of the search tree. A handy tip if you are tidying `/tmp' recursively is to include the directory `.X11' here. This directory is used by the X-windows system and deleting it while a window manager has an open session can cause the user some trouble. Ignore refers to all recursive searches in tidy, files, copy and links.  File: cfengine-Reference.info, Node: import, Next: interfaces, Prev: ignore, Up: Cfagent reference 4.24 import =========== To break up a large configuration file into smaller files you can use the include directive. This conditionally reads in files if the class on the left hand side of the assignment matches the host parsing the file. This enables also a variety of cfengine configuration scripts to read in a standard set of default settings. The syntax of the statement is: import: any:: cf.global_classes linux:: cf.linux_classes Note that, if you define variables in an imported file they will not be defined for operations in their parent files. This because cfengine reads in all the import files after the main file has been parsed--not at the place where you call import in your script. This means that variables or macros defined in imported files are only defined after the main program. Variables from earlier files are inherited by later includes, but not _vice-versa_.  File: cfengine-Reference.info, Node: interfaces, Next: links, Prev: import, Up: Cfagent reference 4.25 interfaces =============== interfaces: CLASSES:: INTERFACENAME netmask=NETMASK broadcast=BROADCAST If you have more than one network interface, or you do not wish to use the default interface name, this section may be used to define further interfaces to be checked. This feature can replace the older method of setting netmask and broadcast address in `control:'. If the `netmask' variable is not set, cfengine ignores the default interface configuration. Example: interfaces: "le1" netmask=255.255.255.0 broadcast=ones "le2" netmask=255.255.255.0 broadcast=ones  File: cfengine-Reference.info, Node: links, Next: mailserver, Prev: interfaces, Up: Cfagent reference 4.26 links ========== The symbolic links function is one of the greatest plusses in cfengine as a system administration tool. It allows you to do two things: check single links for correctness and consistency (or make them if they do not exist), and check or make links to every file in a designated directory. This latter feature is called multiple linking or linking children. The `linkchildren' feature is also available from the `files' action *Note files::. The syntax of a link item is: FROM-LINK ->[!] TO-OBJECT OR FROM-LINK +>[!] TO-OBJECT type=symbolic/absolute/abs/HARD/RELATIVE/REL copy=PATTERN recurse=NUMBER/INF/0 copytype=CHECKSUM/ctime include=PATTERN exclude=PATTERN ignore=PATTERN action=SILENT deadlinks=kill/FORCE define=CLASSLIST nofile=kill/FORCE syslog=TRUE/ON/FALSE/OFF inform=TRUE/ON/FALSE/OFF audit=TRUE/ON/FALSE/OFF ifelapsed=MINS expireafter=MINS _The special variable `$(binserver)' can be used in `links'._ * Menu: * Single links:: * Multiple Links:: * Link Children:: * Relative and absolute links:: * Hard links::  File: cfengine-Reference.info, Node: Single links, Next: Multiple Links, Prev: links, Up: links 4.26.1 Single links ------------------- To define a single link, you create an entry of the following form: links: CLASS:: LINKNAME -> OBJECT_TO_LINK_TO LINKNAME -> ./RELATIVE_LINK LINKNAME -> ../RELATIVE_LINK If links exists and point to their intended destinations then no action is taken. If a link exists but points incorrectly then a warning is issued, unless the pling operator `!' is given, in which case the correct value is forced. If the link exists and points to a file which does not exist a warning is issued unless the command line option `-L' is used, in which case the link is deleted. Here is an example of some valid link statements. links: Physics.sun4:: /usr/local -> /$(site)/$(host)/local /home -> /$(site)/$(host)/u1 /etc/sendmail.cf -> /usr/local/mail/etc/global-sendmail.cf /usr/lib/sendmail ->! /local/lib/sendmail cfengine makes any directories which are required leading up to the link name on the left hand side of the arrow automatically. In the last example the `pling' forces cfengine to make the link even if a file for link exists previously. Plain files are saved by appending `.cfsaved' to the filename, or by moving to a repository, whereas old links are removed. The same effect can be enforced globally using the `-E' option, but only if the program is run interactively. (In this case a prompt is issued to make sure that you wish to use such a big hammer on your system!) The link operation accepts a number of parameters `type=HARD/RELATIVE/ABSOLUTE' If the link type is hard, a hard link is created *Note Hard links::. Symbolic links may specify two special types. If `relative' is selected, and the `to' object is an absolute path name, the link name will be rewritten as a pathname relative to the source file, using `.' and `..' to move relative to the current directory. For instance, a link from `/usr/local/file' to `/usr/file' would be linked as `./../file'. If the `to' object is already relative, this has no effect. If `absolute' is specified, cfengine will try to resolve the true path location of the `to' object, expanding any symbolic links or dots in the path name, up to a maximum of four levels of symbolic links. `copy=PATTERN' This option can be repeated any number of times to build up a list of filenames or wildcards which are to be copied rather than linked symbolically. The copy is made on an age-comparison basis. A global variable may also be set to invoke this feature *Note copylinks::. Directories cannot be copied in this way. `copytype=CHECKSUM/CTIME' This specifies the basis for deciding whether to update a file which is to be copied instead of linked *Note copy::. `nofile=kill/FORCE' This decides what happens to links which point to non-existent files. The default action is to remove such links, or refuse to create them. By setting the FORCE option you can force cfengine to make symbolic links to files which do not exist. This is useful for setting up links to filesystems which are not permanently mounted. `exclude=PATTERN' This option can be repeated any number of times to build up a list of filenames or wildcards which are to be excluded from the linking process. A global variable may also be set to invoke this feature *Note excludelinks::. `ignore' This works like the global ignore directive but here you may provide a private list of ignorable directories and files. Unlike include, exclude this affects the way cfengine parses directory trees. `recurse=NUMBER/inf' This option can only be used with multiple link operations *Note Multiple Links::. If this option is specified, cfengine links only non-directory objects. Directories are instead created and links within those directories are also created. The value of this option specifies the maximum number of levels to which cfengine should recursively descend a link tree. `inf' means infinite recursion. Cfengine also ignores files and directories in the ignore list *Note ignore::. `define=CLASSLIST' If a link is created or replaced, the colon, comma or dot separated list of classes becomes defined. The final feature of the links facility is connected to the use of the cfengine model for mounting NFS filesystems. In particular it concerns the variable `$(binserver)'. The easiest way to understand this feature is to illustrate a couple of examples. Consider the following: links: any:: /local -> /${site}/${binserver}/local The result of this command is quite different depending on which host is executing it. The variable `$(site)' clearly has a fixed value, but the variable `$(binserver)' might expand to any valid binary server for the host executing the program. *Note binservers::. The procedure cfengine adopts is to go through its list of mountables, keeping only those mountable resources which belong to defined binary servers for the current host. It then attempts to match a filesystem by substituting `$(binserver)' with each of its valid binservers in turn and it matches the first one binary server which yields an existing file. Note that every host is a binary server for itself, so that the value of `$(binserver)' which has absolute priority is alway the same as the value of `$(host)'. This ensures that the link will always be made to a local filesystem if the rules of the model are upheld.  File: cfengine-Reference.info, Node: Multiple Links, Next: Link Children, Prev: Single links, Up: links 4.26.2 Multiple Links --------------------- With the link symbol `+>', you opt to link all of the files in a directory to corresponding files in another directory. This procedure is sometimes useful for installing software. In the example links: myclass:: /usr/local/bin +> /usr/local/lib/perl/bin /opt +>! /local every file in the directory `/usr/local/lib/perl/bin' is linked symbolically to a corresponding file in `/usr/local/bin'. The `pling' character forces cfengine to replace old links or plain files already existing. Old links are removed, whereas old files are saved by appending `.cfsaved' to the filename *Note repository::. Each time cfengine runs it goes through all of the files in the directory concerned and checks the appropriate link accordingly. If new files appear, new links will be added. If a file disappears but the link to it remains, a warning will be issued, unless the `-L' command line option is used, in which case the link is deleted.  File: cfengine-Reference.info, Node: Link Children, Next: Relative and absolute links, Prev: Multiple Links, Up: links 4.26.3 Link Children -------------------- The linkchildren directive is a closely related to the cfengine model for NFS filesystems. It is a way of making links which embodies a rudimentary kind of `intelligence'. Consider the following: links: any:: /usr/local/lib/emacs +> linkchildren The word `linkchildren' automatically tells cfengine that it should look for an appropriate file to link to on a binary server for the current host. The exact meaning of the above statement is as follows. cfengine begins searching though the list of mountable resources, discarding any filesystems which do not belong to valid binary servers. It looks for a filesystem ending in `emacs' (the last link of the left hand side). If all is well, these file systems are already mounted and they can be searched. If no resource is found ending in `emacs', we go to the next link `lib' and look for a filesystem ending in `lib'. If this is not found we go to `local' and so on. When a match is made, cfengine then tries to locate the file by checking whether it exists relative to the matched filesystem. For example, suppose `local' matched with `host:/site/host/local'. It would then try to locate `host:/site/host/local/lib/emacs' and link all of the children therein to the local file directory `/usr/local/lib/emacs'. Here is another example which makes reference to the cfengine model for mounting NFS filesystems. Suppose you have a host with some spare disk space. You want to mount `/usr/local' from the binary architecture server, but you also want to use the disk you have locally. The following lines links: electron:: /$(site)/electron/local +> linkchildren any:: /usr/local -> /$(site)/$(binserver)/local have the effect of creating a directory `/$(site)/electron/local' and filling it with links to all of the files and directories on the binary server's mounted filesystem. It results in an exact copy (by linkage) on the local disk, but does not use up your local disk space. The space you have remaining could, for example, be used for software with a special license for that host. The second link links `/usr/local' to the `nearest' binary server. But the nearest binary server is always `$(host)' which means this evaluates to a file which now exists because of the first command, so on the host `electron' the directory `/usr/local' ends up being a link to `/$(site)/electron/local' which is full of links to the binary server. If you've caught your breath after that mouthful you probably have mixed feelings about creating a bunch of links in this way. What happens if the files they point to are removed? Then you are left with a lot of useless links. Actually this is no problem for cfengine, since you can ask cfengine to simply remove links which point to non-existent files *Note files::. Nevertheless, this feature clearly requires some caution and is mainly a spice for advanced users of the cfengine model.  File: cfengine-Reference.info, Node: Relative and absolute links, Next: Hard links, Prev: Link Children, Up: links 4.26.4 Relative and absolute links ---------------------------------- When specifying symbolic linking, you can ask cfengine to change the link type to be either relative to the source or to be an absolute path. What this means is the following. Consider the following link: /var/tmp/cfengine -> /local/cfengine If we add the option `type=relative', then instead of creating a link which points to `/local/cfengine', the link is created pointing to the location ./../../local/cfengine In other words, the link is relative to the calling directory `/var/tmp'. If a link is specified as being absolute with the option `type=absolute', then cfengine attempts to resolve to value of the link so as to be the true path of the target. If the target name contains a symbolic link, then this is expanded as far as possible to give the true path to the file. For example, if `/local' is really a link to `/site/myhost/local' then the link would point to `/site/myhost/local/cfengine'.  File: cfengine-Reference.info, Node: Hard links, Prev: Relative and absolute links, Up: links 4.26.5 Hard Links ----------------- Cfengine will also allow you to create hard links to regular files. A hard link is in every way identical to the original file, it merely has a different name (technically, it is a duplicate inode). To create a hard link you use the link-option `type=hard'. For example: links: /DIRECTORY/NEWNAME -> /DIRECTORY/OTHERNAME type=hard Cfengine will not create hard links to directories or other special files. This is always a slightly dubious practice and is best avoided anyway. POSIX says that the hard link can be on a different device to the file it points to, but both BSD and System V restrict hard links to be on the same device as their predecessors. Cfengine has no policy on this, but--in the theoretical case in which the hard link and the predecessor were on different file systems--it becomes near impossible to determine with certainly between a hard link and a very similar regular file, and thus cfengine issues a warning in verbose mode about this eventuality. Provided both link and predecessor are on the same filesystem cfengine determines the status of hard links by comparing the device and inode numbers of the file pointed to.  File: cfengine-Reference.info, Node: mailserver, Next: methods, Prev: links, Up: Cfagent reference 4.27 mailserver =============== The `mailserver' declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of which NFS filesystem contains mail for its users. All hosts apart from the mail-host itself must then mount the mail spool directory across the network. The declaration looks like this: mailserver: CLASS:: mailhost:/var/spool/mail The result of the `mailcheck' command in the action-sequence is now to mount the filesystem `/var/spool/mail' on the host `mailhost'. This action is carried out on any machine which does not already have that filesystem mounted. The mail spool directory is mounted, by default, onto the official mail spool directory for the system which is parsing the program. In other words, on an HPUX system, the spool directory is mounted on `/usr/mail' by default, whereas on a Sun system it would be mounted on `/var/spool/mail'. The default location can be changed by using the resource file. *Note cfrc resource file::.  File: cfengine-Reference.info, Node: methods, Next: miscmounts, Prev: mailserver, Up: Cfagent reference 4.28 methods ============ From version 2.1.0, cfagent provides for the execution of closed functions or "methods". Methods are similar to the old idea of modules, but they are implemented in a way that allows collaboration between different hosts within a network, using a common standard. Methods must be cfengine programs however, wheras the module interface can be written in any script language. _Methods are designed to offer a firewall-like proxy interface for remote method execution. We can call methods a form of `voluntary RPC', in which hosts execute methods for one another on a purely voluntary basis. This builds in anti-spamming protection. The principle used is that hosts should be immune to Denial of Service attacks; they should only be able to disadvanatge themselves with the attempt._ (Remote method execution was not implemented until version 2.1.3. It is still considered experimental and should be tested carefully for production environments with at least version 2.2.2. List expansion is particularly fragile in cfengine 2. This problem cannot be resolved in version 2, so this should not be reported as a bug. ) Methods allow you to call an independent cfengine program, pass it arguments and classes, and collect the results for use in your main program. It thus introduces parent-child semantics into cfengine "imports". A method is more than an import. (Import is analagous to a C #include, while a method is like a C function.) Communication is peer to peer, by mutual consent. There is no "method server" that executes methods on remote hosts. Hosts exchange information by invitation only. This is an unreliable service (in the sense of UDP). The order of method exeuction is not guaranteed. This results from the decoupling between client request and service provision. methods: CLASS:: FUNCTION_NAME(PARAMETERS OR NONE) action=`filename' sendclasses=COMMA SEPARATED CLASS LIST returnvars=COMMA SEPARATED VARIABLE LIST OR VOID returnclasses=COMMA SEPARATED CLASS LIST server=IP-HOST/LOCALHOST/NONE forcereplyto=IP ADDRESS owner=SETUID group=SETGID chdir=CD FOR CHILD chroot=SANDBOX DIRECTORY Most of these functions will be familiar from other cfengine commands. Some special ones are noted below: `action' The name of the method file that should be defined in the modules directory of the server host. `forcereplyto' Sometimes nameservice problems (especially with remote devices) can lead to confusion about where a method should be sent. The caller can therefore declare to the server which address it wants the reply to be marked for. `returnvars' Returns the values of the variables to the parent process. This acts as an access control list for variable names transmitted by the child process. The names returned by the child must match this list. `returnclasses' Returns the classes to the parent process, if and only if they are defined at the end of the current method. This acts as an access control list for class names transmitted by the child process. The names returned by the child must match this list. `sendclasses' Transmits the current status of the named classes to the child process. In other words, if the listed classes are defined, they become defined in the child process, else they remain undefined. The class may still be defined in the child by independent local definitions. If the server is set to `localhost', the method will be evaluated on the local machine. If the server is set of `none', the method will not be executed at all. The function arguments may not be empty, but a null value can be transmitted with a dummy value, e.g. `Function(null)' or `function(void)'. Here is an example method call. # cfagent.conf control: actionsequence = ( methods ) ################################################# methods: any:: SimpleMethod(null) action=cf.simple returnvars=null returnclasses=null server=localhost With method file (located in the ModulesDirectory), # cf.simple control: MethodName = ( SimpleMethod ) MethodParameters = ( null ) actionsequence = ( timezone ) classes: dummy = ( any ) #################################################### alerts: dummy:: "This simple method does nothing" ReturnVariables(void) ReturnClasses(void) On executing this example, the output is: nexus$ ./cfagent -f ./cftest cfengine:myhost:SimpleMethod: cfengine:nexus: This simple method does nothing If the server name is a wildcard, e.g. `*' then this acts as a multicast or broadcast. * Menu: * localhost examples:: * remotehost examples::  File: cfengine-Reference.info, Node: localhost examples, Next: remotehost examples, Prev: methods, Up: methods 4.28.1 Localhost examples ------------------------- The following example collects the tar file, unpacks it, configures and compiles it, then tidies its files. #################################################### # # This is a cfengine file that calls a method. # It should be in the usual place for cfinputs # #################################################### control: actionsequence = ( methods ) ##################################################### methods: InstallTar(cfengine-2.1.0b7,/local/gnu) action=cf.install returnvars=null returnclasses=null server=localhost We must install the method in the trusted modules directory (normally /var/cfengine/modules or WORKDIR/modules). #################################################### # # This is an example method file, that needs to be # in the module directory /var/cfengine/modules # since this is the trusted directory # # e.g. InstallFromTar(cfengine-2.1.0,/usr/local/gnu) # #################################################### control: MethodName = ( InstallTar ) MethodParameters = ( filename gnuprefix ) path = ( /usr/local/gnu/bin ) TrustedWorkDir = ( /tmp ) TrustedSources = ( /iu/nexus/ud/mark/tmp ) TrustedSourceServer = ( localhost ) actionsequence = ( copy editfiles shellcommands tidy ) #################################################### classes: Force = ( any ) #################################################### copy: $(TrustedSources)/$(filename).tar.gz dest=$(TrustedWorkDir)/$(filename).tar.gz server=$(TrustedSourceServer) #################################################### shellcommands: "$(path)/tar zxf $(filename).tar.gz" chdir=$(TrustedWorkDir) "$(TrustedWorkDir)/$(filename)/configure --prefix=$(gnuprefix)" chdir=$(TrustedWorkDir)/$(filename) define=okay okay:: "$(path)/make" chdir=$(TrustedWorkDir)/$(filename) #################################################### tidy: $(TrustedWorkDir) pattern=$(filename) r=inf rmdirs=true age=0 #################################################### #editfiles: # #{ $(TrustedWorkDir)/$(filename)/configure-opts # #AppendIfNoSuchLine "Something ???" #} #################################################### alerts: Force:: ReturnVariables(none) ReturnClasses(success) A more complex example is given below: GetAnalysis("${parent1}",param2,ReadFile("/etc/passwd",300)) # The name of the method that is in modulesdir action=cf.methodtest # The variables that we get back should be called these names # with method name prefix returnvars=a,b,c,d # This is an access list for returned classes. Classes will # only be handed back if they are included here returnclasses=define1,define2,class1 # The host(s) that should execute the method server=localhost # Only localhost can decide these - not a remote caller # owner=25 # group=root # chdir=/var/cfengine # chroot=/tmp Here the function being called is the cfengine program `cf.methodtest'. It is passed three arguments: the contents of variable PARENT1, the literal string "param2" and the first 300 bytes of the file `/etc/passwd'. On return, if the method gets executed, the values will be placed in the four variables: $(GetAnalysis.a) $(GetAnalysis.b) $(GetAnalysis.c) $(GetAnalysis.d) If the classes `define1' etc, are returned by the method, then we set them also in the main program as GetAnalysis_define:: In other words, the class name is also prefixed with the method name to distinguish it. (`returnclasses' works like an access control list for setting classes, deciding whether or not the main script should accept the results from the child method.). The remaining options are as those for executing shell commands, and apply only on the host that executes the function. Both the client and server hosts must have a copy of the same method declaration. The client should have a non-empty `server=' declaration. The server side should have no `server=' declaration unless it is sending the request on recursively to other hosts. At present only requests to localhost are allowed, so only there is automatic access to the rule. The cfagent file that contains the method code must have the following declarations: control: MethodName = ( IDENTIFIER ) MethodParameters = ( SPACED LIST OF RECIPIENT VARIABLES OR FILES ) # .... alerts: # Return variables are alerts to parent ReturnVariables(COMMA SEPARATED LIST OF VARIABLES OR FUNCTIONS OR VOID) ReturnClasses(COMMA SEPARATED LIST OF CLASSES) e.g. control: MethodName = ( GetAnalysis ) MethodParameters = ( value1 value2 /tmp/file1 ) # .... alerts: # Return variables are alerts to parent ReturnVariables("${var1}","${var2}","var3",literal_value) ReturnClasses(class1,class2) The parameters transmitted by the parent are read into the formal parameters `value1', `value2' and the the file excerpt is placed in the temporary file `/tmp/file1'. The return classes are passed in their current state to the parent; i.e. if class1 is defined then it is offered to the parent, but if it is not defined in the method, it is not passed on. The parent can then choose to accept or ignore the value.  File: cfengine-Reference.info, Node: remotehost examples, Prev: localhost examples, Up: methods 4.28.2 Remote host examples --------------------------- Methods can also be scheduled for execution on remote hosts. * Both hosts must have an identical copy of the method stanza * Public keys must be exchanged between the cooperating hosts * Access must be granted to `/var/cfengine/rpc_out' in cfservd. Remote method execution is the same as local method execution except for some additional requirements. A list of collaborating peers must be added to the control section of `update.conf'. In order the the requests to be collected automatically, you must have `copy' in the action sequence of the `update.conf' file. control: MethodPeers = ( HOSTNAME LIST ) # Must have copy in actionsequence This list tells the agent which remote hosts to collaborate with, i.e. whom should we contact to look for work that we have promised to perform? In order the the requests to be collected automatically, you must have `copy' in the action sequence of the `update.conf' file. For example, to make two hosts collaborate: methods: host1|host2:: MethodTest("my test!") action=cf.methodtest server=host2.iu.hio.no returnclasses=null returnvars=retval ifelapsed=120 Note that an important aspect of remote method invocation is that there is only voluntary cooperation between the parties. A reply bundle from a finished method can collected from a server by the client many times, causing the classes and variables associated with it to be defined at regular intervals, controlled by the ifelapsed time. To avoid multiple actions, you should lock methods or their follow-up actions with long ifelapsed times. This is a fundamental `feature' of voluntary cooperation: each party must take responsibilty for the sense of what it receives from the other. This feature will not be to everyone's taste, and it is unconventional. However, voluntary cooperation provides a way of collaborating without trust in a framework that forces us to confront the security issues directly. As such, it is a successful experiment.  File: cfengine-Reference.info, Node: miscmounts, Next: mountables, Prev: methods, Up: Cfagent reference 4.29 miscmounts =============== If you do not use the cfengine model for statically mounting NFS filesystems (or if there are filesystems which do not naturally fall into the bounds of that model) then you can still statically mount miscellaneous filesystems using a statement of the form: miscmounts: CLASS:: INFOHOST:SOURCE-DIRECTORY DESTINATION MODE INFOHOST:SOURCE-DIRECTORY DESTINATION mode=MODE ifelapsed=MINS expireafter=MINS For example physics:: # old syntax libraryserver:/$(site)/libraryserver/data1 /$(site)/libraryserver/data1 ro # consistent syntax libraryserver:/$(site)/libraryserver/data2 /$(site)/libraryserver/data2 mode=ro host:/foo /foo mode=rw,bg,hard,intr This statement would mount the directory `/$(site)/libraryserver/data' physically attached to host libraryserver onto a directory of the same name on all hosts in the group `physics'. The modes `ro' and `rw' signify read-only and read-write respectively. If no mode is given, read-write is assumed.  File: cfengine-Reference.info, Node: mountables, Next: processes, Prev: miscmounts, Up: Cfagent reference 4.30 mountables =============== The `mountables' declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of what filesystem resources are available for mounting. This list is used in conjunction with `binservers' and `homeservers' to determine which filesystems a given host should mount, according to the cfengine model. The syntax of the list is: mountables: CLASS:: "filesystem to mount" readonly=false/off/TRUE/ON mountoptions=NFS-OPTIONS e.g. mountables: CLASS:: server:/site/server/u1 server:/site/server/local linuxhost:/site/linuxhost/local linuxhost:/site/linuxhost/u1 Notice that binary and home-directory filesystems are mixed freely here. Cfengine determines which of the entries are homedirectories using the `homepattern' variable. Every time you add a disk or a mountable partition to your network, you should add the partition to the list of mountables. _NOTE: This list is read in order, top down. Cfengine looks for the first filesystem matching a given binary server when expanding the variable `$(binserver)', so sometimes the ordering of filesystems matters._ This list can be accessed in editfiles, to allow straightforward configuration of the automounter, using the command `AutomountDirectResources'.  File: cfengine-Reference.info, Node: processes, Next: packages, Prev: mountables, Up: Cfagent reference 4.31 processes ============== Using the processes facility, you can test for the existence of processes, signal (kill) processes and optionally restart them again. Cfengine opens a pipe from the system ps command and searches through the output from this command using regular expressions to match the lines of output from `ps'. The regular expression does not have to be an exact match, only a substring of the process line. The form of a process command is processes: CLASS:: "QUOTED REGULAR EXPRESSION" restart "SHELL COMMAND" useshell=true/FALSE/DUMB owner=RESTART-UID group=RESTART-GID chroot=DIRECTORY chdir=DIRECTORY umask=MASK signal=SIGNAL NAME matches=NUMBER define=CLASSLIST elsedefine=CLASSLIST action=signal/DO/WARN/BYMATCH include=LITERAL exclude=LITERAL filter=FILTER_NAME syslog=TRUE/ON/FALSE/OFF inform=TRUE/ON/FALSE/OFF audit=TRUE/ON/FALSE/OFF ifelapsed=MINS expireafter=MINS SetOptionString "QUOTED OPTION STRING" By default, the options sent to ps are "-aux" for BSD systems and "-ef" for System V. You can use the `SetOptionString' command to redefine the option string. Cfengine assumes only that the first identifiable number on each line is the process identifier for the processes, so you must not choose options for ps which change this basic requirement (this is not a problem in practice). Cfengine reads the output of the ps-command normally only once, and searches through it in memory. The process table is only re-consulted if `SetOptionString' is called. The options have the following meanings: `signal=SIGNAL NAME' This option defines the name of a signal which is to be sent to all processes matching the quoted regular expression. If this option is omitted, no signal is sent. The signal names have the usual meanings. The full list, with largely standardized meanings, is hup 1 hang-up int 2 interrupt quit 3 quit ill 4 illegal instruction trap 5 trace trap iot 6 iot instruction emt 7 emt instruction fpe 8 floating point exception kill 9 kill signal bus 10 bus error segv 11 segmentation fault sys 12 bad argument to system call pipe 13 write to non existent pipe alrm 14 alarm clock term 15 software termination signal urg 16 urgent condition on I/O channel stop 17 stop signal (not from tty) tstp 18 stop from tty cont 19 continue chld 20 to parent on child exit/stop gttin 21 to readers pgrp upon background tty read gttou 22 like TTIN for output if (tp->t_local<OSTOP) io 23 input/output possible signal xcpu 24 exceeded CPU time limit xfsz 25 exceeded file size limit vtalrm 26 virtual time alarm prof 27 profiling time alarm winch 28 window changed lost 29 resource lost (eg, record-lock lost) usr1 30 user defined signal 1 usr2 31 user defined signal 2 Note that cfengine will not attempt to signal or restart processes 0 to 3 on any system since such an attempt could bring down the system. The only exception is that the hangup (hup) signal may be sent to process 1 (init) which normally forces init to reread its terminal configuration files. `restart "SHELL COMMAND"' Note the syntax: there is no equals sign here. If the keyword `restart' appears, then the next quoted string is interpreted as a shell command which is to be executed after any signals have been sent. This command is only issued if the number of processes matching the specified regular expression is zero, or if the signal sent was signal 9 (sigkill) or 15 (sigterm) , i.e. the normal termination signals. This could be used to restart a daemon for instance. Cfengine executes this command and _waits_ for its completion so you should normally only use this feature to execute non-blocking commands, such as daemons which dissociate themselves from the I/O stream and place themselves in the background. Some unices leave a hanging pipe on restart (they never manage to detect the end of file condition). This occurs on POSIX.1 and SVR4 popen calls which use wait4. For some reason they fail to find and end-of-file for an exiting child process and go into a deadlock trying to read from an already dead process. This leaves a zombie behind (the parent daemon process which forked and was supposed to exit) though the child continues. A way around this is to use a wrapper script which prints the line "cfengine-die" to STDOUT after restarting the process. This causes cfengine to close the pipe forcibly and continue. Cfengine places a timeout on the restart process and attempts to clean up zombies, but you should be aware of this possibility. `owner=,group=' Sets the process uid and gid (setuid,gid) for processes which are restarted. This applies only to cfengine run by root. `chroot' Changes the process root directory of the restarted process, creating a `sandbox' which the process cannot escape from. Best used together with a change of owner, since a root process can break out of such a confinement in principle. `chdir' Change the current working directory of the restarted process. `useshell=TRUE/FALSE/DUMB' When restarting processes, cfengine normally uses a shell to interpret and execute the restart command. This has inherent security problems associated with it. If you set this option to false, cfengine executes restart commands without using a shell. This is recommended, but it does mean that you cannot use any shell operators or features in the restart command-line. Some programs (like cron) do not handle I/O properly when they fork their daemon parts, this causes a zombie process and normally hangs cfengine. By choosing the value `dumb' for this, cfengine ignores all output from a program and does not use a startup shell. This prevents programs like cron from hanging cfengine. `matches=NUMBER' This option may be used to set a maximum, minimum or exact number of matches. If cfengine doesn't find a number of matches to the regular expression which is in accordance with this value it signals a warning. The `<', `>' symbols are used to specify upper and lower limits. For example, matches=>6 # warn number of matches is greater than or equal to 6 matches=1 # warn if not exactly 1 matching process matches=<2 # warn if there are less than or equal to 2 matching processes `include=LITERAL' Items listed as includes provide an extra level of selection after the regular expression matches have been expanded. If you include one include option, then only lines containing one or more of the literal strings or wildcards will be matched. `exclude=LITERAL' Process lines containing literal strings or wildcards in exclude statements are not matched. Excludes are processed after regular expression matching and after includes. `define=CLASSLIST' The colon, comma or dot separated list of classes becomes activated if the number of regular expression matches is non-zero. `elsedefine=CLASSLIST' The colon, comma or dot separated list of classes becomes activated if the number of regular expression matches is zero. `action=SIGNAL/DO/WARN/BYMATCH' The default value of this option is to silently send a signal (if one was defined using the `signal' option) to matching processes. This is equivalent to setting the value of this parameter to `signal' or `do'. If you set this option to `warn', cfengine sends no signal, but prints a message detailing the processes which match the regular expression. If the option is set to `bymatch', then signals are only sent to the processes if the matches criteria fail. Here is an example script which sends the hang-up signal to cron, forcing it to reread its crontab files: processes: "cron" signal=hup Here is a second example which may be used to restart the nameservice on a Solaris system: processes: solaris:: "named" signal=kill restart "/usr/sbin/in.named" A more complex match could be used to look for processes belonging to a particular user. Here is a script which kills ftp related processes belonging to a particular user who is known to spend the whole day FTP-ing files: control: actionsequence = ( processes ) # # Set a kill signal here for convenience # sig = ( kill ) # # Better not find that dumpster here! # matches = ( 1 ) processes: # # Look for Johnny Mnemonic trying to dump his head, user = jmnemon # ".*jmnemon.*ftp.*" signal=$(sig) matches=<$(matches) action=$(do) # No mercy! The regular expression `.*' matches any number of characters, so this command searches for a line containing both the username and something to do with ftp and sends these processes the kill signal. You can arrange for signals to be sent, only if the number of matches fails the test. The `action=bymatch' option is used for this. For instance, to kill process `XXX' only if the number of matches is greater than 20, one would write: processes: "XXX" matches=<20 action=bymatch signal=kill See also filters *Note filters::, for more complex searches. cfengine-2.2.10/doc/cfexecd.80000644000175000001440000000140610202127306012520 00000000000000.TH cfengine 8 "Maintenance Commands" HiOslo .SH NAME cfengine \- network configuration engine .SH SYNOPSIS /usr/local/sbin/cfexecd .SH DESCRIPTION .B cfengine is a language based system specifically designed for testing and configuring unix\-like systems attached to a TCP/IP network. Th cfexecd is a wrapper for local execution of cfagent. It may be used to capture cfagent output and send it as mail when run cron cron, e.g. .PP 0,30 * * * * /var/cfengine/bin/cfexecd -F .PP or it can be run in daemon mode with scheduling parameters set in cfagent.conf. All control parameters are set in cfagent.conf. .IP "-F (--no-fork)" Run the executor in non-daemom (cron wrapper) mode. .SH AUTHOR Mark Burgess, Oslo University College .SH INFORMATION http://www.cfengine.org cfengine-2.2.10/doc/Makefile.in0000644000175000001440000007026011170173244013106 00000000000000# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = doc DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(srcdir)/stamp-1 $(srcdir)/stamp-vti $(srcdir)/version1.texi \ $(srcdir)/version2.texi mdate-sh texinfo.tex ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/conf.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = INFO_DEPS = cfengine-Reference.info cfengine-Tutorial.info am__TEXINFO_TEX_DIR = $(srcdir) DVIS = cfengine-Reference.dvi cfengine-Tutorial.dvi PDFS = cfengine-Reference.pdf cfengine-Tutorial.pdf PSS = cfengine-Reference.ps cfengine-Tutorial.ps HTMLS = cfengine-Reference.html cfengine-Tutorial.html TEXINFOS = cfengine-Reference.texinfo cfengine-Tutorial.texinfo TEXI2PDF = $(TEXI2DVI) --pdf --batch AM_MAKEINFOHTMLFLAGS = $(AM_MAKEINFOFLAGS) am__installdirs = "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man8dir)" \ "$(DESTDIR)$(docdir)" "$(DESTDIR)$(htmldir)" am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; man8dir = $(mandir)/man8 NROFF = nroff MANS = $(man_MANS) docDATA_INSTALL = $(INSTALL_DATA) htmlDATA_INSTALL = $(INSTALL_DATA) DATA = $(doc_DATA) $(html_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BERKELEY_DB_CFLAGS = @BERKELEY_DB_CFLAGS@ BERKELEY_DB_LDFLAGS = @BERKELEY_DB_LDFLAGS@ BERKELEY_DB_LIB = @BERKELEY_DB_LIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EIGHTBIT = @EIGHTBIT@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCC_CFLAG = @GCC_CFLAG@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SELINUX = @LIB_SELINUX@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ NOWRAP = @NOWRAP@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_LIB_CPPFLAGS = @OPENSSL_LIB_CPPFLAGS@ OPENSSL_LIB_LDFLAGS = @OPENSSL_LIB_LDFLAGS@ OPENSSL_LIB_LIB = @OPENSSL_LIB_LIB@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PS2PDF = @PS2PDF@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TEXI2DVI = @TEXI2DVI@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = $(pkgdatadir)/doc dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = $(pkgdatadir)/html includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ # Info used in building the MAN files man_MANS = cfengine.8 cfagent.8 cfenvd.8 cfenvgraph.8 cfexecd.8 cfkey.8 cfrun.8 cfservd.8 cfshow.8 cfetoolcheck.8 cfetooldump.8 cfetoolimport.8 cfetoolupdate.8 cfetoolcreate.8 cfetoolgraph.8 cfetoolinfo.8 # Info used in building the Info files info_TEXINFOS = cfengine-Reference.texinfo cfengine-Tutorial.texinfo infofiles = $(info_TEXINFOS:.texinfo=.info) MAKEINFOHTML = $(MAKEINFO) --html --no-split --css-include=cfcomdoc.css # Info used in building and installing HTML files htmlfiles = $(info_TEXINFOS:.texinfo=.html) html_DATA = $(htmlfiles) # Info used in building and installing Postscript files psfiles = $(info_TEXINFOS:.texinfo=.ps) pdffiles = $(info_TEXINFOS:.texinfo=.pdf) dvifiles = $(info_TEXINFOS:.texinfo=.dvi) doc_DATA = $(psfiles) $(pdffiles) # Make sure these get distributed with everything else. EXTRA_DIST = cfagent.8 cfenvd.8 cfenvgraph.8 cfexecd.8 cfkey.8 cfrun.8 cfservd.8 cfengine.8 cfshow.8 cfetoolcheck.8 cfetooldump.8 cfetoolimport.8 cfetoolupdate.8 cfetoolcreate.8 cfetoolgraph.8 cfetoolinfo.8 cfetoolcheck.8 cfetooldump.8 cfetoolimport.8 cfetoolupdate.8 cfetoolcreate.8 cfetoolgraph.8 cfetoolinfo.8 texinfo.tex $(htmlfiles) $(infofiles) $(pdffiles) SUFFIXES = html latex pdf ps dvi # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = $(htmlfiles) $(psfiles) $(pdffiles) # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = *.log *.aux *.mbs *.mb *.info* # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in mdate-sh all: all-am .SUFFIXES: .SUFFIXES: html latex pdf ps dvi .dvi .ps $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu doc/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs cfengine-Reference.info: cfengine-Reference.texinfo $(srcdir)/version1.texi restore=: && backupdir="$(am__leading_dot)am$$$$" && \ rm -rf $$backupdir && mkdir $$backupdir && \ if ($(MAKEINFO) --version) >/dev/null 2>&1; then \ for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \ if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \ done; \ else :; fi && \ if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ -o $@ `test -f 'cfengine-Reference.texinfo' || echo '$(srcdir)/'`cfengine-Reference.texinfo; \ then \ rc=0; \ else \ rc=$$?; \ $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \ fi; \ rm -rf $$backupdir; exit $$rc cfengine-Reference.dvi: cfengine-Reference.texinfo $(srcdir)/version1.texi TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ $(TEXI2DVI) -o $@ `test -f 'cfengine-Reference.texinfo' || echo '$(srcdir)/'`cfengine-Reference.texinfo cfengine-Reference.pdf: cfengine-Reference.texinfo $(srcdir)/version1.texi TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ $(TEXI2PDF) -o $@ `test -f 'cfengine-Reference.texinfo' || echo '$(srcdir)/'`cfengine-Reference.texinfo cfengine-Reference.html: cfengine-Reference.texinfo $(srcdir)/version1.texi rm -rf $(@:.html=.htp) if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ -o $(@:.html=.htp) `test -f 'cfengine-Reference.texinfo' || echo '$(srcdir)/'`cfengine-Reference.texinfo; \ then \ rm -rf $@; \ if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \ else \ if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \ exit 1; \ fi $(srcdir)/version1.texi: $(srcdir)/stamp-vti $(srcdir)/stamp-vti: cfengine-Reference.texinfo $(top_srcdir)/configure @(dir=.; test -f ./cfengine-Reference.texinfo || dir=$(srcdir); \ set `$(SHELL) $(srcdir)/mdate-sh $$dir/cfengine-Reference.texinfo`; \ echo "@set UPDATED $$1 $$2 $$3"; \ echo "@set UPDATED-MONTH $$2 $$3"; \ echo "@set EDITION $(VERSION)"; \ echo "@set VERSION $(VERSION)") > vti.tmp @cmp -s vti.tmp $(srcdir)/version1.texi \ || (echo "Updating $(srcdir)/version1.texi"; \ cp vti.tmp $(srcdir)/version1.texi) -@rm -f vti.tmp @cp $(srcdir)/version1.texi $@ mostlyclean-vti: -rm -f vti.tmp maintainer-clean-vti: -rm -f $(srcdir)/stamp-vti $(srcdir)/version1.texi cfengine-Tutorial.info: cfengine-Tutorial.texinfo $(srcdir)/version2.texi restore=: && backupdir="$(am__leading_dot)am$$$$" && \ rm -rf $$backupdir && mkdir $$backupdir && \ if ($(MAKEINFO) --version) >/dev/null 2>&1; then \ for f in $@ $@-[0-9] $@-[0-9][0-9] $(@:.info=).i[0-9] $(@:.info=).i[0-9][0-9]; do \ if test -f $$f; then mv $$f $$backupdir; restore=mv; else :; fi; \ done; \ else :; fi && \ if $(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ -o $@ `test -f 'cfengine-Tutorial.texinfo' || echo '$(srcdir)/'`cfengine-Tutorial.texinfo; \ then \ rc=0; \ else \ rc=$$?; \ $$restore $$backupdir/* `echo "./$@" | sed 's|[^/]*$$||'`; \ fi; \ rm -rf $$backupdir; exit $$rc cfengine-Tutorial.dvi: cfengine-Tutorial.texinfo $(srcdir)/version2.texi TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ $(TEXI2DVI) -o $@ `test -f 'cfengine-Tutorial.texinfo' || echo '$(srcdir)/'`cfengine-Tutorial.texinfo cfengine-Tutorial.pdf: cfengine-Tutorial.texinfo $(srcdir)/version2.texi TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ MAKEINFO='$(MAKEINFO) $(AM_MAKEINFOFLAGS) $(MAKEINFOFLAGS) -I $(srcdir)' \ $(TEXI2PDF) -o $@ `test -f 'cfengine-Tutorial.texinfo' || echo '$(srcdir)/'`cfengine-Tutorial.texinfo cfengine-Tutorial.html: cfengine-Tutorial.texinfo $(srcdir)/version2.texi rm -rf $(@:.html=.htp) if $(MAKEINFOHTML) $(AM_MAKEINFOHTMLFLAGS) $(MAKEINFOFLAGS) -I $(srcdir) \ -o $(@:.html=.htp) `test -f 'cfengine-Tutorial.texinfo' || echo '$(srcdir)/'`cfengine-Tutorial.texinfo; \ then \ rm -rf $@; \ if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ mv $(@:.html=) $@; else mv $(@:.html=.htp) $@; fi; \ else \ if test ! -d $(@:.html=.htp) && test -d $(@:.html=); then \ rm -rf $(@:.html=); else rm -Rf $(@:.html=.htp) $@; fi; \ exit 1; \ fi $(srcdir)/version2.texi: $(srcdir)/stamp-1 $(srcdir)/stamp-1: cfengine-Tutorial.texinfo $(top_srcdir)/configure @(dir=.; test -f ./cfengine-Tutorial.texinfo || dir=$(srcdir); \ set `$(SHELL) $(srcdir)/mdate-sh $$dir/cfengine-Tutorial.texinfo`; \ echo "@set UPDATED $$1 $$2 $$3"; \ echo "@set UPDATED-MONTH $$2 $$3"; \ echo "@set EDITION $(VERSION)"; \ echo "@set VERSION $(VERSION)") > 1.tmp @cmp -s 1.tmp $(srcdir)/version2.texi \ || (echo "Updating $(srcdir)/version2.texi"; \ cp 1.tmp $(srcdir)/version2.texi) -@rm -f 1.tmp @cp $(srcdir)/version2.texi $@ mostlyclean-1: -rm -f 1.tmp maintainer-clean-1: -rm -f $(srcdir)/stamp-1 $(srcdir)/version2.texi .dvi.ps: TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \ $(DVIPS) -o $@ $< uninstall-dvi-am: @$(NORMAL_UNINSTALL) @list='$(DVIS)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(dvidir)/$$f'"; \ rm -f "$(DESTDIR)$(dvidir)/$$f"; \ done uninstall-html-am: @$(NORMAL_UNINSTALL) @list='$(HTMLS)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -rf '$(DESTDIR)$(htmldir)/$$f'"; \ rm -rf "$(DESTDIR)$(htmldir)/$$f"; \ done uninstall-info-am: @$(PRE_UNINSTALL) @if test -d '$(DESTDIR)$(infodir)' && \ (install-info --version && \ install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ list='$(INFO_DEPS)'; \ for file in $$list; do \ relfile=`echo "$$file" | sed 's|^.*/||'`; \ echo " install-info --info-dir='$(DESTDIR)$(infodir)' --remove '$(DESTDIR)$(infodir)/$$relfile'"; \ install-info --info-dir="$(DESTDIR)$(infodir)" --remove "$(DESTDIR)$(infodir)/$$relfile"; \ done; \ else :; fi @$(NORMAL_UNINSTALL) @list='$(INFO_DEPS)'; \ for file in $$list; do \ relfile=`echo "$$file" | sed 's|^.*/||'`; \ relfile_i=`echo "$$relfile" | sed 's|\.info$$||;s|$$|.i|'`; \ (if test -d "$(DESTDIR)$(infodir)" && cd "$(DESTDIR)$(infodir)"; then \ echo " cd '$(DESTDIR)$(infodir)' && rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]"; \ rm -f $$relfile $$relfile-[0-9] $$relfile-[0-9][0-9] $$relfile_i[0-9] $$relfile_i[0-9][0-9]; \ else :; fi); \ done uninstall-pdf-am: @$(NORMAL_UNINSTALL) @list='$(PDFS)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(pdfdir)/$$f'"; \ rm -f "$(DESTDIR)$(pdfdir)/$$f"; \ done uninstall-ps-am: @$(NORMAL_UNINSTALL) @list='$(PSS)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(psdir)/$$f'"; \ rm -f "$(DESTDIR)$(psdir)/$$f"; \ done dist-info: $(INFO_DEPS) @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ list='$(INFO_DEPS)'; \ for base in $$list; do \ case $$base in \ $(srcdir)/*) base=`echo "$$base" | sed "s|^$$srcdirstrip/||"`;; \ esac; \ if test -f $$base; then d=.; else d=$(srcdir); fi; \ base_i=`echo "$$base" | sed 's|\.info$$||;s|$$|.i|'`; \ for file in $$d/$$base $$d/$$base-[0-9] $$d/$$base-[0-9][0-9] $$d/$$base_i[0-9] $$d/$$base_i[0-9][0-9]; do \ if test -f $$file; then \ relfile=`expr "$$file" : "$$d/\(.*\)"`; \ test -f $(distdir)/$$relfile || \ cp -p $$file $(distdir)/$$relfile; \ else :; fi; \ done; \ done mostlyclean-aminfo: -rm -rf cfengine-Reference.aux cfengine-Reference.cp cfengine-Reference.cps \ cfengine-Reference.fn cfengine-Reference.fns \ cfengine-Reference.ky cfengine-Reference.kys \ cfengine-Reference.log cfengine-Reference.mb \ cfengine-Reference.mbs cfengine-Reference.pg \ cfengine-Reference.pgs cfengine-Reference.tmp \ cfengine-Reference.toc cfengine-Reference.tp \ cfengine-Reference.tps cfengine-Reference.vr \ cfengine-Reference.vrs cfengine-Reference.dvi \ cfengine-Reference.pdf cfengine-Reference.ps \ cfengine-Reference.html cfengine-Tutorial.aux \ cfengine-Tutorial.cp cfengine-Tutorial.cps \ cfengine-Tutorial.fn cfengine-Tutorial.fns \ cfengine-Tutorial.ky cfengine-Tutorial.kys \ cfengine-Tutorial.log cfengine-Tutorial.mb \ cfengine-Tutorial.mbs cfengine-Tutorial.pg \ cfengine-Tutorial.pgs cfengine-Tutorial.tmp \ cfengine-Tutorial.toc cfengine-Tutorial.tp \ cfengine-Tutorial.tps cfengine-Tutorial.vr \ cfengine-Tutorial.vrs cfengine-Tutorial.dvi \ cfengine-Tutorial.pdf cfengine-Tutorial.ps \ cfengine-Tutorial.html maintainer-clean-aminfo: @list='$(INFO_DEPS)'; for i in $$list; do \ i_i=`echo "$$i" | sed 's|\.info$$||;s|$$|.i|'`; \ echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \ rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \ done install-man8: $(man8_MANS) $(man_MANS) @$(NORMAL_INSTALL) test -z "$(man8dir)" || $(MKDIR_P) "$(DESTDIR)$(man8dir)" @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ else file=$$i; fi; \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \ done uninstall-man8: @$(NORMAL_UNINSTALL) @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ for i in $$l2; do \ case "$$i" in \ *.8*) list="$$list $$i" ;; \ esac; \ done; \ for i in $$list; do \ ext=`echo $$i | sed -e 's/^.*\\.//'`; \ case "$$ext" in \ 8*) ;; \ *) ext='8' ;; \ esac; \ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ inst=`echo $$inst | sed -e 's/^.*\///'`; \ inst=`echo $$inst | sed '$(transform)'`.$$ext; \ echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \ rm -f "$(DESTDIR)$(man8dir)/$$inst"; \ done install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)" @list='$(doc_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(docDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(docdir)/$$f'"; \ $(docDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(docdir)/$$f"; \ done uninstall-docDATA: @$(NORMAL_UNINSTALL) @list='$(doc_DATA)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(docdir)/$$f'"; \ rm -f "$(DESTDIR)$(docdir)/$$f"; \ done install-htmlDATA: $(html_DATA) @$(NORMAL_INSTALL) test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)" @list='$(html_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(htmlDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \ $(htmlDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \ done uninstall-htmlDATA: @$(NORMAL_UNINSTALL) @list='$(html_DATA)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(htmldir)/$$f'"; \ rm -f "$(DESTDIR)$(htmldir)/$$f"; \ done tags: TAGS TAGS: ctags: CTAGS CTAGS: distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-info check-am: all-am check: check-am all-am: Makefile $(INFO_DEPS) $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(docdir)" "$(DESTDIR)$(htmldir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: $(DVIS) html: html-am html-am: $(HTMLS) info: info-am info-am: $(INFO_DEPS) install-data-am: install-docDATA install-htmlDATA install-info-am \ install-man install-dvi: install-dvi-am install-dvi-am: $(DVIS) @$(NORMAL_INSTALL) test -z "$(dvidir)" || $(MKDIR_P) "$(DESTDIR)$(dvidir)" @list='$(DVIS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(dvidir)/$$f'"; \ $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(dvidir)/$$f"; \ done install-exec-am: install-html: install-html-am install-html-am: $(HTMLS) @$(NORMAL_INSTALL) test -z "$(htmldir)" || $(MKDIR_P) "$(DESTDIR)$(htmldir)" @list='$(HTMLS)'; for p in $$list; do \ if test -f "$$p" || test -d "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ if test -d "$$d$$p"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(htmldir)/$$f'"; \ $(MKDIR_P) "$(DESTDIR)$(htmldir)/$$f" || exit 1; \ echo " $(INSTALL_DATA) '$$d$$p'/* '$(DESTDIR)$(htmldir)/$$f'"; \ $(INSTALL_DATA) "$$d$$p"/* "$(DESTDIR)$(htmldir)/$$f"; \ else \ echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(htmldir)/$$f'"; \ $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(htmldir)/$$f"; \ fi; \ done install-info: install-info-am install-info-am: $(INFO_DEPS) @$(NORMAL_INSTALL) test -z "$(infodir)" || $(MKDIR_P) "$(DESTDIR)$(infodir)" @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ list='$(INFO_DEPS)'; \ for file in $$list; do \ case $$file in \ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ esac; \ if test -f $$file; then d=.; else d=$(srcdir); fi; \ file_i=`echo "$$file" | sed 's|\.info$$||;s|$$|.i|'`; \ for ifile in $$d/$$file $$d/$$file-[0-9] $$d/$$file-[0-9][0-9] \ $$d/$$file_i[0-9] $$d/$$file_i[0-9][0-9] ; do \ if test -f $$ifile; then \ relfile=`echo "$$ifile" | sed 's|^.*/||'`; \ echo " $(INSTALL_DATA) '$$ifile' '$(DESTDIR)$(infodir)/$$relfile'"; \ $(INSTALL_DATA) "$$ifile" "$(DESTDIR)$(infodir)/$$relfile"; \ else : ; fi; \ done; \ done @$(POST_INSTALL) @if (install-info --version && \ install-info --version 2>&1 | sed 1q | grep -i -v debian) >/dev/null 2>&1; then \ list='$(INFO_DEPS)'; \ for file in $$list; do \ relfile=`echo "$$file" | sed 's|^.*/||'`; \ echo " install-info --info-dir='$(DESTDIR)$(infodir)' '$(DESTDIR)$(infodir)/$$relfile'";\ install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\ done; \ else : ; fi install-man: install-man8 install-pdf: install-pdf-am install-pdf-am: $(PDFS) @$(NORMAL_INSTALL) test -z "$(pdfdir)" || $(MKDIR_P) "$(DESTDIR)$(pdfdir)" @list='$(PDFS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(pdfdir)/$$f'"; \ $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(pdfdir)/$$f"; \ done install-ps: install-ps-am install-ps-am: $(PSS) @$(NORMAL_INSTALL) test -z "$(psdir)" || $(MKDIR_P) "$(DESTDIR)$(psdir)" @list='$(PSS)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(psdir)/$$f'"; \ $(INSTALL_DATA) "$$d$$p" "$(DESTDIR)$(psdir)/$$f"; \ done installcheck-am: maintainer-clean: maintainer-clean-am -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-1 \ maintainer-clean-aminfo maintainer-clean-generic \ maintainer-clean-vti mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-1 mostlyclean-aminfo mostlyclean-generic \ mostlyclean-libtool mostlyclean-vti pdf: pdf-am pdf-am: $(PDFS) ps: ps-am ps-am: $(PSS) uninstall-am: uninstall-docDATA uninstall-dvi-am uninstall-html-am \ uninstall-htmlDATA uninstall-info-am uninstall-man \ uninstall-pdf-am uninstall-ps-am uninstall-man: uninstall-man8 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ dist-info distclean distclean-generic distclean-libtool \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-docDATA \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-htmlDATA install-info \ install-info-am install-man install-man8 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-1 maintainer-clean-aminfo \ maintainer-clean-generic maintainer-clean-vti mostlyclean \ mostlyclean-1 mostlyclean-aminfo mostlyclean-generic \ mostlyclean-libtool mostlyclean-vti pdf pdf-am ps ps-am \ uninstall uninstall-am uninstall-docDATA uninstall-dvi-am \ uninstall-html-am uninstall-htmlDATA uninstall-info-am \ uninstall-man uninstall-man8 uninstall-pdf-am uninstall-ps-am %.html : %.texinfo ${MAKEINFO} -I $(srcdir) --html --no-split $< %.dvi : %.latex ${LATEX} $< %.dvi : %.texinfo ${TEXI2DVI} $< %.pdf : %.ps ${PS2PDF} $< # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-2.2.10/doc/cfkey.80000644000175000001440000000077110202127306012224 00000000000000.TH cfengine 8 "Maintenance Commands" HiOslo .SH NAME cfengine \- network configuration engine .SH SYNOPSIS /usr/local/sbin/cfkey .SH DESCRIPTION .B cfengine is a language based system specifically designed for testing and configuring unix\-like systems attached to a TCP/IP network. The command generates a pair of public-private keys for remote authentication during cfrun or cfagent and the server cfservd. .SH AUTHOR Mark Burgess, Oslo University College .SH INFORMATION http://www.cfengine.org cfengine-2.2.10/doc/version1.texi0000644000175000001440000000014511170173455013501 00000000000000@set UPDATED 21 January 2009 @set UPDATED-MONTH January 2009 @set EDITION 2.2.10 @set VERSION 2.2.10 cfengine-2.2.10/doc/cfrun.80000644000175000001440000000330210736710275012250 00000000000000.TH cfengine 8 "Maintenance Commands" .SH NAME cfrun \- Execute remote cfagents .SH SYNOPSIS /usr/local/sbin/cfrun [options] .SH DESCRIPTION .B cfengine is a language based system specifically designed for testing and configuring unix\-like systems attached to a TCP/IP network. .PP cfrun is a tool for executing one or more remote agents; it contacts the cfservd daemon running on a remote host, which (in turn) starts an authorized agent. Cfrun cannot be used to send instructions to a remote agent, but it can be used to flag certain aspects to the agent's existing policy for special attention.. .PP The command line options for cfrun are slightly unusual. They are separated into three sections: options to the cfrun program, options to the remote cfagent (with some security restrictions) and finally classes or flags to the remote agent. .SH EXAMPLES cfrun specialhost1 specialhost2 -- --verbose -- \!solaris .PP In this example, we contact hosts specialhost1 specialhost2 by name, and ask them to execute cfagent with the --verbose flag, if the class solaris is not defined. .PP .PP cfrun specialhost1 --verbose -- -- \!solaris .PP In this example the verbose flag is sent to cfrun rather than to the remote agent. No options are sent to the remote agents. The class specifier is sent to all the agents so that they may determine whether they fulfill the required class membership for execution. .PP The default behaviour is to execute cfagent serially on all hosts listed in the cfrun.hosts file. .SH FILES cfrun read a configuration file cfrun.hosts which must contain a list of every potentially contactable host. .SH AUTHOR Mark Burgess, Oslo University College .SH INFORMATION http://www.cfengine.org cfengine-2.2.10/doc/cfenvd.80000644000175000001440000000137410202127306012370 00000000000000.TH cfengine 8 "Maintenance Commands" HiOslo .SH NAME cfengine \- network configuration engine .SH SYNOPSIS /usr/local/sbin/cfenvd .SH DESCRIPTION .B cfengine is a language based system specifically designed for testing and configuring unix\-like systems attached to a TCP/IP network. Cfenvd is part of the anomaly detection subsystem for cfagent. It is a "plug'n'play" module that provides machine learning support to the agent. Cfenvd requires no configuration. It is completely optional. If it is run, cfagent can extract useful data from it; if it is not run cfagent continues as usual. .PP It is part of the on-going research in anomaly detection using cfengine. .SH AUTHOR Mark Burgess, Oslo University College .SH INFORMATION http://www.cfengine.org cfengine-2.2.10/doc/cfengine-Reference.info0000644000175000001440000002432711170173455015377 00000000000000This is cfengine-Reference.info, produced by makeinfo version 4.12 from cfengine-Reference.texinfo. INFO-DIR-SECTION System Utilities START-INFO-DIR-ENTRY * cfengine Reference: (cfengine-Reference.info). Cfengine is a language based tool specifically designed for configuring and maintaining BSD and System-5-like operating systems attached to a TCP/IP network. END-INFO-DIR-ENTRY  Indirect: cfengine-Reference.info-1: 479 cfengine-Reference.info-2: 297727  Tag Table: (Indirect) Node: Top479 Node: Reference introduction1004 Node: Installation1742 Node: Work directory2667 Node: Hard classes4538 Node: Filenames and paths6216 Node: Debugging with signals7684 Node: Cfkey8531 Node: Cfshow9533 Node: Cfagent reference13262 Node: Cfagent intro14026 Node: The file cfagent.conf15305 Node: Cfagent Runtime Options15688 Node: Variable expansion and contexts21902 Node: Setting variables with functions23344 Node: Special variables30946 Node: Iteration over lists36380 Node: Cfengine classes38896 Node: Setting classes with special functions45566 Node: AccessedBefore46050 Node: ChangedBefore46340 Node: ClassMatch46621 Node: FileExists47073 Node: GroupExists47308 Node: HostRange47554 Node: IsDefined47965 Node: IsDir48280 Node: IsLink48457 Node: IsPlain48641 Node: IsNewerThan48831 Node: IPRange49070 Node: PrepModule49301 Node: Regcmp49829 Node: ReturnsZero50079 Node: ReturnsZeroShell50381 Node: Strcmp50701 Node: UserExists50906 Node: IsGreaterThan51218 Node: IsLessThan51594 Node: Examples setting classes52253 Node: acl52840 Node: ACEs55256 Node: Solaris ACLs57759 Node: DFS ACLs58430 Node: NT ACLs60114 Node: Windows ACL Example62398 Node: Posix ACL Example63225 Node: alerts64658 Node: binservers68644 Node: broadcast70423 Node: control71538 Node: AbortClasses75304 Node: access75987 Node: actionsequence76557 Node: addclasses84646 Node: addinstallable86232 Node: AllowRedefinitionOf87733 Node: Auditing88238 Node: AutoDefine88921 Node: BinaryPaddingChar89539 Node: BindToInterface in cfagent89990 Node: ChecksumDatabase in cfagent90553 Node: ChecksumPurge91026 Node: ChecksumUpdates91717 Node: CompressCommand92531 Node: childlibpath92826 Node: copylinks93490 Node: defaultcopytype94205 Node: defaultpkgmgr94595 Node: deletenonuserfiles95127 Node: deletenonownerfiles95645 Node: deletenonusermail96162 Node: deletenonownermail96514 Node: domain96849 Node: dpkginstallcommand97738 Node: dryrun98291 Node: editbinaryfilesize98675 Node: editfilesize99235 Node: emptyresolvconf100123 Node: exclamation100478 Node: excludecopy100823 Node: excludelinks101489 Node: ExpireAfter102159 Node: FreeBSDInstallCommand103359 Node: FreeBSDRemoveCommand103932 Node: FullEncryption104523 Node: homepattern105081 Node: HostnameKeys in cfagent106713 Node: IfElapsed in cfagent107521 Node: IgnoreFriendRegex108584 Node: IgnoreInterfaceRegex108917 Node: Inform109334 Node: interfacename109861 Node: fileextension110611 Node: lastseen111092 Node: lastseenexpireafter111616 Node: linkcopies111992 Node: LogDirectory112672 Node: LogTidyHomeFiles113021 Node: moduledirectory113346 Node: mountpattern113971 Node: netmask115311 Node: nonalphanumfiles118981 Node: nfstype119571 Node: PortageInstallCommand120652 Node: repchar121443 Node: repository122048 Node: RPMcommand122564 Node: rpminstallcommand122878 Node: schedule123910 Node: secureinput125008 Node: sensiblecount125333 Node: sensiblesize125912 Node: showactions126566 Node: singlecopy127012 Node: site128795 Node: SkipIdentify129492 Node: Smtpserver130004 Node: SplayTime130255 Node: split130600 Node: spooldirectories131162 Node: suninstallcommand131733 Node: suspiciousnames132305 Node: sysadm132794 Node: Syslog133411 Node: SyslogFacility133740 Node: timezone134163 Node: TimeOut135297 Node: Verbose135825 Node: Warnings136541 Node: warnnonuserfiles136989 Node: warnnonownerfiles137332 Node: warnnonusermail137854 Node: warnnonownermail138200 Node: classes138516 Node: copy138726 Ref: dest141925 Ref: copyaction143684 Ref: force143990 Ref: forceipv4144109 Ref: forcedirs144336 Ref: copybackup144618 Ref: copyrepository144883 Ref: stealth145316 Ref: checkroot145850 Ref: timestamps146071 Ref: recurse146277 Ref: symlink146617 Ref: copyignore146920 Ref: copyinclude147149 Ref: copyexclude147707 Ref: copyxdev148038 Ref: copytype148177 Ref: findertype148772 Ref: server149547 Ref: failover150101 Ref: oldserver150261 Ref: trustkey150403 Ref: encrypt150807 Ref: verify151548 Ref: size151768 Ref: linktype152554 Ref: typecheck153241 Ref: copydefine153547 Ref: purge153985 Node: copy example155235 Node: hard links in copy156665 Node: Too many open files158667 Node: defaultroute159395 Node: disks160323 Node: directories163393 Node: disable165337 Node: editfiles170630 Node: AbortAtLineMatching178579 Node: Append179457 Node: AppendIfNoLineMatching179824 Node: AppendIfNoSuchLine180558 Node: AppendIfNoSuchLinesFromFile180915 Node: AppendToLineIfNotContains181390 Node: Audit181837 Node: AutoCreate182162 Node: AutomountDirectResources182791 Node: Backup in editfiles183644 Node: BeginGroupIfDefined184334 Node: BeginGroupIfNotDefined184694 Node: BeginGroupIfFileExists185070 Node: BeginGroupIfFileIsNewer185563 Node: BeginGroupIfLineContaining185975 Node: BeginGroupIfLineMatching186389 Node: BeginGroupIfMatch186799 Node: BeginGroupIfNoLineContaining187187 Node: BeginGroupIfNoLineMatching187613 Node: BeginGroupIfNoMatch188042 Node: BeginGroupIfNoSuchLine188440 Node: BreakIfLineMatches188841 Node: CatchAbort189172 Node: CommentLinesMatching189827 Node: CommentLinesStarting190224 Node: CommentNLines190617 Node: CommentToLineMatching191241 Node: DefineClasses191684 Node: DefineInGroup192001 Node: DeleteLinesAfterThisMatching193347 Node: DeleteLinesContaining193689 Node: DeleteLinesMatching194092 Node: DeleteLinesStarting194495 Node: DeleteLinesNotContaining194892 Node: DeleteLinesNotMatchingFileItems195261 Node: DeleteLinesNotStartingFileItems195648 Node: DeleteNLines196014 Node: DeleteToLineMatching196448 Node: EditMode (binary)196927 Node: EditSplit197248 Node: EmptyEntireFilePlease198088 Node: ElseDefineClasses198314 Node: EndGroup198510 Node: EndLoop198700 Node: ExpandVariables198879 Node: ExpireAfter editfiles199270 Node: Filter199473 Node: FixEndOfLine199686 Node: ForEachLineIn200130 Node: GotoLastLine200542 Node: HashCommentLinesContaining200774 Node: HashCommentLinesMatching201099 Node: HashCommentLinesStarting201446 Node: IfElapsed (editing)201772 Node: IncrementPointer201968 Node: Inform (editing)202598 Node: InsertFile203080 Node: InsertLine203682 Node: LocateLineMatching204197 Node: PercentCommentLinesContaining204714 Node: PercentCommentLinesMatching205063 Node: PercentCommentLinesStarting205421 Node: Prepend (editing)205765 Node: PrependIfNoLineMatching206160 Node: PrependIfNoSuchLine206571 Node: Recurse (editing)206927 Node: ReplaceLineWith207171 Node: ReplaceAll With207527 Node: ReplaceFirst208477 Node: ReplaceLinesMatchingField209138 Node: Repository209890 Node: ResetSearch210325 Node: RunScript210622 Node: RunScriptIfLineMatching211388 Node: RunScriptIfNoLineMatching211950 Node: SetCommentStart212519 Node: SetCommentEnd212929 Node: SetLine213386 Node: SetScript213665 Node: SlashCommentLinesContaining213927 Node: SlashCommentLinesMatching214258 Node: SlashCommentLinesStarting214616 Node: SplitOn214940 Node: SysLog215445 Node: Umask215702 Node: UnCommentLinesContaining215923 Node: UnCommentLinesMatching216333 Node: UnCommentsNLines216742 Node: UnCommentToLineMatching217415 Node: UnsetAbort217765 Node: UseShell218004 Node: WarnIfFileMissing218435 Node: WarnIfLineContaining218719 Node: WarnIfLineMatching219050 Node: WarnIfLineStarting219370 Node: WarnIfNoLineContaining219694 Node: WarnIfNoLineMatching220031 Node: WarnIfNoLineStarting220364 Node: WarnIfNoSuchLine220698 Node: Editfiles on Binary Files220988 Node: files222513 Node: Syntax223014 Node: Recursion232916 Node: Directory permissions233714 Node: Checksums and change management234534 Node: home directive235878 Node: Owner and group wildcards237059 Node: Files linkchildren237530 Node: touch238019 Node: create238395 Node: filters238751 Node: Complete filter examples244403 Node: groups245936 Node: homeservers250149 Node: ignore252413 Node: import254007 Node: interfaces255058 Node: links255791 Node: Single links257251 Node: Multiple Links263032 Node: Link Children264172 Node: Relative and absolute links267340 Node: Hard links268464 Node: mailserver269771 Node: methods270935 Node: localhost examples276060 Node: remotehost examples281969 Node: miscmounts284175 Node: mountables285449 Node: processes286978 Node: packages297727 Node: rename312956 Node: required313158 Node: resolve313337 Node: scli315118 Node: shellcommands317139 Node: strategies323522 Node: tidy324834 Node: unmount333498 Node: Cfservd.conf and cfrun reference334857 Node: cfservd control337770 Node: IP address ranges338398 Node: AllowConnectionsFrom339363 Node: AllowMultipleConnectionsFrom340058 Node: AllowUsers340867 Node: AutoExecCommand341931 Node: AutoExecInterval342154 Node: BindToInterface in cfservd342400 Node: ChecksumDatabase in cfservd342965 Node: cfrunCommand343750 Node: DenyBadClocks344210 Node: DenyConnectionsFrom344652 Node: cfservd HostnameKeys345028 Node: cfservd IfElapsed345734 Node: LogAllConnections346179 Node: LogEncryptedTransfers346642 Node: MaxConnections346966 Node: TrustKeysFrom347310 Node: DynamicAddresses348056 Node: admit grant and deny349408 Node: root=349648 Node: encrypt=350990 Node: SkipVerify351352 Node: cfrun352127 Node: Firewalls and NATs357107 Node: Cfexecd reference358331 Node: Problem solving361760 Node: cf.preconf bootstrap file361988 Node: cfrc resource file364254 Node: Example configuration file367129 Node: cfagent.conf367607 Node: cf.groups368693 Node: cf.main370140 Node: cf.site375491 Node: cf.motd386458 Node: cf.users387512 Node: cf.solaris391147 Node: cf.linux396654 Node: cf.freebsd398874 Node: cfservd.conf400594 Node: Variable Index401719 Node: Concept Index418373 Node: FAQ Index457077  End Tag Table cfengine-2.2.10/doc/cfengine-Reference.texinfo0000644000175000001440000156533111135644106016123 00000000000000\input texinfo @c -*-texinfo-*-exec @c ********************************************************************* @c @c This is a TEXINFO file. It generates both TEX documentation and @c the "on line" documentation "info" files. @c @c The file is structured like a programming language. Each chapter @c starts with a chapter comment. @c @c Menus list the subsections so that an online info-reader can parse @c the file hierarchically. @c @c *********************************************************************** @c %** start of header @setfilename cfengine-Reference.info @settitle Cfengine v2 reference @setchapternewpage odd @c %** end of header @defindex mb @include version1.texi @titlepage @title cfengine v2 reference @subtitle Edition @value{EDITION} for version @value{VERSION} @author Mark Burgess @author Faculty of Engineering, Oslo University College, Norway @c @smallbook @page @vskip 0pt plus 1filll Copyright @copyright{} 2008 Mark Burgess This manual corresponds to CFENGINE Edition @value{EDITION} for version @value{VERSION} as last updated @value{UPDATED}. @end titlepage @c *************************** File begins here ************************ @ifinfo @dircategory System Utilities @direntry * cfengine Reference: (cfengine-Reference.info). Cfengine is a language based tool specifically designed for configuring and maintaining BSD and System-5-like operating systems attached to a TCP/IP network. @end direntry @end ifinfo @ifnottex @node Top, Reference introduction, (dir), (dir) @top Cfengine-Reference @end ifnottex @ifinfo Copyright @copyright{} 2008 Mark Burgess This manual corresponds to CFENGINE Edition @value{EDITION} for version @value{VERSION} as last updated @value{UPDATED}. @end ifinfo @ifhtml @html

COMPLETE TABLE OF CONTENTS

This manual is for version @value{VERSION} of cfengine and was last updated on the @value{UPDATED}.

Summary of contents

@end html @end ifhtml @c ********************************************************************** @c CHAPTER @c ********************************************************************** @menu * Reference introduction:: * Cfkey:: * Cfshow:: * Cfagent reference:: * Cfservd.conf and cfrun reference:: * Cfexecd reference:: * Problem solving:: * Example configuration file:: * Variable Index:: * Concept Index:: * FAQ Index:: @end menu @node Reference introduction, Cfkey, Top, Top @chapter Introduction to reference manual The purpose of the cfengine reference manual is to collect together and document the raw facts about the different components of cfengine. Once you have become proficient in the use of cfengine, you will no longer have need of the tutorial. The reference manual, on the other hand, changes with each version of cfengine. You will be able to use it online, or in printed form to find out the details you require to implement configurations in practice. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @menu * Installation:: * Work directory:: * Hard classes:: * Filenames and paths:: * Debugging with signals:: @end menu @node Installation, Work directory, Reference introduction, Reference introduction @section Installation @c chew begin Dependencies In order to install cfengine, you should first ensure that the following packages are installed. @table @r @item @b{OpenSSL} Open source Secure Sockets Layer for encryption.@*URL: @url{http://www.openssl.org} @item @b{BerkeleyDB} (version 3.2 or later) Light-weight flat-file database system.@*URL: @url{http://www.oracle.com/technology/products/berkeley-db/index.html} @end table @c chew end Dependencies @noindent The preferred method of installation is then @smallexample tar zxf cfengine-x.x.x.tar.gz cd cfengine-x.x.x ./configure make make install @end smallexample @noindent This results in binaries being installed in @file{/usr/local/sbin}. Since this is not necessarily a local file system on all hosts, users are encouraged to keep local copies of the binaries on each host, inside the cfengine trusted work directory. @node Work directory, Hard classes, Installation, Reference introduction @section Work directory In order to achieve the desired simplifications, it was decided to reserve a private work area for the cfengine tool-set. @c chew begin Work directory In cfengine 1.x, the administrator could choose the locations of configuration files, locks, and logging data independently. In cfengine 2.x, this diversity has been simplified to a single directory which defaults to @file{/var/cfengine} (similar to @file{/var/cron}): @w{} @smallexample /var/cfengine /var/cfengine/bin /var/cfengine/inputs /var/cfengine/outputs @end smallexample @c chew end Work directory The installation location @file{/usr/local/sbin} is not necessarily a local file system, and cannot therefore be trusted to a) be present, and b) be authentic on an arbitrary system. Similarly, a trusted cache of the input files must now be maintained in the @file{inputs} subdirectory. When cfengine is invoked by the scheduler, it reads only from this directory. It is up to the user to keep this cache updated, on each host. This simplifies and consolidates the cfengine resources in a single place. The environment variable @code{CFINPUTS} still overrides this default location, as before, but in its absence or when called from the scheduler, this becomes the location of trusted files. A special configuration file @file{update.conf} is parsed and run before the main configuration is parsed, which is used to ensure that the currently caches policy is up-to-date. This has private classes and variables. @cindex @file{update.conf} If no value is set for @code{CFINPUTS}, then the default location is the trusted cfengine directory @file{/var/cfengine/inputs}. The @file{outputs} directory is now a record of spooled run-reports. These are mailed to the administrator, as previously, or can be copied to another central location and viewed in an alternative browser.. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Hard classes, Filenames and paths, Work directory, Reference introduction @section Cfengine hard classes A single class can be one of several things: @c chew start Hard classes @itemize @bullet @item The name of an operating system architecture e.g. @code{ultrix}, @code{sun4}, etc. This is referred to as a @emph{hard class}. @item The unqualified name of a particular host. If your system returns a fully qualified domain name for your host, cfagent truncates it at the first dot. @item The name of a user-defined group of hosts. @item A day of the week (in the form @code{Monday, Tuesday, Wednesday, ..}). @item An hour of the day (in the form @code{Hr00, Hr01 ... Hr23}). @item Minutes in the hour (in the form @code{Min00, Min17 ... Min45}). @item A five minute interval in the hour (in the form @code{Min00_05, Min05_10 ... Min55_00}) @item A day of the month (in the form @code{Day1, Day2, ... Day31}). @item A month (in the form @code{January, February, ... December}). @item A year (in the form @code{Yr1997, Yr2004}). @item An arbitrary user-defined string. @item The IP address octets of any active interface (in the form @code{@w{ipv4_192_0_0_1}}, @code{@w{ipv4_192_0_0}}, @code{@w{ipv4_192_0}}, @code{@w{ipv4_192}}). @item The name of all interfaces Cfengine can find, in the form @code{net_iface_eth0}. @end itemize @c chew end Hard classes To see all of the classes define on a particular host, run @smallexample host# cfagent -p -v @end smallexample as a privileged user. Note that some of the classes are set only if a trusted link can be established with cfenvd, i.e. if both are running with privilege, and the @file{/var/cfengine/state/env_data} file is secure. More information about classes can be found in connection with @code{allclasses}. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Filenames and paths, Debugging with signals, Hard classes, Reference introduction @section Filenames and paths @c chew start Unix filenames Filenames in Unix-like operating systems use for their directory separator the forward slash '/' character. All references to file locations must be absolute pathnames in cfengine, i.e. they must begin with a complete specification of which directory they are in. For example: @smallexample /etc/passwd /usr/local/masterfiles/distfile @end smallexample @noindent The only place where it makes sense to refer to a file without a complete directory specification is when searching through directories for different kinds of file, e.g. @smallexample tidy: /home/user pattern=core age=0 recurse=inf @end smallexample @noindent Here, one can write @file{core} without a path, because one is looking for any file of that name in a number of directories. @c chew end Unix filenames @c chew start Windows filenames The Windows operating systems traditionally use a different filename convention. The following are all valid absolute file names under Windows: @smallexample c:\winnt c:/winnt /var/cfengine/inputs //@var{fileserver}/share2/dir @end smallexample The `drive' name ``C:'' in Windows refers to a partition or device. Unlike Unix, Windows does not integrate these seamlessly into a single file-tree. This is not a valid absolute filename: @smallexample \var\cfengine\inputs @end smallexample Paths beginning with a backslash are assumed to be win32 paths. They must begin with a drive letter or double-slash server name. @c chew end Windows filenames @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Debugging with signals, , Filenames and paths, Reference introduction @section Debugging with signals It is possible to turn debugging output on or off on a running cfagent. This is useful for troubleshooting the cause of hangups, or for getting debugging output from a cfagent launched from cfexecd. A running cfagent process that receives a SIGUSR1 will immediately begin to behave as if it had been invoked with the '-d2' option. A SIGUSR2 will cause a running cfagent to run as if the '-d2' option had not been invoked. Note that this output is often quite verbose. @c ********************************************************************** @c CHAPTER @c ********************************************************************** @menu * Cfagent reference:: * Cfservd.conf and cfrun reference:: * Cfexecd reference:: * Problem solving:: * Example configuration file:: * Variable Index:: * Concept Index:: * FAQ Index:: @end menu @node Cfkey, Cfshow, Reference introduction, Top @chapter Cfkey reference @c chew start Key generation The very first thing you should do on every host is to establish a public-private key pair. To do this, you need to run the program @smallexample everyhost# cfkey @end smallexample @noindent on every host. This program needs to produce random numbers, and needs a source of randomness. A good strategy is to install and run the @file{cfenvd} program for a week or two in advance of deploying cfengine 2, since @file{cfenvd} collects random events, which are an excellent source of entropy for random number generation. @cindex Key entropy and cfenvd @cindex cfenvd and key entropy If you get the error message ``PRNG not seeded'', it means that insufficient data were found in order to make a random key. In that case, run @file{cfenvd} for a few days more and try again. @cindex PRNG not seeded @c chew end Key generation @c ********************************************************************** @c CHAPTER @c ********************************************************************** @menu * Cfagent reference:: * Cfservd.conf and cfrun reference:: * Cfexecd reference:: * Problem solving:: * Example configuration file:: * Variable Index:: * Concept Index:: * FAQ Index:: @end menu @node Cfshow, Cfagent reference, Cfkey, Top @chapter Cfshow reference The @code{cfshow} command was introduced in cfengine 2.1.11 in order to provide a simple way to show some of the data stored by cfagent for operational purposes. @smallexample everyhost# cfshow -a everyhost# cfshow -l everyhost# cfshow -c everyhost# cfshow -s everyhost# cfshow -p everyhost# cfshow -f cfagent.conf -r linux.* @end smallexample @noindent The command line options are @table @samp @item -a @code{--active} This prints a list of any currently active locks, i.e. tasks that cfengine believes it is currently enagaged in. @item -A @code{--audit} This prints a history of cfengine's behaviour collected if the Auditing variable is true, @xref{Auditing}. The audit data are best viewed in html or parsed with xml, using the @code{--html} and @code{--xml} options. @item -c @code{--checksum} This lists all of the files and their current checksum values in the current checksum database. @item -C @code{--classes} This lists all of the classes that have been used on the system over the past year, with frequency probabilities to show their relative occurrance rates and last observed times. @item -H @code{--html} Generate output in web browser-friendly html. @item -l @code{--locks} This prints a list of the locks and the last times an active lock was secured for each cfengine acivity. This list is potentially very long. @item -s @code{--last-seen} This lists the IP addresses of all known peers and the times they were last engaged in communication with the current host. The expected interval between communications is also printed. See FriendStatus. The output format is in a form that can easily be parsed by user scripts. e.g. @smallexample IP + 192.168.1.101 192.168.1.101 @ [Tue Jan 23 16:13] not seen for (6.42) hrs, Av 0.02 +/- 0.01 hrs IP - 192.168.1.101 192.168.1.101 @ [Tue Jan 23 16:13] not seen for (6.42) hrs, Av 0.02 +/- 0.01 hrs @end smallexample Lines marked with a + represent successful attempts made by cfagent on the current host to connect to another host. Lines with a - are connections attempted (but not necessarily succeeded) into cfservd from another host's cfagent or cfrun. @item -r @code{--regex} @var{regex} Search the cfengine policy file (e.g. @file{cfagent.conf}) for rules that belong to classes matching the named regular expression. Note that the class "any" is not automatically matched and the search is based on the class text from the file. The output is not related to which classes are currently defined. @item -s @code{--performance} Shows the time in seconds required to complete copies and shell executions. @smallexample (0.00 mins @ Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfagent > /var/cfengine/bin/cfagent) (0.00 mins @ Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfenvd > /var/cfengine/bin/cfenvd) (0.02 mins @ Tue Feb 13 19:05) Av 0.02 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfexecd > /var/cfengine/bin/cfexecd) (0.00 mins @ Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Copy(localhost:/usr/local/sbin/cfservd > /var/cfengine/bin/cfservd) (6.41 mins @ Tue Feb 13 18:50) Av 0.00 +/- 0.00 for Exec(/usr/bin/updatedb --prunepaths=/media) (0.00 mins @ Tue Feb 13 19:05) Av 0.00 +/- 0.00 for Exec(/usr/sbin/ntpdate 128.39.74.16 > /dev/null) @end smallexample @item -X @code{--xml} Generate output in xml for parsing by scripts etc. @end table @c ********************************************************************** @c CHAPTER @c ********************************************************************** @menu * Cfagent reference:: * Cfservd.conf and cfrun reference:: * Cfexecd reference:: * Problem solving:: * Example configuration file:: * Variable Index:: * Concept Index:: * FAQ Index:: @end menu @node Cfagent reference, Cfservd.conf and cfrun reference, Cfshow, Top @chapter Cfagent reference @menu * Cfagent intro:: * The file cfagent.conf:: * Cfagent Runtime Options:: * Variable expansion and contexts:: * Cfengine classes:: * acl:: * alerts:: * binservers:: * broadcast:: * control:: * classes:: * copy:: * defaultroute:: * disks:: * directories:: * disable:: * editfiles:: * Editfiles on Binary Files:: * files:: * filters:: * groups:: * homeservers:: * ignore:: * import:: * interfaces:: * links:: * mailserver:: * methods:: * miscmounts:: * mountables:: * processes:: * packages:: * rename:: * required:: * resolve:: * scli:: * shellcommands:: * strategies:: * tidy:: * unmount:: @end menu @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Cfagent intro, The file cfagent.conf, Cfagent reference, Cfagent reference @section Cfagent intro Cfagent is the workhorse of cfengine. It interprets and computes the necessary strategies for implementing convergent maintenance. In order to carry out work efficiently, the agent groups similar actions together. The order of these actions is goverened by a list called the actionsequence. In many cases, cfagent will be able to complete all its work in a single pass of the actionsequence. However, in complex configurations, it is hard to resolve all of the ordering dependencies automatically in a single pass. Cfagent keeps track both of all actions that have been performed and of those that might still need to be performed (given that some actions depend on the later outcomes of others). If there is a possibility that an action ordering dilemma might occur, it runs a second pass of the actionsequence to more quickly resolve the dependency (avoiding the wait for next scheduled run). No actions are performed twice however, since the agent checks off actions that have already been performed to avoid unnecessary duplication. @menu * The file cfagent.conf:: * Cfagent Runtime Options:: @end menu @node The file cfagent.conf, Cfagent Runtime Options, Cfagent intro, Cfagent reference @section The file cfagent.conf @cartouche @w{} @smallexample control: @var{classes}:: domain = ( @var{DNS-domain-name} ) classes: @var{Class/Group definitions} import: @var{Files to import} # other items @end smallexample @end cartouche @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Cfagent Runtime Options, Variable expansion and contexts, The file cfagent.conf, Cfagent reference @section Cfagent runtime options @noindent Note that GNU long options are available with the syntax @code{--longoption}. The long names are given in brackets. @table @samp @item -a (@code{--sysadm}) Print only the name of the system administrator then quit. @item -A (@code{--auto}) Can be used to signify an automatic run of cfengine, as opposed to a manual run. The distinction is not predetermined. Use of this option currently causes cfengine to ignore locks. This option is reserved for future development. @item -b (@code{--force-net-copy}) Normally cfengine detects attempts to copy from a server via the network that will loop back to the localhost. It then avoids using the network to make the copy. This option forces cfengine to copy using the network. @emph{Yes, someone thinks this is useful!} @item -c (@code{--no-check-files}) Do not check file systems for ownership / permissions etc. @item -C (@code{--no-check-mounts}) Check mount points for consistency. If this option is specified then directories which lie in the ``mount point'' area are checked to see whether there is anything mounted on them. Normally this is @emph{off} since not all machines use mounted file systems in the same way. e.g. HPUX does not generally operate with partitions, but nevertheless one might wish to mimick a partition-like environment there, but it would be irritating to be informed that nothing was mounted on the mount point. @item -d (@code{--debug}) Enable debugging output. Normally you will want to send this to a file using the shell script command or a pipe. -d1 shows only parsing output. -d2 shows only runtime action output. -d0 shows both levels. Debugging ouput is intended mainly for the author's convenience and is not a supported feature. The details of this output may change at any time. @item -D (@code{--define}) Define a compound class symbol of the form @emph{alpha.beta.gamma}. @item -e (@code{--no-edits}) Suppress file editing. @item -E (@code{--enforce-links}) Globally force links to be created where plain files or links already exist. Since this option is a big hammer, you have to use it in interactive mode and answer a yes/no query before cfengine will run like this. @item -f (@code{--file}) Parse filename after this switch. By default cfengine looks for a file called @emph{cfengine.conf} in the current directory. @item -h (@code{--help}) Help information. Display version banner and options summary. @item -H (@code{--no-hard-classes}). Prevents cfengine from generating any built-in class name information. Can be used for emulation purposes. @cindex Internal classes, switching off @cindex Switching off built-in classes @item -i (@code{--no-ifconfig}) Do not attempt to configure the local area network interface. @item -I (@code{--inform}) Switches on the inform output level, whereby cfengine reports everything it changes.. @item -k (@code{--no-copy}) Do not copy/image any files. @item -K (@code{--no-lock}) Ignore locks when running. @item -l (@code{--traverse-links}) Normally cfengine does not follow symbolic links when recursively parsing directories. This option will force it to do so. @item -L (@code{--delete-stale-links}) Delete links which do not point to existing files (except in user home directories, which are not touched). @item -m (@code{--no-mount}) Do not attempt to mount file systems or edit the filesystem table. @item -M (@code{--no-modules}) Ignore modules in actionsequence. @item -n (@code{--recon},@code{--dry-run},@code{--just-print}) No action. Only print what has to be done without actually doing it. @item -N (@code{--negate},@code{--undefine}) Cancel a set of classes, or undefine (set value to @emph{false}) a compound class of the form @emph{alpha.beta.gamma}. @item -p (@code{--parse-only}) Parse file and then stop. Used for checking the syntax of a program. You do not have to be superuser to use this option. @item -P (@code{--no-processes}) Do not execute the processes action. @item -q (@code{--no-splay}) Switch off host splaying (sleeping). @item -Q (@code{--quert}) Query the values of the comma separated list of variable names. @item -s (@code{--no-commands}) Do not execute scripts or shell commands. @item -S (@code{--silent}) Silence run time warnings. @item -t (@code{--no-tidy}) Do not tidy file systems. @item -u (@code{--use-env}) Causes cfengine to generate an environment variable @samp{CFALLCLASSES} which can be read by child processes (scripts). This variable contains a summary of all the currently defined classes at any given time. This option causes some System V systems to generate a Bus Error or segmentation fault. The same information is available from the cfengine built-in variable @code{$(allclasses)} and can be passed as a parameter to scripts. @cindex Environment variable CFALLCLASSES @cindex CFALLCLASSES in a file @cindex @file{allclasses} file @vindex CFALLCLASSES When this variable grows too large for embedding one can also access a complete list of current classes in @file{/var/cfengine/state/allclasses}. @item -U (@code{--underscore-classes}). When this option is set, cfengine adds an underscore to the beginning of the hard system classes (like @code{_sun4}, @code{_linux} etc. The longer compound classes are not underscored, since these are already complex and would unlikely result in collisions.) This can be used to avoid naming conflicts if you are so unjudicious as to name a host by the name of a hard class. Other classes are not affected. @item -v (@code{--verbose}) Verbose mode. Prints detailed information about actions and state. @item -V (@code{--version}) Print only the version string and then quit. @item -x (@code{--no-preconf}) Do not execute the @file{cf.preconf} net configuration file. @item -X (@code{--no-links}) Do not execute the @code{links} section of a program. @item -w (@code{--no-warn},@code{--quiet}) Do not print warning messages. @item -z (@code{--schedule}) Print the exec schedule for the LAN (used by cfexecd). @end table In version 2.0.4, an abbreviation for actionsequence exclusions was added: @w{} @smallexample $ cfagent --avoid resolve,copy $ cfagent --just tidy --just shellcommands @end smallexample @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Variable expansion and contexts, Cfengine classes, Cfagent Runtime Options, Cfagent reference @section Variable expansion and contexts Variables in cfengine 2 are defined in contexts. Variables in a given context refer to the different phases of execution of cfengine: global, update and main. In the "current" context, variables have the form @smallexample $(variable) $@{variable@} @end smallexample and are expanded either on parsing or at execution. Variables that cannot be expanded remain as dollar strings. Variables belonging to a context that is not the current one may be referred to as @smallexample $(@var{context}.variable) or $@{@var{context}.variable@} @end smallexample Note carefully that cfengine requires parentheses or braces around variable names. Unlike in the shell, they cannot be omitted. There is no difference between these forms as far as cfengine is concerned. Some authors like to use the @code{()} form for cfengine variables, to distinguish them with shell variables in command strings. The @code{()} form does not work in function arguments, except inside quoted strings. Consider the example: @smallexample $(global.env_time) @end smallexample Some variables in cfengine are associative arrays (as made famous by Perl). Such arrays are referred to by square brackets: @smallexample $(array[key]) $(array[$(key)]) @end smallexample @noindent @c ------------------------------------------------------------------------------- @c SUBSECTION @c ------------------------------------------------------------------------------- @menu * Setting variables with functions:: * Special variables:: * Iteration over lists:: @end menu @node Setting variables with functions, Special variables, Variable expansion and contexts, Variable expansion and contexts @subsection Setting variables with functions A number of special functions can be used to set variables in cfengine. You can import values from the execution of a shell command by prefixing a command with the word @code{exec}. This method is deprecated as of cfengine version 2; use the @code{ExecResult} function instead. @cindex Variables, setting to result of a shell command @vindex @code{exec} @smallexample control: # old method listing = ( "exec /bin/ls -l" ) # new method listing = ( ExecResult(/bin/ls -l) ) @end smallexample @noindent This sets the variable `listing' to the output of the command in the quotes. @cindex Built-in functions @cindex Functions, built-in @cindex Random numbers Some other built-in functions are @table @code @item A(@var{X},@var{Y}) Makes an associative array entry, associating @var{X} and @var{Y}. For instance: @smallexample control: assoc_array = ( A(B,"is for bird") A(C,"is for cat") ) @end smallexample @noindent results in: @smallexample OBJECT: main 4569 : assoc_array[B]=is for bird 4630 : assoc_array[C]=is for cat @end smallexample @cindex Associative arrays. Another example: @smallexample control: binhost = ( A(linux,machine1) A(solaris,machine2) ) copy: # Contact machine 1 for linux # Contact machine 2 for solaris /etc/source dest=/etc/receve server=$(binhost[$(class)]) @end smallexample @item ExecResult(@var{command}) Executes the named command without a shell-wrapper and inserts the output into the variable. Note that, when this is used in cfengine built-in list variables, any spaces are interpreted as list separators. In other lists, normal rules for iteration apply. @item ExecShellResult(@var{command}) Executes the named command with a shell-wrapper and inserts the output into the variable. Note that, when this is used in cfengine built-in list variables, any spaces are interpreted as list separators. In other lists, normal rules for iteration apply. @item RandomInt(@var{a},@var{b}) Generate a random integer between a and b. @item ReadArray(@var{filename},@var{fileformat},@var{separator},@var{comment},@var{Max number of bytes}) Reads up to a maximum number of bytes from a properly formatted file into a one-dimensional associated array. File formats are: @table @code @item autokey If this format is specified, @code{ReadArray} tries to interpret the file as a table of items separated with the separator character. Blank lines and comments (to end of line) are ignored. Items are keyed numerically starting from 1 to the maximum number in the file. The newline @code{$(n)} is always considered to be a separator, no matter what the current separator is. @cindex Associative arrays. @item textkey If this format is specified, @code{ReadArray} tries to interpret the file as a list of lines of the form: @smallexample key,value @end smallexample @end table @item ReadFile(@var{filename},@var{Max number of bytes}) Read a maximum number of bytes from a file. @cindex ReadFile @item ReadTable(@var{filename},@var{fileformat},@var{separator},@var{comment},@var{Max number of bytes}) Reads up to a maximum number of bytes from a properly formatted file into a two-dimensional associated array. @table @code @item autokey If this format is specified, @code{ReadArray} tries to interpret the file as a table of items separated with the separator character. Blank lines and comments (to end of line) are ignored. Items are keyed numerically starting from 1 to the maximum number in the file. Any lines that do not contain the correct number of separators cause the function to fail without making any assignment. @cindex ReadTable @cindex Read array from table @item textkey If this format is specified, @code{ReadArray} tries to interpret the file as a list of lines of the form: @smallexample key1,key2,value1 key3,key4,value2 @end smallexample This variable would then be references as $(table[key1][key2]). @end table @item ReadList(@var{filename},@var{fileformat},@var{comment},@var{Max number of bytes}) Reads up to a maximum number of bytes from a properly formatted file into a listvariable. File formats are: @table @code @item lines If this format is specified, @code{ReadList} tries to interpret the file as a list of items on separate lines. The value returned is a list formatted by the @code{Split} character. @cindex Associative arrays. @end table @w{} @smallexample hosts = ( ReadList(/var/cfengine/inputs/datafile,lines,#,1000) ) @end smallexample @item ReadTCP(@var{host/IP},@var{portnumber},@var{send string},@var{Max number of bytes}) Reads up to a maximum number of bytes from a TCP service. Can be used to test whether certain services are responding to queries. It is recommended that this be used primarily to check services running on localhost. Bear in mind that this clause, executed on 100 hosts will produce the effect of a distributed denial of service attack, so the probe should be restricted to a single representative tester-host. For example: @smallexample one_host_only:: # USE WITH CAUTION ! probewww = ( ReadTCP(localhost,80,'GET index.html',1000) ) @end smallexample Or testing a network service: @smallexample control: checkhost:: probesmtp = ( ReadTCP(localhost,25,"",1024) ) probewww = ( ReadTCP(project.iu.hio.no,80,"GET /viewcvs HTTP/1.0 $@{n@}$@{n@}",1024) ) classes: viewcvs_error = ( RegCmp(".*Python Traceback.*","$@{probewww@}") ) alerts: viewcvs_error:: "Received viewcvs error from web server" @end smallexample @item SelectPartitionNeighbours(@var{filename},@var{comment},@var{Policy},@var{group size}) This function is for use in peer to peer monitoring applications. It allows individual hosts to identify themselves as part of a group and find their peers. The function returns a list variable, delimited by the list separation character, for use with Split. @cindex SelectPartitionGroup @cindex Peer to peer methods @w{} @smallexample control: allpeers = ( SelectPartitionNeighbours(/var/cfengine/inputs/cfrun.hosts,#,random,4) ) copy: /data/file dest=/p2prepository/file server=$(allpeers) @end smallexample @item SelectPartitionLeader(@var{filename},@var{comment},@var{Policy},@var{group size}) This function is for use in peer to peer monitoring applications. It allows individual hosts to identify themselves as part of a group and select a leader. This function reads a text file of hostnames or IP addresses, one host per line, with blank lines and comments and partitions it into groups of a fixed size. It then returns picks a leader for the the group and returns its name as the value of the function. @cindex SelectPartitionLeader @cindex Peer to peer methods @w{} @smallexample control: leader = ( SelectPartitionLeader(/var/cfengine/inputs/cfrun.hosts,#,random,4) ) copy: /data/file dest=/p2prepository/file server=$(leader) @end smallexample @end table Note that functions should have no spaces between the function name and the leading parenthesis, but should themselves be surrounded by white space. @noindent For example: @smallexample control: variable2 = ( RandomInt(0,23) ) variable3 = ( ExecResult(/bin/ls -a /opt) ) myexcerpt = ( ReadFile("/etc/services",220) ) listvar = ( ReadArray(/tmp/array,textkey,",","#",100) ) @end smallexample In the latter case, the file could look like this: @smallexample host$ more /tmp/array one,String to tbe read two,Nothing string three,Everything comes in threes @end smallexample @noindent and results in the definition of (verify with @code{cfagent -p -d3}): @smallexample OBJECT: main 960 : listvar[one]=String to tbe read 259 : listvar[two]=Nothing string 224 : listvar[three]=Everything comes in threes @end smallexample @cindex Array example @cindex Read array from file @cindex Array from file @cindex ReadArray @c ------------------------------------------------------------------------------- @c SUBSECTION @c ------------------------------------------------------------------------------- @menu * Special variables:: * Iteration over lists:: @end menu @node Special variables, Iteration over lists, Setting variables with functions, Variable expansion and contexts @subsection Special variables Variables are referred to in either of two different ways, depending on your taste. You can use the forms @code{$(variable)} or @code{$@{variable@}}. The variable in braces or parentheses can be the name of any user defined macro, environment variable or one of the following special built-in variables. @table @code @item AllClasses A long string in the form @samp{CFALLCLASSES=class1:class2...}. This variable is a summary of all the defined classes at any given time. It is always kept up to date so that scripts can make use of cfengine's class data. @cindex CFALLCLASSES @vindex CFALLCLASSES @cindex Class data and scripts @cindex Scripts, passing classes to @item arch The current detailed architecture string---an amalgamation of the information from @emph{uname}. @emph{A constant}. @vindex $(arch) @item binserver The default server for binary data. @emph{A constant}. @vindex $(binserver) @item cfinputs_version The version string of the current configuration, used for version control and auditing. @cindex Auditing @cindex Version control @vindex cfinputs_version @item ChecksumDatabase If set to the name of a file, cfagent will use this to store checksums of important files, and give `tripwire functionality', @xref{ChecksumDatabase in cfagent}. This option was deprecated in 2.1.22. @item ChecksumUpdates If set to `on', security information is automatically updated. @item class The currently defined system hard-class (e.g. @code{sun4}, @code{hpux}). @emph{A constant}. @vindex $(class) @item date The current date string. Note that if you use this in a shell command it might be interpreted as a list variable, since it contains the default separator @samp{:}. @vindex $(date) @item domain The currently defined domain. @vindex $(domain) @item EmailFrom The email address from whom email from cfexecd should appear to originate. @item EmailMaxLines Most lines of output to email from a single cfexecd-induced run of cfagent. If undefined, defaults to 100. If set to 0, no email is sent by cfexecd. If set to @code{inf}, no maximum is enforced. @vindex $@{EmailMaxLines@} @item EmailTo The E-mail address to whom mail should be sent (overrides @code{sysadm} variable). @item faculty The faculty or site as defined in control (see @code{site}). @vindex $(faculty) @item fqhost The fully qualified hostname of the system. @vindex $(fqhost) @item host The hostname of the machine running the program. @vindex $(host) @item ipaddress The numerical form of the Internet address of the host currently running cfengine found by a reverse lookup in DNS. @vindex $(ipaddress) @item ipv4[@var{interface}] The IPv4 address of the named interface as determined from a probe of the interfaces. This variable belongs in the global context and refers to as in the following examples: @smallexample $@{global.ipv4[hme0]@} $@{global.ipv4[eth0]@} @end smallexample @item MaxCfengines The maximum number of cfengines which should be allowed to run concurrently on the system. This can prevent excessive load due to unintentional spamming in situations where several cfengines are started independently. The default value is unlimited. @vindex MaxCfengines @item ostype A short for of @code{$(arch)}. @item OutputPrefix This quoted string can be used to change the default `cfengine:$@{hostname@}' prefix on output lines to something else. You might wish to shorten the string, or have a different prefix for different hosts. The default is equivalent to, @smallexample OutputPrefix = ( "cfengine:$(host):") @end smallexample @vindex OutputPrefix @item RepChar The character value of the string used by the file repository in constructing unique filenames from path names. This is the character which replaces @samp{/}. @vindex repchar @item site This variable is identical to @code{$(faculty)} and may be used interchangeably. @vindex $(site) @item smtpserver The name of the host to which mail output should be sent. @item split The character on which list variables are split. @vindex split @item sysadm The name or mail address of the system administrator. @vindex $(sysadm) @item timezone The current timezone as defined in @code{control}. @vindex $(timezone) @item UnderscoreClasses If this is set to `on' cfengine uses hard classes which begin with an underscore to avoid name collisions, @xref{Cfagent Runtime Options}. @vindex underscoreclasses @cindex underscoreclasses @cindex Name collision @cindex Hostname collision @cindex Hard class name collision @vindex underscoreclasses @item version The current cfengine version string as defined in the code. @vindex $(version) @item year The current year. @vindex $(year) @end table @noindent These variables are kept special because they play a special role in setting up a system configuration. You are encouraged to use them to define fully generalized rules in your programs. Variables can be used to advantage in defining filenames, directory names and in passing arguments to shell commands. The judicious use of variables can reduce many definitions to a single one if you plan carefully. @cartouche @emph{NOTE: the above control variables are not case sensitive, unlike user macros, so you should not define your own macros with these names.} @end cartouche The following variables are also reserved and may be used to produce troublesome special characters in strings. @table @code @item cr Expands to the carriage return character. @vindex $(cr) @item colon Expands to the colon @samp{:} character. @vindex $(colon) @item dblquote Expands to a double quote @code{"} @vindex $(dblquote) @item dollar Expands to @samp{$}. @vindex $(dollar) @item lf Expands to a line-feed character (Unix end of line). @vindex $(lf) @item n Expands to a newline character. @vindex $(n) @item quote Expands to a single quote @code{'}. @vindex $(quote) @item spc Expands simply to a single space. This can be used to place spaces in filenames etc. @vindex $(spc) @item tab Expands to a single tab character. @vindex $(tab) @end table @c ------------------------------------------------------------------------------- @c SUBSECTION @c ------------------------------------------------------------------------------- @node Iteration over lists, , Special variables, Variable expansion and contexts @subsection Iteration over lists Variables can be used as iterators in some situations. Iteration over lists is currently rather limited in cfengine and is something to be improved on in a future version. When a variable is used as an iterator, a character is chosen to represent a list separator, as in the shell @samp{IFS} variable. The default separator is the colon @samp{:} character: @smallexample control: listvar = ( one:two:three:four ) @end smallexample The action that contains a variable to be interpreted as a list appears as separate actions, one for each case: @smallexample shellcommand: "/bin/echo $(listvar)" @end smallexample is equivalent to @smallexample shellcommand: "/bin/echo one" "/bin/echo two" "/bin/echo three" "/bin/echo four" @end smallexample If multiple iterators are used, these are handled as nested loops: @smallexample cfengine::/bin/echo one 1: one 1 cfengine::/bin/echo one 2: one 2 cfengine::/bin/echo one 3: one 3 cfengine::/bin/echo one 4: one 4 cfengine::/bin/echo two 1: two 1 cfengine::/bin/echo two 2: two 2 cfengine::/bin/echo two 3: two 3 cfengine::/bin/echo two 4: two 4 cfengine::/bin/echo three: three 1 cfengine::/bin/echo three: three 2 cfengine::/bin/echo three: three 3 cfengine::/bin/echo three: three 4 cfengine::/bin/echo four : four 1 cfengine::/bin/echo four : four 2 cfengine::/bin/echo four : four 3 cfengine::/bin/echo four : four 4 @end smallexample Where iterators are not allowed, the implied lists are treated as scalars: @smallexample alerts: amnexus:: "do $(list1) $(list2)" @end smallexample e.g. @smallexample cfengine:: do one:two:three:four 1:2:3:4 @end smallexample Iterative expansion is currently restricted to: @itemize @bullet @item In the directory field of the admit/deny server access rules, @item In the `from' field of a copy action, @item In the server field of the copy action, @item In the directory field of the disable action, @item In the directory field of the files action, @item In the `to' field of a multiple link action, @item In the directory field of the required/disk action, @item In a resolve item. @item In the directory field of a tidy action, @item In the arguments, replyto and server attributes of methods. @item Names in the ignore action. @item A shellcommands body. @item In admit/deny path and attributes of cfserver. @end itemize @cindex split @cindex Iteration over lists @mbindex Iterating over lists @vindex split @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node Cfengine classes, acl, Variable expansion and contexts, Cfagent reference @section Cfengine classes @cindex classes A @emph{cfengine action} looks like this: @smallexample @var{action-type}: @var{compound-class}:: @var{declaration} @end smallexample @noindent A single class is an identifier that may consist of any alphanumeric character or the underscore, just like identifiers in ordinary programming languages. Classes that are derived from data like IP addresses or host names convert any other characters (like @samp{.} or @samp{-}) into underscores. A single class can be one of several things: @itemize @bullet @item The name of an operating system architecture e.g. @code{ultrix}, @code{sun4}, etc. This is referred to as a @emph{hard class}. @item The unqualified name of a particular host. If your system returns a fully qualified domain name for your host, cfagent truncates it at the first dot. @item The name of a user-defined group of hosts. @item A day of the week (in the form @code{Monday, Tuesday, Wednesday, ..}). @item An hour of the day (in the form @code{Hr00, Hr01 ... Hr23}). @item Minutes in the hour (in the form @code{Min00, Min17 ... Min45}). @item A five minute interval in the hour (in the form @code{Min00_05, Min05_10 ... Min55_00}) @item A quart hour (in the form @code{Q1, Q2, Q3, Q4}) @item An abbreviated time with quarter hour specified (in the form @code{Hr00_Q1, Hr23_Q4} etc.) @item A day of the month (in the form @code{Day1 ... Day31}). @item A month (in the form @code{January, February, ... December}). @item A year (in the form @code{Yr1997, Yr2004}). @item An arbitrary user-defined string. @item The IP address octets of any active interface (in the form @code{@w{ipv4_192_0_0_1}}, @code{@w{ipv4_192_0_0}}, @code{@w{ipv4_192_0}}, @code{@w{ipv4_192}}). @end itemize A compound class is a sequence of simple classes connected by dots or `pipe' symbols (vertical bars). For example: @cindex Compound classes @cindex Classes, compound @w{} @smallexample myclass.sun4.Monday:: sun4|ultrix|osf:: @end smallexample @noindent A compound class evaluates to `true' if all of the individual classes are separately true, thus in the above example the actions which follow @code{compound_class::} are only carried out if the host concerned is in @code{myclass}, is of type @code{sun4} and the day is Monday! In the second example, the host parsing the file must be either of type @code{sun4} @emph{or} @code{ultrix} @emph{or} @code{osf}. In other words, compound classes support two operators: AND and OR, written @samp{.} and @samp{|} respectively. From cfengine version 2.1.1, I bit the bullet and added @samp{&} as a synonym for the AND operator. Cfengine doesn't care how many of these operators you use (since it skips over blank class names), so you could write either @smallexample solaris|irix:: @end smallexample @noindent or @smallexample solaris||irix:: @end smallexample @noindent depending on your taste. On the other hand, the order in which cfengine evaluates AND and OR operations @emph{does} matter, and the rule is that AND takes priority over OR, so that @samp{.} binds classes together tightly and all AND operations are evaluated before ORing the final results together. This is the usual behaviour in programming languages. You can use round parentheses in cfengine classes to override these preferences. Cfengine allows you to define switch on and off dummy classes so that you can use them to select certain subsets of action. In particular, note that by defining your own classes, using them to make compound rules of this type, and then switching them on and off, you can also switch on and off the corresponding actions in a controlled way. The command line options @code{-D} and @code{-N} can be used for this purpose. See also @code{addclasses} in the Reference manual. @vindex -N option @vindex -D option @cindex Classes, defining and undefining @cindex NOT operator @cindex Logical NOT @vindex ! @cindex ! A logical NOT operator has been added to allow you to exclude certain specific hosts in a more flexible way. The logical NOT operator is (as in C and C++) @samp{!}. For instance, the following example would allow all hosts except for @code{myhost}: @smallexample @var{action}: !myhost:: @var{command} @end smallexample @noindent and similarly, so allow all hosts in a user-defined group @code{mygroup}, @emph{except} for @code{myhost}, you would write @w{} @smallexample @var{action}: mygroup.!myhost:: @var{command} @end smallexample @noindent which reads `mygroup AND NOT myhost'. The NOT operator can also be combined with OR. For instance @smallexample @var{class1}|!@var{class2} @end smallexample @noindent would select hosts which were either in class 1, or those which were not in class 2. Finally, there is a number of reserved classes. The following are hard classes for various operating system architectures. They do not need to be defined because each host knows what operating system it is running. Thus the appropriate one of these will always be defined on each host. Similarly the day of the week is clearly not open to definition, unless you are running cfengine from outer space. The reserved classes are: @smallexample ultrix, sun4, sun3, hpux, hpux10, aix, solaris, osf, irix4, irix, irix64 sco, freebsd, netbsd, openbsd, bsd4_3, newsos, solarisx86, aos, nextstep, bsdos, linux, debian, cray, unix_sv, GnU, NT @end smallexample @noindent If these classes are not sufficient to distinguish the hosts on your network, cfengine provides more specific classes which contain the name and release of the operating system. To find out what these look like for your systems you can run cfengine in `parse-only-verbose' mode: @smallexample cfagent -p -v @end smallexample @noindent and these will be displayed. For example, Solaris 2.4 systems generate the additional classes @code{sunos_5_4} and @code{sunos_sun4m}, @code{sunos_sun4m_5_4}. Cfengine uses both the unqualified and fully host names as classes. Some sites and operating systems use fully qualified names for their hosts. i.e. @code{uname -n} returns to full domain qualified hostname. This spoils the class matching algorithms for cfengine, so cfengine automatically truncates names which contain a dot `.' at the first `.' it encounters. If your hostnames contain dots (which do not refer to a domain name, then cfengine will be confused. The moral is: don't have dots in your host names! @emph{NOTE: in order to ensure that the fully qualified name of the host becomes a class you must define the domain variable.} The dots in this string will be replaced by underscores. @cindex Fully qualified names @cindex Dots in hostnames @cindex Host name gets truncated In summary, the operator ordering in cfengine classes is as follows: @cindex Operator ordering @mbindex Brackets (parentheses) in classes. @mbindex Parentheses in classes. @table @samp @item () Parentheses override everything. @item ! The NOT operator binds tightest. @item . & The AND operator binds more tightly than OR. @item | OR is the weakest operator. @end table @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @menu * Setting classes with special functions:: * AccessedBefore:: * ChangedBefore:: * ClassMatch:: * FileExists:: * GroupExists:: * HostRange:: * IsDefined:: * IsDir:: * IsLink:: * IsPlain:: * IsNewerThan:: * IPRange:: * PrepModule:: * Regcmp:: * ReturnsZero:: * ReturnsZeroShell:: * Strcmp:: * UserExists:: * IsGreaterThan:: * IsLessThan:: * Examples setting classes:: @end menu @node Setting classes with special functions, AccessedBefore, Cfengine classes, Cfengine classes @subsection Setting classes with special functions Cfengine provides a number of built-in functions for evaluating classes, based on file tests. Using these built-in functions is quicker than calling the shell @code{test} function. The time functions place their arguments in chronological order. @node AccessedBefore, ChangedBefore, Setting classes with special functions, Cfengine classes @subsection AccessedBefore @smallexample AccessedBefore(@var{f1},@var{f2}) @end smallexample True if file 1 was accessed more recently than file 2 (UNIX atime) @node ChangedBefore, ClassMatch, AccessedBefore, Cfengine classes @subsection ChangedBefore @smallexample ChangedBefore(@var{f1},@var{f2}) @end smallexample True if file 1's attributes were changed in any way more recently than file 2's (UNIX ctime) @node ClassMatch, FileExists, ChangedBefore, Cfengine classes @subsection ClassMatch @smallexample ClassMatch(@var{regexp}) @end smallexample True if the quoted regular expression matches one of the currently defined classes. It is wise to place ClassMatch at the end of your parsing in order to capture as many of the user-defined classes as possible. @smallexample classes: userdef = ( ClassMatch(.*linux.*) ) @end smallexample @node FileExists, GroupExists, ClassMatch, Cfengine classes @subsection FileExists @smallexample FileExists(@var{file}) @end smallexample True if the named file object (file/directory or link) exists. @node GroupExists, HostRange, FileExists, Cfengine classes @subsection GroupExists @smallexample GroupExists(@var{groupname}|@var{gid}) @end smallexample True if the groupname or group id is registered on the system. @node HostRange, IsDefined, GroupExists, Cfengine classes @subsection HostRange @smallexample HostRange(@var{basename},@var{start-stop}) @end smallexample True if the current relative domain name begins with basename and ends with an integer between start and stop. Note well: matching is case insensitive (both hostname and basename are converted to all lower case for comparison.) @node IsDefined, IsDir, HostRange, Cfengine classes @subsection IsDefined @smallexample IsDefined(@var{variable-id}) @end smallexample True if the named variable is defined. Note well: use the variable name, not its contents (that is, @code{IsDefined(var)}, and not @code{IsDefined($@{var@})}) @node IsDir, IsLink, IsDefined, Cfengine classes @subsection IsDir @smallexample IsDir(@var{f}) @end smallexample True if the file f is a directory @node IsLink, IsPlain, IsDir, Cfengine classes @subsection IsLink @smallexample IsLink(@var{f}) @end smallexample True if the file f is a symbolic link @node IsPlain, IsNewerThan, IsLink, Cfengine classes @subsection IsPlain @smallexample IsPlain(@var{f}) @end smallexample True if the file f is a plain file @node IsNewerThan, IPRange, IsPlain, Cfengine classes @subsection IsNewerThan @smallexample IsNewerThan(@var{f1},@var{f2}) @end smallexample True if file 2 was modified more recently than file 1 (UNIX mtime) @node IPRange, PrepModule, IsNewerThan, Cfengine classes @subsection IPRange @smallexample IPRange(@var{address-range}) @end smallexample True if the current host lies within the specified IP range @node PrepModule, Regcmp, IPRange, Cfengine classes @subsection PrepModule @smallexample PrepModule(@var{module},@var{arg1 arg2...}) @end smallexample True if the named module exists and can be executed. The module is assumed to follow the standard programming interface for modules (see Writing plugin modules in tutorial). Unlike actionsequence modules, these modules are evaluated immediately on parsing. Note that the module should be specified relative to the authorized module directory. @cindex Module directory @cindex PrepModule @cindex Modules executed immediately @node Regcmp, ReturnsZero, PrepModule, Cfengine classes @subsection Regcmp @smallexample Regcmp(@var{regexp},@var{string or list separated string}) @end smallexample True if the string matched the regular expression regexp. @node ReturnsZero, ReturnsZeroShell, Regcmp, Cfengine classes @subsection ReturnsZero @smallexample ReturnsZero(@var{command}) @end smallexample True if the named shell command returns with exit code zero (success). The command is executed without a shell wrapper. @node ReturnsZeroShell, Strcmp, ReturnsZero, Cfengine classes @subsection ReturnsZeroShell @smallexample ReturnsZeroShell(@var{command}) @end smallexample True if the named shell command returns with exit code zero (success) when executed in the environment of a shell wrapper. @node Strcmp, UserExists, ReturnsZeroShell, Cfengine classes @subsection Strcmp @smallexample Strcmp(@var{s1},@var{s2}) @end smallexample True if the string s1 exactly matches s2 @node UserExists, IsGreaterThan, Strcmp, Cfengine classes @subsection UserExists @smallexample UserExists(@var{username}|@var{uid}) @end smallexample True if the username or user id is registered on the system (this does not imply that the user can log in or has a home directory). @cindex IsGreatThan @cindex IsLessThan @cindex > @cindex < @node IsGreaterThan, IsLessThan, UserExists, Cfengine classes @subsection IsGreaterThan @smallexample IsGreaterThan(@var{s1},@var{s2}) @end smallexample Returns true if the value of s1 is greater than the value of s2. Note that, if the strings have numerical values, a numerical comparison is performed, otherwise a string comparison is used. @node IsLessThan, Examples setting classes, IsGreaterThan, Cfengine classes @subsection IsLessThan @smallexample IsLessThan(@var{s1},@var{s2}) @end smallexample Returns true if the value of s1 is less than the value of s2. Note that, if the strings have numerical values, a numerical comparison is performed, otherwise a string comparison is used. @smallexample control: actionsequence = ( files ) a = ( 2.12 ) b = ( 2.11 ) classes: lt = ( IsLessThan($@{a@},$@{b@}) ) gt = ( IsGreaterThan($@{a@},$@{b@}) ) alerts: lt:: "$(a) LESS THAN $(b)" gt:: "$(a) GREATER THAN $(b)" @end smallexample @node Examples setting classes, , IsLessThan, Cfengine classes @subsection Examples setting classes @noindent For example: @smallexample classes: access_to_dir = ( ReturnsZero(/bin/cd /mydir) ) compare = ( ChangedBefore(/etc/passwd_master,/etc/passwd) ) isplain = ( IsPlain(/tmp/import) ) inrange = ( IPRange(128.39.89.10-15) ) CIDR = ( IPRange(128.39.89.10/24) ) compute_nodes = ( HostRange(cpu-,01-32) gotinit = ( PrepModule(startup2,"arg1 arg2") ) @end smallexample @cindex Classes, built-in functions @cindex Testing files @cindex File types @cindex Comparing file objects @vindex ReturnsZero() @vindex ChangedBefore() @vindex IsPlain() @vindex IsDir() @vindex IsLink() @vindex IsNewerThan() @vindex AccessedBefore() @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node acl, alerts, Cfengine classes, Cfagent reference @section acl @cindex Access control lists @cindex ACLs @cartouche @w{} @smallexample acl: @var{class}:: @{ @var{acl-alias} @var{action} @} @end smallexample @end cartouche @noindent Cfengine's @code{ACL} feature is a common interface for managing filesystem access control lists (ACLs). An access control list is an extended file permission. It allows you to open or close a file to a named list of users (without having to create a group for those users); similarly, it allows you to open or close a file for a list of groups. Several operating systems have access control lists, but each typically has a different syntax and different user interface to this facility, making it very awkward to use. This part of a cfengine configuration simplifies the management of ACLs by providing a more convenient user interface for controlling them and---as far as possible---a common syntax. An ACL may, by its very nature, contain a lot of information. Normally you would set ACLs in a @code{files} command, @xref{files}, or a @code{copy} command, @xref{copy}. It would be too cumbersome to repeat all of the information in every command in your configuration, so cfengine simplifies this by first associating an alias together with a complex list of ACL information. This alias is then used to represent the whole bundle of ACL entries in a @code{files} or @code{copy} command. The form of an ACL is similar to the form of an @code{editfiles} command. It is a bundle of information concerning a file's permissions. @smallexample @{ @var{acl-alias} method:@b{overwrite}@var{/append} fstype:@var{posix/solaris/dfs/afs/hpux/nt} @var{acl_type}:@var{user/group}:@var{permissions} @var{acl_type}:@var{user/group}:@var{permissions} ... @} @end smallexample @noindent The name @var{acl-alias} can be any identifier containing alphanumeric characters and underscores. This is what you will use to refer to the ACL entries in practice. The method entry tells cfengine how to interpret the entries: should a file's ACLs be overwritten or only adjusted? Since the filesystems from different developers all use different models for ACLs, you must also tell cfengine what kind of filesystem the file resides on. Currently only Solaris and DCE/DFS ACLs are implemented. NOTE: if you set both file permissions and ACLs the file permissions override the ACLs. @c ..................................................... @c SUBSECTION @c ..................................................... @menu * ACEs:: * Solaris ACLs:: * DFS ACLs:: * NT ACLs:: * Windows ACL Example:: * Posix ACL Example:: @end menu @node ACEs, Solaris ACLs, acl, acl @subsection Access control entries An access control list is build of any number of individual access control entries (ACEs). The ACEs has the following general syntax: @smallexample @var{acl_type}:@var{user/group}:@var{permissions} @end smallexample @noindent The user or group is sometimes referred to as a @emph{key}. @cindex ACL key For an explanation of ACL types and their use, refer to your local manual page. However, note that for each type of filesystem, there are certain entries which must exist in an ACL. If you are creating a new ACL from scratch, you must specify these. For example, in Solaris ACLs you must have entries for @code{user}, @code{group} and @code{other}. Under DFS you need what DFS calls a @code{user_obj}, @code{group_obj} and an @code{other_obj}, and in some cases @code{mask_obj}. In cfengine syntax these are called @code{user:*:}, @code{other:*:} and @code{mask:*:}, as described below. If you are appending to an existing entry, you do not have to re-specify these unless you want to change them. Cfengine can overwrite (replace) or append to one or more ACL entries. @table @code @item overwrite @code{method:overwrite} is the default. This sets the ACL according to the specified entries which follow. The existing ACL will be overwritten completely. @item append @code{method:append} adds or modifies one or more specified ACL entries. If an entry already exists for the specified type and user/group, the specified permission bits will be added to the old permissions. If there is no ACL entry for the given type and user/group, a new entry will be appended. @end table @noindent If the new ACL exactly matches the existing ACL, the ACL is not replaced. The individual bits in an ACE may be either added subtracted or set equal to a specified mask. The @samp{+} symbol means add, the @samp{-} symbol subtract and @samp{=} means set equal to. Here are some examples: @smallexample @var{acltype}:@var{id/*}:@var{mask} user:mark:+rx,-w user:ds:=r user:jacobs:noaccess user:forgiven:default user:*:rw group:*:r other:*:r @end smallexample @noindent The keyword @code{noaccess} means set all access bits to zero for that user, i.e. remove all permissions. The keyword @code{default} means remove the named user from the access crontrol list altogether, so that the default permissions apply. A star/asterisk in the centre field indicates that the user or group ID is implicitly specified as of the owner of the file, or that no ID is applicable at all (as is the case for `other'). @node Solaris ACLs, DFS ACLs, ACEs, acl @subsection Solaris ACLs Under Solaris, the ACL type can be one of the following: @smallexample user group mask other default_user default_group default_mask default_other @end smallexample @noindent A user or group can be specified to the user, group, default_user and default_group types. Solaris ACL permissions are the normal UNIX permissions bits @samp{rwx}, where: @smallexample @var{ @b{r} - Grants read privileges. @b{w} - Grants write privileges. @b{x} - Grants execute privileges.} @end smallexample @noindent @c ..................................................... @c SUBSECTION @c ..................................................... @node DFS ACLs, NT ACLs, Solaris ACLs, acl @subsection DFS ACLs @cindex DCE key @cindex Key, ACL In DCE, the ACL type can be one of the following: @smallexample other mask any unauthenticated user group foreign_other foreign_user foreign_group @end smallexample @noindent The @code{user}, @code{group}, @code{foreign_user} and @code{foreign_group} types require that you specify a user or group. The DCE documentation refers to types @code{user_obj}, @code{group_obj} and so on. In the cfengine implementation, the ugly @samp{_obj} suffix has been dropped to make these more in keeping with the POSIX names. @code{user_obj::}, is equivalent to @code{user:*:} is cfengine. The star/asterisk implies that the ACL applies to the owner of the file object. DFS permissions are comprised of the bits @samp{crwxid}, where: @w{} @smallexample @b{c} - Grants control privileges, to modify an acl. @b{r} - Grants read privileges. @b{w} - Grants write privileges. @b{x} - Grants execute privileges. @b{i} - Grants insert privileges. @b{d} - Grants delete privileges. @end smallexample @noindent See the DCE/DFS documentation for more information about this. It is not possible to set ACLs in foreign cells currently using cfengine, but you can still have all of your ACL definitions in the same file. You must however arrange for the file to be executed on the server for the cell concerned. Note also that you must perform a DCE login (normally as user @samp{cell_admin}) in order to set ACLs on files which are not owned by the owner of the cfengine-process. This is because you must have a valid security ticket. @c ..................................................... @c SUBSECTION @c ..................................................... @node NT ACLs, Windows ACL Example, DFS ACLs, acl @subsection NT ACLs @cindex NT, ACL NT ACEs are written as follows: @smallexample acl_type:user/group:permissions:accesstype @end smallexample The actual change consists of the extra field containing the access type. A star/asterisk in the field for @var{user/group} would normally imply that the ACL applies to the owner of the file object. However this functionality is as of today not yet implemented. In NT, the ACL type can be one of the following: @smallexample user group @end smallexample Both types require that you specify the name of a user or a group. NT permissions are comprised of the bits @samp{rwxdpo}, where: @smallexample r - Read privileges w - Write privileges x - Execute privileges d - Delete privileges p - Privileges to change the permissions on the file o - Privileges to take ownership of the file @end smallexample In addition to any combination of these bits, the word @code{noaccess} or @code{default} can be used as explained in the previous section. NT comes with some standard, predefined permissions. The standards are only a predefined combination of the different bits specified above and are provided with cfengine as well. You can use the standards by setting the permission to @code{read}, @code{change} or @code{all}. The bit implementation of each standard is as on NT: @smallexample read - rx change - rwxd all - rwxdpo @end smallexample where the bits follow the earlier definition. The keywords mentioned above can only be used alone, and not in combination with @samp{+}, @samp{-}, @samp{=} and/or other permission bits. NT defines several different access types, of which only two are used in connection with the ACL type that is implemented in cfengine for NT. The access type can be one of the following: @smallexample allowed denied @end smallexample Intuitively, @code{allowed} access grants the specified permissions to the user, whilst @code{denied} denies the user the specified permissions. If no access type is specified, the default is @code{allowed}. This enables cfengine's behaviour as on UNIX systems without any changes to the configuration file. If the permissions @code{noaccess} or @code{default} is used, the access type will be irrelevant. @c ..................................................... @c SUBSECTION @c ..................................................... @node Windows ACL Example, Posix ACL Example, NT ACLs, acl @subsection Windows ACL Example Here is an example of a configuration file for an NT ACL: @smallexample control: actionsequence = ( files ) domain = ( iu.hioslo.no ) files: $(HOME)/tt acl=acl_alias1 action=fixall acl: @{ acl_alias1 method:overwrite fstype:nt user:gustafb:rwx:allowed user:mark:all:allowed user:toreo:read:allowed user:torej:default:allowed user:ds2:+rwx:allowed group:dummy:all:denied group:iu:read:allowed group:root:all:allowed group:guest:dpo:denied @} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node Posix ACL Example, , Windows ACL Example, acl @subsection Posix ACL Example Here is an example of a configuration file for one Solaris ACL and one DCE/DFS ACL: @smallexample control: actionsequence = ( files ) domain = ( iu.hioslo.no ) files: $(HOME)/tt acl=acl_alias1 action=fixall /:/bigfile acl=acl_alias2 action=fixall acl: @{ acl_alias1 method:overwrite fstype:posix user:*:rwx user:mark:=rwx user:sowille:=rx user:toreo:=rx user:torej:default user:ds2:+rwx group:*:rx group:iu:r group:root:x mask:*:rx other:*:rx default_user:*:=rw default_user:mark:+rwx default_user:ds:=rwx default_group::=r default_group:iu:+r default_mask::w default_other::rwx @} @{ acl_alias2 method:overwrite fstype:dfs user:*:rwxcid group:*:rxd other:*:wxir mask:*:rxw user:/.../iu.hioslo.no/cell_admin:rc group:/.../iu.hioslo.no/acct-admin:rwxcid user:/.../iu.hioslo.no/root:rx @} @end smallexample @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node alerts, binservers, acl, Cfagent reference @section alerts @cindex Alerts @vindex alerts Alerts are normally just messages that are printed when classes become activated in order to alert the system administrator to some condition that has arisen. Alerts can also be special functions, like @code{ShowState()} that generate system output. Alerts cannot belong to the class @code{any}, that would generate a message from every host. In a huge network this could result in vast amounts of Email. This behaviour can be forced, however, by creating an alias for the class `any' that is defined on the affected hosts. @smallexample alerts: class:: @var{quoted message} ifelapsed=@var{time} audit=@var{true/false} ShowState(@var{parameter}) SysLog(@var{priority},@var{message}) SetState(@var{name},@var{ttl},@var{policy}) UnSetState(@var{name}) FriendStatus(@var{hours}) PrintFile(@file{filename},@var{lines}) @end smallexample For example: @cindex ShowState() @cindex SysLog() @cindex SetState() @cindex UnsetState() @w{} @smallexample alerts: myclass:: "Reminder: say hello every hour" ifelapsed=60 nfsd_in_high_dev2:: "High NFS server access rate 2dev at $(host) value $(value_nfsd_in) av $(average_nfsd_in) pm $(stddev_nfsd_in)" ShowState(incoming.nfs) # ROOT PROCS anomaly_hosts.RootProcs_high_dev2:: "RootProc anomaly high 2 dev on $(host) value $(value_rootprocs) av $(average_rootprocs) pm $(stddev_rootprocs)" ShowState(rootprocs) @end smallexample The @code{ShowState()} function reports on state gathered by the cfenvd daemon. @smallexample ShowState(incoming.tcpsyn) ShowState(outgoing.smtp) ShowState(incoming.www) ShowState(outgoing.www) ShowState(procs) ShowState(rootprocs) ShowState(otherprocs) ShowState(users) @end smallexample To limit the frequency of alerts, you can set locking times: @smallexample # ROOT PROCS anomaly_hosts.RootProcs_high_dev2:: "RootProc anomaly high 2 dev on $(host) value $(value_rootprocs) av $(average_rootprocs) pm $(stddev_rootprocs)" ShowState(rootprocs) ifelapsed=10 expireafter=20 @end smallexample Alerts can also be channeled directly to syslog, to avoid extraneous console messages or email. @smallexample SysLog(LOG_ERR,"Test syslog message") @end smallexample One application for alerts is to pass signals from one cfengine to another by persistent, shared memory. For example, suppose a short-lived anomaly event triggers a class that relates to a security alert. The event class might be too short-lived to be followed up by cfagent in full. One could thus set a long term class that would trigger up several follow-up checks. A persistent class could also be used to exclude an operation for an interval of time. Persistent class memory can be added through a system alert functions to give timer behaviour. For example, consider setting a class that acts like a non-resettable timer. It is defined for exactly 10 minutes before expiring. @smallexample SetState("preserved_class",10,Preserve) @end smallexample Or to set a class that acts as a resettable timer. It is defined for 60 minutes unless the SetState call is called again to extend its lifetime. @smallexample SetState(non_preserved_class,60,Reset) @end smallexample Existing persistent classes can be deleted with: @smallexample UnsetState(myclass) @end smallexample The @code{FriendStatus} function is available from version 2.1.4 and displays a message if hosts that normally have a cfengine protocol connection with the current host have not connected for more than than specified number of hours. If the number of hours is set to zero, cfengine uses a machine-learned expectation value for the time and uses this to report. The friend status of a host is thus the expectation that there is a problem with a remote peer. Expected contact rates of more than the variable @code{LastSeenExpireAfter} are ignored as spurious, @xref{lastseenexpireafter}. @cindex FriendStatus @cindex Last Seen database @cindex Peer watching (FriendStatus) @cindex Monitoring other hosts @cindex PrintFile The @code{PrintFile} function can be used to display short excerpts from text files. The arguments are the filename and a maximum number of lines to be printed. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node binservers, broadcast, alerts, Cfagent reference @section binservers @cindex Binary servers, defining @cindex Defining a binary server @vindex binservers The @code{binservers} declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of which other hosts on the network possess filesystems containing software (binary files) which client hosts should mount. This includes resources like programs in @code{/usr/local} and so on. A host may have several binary servers, since there may be several machines to which disks are physically attached. In most cases, on a well organized network, there will be only one @emph{architecture server} per UNIX platform type, for instance a SunOS server, an ULTRIX server and so on. Binary servers are defined as follows: @smallexample binservers: physics.sun4:: sunserver sunserver2 physics.linux:: linuxserver @end smallexample @noindent The meaning of this declaration is the following. All hosts of type @code{sun4} which are members of the group @code{physics} should mount any binaries declared in the @code{mountables} resource list which belong to hosts @code{sunserver} or @code{sunserver2}. Similarly all @code{linux} machines should mount binary filesystems in the mountables list from @code{linuxserver}. Cfengine knows the difference between binaries and home directories in the @code{mountables} list, because home directories match the pattern given by @code{homepattern}. @xref{homepattern}. @xref{homeservers}. Note that every host is a binary server for itself, so that the first binary server (and that with highest priority) is always the current host. This ensures that local filesystems are always used in preference to NFS mounted filesystems. This is only relevant in connection with the variable @code{$(binserver)}. @cindex Binary servers, priority @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node broadcast, control, binservers, Cfagent reference @section broadcast @cindex Broadcast address @vindex broadcast This information is used to configure the network interface for each host. Every local area network has a convention for determining which internet address is used for broadcast requests. Normally this is an address of the form @code{aaa.bbb.ccc.255} or @code{aaa.bbb.ccc.0}. The difference between these two forms is whether all of the bits in the last number are ones or zeroes respectively. You must find out which convention is used at your establishment and tell cfengine using a declaration of the form: @smallexample broadcast: any:: ones # or zeros, or zeroes @end smallexample @vindex ones @vindex zeroes @vindex zeros @cindex ones @cindex zeros @noindent In most cases you can use the generic class @code{any}, since all of the hosts on the same subnet have to use the same convention. If your configuration file encompasses several different subnets with different conventions then you will need to use a more specific. Cfengine computes the actual value of the broadcast address using the value specified above and the netmask @xref{netmask}. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node control, classes, broadcast, Cfagent reference @section control @cindex control section @vindex control The fundamental piece of any cfengine script or configuration file is the control section. If you omit this part of a cfengine script, it will not do anything! The control section is used to define certain variables, set default values and define the order in which the various actions you have defined will be carried out. Because cfengine is a declarative or descriptive language, the order in which actions appear in the file does not necessarily reflect the order in which they are executed. The syntax of declarations here is: @cartouche @w{} @smallexample control: @var{classes}:: @var{variable} = ( @var{list or value} @var{function}(@var{args}) ) @end smallexample @end cartouche The control section is a sequence of declarations which looks something like the following example: @smallexample control: site = ( univ ) domain = ( univ.edu ) sysadm = ( admin@@computing.univ.edu ) netmask = ( 255.255.252.0 ) timezone = ( EDT ) nfstype = ( nfs ) childlibpath = ( /usr/local:/mylibs ) sensiblesize = ( 1000 ) sensiblecount = ( 2 ) editfilesize = ( 4000 ) actionsequence = ( links.some mountall links.others files ) myvariable = ( something ) mymacro = ( somethingelse ) myrandom = ( RandomInt(3,6) ) myexcerpt = ( ReadFile("/etc/services",220)) @end smallexample @noindent Parentheses are required when making a declaring information in cfengine. Note that a limited number of built-in functions exists: @cindex RandomInt() function @cindex ReadFile() function @itemize @bullet @item @code{ExecResult}(@var{command}) Executes the named shell command and inserts the output into the variable. Note that, when this is used in cfengine built-in list variables, any spaces are interpreted as list separators. In other lists, normal rules for iteration apply. @item @code{RandomInt(a,b)} Is substituted for a random number between (a,b). @item @code{ReadFile}(@var{filename},@var{Max number of bytes}) A maximum number of bytes is read from the named file and placed in a variable. @end itemize For more functions, @xref{Setting variables with functions}. @vindex site @vindex domain @vindex sysadm @vindex netmask @vindex timezone @vindex nfstype @vindex sensiblecount @vindex sensiblesize @vindex editfilesize @vindex actionsequence @vindex LD_LIBRARY_PATH @vindex AbortClasses The meaning of each of these lines is described below. @menu * AbortClasses:: * access:: * actionsequence:: * addclasses:: * addinstallable:: * AllowRedefinitionOf:: * Auditing:: * AutoDefine:: * BinaryPaddingChar:: * BindToInterface in cfagent:: * ChecksumDatabase in cfagent:: * ChecksumPurge:: * ChecksumUpdates:: * CompressCommand:: * childlibpath:: * copylinks:: * defaultcopytype:: * defaultpkgmgr:: * deletenonuserfiles:: * deletenonownerfiles:: * deletenonusermail:: * deletenonownermail:: * domain:: * dpkginstallcommand:: * dryrun:: * editbinaryfilesize:: * editfilesize:: * emptyresolvconf:: * exclamation:: * excludecopy:: * excludelinks:: * ExpireAfter:: * FreeBSDInstallCommand:: * FreeBSDRemoveCommand:: * FullEncryption:: * homepattern:: * HostnameKeys in cfagent:: * IfElapsed in cfagent:: * IgnoreFriendRegex:: * IgnoreInterfaceRegex:: * Inform:: * interfacename:: * fileextension:: * lastseen:: * lastseenexpireafter:: * linkcopies:: * LogDirectory:: * LogTidyHomeFiles:: * moduledirectory:: * mountpattern:: * netmask:: * nonalphanumfiles:: * nfstype:: * PortageInstallCommand:: * repchar:: * repository:: * RPMcommand:: * rpminstallcommand:: * schedule:: * secureinput:: * sensiblecount:: * sensiblesize:: * showactions:: * singlecopy:: * site:: * SkipIdentify:: * Smtpserver:: * SplayTime:: * split:: * spooldirectories:: * suninstallcommand:: * suspiciousnames:: * sysadm:: * Syslog:: * SyslogFacility:: * timezone:: * TimeOut:: * Verbose:: * Warnings:: * warnnonuserfiles:: * warnnonownerfiles:: * warnnonusermail:: * warnnonownermail:: @end menu @c ..................................................... @c SUBSECTION @c ..................................................... @node AbortClasses, access, control, control @subsection AbortClasses The @code{AbortClasses} list is a list of class identifiers that will result in the abortion of the current cfagent instanitation with an error message containing the name of the offending class. @smallexample AbortClasses = ( emergency nologin_exists ) @end smallexample @cindex Aborting cfagent @cindex AbortClasses This mechanism allows one to make controlled exceptions at the agent level. For example @smallexample control: actionsequence = ( shellcommands ) AbortClasses = ( danger_will_robinson ) shellcommands: "shellcom 1" "shellcom 2" define=ok elsedefine=danger_will_robinson @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node access, actionsequence, AbortClasses, control @subsection access @cindex Access control @vindex Restricting access The @code{access} list is a list of users who are to be allowed to execute a cfengine program. If the list does not exist then all users are allowed to run a program. @smallexample access = ( @var{user1} @var{user2} ... ) @end smallexample @noindent The list may consist of either numerical user identifiers or valid usernames from the password database. For example: @smallexample access = ( mark aurora 22 456 ) @end smallexample @noindent would restrict a script to users mark, aurora and user id 22 and 456. @c ..................................................... @c SUBSECTION @c ..................................................... @node actionsequence, addclasses, access, control @subsection actionsequence @cindex action sequence @vindex actionsequence The action sequence determines the order in which collective actions are carried out. Here is an example containing the full list of possibilities: @smallexample actionsequence = ( mountall # mount filesystems in fstab mountinfo # scan mounted filesystems checktimezone # check timezone netconfig # check net interface config resolve # check resolver setup unmount # unmount any filesystems packages # install/upgrade/remove packages shellcommands # execute shell commands editfiles # edit files addmounts # add new filesystems to system directories # make any directories links # check and maintain links (single and child) mailcheck # check mailserver mountall # (again) required # check required filesystems tidy # tidy files disable # disable files files # check file permissions copy # make a copy/image of a master file processes # signal / check processes module:name # execute a user-defined module ) @end smallexample @vindex mountall @vindex mountinfo @vindex checktimezone @vindex netconfig @vindex childlinks @vindex singlelinks @vindex resolve @vindex unmount @vindex shellcommands @vindex editfiles @vindex addmounts @vindex directories @vindex links @vindex mailcheck @vindex required @vindex tidy @vindex disable @vindex files @vindex processes @vindex packages @vindex module @noindent Here is a more complete description of the meaning of these keywords. @table @code @item addmounts causes cfengine to compute which NFS filesystems are missing from the current host and add them. This includes editing the filesystem table, creating the mount-directory, if required. This command relies on information provided by @code{mountinfo}, so it should normally only be called after @code{mountinfo}. If the filesystem already appears to be in the filesystem table, a warning is issued. @item checktimezone runs a check on the timezone defined for the shell running cfengine. @item directories executes all the commands defined under the @code{directories} section of the program. It builds new directories. @item disable executes all the commands defined under the @code{disable} section of the program. @item editfiles executes all the commands defined under the @code{editfiles} section of the program. @item files executes all the commands defined under the @code{files} section of the program. @item links executes all the commands defined under the @code{links} section of the program. @item mailcheck tests for the presence of the NFS-mounted mail spooling directory on the current host. The name of the mail spool directory is defined in the @code{mailserver} section of the cfengine program. If the current host is the same as the mailserver (the host which has the physical spool directory disk) nothing is done. Otherwise the filesystem table is edited so as to include the mail directory. @item module @cindex Modules, user defined Normally cfengine's ability to detect the system's condition is limited to what it is able to determine while excuting predefined actions. Classes may be switched on as a result of actions cfengine takes to correct a problem. To increase the flexibility of cfengine, a mechanism has been introduced in version 1.5 which allows you to include a module of your own making in order to define or undefine a number of classes. The syntax @smallexample module:mytests "module:mytests arg1 arg2 .." @end smallexample declares a user defined module which can potentially set the classes @var{class1} etc. Classes returned by the module must be declared so that cfengine knows to pay attention to rules which use these classes when parsing; this is done using @code{AddInstallable}. If arguments are passed to the module, the whole string must be quoted like a shellcommand. @xref{Writing plugin modules,Writing plugin modules,Writing plugin modules,cfengine-Tutorial}. Whether or not these classes become set or not depends on the behaviour of your module. The classes continue to apply for all actions which occur after the module's execution. The module must be owned by the user executing cfengine or root (for security reasons), it must be named @file{module:@var{module-name}} and must lie in a special directory, @xref{moduledirectory}. @item mountall mounts all filesystems defined in the hosts filesystem table. This causes new NFS filesystems added by @code{addmounts} and @code{mailcheck} to be actually mounted. This should probably be called both before @code{mountinfo} and after @code{addmounts} etc. A short timeout is placed on this operation to avoid hanging RPC connections when parsing NFS mounted file systems. @item mountinfo builds internal information about which filesystems are presently mounted on the current host. Cfengine assumes that required-filesystems which are not found need to be mounted. A short timeout is placed on this operation to avoid hanging RPC connections when parsing NFS mounted file systems. If this times out, no further mount operations are considered reliable and are summarily cancelled. @item netconfig checks the netmask, hostname, IP address and broadcast address for the current host. The correct values for the netmask and broadcast address are set if there is an error. The defaultroute is matched against the static routing table and added if no default route exists. This does not apply to DHCP clients, which set a default route automatically. @cindex DHCP @item required executes all the commands defined under the @code{required} section of the program. It checks for the absence of important NFS resources. @item resolve checks and corrects the DNS domain name and the order of nameservers in the file @file{/etc/resolv.conf}. @item packages executes commands defined under the @code{packages} section of the program. This will query the system's package database for the specified packages, at the specified versions, set classes based on whether or not those packages exist, and optionally install, upgrade or remove those packages using a pre-defined package manager command. @item shellcommands executes all the commands defined under the @code{shellcommands} section of the program. @item tidy executes all the commands defined under the @code{tidy} section of the program. @item unmount executes all the commands defined under the @code{unmount} section of the program. The filesystem table is edited so as to remove the unwanted filesystems and the unmount operation is executed. @item processes executes commands defined under the @code{processes} section of the program. @end table Under normal circumstances this coarse ordering is enough to suit most purposes. In some cases you might want to, say, only perform half the link operations before mounting filesystems and then, say, perform the remainder. You can do this (and similar things) by using the idea of defining and undefining classes. @xref{Defining classes,Defining classes,Defining classes,cfengine-Tutorial}. The syntax @smallexample actionsequence = ( links.firstpass.include ... links.secondpass ) @end smallexample @noindent means that cfengine first executes @code{links} with the classes @code{firstpass} and @code{include} @emph{defined}. Later it executes @code{links} with @code{secondpass} defined. You can use this method of adding classes to distinguish more finely the flow of control in programs. @cindex Negating classes A note about style: if you define and undefine lots of classes to do what you want to do, you might stop and ask yourself if your @code{groups} are defined as well as they should be. @xref{groups}. Programming in cfengine is about doing a lot for only a little writing. If you find yourself writing a lot, you are probably not going about things in the right way. @c ..................................................... @c SUBSECTION @c ..................................................... @node addclasses, addinstallable, actionsequence, control @subsection AddClasses @cindex Defining classes @cindex Adding defined classes @cindex Classes, adding and defining @vindex AddClasses @example AddClasses = ( @var{list of identifiers} ) @end example The @code{AddClasses} directive is used to define a list of class attributes for the current host. Normally only the hard classes defined by the system are `true' for a given host. It is convenient though to be able to define classes of your own to label certain actions, mainly so that they can later be excluded so as to cut short or filter out certain actions. This can be done in two ways. @xref{actionsequence}. To define a list of classes for the current session, you write: @smallexample AddClasses = ( exclude shortversion ) @end smallexample @noindent This is equivalent to (though more permanent than) defining classes on the command line with the @code{-D} option. @vindex -D option @cindex -D option @cindex Defining classes You can now use these to qualify actions. For example @smallexample any.exclude:: ... @end smallexample Under normal circumstances @code{exclude} is always true --- because you have defined it to be so, but you can @emph{undefine} it in two ways so as to prevent the action from being carried out. One way is to undefine a class on the command line when you invoke cfengine: @vindex -N option @cindex Excluding classes @example @cartouche host# cfengine -N exclude @end cartouche @end example @noindent or @example @cartouche host# cfengine -N exclude.shortversion host# cfengine -N a.b.c.d @end cartouche @end example @noindent These commands run cfengine with the named classes @emph{undefined}. That means that actions labelled with these classes are excluded during that run. Another way to restrict classes is to add a list of classes to be undefined in the actionsequence. See next section. @c ..................................................... @c SUBSECTION @c ..................................................... @node addinstallable, AllowRedefinitionOf, addclasses, control @subsection AddInstallable @cindex Declaring classes @cindex Defining before use @vindex AddInstallable @example AddInstallable = ( @var{list of identifiers} ) @end example Some actions in your cfengine program will be labelled by classes which only become defined at run time using a @code{define=} option. Cfengine is not always able to see these classes until it meets them and tries to save space by only loading actions for classes which is believes will become defined at some point in the program. This can lead to some actions being missed if the action is parsed before the place where the class gets switched on, since cfengine is a one-pass interpreter,. To help cfengine determine classes which @emph{might become defined} during a run, you can declare them in this list. It does no harm to declare classes here anyway. Here is an example where you need to declare a class because of the ordering of the actions. @smallexample control: AddInstallable = ( myclass ) files: myclass:: /tmp/test mode=644 action=fixall copy: /tmp/foo dest=/tmp/test define=myclass @end smallexample @noindent If we remove the declaration, then when cfengine meets the files command, it skips it because it knows nothing about the class @samp{myclass}---when the copy command follows, it is too late. Remember that imported files are always parsed after the main program so definitions made in imported files always come later than things in the main program. @c ..................................................... @c SUBSECTION @c ..................................................... @node AllowRedefinitionOf, Auditing, addinstallable, control @subsection AllowRedefinitionOf Normally cfagent warns about redefinitions of variables during parsing. This is presumed to be a mistake. To avoid this behaviour, add the name of the variable to this list, and the warning disappears. @smallexample control: actionsequence = ( copy ) AllowRedefinitionOf = ( cfrep ) cfrep = ( bla ) cfrep = ( blo ) @end smallexample @cindex Redefinition of macros @c ..................................................... @c SUBSECTION @c ..................................................... @node Auditing, AutoDefine, AllowRedefinitionOf, control @subsection Auditing @cindex Audit log @vindex Auditing If this variable is set to true then cfengine conducts extensive auditing of its actions to a database in the work directory. When rules are applied, their locations and policy version are recorded also so that it is possible to see exactly which rule was applied and when. It is assumed that the version is recorded as below: @smallexample control: cfinputs_version = ( 1.2.1 ) Auditing = true @end smallexample This variable acts as the global default behaviour and may be overriden locally by @code{audit=true/false} attributes, where applicable. @c ..................................................... @c SUBSECTION @c ..................................................... @node AutoDefine, BinaryPaddingChar, Auditing, control @subsection AutoDefine @w{} @smallexample control: hup_syslogd:: autodefine = ( /etc/syslog.c* ) @end smallexample Referring to the class that prefixes the command, @code{autodefine} is a list of file patterns that will define the said class, if a named file is copied in any statement. This helps to avoid having to write a large number of file-specific copy: lines with define=class configured. In the example above, the class @code{hup_syslogd} would be defined if @file{/etc/syslog.conf} is copied at any time. @c ..................................................... @c SUBSECTION @c ..................................................... @node BinaryPaddingChar, BindToInterface in cfagent, AutoDefine, control @subsection BinaryPaddingChar @w{} @smallexample BinaryPaddingChar = ( \0 ) @end smallexample This specifies the type of character used to pad strings of unequal length in @code{editfiles} during binary editing. The default value is the space character, since this is normally used to edit filenames or text messages within program code. @c ........................................... @c SUBSECTION @c ........................................... @node BindToInterface in cfagent, ChecksumDatabase in cfagent, BinaryPaddingChar, control @subsection BindToInterface in cfagent If this is set to a specific IP address of an IP configured interface, cfagent will use that address for outgoing connections. On Multi-homed hosts this allows one to restrict the traffic to a known interface. An interface must be configured with an IP address in order to be bound. This feature is not available for old operating systems. @cindex Multihomed hosts @vindex BindToInterface @cindex Binding to one interface only @c ..................................................... @c SUBSECTION @c ..................................................... @node ChecksumDatabase in cfagent, ChecksumPurge, BindToInterface in cfagent, control @subsection ChecksumDatabase in cfagent @w{} @smallexample ChecksumDatabase = ( /var/cfengine/cfdb ) @end smallexample @cindex ChecksumDatabase @cindex Message digests @cindex Hashes of files @cindex Tripwire functionality @vindex ChecksumDatabase If this filename is defined, cfengine will use it to store message digests (i.e. cryptographic checksums) of files for security purposes, @xref{files}, @code{checksum=}. This option was deprecated in 2.1.22. @c ..................................................... @c SUBSECTION @c ..................................................... @node ChecksumPurge, ChecksumUpdates, ChecksumDatabase in cfagent, control @subsection ChecksumPurge @w{} @smallexample ChecksumPurge = ( on ) @end smallexample @cindex ChecksumPurge @vindex ChecksumPurge This variable defaults to `off'. If set to true, cfagent will look at all of the registered files in the database and check whether thet still exist. If the file no longer exists, it is removed from the database and a warning is issued. To purge files now and then, but at no particular time, one could do something like this: @smallexample strategies: @{ purging NowAndThen: 1 ElseWhen: 49 @} control: NowAndThen:: ChecksumPurge = ( on ) @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node ChecksumUpdates, CompressCommand, ChecksumPurge, control @subsection ChecksumUpdates @w{} @smallexample ChecksumUpdates = ( on ) @end smallexample @cindex ChecksumUpdates @vindex ChecksumUpdates This variable defaults to `off'. If set to true, cfagent will automatically update the checksum of a file, if it changes on the disk. This means that a security warning will be issued only once about files which have changed, and the changed version will be re-registered as the correct version. This option could be switched on after a system upgrade, for instance, in order to update the database, and then switched to `off' again to reduce the risk of missing a security alert. Alternatively, if you are confident that the first message is sufficient, it can be left as `on' so that only one message is given. @c ..................................................... @c SUBSECTION @c ..................................................... @node CompressCommand, childlibpath, ChecksumUpdates, control @subsection CompressCommand Specified the name of a program that is used in the files @code{action=compress} attribute. @w{} @smallexample CompressCommand = ( /usr/bin/gzip ) @end smallexample @cindex CompressCommand @vindex CompressCommand @c ..................................................... @c SUBSECTION @c ..................................................... @node childlibpath, copylinks, CompressCommand, control @subsection ChildLibPath Sets a value for LD_LIBRARY_PATH in child processes: @example childlibpath = ( /usr/local/lib:/local/mysql/lib ) @end example Note that the variables LD_LIBRARY_PATH is special. This library path is needed to run processes as children of cfengine. Often, if the agent is started from cron (which is started by init), there is no suitable library path set, and shellcommands will fail with strange errors about not being able to load shared objects. Setting a library path here is a useful way of correcting this problem. @c ..................................................... @c SUBSECTION @c ..................................................... @node copylinks, defaultcopytype, childlibpath, control @subsection CopyLinks This list is used to define a global list of names or patterns which are to be copied rather than linked symbolically. For example @smallexample CopyLinks = ( *.config ) @end smallexample The same facility can be specified for each individual link operation using the @code{copy} option @xref{links}. Copying is performed using a file age comparison. Note that all entries defined under a specified class are valid only as long as that class is defined. For instance @smallexample @var{class}:: CopyLinks = ( @var{pattern} ) @end smallexample @noindent would define a pattern which was only valid when @var{class} is defined. @c ..................................................... @c SUBSECTION @c ..................................................... @node defaultcopytype, defaultpkgmgr, copylinks, control @subsection DefaultCopyType This parameter determines the default form of copying for all copy operations parsed after this variable. The legal values are @code{ctime} (intial default), @code{mtime}, @code{checksum} and @code{binary}. e.g. @smallexample DefaultCopyType = ( mtime ) @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node defaultpkgmgr, deletenonuserfiles, defaultcopytype, control @subsection DefaultPkgMgr Sets the default value of the @code{pkgmgr} attribute for @code{packages} items. @w{} @smallexample DefaultPkgMgr = ( rpm ) @end smallexample By default, this variable is not set, meaning there will be no package manager selected, and each item in the @code{packages} section must specify its own package manager, or it will not be checked. For information on the values of this variable, @xref{packages}. @c ..................................................... @c SUBSECTION @c ..................................................... @node deletenonuserfiles, deletenonownerfiles, defaultpkgmgr, control @subsection DeleteNonUserFiles If this parameter is set to true, cfengine will delete files which do not have a name belonging to a known user id. @smallexample DeleteNonUserFiles = ( true ) SpoolDirectories = ( /var/spool/cron/crontabs ) @end smallexample @cindex DeleteNonUserMail DeleteNonUserFiles This is an generalization of DeleteNonUserMail and makes it redundant. it is formally executed as a part of the ``tidy'' action. @c ..................................................... @c SUBSECTION @c ..................................................... @node deletenonownerfiles, deletenonusermail, deletenonuserfiles, control @subsection DeleteNonOwnerFiles If this parameter is set to true, cfengine will delete files on mailservers whose names do not correspond to a known user name, but might be owned by a known user. @smallexample DeleteNonOwnerFiles = ( true ) SpoolDirectories = ( /var/spool/cron/crontabs ) @end smallexample @cindex DeleteNonOwnerMail @cindex DeleteNonUserFiles This is an generalization of DeleteNonOwnerMail and makes it redundant. @c ..................................................... @c SUBSECTION @c ..................................................... @node deletenonusermail, deletenonownermail, deletenonownerfiles, control @subsection DeleteNonUserMail If this parameter is set to true, cfengine will delete mail files on mailservers which do not have a name belonging to a known user id. This does not include lock files. @c ..................................................... @c SUBSECTION @c ..................................................... @node deletenonownermail, domain, deletenonusermail, control @subsection DeleteNonOwnerMail If this parameter is set to true, cfengine will delete files on mailservers whose names do not correspond to a known user name, but might be owned by a known user. @c ..................................................... @c SUBSECTION @c ..................................................... @node domain, dpkginstallcommand, deletenonownermail, control @subsection domain @cindex domain @vindex domain @example domain = ( @var{domain name} ) @end example This variable defines the domainname for your site. You must define it here, because your system might not know its domainname when you run cfengine for the first time. The domainname can be used as a cfengine variable subsequently by referring to $(domain). The domainname variable is used by the action @code{resolve}. The domain is also used implicitly by other matching routines. You should define the domain as early as possible in your configuration file so as to avoid problems, especially if you have the strange practice of naming hosts with their fully qualified host names since groups which use fully qualified names can fail to be defined if cfengine is not able to figure out the domain name. @c ..................................................... @c SUBSECTION @c ..................................................... @node dpkginstallcommand, dryrun, domain, control @subsection DPKGInstallCommand Sets the command used to install packages that need to be installed under the DPKG package manager. @smallexample DPKGInstallCommand = ( "/usr/bin/pkgmgr %s" ) @end smallexample By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the "'s around the string, and the %s is replaced with the name of the package to be installed. @c ..................................................... @c SUBSECTION @c ..................................................... @node dryrun, editbinaryfilesize, dpkginstallcommand, control @subsection DryRun @cindex DryRun @vindex DryRun @w{} @smallexample DryRun = ( @var{on/}@b{off} ) @end smallexample This variable has the same effect as the command line options @kbd{--dry-run} or @kbd{-n}. It tells cfengine to only report what it should do without actually doing it. @smallexample @var{classes}:: DryRun = ( on ) @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node editbinaryfilesize, editfilesize, dryrun, control @subsection editbinaryfilesize @cindex Restricting the size of binary files to be edited @vindex editbinaryfilesize @example EditBinaryFileSize = ( @var{size} ) @end example Cfengine will refuse to edit a file which is larger than the value of @code{editbinaryfilesize} in bytes. This is to prevent possible accidents from occurring. The default value for this variable is 10000000 bytes. If you don't like this feature, simply set the value to be a very large number or to zero. If the value is zero, cfengine will ignore it. @c ..................................................... @c SUBSECTION @c ..................................................... @node editfilesize, emptyresolvconf, editbinaryfilesize, control @subsection editfilesize @cindex Restricting the size of files to be edited @vindex editfilesize @example EditfileSize = ( @var{size} ) @end example This variable is used by cfengine every time it becomes necessary to edit a file. Since file editing applies only to text files, the files are probably going to be relatively small in most cases. Asking to edit a very large (perhaps binary) file could therefore be the result of an error. A check is therefore made as a security feature. Cfengine will refuse to edit a file which is larger than the value of @code{editfilesize} in bytes. This is to prevent possible accidents from occurring. The default value for this variable is 10000 bytes. If you don't like this feature, simply set the value to be a very large number or to zero. If the value is zero, cfengine will ignore it. @c ..................................................... @c SUBSECTION @c ..................................................... @node emptyresolvconf, exclamation, editfilesize, control @subsection EmptyResolvConf @cindex Emptying old nameservers from @file{/etc/resolv.conf} @vindex EmptyResolvConf @example EmptyResolvConf = ( true ) @end example Normally cfengine does not tidy up old entries in the @file{/etc/resolv.conf} file. This option causes cfengine to remove all existing content from the file. @c ..................................................... @c SUBSECTION @c ..................................................... @node exclamation, excludecopy, emptyresolvconf, control @subsection Exclamation This variable defaults to ``on''. If set to ``off'', no exclamation marks (Br. pling, Am: shriek) are printed during security alerts, e.g. for checksum violations. @example Exclamation = ( off ) @end example @vindex Exclamation @cindex Checksum warning, turning off exclamation @cindex Exclamation marks, turning off @c ..................................................... @c SUBSECTION @c ..................................................... @node excludecopy, excludelinks, exclamation, control @subsection ExcludeCopy This list is used to define a global list of names or patterns which are to be excluded from copy operations. For example @smallexample ExcludeCopy = ( *~ *% core ) @end smallexample The same facility can be specified for each individual link operation using the @code{exclude} option @xref{copy}. Note that all entries defined under a specified class are valid only as long as that class is defined. For instance @smallexample @var{class}:: ExcludeCopy = ( @var{pattern} ) @end smallexample @noindent would define a pattern which was only valid when @var{class} is defined. @c ..................................................... @c SUBSECTION @c ..................................................... @node excludelinks, ExpireAfter, excludecopy, control @subsection ExcludeLink This list is used to define a global list of names or patterns which are to be excluded from linking operations. For example @smallexample ExcludeLink = ( *~ *% core ) @end smallexample The same facility can be specified for each individual link operation using the @code{exclude} option @xref{links}. Note that all entries defined under a specified class are valid only as long as that class is defined. For instance @smallexample @var{class}:: ExcludeLink = ( @var{pattern} ) @end smallexample @noindent would define a pattern which was only valid when @var{class} is defined. @c ..................................................... @c SUBSECTION @c ..................................................... @node ExpireAfter, FreeBSDInstallCommand, excludelinks, control @subsection ExpireAfter If you change the value of this parameter, it should be one of the first things you do in your configuration script. This parameter controls the global value of the ExpireAfter parameter. @xref{Spamming and security,Spamming and security,Spamming and security,cfengine-Tutorial}. This parameter controls the maximum time in minutes which a cfengine action is allowed to live. After this time a second cfengine agent will try to kill the cfengine which seems to have hung and attempt to restart the action. This is different from a TimeOut, where an internal alarm interrupt is used. @cartouche @w{} @smallexample ExpireAfter = ( @var{time-in-minutes} ) @end smallexample @end cartouche @noindent This parameter may also be set per action in the action sequence by appending a pseudo-class called @code{ExpireAfter@var{time}}. For instance, @smallexample actionsequence = ( copy.ExpireAfter15 ) @end smallexample @noindent sets the expiry time parameter to 15 minutes for this copy command. This method should be considered old and deprecated however. As of version 2.1.0, you can define the expiry time on a per-command basis, as options of the form @code{expireafter=10}. @c ..................................................... @c SUBSECTION @c ..................................................... @node FreeBSDInstallCommand, FreeBSDRemoveCommand, ExpireAfter, control @subsection FreeBSDInstallCommand Sets the path to `pkg_add' which is used to install packages that need to be installed under FreeBSD. @smallexample FreeBSDInstallCommand = ( "/usr/sbin/pkg_add -r %s" ) @end smallexample By default, this variable is not set, meaning that any packages with action=install will NOT be installed. Note the quotes around the string, and the @code{%s} is replaced with the name of the package to be installed. @c ..................................................... @c SUBSECTION @c ..................................................... @node FreeBSDRemoveCommand, FullEncryption, FreeBSDInstallCommand, control @subsection FreeBSDRemoveCommand Sets the path to `pkg_delete' which is used to remove packages that need to be uninstalled under FreeBSD. @smallexample FreeBSDRemoveCommand = ( "/usr/sbin/pkg_delete %s" ) @end smallexample By default, this variable is set to /usr/sbin/pkg_delete, meaning that any packages with action=remove will be removed. Note the quotes around the string, and the @code{%s} is replaced with the name of the package to be installed. @c ..................................................... @c SUBSECTION @c ..................................................... @node FullEncryption, homepattern, FreeBSDRemoveCommand, control @subsection FullEncryption From version 2.1.22. This is false for protocol compatability with older servers. If this is set to true, directory filenames are encrypted in addition to file contents. If transferred data are not especially secret or travel over public networks this is a waste of CPU time. In high security environments it provides full privacy of data transmission. @cartouche @w{} @smallexample FullEncryption = ( true ) @end smallexample @end cartouche @c ..................................................... @c SUBSECTION @c ..................................................... @node homepattern, HostnameKeys in cfagent, FullEncryption, control @subsection HomePattern @cindex Home path @cindex Path to home directories @vindex HomePattern @example HomePattern = ( @var{list of patterns} ) @end example The @code{homepattern} variable is used by the cfengine model for mounting nfs filesystems. @xref{NFS resources,NFS resources,NFS resources,cfengine-Tutorial}. It is also used in the evaluation of the pseudo variable @code{home}, See @ref{files}, @ref{tidy}. @code{homepattern} is in fact a list and is used like a wildcard or @emph{pattern} to determine which filesystems in the list of mountables are home directories. @xref{mountables}. This relies on your sticking to a rigid naming convention as described in the first reference above. For example, you might wish to mount (or locate directly if you are not using a separate partition for home directories) your home directories under @code{mountpattern} in directories @code{u1}, @code{u2} and so on. In this case you would define @code{homepattern} to match these numbers: @cindex Wildcards in homepattern @cindex Searching for home directories @w{} @smallexample homepattern = ( u? ) @end smallexample @noindent Cfengine now regards any directory matching @code{$(mountpattern)/u?} as being a user login directory. Suppose you want to create mount home directories under @code{$(mountpattern)/home} and make subdirectories for staff and students. Then you would be tempted to write: @smallexample HomePattern = ( home/staff home/students ) @end smallexample @noindent Unfortunately this is not presently possible. (This is, in principle, a bug which should be fixed in the future.) What you can do instead is to achieve the same this as follows: @smallexample MountPattern = ( /$(site)/$(host) /$(site)/$(host)/home ) HomePattern = ( staff students ) @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node HostnameKeys in cfagent, IfElapsed in cfagent, homepattern, control @subsection HostnameKeys in cfagent If this variable is set to true/on, it causes cfagent to lookup and store trusted public keys according to their DNS fully qualified host name, instead of using the IP address. This can be useful in environments where hosts do not have fixed IP addresses, but do have fixed hostnames. @smallexample HostnameKeys = ( on ) @end smallexample This method of storing keys is not recommended for sites with fixed IP addresses, since it removes one security barrier from a potential attacker by potentially allowing DNS spoofing. Note that there is a corresponding variable to be set in @file{cfrun.hosts} which must be set for consistency. @c ..................................................... @c SUBSECTION @c ..................................................... @node IfElapsed in cfagent, IgnoreFriendRegex, HostnameKeys in cfagent, control @subsection IfElapsed in cfagent If you change the value of this parameter, it should be one of the first things you do in your configuration script. This parameter controls the global value of the IfElapsed parameter, @xref{Spamming and security,Spamming and security,Spamming and security,cfengine-Tutorial}. This parameter controls the minimum time which must have elapsed for an action in the action sequence before which it will be executed again. @cartouche @w{} @smallexample IfElapsed = ( @var{time-in-minutes} ) @end smallexample @end cartouche @noindent This parameter may also be set per action in the action sequence by appending a pseudo-class called @code{IfElapsed@var{time}}. For instance, @smallexample ActionSequence = ( copy.IfElapsed15 ) @end smallexample @noindent sets the elapsed time parameter to 15 minutes for this copy command. This method should be considered old and deprecated however. As of version 2.1.0, you can define the expiry time on a per-command basis, as options of the form @code{ifelapsed=15}. @c ..................................................... @c SUBSECTION @c ..................................................... @node IgnoreFriendRegex, IgnoreInterfaceRegex, IfElapsed in cfagent, control @subsection FriendIgnoreRegex Use this regular expression to suppress FriendStatus warnings for matching hosts. e.g. @smallexample IgnoreFriendRegex = ( "2001:700:.*|host1|host2" ) @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node IgnoreInterfaceRegex, Inform, IgnoreFriendRegex, control @subsection IgnoreInterfaceRegex Use this regular expression to delete class information about interfaces that you do not want to see on a host. This is useful for tamig virtual machines and their multitudinous interfaces. @smallexample IgnoreInterfaceRegex = ( "vm.*" ) @end smallexample @cindex Virtual interfaces @cindex Interface classes @vindex IgnoreInterfaceRegex @c ..................................................... @c SUBSECTION @c ..................................................... @node Inform, interfacename, IgnoreInterfaceRegex, control @subsection Inform @w{} @smallexample Inform = ( @var{on/}@b{off} ) @end smallexample This variable switches on the output level whereby cfengine reports changes it makes during a run. Normally only urgent messages or clear errors are printed. Setting @code{Inform} to @code{on} makes cfengine report on all actions not explicitly cancelled with a `silent' option. To set this output level one writes: @smallexample @var{classes}:: Inform = ( on ) @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node interfacename, fileextension, Inform, control @subsection InterfaceName @cindex InterfaceName @vindex InterfaceName @cindex Interface name, redefining by class If you have an operating system which is installed on some non-standard hardware, you might have to specifically set the name of the network interface. For example: @smallexample control: nextstep.some:: InterfaceName = ( en0 ) nextstep.others:: InterfaceName = ( ec0 ) @end smallexample @noindent It is only necessary to set the interface name in this fashion if you have an operating system which is running on special hardware. Most users will not need this. The choice set here overrides the system defaults and the choices made in the @file{cfrc} file, @xref{cfrc resource file}. @c ..................................................... @c SUBSECTION @c ..................................................... @node fileextension, lastseen, interfacename, control @subsection FileExtensions This list may be used to define a number of extensions which are regarded as being plain files by the system. As part of the general security checking cfengine will warn about any directories which have names using these extensions. They may be used to conceal directories. @smallexample FileExtensions = ( c o gif jpg html ) @end smallexample @vindex FileExtensions @cindex Directories, hidden @c ..................................................... @c SUBSECTION @c ..................................................... @node lastseen, lastseenexpireafter, fileextension, control @subsection LastSeen This option is true by default. If set to off or false it prevents cfengine and/or cfservd from learning about last times hosts were observed connecting to one another. Some users with broken resolvers (particularly in view of the change over to IPv6 compatible libraries) might find this useful when processes appear to hang on connecting. @cindex Broken resolver @cindex LastSeen @cindex Hanging processes @w{} @smallexample LastSeen = ( off ) @end smallexample @vindex LastSeen @c ..................................................... @c SUBSECTION @c ..................................................... @node lastseenexpireafter, linkcopies, lastseen, control @subsection LastSeenExpireAfter This value (in days) sets the time after which unseen friend hosts are purged from the `last seen' database, as viewed by the @code{FriendStatus} function, @xref{alerts}. @smallexample LastSeenExpireAfter = ( 2 ) @end smallexample @vindex LastSeenExpireAfter @cindex Last Seen database @c ..................................................... @c SUBSECTION @c ..................................................... @node linkcopies, LogDirectory, lastseenexpireafter, control @subsection LinkCopies This list is used to define a global list of names or patterns which are to be linked symbolically rather than copied. For example @smallexample excludelinks = ( *.gif *.jpg ) @end smallexample The same facility can be specified for each individual link operation using the @code{symlink} option @xref{copy}. Note that all entries defined under a specified class are valid only as long as that class is defined. For instance @smallexample @var{class}:: LinkCopies = ( @var{pattern} ) @end smallexample @noindent would define a pattern which was only valid when @var{class} is defined. @c ..................................................... @c SUBSECTION @c ..................................................... @node LogDirectory, LogTidyHomeFiles, linkcopies, control @subsection LogDirectory This is now deprecated. Specify an alternative directory for keeping cfengine's log data. This defaults to @file{/var/run/cfengine} or @file{/var/cfengine}. @w{} @smallexample LogDirectory = ( /var/cfengine ) @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node LogTidyHomeFiles, moduledirectory, LogDirectory, control @subsection LogTidyHomeFiles @w{} @smallexample LogTidyHomeFiles = ( off ) @end smallexample If set to ``off'', no log is made of user files, in their home directories, of the files which are tidied by cfengine. @cindex Tidy log files for users @c ..................................................... @c SUBSECTION @c ..................................................... @node moduledirectory, mountpattern, LogTidyHomeFiles, control @subsection moduledirectory @cindex Module directory @cindex Directory for cfengine modules @vindex moduledirectory @example moduledirectory = ( @var{directory for plugin modules} ) @end example This is the directory where cfengine will look for plug-in modules for the actionsequence, @xref{actionsequence}. Plugin modules may be used to activate classes using special algorithms. @xref{Writing plugin modules,Writing plugin modules,Writing plugin modules,cfengine-Tutorial}. This variable defaults to @file{/var/cfengine/modules} for privileged users and to @file{$HOME)/.cfengine/modules} for non-privileged users. @c ..................................................... @c SUBSECTION @c ..................................................... @node mountpattern, netmask, moduledirectory, control @subsection mountpattern @cindex Mount paths @cindex Path to mounted filesystems @vindex mountpattern @example mountpattern = ( @var{mount-point} ) @end example The @code{mountpattern} list is used by the cfengine model for mounting nfs filesystems. @xref{NFS resources,NFS resources,NFS resources,cfengine-Tutorial}. It is also used in the evaluation of the pseudo variable @code{home}, See @ref{files}, @ref{tidy}. It is used together with the value of @code{homepattern} to locate and identify what filesystems are local to a given host and which are mounted over the network. For this list to make sense you need to stick to a rigid convention for mounting your filesystems under a single naming scheme as described in the section mentioned above. If you follow the recommended naming scheme then you will want to set the value of mountpattern to @smallexample mountpattern = ( /$(site)/$(host) ) @end smallexample @noindent which implies that cfengine will look for local disk partitions under a unique directory given by the name of the host and site. Any filesystems which are physically located on the current host lie in this directory. All mounted filesystems should lie elsewhere. If you insist on keeping mounted file systems in more than one location, you can make a list like this: @smallexample mountpattern = ( /$(site)/users /$(site)/projects ) @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node netmask, nonalphanumfiles, mountpattern, control @subsection netmask @cindex netmask @vindex netmask @example netmask = ( @var{aaa.bbb.ccc.ddd} ) @end example The netmask variable defines the partitioning of the subnet addresses on your network. Its value is defined by your network administrator. On most systems it is likely to be @code{255.255.255.0}. This is used to configure the network interface in @code{netconfig}. @xref{actionsequence}. @cindex Domain name @cindex IP address @cindex Internet address @cindex Netmask @cindex Subnet mask Every host on the internet has its own unique address. The addresses are assigned hierarchically. Each network gets a @emph{domain name} and can attach something like 65,000 hosts to that network. Since this is usually too many to handle in one go, every such network may be divided up into subnets. The administrator of the network can decide how the division into subnets is made. The decision is a trade-off between having many subnets with few hosts, or many hosts on few subnets. This choice is made by setting the value of a variable called @code{netmask}. The netmask looks like an internet address. It takes the form: @example aaa.bbb.ccc.mmm @end example @noindent The first two numbers @samp{aaa.bbb} are the address of the domain. The remainder @samp{ccc.mmm} specifies both the subnet and the hostname. The value of @code{netmask} tells all hosts on the network: how many of the bits in the second half label different subnets and how many label different hosts on each of the subnets? The most common value for the netmask is @samp{255.255.255.0}. It is most helpful to think of the netmask in terms of bits. Each base-10 number between 0-255 represents 8 bits which are either set or not set. Every bit which is set is a network address and every bit which is zero is part of a host address. The first two parts of the address @samp{255.255} always takes these values. If the third number is @samp{255}, it means that the domain is divided up into 256 sub networks and then the remaining bits which are zero can be used to give 255 different host addresses on each of the subnets. If the value had been @samp{255.255.255.254}, the network would be divided up into @math{2^15} subnets, since fifteen of the sixteen bits are one. The remaining bit leaves enough room for two addresses 0 and 1. One of those is reserved for @emph{broadcasts} to all hosts, the other can be an actual host --- there would only be room for one host per subnet. This is a stupid example of course, the main point with the subnet mask is that it can be used to trade subnets for hosts per subnet. A value of @samp{255.255.254.0} would allow 128 different subnets with @math{2*256-1 = 511} hosts on each. We needn't be concerned with the details of the netmask here. Suffice it to say that its value is determined for your entire domain by the network administrator and each host has to be told what the value is. Each host must also know what convention is used for the @emph{broadcast address}. This is an address which hosts can send to if they wish to send a message to every other host on their subnet simultaneously. It is used a lot by services like NIS to ask if any hosts are willing to perform a particular service. There are two main conventions for the broadcast address: address zero (all host bits are zero) and the highest address on the subnet (all host bits are ones). The convention can be different on every subnet and it is decided by the network administrator. When you write a cfengine program you just specify the convention used on your subnet and cfengine works out the value of the broadcast address from the netmask and the host address @xref{broadcast}. Cfengine works out the value of the broadcast address using the value of the netmask. @c ..................................................... @c SUBSECTION @c ..................................................... @node nonalphanumfiles, nfstype, netmask, control @subsection NonAlphaNumFiles If enabled, this option causes cfengine to detect and disable files which have purely non-alphanumeric filenames, i.e. files which might be accidental or deliberately concealed. The files are then marked with a suffix @code{.cf-nonalpha} and are rendered visible. @smallexample NonAlphaNumFiles = ( on ) @end smallexample These files can then be tidied by searching for the suffix. Note that alphanumeric means ascii codes less than 32 and greater than 126. @c ..................................................... @c SUBSECTION @c ..................................................... @node nfstype, PortageInstallCommand, nonalphanumfiles, control @subsection nfstype @cindex nfs @cindex nfstype @vindex nfstype @example nfstype = ( @var{nfs-type} ) @end example This variable is included only for future expansion. If you do not define this variable, its value defaults to ``nfs''. At present cfengine operates only with NFS (the network file system). When cfengine looks for network file systems to mount, it adds lines in the filesystem table (@samp{/etc/fstab},@samp{/etc/checklist} etc.) to try to mount filesystems of type ``nfs''. In principle you might want to use a completely different system for mounting filesystems over the network, in which case the `mount type' would not be ``nfs'' but something else. At the time of writing certain institutions are replacing NFS with AFS (the Andrew filesystem) and DFS (from the distributed computing environment). The use of these filesystems really excludes the need to use the mount protocol at all. In other words if you are using AFS or DFS, you don't need to use cfengine's mounting commands at all. @cindex AFS @cindex Andrew filesystem @cindex DFS @c ..................................................... @c SUBSECTION @c ..................................................... @node PortageInstallCommand, repchar, nfstype, control @subsection PortageInstallCommand Sets the path to `emerge' which is used to install packages that need to be installed under Gentoo Portage. @smallexample gentoo.some:: DefaultPkgMgr = ( portage ) PortageInstallCommand = ( "/usr/bin/emerge --nocolor %s" ) gentoo.other:: DefaultPkgMgr = ( portage ) PortageInstallCommand = ( "/usr/lib/portage/bin/emerge --color=n %s" @end smallexample By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the quotes around the string, and the @code{%s} is replaced with the name of the package to be installed. @c ..................................................... @c SUBSECTION @c ..................................................... @node repchar, repository, PortageInstallCommand, control @subsection RepChar @example RepChar = ( @var{character} ) @end example The value of this variable determines the characters which is used by cfengine in creating the unique filenames in the file repository. Normally, its value is set to @samp{_} and each @samp{/} in the path name of the file is changed to @samp{_} and stored in the repository. If you prefer a different character, define it here. Note that the character can be quoted with either single or double quotes in order to encompass spaces etc. @vindex RepChar @cindex Repository filenames, changing @mbindex Changing repository name conventions @c ..................................................... @c SUBSECTION @c ..................................................... @node repository, RPMcommand, repchar, control @subsection Repository @example Repository = ( @var{directory} ) @end example Defines a special directory where all backup and junk files are collected. Files are assigned a unique filename which identifies the path from which they originate. This affects files saved using @code{disable}, @code{copy}, @code{links} and @code{editfiles} @xref{Disabling and the file repository,Disabling and the file repository,Disabling and the file repository,cfengine-Tutorial}. @c ..................................................... @c SUBSECTION @c ..................................................... @node RPMcommand, rpminstallcommand, repository, control @subsection RPMcommand The default value of the Red Hat Package manager command @file{/bin/rpm} can be altered for non-standard systems with this variable. @example RPMcommand = ( /usr/bin/rpm ) @end example @c ..................................................... @c SUBSECTION @c ..................................................... @node rpminstallcommand, schedule, RPMcommand, control @subsection RPMInstallCommand Sets the command used to install packages that need to be installed under the RPM package manager. @smallexample RPMInstallCommand = ( "/usr/bin/pkgmgr %s" ) @end smallexample By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the quotes around the string, and the @code{%s} is replaced with the name of the package to be installed. @smallexample control: DefaultPkgMgr = ( rpm ) RPMInstallCommand = ( "/usr/bin/yum -d 0 -e 0 -y install %s" ) # This would remove all dependencies (!) # # RPMRemoveCommand = ( "/usr/bin/yum -d 0 -e 0 -y remove %s" ) # This might be less drastic RPMRemoveCommand = ( "/bin/rpm -e --nodeps %s" ) packages: # this will remove this package regardless of version. some_rpm_name version=0:0.0 cmp=ge action=remove @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node schedule, secureinput, rpminstallcommand, control @subsection Schedule @cindex scheduling @vindex scheduling @example schedule = ( Min00_05 Min30_35 @var{time class} ) @end example When @code{cfexecd} is used in daemon mode, it defaults to running once an hour, on the hour, i.e.. @example schedule = ( Min00_05 ) @end example This can be extended to make the agent run more often. The time specifiers are cfengine classes, and are written as intervals of time rather the precise times. Cfengine's time resolution is purposely limited to five minutes because the auto-correlation time of user resources is generally greater than this. Thus, it is assumed that precision timing is not required and the start time of cfengine, when scheduled in daemon mode, is not better than a few minutes. The daemon does not require precision, but offers many other strategic features for load balancing and security. Other time classes can be used in the schedule list, but note that cfexecd will not run the agent more than once every five minutes. This is treated as a fundamental granularity. @c ..................................................... @c SUBSECTION @c ..................................................... @node secureinput, sensiblecount, schedule, control @subsection SecureInput @cindex Secure input @vindex SecureInput @example SecureInput = ( on ) @end example If this is set cfengine will not import files which are not owned by the uid running the program, or which are writable by groups or others. @c ..................................................... @c SUBSECTION @c ..................................................... @node sensiblecount, sensiblesize, secureinput, control @subsection SensibleCount @cindex Sensible limits on files in a directory @vindex SensibleCount @example SensibleCount = ( @var{count} ) @end example This variable is used by the action @code{required}. It defines for cfengine what you consider to be the minimum number of files in a `required' directory. If you declare a directory as being required, cfengine will check to see if it exists. Then, if the directory contains fewer than the value of @code{sensiblecount} files, a warning is issued. The default value for this variable is 2. @c ..................................................... @c SUBSECTION @c ..................................................... @node sensiblesize, showactions, sensiblecount, control @subsection SensibleSize @cindex Sensible file sizes @vindex SensibleSize @example SensibleSize = ( @var{size} ) @end example This variable is used by the action @code{required}. It defines for cfengine what you consider to be the minimum size for a `required' file. If you declare a file as being required, cfengine will check to see if the file exists. Of course, the file may exist but be empty, so the size of the file is also checked against this constant. If the file is smaller than the value of @code{sensiblesize} a warning is issued. The default value for this variable is 1000 bytes. @c ..................................................... @c SUBSECTION @c ..................................................... @node showactions, singlecopy, sensiblesize, control @subsection ShowActions @vindex ShowActions @example ShowActions = ( @var{on} ) @end example This causes cfengine to produce detailed output of what action is being carried out as part of the prefix information during output. This is intended only for third party tools which collect and parse the cfengine output. It will be of little interest to humans. @c ..................................................... @c SUBSECTION @c ..................................................... @node singlecopy, site, showactions, control @subsection SingleCopy @smallexample singlecopy = ( path_and_filename_wildcard ) @end smallexample If a @code{singlecopy} pattern is defined the behavior of copy: is modified so that a given destination file, matching the pattern, will only be updated once. In other words, if someone tries to copy more then one source file to the same location, the destination will not be overwritten in the same run. If the path name and wildcard is any of '*', 'on' or 'true', then the list applies to all files. For example: @smallexample control: actionsequence = ( copy ) singlecopy = ( /tmp/* ) addinstallables = ( zzz ) zzz:: autodefine = ( /tmp/* ) copy: /etc/passwd dest=/tmp/destination type=binary /etc/group dest=/tmp/destination type=binary alerts: zzz:: "Copied something in /tmp" @end smallexample Note (Warning) that this feature has several problems. It assumes an order dependence that cfengine generally tries to avoid. The first copy that takes place wins. Also, if files are locked at different times, this can result in oscillations between several different source files. e.g. @smallexample copy: /etc/passwd dest=/tmp/bla type=binary ifelapsed=2 /etc/group dest=/tmp/bla type=binary ifelapsed=1 @end smallexample In order to avoid explicit looping, cfengine assumes that a file has been copied even if no actual copy took place -- i.e. as long as a file is apparently up to date, that counts as a valid copy update and the promise/action is considered done. If this were not the case, then the following promises would still be in line for execution and cfengine would loop between the different versions on subsequent invocations. @c ..................................................... @c SUBSECTION @c ..................................................... @node site, SkipIdentify, singlecopy, control @subsection site/faculty @cindex site @vindex site @example site = ( @var{sitename} ) faculty = ( @var{facultyname} ) @end example This variable defines a convenient name for your site configuration. It is useful for making generic rules later on, because it means for instance that you can define the name of a directory to be @smallexample /$(site)/$(host)/local @end smallexample @noindent without having to redefine the rule for a specific site. This is a handy trick for making generic rules in your files which can be imported into a configuration for any site. @code{faculty} is a synonym for @code{site}. The two names may be used interchangeably. @c ..................................................... @c SUBSECTION @c ..................................................... @node SkipIdentify, Smtpserver, site, control @subsection SkipIdentify @example SkipIdentify = ( true ) @end example This is the client side directive corresponding to the server directive @code{SkipVerify}. It tells cfengine not to assume that the client is registered in the Domain Name Service (DNS). Sometimes the assumption of DNS registration can break connectivity between hosts, particularly if firewalls or Network Address Translation is in use. @cindex SkipIdentify @cindex Network Address Translation @c ..................................................... @c SUBSECTION @c ..................................................... @node Smtpserver, SplayTime, SkipIdentify, control @subsection smtpserver @example smtpserver = ( @var{mailhost} ) @end example This variable specified the destination for Email sent by cfexecd. @cindex Mailhost @cindex smtpserver @c ..................................................... @c SUBSECTION @c ..................................................... @node SplayTime, split, Smtpserver, control @subsection SplayTime @example SplayTime = ( @var{time-in-minutes} ) @end example This variable is used to set the maximum time over which cfengine will share its load on a server, @xref{Splaying host times,Splaying host times,Splaying host times,cfengine-Tutorial}. @c ..................................................... @c SUBSECTION @c ..................................................... @node split, spooldirectories, SplayTime, control @subsection Split @example Split = ( @var{character} ) @end example The value of this variable is used to define the list separator in variables which are expected to be treated as lists. The default value of this variable is the colon @samp{:}. Cfengine treats variables containing this character as lists to be broken up and iterated over, @xref{Iteration over lists}. This typically allows communication with PATH-like environment variables in the shell. @cindex split @cindex Iteration over lists @mbindex Iterating over lists @vindex split @c ..................................................... @c SUBSECTION @c ..................................................... @node spooldirectories, suninstallcommand, split, control @subsection SpoolDirectories @cindex SpoolDirectories @vindex SpoolDirectories A list of additional spool directories for cfengine to police. In these directories, filenames should correspond to existing users of the system. When users lost their accounts, this list plus the mail spool directory will be checked for files owned by deprecated users. See also: @code{DeleteNonOwnerFiles}, @code{DeleteNonUserFiles}. @example SpoolDirectories = ( /var/spool/cron/crontabs /var/spool/cron/atjobs ) @end example @c ..................................................... @c SUBSECTION @c ..................................................... @node suninstallcommand, suspiciousnames, spooldirectories, control @subsection SUNInstallCommand Sets the command used to install packages that need to be installed under the SUN package manager. @smallexample SUNInstallCommand = ( "/usr/bin/pkgmgr %s" ) @end smallexample By default, this variable is not set, meaning that any packages with action=install will NOT be installed if installation is required. Note the quotes around the string, and the @code{%s} is replaced with the name of the package to be installed. @c ..................................................... @c SUBSECTION @c ..................................................... @node suspiciousnames, sysadm, suninstallcommand, control @subsection suspiciousnames @cindex suspiciousnames @vindex SuspiciousNames @example SuspiciousNames = ( .mo lrk3 ) @end example Filenames in this list are treated as suspicious and generate a warning as cfengine scans directories. This might be used to detect hacked systems or concealed programs. Checks are only made in directories which cfengine scans in connection with a command such as files, tidy or copy. @c ..................................................... @c SUBSECTION @c ..................................................... @node sysadm, Syslog, suspiciousnames, control @subsection sysadm @cindex sysadm @vindex sysadm @example sysadm = ( @var{mail address} ) @end example The mail address of your system administrator should be placed here. This is used in two instances. If cfengine is invoked with the option @code{-a}, then it simply prints out this value. This is a handy feature for making scripts. The administrators mail address is also written into the personal log files which cfengine creates for each user after tidying files, so you should make this an address which users can mail if they have troubles. @c ..................................................... @c SUBSECTION @c ..................................................... @node Syslog, SyslogFacility, sysadm, control @subsection Syslog @w{} @smallexample Syslog = ( @var{on/}@b{off} ) @end smallexample This variable activates syslog logging of cfengine output at the `inform' level. To set this output level one writes: @smallexample @var{classes}:: Syslog = ( on ) @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node SyslogFacility, timezone, Syslog, control @subsection SyslogFacility @w{} @smallexample SyslogFacility = ( @var{facility} ) @end smallexample This variable alters the syslog facility level. e.g. @smallexample SyslogFacility = ( LOG_LOCAL1 ) @end smallexample Valid arguments are @smallexample LOG_USER LOG_DAEMON LOG_LOCAL0 LOG_LOCAL1 LOG_LOCAL2 LOG_LOCAL3 LOG_LOCAL4 @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node timezone, TimeOut, SyslogFacility, control @subsection timezone @example timezone = ( @var{3-character timezone} ) @end example The timezone variable is a list of character strings which define your local timezone. Normally you will only need a single timezone, but sometimes there are several aliases for a given timezone e.g. MET and CET are synonymous. Currently only the first three characters of this string are checked against the timezone which cfengine manages to glean from the system. If a mismatch is detected a warning message is printed. cfengine does not attempt to configure the timezone. This feature works only as a reminder, since the timezone should really be set once and for all at the time the system is installed. On some systems you can set the timezone by editing a file, a procedure which you can automate with cfengine @xref{editfiles}. The value of the @code{timezone} can be accessed by variable substitution in the usual way. It expands to the first item in your list. @smallexample shellcommands: "echo $@{timezone@} | mail $@{sysadm@}" @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node TimeOut, Verbose, timezone, control @subsection TimeOut @w{} @smallexample TimeOut = ( 10 ) @end smallexample The default timeout for network connections is 10 seconds. This is too short on some routed networks. It is not permitted to set this variable smaller than 3 seconds or larger than 60 seconds. A timeout is generated by an `alarm' interrupt within an executing agent. This is constrasted with ExpireAfter, in which a second agent is required to interrupt the activity. @c ..................................................... @c SUBSECTION @c ..................................................... @node Verbose, Warnings, TimeOut, control @subsection Verbose @w{} @smallexample Verbose = ( @var{on/}@b{off} ) @end smallexample This variable switches on the output level whereby cfengine reports everything it does during a run in great detail. Normally only urgent messages or clear errors are printed, @xref{Inform}. This option is almost equivalent to using the @kbd{--verbose} of @kbd{-v} command-line options. The only difference is that system environment reporting information, which is printed prior to parsing, is not shown. To set this output level on selected hosts one writes: @smallexample @var{classes}:: Verbose = ( on ) @end smallexample For related more limited output, @xref{Inform}. @c ..................................................... @c SUBSECTION @c ..................................................... @node Warnings, warnnonuserfiles, Verbose, control @subsection Warnings @w{} @smallexample Warnings = ( @var{on/}@b{off} ) @end smallexample This variable switches on the parser-output level whereby cfengine reports non-fatal warnings. This is equivalent to setting the command line switch @kbd{--no-warn}, or @kbd{-w}. To set this output level on selected hosts one writes: @smallexample @var{classes}:: Warnings = ( on ) @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node warnnonuserfiles, warnnonownerfiles, Warnings, control @subsection WarnNonUserFiles If this parameter is set to true, cfengine will warn about files in spool directories which do not have a name belonging to a known user id. See also @code{DeleteNonUserFiles}. @c ..................................................... @c SUBSECTION @c ..................................................... @node warnnonownerfiles, warnnonusermail, warnnonuserfiles, control @subsection WarnNonOwnerFiles If this parameter is set to true, cfengine will warn about files on mailservers whose names do not correspond to a known user name, but might be owned by a known user. @smallexample SpoolDirectories = ( /var/spool/cron/crontabs ) WarnNonOwnerFiles = ( true ) @end smallexample See also @code{DeleteNonOwnerFiles}. This generalizes and succeeds @code{DeleteNonOwnerMail}. @c ..................................................... @c SUBSECTION @c ..................................................... @node warnnonusermail, warnnonownermail, warnnonownerfiles, control @subsection WarnNonUserMail If this parameter is set to true, cfengine will warn about mail files on mailservers which do not have a name belonging to a known user id. This does not include lock files. @c ..................................................... @c SUBSECTION @c ..................................................... @node warnnonownermail, , warnnonusermail, control @subsection WarnNonOwnerMail If this parameter is set to true, cfengine will warn about files on mailservers whose names do not correspond to a known user name, but might be owned by a known user. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node classes, copy, control, Cfagent reference @section classes @cindex @code{classes} @cindex Defining classes @cindex groups The @code{classes} keyword is an alias for @code{groups} as of version 1.4.0 of cfengine. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node copy, defaultroute, classes, Cfagent reference @section copy @cindex copy @cindex Copying files @cindex File images (copy) Cfengine copies files between locally mounted filesystems and via the network from registered servers. The copy algorithm avoids race-conditions which can occur due to network and system latencies by copying first to a file called @file{@var{file}.cfnew} on the local filesystem, and then renaming this quickly into place. The aim of this roundabout procedure is to avoid situations where the direct rewriting of a file is interrupted midway, leaving a partially written file to be read by other processes. Cfengine attempts to preserve hard links to non-directory file-objects, but see the caution below. @cindex @file{.cfnew} files @emph{Caution should be exercised in copying files which change rapidly in size. This can lead to file corruption, if the size changes during copying. Cfengine attempts to prevent this during remote copies.} The syntax summary is: @cartouche @w{} @smallexample copy: @var{class}:: @var{master-file} dest=@var{destination-file} mode=@var{mode} owner=@var{owner} group=@var{group} action=@var{warn/silent/fix} backup=@b{true}@var{/false/timestamp} repository=@var{backup directory} stealth=@var{true/on/@b{false/off}} checkroot=@var{true/on/@b{false/off}} timestamps=@b{preserve/keep} symlink=@var{pattern} include=@var{pattern} exclude=@var{pattern} ignore=@var{pattern} filter=@var{filteralias} xdev=@var{true/on}/@b{false/off} recurse=@var{number/inf/}@var{0} type=@b{ctime}@var{/mtime/checksum/sum/byte/binary/any} linktype=@b{absolute/symbolic}@var{/relative/hard/none/copy} typecheck=@b{true/on}/@var{false/off} define=@var{class-list}(,:.) elsedefine=@var{class-list}(,:.) force=@var{true/on}/@b{false/off} forcedirs=@var{true/on}/@b{false/off} forceipv4=@var{true/on}/@b{false/off} size=@var{size limits} server=@var{server-host} failover=@var{classes} trustkey=@var{true}/@b{false} secure=[deprecated] encrypt=@var{true}/@b{false} verify=@var{true}/@b{false} oldserver=@var{true}/@b{false} purge=@var{true/}@b{false} syslog=@var{true/on}/@var{false/off} inform=@var{true/on}/@var{false/off} audit=@var{true/false} findertype=@var{MacOSX finder type} @end smallexample @end cartouche @noindent Note that the @code{$(this)} contains the name of the server used. This variable may be used in the source and destination strings in order to tailor the filename when downloading from multiple sources (see below). @table @code @anchor{dest} @item dest The destination file is the only obligatory item. This must be the name of an object which matches the type of the master object i.e. if the master is a plain file, the destination must also be the explicit name of a plain file. An implicit `copy file to directory' syntax is not allowed. Symbolic links are copied as symbolic links, plain files are copied as plain files and special files are copied as special files. The @code{recurse} option is required to copy the contents of subdirectories. If the destination file name is of the form @file{filename/..namedfork/rsrc}, then it is assumed that you are copying the resource fork of a file to an HFS+ file system on OS X Jaguar. In the absence of the destination file being in this form (just dest=filename), cfengine will assume that you are working with the data fork of the file. See @ref{dest}. For a resource fork copy to properly work, the data fork must have already been copied. Ie the OS will not allow you to copy the resource fork for a file that does not exist. And, copying a data fork after the resource fork will overwrite the resource fork. So, order is important. Copy the data fork, first. Then, copy the resource fork. To split the data and resource forks of a file into two parts, open up a terminal. The following commands will copy MyFile 's data and resource forks into two separate files which can then be recombined by cfengine: @smallexample cp MyFile MyFile-datafork cp MyFile/..namedfork/rsrc MyFile-rsrcfork @end smallexample @item mode, owner, group The file mode, owner and group of the images are specified as in the @code{files} function @xref{files}. @anchor{copyaction} @item action The action may take the values @code{warn}, @code{silent} or @code{fix}. The default action is @code{fix}, i.e. copy files. If @code{warn} is specified, only a warning is issued about files which require updating. If @code{silent} is given, then cfengine will copy the files but not report the fact. @anchor{force} @item force If set to `true', this option causes cfengine to copy files regardless of whether it is up to date. @anchor{forceipv4} @item forceipv4 If you are working on an ipv6 enabled pair of hosts, cfengine will normally select ipv6 for communication between them. If you wish to force the use of ipv4 for some reason, set this option to true. @anchor{forcedirs} @item forcedirs If set to `true', this option causes files or links which block the creation of directories, during recursive copying, to be moved aside forcably. A single non-supressable warning is given when this occurs; the file is moved to filename@file{.cf-moved}. @anchor{copybackup} @item backup If the @code{backup} option is set to ``false'', cfengine will not make a backup copy of the file before copying. The default value is ``true''. If the option ``timestamp'' is chosen, a unique timestamp will be appended to the saved filename. @cindex Backup of files in copy @vindex backup= @cindex Switching off backup in copy @anchor{copyrepository} @item repository This allows a local override of the @code{Repository} variable, on an item by item basis. If set to ``off'' or ``none'' it cancels the value of a global repository. Copy makes a literal image of the master file at the destination, checking whether the master is newer than the image. If the image needs updating it is copied. Existing files are saved by appending @code{.cfsaved} to the filename. @anchor{stealth} @item stealth If set to `on' causes cfengine to preserve atime and mtime on the source files during @emph{local} file copies. File times cannot be preserved on remote copies. This option should normally only be used together with a checksum copy, since preserving atime and mtime implies changing ctime which will force continual copying. This is a weakness in the Unix file system. Ctime cannot be preserved. Before version 1.5.0, there was a typo which made this option active on many file copies. @mbindex ctime copy doesn't always copy files @mbindex copy doesn't always copy files @anchor{checkroot} @item checkroot Default value @code{false}, this option causes cfengine to check the permissions of the root directory during recursive directory copies. If not true, cfengine sets its own permissions on the root. @anchor{timestamps} @item timestamps If this is set to `preserve' or `keep', the times of the source files are inherited by the destination files during copying. This is like the `p' option of the @code{tar} command. @cindex Preserving file times in copy @anchor{recurse} @item recurse Specifies the depth of recursion when copying whole file-trees recursively. The value may be a number or the keyword @code{inf}. Cfengine crosses device boundaries or mounted filesystems when descending recursively through file trees. To prevent this it is simplest to specify a maximum level of recursion. @cindex Device boundaries @cindex Mounted filesystems @anchor{symlink} @item symlink This option may be repeated a number of times to specify the names of files, or wildcards which match files which are to be symbolically linked instead of copied. A global list of patterns can also be defined in the control section of the program @xref{linkcopies}. @anchor{copyignore} @item ignore This works like the global ignore directive but here you may provide a private list of ignorable directories and files. Unlike include, exclude this affects the way cfengine parses directory trees. @anchor{copyinclude} @item include This option may be repeated a number of times to specify the names of files, or wildcards which match files which are to be included in a copy operation. Specifying one of these automatically excludes everything else except further include patterns. A global list of patterns can also be defined in the control section of the program. @cindex Purge, excluding files If the @code{purge} option is used in copying, then the @code{ignore} option has the effect of the excluding files from the purge, i.e. @code{ignore} means `keep' the named files. @anchor{copyexclude} @item exclude This option may be repeated a number of times to specify the names of files, or wildcards which match files which are to be excluded from a copy operation. A global list of patterns can also be defined in the control section of the program `excludes' override `includes'. @xref{excludelinks}. @anchor{copyxdev} @item xdev Prevents cfengine from descending into file systems that are not on the same device as the root of the rescurion path. @cindex xdev @anchor{copytype} @item type Normally cfengine uses the ctime date-stamps on files to determine whether a file needs to be copied: a file is only copied if the master is newer than the copy or if the copy doesn't exist. If the type is set to @samp{checksum} or @samp{sum}, then a secure MD5 checksum is used to determine whether the source and destination files are identical. If @samp{byte} or @samp{binary} is specified, a byte by byte comparison is initiated. An @samp{mtime} comparison does not take into account changes of file permissions, only modifications to the contents of the files. @anchor{findertype} @item findertype Sets the four letter file type code in an HFS+ file system on Mac OS X Jaguar. For example, the four letter code APPL indicates the file is an Application (and will be executed when double-clicked). The four letter code TEXT indicates the file is a text file and will be opened by the default text editor. If the file also has an extension (for example @code{.txt}), then if setting the finder type code, you should make sure your finder type code does not conflict with the file extension. Files both without extensions and finder type codes are mostly useless to OS X, so be sure to do one or the other! Also note that finder type codes should not be applied to the resource forks of files. @anchor{server} @item server If you want to copy a file remotely from a server, you specify the name of the server here. This must be the name of a host which is running the @code{cfservd} daemon, and you must make sure that you have defined the variable @code{domain} in the control section of the @file{cfagent.conf} file. If you don't define a domain you will probably receive an error of the form `cfengine: Hey! cannot stat file'. If the server name is `localhost', cfengine will perform a local copy, without using a connection to cfservd. @mbindex Hey! Cannot stat file error @mbindex Remote copy problems, can't stat @mbindex locahost in copy @anchor{failover} @item failover If a file copy fails due to an error, the classes in this assignment will become active, allowing failover rules to become active. @cindex failover @anchor{oldserver} @item oldserver If this is true, cfengine uses the old protocol specification for temporary compatibility with early version 2 alphas. @anchor{trustkey} @item trustkey This option defaults to 'no' or 'false'. If set to true, cfagent will accept a public key from a server whose public key is presently unknown to the agent, on trust. This option should be used to bootstrap public key transfer between hosts. Once a public key has been accepted, it will not be replaced automatically. Dated public keys must be removed by hand. @cindex Public keys @cindex Trusted hosts @anchor{encrypt} @item encrypt Has an effect only when used in conjuction with copy from a remote file server. This causes cfengine to use encryption and one-time keys on transferred data. (This requires RSA keys to be installed on both client and server hosts, and provides strong authentication and encryption, using random session keys.) The preferred algorithm is Blowfish, with a 128 bit key. Generally speaking the only case in which this function makes sense is in transferring shadow password files. Encrypting the transfer of system binaries makes little sense. Note: the encryption keys required to get files from cfservd are those for the user under which cfservd is running (normally root). @anchor{verify} @item verify If verify is true, cfagent attempts to verify the integrity of a remote file transfer before the new file is installed. This takes time, since an MD5 computation and transaction must take place. @anchor{size} @item size With this option you can specify that a file is only to be copied if the source file meets a size critereon. This could be used to avoid installing a corrupted file (the copying of an empty password file, for instance). Sizes are in bytes by default, but may also be quoted in kilobytes or megabytes using the notation: @smallexample @var{number}bytes @var{number}kbytes @var{number}mbytes @end smallexample @noindent Only the first characters of these strings are significant, so they may be written however is convenient: e.g. @kbd{14kB}, @kbd{14k}, @kbd{14kilobytes} etc. Examples are: @smallexample size=<400 # copy if file size is < 400 bytes size=400 # copy if file size is equal to 400 bytes size=>400 # copy if file size > 400 bytes @end smallexample @noindent @anchor{linktype} @item linktype This option determines the type of link used to make links. This only applies if the file is linked rather than copied because it matches a pattern set by @code{symlink}. The default type is a direct symbolic link. The values @samp{relative} or @samp{absolute} may be used, but hard links may not be created in place of copied files, since hard links must normally reside on the same filesystem as their files, and it is assumed that most links will be between filesystems. If this value is set to @code{copy} or @code{none}, symbolic links will be replaced by actual copies of the files they point to. Note that for directories, this option is ignored. @anchor{typecheck} @item typecheck Controls whether cfengine allows files of one type to overwrite files of another type, i.e. switches on/off errors if source and existing destination files do not match in type, e.g. if a file would overwrite a directory or link. The default is on for safety reasons. @anchor{copydefine} @item define This option is followed by a list of classes which are to be `switched on' if and only if the named file was copied. In multiple (recursive) copy operations the classes become defined if any of the files in the file tree were copied. This feature is useful for switching on other actions which are to be performed after the installation of key files (e.g. package installation scripts etc). @anchor{purge} @item purge If this option is set to true, cfengine will remove files in the destination directory which are not also in the source directory. This allows exact images of filesystems to be mantained. Note that if the copy command has includes or excludes or ignored files, cfengine will purge only those files on the client machine which are also on the server. Included files are not purged. This means that some files (such as system specific work files) can be excluded from copies without them being destroyed. @vindex purge= @cindex Copy, exact filetree images @cindex File tree images @cindex Tree copying, exact Note that purging is disallowed if contact with a remote server fails. This means that local files will not be destroyed by a denial of service attack. @emph{You should not use this option to synchronize NFS mounted file systems. If the NFS server goes down, cfengine cannot then tell the difference between a valid empty directory and a missing NFS file system. If you use purge, use a remote copy also.} If we specify purge, then the following options will also be set and cannot be altered: @code{forcedirs=true}, @code{typecheck=false}, since other defaults could be very destructive. @end table @menu * copy example:: * hard links in copy:: * Too many open files:: @end menu @node copy example, hard links in copy, copy, copy @subsection copy example Example: @smallexample copy: /local/etc/aliases dest=/etc/aliases m=644 o=root g=other /local/backup-etc dest=/etc solaris:: /local/etc/nsswitch.conf dest=/etc/nsswitch.conf @end smallexample @noindent In the first example, a global aliases file is copied from the master site file @file{/local/etc/aliases} to @file{/etc/aliases}, setting the owner and protection as specified. The file gets installed if @file{/etc/aliases} doesn't exist and updated if @file{/local/etc/aliases} is newer than @file{/etc/aliases}. In the second example, @file{backup-etc} is a directory containing master configuration files (for instance, @file{services}, @file{aliases}, @file{passwd}...). Each of the files in @file{backup-etc} is installed or updated under @file{/etc}. Finally, a global @file{nsswitch.conf} file is kept up to date for Solaris systems. The @code{home} directive can be used as a destination, in which case cfengine will copy files to every user on the system. This is handy for distributing setup files and keeping them updated: @smallexample copy: /local/masterfiles/.cshrc dest=home/.cshrc mode=0600 @end smallexample @noindent You can force the copying of files, regardless of the date stamps by setting the option @code{force=true} or @code{force=on}. The default is @code{force=false} or @code{force=off}. @cindex Force copying @vindex force= @menu * hard links in copy:: * Too many open files:: @end menu @node hard links in copy, Too many open files, copy example, copy @subsection Hard links in copying Hard links are not like symbolic links, they are not merely pointers to other files, but alternative names for the same file. The name of every file is a hard link, the first so to speak. You can add additional names which @emph{really are} the file, they are not just pointers. For the technically minded, they are not separate inodes, they are additional directory references to the same inode. When you perform a copy operation on multiple files, cfengine attempts to preserve hard links but this is a difficult task. Because a hard link just looks like an ordinary file (it cannot be distingiushed from the original, the way a symbolic link can) there is a danger that any copy operation will copy two hard links to the same file as two separate copies of the same file. The difference is that changes a hard-linked file propagate to the links, whereas two copies of a file are completely independent thereafter. In order to faithfully reproduce all hardlinks to all files, cfengine needs to examine every file on the same filesystem and check whether they have the same inode-number. This would be an enourmous overhead, so it is not done. Instead what happens is that cfengine keeps track of only the files which it is asked to examine, for each atomic copy-command, and makes a note of any repeated inodes within this restricted set. It does not try to go off, wandering around file systems looking to other files which might be hardlinks. To summarize, cfengine preserves hardlinks during copying, only within the scope of the present search. No backups are made of hard links, only of the first link or name of the file is backed up. This is a necessary precaution to avoid dangling references in the inode table. As a general rule, hard links are to be avoided because they are difficult to keep track of. @node Too many open files, , hard links in copy, copy @subsection Too many open files @cindex Too many open files error @mbindex Too many open files error In long recursive copies, where you descend into many levels of diretories, you can quickly run out of file descriptors. The number of file descriptors is a resource which you can often set in the shell. It is a good idea to set this limit to a large number on a host which will be copying a lot of files. For instance, in the C shell you would write, @smallexample limit descriptors 1024 @end smallexample @noindent Most systems should have adequate defaults for this parameter, but on some systems it appears to be set to a low value such as 64, which is not sufficient for large recursive tree searches. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node defaultroute, disks, copy, Cfagent reference @section defaultroute Dynamical routing is not configurable in cfengine, but for machines with static routing tables it is useful to check that a default route is configured to point to the nearest gateway or router. The syntax for this statement is simply: @smallexample defaultroute: @var{class}:: my_gateway @end smallexample @noindent For example: @smallexample defaultroute: most:: 129.240.22.1 rest:: small_gw no_default_route:: 192.168.1.1 @end smallexample @noindent Gateways and routers usually have internet address @code{aaa.bbb.ccc.1} --- i.e. the first address on the subnet. You may use the numerical form or a hostname for the gateway. The class @code{no_default_route} is defined if the current host does not have a currently defined default route, but specifies one in its configuration. @cindex no_default_route class @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node disks, directories, defaultroute, Cfagent reference @section disks This is a synonyn for @code{required}, @xref{required}. @cindex disks actions This action tests for the existence of a file or filesystem. It should be called after all NFS filesystems have been mounted. You may use the special variable @code{$(binserver)} here. @cartouche @w{} @smallexample disks: /@var{filesystem} freespace=@var{size-limit} define=@var{class-list}(,:.) inform=@var{true} log=@var{true} audit=@var{true/false} scanarrivals=@var{true} force=@var{true} ifelapsed=@var{mins} expireafter=@var{mins} @end smallexample @end cartouche Files or filesystems which you consider to be essential to the operation of the system can be declared as `required'. Cfengine will warn if such files are not found, or if they look funny. Suppose you mount your filesystem @code{/usr/local} via NFS from some binary server. You might want to check that this filesystem is not empty! This might occur if the filesystem was actually @emph{not} mounted as expected, but failed for some reason. It is therefore not enough to check whether the directory @code{/usr/local} exists, one must also check whether it contains anything sensible. Cfengine uses two variables: @code{sensiblesize} and @code{sensiblecount} to figure out whether a file or filesystem is sensible or not. You can change the default values of these variables (which are 1000 and 2 respectively) in the @code{control} section. @xref{control}. If a file is smaller than @code{sensiblesize} or does not exist, it fails the `required' test. If a directory does not exist, or contains fewer than @code{sensiblecount} files, then it also fails the test and a warning is issued. @smallexample disks: any:: /$(site)/$(binserver)/local @end smallexample If you set the @code{freespace} variable to a value and set @code{inform=true}, cfagent issues warnings when free disk space falls below this threshold. Any define-classes also become defined in this instance. (the default units are kilobytes, but you may specify bytes or megabytes), e.g. @vindex freespace= @cindex freespace= @cindex Warning about full disks @cindex Full disk warnings @w{} @smallexample required: /site/host/home1 freespace=50mb define=dotidy /site/host/home2 freespace=10% define=dotidy @end smallexample @cindex Percentage disk space @noindent then cfengine will warn when the filesystem concerned has less than this amount of free space. By adding a @code{define} tag, you can switch on any number of classes if this happens. This allows you to activate special measures for dealing with a filesystem which is in danger of becoming full. If the option @code{force=true} is used, cfengine will parse filesystems even on NFS mounted filesystems. Normally it does not make sense to check filesystems that are not native to the local host, but occasionally ne would like to force such a check in order to set a class, based on the result, for instance. @vindex force= @cindex NFS filesystems and disk checking @cindex Setting classes based on non-local disks @vindex scanarrivals= @cindex scanarrivals= If the @code{scanarrivals} option is set, the agent will recursively descend through the file system building a database of file modification times. This data is used for research purposes and will eventually be used to trigger classes that determine optimal times for backup of filesystem. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node directories, disable, disks, Cfagent reference @section directories @cindex Directories, making @cindex Paths, making @cindex Making directories @cindex Making paths Directories declarations consist of a number of directories to be created. Directories and files may also be checked and created using the @code{touch} option in the @code{files} actions. @xref{files}. The form of a declaration is: @cartouche @w{} @smallexample directories: @var{classes}:: /@var{directory} mode=@var{mode} owner=@var{uid} group=@var{gid} rxdirs=@var{true/on}/@var{false/off} define=@var{classlist} elsedefine=@var{classlist} syslog=@var{true/on}/@var{false/off} inform=@var{true/on}/@var{false/off} audit=@var{true/on}/@var{false/off} ifelapsed=@var{mins} expireafter=@var{mins} @end smallexample @end cartouche @noindent For example @smallexample directories: @var{class}:: /usr/local/bin mode=755 owner=root group=wheel @end smallexample @noindent The form of the command is similar to that of @code{files} but this command is only used to create new directories. Valid options are @code{mode}, @code{owner}, @code{group} and @code{rxdirs}; these are described under @code{files} @xref{files}. This interface is only for convenience. It is strictly a part of the `files' functionality and is performed together with other `files' actions at run time. The creation of a path will fail if one of the links in the path is a plain file or device node. A list of classes may optionally be defined here if a directory is created. If the @code{owner} value is set to the literal "LastNode", then the owner will be exchanged for the last node of the path. This allows the creation of home directories owned by users. @cindex Home directories, creating @cindex @code{LastNode} literal @smallexample control: homedirs = ( mark:simen:luke:aeleen ) directories: /home/$(listcontent) owner=LastNode @end smallexample @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node disable, editfiles, directories, Cfagent reference @section disable @cindex Disabling files @cindex Renaming files @vindex disable Disabling a file means renaming it so that it becomes harmless. This feature is useful if you want to prevent certain dangerous files from being around, but you don't want to delete them--- a deleted file cannot be examined later. The syntax is @cartouche @w{} @smallexample disable: @var{class}:: /@var{filename} dest=@var{filename} type=@var{plain/file/link/links} rotate=@var{empty/truncate/numerical-value} size=@var{numerical-value} define=@var{classlist} syslog=@var{true/on}/@b{false/off} inform=@var{true/on}/@b{false/off} audit=@var{true/on}/@var{false/off} repository=@var{destination directory} action=@b{disable}/@var{warn} ifelapsed=@var{mins} expireafter=@var{mins} @end smallexample @end cartouche @noindent If a destination filename is specified, cfagent renames the source file to the destination, where possible (renaming across filesystems is not allowed). If no destination is given, cfagent renames a given file by appending the name of the file with the suffix @file{.cfdisabled}. Note that directories are only renamed if they have a specific destination specified. A typical example of a file you would probably want to disable would be the @code{/etc/hosts.equiv} file which is often found with the @samp{+} symbol written in it, opening the system concerned to the entire NIS universe without password protection! @cindex @file{/etc/hosts.equiv} @cindex @code{.cfdisabled} Here is an example: @smallexample disable: /etc/hosts.equiv /etc/nologin /usr/lib/sendmail.fc sun4:: /var/spool/cron/at.allow @end smallexample @noindent Hint: The last example disables a file which restricts access to the @code{at} utility. Such a command could be followed by a file action, @xref{files}, @w{} @smallexample files: some:: /var/spool/cron/at.allow =0644 N owner=root group=wheel touch @end smallexample @noindent which would create an empty security file @file{at.allow}. See also your system manual pages for the @code{at} command if you don't understand why this could be useful. Disabling a link deletes the link. If you wish you may use the optional syntax @smallexample disable: /directory/name type=file @end smallexample @noindent to specify that a file object should only be disabled if it is a plain file. The optional element @code{type=} can take the values @code{plain}, @code{file}, @code{link} or @code{links}. If one of these is specified, cfengine checks the type and only disables the object if there is a match. This allows you to disable a file and replace it by a link to another file for instance. @cindex Replacing file by link @vindex type= @cindex Disabling file types NOTE that if you regularly disable a file which then gets recreated by some process, the disabled file @file{@var{filename}.cfdisabled} will be overwritten each time cfengine disables the file and therefore the contents of the original are lost each time. The @code{rotate} facility was created for just this contingency. @cindex Truncating log files @cindex Controlling the size of log files @cindex Log files, controlling the size of @cindex Rotating log files The disable feature can be used to control the size of system log files, such as @file{/var/adm/messages} using a further option @code{rotate}. @vindex rotate= @vindex empty @vindex truncate If the value rotate is set to 4, say, @smallexample disable: @var{filename} rotate=4 @end smallexample @noindent then cfengine renames the file concerned by appending `.1' to it and a new, empty file is created in its place with the same owner and permissions. The next time disable is executed `.1' is renamed to `.2' and the file is renamed `.1' and a new empty file is created with the same permissions. Cfengine continues to rotate the files like this keeping a maximum of four files. This is similar to the behaviour of syslog. If you simply want to empty the contents of a log file, without retaining a copy then you can use @code{rotate=empty} or @code{rotate=truncate}. For instance, to keep control of your World Wide Web server logs: @smallexample disable: Sunday|Wednesday:: /usr/local/httpd/logs/access_log rotate=empty @end smallexample @noindent This keeps a running log which is emptied each Sunday and Wednesday. @cindex WWW server logs The @code{size=} option in disable allows you to carry out a disable operation only if the size of the file is less than, equal to or greater than some specified size. Sizes are in bytes by default, but may also be quoted in kilobytes or megabytes using the notation: @smallexample @var{number}bytes @var{number}kbytes @var{number}mbytes @end smallexample @noindent Only the first characters of these strings are significant, so they may be written however is convenient: e.g. @kbd{14kB}, @kbd{14k}, @kbd{14kilobytes} etc. Examples are: @smallexample size=<400 # disable if file size is < 400 bytes size=400 # disable if file size is equal to 400 bytes size=>400 # disable if file size > 400 bytes @end smallexample @noindent This options works with @code{rotate} or normal disabling; it is just an extra condition which must be satisfied. @cindex size field in disable If a disable command results in action being taken by cfengine, an optional list of classes becomes can be switched on with the aid of a statement @code{define=@var{classlist}} in order to trigger knock-on actions. The @code{repository} declaration allows a local override of the @code{Repository} variable, on an item by item basis. If set to ``off'' or ``none'' it cancels the value of a global repository and leaves the disabled file in the same directory. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node editfiles, Editfiles on Binary Files, disable, Cfagent reference @section editfiles Performs ascii (line-based) editing on text-files or limited binary editing of files. If editing a file which has hard links to it, be aware that editing the file will destroy the hard link references. This is also the case with shell commands. You should avoid hard links whenever possible. @cindex awk, editing @cindex sed, editing The form of an editing command is @code{editfiles} can also search directories recursively through directories and edit all files matching a pattern, using @code{Include}, @code{Exclude}, and @code{Ignore} (see Recursive File Sweeps in the tutorial). @cartouche @w{} @smallexample editfiles: @var{class}:: @{ @var{file-to-be-edited} @var{action} "@var{quoted-string...}" @} @{ @var{directory-to-be-edited} Recurse "inf" # iterated over all files Filter "filteralias" Include ".cshrc" Ignore "bin" Ignore ".netscape" @var{action} "@var{quoted-string...}" @} @end smallexample @end cartouche @noindent Here are some examples: @smallexample editfiles: sun4:: @{ /etc/netmasks DeleteLinesContaining "255.255.254.0" AppendIfNoSuchLine "128.39 255.255.255.0" @} PrintServers:: @{ /etc/hosts.lpd AppendIfNoSuchLine "tor" AppendIfNoSuchLine "odin" AppendIfNoSuchLine "borg" @} @end smallexample @noindent The first of these affects the file @file{/etc/netmasks} on all SunOS 4 systems, deleting any lines containing the string ``255.255.254.0'' and Appending a single line to the file containing ``128.39 255.255.255.0'' if none exists already. The second affects only hosts in the class `PrintServers' and adds the names of three hosts: tor, odin and borg to the file @file{/etc/hosts.lpd} which specifies that they are allowed to connect to the printer services on any host in the class `PrintServers'. @cindex Quoted strings @cindex Single quotes @cindex Double quotes @noindent Note that single or double quotes may be used to enclose strings in cfengine. If you use single quotes, your strings may contain double quotes and vice-versa. Otherwise a double quoted string may not currently contain double quotes and likewise for single quoted strings. As of version 2.0.6 quoted strings may contain escaped quotes using @code{\"}. As of version 1.3.0, you can use the @samp{home} directive in edit filenames, enabling you to edit files for every user on the system, provided they exist. For example, to edit every user's login files, you would write @smallexample @{ home/.cshrc AppendIfNoSuchLine "setenv PRINTER default-printer" AppendIfNoSuchLine "set path = ( $path /new/directory )" @} @end smallexample @noindent If a user does not possess the named file, cfengine just skips that user. A new file is not created. @noindent The meanings of the file-editing actions should be self-explanatory. Commands containing the word 'comment' are used to `comment out' certain lines in a file rather than deleting them. @code{Hash} implies a shell comment of the type @smallexample # comment @end smallexample @noindent @code{Slash} implies a comment of the C++ type: @w{} @smallexample // comment @end smallexample @noindent @code{Percent} implies a comment of the type: @w{} @smallexample % comment @end smallexample More general comment types may be defined using the @code{SetCommentStart}, @code{SetCommentEnd} and @code{CommentLinesMatching}, @code{CommentLinesStarting} functions. A special group of editing commands is based on the POSIX Regular Expression package. These use regular expressions to search line by line through text and perform various editing functions. Searches are of two different types: ``LineMatching'' and ``LineContaining''. In the first case the regular expression must match the entire line exactly; in the latter, a substring is searched for in the file. Some of these commands are based on the concept of a file pointer. The pointer starts at line one of the file and can be reset by 'locating' a certain line, or by using the reset-pointer commands. The current position of the pointer is used by commands such as @code{InsertLine} to allow a flexible way of editing the middle of files. A simple decision mechanism is incorporated to allow certain editing actions to be excluded. For instance, to insert a number of lines in a file once only, you could write: @smallexample @{ @var{file} LocateLineMatching "@var{insert point...}" IncrementPointer "1" BeginGroupIfNoMatch "# cfengine - 2/Jan/95" IncrementPointer "-1" InsertLine "# cfengine - 2/Jan/95" InsertLine "/local/bin/start-xdm" DefineInGroup "AddedXDM" EndGroup @} @end smallexample @noindent Since the first inserted line matches the predicate on subsequent calls, the grouped lines will only be carried out once. When the grouped lines are run, the @samp{AddedXDM} class will be activated for use by a later part of the script. The full list of editing actions is given below in alphabetical order. Note that some commands refer to regular expressions and some refer to 'literal strings' (i.e. any string which is not a regular expression). Variable substitution is performed on all strings. Be aware that symbols such as @samp{.}, @samp{*} and so on are meta-characters in regular expressions and a backslash must be used to make them literal. The regular expression matching functions are POSIX extended regular expressions. @xref{Regular expressions,Regular expressions,Regular expressions,cfengine-Tutorial}. @cartouche @b{Editfile caution.} It is suggested that you use these editing functions with caution. Although all possible safeguards have been incorporated into them, it is still possible through carelessness to do damage to important files on your system. Always test editing programs carefully before committing them to your global site configuration. @end cartouche @c ..................................................... @c SUBSECTION @c ..................................................... @menu * AbortAtLineMatching:: * Append:: * AppendIfNoLineMatching:: * AppendIfNoSuchLine:: * AppendIfNoSuchLinesFromFile:: * AppendToLineIfNotContains:: * Audit:: * AutoCreate:: * AutomountDirectResources:: * Backup in editfiles:: * BeginGroupIfDefined:: * BeginGroupIfNotDefined:: * BeginGroupIfFileExists:: * BeginGroupIfFileIsNewer:: * BeginGroupIfLineContaining:: * BeginGroupIfLineMatching:: * BeginGroupIfMatch:: * BeginGroupIfNoLineContaining:: * BeginGroupIfNoLineMatching:: * BeginGroupIfNoMatch:: * BeginGroupIfNoSuchLine:: * BreakIfLineMatches:: * CatchAbort:: * CommentLinesMatching:: * CommentLinesStarting:: * CommentNLines:: * CommentToLineMatching:: * DefineClasses:: * DefineInGroup:: * DeleteLinesAfterThisMatching:: * DeleteLinesContaining:: * DeleteLinesMatching:: * DeleteLinesStarting:: * DeleteLinesNotContaining:: * DeleteLinesNotMatchingFileItems:: * DeleteLinesNotStartingFileItems:: * DeleteNLines:: * DeleteToLineMatching:: * EditMode (binary):: * EditSplit:: * EmptyEntireFilePlease:: * ElseDefineClasses:: * EndGroup:: * EndLoop:: * ExpandVariables:: * ExpireAfter editfiles:: * Filter:: * FixEndOfLine:: * ForEachLineIn:: * GotoLastLine:: * HashCommentLinesContaining:: * HashCommentLinesMatching:: * HashCommentLinesStarting:: * IfElapsed (editing):: * IncrementPointer:: * Inform (editing):: * InsertFile:: * InsertLine:: * LocateLineMatching:: * PercentCommentLinesContaining:: * PercentCommentLinesMatching:: * PercentCommentLinesStarting:: * Prepend (editing):: * PrependIfNoLineMatching:: * PrependIfNoSuchLine:: * Recurse (editing):: * ReplaceLineWith:: * ReplaceAll With:: * ReplaceFirst:: * ReplaceLinesMatchingField:: * Repository:: * ResetSearch:: * RunScript:: * RunScriptIfLineMatching:: * RunScriptIfNoLineMatching:: * SetCommentStart:: * SetCommentEnd:: * SetLine:: * SetScript:: * SlashCommentLinesContaining:: * SlashCommentLinesMatching:: * SlashCommentLinesStarting:: * SplitOn:: * SysLog:: * Umask:: * UnCommentLinesContaining:: * UnCommentLinesMatching:: * UnCommentsNLines:: * UnCommentToLineMatching:: * UnsetAbort:: * UseShell:: * WarnIfFileMissing:: * WarnIfLineContaining:: * WarnIfLineMatching:: * WarnIfLineStarting:: * WarnIfNoLineContaining:: * WarnIfNoLineMatching:: * WarnIfNoLineStarting:: * WarnIfNoSuchLine:: @end menu @node AbortAtLineMatching, Append, editfiles, editfiles @subsection AbortAtLineMatching @smallexample AbortAtLineMatching @var{quoted-regex} @end smallexample This command sets the value of a regular expression. In all editing operations (except @code{FixEndOfLine} and @code{GotoLastLine}) which involve multiple replacements and searches, this expression marks a boundary beyond which cfengine will cease to look any further. In other words, if cfengine encounters a line matching this regular expression, it aborts the current action. BE CAREFUL with this feature: once set, the string remains set for the remainder of the current file. It might therefore interact in unsuspected ways with other search parameters. Editing actions are always aborted as soon as the abort expression is matched. Use @code{UnsetAbort} to unset the feature. @c ..................................................... @c SUBSECTION @c ..................................................... @node Append, AppendIfNoLineMatching, AbortAtLineMatching, editfiles @subsection Append @smallexample Append @var{quoted-regex} @end smallexample Add a line containing the quoted string to the end of the file. This should be used in conjunction with the decision structures @code{BeginGroupIfNoLineMatching} and @code{BreakIfLineMatches}. @c ..................................................... @c SUBSECTION @c ..................................................... @node AppendIfNoLineMatching, AppendIfNoSuchLine, Append, editfiles @subsection AppendIfNoLineMatching @smallexample AppendIfNoLineMatching @var{quoted-regex}/ ``ThisLine'' @end smallexample A new version of the older @code{AppendIfNoSuchLine} which uses a regular expression instead of a literal string. The line which gets appended must be set previously using @code{SetLine}. If @code{``ThisLine''} is given as the argument, the current value of then line buffer is assumed. This allows constructions for merging files on a convergent line-by-line basis: @smallexample editfiles: @{ /tmp/bla ForEachLineIn "/tmp/in" AppendIfNoLineMatching "ThisLine" EndLoop @} @end smallexample @cindex Merging files. @c ..................................................... @c SUBSECTION @c ..................................................... @node AppendIfNoSuchLine, AppendIfNoSuchLinesFromFile, AppendIfNoLineMatching, editfiles @subsection AppendIfNoSuchLine @smallexample AppendIfNoSuchLine @var{quoted-string} @end smallexample Add a line containing the quoted string to the end of the file if the file doesn't contain the exact line already. @c ..................................................... @c SUBSECTION @c ..................................................... @node AppendIfNoSuchLinesFromFile, AppendToLineIfNotContains, AppendIfNoSuchLine, editfiles @subsection AppendIfNoSuchLinesFromFile @smallexample AppendIfNoSuchLinesFromFile @var{filename} @end smallexample For each line in the named file, call AppendIfNoSuchLine. This adds lines containing the strings listed in the named file to the end of the current file if the file doesn't contain the exact line already. @cindex @code{AppendIfNoSuchLinesFromFile} @c ..................................................... @c SUBSECTION @c ..................................................... @node AppendToLineIfNotContains, Audit, AppendIfNoSuchLinesFromFile, editfiles @subsection AppendToLineIfNotContains @smallexample AppendToLineIfNotContains @var{quoted-string} @end smallexample This commands looks for an exact match of the quoted string in the current line. If the quoted string is not contained in the line, it is appended. This may be used for adding entries to a list. @c ..................................................... @c SUBSECTION @c ..................................................... @node Audit, AutoCreate, AppendToLineIfNotContains, editfiles @subsection Audit in editfiles @smallexample Audit @var{true/false} @end smallexample Local decision about whether this edit stanza will be audited. Requires auditing to be on globally for this to have an effect. @c ..................................................... @c SUBSECTION @c ..................................................... @node AutoCreate, AutomountDirectResources, Audit, editfiles @subsection AutoCreate If this command is listed anywhere in the file action list, cfengine will create the named file if it doesn't exist. Normally cfengine issues an error if the named file does not exist, but if this is set, notification of the file's absence is only in verbose output. New files are created with mode 644 (see also Umask), read access for everyone and write access for the cfengine user (normally root). Note that if you set this, BeginGroupIfFileIsNewer will always be true. @cindex @code{AutoCreate} @mbindex How to create files while editing @c ..................................................... @c SUBSECTION @c ..................................................... @node AutomountDirectResources, Backup in editfiles, AutoCreate, editfiles @subsection AutomountDirectResources @smallexample AutomountDirectResources @var{quoted-string} @end smallexample This command is designed to assist with automounter configuration for users wishing to use the automounter for NFS filesystems, but still use the cfengine mount model. @cindex NFS mount model and automounter @cindex automounter Applied to the current file, it is equivalent to saying: for each of the mountable resources in the list @xref{mountables}, append if not found a line for a direct automount map command, to the current file. The string which follows can be used to specify any special mount options e.g. @code{``-nosuid''} for non setuid mounting (of all the mountables). Note that this is added to the current file and not to a file named @file{/etc/auto_direct}. @c ..................................................... @c SUBSECTION @c ..................................................... @node Backup in editfiles, BeginGroupIfDefined, AutomountDirectResources, editfiles @subsection Backup in editfiles @smallexample Backup @var{quoted-string} @end smallexample Set to true or false, on or off to set backup policy for this file. Default is on. The default is to produce time-stamped backups of files; this may be coded explicitly by setting to ``timestamp'' or ``stamp''. If set to ``false'' or ``off'', no backup is kept of the edited file. If the value is set to ``single'' or ``one'' then only the last version of the file is kept, overwriting any previously saved versions. See @ref{copybackup}. @smallexample Backup "single" @end smallexample @cindex Backup @c ..................................................... @c SUBSECTION @c ..................................................... @node BeginGroupIfDefined, BeginGroupIfNotDefined, Backup in editfiles, editfiles @subsection BeginGroupIfDefined @smallexample BeginGroupIfDefined @var{quoted-string} @end smallexample The lines following, up to the first @code{EndGroup} are executed if the quoted class is defined. Edit groups may be nested. @cindex @code{BeginGroupIfDefined} @c ..................................................... @c SUBSECTION @c ..................................................... @node BeginGroupIfNotDefined, BeginGroupIfFileExists, BeginGroupIfDefined, editfiles @subsection BeginGroupIfNotDefined @smallexample BeginGroupIfNotDefined @var{quoted-string} @end smallexample The lines following, up to the first @code{EndGroup} are executed if the quoted class is not defined. Edit groups may be nested. @cindex @code{BeginGroupIfNotDefined} @c ..................................................... @c SUBSECTION @c ..................................................... @node BeginGroupIfFileExists, BeginGroupIfFileIsNewer, BeginGroupIfNotDefined, editfiles @subsection BeginGroupIfFileExists @smallexample BeginGroupIfFileExists @var{quoted-string} @end smallexample The lines following, up to the first @code{EndGroup} are executed if the quoted filename exists (can be statted). Files which are not readable by the running process are for all intents and purposes non-existent. Edit groups may be nested. @cindex @code{BeginGroupIfFileExists} @c ..................................................... @c SUBSECTION @c ..................................................... @node BeginGroupIfFileIsNewer, BeginGroupIfLineContaining, BeginGroupIfFileExists, editfiles @subsection BeginGroupIfFileIsNewer @smallexample BeginGroupIfFileIsNewer @var{quoted-string} @end smallexample The lines following, up to the first @code{EndGroup} are executed if the quoted filename is newer than the file being edited. Edit groups may be nested. @cindex @code{BeginGroupIfFileIsNewer} @c ..................................................... @c SUBSECTION @c ..................................................... @node BeginGroupIfLineContaining, BeginGroupIfLineMatching, BeginGroupIfFileIsNewer, editfiles @subsection BeginGroupIfLineContaining @smallexample BeginGroupIfLineContaining @var{quoted-string} @end smallexample The lines following, up to the first @code{EndGroup} are executed if the quoted string appears in any line in the file. Edit groups may be nested. @c ..................................................... @c SUBSECTION @c ..................................................... @node BeginGroupIfLineMatching, BeginGroupIfMatch, BeginGroupIfLineContaining, editfiles @subsection BeginGroupIfLineMatching @smallexample BeginGroupIfLineMatching @var{quoted-regex} @end smallexample The lines following, up to the first @code{EndGroup} are executed if the quoted regular expression matches any line in the file. Edit groups may be nested. @c ..................................................... @c SUBSECTION @c ..................................................... @node BeginGroupIfMatch, BeginGroupIfNoLineContaining, BeginGroupIfLineMatching, editfiles @subsection BeginGroupIfMatch @smallexample BeginGroupIfMatch @var{quoted-regex} @end smallexample The lines following, up to the first @code{EndGroup} are executed if the quoted regular expression matches the current line. Edit groups may be nested. @c ..................................................... @c SUBSECTION @c ..................................................... @node BeginGroupIfNoLineContaining, BeginGroupIfNoLineMatching, BeginGroupIfMatch, editfiles @subsection BeginGroupIfNoLineContaining @smallexample BeginGroupIfNoLineContaining @var{quoted-string} @end smallexample The lines following, up to the first @code{EndGroup} are executed if the quoted string does not appear in any line in the file. Edit groups may be nested. @c ..................................................... @c SUBSECTION @c ..................................................... @node BeginGroupIfNoLineMatching, BeginGroupIfNoMatch, BeginGroupIfNoLineContaining, editfiles @subsection BeginGroupIfNoLineMatching @smallexample BeginGroupIfNoLineMatching @var{quoted-regex} @end smallexample The lines following, up to the first @code{EndGroup} are executed if the quoted regular expression does not match any line in the file. Edit groups may be nested. @c ..................................................... @c SUBSECTION @c ..................................................... @node BeginGroupIfNoMatch, BeginGroupIfNoSuchLine, BeginGroupIfNoLineMatching, editfiles @subsection BeginGroupIfNoMatch @smallexample BeginGroupIfNoMatch @var{quoted-regex} @end smallexample The lines following, up to the first @code{EndGroup} are executed if the quoted regular expression does not match the current line. Edit groups may be nested. @c ..................................................... @c SUBSECTION @c ..................................................... @node BeginGroupIfNoSuchLine, BreakIfLineMatches, BeginGroupIfNoMatch, editfiles @subsection BeginGroupIfNoSuchLine @smallexample BeginGroupIfNoSuchLine @var{quoted-string} @end smallexample The lines following, up to the first @code{EndGroup} are executed if the quoted literal string does not match any line in the file. Edit groups may be nested. @c ..................................................... @c SUBSECTION @c ..................................................... @node BreakIfLineMatches, CatchAbort, BeginGroupIfNoSuchLine, editfiles @subsection BreakIfLineMatches @smallexample BreakIfLineMatches @var{quoted-regex} @end smallexample Terminates further editing of the current file if the current line matches the quoted regular expression. @c ..................................................... @c SUBSECTION @c ..................................................... @node CatchAbort, CommentLinesMatching, BreakIfLineMatches, editfiles @subsection CatchAbort @cindex CatchAbort Edit actions which abort on failure (such as @code{LocateLineMatching}) will jump to the first instance of this marker instead of completely aborting an edit if this keyword occurs in an editing script. You can catch the exceptions thrown by the following commands: @code{CommentNLines},@code{CommentToLineMatching},@code{DeleteNLines},@code{DeleteToLineMatching}, @code{HashCommentToLineMatching},@code{IncrementPointer}, @code{LocateLineMatching},@code{PercentCommentToLineMatching}, @code{RunScriptIf(No)LineMatching},@code{UnCommentNLines}. @c ..................................................... @c SUBSECTION @c ..................................................... @node CommentLinesMatching, CommentLinesStarting, CatchAbort, editfiles @subsection CommentLinesMatching @smallexample CommentLinesMatching @var{quoted-regex} @end smallexample Use the current value of the comment delimiters set using @code{SetCommentStart} and @code{SetCommentEnd} to comment out lines matching the given regular expression in quotes. @c ..................................................... @c SUBSECTION @c ..................................................... @node CommentLinesStarting, CommentNLines, CommentLinesMatching, editfiles @subsection CommentLinesStarting @smallexample CommentLinesStarting @var{quoted-string} @end smallexample Use the current value of the comment delimiters set using @code{SetCommentStart} and @code{SetCommentEnd} to comment out lines starting with the quoted literal string. @c ..................................................... @c SUBSECTION @c ..................................................... @node CommentNLines, CommentToLineMatching, CommentLinesStarting, editfiles @subsection CommentNLines @smallexample CommentNLines @var{quoted-string} @end smallexample Comments up to @math{N} lines from the current file, starting from the location of the current line pointer. If the end of the file is reached and less than @math{N} lines are deleted, a warning is issued, but editing continues. The current value of the comment delimiters is used to determine the method of commenting, (see @code{SetCommentStart}). After the operation the pointer points to the line after the commented lines. @c ..................................................... @c SUBSECTION @c ..................................................... @node CommentToLineMatching, DefineClasses, CommentNLines, editfiles @subsection CommentToLineMatching @smallexample CommentToLineMatching @var{quoted-regex} @end smallexample Use the current value of the comment delimiters set using @code{SetCommentStart} and @code{SetCommentEnd} to comment out lines from the current position in a file to a line matching the given regular expression in quotes. @c ..................................................... @c SUBSECTION @c ..................................................... @node DefineClasses, DefineInGroup, CommentToLineMatching, editfiles @subsection DefineClasses @smallexample DefineClasses "@var{class1}:@var{class2}:..." @end smallexample Activate the following colon, comma or dot-separated list of classes if and only if the file is edited. @c ..................................................... @c SUBSECTION @c ..................................................... @node DefineInGroup, DeleteLinesAfterThisMatching, DefineClasses, editfiles @subsection DefineInGroup @smallexample DefineInGroup "@var{class1}:@var{class2}:..." @end smallexample Activate the following colon, comma or dot-separated list of classes if the edit group is entered. This can be combined with other classes to identify what particular edits took place. Use DefineInGroup if you want to define a class or list of classes conditional on entry to a BeginGroup ... EngGroup block. For example, @smallexample editfiles: @{ /etc/inetd.conf BeginGroupIfNoSuchLine "$(myservice1)" Append "$(myservice1)" DefineInGroup "myservice1_added" EndGroup BeginGroupIfNoSuchLine "$(myservice2)" Append "$(myservice2)" DefineInGroup "myservice2_added" EndGroup @} @end smallexample @noindent This will define service_added and service_added_another_way if either line is added, but additionally myservice1_added if myservice1 was added and likewise for myservice2_added. Activate the following colon, comma or dot-separated list of classes if execution reaches the @code{BeginGroup} ... @code{EndGroup} section(s) containing this command. If you think you want to put DefineClasses within a @code{BeginGroup} ... @code{EndGroup} section, you actually want this. @c ..................................................... @c SUBSECTION @c ..................................................... @node DeleteLinesAfterThisMatching, DeleteLinesContaining, DefineInGroup, editfiles @subsection DeleteLinesAfterThisMatching @smallexample DeleteLinesAfterThisMatching @var{quoted-regex} @end smallexample Delete lines after the current position which match the quoted expression. @c ..................................................... @c SUBSECTION @c ..................................................... @node DeleteLinesContaining, DeleteLinesMatching, DeleteLinesAfterThisMatching, editfiles @subsection DeleteLinesContaining/DeleteLinesNotContaining @smallexample DeleteLinesContaining @var{quoted-string} DeleteLinesNotContaining @var{quoted-string} @end smallexample Delete all lines (not) containing the exact string quoted. @c ..................................................... @c SUBSECTION @c ..................................................... @node DeleteLinesMatching, DeleteLinesStarting, DeleteLinesContaining, editfiles @subsection DeleteLinesMatching/DeleteLinesNotMatching @smallexample DeleteLinesMatching @var{quoted-regex} DeleteLinesNotMatching @var{quoted-regex} @end smallexample Delete all lines (not) fully matching the tied quoted regular expression. @c ..................................................... @c SUBSECTION @c ..................................................... @node DeleteLinesStarting, DeleteLinesNotContaining, DeleteLinesMatching, editfiles @subsection DeleteLinesStarting/DeleteLinesNotStarting @smallexample DeleteLinesStarting @var{quoted-string} DeleteLinesNotStarting @var{quoted-string} @end smallexample Delete all lines (not) beginning with the exact string quoted. @c ..................................................... @c SUBSECTION @c ..................................................... @node DeleteLinesNotContaining, DeleteLinesNotMatchingFileItems, DeleteLinesStarting, editfiles @subsection DeleteLinesNotContainingFileItems @smallexample DeleteLinesNotContainingFileItems @var{filename} @end smallexample Delete lines in the file that do not contain the any of the substrings in the file. @c ..................................................... @c SUBSECTION @c ..................................................... @node DeleteLinesNotMatchingFileItems, DeleteLinesNotStartingFileItems, DeleteLinesNotContaining, editfiles @subsection DeleteLinesNotMatchingFileItems @smallexample DeleteLinesNotMatchingFileItems @var{filename} @end smallexample Delete lines in the file that do not match the any of the regular expressions in the file. @c ..................................................... @c SUBSECTION @c ..................................................... @node DeleteLinesNotStartingFileItems, DeleteNLines, DeleteLinesNotMatchingFileItems, editfiles @subsection DeleteLinesNotStartingFileItems @smallexample DeleteLinesNotStartingFileItems @var{filename} @end smallexample Delete lines in the file that do not start with any of the substrings in the file. @c ..................................................... @c SUBSECTION @c ..................................................... @node DeleteNLines, DeleteToLineMatching, DeleteLinesNotStartingFileItems, editfiles @subsection DeleteNLines @smallexample DeleteNLines @var{quoted-string} @end smallexample Deletes up to @math{N} lines from the current file, starting from the location of the current line pointer. If the end of the file is reached and less than @math{N} lines are deleted, a warning is issued, but editing continues. @c ..................................................... @c SUBSECTION @c ..................................................... @node DeleteToLineMatching, EditMode (binary), DeleteNLines, editfiles @subsection DeleteToLineMatching @smallexample DeleteToLineMatching @var{quoted-regex} @end smallexample Delete lines from the current position, up to but not including a line matching the regular expression in the quoted string. If no line matches the given expression, a warning is only printed in verbose mode, but all edits are immediately abandoned. @c ..................................................... @c SUBSECTION @c ..................................................... @node EditMode (binary), EditSplit, DeleteToLineMatching, editfiles @subsection EditMode and binary editing If set to binary, the file will be edited as if it were a non-ASCII file. See discussion below. @smallexample EditMode "Binary" @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node EditSplit, EmptyEntireFilePlease, EditMode (binary), editfiles @subsection EditSplit Editfiles treats lists as private interpretations, since iteration over lists could lead to unpredictable behaviour if text variables accidentally contain the list separator. The control option @code{Split} therefore has no effect on editfiles. This definition makes list expansion work in editfiles. @smallexample EditSplit "," @end smallexample @vindex EditSplit @vindex Split @cindex Split in editfiles @cindex Iteration over lists (editfiles) Be careful not to confuse this with the @code{SplitOn} character. @smallexample editfiles: @{ /tmp/bla1 EditSplit "!" AppendIfNoSuchLine "alpha1!beta1" EditSplit ":" AppendIfNoSuchLine "alpha2!beta2" EditSplit "@@" AppendIfNoSuchLine "alpha3@@beta3" @} @{ /tmp/bla2 AppendIfNoSuchLine "new1@@new2" @} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node EmptyEntireFilePlease, ElseDefineClasses, EditSplit, editfiles @subsection EmptyEntireFilePlease Deletes all lines from the current file. @c ..................................................... @c SUBSECTION @c ..................................................... @node ElseDefineClasses, EndGroup, EmptyEntireFilePlease, editfiles @subsection ElseDefineClasses See @code{DefineClasses} @c ..................................................... @c SUBSECTION @c ..................................................... @node EndGroup, EndLoop, ElseDefineClasses, editfiles @subsection EndGroup Terminates a begin-end conditional structure. @c ..................................................... @c SUBSECTION @c ..................................................... @node EndLoop, ExpandVariables, EndGroup, editfiles @subsection EndLoop Terminates a loop. See @code{ForEachLineIn} @c ..................................................... @c SUBSECTION @c ..................................................... @node ExpandVariables, ExpireAfter editfiles, EndLoop, editfiles @subsection ExpandVariables This causes cfengine to run through the contents of the file and expand any recognisable editfile strings in the file, if they are defined within the scope of the cfagent script. This gives cfengine an m4 like capacity. @cindex ExpandVariables @cindex Templates @cindex m4 functionality @c ..................................................... @c SUBSECTION @c ..................................................... @node ExpireAfter editfiles, Filter, ExpandVariables, editfiles @subsection ExpireAfter editfiles @smallexample ExpireAfter @var{mins} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node Filter, FixEndOfLine, ExpireAfter editfiles, editfiles @subsection Filter Name a fiter for pruning file searches. @smallexample Filter @var{filteralias} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node FixEndOfLine, ForEachLineIn, Filter, editfiles @subsection FixEndOfLine The quoted string which follows may be either @samp{dos} or @samp{Unix} to fix the end of line character conventions to match these systems. This command should be executed last of all, since cfengine appends new lines with the conventions of the system on which is was complied during edit operations. @c ..................................................... @c SUBSECTION @c ..................................................... @node ForEachLineIn, GotoLastLine, FixEndOfLine, editfiles @subsection ForEachLineIn @var{quoted-filename} @smallexample ForEachLineIn @var{quoted-filename} @end smallexample This marks the beginning of a for-loop which reads successive lines from a named file. The result is like using @code{SetLine} for each line in the file. Nested loops are not permitted. @c ..................................................... @c SUBSECTION @c ..................................................... @node GotoLastLine, HashCommentLinesContaining, ForEachLineIn, editfiles @subsection GotoLastLine Moves the file pointer to the last line in the current file. @c ..................................................... @c SUBSECTION @c ..................................................... @node HashCommentLinesContaining, HashCommentLinesMatching, GotoLastLine, editfiles @subsection HashCommentLinesContaining Add a @samp{#} to the start of any line containing the quoted string. @smallexample HashCommentLinesContaining @var{quoted-string} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node HashCommentLinesMatching, HashCommentLinesStarting, HashCommentLinesContaining, editfiles @subsection HashCommentLinesMatching Add a @samp{#} to the start of any line exactly matching the quoted regular expression. @smallexample HashCommentLinesMatching @var{quoted-regex} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node HashCommentLinesStarting, IfElapsed (editing), HashCommentLinesMatching, editfiles @subsection HashCommentLinesStarting Add a @samp{#} to the start of any line starting with the quoted string. @smallexample HashCommentLinesStarting @var{quoted-string} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node IfElapsed (editing), IncrementPointer, HashCommentLinesStarting, editfiles @subsection IfElapsed @smallexample ExpireAfter @var{mins} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node IncrementPointer, Inform (editing), IfElapsed (editing), editfiles @subsection IncrementPointer @var{quoted-number} @smallexample IncrementPointer @var{quoted-number} @end smallexample Increments the value (in lines) of the file pointer by the number of lines specified in the quoted string (as a denary number). e.g. @samp{``4''}. Negative values are equivalent to decrementing the pointer. If a request is made to increment/decrement outside of the file boundaries the pointer `bumps' into the boundary and remains there, i.e. either at start of file or end of file. @cindex Incrementing line pointer in editfiles @cindex Decrementing line pointer in editfiles @c ..................................................... @c SUBSECTION @c ..................................................... @node Inform (editing), InsertFile, IncrementPointer, editfiles @subsection Inform editfiles @smallexample Inform @var{quoted-string} @end smallexample Set to @code{true} or @code{false}, @code{on} or @code{off} to set the inform level for this file. Default is @code{off}. Note that, owing to the way that cfengine re-uses code, this feature does not work very well. Detailed messages are not available, only a summary of whether or not the file changed. @c ..................................................... @c SUBSECTION @c ..................................................... @node InsertFile, InsertLine, Inform (editing), editfiles @subsection InsertFile @smallexample InsertFile @var{quoted-string} @end smallexample Inserts the named file after the current line position in the file. This should be used in conjunction with a begin-end construction in order to avoid including the file every time cfengine is run. If the file does not exist, or cannot be opened, there is only a warning issued in verbose mode. Note if the file is empty, or if the current line pointer is not set, the file is inserted at the start of the file. @c ..................................................... @c SUBSECTION @c ..................................................... @node InsertLine, LocateLineMatching, InsertFile, editfiles @subsection InsertLine @smallexample InsertFile @var{quoted-string} @end smallexample Inserts the quoted string as a line after the current line pointer in the file. After the insert, the line pointer is incremented by one so that subsequent inserted lines are placed after the first. This should probably be used in conjunction with the conditional begin-end tests to avoid lines being inserted on every run. @c ..................................................... @c SUBSECTION @c ..................................................... @node LocateLineMatching, PercentCommentLinesContaining, InsertLine, editfiles @subsection LocateLineMatching @smallexample LocateLineMatching @var{quoted-regex} @end smallexample Moves the current line pointer to the line matching the quoted regular expression. If there is no match, a warning is only issued in verbose mode, but all editing is immediately aborted. See also @code{WarnIfNoLineMatching} so that you can get an explicit warning, even out of verbose mode. @c ..................................................... @c SUBSECTION @c ..................................................... @node PercentCommentLinesContaining, PercentCommentLinesMatching, LocateLineMatching, editfiles @subsection PercentCommentLinesContaining @smallexample PercentCommentLinesContaining @var{quoted-string} @end smallexample Add a @samp{%} to the start of any line containing the quoted string. @c ..................................................... @c SUBSECTION @c ..................................................... @node PercentCommentLinesMatching, PercentCommentLinesStarting, PercentCommentLinesContaining, editfiles @subsection PercentCommentLinesMatching @smallexample PercentCommentLinesMatching @var{quoted-regex} @end smallexample Add a @samp{%} to the start of any line exactly matching the quoted regular. @c ..................................................... @c SUBSECTION @c ..................................................... @node PercentCommentLinesStarting, Prepend (editing), PercentCommentLinesMatching, editfiles @subsection PercentCommentLinesStarting @smallexample PercentCommentLinesStarting @var{quoted-string} @end smallexample Add a @samp{%} to the start of any line starting with the quoted string. @c ..................................................... @c SUBSECTION @c ..................................................... @node Prepend (editing), PrependIfNoLineMatching, PercentCommentLinesStarting, editfiles @subsection Prepend @smallexample Prepend @var{quoted-string} @end smallexample Add a line containing the quoted string to the start of the file. This should be used in conjunction with the decision structures @code{BeginGroupIfNoLineMatching} and @code{BreakIfLineMatches}. @c ..................................................... @c SUBSECTION @c ..................................................... @node PrependIfNoLineMatching, PrependIfNoSuchLine, Prepend (editing), editfiles @subsection PrependIfNoLineMatching @smallexample PrependIfNoLineMatching @var{quoted-regex} @end smallexample A new version of the older @code{PrependIfNoSuchLine} with uses a regular expression instead of a literal string. The string prepended is the one set using @code{SetLine}. @c ..................................................... @c SUBSECTION @c ..................................................... @node PrependIfNoSuchLine, Recurse (editing), PrependIfNoLineMatching, editfiles @subsection PrependIfNoSuchLine @smallexample PrependIfNoSuchLine @var{quoted-string} @end smallexample Add a line containing the quoted string to the start of the file if the file doesn't contain the exact line already. @c ..................................................... @c SUBSECTION @c ..................................................... @node Recurse (editing), ReplaceLineWith, PrependIfNoSuchLine, editfiles @subsection Recurse @smallexample Recurse @var{digit/inf} @end smallexample For recursive descents when editing whole file trees. @c ..................................................... @c SUBSECTION @c ..................................................... @node ReplaceLineWith, ReplaceAll With, Recurse (editing), editfiles @subsection ReplaceLineWith @smallexample ReplaceLineWith @var{quoted-string} @end smallexample Replace the line at the current position with the text in the quoted string. The file pointer remains pointing to this line after the change. @c ..................................................... @c SUBSECTION @c ..................................................... @node ReplaceAll With, ReplaceFirst, ReplaceLineWith, editfiles @subsection ReplaceAll/With @smallexample ReplaceAll @var{quoted-regex} With @var{quoted-string} @end smallexample Replace all instances of strings matching the regular expression in the first quotes with the exact string in the second set of quotes, throughout the current file. Note that cfengine matches on a left to right basis, with the first match taking precedence, so if your regular expression matches text ambiguously it is the first occurrence which is replaced. For example, if you replace @samp{cf.*} with @samp{CFENGINE} and cfengine encounters a line @samp{hello cfengine cfengine}, then this will be replaced with @samp{hello CFENGINE} even though two possible strings match the regular expression. On the other hand if the expression is not ambiguous, say replacing @samp{cfengine} with @samp{CFENGINE}, then the result would be @samp{hello CFENGINE CFENGINE}. @c ..................................................... @c SUBSECTION @c ..................................................... @node ReplaceFirst, ReplaceLinesMatchingField, ReplaceAll With, editfiles @subsection ReplaceFirst/With @smallexample ReplaceFirst @var{quoted-regex} With @var{quoted-string} @end smallexample For each line of the current file, replace the first string matching the regular expression in the first quotes (@var{quoted-regex}) with the string given in the second set of quotes (@var{quoted-string}). Matching is done left to right. For example, if you replace @samp{``YY = [[:digit:]][[:digit:]]''} with @samp{``YY = 04''} and cfengine encounters @samp{``YY = 03 but old YY = 70''} then it will be replaced with @samp{``YY = 04 but old YY = 70''} @c ..................................................... @c SUBSECTION @c ..................................................... @node ReplaceLinesMatchingField, Repository, ReplaceFirst, editfiles @subsection ReplaceLinesMatchingField @smallexample ReplaceLinesMatchingField @var{quoted-number} @end smallexample This command replaces any lines in the current file with the current line set by @code{SetLine} or @code{ForEachLineIn}, if the lines are split into fields (e.g. the password file) separated by the @code{SplitOn} character (':' by default), and the corresponding fields match. The idea behind this command was to be able to override global passwords (from a file which gets distributed) by new passwords in a local file. Rather than maintaining the files separately, this simply overrides the entries with the new ones. @c ..................................................... @c SUBSECTION @c ..................................................... @node Repository, ResetSearch, ReplaceLinesMatchingField, editfiles @subsection Repository editfiles @smallexample Repository @var{quoted string} @end smallexample This allows a local override of the @code{Repository} variable, on an item by item basis. If set to ``off'' or ``none'' it cancels the value of a global repository. See @ref{copybackup}. See @ref{Backup in editfiles}. @c ..................................................... @c SUBSECTION @c ..................................................... @node ResetSearch, RunScript, Repository, editfiles @subsection ResetSearch @smallexample ResetSearch @var{quoted-string} @end smallexample Sets the current-position pointer to the line number in the quoted string. @samp{EOF} indicates the end of the file. @c ..................................................... @c SUBSECTION @c ..................................................... @node RunScript, RunScriptIfLineMatching, ResetSearch, editfiles @subsection RunScript @smallexample RunScript @var{quoted-string} @end smallexample Executes the named script command. Before executing the script any edits are saved to disk. After the script has executed, cfengine reloads the file for any further editing operations. The script (which may be any executable program) is appended with two arguments: the name of the file which is being edited and the system hard class (e.g. sun4, ultrix etc.) of the system executing the script. CAUTION: cfengine knows nothing about the success or failure of anything that is done during the execution of user scripts. This feature is to be used at the users own peril! @c ..................................................... @c SUBSECTION @c ..................................................... @node RunScriptIfLineMatching, RunScriptIfNoLineMatching, RunScript, editfiles @subsection RunScriptIfLineMatching @smallexample RunScriptIfLineMatching @var{quoted-string} @end smallexample Executes the script named with the @code{SetScript} command only if the current file contains a line matching the quoted regular expression. CAUTION: cfengine knows nothing about the success or failure of anything that is done during the execution of user scripts. This feature is to be used at the users own peril! @c ..................................................... @c SUBSECTION @c ..................................................... @node RunScriptIfNoLineMatching, SetCommentStart, RunScriptIfLineMatching, editfiles @subsection RunScriptIfNoLineMatching @smallexample RunScriptIfNoLineMatching @var{quoted-regex} @end smallexample Executes the script named with the @code{SetScript} command if the current file contains no line matching the quoted regular expression. CAUTION: cfengine knows nothing about the success or failure of anything that is done during the execution of user scripts. This feature is to be used at the users own peril! @c ..................................................... @c SUBSECTION @c ..................................................... @node SetCommentStart, SetCommentEnd, RunScriptIfNoLineMatching, editfiles @subsection SetCommentStart @smallexample SetCommentStart @var{quoted-string} @end smallexample Specify which string should be used for starting a comment using the commands @code{CommentLineMatching} and @code{CommentLineStarting}. The default is the hash symbol @samp{#} followed by a single space. @c ..................................................... @c SUBSECTION @c ..................................................... @node SetCommentEnd, SetLine, SetCommentStart, editfiles @subsection SetCommentEnd @smallexample SetCommentEnd @var{quoted-string} @end smallexample Specify which string should be used for ending a comment using the commands @code{CommentLineMatching} and @code{CommentLineStarting}. The default is the empty string. For example, you could make C style comments by setting CommentStart to @samp{/*} and comment end to @samp{*/}. @c ..................................................... @c SUBSECTION @c ..................................................... @node SetLine, SetScript, SetCommentEnd, editfiles @subsection SetLine @smallexample SetLine @var{quoted-string} @end smallexample Sets a current line value which can be appended using @code{AppendIfNoLineMatching} using a regular expression. @c ..................................................... @c SUBSECTION @c ..................................................... @node SetScript, SlashCommentLinesContaining, SetLine, editfiles @subsection SetScript @smallexample SetScript @var{quoted-string} @end smallexample Sets the name of a user-supplied script for editing the current file. @c ..................................................... @c SUBSECTION @c ..................................................... @node SlashCommentLinesContaining, SlashCommentLinesMatching, SetScript, editfiles @subsection SlashCommentLinesContaining @smallexample SlashCommentLinesContaining @var{quoted-string} @end smallexample Add a @samp{//} to the start of any line containing the quoted string. @c ..................................................... @c SUBSECTION @c ..................................................... @node SlashCommentLinesMatching, SlashCommentLinesStarting, SlashCommentLinesContaining, editfiles @subsection SlashCommentLinesMatching @smallexample SlashCommentLinesMatching @var{quoted-regex} @end smallexample Add a @samp{//} to the start of any line exactly matching the quoted regular expression. @c ..................................................... @c SUBSECTION @c ..................................................... @node SlashCommentLinesStarting, SplitOn, SlashCommentLinesMatching, editfiles @subsection SlashCommentLinesStarting @smallexample SlashCommentLinesStarting @var{quoted-string} @end smallexample Add a @samp{//} to the start of any line starting with the quoted string. @c ..................................................... @c SUBSECTION @c ..................................................... @node SplitOn, SysLog, SlashCommentLinesStarting, editfiles @subsection SplitOn @smallexample SplitOn @var{quoted-string} @end smallexample This defines a single character which is to be interpreted as a field separator for editing files with columns. The default value for this is @samp{:}, as is used in the password and group files. It is used in conjunction with @code{ReplaceLinesMatchingField}. Note, be careful not to confuse this with the @code{EditSplit} character. @cindex SplitOn @cindex Password file, editing @cindex Group field, editing @cindex Field separator in editfiles @c ..................................................... @c SUBSECTION @c ..................................................... @node SysLog, Umask, SplitOn, editfiles @subsection Syslog editfiles Set to true or false, on or off to set inform level for this file. Default is off. @smallexample Syslog @var{quoted-string} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node Umask, UnCommentLinesContaining, SysLog, editfiles @subsection Umask @smallexample @var{quote mode} @end smallexample Set local umask for file creation and script execution. @cindex umask @c ..................................................... @c SUBSECTION @c ..................................................... @node UnCommentLinesContaining, UnCommentLinesMatching, Umask, editfiles @subsection UnCommentLinesContaining @smallexample UnCommentLinesContaining @var{quoted-string} @end smallexample Uncomment all lines in file containing the quoted string as a substring. The comment delimiters are assumed to be those set using SetCommentStart and SetCommentEnd. @c ..................................................... @c SUBSECTION @c ..................................................... @node UnCommentLinesMatching, UnCommentsNLines, UnCommentLinesContaining, editfiles @subsection UnCommentLinesMatching @smallexample UnCommentLinesMatching @var{quoted-regex} @end smallexample Uncomment all lines in file matching the quoted regular expression. The comment delimiters are assumed to be those set using SetCommentStart and SetCommentEnd. @c ..................................................... @c SUBSECTION @c ..................................................... @node UnCommentsNLines, UnCommentToLineMatching, UnCommentLinesMatching, editfiles @subsection UnCommentNLines @smallexample UnCommentNLines @var{quoted-string} @end smallexample Uncomments N lines starting from the current position, using the currently defined method for commenting. Note that the comment start and end symbols are removed independently, i.e. they are not matched, so that a comment may be spread over several lines. e.g. If using C style @samp{/*} and @samp{*/} comments, the command @code{UnCommentNLines "3"} would uncomment @smallexample /* 1 */ /* 2 */ /* 3 */ @end smallexample @noindent and also @smallexample /* 1 2 3 */ @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node UnCommentToLineMatching, UnsetAbort, UnCommentsNLines, editfiles @subsection UnCommentToLineMatching @smallexample UnCommentToLineMatching @var{quoted-string} @end smallexample Uncomments from the current position up to and including the first line matching the named regular expression. @c ..................................................... @c SUBSECTION @c ..................................................... @node UnsetAbort, UseShell, UnCommentToLineMatching, editfiles @subsection UnsetAbort Switches off the feature @code{AbortAtLineMatching}. @smallexample UnsetAbort @var{quoted-string} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node UseShell, WarnIfFileMissing, UnsetAbort, editfiles @subsection UseShell Normally cfengine uses a shell based exec function to run scripts during editing. This involves the inheritance of environment variables and path, which carries with it an inherent security risk. Setting this value to false causes execution to execute without an encapsulating shell. @c ..................................................... @c SUBSECTION @c ..................................................... @node WarnIfFileMissing, WarnIfLineContaining, UseShell, editfiles @subsection WarnIfFileMissing If the file to be edited does not exist, a visible alert is issued. @smallexample WarnIfFileMissing @var{quoted-string} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node WarnIfLineContaining, WarnIfLineMatching, WarnIfFileMissing, editfiles @subsection WarnIfLineContaining Issue a warning if the quoted string is found as a substring of one or more lines in the file. @smallexample WarnIfLineContaining @var{quoted-string} @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node WarnIfLineMatching, WarnIfLineStarting, WarnIfLineContaining, editfiles @subsection WarnIfLineMatching @smallexample WarnIfLineMatching @var{quoted-regex} @end smallexample Issue a warning if the quoted regular expression matches one or more lines in the file. @c ..................................................... @c SUBSECTION @c ..................................................... @node WarnIfLineStarting, WarnIfNoLineContaining, WarnIfLineMatching, editfiles @subsection WarnIfLineStarting @smallexample WarnIfLineStarting @var{quoted-string} @end smallexample Issue a warning if the quoted string matches the start of one or more lines in the file. @c ..................................................... @c SUBSECTION @c ..................................................... @node WarnIfNoLineContaining, WarnIfNoLineMatching, WarnIfLineStarting, editfiles @subsection WarnIfNoLineContaining @smallexample WarnIfNoLineContaining @var{quoted-string} @end smallexample Issue a warning if the quoted string is not contained in one or more lines in the file. @c ..................................................... @c SUBSECTION @c ..................................................... @node WarnIfNoLineMatching, WarnIfNoLineStarting, WarnIfNoLineContaining, editfiles @subsection WarnIfNoLineMatching @smallexample WarnIfNoLineMatching @var{reg-ex} @end smallexample Issue a warning if the quoted regular expression does not match one or more lines in the file. @c ..................................................... @c SUBSECTION @c ..................................................... @node WarnIfNoLineStarting, WarnIfNoSuchLine, WarnIfNoLineMatching, editfiles @subsection WarnIfNoLineStarting @smallexample WarnIfNoLineStarting @var{quoted-string} @end smallexample Issue a warning if the quoted string is not found at the start of one or more lines in the file. @c ..................................................... @c SUBSECTION @c ..................................................... @node WarnIfNoSuchLine, , WarnIfNoLineStarting, editfiles @subsection WarnIfNoSuchLine @smallexample WarnIfNoSuchLine @var{quoted-regex} @end smallexample Issue a warning if the quoted regular expression does not match one or more lines in the file. @c %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @c SECTION @c %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @node Editfiles on Binary Files, files, editfiles, Cfagent reference @section Editfiles on Binary Files @noindent A limited number of operations can also be performed on purely binary files, e.g. compiled programs, in order to search for strings or viral code, or to modify strings within a program. Binary mode is a mutually exclusive, separate mode to normal editing. The limit on the size of binary files is set by @code{editbinaryfilesize} in @code{control}. @itemize @bullet @item ReplaceAll @var{regex} With @var{literal} Replaces occurrences of the matched regular expression with\ the provided literal text, only if the length of the literal substitute is less than or equal to the length of the located string. If the replacement string is shorter, it is padded with ascii spaces (character 32) by default. The padding character can be changed by setting @code{BinaryPaddingChar} in @code{control}. Padding with a null byte would lead to corruption of text within a program. @item WarnIfContainsString @var{regex/literal} Yields a warning if the literal string or regular expression matches. Cfengine first attempts a literal match and then a regular expression match. @item WarnIfContainsFile @var{filename} Yields a warning if the contents of the named file exactly match part of the file which is being edited. This can be used to search for binary data which cannot be typed directly into the cfengine program, e.g. virus signatures. @end itemize @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node files, filters, Editfiles on Binary Files, Cfagent reference @section files @cindex File management @cindex Files, checking permissions @cindex Files, setting owner @vindex files The @code{files} facility allows you to touch (create), check for the existence, owner and permissions of files, change the permissions and test for setuid root programs. @c ..................................................... @c SUBSECTION @c ..................................................... @menu * Syntax:: * Recursion:: * Directory permissions:: * Checksums and change management:: * home directive:: * Owner and group wildcards:: * Files linkchildren:: * touch:: * create:: @end menu @node Syntax, Recursion, files, files @subsection Syntax @cindex Files, syntax A files-statement can have several options. We can begin by examining the form of the statement in pseudo-code: @cartouche @w{} @smallexample files: @var{classes}:: /@var{file-object} mode=@var{mode} owner=@var{uid-list} group=@var{gid-list} action=@var{fixall/other-options}/@b{warnall} links=@b{false/stop}@var{/traverse/follow/tidy} rxdirs=@b{true/on}/@var{false/off} ignore=@var{pattern} include=@var{pattern} exclude=@var{pattern} filter=@var{filter alias} xdev=@var{true/on}/@b{false/off} define=@var{classlist} elsedefine=@var{classlist} checksum=@var{md5/sha/best} syslog=@var{true/on}/@b{false/off} inform=@var{true/on}/@b{false/off} audit=@var{true/on}/@var{false/off} ifelapsed=@var{mins} expireafter=@var{mins} @var{Special OS flags:} flags=@var{BSD flags} @end smallexample @end cartouche @noindent An example would be the following: @smallexample any:: /var/spool/printQ mode=0775 r=0 o=daemon g=daemon act=fixdirs @end smallexample @noindent The meaning of these item is sketched out below and becomes clearer on looking at a number of examples. Note that, each of the options below can be written in either upper or lower case and abbreviated by any unique abbreviation. @vindex m= @vindex mode @vindex l= @vindex link @vindex recurse @vindex r= @vindex a= @vindex action @vindex o= @vindex owner @vindex g= @vindex group @vindex rxdirs @table @code @item @var{/file-object} This is the only obligatory part of a file action. This may be a single file or a directory. If it is a directory then it indicates where does the file search should begin. The recursion specifier may be used to force cfengine to descend into subdirectories in a controlled fashion, starting from this point, checking files there also. The wildcard @code{home} may also be used. @xref{home directive}. A file object is interpreted as a directory if you write it in the following form: @file{/directory-path/.}. i.e. a trailing dot signifies a directory. This then becomes the same as the @code{directory} command. @cindex home wildcard @cindex Wildcard home @vindex home @item mode=@var{modestring} Specifies what the allowed permissions for files are. If cfengine finds that a file's mode is incorrect, the value of the @code{action} option determines what will be done about it. The modestring should consist of either a three digit octal numbers with @samp{+}, @samp{-} or @samp{=} symbols, or a text string like that used by the command @code{chmod}. For instance: @code{mode=u=rwx,og+rx} would mean set the read/write and execute flags for the user (file owner) and add the read/execute flags for others and group bits. An example of the numerical form might be @code{-002} which would mean that the read-for-others flag should either not be set or should be unset, depending on the action you choose. @code{+2000} would mean that the setgid flag should be present or set, depending on the action. @code{+2000,-002} would be a combination of these. The @samp{=} sign sets to an absolute value, so @code{=755} would set the file mode to mode 755. @item flags=@var{BSD flags} The free BSD Unices have additional filesystem flags which can be seton files. Refer to the BSD @code{chflags} documentation for this. For example, @smallexample /tmp/flags.01 mode=0600 owner=0 group=0 flags=uappnd,uchg,uunlnk,nodump,opaque,sappnd,schg,sunlnk action=touch @end smallexample @item recurse=@var{number/inf} This specifier tells cfengine whether or not to recurse into subdirectories. If the value is zero, only the named file or directory is affected. If the value is 1, it will open at most one level of subdirectory and affect the files within this scope. If the value is @code{inf} then cfengine opens all subdirectories and files beginning from the specified filename.@xref{Recursion}. @item owner=@var{owner list} This is a list of allowed owners, or uids by number, separated by commas. For example @code{root,2,3,sysadm}. In cases where you ask cfengine to fix the ownership automatically, the owner will be set to the first recogized owner in the list if and only if it is not one of the named uids in the list. @item group=@var{group list} This is a list of allowed groups, or gids by number, separated by commas. For example @code{wheel,2,3,sysadm}. In cases where you ask cfengine to fix the ownership automatically, the group will be set to the first recognized group in the list if and only if it is not one of the named gids in the list. @item action=@var{action} The action is one of the following keywords. @smallexample warnall warndirs warnplain fixall fixdirs fixplain touch linkchildren create compress alert @end smallexample @noindent The upper line results only in warnings being issued. The actions beginning `fix' prompt cfengine to fix encountered problems without bothering the user. No message is issued unless in verbose mode. The special features on the third line will be explained separately. Alert is like @code{-print} in the find command, it triggers on the existence of files which have not been ignored, excluded or filtered. This should normally be used together @code{filter}, in order to locate files of particular types. @item include=@var{wildcard/pattern} You can include this option several times to specify specific patterns which are to be included in the search. Once you specify one pattern you exclude all files not matching at least one of the patterns. The case be useful for restricting a search, or for modifying the permissions of only certain files. @cindex Search patterns in @code{files} @vindex include= @cindex Pattern matching in file sweeps @item exclude=@var{wildcard/pattern} You can include this option several times to specify specific patterns which are to be excluded from the search. This overrides any patterns given in the @code{include=} list. @vindex exclude= @cindex Excluding files from a file sweep @item ignore This works like the global ignore directive but here you may provide a private list of ignorable directories and files. Unlike include, exclude this affects the way cfengine parses directory trees. @item links=@var{stop/traverse/tidy} Normally cfengine does not descend into subdirectories which are pointed to by symbolic links. If you wish to force it to do so (without using the @code{-l} command line option) you may give this option the value @code{true}, or @code{traverse}, or @code{follow}. To specify no recursion you set the value @code{false} or @code{stop}. @cindex Links, traversing in searches @vindex -l @cindex -l option Note that the value set here in the cfengine program @emph{always overrides} the value set by the @code{-l} command line option, so you can protect certain actions from this command line option by specifying a negative value here. If you specify no value here, the behaviour is determined by what you specify on the command line. The value @code{links=tidy} has the same effect as the @samp{-L} command line option except that here it may be specified per item rather than globally. Setting this value causes links which point to non-existent files to be deleted. @cindex Deleting stale links @cindex Links, deleting stale @noindent If the warn directive is used (for directories, plain files or both) then only a warning message is issued if the file being tested does not match the specification given. If the fix directives are used then cfengine does not issue a warning, it simply fixes the value silently. Non-existent files are created by the @code{touch} command. A directory may be touched (created) by writing the filename @code{/a/b/c/.} with a dot as the last character. (This may also be achieved with the @code{directories} directive, @xref{directories}.) @item define=@var{classlist} If a file operation results in action being taken to fix a file, the colon, comma or dot separated list of classes becomes defined. Warnings do not activate the classes. @item checksum=@var{md5/sha/best} If set this option causes cfengine to add a checksum for the named file to a database. Changes in the value of this checksum are then warned as a security issue. This should normally only be used to monitor binary files which one would not expect to change often. Note also that the use of this option can mean a significant performance penalty. If the value @code{best} is used for this option then the best known pair of checksum methods are cross-checked for each file. (The best value are determined by the algorithms supported in the OpenSSL interfaces used to compile the program). If @code{ChecksumUpdates} is set, then security warning messages are issued only once and the value in the database is then changed to the new value of the file automatically i.e. the behaviour is similar to that of setuid root program detection, @xref{ChecksumPurge}. Also, @xref{ChecksumUpdates}. @cindex Message digests @cindex Hashes of files @cindex Tripwire functionality @item xdev Prevents cfengine from descending into file systems that are not on the same device as the root of the rescurion path. @cindex xdev @item rxdirs If true (the default) cfengine assumes that a directory that is readable should also have its execute flag set, allowing users to enter it and perform directory browsing. If false, cfengine will not make this assumption. Note that if set to false, it will affect recursive file checks. Thus setting to false with @code{mode=644 recurse=true} could lead to unintended permissions on directories. @end table The default values are @code{mode=+000}, @code{recurse=0}, @code{action=warnall} and any owner or group is acceptable. The default for @code{links} is to not traverse links unless the @code{-l} option is set on the command line. @c ..................................................... @c SUBSECTION @c ..................................................... @node Recursion, Directory permissions, Syntax, files @subsection Recursion @cindex Recursion in files @cindex Files, recursion The recursion specifier tells cfengine what to do, starting from @code{/directory name}. A value of @code{r=0} means `no recursion' and any checking is limited only to the named file or directory. A value of @code{r=inf} implies unlimited recursion. Cfengine then descends into all subdirectories checking or setting the permissions of files until it `bottoms out' at a plain file. A value such as @code{R=4} means descend recursively into subdirectories, but no more than four levels. This is a useful safety net in preventing unforeseen accidents. A recursive search also bottoms out on device boundaries and symbolic links (provided the @kbd{-l} option is not used). @cindex Device boundaries and files @cindex xdev (File system boundaries) @c ..................................................... @c SUBSECTION @c ..................................................... @node Directory permissions, Checksums and change management, Recursion, files @subsection Directory permissions @cindex Directory permissions @cindex Permissions, directories When you specify the permissions for a whole file tree, using the recursion specifier it is awkward to have to remember that directories must be executable. cfengine will do this for you automatically. If you specify that a file tree is to have a read flag set, cfengine will ensure that the corresponding execute flag is also set for directories which live in the tree. So the command @smallexample files: myclass:: /dir mode=a+rw r=inf fixall @end smallexample @noindent would set all plain files to mode 644 and all directories to 755, that is read/write for everyone on plain files and read/write/execute for everyone on directories. @c ..................................................... @c SUBSECTION @c ..................................................... @node Checksums and change management, home directive, Directory permissions, files @subsection Checksums and change management @cindex Checksums @cindex Hashes Integrity checks are a good way of detecting tampering with a system, or simply for monitoring upgrades that happen as a result of software unrelated to cfengine. The @code{checksum} option asks cfengine to compute and cache the value of the cryptographic checksum of the named file. @smallexample files: /my/file checksum=best action=warnall @end smallexample The checksum type can be @code{md5}, @code{sha} or @code{best}. The option best cross checks the best two available algorithms. At present cfengine is waiting for improvements to the OpenSSL library supporting sha2 algorithms. Once a value has been computed and placed in the database each new computation will be checked against the old one. Any change will lead to a mismatch and the following will happen: @itemize @bullet @item A warning is printed about the change @item As of 2.2.8 a class called @code{checksum_alerts} will be defined, indicating that a change has occurred. This can be used to trigger followup actions. The class is a persistant class that lasts for 60 minutes. @item If ChecksumUpdates is set to true, the new value will replace the old in the database @end itemize @c ..................................................... @c SUBSECTION @c ..................................................... @node home directive, Owner and group wildcards, Checksums and change management, files @subsection @code{home} directive @cindex home directive @cindex Files, home wildcard If you want to check the files of all the users who have their login areas on the current host, you can use a wildcard directive @code{home} instead of a directory name. In this case the file action iterates over all home directories physically on the current host. The home directories are, of course, located by searching for files which match @smallexample $(mountpattern)/$(homepattern) @end smallexample @noindent i.e. the values which are specified in the @code{control} part of the program. For example the following line is a very useful service to ignorant users. @smallexample files: any:: home mode=o-w r=inf act=fixall @end smallexample @noindent It ensures automatically that no user has files which can be written to by other arbitrary users. As a corollary to this, you may write something like @smallexample any:: home/www mode=a+r fixall @end smallexample @noindent to specify a special subdirectory of every users' home directory. This statement would check that all of the files in users' world wide web directories were readable for everyone. @c ..................................................... @c SUBSECTION @c ..................................................... @node Owner and group wildcards, Files linkchildren, home directive, files @subsection Owner and group wildcards @cindex Ownership of files @cindex Files, ownership If you do not want to explicitly state the owner or group of a file you may simply omit the group or owner options. @smallexample /@var{file-object} m=0664 r=inf @end smallexample This example generate a warning if any files under the named directory do not have permission read/write for all users. @c ..................................................... @c SUBSECTION @c ..................................................... @node Files linkchildren, touch, Owner and group wildcards, files @subsection Files linkchildren @vindex linkchildren @cindex Linkchildren The @code{linkchildren} facility is almost identical to that already described under @code{links}. @xref{Link Children}. The only difference here is that the ownership and permissions on the links are set all in one operation. For example: @smallexample @var{myclass}:: /local/lib/emacs m=0770 o=me g=mygroup act=linkchildren @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node touch, create, Files linkchildren, files @subsection touch @vindex touch @cindex Touching files The @code{touch} facility creates a new file with the specified permissions and ownership, or corrects the permissions and ownership of an existing file, in addition to updating the time stamps. @smallexample @var{myclass}:: /@var{newfile} mode=0644 action=touch @end smallexample @c ..................................................... @c SUBSECTION @c ..................................................... @node create, , touch, files @subsection create @vindex create @cindex Creating files This is like @code{touch} except that an existing file's time stamps, permissions and ownership will not be modified if the file already exists. If the file does not exist, the attributes are set to the values specified, or to the default values of @code{0644}. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node filters, groups, files, Cfagent reference @section filters @vindex filter @cindex Selecting files in searches @cindex Searching, advanced A filter is a way of selecting or pruning during a search over files or processes. Since filter rules could apply to several objects, cfengine allows you to define filter conditions as separate objects to be applied in different contexts. Filter objects can be used in @code{copy}, @code{editfiles}, @code{files}, @code{tidy} and @code{processes}. In most cases one writes @smallexample .. filter=filteralias @end smallexample in the appropriate command. The exception is @code{editfiles}, where the syntax is @smallexample @{ .. Filter "filteralias" .. @} @end smallexample Example: @smallexample files: /tmp filter=testfilteralias action=alert r=inf @end smallexample Filters are defined in a separate section. Filters for files and processes are defined together. They differ only in the criteria they contain. Here is are examples of file filters: @smallexample Filters: @{ filteralias1 Owner: "mark|cell|motd" Group: "ecg|mark" Mode: "700" FromCtime: "date(2000,1,1,0,0,0)" # absolute date ToCtime: "now" FromMtime: "tminus(1,0,0,2,30,0)" # relative "ago" from now ToMtime: "inf" # end of time FromAtime: "date(1997,2,22,0,0,0)" ToAtime: "inf" FromSize: "10000" # File size interval ToSize: "10mb" ExecRegex: "/usr/bin/file $(this) (.*ascii.*)"# Result from "files" command Type: "dir|link" # reg|link|dir|socket|fifo|door|char|block NameRegex: ".*.asc" # regex matching file name IsSymLinkTo: "/dev/null" # True if file is a link to object name regex Result: "Type" # Result which shouldbe returned @} ######################################### @{ testfilteralias2 ExecProgram: "/bin/ls $(this)" # True if the program returns true. $(this) is the current object @} ######################################### @{ testfilteralias3 Owner: "mark" @} @end smallexample Filters are evaluated like classes. In fact, the filtering works by evaluating the class attributes for each file. File filters: @table @code @item Owner: and Group can use numerical id's or names, or @code{``none''} for users or groups which are undefined in the system passwd/group file. @item Mode: applies only to file objects. It shares syntax with the @code{mode=} strings in the files command. This test returns true if the bits which are specified as `should be set' are indeed set, and those which are specified as `should not be set' are not set. @item Atime:,Ctime:,Mtime: apply only to file objects. These specify ranges From and To. If the file's time stamps lie in the specified range, this returns true. Times are specfied by a six component vector @smallexample (year,month,day,hour,minutes,seconds) @end smallexample This may be evaluated as two functions: date() or tminus() which give absolute times and times relative to the current time respectively. In addition, the words now and inf may be used. e.g. @smallexample FromCtime: "date(2000,1,1,0,0,0)" # absolute date ToCtime: "now" FromMtime: "tminus(1,0,0,2,30,0)" # relative "ago" from now ToMtime: "inf" # end of time @end smallexample @item Type: applies only to file objects may be a list of file types which are to be matched. The list should be separated by the OR symbol `|', since these types are mutually exclusive. The possible values are currently @smallexample file|reg|link|dir|socket|fifo|door|char|block @end smallexample Note that @code{file} and @code{reg} are synonymous. @item ExecRegex: matches the test string against the output of the specified command. @item NameRegex: matches the name of the file with a regular expression. @item IsSymLinkTo: applies only when the file object $(this) is a symbolic link. It is true if the regular expression matches the contents of the link. @item ExecProgram: matches if the command returns successfully (with return code 0). Note that this feature introduces an implicit dependency on the command being called. This might be exploitable as a security weakness by advanced intruders. @item Result: specifies the way in which the above elements are combined into a single filter. @end table Process filters: @table @code @item Owner process owner UID (quoted regex) @item PID: process ID (quoted regex) @item PPID: parent process ID (quoted regex) @item PGID: process group ID (quoted regex) @item RSize: resident size (quoted regex) @item VSize: virtual memory size (quoted regex) @item Status: status (quoted regex) @item Command: CMD or COMMAND fields (quoted regex) @item (From/To)TTime: Total elasped time in TIME field (accumulated time) @item (From/To)STime: Starting time for process in STIME or START field (accumulated time) @item TTY: terminal type, or none (quoted regex) @item Priority: PRI or NI field (quoted regex) @item Threads: NLWP field for SVR4 (quoted regex) @item Result: logical combination of above returned by filter (quoted regex) @end table Examples: processes started between 18th Nov 2000 and now. @smallexample @{ filteralias FromSTime: "date(2000,11,18,0,0,0)" ToSTime: "now" @} @end smallexample All processes which have accumulated between 1 and 20 hours of CPU time. @smallexample @{ filteralias FromTTime: "accumulated(0,0,0,1,0,0)" ToTTime: "accumulated(0,0,0,20,0,0)" @} @end smallexample @menu * Complete filter examples:: @end menu @node Complete filter examples, , filters, filters @subsection Complete filter examples Here is an example filter to search for all files which are either directories or links, or any kind of file owned by mark, in group cfengine. @smallexample control: actionsequence = ( files ) files: /tmp filter=testfilteralias action=alert r=inf /cfengine filter=testfilteralias action=fixall r=inf mode=644 filters: @{ testfilteralias Owner: "mark" Group: "cfengine" Type: "dir|link" Result: "Type|(Owner.Group)" # Both owner AND group required correct @} @end smallexample Find all ELF executables using data from the Unix @code{file} command. Caution, this takes a long time if used indescriminately. @smallexample control: actionsequence = ( files ) files: /tmp filter=testfilteralias action=alert r=inf /cfengine filter=testfilteralias action=fixall r=inf mode=644 filters: @{ testfilteralias ExecRegex: "/bin/file (.*ELF.*)" Result: "ExecRegex" @} @end smallexample Here is an example which warns of any process coupled to a terminal started in November: @smallexample control: actionsequence = ( processes ) filters: @{ filteralias FromSTime: "date(2000,11,0,0,0,0)" ToSTime: "date(2000,11,30,0,0,0)" TTY: ".*pt.*" Result: "TTY.STime" @} processes: "." filter=filteralias action=warn @end smallexample @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node groups, homeservers, filters, Cfagent reference @section groups/classes @vindex groups @cindex Defining groups @cindex Groups, defining The @code{groups} action (equivalently referred to as @code{classes} as of version 1.4.0) is used to define classes which stand for groups of hosts. If you use the NIS (network information service) facility for defining @emph{netgroups} then this idea will already be familiar to you and you can probably use your already-defined netgroups in cfengine. @cindex @code{groups} @cindex @code{classes} To define a group, you simply make a list and assign it a name. Here is an example of the syntax: @smallexample groups: ANDed_class:: science = ( saga tor odin ) packages = ( saga ) AllHomeServers = ( saga ) AllBinaryServers = ( saga ) OIH_servers = ( saga ) OIH_clients = ( tor odin ) notthis = ( !this ) ip_in_range = ( IPRange(129.0.0.1-15) ) # host is in ip address range ip_in_range = ( IPRange(129.0.0.1/24) ) # host is in ip address range (CIDR notation) compute_nodes = ( HostRange(cpu-,1-32) ) # host name in the cpu-01 through cpu-32 range @end smallexample @cindex CIDR @cindex Classless IP addresses @noindent To include a list of hosts from a NIS netgroup, you use the @samp{+} symbol, or the @samp{+@@} construction. For example: @cindex Netgroups @cindex NIS, netgroup support @vindex + @w{} @smallexample groups: science = ( +science-allhosts ) physics = ( +physics-allhosts ) physics_theory = ( +@@physics-theory-sun4 dirac feynman schwinger ) @end smallexample @noindent Using an enormous netgroup does not use up any space. A group declaration results in the storage of only the class name regardless of how many hosts are in the list. The rule is that the left hand side of the assignment becomes defined (true) if the list on the right hand side includes the host which is parsing the file --- i.e. @code{$(host)}. In some cases your netgroups will not correspond exactly to the list you want, but it might be more convenient to use a netgroup @emph{except} for certain hosts. You can `undefine' or remove hosts from the netgroup list by using the minus `-' symbol. For example: @cindex Removing entries from netgroups @cindex Negating entries from netgroups @cindex Netgroups, negating entries @w{} @smallexample group = ( +mynetgroup -specialhost -otherhost ) @end smallexample @noindent which means, of course, all hosts in netgroup @code{mynetgroup} except for @code{specialhost} and @code{otherhost}. Finally, you may also subtract two netgroups in the following manner. @smallexample group = ( +bignetgroup -smallnetgroup ) @end smallexample @noindent The `minus' command effectively eliminates its members from @code{bignetgroup} if they exist within that group. If none of the hosts in @code{smallnetgroup} exist in @code{bignetgroup} then the command has no effect. @cindex Group dependencies @cindex Class dependencies @cindex Dependencies Groups may contain previously defined cfengine groups too. This allows one class to inherit the attributes of another class, for instance: @smallexample AllSun4Hosts = ( sonny sunny solar stella ) AllUltrixHosts = ( ully olly wally golly ) AllBSD = ( AllSun4Hosts AllUltrixHosts ) @end smallexample @noindent The classes on the right hand side are effectively ORed together into the left hand side. This enables complex classes to be constructed from several other basic classes, e.g. @smallexample SpecialTimes = ( Hr00 Monday Day1 ) @end smallexample @noindent which evaluates to true every day when it between 00:00 hours and 00:59, all day Monday and all day on the first day of every month. If you apply a class predicate before a definition then the result is effectively the AND of the classes: @smallexample Hr00:: SpecialTime = ( Monday Tuesday ) @end smallexample defines @code{SpecialTime} at Hr00 on Monday or Tuesday. @cindex Shell command to decide class @cindex Class decided by shell command Finally, you can define groups (strictly classes) by the result of a shell command. A shell command or program is deemed to be `true' if it exits with a status of zero, i.e. it calls @code{exit(0)}. Any other value is taken to be false. You can include shell commands as the members of groups in order to define classes based on the outcomes of your own scripts by enclosing the script in single or double quotes: @smallexample have_cc = ( '/bin/test -f /usr/ucb/cc' ) @end smallexample @noindent The class @code{have_cc} will then be defined if the shell command returns true. Of course, you can put any script or program in the single quotes as long as they adhere to the convention that zero exit status means true. If you have several members which are shell commands, then the effect is to make the class the logical OR of the scripts' results. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node homeservers, ignore, groups, Cfagent reference @section homeservers @cindex Home servers, defining @cindex Defining a home server @vindex homeservers The @code{homeservers} declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of which other hosts on the network possess filesystems containing home directories (login areas) which client hosts should mount. A sample homeserver declaration looks like this: @smallexample homeservers: Physics:: einstein Math:: riemann euler @end smallexample @noindent The meaning of this declaration is the following. Any host which finds itself to be a member of the classes on the left hand side of the assignment need to mount all home directory resources from the hosts on the right hand side of the assignment. The pattern variable @code{homepattern} is used to determine which resources are home directories in the list of @code{mountables}. @xref{mountables}. Let us consider an example in which @code{homepattern} is set to the wildcard value @samp{home?} and the mountables list is given by @smallexample mountables: einstein:/mysite/einstein/home1 einstein:/mysite/einstein/home2 mountoptions=soft,bg,intr,rsize=8192,wsize=8192 riemann:/mysite/riemann/local readonly=true euler:/mysite/euler/home1 @end smallexample @vindex mountables @cindex Mountable resources, defining Any host in the group @code{Physics} would now want to mount all home directories from the host @code{einstein}. There are two of these. Both the filesystems listed for @code{einstein} match the @code{homepattern} variable since they end in @samp{home?}. cfengine would therefore take this to mean that all hosts in @code{Physics} should mount both of these filesystems. Hosts in @code{Math}, on the other hand, should mount only homedirectories from the hosts @code{riemann} and @code{euler}. There is only a single filesystem on @code{riemann} and it does not match @code{homepattern}, so it is not mounted. On @code{euler} there is a match, so this filesystem will be added to the appropriate hosts. @emph{Cfengine picks out home directory resources from the @code{mountables} list by trying to match the @code{homepattern} variable, starting from the end of the directory name. You do not therefore have to use the designation @code{/site/host/home?} but this is a simple choice and is highly recommended.} @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node ignore, import, homeservers, Cfagent reference @section ignore When you specify a recursive search as part of a @code{files}, @code{tidy} or @code{copy} action, you would sometimes like to exclude certain directories from the list of sub directories. In most cases you will want to do this on a per-command basis (see the pages for these actions separately), but you can also make a global ignore list. This can be accomplished by adding the directory to the ignore-list. The syntax is @cartouche @w{} @smallexample ignore: @var{wildcards/directories/filenames} @end smallexample @end cartouche For example: @cindex ignore command @w{} @smallexample ignore: any:: # # Prevent tidying .X11 directories in /tmp where # window managers write semaphores # .X11 # # Don't tidy emacs locks # !* /local/lib/gnu/emacs/lock/ /local/tmp /local/bin/top /local/lib/tex/fonts /local/etc /local/www /local/mutils/etc/finger.log @end smallexample @noindent None of the above directories will be checked or entered during recursive descents unless a specific command is initiated to search those directories with their names as the top of the search tree. @cindex .X11 directory A handy tip if you are tidying @file{/tmp} recursively is to include the directory @file{.X11} here. This directory is used by the X-windows system and deleting it while a window manager has an open session can cause the user some trouble. Ignore refers to all recursive searches in tidy, files, copy and links. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node import, interfaces, ignore, Cfagent reference @section import @cindex Importing files @cindex Several files @cindex Files, importing @cindex Files, breaking up into several @vindex import To break up a large configuration file into smaller files you can use the include directive. This conditionally reads in files if the class on the left hand side of the assignment matches the host parsing the file. This enables also a variety of cfengine configuration scripts to read in a standard set of default settings. The syntax of the statement is: @smallexample import: any:: cf.global_classes linux:: cf.linux_classes @end smallexample Note that, if you define variables in an imported file they will not be defined for operations in their parent files. This because cfengine reads in all the import files after the main file has been parsed---not at the place where you call import in your script. This means that variables or macros defined in imported files are only defined after the main program. Variables from earlier files are inherited by later includes, but not @emph{vice-versa}. @cindex Variables in import files @cindex Import files, variables in @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node interfaces, links, import, Cfagent reference @section interfaces @cindex Network interfaces, several @cindex Dual homed hosts @vindex interface configuration @cartouche @w{} @smallexample interfaces: @var{classes}:: @var{interfacename} netmask=@var{netmask} broadcast=@var{broadcast} @end smallexample @end cartouche If you have more than one network interface, or you do not wish to use the default interface name, this section may be used to define further interfaces to be checked. This feature can replace the older method of setting netmask and broadcast address in @code{control:}. If the @code{netmask} variable is not set, cfengine ignores the default interface configuration. Example: @smallexample interfaces: "le1" netmask=255.255.255.0 broadcast=ones "le2" netmask=255.255.255.0 broadcast=ones @end smallexample @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node links, mailserver, interfaces, Cfagent reference @section links @cindex Making links @cindex Links, making @vindex links The symbolic links function is one of the greatest plusses in cfengine as a system administration tool. It allows you to do two things: check single links for correctness and consistency (or make them if they do not exist), and check or make links to every file in a designated directory. This latter feature is called multiple linking or linking children. The @code{linkchildren} feature is also available from the @code{files} action @xref{files}. The syntax of a link item is: @cartouche @w{} @smallexample @var{from-link} ->[!] @var{to-object} @var{or} @var{from-link} +>[!] @var{to-object} type=@b{symbolic/absolute/abs}/@var{hard/relative/rel} copy=@var{pattern} recurse=@var{number/inf/}@b{0} copytype=@var{checksum/}@b{ctime} include=@var{pattern} exclude=@var{pattern} ignore=@var{pattern} action=@var{silent} deadlinks=@b{kill}/@var{force} define=@var{classlist} nofile=@b{kill}/@var{force} syslog=@var{true/on}/@var{false/off} inform=@var{true/on}/@var{false/off} audit=@var{true/on}/@var{false/off} ifelapsed=@var{mins} expireafter=@var{mins} @end smallexample @end cartouche @noindent @emph{The special variable @code{$(binserver)} can be used in @code{links}.} @c ..................................................... @c SUBSECTION @c ..................................................... @menu * Single links:: * Multiple Links:: * Link Children:: * Relative and absolute links:: * Hard links:: @end menu @node Single links, Multiple Links, links, links @subsection Single links @cindex Single links @cindex Links, single To define a single link, you create an entry of the following form: @smallexample links: @var{class}:: @var{linkname} -> @var{object_to_link_to} @var{linkname} -> ./@var{relative_link} @var{linkname} -> ../@var{relative_link} @end smallexample @noindent If links exists and point to their intended destinations then no action is taken. If a link exists but points incorrectly then a warning is issued, unless the pling operator @samp{!} is given, in which case the correct value is forced. If the link exists and points to a file which does not exist a warning is issued unless the command line option @code{-L} is used, in which case the link is deleted. @cindex @code{-L} option @vindex -L Here is an example of some valid link statements. @smallexample links: Physics.sun4:: /usr/local -> /$(site)/$(host)/local /home -> /$(site)/$(host)/u1 /etc/sendmail.cf -> /usr/local/mail/etc/global-sendmail.cf /usr/lib/sendmail ->! /local/lib/sendmail @end smallexample @noindent cfengine makes any directories which are required leading up to the link name on the left hand side of the arrow automatically. In the last example the `pling' forces cfengine to make the link even if a file for link exists previously. Plain files are saved by appending @file{.cfsaved} to the filename, or by moving to a repository, whereas old links are removed. The same effect can be enforced globally using the @code{-E} option, but only if the program is run interactively. (In this case a prompt is issued to make sure that you wish to use such a big hammer on your system!) The link operation accepts a number of parameters @table @code @item type=@var{hard/relative/absolute} If the link type is hard, a hard link is created @xref{Hard links}. Symbolic links may specify two special types. If @code{relative} is selected, and the `to' object is an absolute path name, the link name will be rewritten as a pathname relative to the source file, using @samp{.} and @samp{..} to move relative to the current directory. For instance, a link from @file{/usr/local/file} to @file{/usr/file} would be linked as @file{./../file}. If the `to' object is already relative, this has no effect. If @code{absolute} is specified, cfengine will try to resolve the true path location of the `to' object, expanding any symbolic links or dots in the path name, up to a maximum of four levels of symbolic links. @cindex Relative links @cindex Symbolic links, relative @cindex Links, absolute @cindex Absolute links @cindex Symbolic links, absolute @cindex Links, absolute @item copy=@var{pattern} This option can be repeated any number of times to build up a list of filenames or wildcards which are to be copied rather than linked symbolically. The copy is made on an age-comparison basis. A global variable may also be set to invoke this feature @xref{copylinks}. Directories cannot be copied in this way. @item copytype=@var{checksum/ctime} This specifies the basis for deciding whether to update a file which is to be copied instead of linked @xref{copy}. @item nofile=@b{kill}/@var{force} This decides what happens to links which point to non-existent files. The default action is to remove such links, or refuse to create them. By setting the @var{force} option you can force cfengine to make symbolic links to files which do not exist. This is useful for setting up links to filesystems which are not permanently mounted. @cindex Links, removing dead @cindex Links, forcing for non-existent files @item exclude=@var{pattern} This option can be repeated any number of times to build up a list of filenames or wildcards which are to be excluded from the linking process. A global variable may also be set to invoke this feature @xref{excludelinks}. @item ignore This works like the global ignore directive but here you may provide a private list of ignorable directories and files. Unlike include, exclude this affects the way cfengine parses directory trees. @item recurse=@var{number/}inf This option can only be used with multiple link operations @xref{Multiple Links}. If this option is specified, cfengine links only non-directory objects. Directories are instead created and links within those directories are also created. The value of this option specifies the maximum number of levels to which cfengine should recursively descend a link tree. @code{inf} means infinite recursion. Cfengine also ignores files and directories in the ignore list @xref{ignore}. @item define=@var{classlist} If a link is created or replaced, the colon, comma or dot separated list of classes becomes defined. @end table @cindex Binary servers and links @cindex Links and binary servers @vindex binserver The final feature of the links facility is connected to the use of the cfengine model for mounting NFS filesystems. In particular it concerns the variable @code{$(binserver)}. The easiest way to understand this feature is to illustrate a couple of examples. Consider the following: @smallexample links: any:: /local -> /$@{site@}/$@{binserver@}/local @end smallexample @noindent The result of this command is quite different depending on which host is executing it. The variable @code{$(site)} clearly has a fixed value, but the variable @code{$(binserver)} might expand to any valid binary server for the host executing the program. @xref{binservers}. The procedure cfengine adopts is to go through its list of mountables, keeping only those mountable resources which belong to defined binary servers for the current host. It then attempts to match a filesystem by substituting @code{$(binserver)} with each of its valid binservers in turn and it matches the first one binary server which yields an existing file. @cindex Binary servers, priority Note that every host is a binary server for itself, so that the value of @code{$(binserver)} which has absolute priority is alway the same as the value of @code{$(host)}. This ensures that the link will always be made to a local filesystem if the rules of the model are upheld. @c ..................................................... @c SUBSECTION @c ..................................................... @node Multiple Links, Link Children, Single links, links @subsection Multiple Links @cindex Multiple links @cindex Links, multiple With the link symbol @code{+>}, you opt to link all of the files in a directory to corresponding files in another directory. This procedure is sometimes useful for installing software. In the example @smallexample links: myclass:: /usr/local/bin +> /usr/local/lib/perl/bin /opt +>! /local @end smallexample @noindent every file in the directory @code{/usr/local/lib/perl/bin} is linked symbolically to a corresponding file in @code{/usr/local/bin}. The `pling' character forces cfengine to replace old links or plain files already existing. Old links are removed, whereas old files are saved by appending @file{.cfsaved} to the filename @xref{repository}. @cindex @file{.cfsaved} files Each time cfengine runs it goes through all of the files in the directory concerned and checks the appropriate link accordingly. If new files appear, new links will be added. If a file disappears but the link to it remains, a warning will be issued, unless the @code{-L} command line option is used, in which case the link is deleted. @c ..................................................... @c SUBSECTION @c ..................................................... @node Link Children, Relative and absolute links, Multiple Links, links @subsection Link Children @cindex Linkchildren @vindex linkchildren The linkchildren directive is a closely related to the cfengine model for NFS filesystems. It is a way of making links which embodies a rudimentary kind of `intelligence'. @cindex Binary servers and links @cindex Links and binary servers @vindex binserver Consider the following: @smallexample links: any:: /usr/local/lib/emacs +> linkchildren @end smallexample @noindent The word @code{linkchildren} automatically tells cfengine that it should look for an appropriate file to link to on a binary server for the current host. The exact meaning of the above statement is as follows. cfengine begins searching though the list of mountable resources, discarding any filesystems which do not belong to valid binary servers. It looks for a filesystem ending in `emacs' (the last link of the left hand side). If all is well, these file systems are already mounted and they can be searched. If no resource is found ending in `emacs', we go to the next link @code{lib} and look for a filesystem ending in `lib'. If this is not found we go to @code{local} and so on. When a match is made, cfengine then tries to locate the file by checking whether it exists relative to the matched filesystem. For example, suppose `local' matched with @code{host:/site/host/local}. It would then try to locate @code{host:/site/host/local/lib/emacs} and link all of the children therein to the local file directory @code{/usr/local/lib/emacs}. @cindex Making use of local disk space @cindex Local disk space, make use of Here is another example which makes reference to the cfengine model for mounting NFS filesystems. Suppose you have a host with some spare disk space. You want to mount @code{/usr/local} from the binary architecture server, but you also want to use the disk you have locally. The following lines @smallexample links: electron:: /$(site)/electron/local +> linkchildren any:: /usr/local -> /$(site)/$(binserver)/local @end smallexample @noindent have the effect of creating a directory @code{/$(site)/electron/local} and filling it with links to all of the files and directories on the binary server's mounted filesystem. It results in an exact copy (by linkage) on the local disk, but does not use up your local disk space. The space you have remaining could, for example, be used for software with a special license for that host. The second link links @code{/usr/local} to the `nearest' binary server. But the nearest binary server is always @code{$(host)} which means this evaluates to a file which now exists because of the first command, so on the host `electron' the directory @code{/usr/local} ends up being a link to @code{/$(site)/electron/local} which is full of links to the binary server. If you've caught your breath after that mouthful you probably have mixed feelings about creating a bunch of links in this way. What happens if the files they point to are removed? Then you are left with a lot of useless links. Actually this is no problem for cfengine, since you can ask cfengine to simply remove links which point to non-existent files @xref{files}. Nevertheless, this feature clearly requires some caution and is mainly a spice for advanced users of the cfengine model. @c ..................................................... @c SUBSECTION @c ..................................................... @node Relative and absolute links, Hard links, Link Children, links @subsection Relative and absolute links When specifying symbolic linking, you can ask cfengine to change the link type to be either relative to the source or to be an absolute path. What this means is the following. Consider the following link: @smallexample /var/tmp/cfengine -> /local/cfengine @end smallexample @noindent If we add the option @code{type=relative}, then instead of creating a link which points to @file{/local/cfengine}, the link is created pointing to the location @smallexample ./../../local/cfengine @end smallexample @noindent In other words, the link is relative to the calling directory @file{/var/tmp}. If a link is specified as being absolute with the option @code{type=absolute}, then cfengine attempts to resolve to value of the link so as to be the true path of the target. If the target name contains a symbolic link, then this is expanded as far as possible to give the true path to the file. For example, if @file{/local} is really a link to @file{/site/myhost/local} then the link would point to @file{/site/myhost/local/cfengine}. @c ..................................................... @c SUBSECTION @c ..................................................... @node Hard links, , Relative and absolute links, links @subsection Hard Links @cindex Hardlinks @vindex type= Cfengine will also allow you to create hard links to regular files. A hard link is in every way identical to the original file, it merely has a different name (technically, it is a duplicate inode). To create a hard link you use the link-option @code{type=hard}. For example: @smallexample links: /@var{directory}/@var{newname} -> /@var{directory}/@var{othername} type=hard @end smallexample @noindent Cfengine will not create hard links to directories or other special files. This is always a slightly dubious practice and is best avoided anyway. POSIX says that the hard link can be on a different device to the file it points to, but both BSD and System V restrict hard links to be on the same device as their predecessors. Cfengine has no policy on this, but---in the theoretical case in which the hard link and the predecessor were on different file systems---it becomes near impossible to determine with certainly between a hard link and a very similar regular file, and thus cfengine issues a warning in verbose mode about this eventuality. Provided both link and predecessor are on the same filesystem cfengine determines the status of hard links by comparing the device and inode numbers of the file pointed to. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node mailserver, methods, links, Cfagent reference @section mailserver @cindex Mail server, defining @cindex Defining a mail server @vindex mailserver The @code{mailserver} declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of which NFS filesystem contains mail for its users. All hosts apart from the mail-host itself must then mount the mail spool directory across the network. The declaration looks like this: @smallexample mailserver: @var{class}:: mailhost:/var/spool/mail @end smallexample @noindent The result of the @code{mailcheck} command in the action-sequence is now to mount the filesystem @code{/var/spool/mail} on the host @code{mailhost}. This action is carried out on any machine which does not already have that filesystem mounted. @vindex mailcheck The mail spool directory is mounted, by default, onto the official mail spool directory for the system which is parsing the program. In other words, on an HPUX system, the spool directory is mounted on @code{/usr/mail} by default, whereas on a Sun system it would be mounted on @code{/var/spool/mail}. The default location can be changed by using the resource file. @xref{cfrc resource file}. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node methods, miscmounts, mailserver, Cfagent reference @section methods @cindex Methods @cindex Private modules @vindex methods From version 2.1.0, cfagent provides for the execution of closed functions or "methods". Methods are similar to the old idea of modules, but they are implemented in a way that allows collaboration between different hosts within a network, using a common standard. Methods must be cfengine programs however, wheras the module interface can be written in any script language. @emph{Methods are designed to offer a firewall-like proxy interface for remote method execution. We can call methods a form of `voluntary RPC', in which hosts execute methods for one another on a purely voluntary basis. This builds in anti-spamming protection. The principle used is that hosts should be immune to Denial of Service attacks; they should only be able to disadvanatge themselves with the attempt.} (Remote method execution was not implemented until version 2.1.3. It is still considered experimental and should be tested carefully for production environments with at least version 2.2.2. List expansion is particularly fragile in cfengine 2. This problem cannot be resolved in version 2, so this should not be reported as a bug. ) @cindex Warning remote methods @cindex Methods, remote caution Methods allow you to call an independent cfengine program, pass it arguments and classes, and collect the results for use in your main program. It thus introduces parent-child semantics into cfengine "imports". A method is more than an import. (Import is analagous to a C #include, while a method is like a C function.) Communication is peer to peer, by mutual consent. There is no "method server" that executes methods on remote hosts. Hosts exchange information by invitation only. This is an unreliable service (in the sense of UDP). The order of method exeuction is not guaranteed. This results from the decoupling between client request and service provision. @cartouche @smallexample methods: @var{class}:: @var{function_name}(@var{parameters or none}) action=@file{filename} sendclasses=@var{comma separated class list} returnvars=@var{comma separated variable list or void} returnclasses=@var{comma separated class list} server=@var{ip-host/localhost/none} forcereplyto=@var{ip address} owner=@var{setuid} group=@var{setgid} chdir=@var{cd for child} chroot=@var{sandbox directory} @end smallexample @end cartouche Most of these functions will be familiar from other cfengine commands. Some special ones are noted below: @table @code @item action The name of the method file that should be defined in the modules directory of the server host. @item forcereplyto Sometimes nameservice problems (especially with remote devices) can lead to confusion about where a method should be sent. The caller can therefore declare to the server which address it wants the reply to be marked for. @item returnvars Returns the values of the variables to the parent process. This acts as an access control list for variable names transmitted by the child process. The names returned by the child must match this list. @item returnclasses Returns the classes to the parent process, if and only if they are defined at the end of the current method. This acts as an access control list for class names transmitted by the child process. The names returned by the child must match this list. @item sendclasses Transmits the current status of the named classes to the child process. In other words, if the listed classes are defined, they become defined in the child process, else they remain undefined. The class may still be defined in the child by independent local definitions. @end table If the server is set to @code{localhost}, the method will be evaluated on the local machine. If the server is set of @code{none}, the method will not be executed at all. @cindex none in server @vindex none The function arguments may not be empty, but a null value can be transmitted with a dummy value, e.g. @code{Function(null)} or @code{function(void)}. Here is an example method call. @smallexample # cfagent.conf control: actionsequence = ( methods ) ################################################# methods: any:: SimpleMethod(null) action=cf.simple returnvars=null returnclasses=null server=localhost @end smallexample With method file (located in the ModulesDirectory), @smallexample # cf.simple control: MethodName = ( SimpleMethod ) MethodParameters = ( null ) actionsequence = ( timezone ) classes: dummy = ( any ) #################################################### alerts: dummy:: "This simple method does nothing" ReturnVariables(void) ReturnClasses(void) @end smallexample On executing this example, the output is: @example nexus$ ./cfagent -f ./cftest cfengine:myhost:SimpleMethod: cfengine:nexus: This simple method does nothing @end example If the server name is a wildcard, e.g. @code{*} then this acts as a multicast or broadcast. @c ........................................... @c SUBSECTION @c ........................................... @menu * localhost examples:: * remotehost examples:: @end menu @node localhost examples, remotehost examples, methods, methods @subsection Localhost examples The following example collects the tar file, unpacks it, configures and compiles it, then tidies its files. @smallexample #################################################### # # This is a cfengine file that calls a method. # It should be in the usual place for cfinputs # #################################################### control: actionsequence = ( methods ) ##################################################### methods: InstallTar(cfengine-2.1.0b7,/local/gnu) action=cf.install returnvars=null returnclasses=null server=localhost @end smallexample We must install the method in the trusted modules directory (normally /var/cfengine/modules or WORKDIR/modules). @smallexample #################################################### # # This is an example method file, that needs to be # in the module directory /var/cfengine/modules # since this is the trusted directory # # e.g. InstallFromTar(cfengine-2.1.0,/usr/local/gnu) # #################################################### control: MethodName = ( InstallTar ) MethodParameters = ( filename gnuprefix ) path = ( /usr/local/gnu/bin ) TrustedWorkDir = ( /tmp ) TrustedSources = ( /iu/nexus/ud/mark/tmp ) TrustedSourceServer = ( localhost ) actionsequence = ( copy editfiles shellcommands tidy ) #################################################### classes: Force = ( any ) #################################################### copy: $(TrustedSources)/$(filename).tar.gz dest=$(TrustedWorkDir)/$(filename).tar.gz server=$(TrustedSourceServer) #################################################### shellcommands: "$(path)/tar zxf $(filename).tar.gz" chdir=$(TrustedWorkDir) "$(TrustedWorkDir)/$(filename)/configure --prefix=$(gnuprefix)" chdir=$(TrustedWorkDir)/$(filename) define=okay okay:: "$(path)/make" chdir=$(TrustedWorkDir)/$(filename) #################################################### tidy: $(TrustedWorkDir) pattern=$(filename) r=inf rmdirs=true age=0 #################################################### #editfiles: # #@{ $(TrustedWorkDir)/$(filename)/configure-opts # #AppendIfNoSuchLine "Something ???" #@} #################################################### alerts: Force:: ReturnVariables(none) ReturnClasses(success) @end smallexample A more complex example is given below: @smallexample GetAnalysis("$@{parent1@}",param2,ReadFile("/etc/passwd",300)) # The name of the method that is in modulesdir action=cf.methodtest # The variables that we get back should be called these names # with method name prefix returnvars=a,b,c,d # This is an access list for returned classes. Classes will # only be handed back if they are included here returnclasses=define1,define2,class1 # The host(s) that should execute the method server=localhost # Only localhost can decide these - not a remote caller # owner=25 # group=root # chdir=/var/cfengine # chroot=/tmp @end smallexample Here the function being called is the cfengine program @file{cf.methodtest}. It is passed three arguments: the contents of variable @var{parent1}, the literal string "param2" and the first 300 bytes of the file @file{/etc/passwd}. On return, if the method gets executed, the values will be placed in the four variables: @smallexample $(GetAnalysis.a) $(GetAnalysis.b) $(GetAnalysis.c) $(GetAnalysis.d) @end smallexample If the classes @code{define1} etc, are returned by the method, then we set them also in the main program as @smallexample GetAnalysis_define:: @end smallexample In other words, the class name is also prefixed with the method name to distinguish it. (@code{returnclasses} works like an access control list for setting classes, deciding whether or not the main script should accept the results from the child method.). The remaining options are as those for executing shell commands, and apply only on the host that executes the function. Both the client and server hosts must have a copy of the same method declaration. The client should have a non-empty @code{server=} declaration. The server side should have no @code{server=} declaration unless it is sending the request on recursively to other hosts. At present only requests to localhost are allowed, so only there is automatic access to the rule. The cfagent file that contains the method code must have the following declarations: @cartouche control: MethodName = ( @var{identifier} ) MethodParameters = ( @var{spaced list of recipient variables or files} ) # .... alerts: # Return variables are alerts to parent ReturnVariables(@var{comma separated list of variables or functions or void}) ReturnClasses(@var{comma separated list of classes}) @end cartouche e.g. @smallexample control: MethodName = ( GetAnalysis ) MethodParameters = ( value1 value2 /tmp/file1 ) # .... alerts: # Return variables are alerts to parent ReturnVariables("$@{var1@}","$@{var2@}","var3",literal_value) ReturnClasses(class1,class2) @end smallexample The parameters transmitted by the parent are read into the formal parameters @code{value1}, @code{value2} and the the file excerpt is placed in the temporary file @file{/tmp/file1}. The return classes are passed in their current state to the parent; i.e. if class1 is defined then it is offered to the parent, but if it is not defined in the method, it is not passed on. The parent can then choose to accept or ignore the value. @c ........................................... @c SUBSECTION @c ........................................... @node remotehost examples, , localhost examples, methods @subsection Remote host examples Methods can also be scheduled for execution on remote hosts. @itemize @item Both hosts must have an identical copy of the method stanza @item Public keys must be exchanged between the cooperating hosts @item Access must be granted to @file{/var/cfengine/rpc_out} in cfservd. @end itemize Remote method execution is the same as local method execution except for some additional requirements. A list of collaborating peers must be added to the control section of @file{update.conf}. In order the the requests to be collected automatically, you must have @code{copy} in the action sequence of the @file{update.conf} file. @smallexample control: MethodPeers = ( @var{hostname list} ) # Must have copy in actionsequence @end smallexample This list tells the agent which remote hosts to collaborate with, i.e. whom should we contact to look for work that we have promised to perform? In order the the requests to be collected automatically, you must have @code{copy} in the action sequence of the @file{update.conf} file. For example, to make two hosts collaborate: @smallexample methods: host1|host2:: MethodTest("my test!") action=cf.methodtest server=host2.iu.hio.no returnclasses=null returnvars=retval ifelapsed=120 @end smallexample Note that an important aspect of remote method invocation is that there is only voluntary cooperation between the parties. A reply bundle from a finished method can collected from a server by the client many times, causing the classes and variables associated with it to be defined at regular intervals, controlled by the ifelapsed time. To avoid multiple actions, you should lock methods or their follow-up actions with long ifelapsed times. This is a fundamental `feature' of voluntary cooperation: each party must take responsibilty for the sense of what it receives from the other. This feature will not be to everyone's taste, and it is unconventional. However, voluntary cooperation provides a way of collaborating without trust in a framework that forces us to confront the security issues directly. As such, it is a successful experiment. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node miscmounts, mountables, methods, Cfagent reference @section miscmounts @cindex Mounting filesystems. @cindex Miscellaneous mount operations @vindex miscmounts If you do not use the cfengine model for statically mounting NFS filesystems (or if there are filesystems which do not naturally fall into the bounds of that model) then you can still statically mount miscellaneous filesystems using a statement of the form: @cartouche @w{} @smallexample miscmounts: @var{class}:: @var{infohost}:@var{source-directory} @var{destination} @var{mode} @var{infohost}:@var{source-directory} @var{destination} mode=@var{mode} ifelapsed=@var{mins} expireafter=@var{mins} @end smallexample @end cartouche @noindent For example @smallexample physics:: # old syntax libraryserver:/$(site)/libraryserver/data1 /$(site)/libraryserver/data1 ro # consistent syntax libraryserver:/$(site)/libraryserver/data2 /$(site)/libraryserver/data2 mode=ro host:/foo /foo mode=rw,bg,hard,intr @end smallexample @noindent This statement would mount the directory @file{/$(site)/libraryserver/data} physically attached to host libraryserver onto a directory of the same name on all hosts in the group @code{physics}. The modes @code{ro} and @code{rw} signify read-only and read-write respectively. If no mode is given, read-write is assumed. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node mountables, processes, miscmounts, Cfagent reference @section mountables @cindex Mountable resources, defining @cindex Defining a mountable @vindex mountables The @code{mountables} declaration need only be used if you are using cfengine's model for mounting NFS filesystems. This declaration informs hosts of what filesystem resources are available for mounting. This list is used in conjunction with @code{binservers} and @code{homeservers} to determine which filesystems a given host should mount, according to the cfengine model. The syntax of the list is: @smallexample mountables: @var{class}:: "filesystem to mount" readonly=@b{false/off}/@var{true/on} mountoptions=@var{nfs-options} @end smallexample e.g. @smallexample mountables: @var{class}:: server:/site/server/u1 server:/site/server/local linuxhost:/site/linuxhost/local linuxhost:/site/linuxhost/u1 @end smallexample @noindent Notice that binary and home-directory filesystems are mixed freely here. Cfengine determines which of the entries are homedirectories using the @code{homepattern} variable. @vindex homepattern @cindex Homepattern variable. Every time you add a disk or a mountable partition to your network, you should add the partition to the list of mountables. @emph{NOTE: This list is read in order, top down. Cfengine looks for the first filesystem matching a given binary server when expanding the variable @code{$(binserver)}, so sometimes the ordering of filesystems matters.} This list can be accessed in editfiles, to allow straightforward configuration of the automounter, using the command @code{AutomountDirectResources}. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node processes, packages, mountables, Cfagent reference @section processes Using the processes facility, you can test for the existence of processes, signal (kill) processes and optionally restart them again. Cfengine opens a pipe from the system ps command and searches through the output from this command using regular expressions to match the lines of output from @samp{ps}. The regular expression does not have to be an exact match, only a substring of the process line. The form of a process command is @cartouche @w{} @smallexample processes: @var{class}:: @var{"quoted regular expression"} restart @var{"shell command"} useshell=@b{true}/@var{false/dumb} owner=@var{restart-uid} group=@var{restart-gid} chroot=@var{directory} chdir=@var{directory} umask=@var{mask} signal=@var{signal name} matches=@var{number} define=@var{classlist} elsedefine=@var{classlist} action=@b{signal}@var{/do/warn/bymatch} include=@var{literal} exclude=@var{literal} filter=@var{filter_name} syslog=@var{true/on}/@var{false/off} inform=@var{true/on}/@var{false/off} audit=@var{true/on}/@var{false/off} ifelapsed=@var{mins} expireafter=@var{mins} SetOptionString @var{"quoted option string"} @end smallexample @end cartouche @cindex umask By default, the options sent to ps are "-aux" for BSD systems and "-ef" for System V. You can use the @code{SetOptionString} command to redefine the option string. Cfengine assumes only that the first identifiable number on each line is the process identifier for the processes, so you must not choose options for ps which change this basic requirement (this is not a problem in practice). Cfengine reads the output of the ps-command normally only once, and searches through it in memory. The process table is only re-consulted if @code{SetOptionString} is called. The options have the following meanings: @table @code @item signal=@var{signal name} This option defines the name of a signal which is to be sent to all processes matching the quoted regular expression. If this option is omitted, no signal is sent. The signal names have the usual meanings. The full list, with largely standardized meanings, is @smallexample hup 1 hang-up int 2 interrupt quit 3 quit ill 4 illegal instruction trap 5 trace trap iot 6 iot instruction emt 7 emt instruction fpe 8 floating point exception kill 9 kill signal bus 10 bus error segv 11 segmentation fault sys 12 bad argument to system call pipe 13 write to non existent pipe alrm 14 alarm clock term 15 software termination signal urg 16 urgent condition on I/O channel stop 17 stop signal (not from tty) tstp 18 stop from tty cont 19 continue chld 20 to parent on child exit/stop gttin 21 to readers pgrp upon background tty read gttou 22 like TTIN for output if (tp->t_local<OSTOP) io 23 input/output possible signal xcpu 24 exceeded CPU time limit xfsz 25 exceeded file size limit vtalrm 26 virtual time alarm prof 27 profiling time alarm winch 28 window changed lost 29 resource lost (eg, record-lock lost) usr1 30 user defined signal 1 usr2 31 user defined signal 2 @end smallexample @noindent Note that cfengine will not attempt to signal or restart processes 0 to 3 on any system since such an attempt could bring down the system. The only exception is that the hangup (hup) signal may be sent to process 1 (init) which normally forces init to reread its terminal configuration files. @cindex Processes, 0 to 3 @item restart @var{"shell command"} Note the syntax: there is no equals sign here. If the keyword `restart' appears, then the next quoted string is interpreted as a shell command which is to be executed after any signals have been sent. This command is only issued if the number of processes matching the specified regular expression is zero, or if the signal sent was signal 9 (sigkill) or 15 (sigterm) , i.e. the normal termination signals. This could be used to restart a daemon for instance. Cfengine executes this command and @emph{waits} for its completion so you should normally only use this feature to execute non-blocking commands, such as daemons which dissociate themselves from the I/O stream and place themselves in the background. Some unices leave a hanging pipe on restart (they never manage to detect the end of file condition). This occurs on POSIX.1 and SVR4 popen calls which use wait4. For some reason they fail to find and end-of-file for an exiting child process and go into a deadlock trying to read from an already dead process. This leaves a zombie behind (the parent daemon process which forked and was supposed to exit) though the child continues. A way around this is to use a wrapper script which prints the line "cfengine-die" to STDOUT after restarting the process. This causes cfengine to close the pipe forcibly and continue. @cindex Deadlock zombie bug in restart @cindex Restart zombie deadlock bug Cfengine places a timeout on the restart process and attempts to clean up zombies, but you should be aware of this possibility. @cindex Setting uid on restarted processes @item owner=,group= Sets the process uid and gid (setuid,gid) for processes which are restarted. This applies only to cfengine run by root. @item chroot Changes the process root directory of the restarted process, creating a `sandbox' which the process cannot escape from. Best used together with a change of owner, since a root process can break out of such a confinement in principle. @item chdir Change the current working directory of the restarted process. @item useshell=@var{true/false/dumb} When restarting processes, cfengine normally uses a shell to interpret and execute the restart command. This has inherent security problems associated with it. If you set this option to false, cfengine executes restart commands without using a shell. This is recommended, but it does mean that you cannot use any shell operators or features in the restart command-line. Some programs (like cron) do not handle I/O properly when they fork their daemon parts, this causes a zombie process and normally hangs cfengine. By choosing the value `dumb' for this, cfengine ignores all output from a program and does not use a startup shell. This prevents programs like cron from hanging cfengine. @item matches=@var{number} This option may be used to set a maximum, minimum or exact number of matches. If cfengine doesn't find a number of matches to the regular expression which is in accordance with this value it signals a warning. The @samp{<}, @samp{>} symbols are used to specify upper and lower limits. For example, @smallexample matches=>6 # warn number of matches is greater than or equal to 6 matches=1 # warn if not exactly 1 matching process matches=<2 # warn if there are less than or equal to 2 matching processes @end smallexample @cindex Processes, counting @item include=@var{literal} Items listed as includes provide an extra level of selection after the regular expression matches have been expanded. If you include one include option, then only lines containing one or more of the literal strings or wildcards will be matched. @item exclude=@var{literal} Process lines containing literal strings or wildcards in exclude statements are not matched. Excludes are processed after regular expression matching and after includes. @item define=@var{classlist} The colon, comma or dot separated list of classes becomes activated if the number of regular expression matches is non-zero. @item elsedefine=@var{classlist} The colon, comma or dot separated list of classes becomes activated if the number of regular expression matches is zero. @vindex bymatch @vindex signal @item action=@var{signal/do/warn/bymatch} The default value of this option is to silently send a signal (if one was defined using the @code{signal} option) to matching processes. This is equivalent to setting the value of this parameter to @samp{signal} or @samp{do}. If you set this option to @samp{warn}, cfengine sends no signal, but prints a message detailing the processes which match the regular expression. If the option is set to @code{bymatch}, then signals are only sent to the processes if the matches criteria fail. @cindex Processes, checking existence of @cindex Processes, signalling @end table Here is an example script which sends the hang-up signal to cron, forcing it to reread its crontab files: @smallexample processes: "cron" signal=hup @end smallexample @noindent Here is a second example which may be used to restart the nameservice on a Solaris system: @smallexample processes: solaris:: "named" signal=kill restart "/usr/sbin/in.named" @end smallexample @noindent A more complex match could be used to look for processes belonging to a particular user. Here is a script which kills ftp related processes belonging to a particular user who is known to spend the whole day FTP-ing files: @smallexample control: actionsequence = ( processes ) # # Set a kill signal here for convenience # sig = ( kill ) # # Better not find that dumpster here! # matches = ( 1 ) processes: # # Look for Johnny Mnemonic trying to dump his head, user = jmnemon # ".*jmnemon.*ftp.*" signal=$(sig) matches=<$(matches) action=$(do) # No mercy! @end smallexample @noindent The regular expression @samp{.*} matches any number of characters, so this command searches for a line containing both the username and something to do with ftp and sends these processes the kill signal. You can arrange for signals to be sent, only if the number of matches fails the test. The @code{action=bymatch} option is used for this. For instance, to kill process `XXX' only if the number of matches is greater than 20, one would write: @smallexample processes: "XXX" matches=<20 action=bymatch signal=kill @end smallexample See also filters @xref{filters}, for more complex searches. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node packages, rename, processes, Cfagent reference @section Packages @cindex packages @cindex Checking for installed packages The packages action allows you to check for the existance of packages on the system, as determined by the package database you select. Optionally, if a package install command was specified, the package can be installed if it is not there. This operation is set up such that it tries not to make assumptions about the package manager in use. For example, it should be possible to use RPM on a Solaris box. The syntax summary is: @cartouche @w{} @smallexample packages: @var{class}:: @var{package-name} pkgmgr=@b{none}/@var{rpm/dpkg/sun/aix/portage/freebsd} cmp=@b{eq}/@var{lt/gt/ge/le/ne} version=@var{version-string} define=@var{class-list}(,:.) elsedefine=@var{class-list}(,:.) action=@b{none}/@var{install/remove/upgrade/fix} ifelapsed=@var{mins} expireafter=@var{mins} audit=@var{true/on}/@var{false/off} inform=@var{true/on}/@var{false/off} EXAMPLES: packages: # install newpackage 1.10 if newpackage 1.0 or greater isn't installed newpackage-1.10 action=install cmp=ge version=1.0 # upgrade any installed versions of compromised to at least 1.2 compromised-1.2 action=upgrade version=1.2 cmp=le # Make sure that version 1.2 is installed compromised-1.2 action=fix version=1.2 cmp=le # remove any version of useless useless action=remove version=0.1 cmp=ge @end smallexample @end cartouche @table @code @item action @vindex action= Determines the action taken if the comparison matches. @itemize @bullet @item @code{install} Install this package if the version comparison does not match. @item @code{upgrade} Upgrade this package if the version comparison does match. @item @code{fix} Install or Upgrade this package if the version comparison does match. @item @code{remove} Uninstall this package if the version comparison does match. @end itemize @item cmp @vindex cmp= Determines how the version of the installed package will be compared to that specified by the @code{version} attribute. Possible values include: @itemize @bullet @item @code{eq} The version installed must be equal to @code{version} @item @code{lt} The version installed must be less than @code{version} @item @code{gt} The version installed must be greater than @code{version} @item @code{le} The version installed must be less than or equal to @code{version} @item @code{ge} The version installed must be creater than or equal to @code{version} @item @code{ne} The version installed must not be equal to @code{version} @end itemize The default value for this attribute is @code{eq}. Note that @code{cmp} is used differently for install versus upgrade, fix and remove. The action is performed when false for install, but when true for upgrade, fix or remove. @item version @vindex version= Specifies the package manager specific version string to match. If this is not specified, then any version matches, and the value of the @code{cmp} attribute is ignored. See the allowed values of @code{pkgmgr} below for an explation of how each package manager will interpret this. @item pkgmgr @vindex pkgmgr= Selects the package manager database to query. This defaults to either the value of the @code{DefaultPkgMgr} variable, or if that is not set, there is no default. In that case, no checking will be done unless @code{pkgmgr} is set explicitly for each package. Note that the default value '@samp{none}' listed is merely a pseudo-value, and cannot actually be used, since it would make no sense anyway. Each package manager will interpret the @code{version} and @code{cmp} attributes in its own way. For example, when you use @code{pkgmgr=rpm}, the comparison will be done with the same rules that RPM use if it were not being run through cfengine. Freebsd actually invokes the standard system utility to do the comparisons for it, etc. Currently, the following package managers are supported: @table @code @item rpm @cindex RPM Database Queries This uses the rpm command, which cfengine expects to find as @file{/bin/rpm} to query the machine's RPM database. The @code{rpm} check assumes that you are using a version of RPM that understands the concept of an epoch, which means that you will want to use RPM version 3.0.3 or greater. Versions as early as 2.5.6 may work, but it is doubtful. If multiple packages of the same name are installed (i.e. kernel), then the check considers the package to be installed at the specified version if @b{at least one} of them satisifies the criteria specified by @code{cmp} and @code{version}. The format of a RPM version string is: [epoch:]version[-release]. The version[-release] can be seen by simply running: @command{rpm -q }. In order to see the epoch, you must use a query format, like this: @command{rpm -q --queryformat "%@{EPOCH@}:%@{VERSION@}-%@{RELEASE@}\n" }. Most packages do not have an epoch, and will print @samp{(none)} in the epoch space. In recent incarnations of RPM, the absense of an epoch is interpreted as 0. This is also how cfengine will interpret it. @emph{Be careful with this. If the installed version of a package has an epoch greater than 0, and you do not specify the epoch, unexpected results may happen.} For example, if you have a package installed, @samp{foo-1:2.0-1}, and you specify a @code{version=3.0-1} and a @code{cmp=gt}, the check will be true, because the installed version has an epoch of 1, and you did not specify an epoch, which implies you wanted an epoch of 0. The rule here is basically to always check the epoch of the package you really want, and specify it. It may take a few extra extra seconds to check, but it will save you lots of headaches later. @item portage @cindex Gentoo Package Database Queries This uses the emerge command to install packages on a Gentoo Linux system. The `portage' Python module is used to query the system and find installed packages. The @i{package_name} and @i{version} support any package that conforms to the Gentoo package naming specification @url{http://www.gentoo.org/proj/en/devrel/handbook/handbook.xml?part=2&chap=1#doc_chap2_sect2}, and even most of those in the Portage tree that do not. Because Gentoo package atoms are flexible, you can use the name of the package, along with a @i{version} and the @i{cmp} cfengine logic, or you can put the comparison operator and version in the @i{package_name} field and leave out the @i{cmp} operator. Because cfengine builds the install string out of the package name, and ignores the @i{version} you were comparing against, using a package atom with a version is the only way to have a specific version emerged. @smallexample packages: any:: # if the version of tar is less than 1.16-r2, # then the *latest* version of tar will be installed: app-arch/tar cmp=ge version=1.16-r2 action=install # This is equivalent, but uses the package atom to # define the version comparison: >=app-arch/tar-1.16-r2 action=install @end smallexample @item dpkg @cindex Debian Package Database Queries Please document me! @item sun @cindex Sun Package Database Queries Please document me! @item freebsd @cindex FreeBSD Package Database Queries FreeBSD has fully working install/upgrade/delete management for packages. You can either get the latest version from a package repository, or define the explicit version to install. @smallexample # install new package from FreeBSD ports tree control: DefaultPkgMgr = ( freebsd ) FreeBSDInstallCommand = ( "/usr/sbin/pkg_add -r %s" ) packages: bsdsar action=install # install a specific version from a local repository control: DefaultPkgMgr = ( freebsd ) FreeBSDInstallCommand = ( "/usr/sbin/pkg_add http://server/path/%s" ) packages: bsdsar-1.10_2 action=install @end smallexample Note that specifying the version of the package that is part of the freebsd package filename is required if not using "-r" mode. It does not use this version for comparison, just for the package filename to install. You can also backgrade if you know that 1.2 is bad for instance. @smallexample packages: bsdsar-1.10_2 action=upgrade version=1.10_2 cmp=gt @end smallexample The only gotcha about FreeBSD installation is trying to specify the package source location. Due to the unfortunate fact that freebsd doesn't provide a command line option -- only an environment variable -- for specifying the source repository, you have a few options. Get it from the main FreeBSD binary package home: @smallexample FreeBSDInstallCommand = ( "/usr/sbin/pkg_add -r %s" ) @end smallexample Get it from a mounted directory or http server @smallexample FreeBSDInstallCommand = ( "/usr/sbin/pkg_add /nfs/packages/%s" ) FreeBSDInstallCommand = ( "/usr/sbin/pkg_add http://server/path/%s" ) @end smallexample Or write a script that tells pkg_add where to find it, like so: @smallexample FreeBSDInstallCommand = ( "/var/cfengine/packages/pkginstall %s" ) @end smallexample such as @smallexample #!/bin/sh PACKAGESITE=http://my.local.repository/packages/ export PACKAGESITE /usr/sbin/pkg_add -r $* @end smallexample @end table @item define Specifies the list of classes to define if the specified package/version was installed (prior to actions taken if any) @item elsedefine Specifies the list of classes to define if the specified package/version was not installed (prior to actions taken if any) @item action Specifies whether the packages should actually do anything about the situation it finds. The default for this is to do nothing. For @code{install}, the action will be taken if the comparison returns false. For @code{upgrade} and @code{remove}, the action will be taken if the comparison returns false. The classes in @code{define} and @code{elsedefine} will always be defined, as applicable, regardless of the action specified. @table @code @item install Installs the package using the command associated with the selected package manager, if it is not currently on the system at the requested version, as follows: @itemize @bullet @item RPM - RPMInstallCommand @item DPKG - DPKGInstallCommand @item SUN - SUNInstallCommand @item Gentoo - PortageInstallCommand @item FreeBSD - FreeBSDInstallCommand @end itemize Each variable is of the format: @smallexample FOOInstallCommand = ( "/usr/bin/foo --args %s --more-args" ) @end smallexample The ---args are of course optional. For FreeBSD and Sun, the %s is replaced with the package name that was checked, and found to not be installed. For all other package managers the %s can have a space separated list of package names. @item upgrade Upgrades the package using the commands associated with the selected package manager, first removal of the old package then installation of the new package. Note that on some package managers this action is unnecessary because the package manager will "do the right thing" when told to install a newer version. @itemize @bullet @item FreeBSD - FreeBSDRemoveCommand followed by FreeBSDInstallCommand Portage - Upgrade is generally not necessary since emerge will do the upgrade for you. @end itemize @item remove Removes the package(s) using the command associated with the selected package manager, if a matching package is found on the system, as follows: @smallexample FOORemoveCommand = ( "/usr/bin/foo --args %s --more-args" ) @end smallexample The ---args are of course optional. The %s is replaced with a space-separated list of the package names that were checked, and found to be installed. @end table @end table @noindent NOTE: classes are defined according to the result of the check, not any action performed as a result of that check. In otherwords, if for example you have a situation where a package is not installed, and the action= is set to install, the classes in @code{elsedefine} will be defined @b{regardless} of whether or not the install was successful. Assuming the package installed, the next run of cfagent will pick up that fact. This has to be done since the package installs are batched, so there is no reliable way to know if a given package was installed successfully. @noindent Examples: @smallexample packages: redhat_8_0:: m4 version=0:1.4.1-11 cmp=eq pkgmgr=rpm elsedefine=needsm4 @end smallexample @noindent In this first example, we are looking for the m4 package at exactly version 0:1.4.1-11. The installed m4 package on a redhat_8_0 box has no epoch which is the same as zero. Specifying it will keep you out of trouble. This check will cause @code{needsm4} to be defined if the exact version of m4 specified is not installed. @smallexample control: redhat:; DefaultPkgMgr = ( rpm ) gentoo:: DefaultPkgMgr = ( portage ) packages: redhat_8_0:: make version=0:4.5-2 cmp=ge define=hasmake elsedefine=needsmake @end smallexample @noindent In the second example, we use the DefaultPkgMgr variable to set the default for the @code{pkgmgr} attribute to @code{rpm}. The actual version of make installed on recent redhat_8_0 machine is 1:3.79.1-14. Since the check is for greater than or equal to this version, the hasmake class will be defined. @smallexample control: redhat:; DefaultPkgMgr = ( rpm ) RPMInstallCommand = ( "/usr/sbin/up2date %s" ) packages: redhat_8_0:: make define=hasmake elsedefine=needsmake action=install @end smallexample @noindent This example is much like the second example, except that if the package is not installed, cfengine will attempt to install it using the command in RPMInstallCommand, replacing the %s with the package name, @code{make}. If there were multiple packages specified in this way, the package installation would occur at the end of the package checks, and one command would be run, with %s replaced with a list of all package names. In this example we chose not to use a version spec, but it is allowed, and as always, is optional. @noindent NOTE here that if make was not installed when the check is made, @code{needsmake} is defined, regardless of whether or not the install succeeds. If the install is successful, the next cfagent run will define @code{hasmake}. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node rename, required, packages, Cfagent reference @section rename As of version 2.1.0 rename is a synonym for disable, @xref{disable}. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node required, resolve, rename, Cfagent reference @section required This is a synonym for disks, @xref{disks}. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node resolve, scli, required, Cfagent reference @section resolve @cindex DNS @cindex Resolver configuration @cindex resolv.conf @vindex resolve The file @code{/etc/resolv.conf} specifies the default nameserver for each host, as well as the local domain name. This file can also contain other information, but these are the only two things cfengine currently cares about. In specifying nameservers you should use the dotted numerical form of the IP addresses since your system may not understand the text form if it is not correctly configured. You may list as many nameservers as you wish, with the default server at the top of the list. The resolver normally ignores entries if you add more than three. The statement: @smallexample resolve: mygroup:: 129.240.22.35 129.240.22.222 129.240.2.3 @end smallexample @noindent declares a list of nameservers for hosts in the group or class @code{mygroup}. When you add the @code{resolve} command to the @code{actionsequence}, this declaration together with the @code{domain} variable (set here to @code{uio.no}) results in a @code{/etc/resolv.conf} file of the form: @w{} @smallexample domain uio.no nameserver 129.240.22.35 nameserver 129.240.22.222 nameserver 129.240.2.3 @end smallexample @noindent Note that the @code{resolve} action does not delete anything from the file @code{/etc/resolv.conf} unless the @code{EmptyResolvConf} variable is set to 'true' . It adds nameservers which do not previously exist and reorders the lines of servers which do exist. As of version 1.3.11, you may use a quoted string to add non-nameserver lines to this file. For example: @smallexample resolve: mygroup:: 129.240.22.35 129.240.22.222 "# Comment line" "order bind, files" @end smallexample @noindent If the line begins with a non-numeric character, the word `nameserver' is not added to the line. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node scli, shellcommands, resolve, Cfagent reference @section scli SCLI is an SNMP command line interpreter written by J@"urgen Sch@"onwaelder of the Jacobs University of Bremen. It is a command interpreter used to simplify the interaction with SNMP enabled devices. SNMP is a stateless, UDP based network protocol for communicating with supporting hardware. The SNMP model does not fit very comfortably with the cfengine ``responsibility for self'' paradigm, but at some level SCLI can be viewed as just another form of interpreted script. SCLI adds a level of user friendliness and stateful behaviour to SNMP through its shell-like interface. This turns out to be both a help and a hindrance to cfagent. The intermingling of stateful and stateless processes in the dialogue between cfengine and scli makes their integration non-trivial. Several compromises have to be made to aid usability and these could lead to difficulties in the practical use of the tools later. The scli section of a cfagent configuration is a single script. The lines are passed as a collective object to the scli interpreter, not line-by-line as in other cases. The basic approach is to open a pipe for the reading and writing of dialogue with the interpreter. There are some limitations to Unix pipes however, in particular input and output are separated which makes per-transaction error control essentially impossible. A work-around for this has been used in the test phase. The cfengine interface is a special case of the @code{shellcommands} interface, passing commands to SCLI instead of to @file{/bin/sh}. The command options are the same as those below for @code{shellcommands}. @cartouche @w{} @smallexample shellcommands: @var{class}:: "@var{scli-string}" @var{shellcommand options} "@var{scli-string}" @end smallexample @end cartouche @vindex scli command interpreter @vindex SNMP @i{This integration was funded by the IST-EMANICS Network of Excellence in Network and Service Management, of which Oslo University College and the Jacobs University of Bremen are members}. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node shellcommands, strategies, scli, Cfagent reference @section shellcommands Cfengine focuses on fairly simple-minded tasks in order to be as general as possible. In many cases, you will therefore want to write a script to do something special on your system. You can still take advantage of the classes you have defined by executing these scripts or shell commands from this section. The syntax is simply to quote the command you wish to be executed. @cartouche @w{} @smallexample shellcommands: @var{class}:: "@var{command-string}" timeout=@var{seconds} useshell=@b{true}@var{/false} umask=@var{octal number} owner=@var{uid} group=@var{gid} background=@b{false}@var{/true} chdir=@var{directory} chroot=@var{directory} preview=@var{true}/@b{false} inform=@b{false}@var{/true} audit=@var{true/on}/@var{false/off} noabspath=@b{false}@var{/true} ifelapsed=@var{mins} expireafter=@var{mins} define=@var{class-list} elsedefine=@var{class-list} @end smallexample @end cartouche @cindex umask @noindent @table @code @item @var{command-string} This is the command to be executed. @item @var{timeout} If you set the optional @var{timeout} parameter, then cfengine will abort the specified shellcommand if it exceeds the given time-limit (specified in seconds). This can be useful for avoiding hung programs caused by hung network connections, etc. Timeouts are generated by alarm interrupts within a single agent. This can be contrasted with @code{expireafter} in which a second agent is required to interrupt a command. @cindex @code{timeout=} in shellcommands @mbindex How can I set a timeout for a shell command? @mbindex How can I avoid hanging shellcommands? @mbindex Hanging commands, timeouts @item @var{useshell} Some program lines, especially those that do not use any shell-specific capabilities (such as redirection and wildcard expansion) can be run without the shell. This is typically more secure, as the command line is not altered by the user or by the system. It is also faster, as the shell does not have to be spawned in order to run the given command. Use the @var{useshell} parameter to tell cfengine to not use the shell to run this shellcommand. @item @var{umask} The umask affects the permissions given to a file created by this shellcommand. The umask specifies, specifically, the permissions that are to be taken away. @item @var{owner} @item @var{group} The user and group ID's of the process can be set (using the @var{owner} and @var{group} parameters respectively) to restrict the permissions of the shellcommand. This can only be done if cfengine is executed by root; otherwise, the user and group will remain that of the the user who started cfengine. @item @var{background} Run this command in the background if this is specified true. This will make cfengine run faster, but no tests can be made (at least directly) on the results of this command. Also when jobs are backgrounded, the output in verbose mode can be somewhat erratic due to the unsychnronized streams. @item @var{chdir} Change to the specified directory before running this command. @item @var{chroot} The @code{chroot} option changes the process root directory of the command, creating a `sandbox' which the process cannot escape from. Best used together with a change of owner (using the @code{owner} parameter), since a root process can break out of a chrooted environment. @item @var{preview} The @code{preview} option means that the shellcommand will also be executed during the @w{@code{--dry-run}} (@code{-n}) options. This allows cfengine to be more aware of the results of scripts which define classes. This option should be used with care. Scripts should conform to the protocol of not executing unnecessary commands when the classes @code{opt_dry_run} is defined. @cindex Previewing shellcommands @cindex @code{--dry-run} option @item @var{inform} @item @var{noabspath} Normally, cfagent requires the command string to begin with a @samp{/} since it is dangerous to rely on an implicit path. However, sometimes it it is appropriate to override this. This behavior can be overridden using the @var{noabspath} parameter. @cindex noabspath @vindex noabspath @mbindex Shellcommands must start with absolute path @mbindex Absolute path and shellcommands @item @var{ifelapsed} The shellcommand specified will not be run unless the specified amount of time (in minutes) has elapsed since the command was previously run. @item @var{expireafter} If this amount of time (in minutes) has elapsed since the command started, then the command is aborted by a second agent that is patrolling the system. @item @var{define} Define the specified classes if the command finishes successfully. @item @var{elsedefine} Define the specified classes if the command does not finish successfully. @end table Variable substitution works within the strings. Here are some examples. @smallexample shellcommands: sun4:: "/usr/lib/find/updatedb" AllHomeServers.Sunday:: "/dir/noseyparker /$(site)/$(host)/u1 $(sysadm) nomail" AllBinaryServers.sun4.Saturday:: "/usr/etc/catman -w -M /usr/local/man" "/usr/etc/catman -w -M /usr/local/X11R5/man" "/usr/etc/catman -w -M /usr/man" "/usr/etc/catman -w -M /usr/local/gnu/man" @end smallexample @noindent If you need to write more advanced scripts which make detailed use of the classes defined by cfengine, use the @code{$(allclasses)} variable to send a complete list of classes to your script. An enviornment variable, CFALLCLASSES, is set and is in the format @smallexample CFALLCLASSES=class1:class2:class3... @end smallexample @noindent This variable is kept up-to-date at any given time with only the classes which are defined. The command line option @samp{-u} or @samp{--use-env} can be used to define an environment variable which will be inherited by all scripts and contains the same information. This is not the standard approach, since some systems cannot cope with this rapid change of environment and generate a Bus Error. @cindex CFALLCLASSES @cindex allclasses variable @cindex Scripts and class information @cindex Class information, passing to scripts Commands can be iterated over variable lists, provided there is at least one space between each variable. For example: @smallexample control: actionsequence = ( shellcommands ) var1 = ( a:b:c ) var2 = ( x:y:z ) shellcommands: "/bin/echo $(var1) $(var2)" @end smallexample @noindent This iterates over all values of the list variables. @xref{Iteration over lists}. @cindex Iterating over lists in shellcommands If you are iterating over a list, the time limit (in seconds) which is specified in the @var{timeout} parameter applies to each separate iteration, not to the sum total of all the iterations. @cindex Timeouts during iterations @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node strategies, tidy, shellcommands, Cfagent reference @section strategies @cindex Gaming stratgies @cindex Strategy, random @vindex Randomizing strategy Strategies (introduced in cfengine version 2.0) are a way of picking from a set of classes randomly. Each class is a possible course of action. A strategy group (of classes) is defined as follows: @smallexample strategies: @{ my_strategy_alias class1: "2" class2: "3" class3: "$(value)" class4: "6" class5: "1" @} tidy: class1.Hr00:: /home pat=*.mp3 age=0 class2.Hr02:: /home pat=*.wav age=0 @end smallexample The idea here is to randomly pick from a selected set of classes. Specifically, each strategy is a class which is defined with a certain probability. An integer weight is provided in quotes to represent the probability weight of the associated class. When cfengine is run, it randomly picks one of the classes from each strategy. Using strategies, you can choose different ways of configuring or protecting a system, at random, thus confounding environmental attempts to break into the system. Note that each strategy has a formal name (such as @samp{my_strategy_alias} in the example), but this name is not used to attach a strategy to an action the same way that filters or ACLs are. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node tidy, unmount, strategies, Cfagent reference @section tidy @cindex Tidying files @cindex Deleting files @vindex tidy The tidy function is used to delete (remove permanently) unwanted files from a system. It is useful for tidying up in @code{/tmp} or cleaning out @code{core} files from users' home directories. The form of an entry is: @cartouche @w{} @smallexample tidy: @var{class}:: @var{/directory} pattern/include=@var{wildcard} recurse=@var{number/inf} age=@var{days} size=@var{number/empty} type=@var{ctime/mtime/}@b{atime} dirlinks=@var{keep/tidy/delete} rmdirs=@var{[true/all]/[@b{false/none}]/sub} links=@b{stop/keep}@var{/traverse/tidy} compress=@var{true/on}/@b{false/off} define=@var{classlist} elsedefine=@var{classlist} syslog=@var{true/on}/@var{false/off} inform=@var{true/on}/@var{false/off} audit=@var{true/on}/@var{false/off} ifelapsed=@var{mins} expireafter=@var{mins} filter=@var{filter alias} ignore=@var{pattern} exclude=@var{pattern} xdev=@var{true/on}/@b{false/off} @end smallexample @end cartouche @noindent Note that, each of the options below can be written in either upper or lower case and abbreviated by any unique abbreviation. @vindex p= @vindex pattern @vindex a= @vindex age @vindex r= @vindex recurse @cindex compress @cindex Compression during tidy @table @code @item @var{/directory} This is the directory name to directories which mark the start of a search for files matching certain wildcards. The wildcard @code{home} may be used instead of an explicit directory, in which case cfengine iterates over all home directories. It is compulsory to specify a directory. @item pattern=@var{wildcard} or include=@var{wildcard} A wildcard or filename to match the files you wish to be deleted. The pattern may contain the special symbols @samp{?} which matches a single character and @samp{*} which matches any number of characters as in the shell. These two options are synonymous, as of version 2.0.x. Note that, this pattern is processed as a filter before any other filter and, for safety reasons, it defaults to nothing. Thus, if you want to use a filter to select the files, you should set @samp{pattern=*}, else the filter will not see any files at all. @cindex pattern= and filtering @vindex Wildcards @item exclude=@var{wildcard} This does not work for the home directive; use the global ignore list for this. @item ignore=@var{wildcard} This does not work for the home directive; use the global ignore list for this. @item recurse=@var{number/inf} This specifier tells cfengine whether or not to recurse into subdirectories. If the value is zero, only the named file or directory is affected. If the value is 1, it will open at most one level of subdirectory and affect the files within this scope. If the value is @code{inf} then cfengine opens all subdirectories and files beginning from the specified filename. @xref{Recursion}. @item age=@var{days} The age of a file in days represents a minimum @emph{access} time elapsed before the file will be deleted. In other word a file will be deleted if it has not been accessed for @var{days} days. @item links=@var{stop/traverse/tidy} Normally cfengine does not descend into subdirectories which are pointed to by symbolic links. If you wish to force it to do so (without using the @code{-l} command line option) you may give this option the value @code{true}, or @code{traverse}, or @code{follow}. To specify no recursion you set the value @code{false} or @code{stop}. @cindex Links, traversing in searches @vindex -l @cindex -l option Note that the value set here in the cfengine program @emph{always overrides} the value set by the @code{-l} command line option, so you can protect certain actions from this command line option by specifying a negative value here. If you specify no value here, the behaviour is determined by what you specify on the command line. The value @code{links=tidy} has the same effect as the @samp{-L} command line option except that here it may be specified per item rather than globally. Setting this value causes links which point to non-existent files to be deleted. This feature will not work on commands with the @samp{home} wildcard feature. If you want to clean up old links you should either user a @code{files} command or the command line option which sets the tidy feature globally. @cindex Deleting stale links @cindex Links, deleting stale @item size=>@var{number/empty} Old syntax @code{size=@var{number/empty}}. The value of this parameter decides the size of files to be deleted. Files larger than this value will be deleted if they also are older than the time specified in @code{age}. The default size is zero so that any file which gets matched by another critereon is deleted. However, if you want to single out only totally empty files, the @code{empty} may be used. With this option only empty files, nevery files with anything in them, will be deleted, if older than @code{age}. By default, the filesizes are in kilobytes, but kilobytes and megabytes may also be specified by appending b,k,m to the numbers. Only the first character after the number is significant so you may write the numbers however it might be convenient, e.g. @kbd{14k}, @kbd{14kB}, @kbd{14kilobytes}, the same as for @code{disable}. @cindex Specifying file sizes @cindex File sizes, specifying @cindex Megabytes, filesize unit @cindex Kilobyte, filesize unit @cindex Empty files @cindex Tidying empty files @item type=@var{ctime/mtime/atime} This value is used to set the type of time comparison made using @code{age}. The default is to compare access times (atime) or the last time the file was read. A comparison by modification time (mtime) uses the last time the contents of the file was changed. The ctime parameter is the last time the contents, owner or permissions of the file were changed. Note that on directories, mtime is always used for comparisons, since the very act of stat'ing alters atime and makes this comparison meaningless. @item dirlinks=@var{keep/tidy/delete} This value is used to decide whether cfengine will delete links which point to directories. The default value is to keep the links. Note that, if the @code{travlinks} option is switched on, cfengine will not tidy or delete links which point to directories, instead it follows them into the subdirectory. This is a supplement to the @code{rmdirs} option. You need both to make links to directories disappear. Note that, even if @code{travlinks} is set to true, cfagent will not follow symbolic links that are not owned by the agent user ID; this is to prevent link race attacks, in which users with write access could divert the agent to another part of the filesystem, @cindex Security, link races and travlinks @cindex travlinks @cindex Tidy by ctime, mtime, atime @cindex ctime tidies @cindex mtime tidies @cindex atime tidies @item rmdirs=@var{true/false/all/sub} Normally cfengine will not delete directories. If this option is set to `true' then cfengine will delete any directories which are @emph{empty}. Non-empty directories will not be touched and no message will be given unless in verbose mode. Note that this option overrides the above option @code{dirlinks}, so that even links which point to empty directories will be removed. If this is set to `sub' then the topmost directory will not be removed, only sub-directories. @cindex rmdirs @cindex Removing directories @cindex Deleting directories @cindex Directories, deleting @item define=@var{classlist} The colon, comma or dot separated list of classes becomes defined if any file matching the specified pattern is deleted. @item xdev Prevents cfengine from descending into file systems that are not on the same device as the root of the rescurion path. @cindex xdev @end table Take a look at the following example: @smallexample tidy: AllHomeServers:: home pattern=core R=inf age=0 home pattern=*~ R=inf age=7 home pattern=#* R=inf age=30 any:: /tmp/ pat=* R=inf age=1 / pat=core R=2 age=0 /etc pat=hosts.equiv r=0 age=0 @end smallexample In the first example, all hosts in the group @code{AllHomeServers} iterate a search over all user home directories looking for `core' files (older than zero days) and @code{emacs} backup files @samp{*~}, @samp{#*} older than seven days. The default values for these options are the empty string for the wildcard pattern, zero for the recursion and a specification of the age is compulsory. @cindex .cfengine.rm @vindex .cfengine.rm When cfengine tidies users' home directories, it keeps a log of all the files it deletes each time it is run. This means that, in case of accidents, the user can see that the file has been deleted and restore it from backup. The log file is called @code{.cfengine.rm} and it is placed in the home directory of each user. The file is owned by root, but is readable to the user concerned. @page @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node unmount, , tidy, Cfagent reference @section unmount @cindex Unmounting filesystems @vindex unmount The unmount function unmounts non-required filesystems and removes the appropriate entry from the filesystem table (@code{/etc/fstab} or equivalent). The syntax is simply @cartouche @w{} @smallexample unmount: @var{class}:: @var{mounthost}:@var{filesystem} deletedir=@var{@b{true}/false} deletefstab=@var{@b{true}/false} force=@var{true/@b{false}} ifelapsed=@var{mins} expireafter=@var{mins} @end smallexample @end cartouche @noindent The options allow you to temporarily unmount a directory without actually removing it from the filesystem table. The option @code{force} is not currently implemented and will likely have to be system dependent. For example: @smallexample unmount: physics:: libraryserver:/$(site)/libraryserver/data @end smallexample @noindent If the device is busy then the actual unmount will not take place until it becomes free, or the machine is rebooted. This feature should work on AIX systems, in spite of these machines inherent peculiarities in the form of the filesystem table. Some users do not mount filesystems on a directory of the same name as the source directory. This can lead to confusion. Note, if you have problems removing a mounted filesystem, try using the mountpoint of the filesystem, rather than the name of the filesystem itself, in the unmount command. @c ********************************************************************** @c CHAPTER @c ********************************************************************** @node Cfservd.conf and cfrun reference, Cfexecd reference, Cfagent reference, Top @chapter Cfservd and cfrun reference @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @menu * cfservd control:: * admit grant and deny:: * cfrun:: * Firewalls and NATs:: @end menu The server daemon is controlled by a file called @file{cfservd.conf}. @cindex @file{cfservd.conf} file The syntax of this configuration file is deliberately modelled on cfengine's own configuration file, but despite the similarities, they are separate. You can use @code{groups} and @code{import} in both files to break up files into convenient modules and to import common resources, such as lists of groups. Note that the classes in the @file{cfservd.conf} file do not tell you the classes of host which have access to files and directories, but rather which classes of host pay attention to the access and deny commands when the file is parsed. Authentication is not by class or group but by hostname, like the @file{/etc/exports} file on most Unix systems. The syntax for the file is as follows: @cartouche @w{} @smallexample control: @var{classes}:: domain = ( @var{DNS-domain-name} ) cfrunCommand = ( "@var{script/filename}" ) # Quoted MaxConnections = ( @var{maximum number of forked daemons} ) # ChecksumDatabase = ( @var{filename} ) - deprecated IfElapsed = ( @var{time-in-minutes} ) DenyBadClocks = ( @var{false} ) AllowConnectionsFrom = ( @var{IP numbers} ) DenyConnectionsFrom = ( @var{IP numbers} ) AllowMultipleConnectionsFrom = ( @var{IP numbers} ) TrustKeysFrom = ( @var{IP numbers} ) AllowUsers = ( mark systemuser ) LogAllConnections = ( @var{false/true} ) LogEncryptedTransfers = ( @var{false/true} ) SkipVerify = ( @var{IP numbers} ) DynamicAddresses = ( @var{IP numbers} ) BindToInterface = ( @var{IP number}/@var{hostname} ) HostnameKeys = ( @var{true/false} ) groups: @var{Group definitions} import: @var{Files to import} admit: | grant: @var{classes}:: /@var{file-or-directory} @var{wildcards/hostnames} deny: @var{classes}:: /@var{file-or-directory} @var{wildcards/hostnames} root=@var{hostlist} encrypt=@var{true/on} @end smallexample @end cartouche @cindex Iteration in server rules @cindex cfservd.conf iteration Iteration of variables is allowed, hence: @noindent @w{} @smallexample control: Split = ( " " ) hostlist = ( "10.10.10.1 10.10.10.2 10.10.10.3" ) dirs = ( "bin etc lib" ) base = ( /usr ) ######################################################### admit: $(base)/$(dirs) $(hostlist) @end smallexample results in: @smallexample Path: /usr/bin (encrypt=0) Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root= Path: /usr/etc (encrypt=0) Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root= Path: /usr/lib (encrypt=0) Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root= @end smallexample The file consists of a control section and access information. @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node cfservd control, admit grant and deny, Cfservd.conf and cfrun reference, Cfservd.conf and cfrun reference @section control cfservd @c ........................................... @c SUBSECTION @c ........................................... @menu * IP address ranges:: * AllowConnectionsFrom:: * AllowMultipleConnectionsFrom:: * AllowUsers:: * AutoExecCommand:: * AutoExecInterval:: * BindToInterface in cfservd:: * ChecksumDatabase in cfservd:: * cfrunCommand:: * DenyBadClocks:: * DenyConnectionsFrom:: * cfservd HostnameKeys:: * cfservd IfElapsed:: * LogAllConnections:: * LogEncryptedTransfers:: * MaxConnections:: * TrustKeysFrom:: * DynamicAddresses:: @end menu @c ........................................... @c SUBSECTION @c ........................................... @node IP address ranges, AllowConnectionsFrom, cfservd control, cfservd control @subsection IP address ranges In the access control lists below, host ranges can be specified in a number of ways i) as substrings, ii) as address ranges denoted by the "-" hyphen, or iii) as CIDR (Classless Inter Domain Routing) notation. For example @smallexample 128.39.73 128.39.74.10/23 128.39.74-75.10-22 2001:700:700:3:290:27ff:fea2:4730-4790 2001:700:700:3:290:27ff:fea2:4730/64 @end smallexample In the CIDR notation, the slash followed by a number indicates the netmask, or the number of bits which are common to a group of hosts. Normally, this is connected to a specific subnet, but here it simply represents the number of bits from the left which are fixed for matching; all remaining bits are wildcards. The following forms are equivalent: @smallexample 128.39.74. 128.39.74.10/24 128.39.74.1-254 @end smallexample @c ........................................... @c SUBSECTION @c ........................................... @node AllowConnectionsFrom, AllowMultipleConnectionsFrom, IP address ranges, cfservd control @subsection AllowConnectionsFrom This variable allows a list of numerical IP masks to be specified, which cfservd will allow connections from. If the list is not empty and a host whose IP address is not specified attempts to connect to the daemon, its connection will be closed immediately. This can be used to prevent hanging connection attacks from malicous hosts and other denial of service attacks which would bind thread resources. @smallexample control: AllowConnectionsFrom = ( 128.39.89 192.2.0.10 ) @end smallexample @cindex @code{AllowConnectionsFrom} variable @mbindex Hanging connections attacks @mbindex Denial of service attacks @c ........................................... @c SUBSECTION @c ........................................... @node AllowMultipleConnectionsFrom, AllowUsers, AllowConnectionsFrom, cfservd control @subsection AllowMultipleConnectionsFrom This variable should contain a list of IP wildcards to hosts which are allowed simultaneous sessions on the server. Hosts which are not in this list are allowed to connect only once, i.e. they must terminate and reconnect in order to establish a new session. This is to prevent a possible attacker from opening multiple sockets and never closing them, resulting in a denial of service attack. Hosts IP's can be placed here if they could have overlapping copy sessions (e.g. long backup transfers which can run over time). This prevents the error message "Multiple connections denied/spam shield". @c ........................................... @c SUBSECTION @c ........................................... @node AllowUsers, AutoExecCommand, AllowMultipleConnectionsFrom, cfservd control @subsection AllowUsers This list determines which users are to be allowed to connect to the daemon. Note that there is no way of identifying users except by their public keys. If a malicious asserts their identity, when no public key for the named user is known to the server, then they could spoof the identity of that user. All users who should be allowed to connect need to be here. This applies to use of cfrun. @cindex cfrun, limiting users on server @cindex Key security of users @w{} @smallexample AllowUsers = ( mark root ) @end smallexample In other words, this is a "security by obscurity" first defence against picking up bad keys, when the server is in trust mode, with respect to a host. The attacker must know a valid user name in order to even try their luck entering into a key dialogue. This reduces the probability that spoofing can be successful. The only real defence against spoofing is to make sure that all required public keys are installed in advance, and to switch off trust. @vindex AllowUsers @cindex AllowUsers in cfservd @c ........................................... @c SUBSECTION @c ........................................... @node AutoExecCommand, AutoExecInterval, AllowUsers, cfservd control @subsection AutoExecCommand This variable no longer exists in cfengine version 2. @c ........................................... @c SUBSECTION @c ........................................... @node AutoExecInterval, BindToInterface in cfservd, AutoExecCommand, cfservd control @subsection AutoExecInterval This variable no longer exists in version 2 of cfengine. @cindex @code{AutoExecInterval} variable @c ........................................... @c SUBSECTION @c ........................................... @node BindToInterface in cfservd, ChecksumDatabase in cfservd, AutoExecInterval, cfservd control @subsection BindToInterface in cfservd If this is set to a specific IP address of an IP configured interface, cfservd will listen for connections only on that interface. On Multi-homed hosts this allows one to restrict the traffic to one interface. Note, Unix only allows one or all interfaces to be selected. An interface must be configured with an IP address in order to be bound. @cindex Multihomed hosts @vindex BindToInterface @cindex Binding to one interface only @c ........................................... @c SUBSECTION @c ........................................... @node ChecksumDatabase in cfservd, cfrunCommand, BindToInterface in cfservd, cfservd control @subsection ChecksumDatabase in cfservd (This variable is deprecated as of version 2.1.21. The location of the database will be fixed internally.) This is the path and filename to a database which will cache MD5 checksum values server-side. This optimization is only available if you have the Berkeley database library @samp{libdb} on your system. If this variable is not defined, no database caching will be used and checksum values will be computed directly on request. The utility of this solution is a trade-off between the time it takes to compute the checksum versus the time for a disk-based lookup. @cindex @code{ChecksumDatabase} variable @mbindex MD5 checksums take a long time to compute. @mbindex Checksums take too long to compute. @c ........................................... @c SUBSECTION @c ........................................... @node cfrunCommand, DenyBadClocks, ChecksumDatabase in cfservd, cfservd control @subsection cfrunCommand This string is the command which you would like to be executed remotely by the @code{cfrun} command. Note that you must, in addition, authorize access to this file in the @code{admit} section. The access rule should (as usual) be to the actual file object path, not including any symbolic links. @cindex @code{cfrunCommand} variable @c ........................................... @c SUBSECTION @c ........................................... @node DenyBadClocks, DenyConnectionsFrom, cfrunCommand, cfservd control @subsection DenyBadClocks If this is set to @code{off}, cfservd will not deny access to clients whose clocks are off by more than one hour. The default is to deny access to systems whose clocks differ by more than one hour. This can prevent messages of the form `Can't stat' file when remote copying. @cindex @code{DenyBadClocks} variable @mbindex Can't stat error when remote copying @c ........................................... @c SUBSECTION @c ........................................... @node DenyConnectionsFrom, cfservd HostnameKeys, DenyBadClocks, cfservd control @subsection DenyConnectionsFrom Hosts which are included by the allow-list above can be explicitly denied access using this list. @smallexample control: DenyConnectionsFrom = ( 128.39.89.76 ) # rogue host @end smallexample @cindex @code{DenyConnectionsFrom} variable @c ..................................................... @c SUBSECTION @c ..................................................... @node cfservd HostnameKeys, cfservd IfElapsed, DenyConnectionsFrom, cfservd control @subsection HostnameKeys in cfservd If this variable is set to true/on, it causes cfservd to lookup and store trusted public keys according to their DNS fully qualified host name, instead of using the IP address. This can be useful in environments where hosts do not have fixed IP addresses, but do have fixed hostnames. @smallexample HostnameKeys = ( on ) @end smallexample This method of storing keys is not recommended for sites with fixed IP addresses, since it removes one security barrier from a potential attacker by potentially allowing DNS spoofing. @c ........................................... @c SUBSECTION @c ........................................... @node cfservd IfElapsed, LogAllConnections, cfservd HostnameKeys, cfservd control @subsection IfElapsed in cfservd The @code{IfElapsed} anti-spamming filter is also built into @code{cfservd} so that a remote user cannot even get as far as causing cfengine to parse its input files (which could be used for spamming in itself). The time is in minutes, the default is one hour. @c ........................................... @c SUBSECTION @c ........................................... @node LogAllConnections, LogEncryptedTransfers, cfservd IfElapsed, cfservd control @subsection LogAllConnections If set to true, every successful connection will be logged to syslog. This could be useful for identifying abuses of the service, if the server should come under attack, e.g. a denial of service attack. The IP address can then be excluded from the allowed connections list. @c ........................................... @c SUBSECTION @c ........................................... @node LogEncryptedTransfers, MaxConnections, LogAllConnections, cfservd control @subsection LogEncryptedTransfers If set to true, every successful request for a file that is granted access only with an encrypted connection is logged in syslog. @c ........................................... @c SUBSECTION @c ........................................... @node MaxConnections, TrustKeysFrom, LogEncryptedTransfers, cfservd control @subsection MaxConnections This integer value sets a limit on the maximum number of child daemon threads which cfservd will `fork' in order to handle remote requests. The default value is ten. @cindex @code{MaxConnections} variable @c ........................................... @c SUBSECTION @c ........................................... @node TrustKeysFrom, DynamicAddresses, MaxConnections, cfservd control @subsection TrustKeysFrom Hosts which are included in this list are automatically trusted, if cfservd does not know their public key. This allows public keys to be exchanged. Cfservd will not automatically accept a public key from a host it does not know, since the key will be used to assert strong authentication later. Once a public key has been associated with an IP address, it will never be updated, unless the existing key is deleted by hand. @smallexample control: TrustKeysFrom = ( 128.39.89.76 ) # trusted host TrustKeysFrom = ( 128.39.89.76/24 ) # trusted subnet @end smallexample @cindex @code{TrustKeysFrom} variable @c ........................................... @c SUBSECTION @c ........................................... @node DynamicAddresses, , TrustKeysFrom, cfservd control @subsection DynamicAddresses Hosts which are included in this list are assumed to have IP addresses which can change with time, e.g. hosts which are given IP addresses by DHCP or a BOOTP like protocol. @cindex DHCP addresses @smallexample control: DynamicAddresses = ( 128.39.74.100-200 ) # DHCP range @end smallexample @cindex @code{DynamicAddresses} variable If cfservd receives a connection from an IP address that is in this list, and trustkey is @emph{true}, the existing key for that IP address can be replaced with a new key, and the old key is recorded in a "used keys" list, access is granted. If trust is switched off, the server looks in the "used key list" to see if the key has been seen before. If not access is refused. If it has been seen before -- it uses this earlier trust to accept the connection and replace the IP-key binding. @cindex DHCP @cindex Dynamic addresses Note that used keys are kept in a database for easy lookup, whereas fixed keys are kept in files for easy administration. If host keys change or are reinstalled on the dynamically allocated hosts, then this database should probably be deleted to purge keys that become illegal. DHCP addresses have no effect on hosts that use IPV6, since IPV6 addresses are generally issued based on an interface MAC address and do not therefore change. @cindex IPV6 and DHCP @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node admit grant and deny, cfrun, cfservd control, Cfservd.conf and cfrun reference @section admit, grant and deny @c ........................................... @c SUBSECTION @c ........................................... @menu * root=:: * encrypt=:: * SkipVerify:: @end menu @node root=, encrypt=, admit grant and deny, admit grant and deny @subsection @code{root=} This list specifies the names of hosts which are to have read access to files, regardless of the owner of the file. This effectively gives root users on connecting hosts privileges to non-root owned files on the server, but not vice-versa, similar to the NFS root mapping, except that there is no question of a client being able to modify files on the server. Caution: cfservd trusts the DNS service, so be aware that cache poisoning attacks are a possible way of bypassing access controls. @b{Cfservd requires you to grant access to files without following any symbolic links. You must grant access to the real file or directory in order to access the file object.} This is a security feature in case parties with login access to the server could grant access to additional files by having the permission to create symbolic links in a transitory directory, e.g. @file{/tmp}. @cindex Symbolic links in admit @cindex Links in access control @cindex Access control by directory @cindex Access control and symlinks As of version 2.0.4: Once a verified host address has been identified with a functioning public/private key authentication, the IP address is added to the SkipVerify list, so that time is not wasted in verifying reverse lookups, when the identify can be verified more efficiently and securely by a key mechanism. @cindex SkipVerify and public-private keys @cindex Caching of reverse lookups @cindex Reverse lookup and SkipVerify @vindex SkipVerify @c ........................................... @c SUBSECTION @c ........................................... @node encrypt=, SkipVerify, root=, admit grant and deny @subsection @code{encrypt=true} If this option is set, cfservd will only serve the named files if the copy access type is @code{secure}, i.e. on an encrypted link. This presupposes that cfengine has been compiled with a working OpenSSL library. @c ........................................... @c SUBSECTION @c ........................................... @node SkipVerify, , encrypt=, admit grant and deny @subsection SkipVerify If connecting hosts use a Network Address Translator in order to share an IP address, reverse lookup will fail to give a correct verification of host identity. You can switch off cfservd's verification of IP host identity for specific IP addresses or patterns using this command. E.g. @smallexample SkipVerify = ( 192.0.0.10 192.0.2. ) @end smallexample This does not affect key verification. NOTE!! This is a security risk because it means that cfservd implicitly trusts the connecting hosts! You should be very careful in using Network Address Translators in a secure environment. It is not recommended for sites which require a high level of security. @cindex Network Address Translators @cindex Security risk @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node cfrun, Firewalls and NATs, admit grant and deny, Cfservd.conf and cfrun reference @section @code{cfrun} The general syntactic form of the @code{cfrun} command is @cartouche @w{} @smallexample cfrun -@var{option} --@var{longoption} @var{class1} @var{class2 ...} @end smallexample @end cartouche @noindent Since @code{cfrun} addresses remote hosts, there is an ambiguity in whether options are intended for the @code{cfrun} command itself, on the local host, or whether they are to be passed on to the agent on the remote hosts. To clarify this distinction, the arguments are organized as follows: @cartouche @w{} @smallexample cfrun -@var{local options} -- @var{remote options} -- @var{remote classes} @end smallexample @end cartouche @noindent Local options are processed by @code{cfrun} on the local host; remote options are passed on as options to the remote @code{cfagent} (actually to the command defined in @code{cfrunCommand} in the file @file{cfservd.conf}; remote classes are processed by the remote @code{cfservd} service, and specifiy classes which must be satisfied by the remote host in order to invoke the remote command. The @samp{-q} and @samp{-I} options are always assumed when executing cfengine remotely, so that @code{SplayTime} is effectively zero when polling hosts serially, and the output always shows what is happening on the remote hosts. @cindex SplayTime in cfrun @cindex @samp{-T} in cfrun. @cindex Trust, key exchange with cfrun On connecting to a remote host, cfengine attempts to obtain credentials by exchanging keys. Unknown keys, in a key exchange, need to be explicitly accepted on trust. Normally, the interactive @code{cfrun} program prompts the user explicitly, (like in the secure shell, @code{ssh}, connections). This can be annoying if there are many hosts to connect to. The @samp{-T} option tells cfengine to trust all new keys. This option should be used with caution, and only at times when one is sure that the hosts one is connecting to are trustworthy. Each host evaluates the classes sent by @code{cfrun} and decides whether cfengine should be invoked. @cindex Running @code{cfrun} Only hosts which belong to the classes defined on the @code{cfrun} command line are executed. This allows you to single out groups of hosts which should execute cfengine, based on the very classes which you have defined for your configuration. If no classes are sent on the command line, then all hosts are run. @code{cfrun} uses a configuration file which is located under the @code{CFINPUTS} directory in order to determine which hosts and in which order it should try to connect. Because cfengine always uses a reliable TCP protocol for connections, it verifies each connection rather than simply broadcasting openly. Using this file you can even simulate broadcasting to hosts outside your subnet. @cindex Broadcasts to the cfengine service. This file should contain every host name you ever want to configure remotely, because you can still select subsets of the file by specifying classes which the remote host will understand. If the remote host is not in one of the classes you specify when you run @code{cfrun}, then it will simply ignore the request. Conversely, if you do not place a host in this file, it will never be contacted when you use the @code{cfrun} command. The format of the file is as follows @cartouche @w{} @smallexample # # Comment .. # domain=@var{my.domain} access=@var{user1},@var{user2} outputdir=@var{directory} maxchild=@var{number limit} hostnamekeys=@var{true/false} bindtointerface=@var{IP address} @var{hostname1} @var{options} @var{hostname2}:@var{port} @var{options} ... include=cfrun.site1.external.hosts include=cfrun.site1.internal.hosts include=cfrun.site2.private.hosts include=cfrun.site2.shared.hosts @end smallexample @end cartouche @cindex hostnamekeys @cindex include in cfrun @noindent If the option @code{outputdir} is present, cfrun forks a separate process for each host and passes the output to files in a named directory. The @code{maxchild} line limits the number of forked processes. It is important to add the domain-name to this file. The options you specifiy in this file, per host, are added to those you might specify on the command line when invoking cfengine remotely. For instance, you might know of a bug on one host and decide not to perform interface configuration on that one machine. You would write a line like this: @smallexample funny.domain -- -i # problem host @end smallexample @cindex Running cfengine from a single master host @cindex Running cfengine from a single master host You could use @code{cfrun} inside one of your cfengine configuration files in order to remotely execute cfengine on all of the other network machines, by setting up a host list. The disadvantage however is that cfengine has to poll the systems on the network, which means that cfengine cannot be working in parallel on all hosts. Some other examples: @smallexample e.g. cfrun -- -- linux Run on all linux machines cfrun -- -p Ping and parse on all hosts cfrun -v -- -p Ping all, local verbose cfrun -v -- -k -- solaris Local verbose, all solaris, but no copy @end smallexample Amongst the local options, one may specify a subset of the hosts which are to be contacted by cfrun, i.e. to avoid processing the entire list of hosts. For example, to contact only host1 and host2, given that they are already in the list of hosts. @smallexample cfrun -v host1 host2 cfrun -v host1 host2 -- -p @end smallexample @cindex Contacting specific hosts with cfrun @node Firewalls and NATs, , cfrun, Cfservd.conf and cfrun reference @section Firewalls and NATs Firewalls and Network Address Translators (NAT) can be a problem for addressing. Suppose you have a firewall and with a private IP-range behind the firewall. You want to update the nodes from a central host. You can do a two stage configuration: first update the firewall and then update from the firewall to the nodes. But suppose you already use SNAT (Source Network Address Translation) and DNAT (Destination ...) for the nodes. With DNAT you can say that socket 22000 on the firewall is routed to @var{host-name}:5308. DNAT gives us the possibilty to update the nodes from a central server in one step instead of two. If the port command is given cfrun uses this to connect to the client instead of the default (5308) one. Here is an example (@file{cfrun.hosts}): @smallexample domain=example.org access=mark,sigmund hostnamekeys=true node1.example.org node2.example.org:22000 -DNis node2.example.org:22001 @end smallexample @cindex HostnameKeys This connects to: 1) node1 with standard port, 2) node2 with port 22000 and extra options -DNis and, 3) node2 with port 22000. @cindex NAT @cindex Network address translator @cindex Changing cfengine port @cindex Port, connecting to different @c ********************************************************************** @c CHAPTER @c ********************************************************************** @node Cfexecd reference, Problem solving, Cfservd.conf and cfrun reference, Top @chapter Cfexecd reference In wrapper mode (non-forking, non-daemon mode), cfagent is run by adding a line to the root crontab file of each system: @smallexample 0,30 * * * * /usr/local/sbin/cfexecd -F @end smallexample This is enough to ensure that cfengine will get run. Any output generated by this job, will be stored in @file{/var/cfengine/outputs}. The program @code{cfexecd} operates as a wrapper for cfagent. It has the following options: @smallexample -h (--help) -d (--debug) -v (--verbose) -q (--no-splay) -F (--no-fork) -1 (--once) -g (--foreground) -p (--parse-only) -L (--ld-library-path) @end smallexample @cindex /var/cfengine/output @vindex /var/cfengine/output @cindex Output logs In addition, if you add the following to the file @file{cfagent.conf}, the system administrator will be emailed a summary of any output: @smallexample control: smtpserver = ( mailhub.example.org ) # site MTA which can talk smtp sysadm = ( mark@@example.org ) # mail address of sysadm EmailMaxLines = ( @var{n} ) # max lines of output to email OutputPrefix = ( "!" ) # Line prefix @end smallexample @noindent Fill in suitable values for these variables. @code{EmailMaxLines} may be set to 0 to disable email output, a postive integer to set a limit, or @code{inf} to email the whole output regardless of its size. If undefined, @code{EmailMaxLines} defaults to 100. @cindex Mailing output @vindex smtpserver @vindex sysadm @vindex EmailMaxLines @cindex cfexecd An alternative, or additional way to run cfengine, is to run the @file{cfexecd} program is daemon mode (without the @samp{-F}) option. In this mode, the daemon lives in the background and sleeps, activating only in accordance with a scheduling policy. The default policy is to run once every hour (equivalent to @code{Min00_05}). Here is how you would modify @file{cfagent.conf} in order to make the daemon execute cfagent every half-hour: @smallexample control: # When should cfexecd in daemon mode wake up the agent? schedule = ( Min00_05 Min30_35 ) @end smallexample Note that the time specifications are the basic cfengine @emph{time classes}. Although one of these methods should suffice, no harm will arise from running both cron and the cfexecd side-by-side. Locking mechanisms are used by @code{cfagent} to ensure that no contention will occur. @cindex Mailing output @vindex smtpserver @vindex sysadm @cindex cfexecd Note, that if problems with library path for compiled-in libraries occur, an explicit library path can be specified with the @samp{-L} option. @smallexample 0,30 * * * * /usr/local/sbin/cfexecd -F -L /local/iu/lib:/local/lib:/local/gnu/lib @end smallexample The output generated by a cfagent run is collected and stored with date stamps in the @file{outputs} subdirectory of the work directory (usually @file{/var/cfengine/outputs}). If cfengine has a valid smtp server configured it will attempt to E-mail new reports to the system administrator. Duplicate reports are suppressed however for a period of one day. Thus, if one has a repeating message, then it will only be sent by E-mail once per day -- this feature is meant to prevent cfagent from spamming administators with multiple, indentical reports. As soon a report different from the previous one is received, the memory is reset. Note: this repeated message suppression feature cannot work if you include time dependent data in messages, i.e. if you include the date or time in an alert, then clearly the message will be a different message each time. Output from cfengine should not contain the time or date, except in the E-mail header. @cindex Mail from cfexecd @cindex Spam suppression @c ********************************************************************** @c CHAPTER @c ********************************************************************** @node Problem solving, Example configuration file, Cfexecd reference, Top @chapter Problem solving @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @menu * cf.preconf bootstrap file:: * cfrc resource file:: @end menu @node cf.preconf bootstrap file, cfrc resource file, Problem solving, Problem solving @section cf.preconf bootstrap file @cindex cf.preconf bootstrap file @vindex cf.preconf @cindex Bootstrap file @cindex Deadlock @cindex Hung machine In some cases you will want to run cfengine on a system to configure it from scratch. If the system is in a very bad way, it might not even be able to parse the cfengine configuration file, perhaps because the network was not properly configured or the DNS (Domain Name Service) was out of action. To help prevent this situation, cfengine looks for a script called @code{cf.preconf} which gets executed prior to parsing and can be used to perform any emergency tests. This file needs only contain enough to get the system to parse the configuration files. @code{cf.preconf} may be any script in any language. It need not exist at all! It is fed one argument by cfengine, namely the system hard-class for the current system (e.g. @code{ultrix}). Here is an example: @smallexample #!/bin/sh # # cf.preconf is an emergency/bootstrap file to get things going # in case cfengine is unable to parse its config file # backupdir=/iu/nexus/local/iu/etc # # If these files don't exist, you might not be able to parse cfagent.conf # if [ ! -s /etc/resolv.conf ]; then echo Patching basics resolv.conf file cat > /etc/resolv.conf << XX domain iu.hioslo.no nameserver 128.39.89.10 XX fi # # SVR4 # if [ "$1" = "solaris" ]; then if [ ! -s "/etc/passwd" ]; then echo Patching missing passwd file /bin/cp $backupdir/passwd /etc/passwd fi if [ ! -s "/etc/shadow" ]; then echo Patching missing passwd file /bin/cp $backupdir/shadow /etc/shadow fi fi # # BSD 4.3 # if [ "$1" = "linux" ]; then if [ ! -s "/etc/passwd" ] then echo Patching missing passwd file /bin/cp $backupdir/passwd.linux /etc/passwd fi fi @end smallexample @cindex /etc/host.conf @vindex /etc/host.conf @cindex -x option @vindex -x option Note - in some circumstances, it might be appropriate to exit cfengine altogether after this script. If the script outputs a string containing the text "cfengine-preconf-abort", then cfagent will abort execution immediately after this. @cindex Emergency abort @cindex Abort cfengine after cf.preconf @c ------------------------------------------------------------------------------- @c SECTION @c ------------------------------------------------------------------------------- @node cfrc resource file, , cf.preconf bootstrap file, Problem solving @section cfrc resource file @cindex cfrc resource file @cindex Resource file @vindex cfrc If, for some reason you are not satisfied with the defaults which cfengine uses, then you can change them by making an entry in the resource file. The default values are defined in the source code file @code{classes.c} in the distribution. The format of the resource file is: @smallexample hardclass.variable: value @end smallexample @noindent For example, you might want to forget about where your HPUX system mounts its mail directory and mount it under @code{/usr/spool/mail}. In this case you would add the line: @smallexample hpux.maildir: /usr/spool/mail @end smallexample @noindent To redefine the filesystem table for GNU/linux, you would write: @smallexample linux.fstab: /etc/linuxfstab @end smallexample @noindent The full list of re-definable resources is: @smallexample mountcomm # command used to mount filesystems unmountcomm # command used to unmount filesystems ethernet # name of the ethernet device mountopts # options to above mount command fstab # the name of the filesystemtable maildir # the location of the mail directory netstat # the full path to netstat and options pscomm # the path to the system's ps command psopts # the options used by ps (default aux/ef) @end smallexample You should never need to redefine resources unless you decide to do something non-standard. Interested readers are referred to the values in @code{classes.c}. @cindex Adding new classes @cindex Support for new systems @cindex New systems, support for Cfengine is easily extensible so as to support a variety of architectures. You can even add your own. To do so you need, first of all, to define a new class for the operating system concerned. The file @emph{classes.c} has been separated off from the remainder of the source code so that you can easily see which data structures need to be extended. To make life as straightforward as possible, three unused classes have been defined. They are called (unremarkably) @emph{unused1}, @emph{unused2} and @emph{unused3}. If you add any further classes, it will be necessary to increase the constant @emph{clssattr} defined in @emph{cf.defs.h} by one for every new addition. You do not need to change @emph{clssattr} if you simple replace one of the unused classes by a real class. To see fully the impact of what you need to do, you should make a search for the strings @emph{unused?} in all of the source files. Certain special cases need to be handled for each operating system. For example, the form of the filesystem table is quite radically different on some systems such as AIX. One thing you must do is to fill in the default values for the new operating system in the file @emph{classes.c}. If you fill in the details for a new operating system before it finds its way into a new release, you might consider sending the details to the bug list in the next paragraph. @c ********************************************************************** @c CHAPTER @c ********************************************************************** @node Example configuration file, Variable Index, Problem solving, Top @chapter Example configuration files @cindex Example configuration files Here is a sample from a large configuration file, just to give you some ideas. The file is broken up into manageable pieces for convenience. @menu * cfagent.conf:: * cf.groups:: * cf.main:: * cf.site:: * cf.motd:: * cf.users:: * cf.solaris:: * cf.linux:: * cf.freebsd:: * cfservd.conf:: @end menu @c ..................................................... @c SECTION @c ..................................................... @node cfagent.conf, cf.groups, Example configuration file, Example configuration file @section cfagent.conf @cindex @file{cfagent.conf} @w{} @smallexample ##################################################################### # # CFENGINE CONFIGURATION FOR site = iu.hioslo.no # # This file is for root only. # ###################################################################### ### # # BEGIN cfagent.conf # ### import: # # Split things up to keep things tidy # any:: cf.groups cf.main cf.site cf.motd hpux:: cf.hpux linux:: cf.linux solaris:: cf.solaris sun4:: cf.sun4 ultrix:: cf.ultrix freebsd:: cf.freebsd # # Do you want to do this ? # AllHomeServers:: cf.users ### # # END cfengine.conf # ### @end smallexample @c ..................................................... @c SECTION @c ..................................................... @node cf.groups, cf.main, cfagent.conf, Example configuration file @section cf.groups @cindex @file{cf.groups} @w{} @smallexample ############################################################## # # cf.groups - for iu.hioslo.no # # This file contains all group/class definitions # ################################################################# ### # # BEGIN cf.groups # ### groups: # # Define some groups # iu = ( nexus ferengi regula borg dax lore axis worf daystrom voyager aud1 aud2 aud3 aud4 bajor ds9 takpah takpeh nostromo galron thistledown rama chaos pc-steinarj pc-hildeh way jart kosh ) diskless = ( regula ferengi lore ) standalone = ( nexus axis dax borg worf daystrom voyager aud1 aud2 aud3 aud4 bajor ds9 takpah takpeh nostromo galron thistledown rama pc-torejo pc-steinarj pc-hildeh ) AllHomeServers = ( nexus ) AllBinaryServers = ( nexus borg ) XBootServer = ( nexus ) WWWServers = ( nexus ) FTPserver = ( nexus ) NameServers = ( nexus ) PasswdServer = ( nexus ) BackupHost = ( nexus ) MailHub = ( nexus ) MailClients = ( iu -nexus ) ### # # END cf.groups # ### @end smallexample @c ..................................................... @c SECTION @c ..................................................... @node cf.main, cf.site, cf.groups, Example configuration file @section cf.main @cindex @file{cf.main} @w{} @smallexample ############################################################## # # cf.main - for iu.hioslo.no # # This file contains generic config stuff # ################################################################# ### # # BEGIN cf.main # ### control: access = ( root ) # Only root should run this site = ( iu ) domain = ( iu.hioslo.no ) sysadm = ( drift@@iu.hioslo.no ) repository = ( /var/spool/cfengine ) netmask = ( 255.255.255.0 ) timezone = ( MET ) nfstype = ( nfs ) sensiblesize = ( 1000 ) sensiblecount = ( 2 ) editfilesize = ( 20000 ) mountpattern = ( /$(site)/$(host) ) homepattern = ( u? ) # # If we undefine this with cfengine -N longjob # then we switch off all jobs labelled with this class # addclasses = ( longjob ) # # Macros & constants are inherited downwards in imports # but are not passed up to parent files. Good idea to # define them all here # masterfiles = ( /iu/nexus/local/iu ) main_server = ( nexus ) cfbin = ( /iu/nexus/local/gnu/lib/cfengine/bin ) gnu = ( /local/gnu ) ftp = ( /local/iu/ftp ) nisslave = ( dax ) nisfiles = ( /iu/nexus/local/iu/etc ) # # The action sequence for daily (full) runs and # for hourly updates (called with -DHourly) # Hr00:: actionsequence = ( copy mountall mountinfo checktimezone netconfig resolve unmount shellcommands addmounts links.Prepare files.Prepare directories links.Rest mailcheck mountall required tidy disable editfiles files.Rest processes ) !Hr00:: actionsequence = ( resolve shellcommands copy editfiles processes links ) force:: actionsequence = ( files.Prepare.Rest tidy ) ###################################################################### homeservers: iu:: nexus binservers: iu.solaris:: nexus iu.linux:: borg mailserver: any:: nexus:/var/mail mountables: any:: nexus:/iu/nexus/u1 nexus:/iu/nexus/u2 nexus:/iu/nexus/u3 nexus:/iu/nexus/u4 nexus:/iu/nexus/u5 nexus:/iu/nexus/u6 nexus:/iu/nexus/ua nexus:/iu/nexus/ud nexus:/iu/nexus/local nexus:/opt/NeWSprint nexus:/opt/AcroRead borg:/iu/borg/local dax:/iu/dax/local miscmounts: linux||freebsd:: nexus:/iu/nexus/local /iu/nexus/local ro ###################################################################### broadcast: ones defaultroute: cadeler30-gw ###################################################################### resolve: 128.39.89.10 # nexus 158.36.85.10 # samson.hioslo.no 129.241.1.99 ###################################################################### tidy: # # Some global tidy-ups # /tmp/ pat=* r=inf A=1 /var/tmp pat=* r=inf A=1 / pat=core r=1 A=0 /etc pat=core r=1 A=0 ###################################################################### ignore: # Don't check or tidy these directories /local/lib/gnu/emacs/lock/ /local/tmp ftp projects /local/bin/top /local/lib/tex/fonts /local/iu/etc /local/etc /local/iu/httpd/conf /usr/tmp/locktelelogic /usr/tmp/lockIDE RootMailLog # # Emacs lock files etc # !* /local/lib/xemacs # # X11 keeps X server data in /tmp/.X11 # better not delete this! # .X11 # # Some users like to give a file or two 777 protection here # so netsurfers can update a log or counter when running as # `nobody' # www ##################################################################### disable: /etc/hosts.equiv /etc/nologin /usr/lib/sendmail.fc ### # # END cf.main # ### @end smallexample @c ..................................................... @c SECTION @c ..................................................... @node cf.site, cf.motd, cf.main, Example configuration file @section cf.site @cindex @file{cf.site} @w{} @smallexample ############################################################## # # cf.site - for iu.hioslo.no # # This file contains site specific data # ################################################################# ### # # BEGIN cf.site # ### links: Prepare:: /local -> /$(site)/$(binserver)/local /usr/local -> /local dax:: /iu/dax/local +> /iu/nexus/local /projects -> /iu/dax/local/projects /iu/nexus/u1/sowille/data -> /iu/dax/scratch/data XBootServer:: # # Set up a /local/tftpboot area where all X terminal # stuff will be kept. # /tftpboot -> /local/tftpboot /local/tftpboot/td/configs -> /local/tftpboot/td/examples/configs /etc/bootptab -> /tftpboot/bootptab /tftpboot/usr/lib/X11/td -> /tftpboot/td NameServers:: /etc/named.boot -> /local/iu/named/named.boot MailHub:: /etc/mail/sendmail.cf ->! /iu/nexus/local/mail/sendmail.cf MailClients.solaris:: /etc/mail/sendmail.cf ->! /iu/nexus/local/mail/client.cf nexus:: /local/bin +> /local/latex/bin ############################################################# disable: # # We run Berkeley sendmail and the config files are # all under /iu/nexus/local/lib/mail # /etc/aliases WWWServers.Sunday:: # # Disabling these log files weekly prevents them from # growing so enormous that they fill the disk! # /local/iu/httpd/logs/access_log rotate=empty /local/iu/httpd/logs/agent_log rotate=empty /local/iu/httpd/logs/error_log rotate=empty /local/iu/httpd/logs/referer_log rotate=empty # # CERT warning, security fix # any:: /usr/lib/expreserve FTPserver.Sunday.Hr00:: /local/iu/xferlog rotate=3 ################################################################# files: Prepare:: /etc/motd m=0644 r=0 o=root act=touch /.cshrc m=0644 r=0 o=root act=touch PasswdServer:: /local/iu/etc/passwd m=0644 o=root g=other action=fixplain /local/iu/etc/shadow m=0644 o=root g=other action=fixplain WWWServers.Rest:: /local/iu/www m=775 g=www act=fixall r=inf /local/iu/httpd/conf m=664 o=root g=www act=fixall r=inf /local/iu/www/cgi-bin-public/count_file m=777 o=root g=www act=fixplain FTPserver:: # # Make sure anonymous ftp areas have the correct # protection, or logins won't be able to read # files - or perhaps a security risk. This is # Solaris 2 specific... # $(ftp)/pub mode=755 o=ftp g=ftp r=inf act=fixall $(ftp)/Obin mode=111 o=root g=other act=fixall $(ftp)/etc mode=111 o=root g=other act=fixdirs $(ftp)/usr/bin/ls mode=111 o=root g=other act=fixall $(ftp)/dev mode=555 o=root g=other act=fixall $(ftp)/usr mode=555 o=root g=other act=fixdirs Prepare:: /etc/shells mode=0644 action=touch AllBinaryServers.Rest.longjob:: /local mode=-0002 r=inf owner=root,bin group=0,1,2,3,4,5,6,7,staff links=tidy action=fixall /local/iu/RootMailLog m=0666 action=touch dax.Rest:: /iu/dax/scratch r=0 o=root mode=1777 action=fixall /iu/dax/local/projects r=0 o=root mode=755 action=fixdirs nexus:: /local/mail/sendmail.cf o=root m=444 act=fixplain /iu/nexus/ua/robot/.rhosts o=robot m=600 act=touch /local/iu/named/pz o=root m=644 act=fixall r=1 /local/latex/lib/tex/texmf/fonts owner=root mode=1666 recurse=inf action=fixall ################################################################# tidy: # # Make sure the file repository doesn't fill up # /var/spool/cfengine pattern=* age=3 /var pattern=core age=0 r=inf /var/spool/mqueue pattern=* age=14 type=mtime BackupHost:: # Here we tidy old backup tar files from the backup area # A special tmp area gets cleared every 4 days. The files # are created by Audun's backup help script (see shellcommands) /iu/nexus/backup1 pat=* age=7 ################################################################# shellcommands: PasswdServer:: # Build and install the BSD compatible passwd file # from the master passwd/shadow file on Solaris "/local/iu/bin/BuildPasswdFiles" "/local/iu/bin/BuildGroupFiles" BackupHost.Sunday.Hr00|BackupHost.Wednesday.Hr00:: # # Make a system backup of /iu/nexus/u? with Audun's script # "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/ud" "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/ua" "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/u1" "$(cfbin)/cfbackup -p -f /iu/nexus/backup1 -s /iu/nexus/u2" "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u3" "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u4" "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u5" "$(cfbin)/cfbackup -p -f /iu/nexus/backup2 -s /iu/nexus/u6" nexus.Sunday.longjob.Hr00:: # # See how much rubbish users have accumulated each Sunday # "$(cfbin)/noseyparker /iu/nexus/u1 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/u2 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/u3 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/u4 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/u5 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/u6 $(sysadm) " "$(cfbin)/noseyparker /iu/nexus/ua $(sysadm) nomail" "$(cfbin)/noseyparker /iu/nexus/ud $(sysadm) nomail" nexus.longjob.Hr00:: # # Update the GNU find/locate database each night # "$(gnu)/lib/locate/updatedb" "/local/iu/bin/newhomepage.sh" ############################################################### editfiles: # # cfengine installs itself as a cron job - sneaky! :) # @{ /var/spool/cron/crontabs/root AppendIfNoSuchLine "0 * * * * $(cfbin)/cfwrap $(cfbin)/cfhourly" @} FTPserver:: @{ /etc/shells AppendIfNoSuchLine "/bin/tcsh" AppendIfNoSuchLine "/local/gnu/bin/bash" @} XBootServer:: @{ /etc/inetd.conf AppendIfNoSuchLine "bootp dgram udp wait root /local/bin/bootpd bootpd -i -d" @} nexus:: @{ /iu/nexus/ua/robot/.rhosts AppendIfNoSuchLine "borg" AppendIfNoSuchLine "borg.iu.hioslo.no" AppendIfNoSuchLine "aud4" AppendIfNoSuchLine "aud4.iu.hioslo.no" @} dax:: @{ /etc/system AppendIfNoSuchLine "set pt_cnt=128" @} ###################################################################### required: # # Any host must have a /local, /usr/local fs. Check that # it exists and looks sensible. (i.e. not empty) # /$(site)/$(binserver)/local ###################################################################### copy: # # NIS seems broken at IU, so here we use NFS to fudge # a file distribution as a temporary solution. Actually # this makes the system work faster without NIS! # $(nisfiles)/services dest=/etc/services o=root g=other mode=0644 $(nisfiles)/hosts.deny dest=/etc/hosts.deny o=root mode=0644 !debian:: $(nisfiles)/hosts dest=/etc/hosts o=root g=other mode=0644 PasswdServer:: /etc/passwd dest=$(nisfiles)/passwd o=root g=other mode=0644 /etc/shadow dest=$(nisfiles)/shadow o=root g=other mode=0644 nexus:: /local/iu/etc/dfstab dest=/etc/dfs/dfstab o=root mode=0744 solaris.!PasswdServer:: $(nisfiles)/passwd dest=/etc/passwd o=root g=other mode=0644 $(nisfiles)/shadow dest=/etc/shadow o=root g=other mode=0600 $(nisfiles)/group.solaris dest=/etc/group o=root g=other mode=0644 linux:: $(nisfiles)/passwd.linux dest=/etc/passwd o=root g=other mode=0644 $(nisfiles)/group.linux dest=/etc/group o=root g=other mode=0644 ############################################################### processes: "eggdrop" signal=kill "irc" signal=kill "ping" signal=kill "NetXRay" signal=kill "netxray" signal=kill "ypserv" signal=kill "ypbind" signal=kill "rarpd" signal=kill "rpc.boot" signal=kill "README" signal=kill # You don't sh README ! !XBootServer:: "bootp" signal=kill # # These processes are not killed every hour, but once a day # when cfengine runs at night. Note that there are often # hanging pine and elm processes. These programs crash and # go berserk, using hundreds of hours of CPU time. # Hr00:: "cron" signal=hup # HUP these to update their config "inetd" signal=hup "/local/sdt/sdt/bin" signal=term # For those elektro dudes who forget # to log out "netscape" signal=kill "pine" signal=kill "elm" signal=kill ### # # END cf.site # ### @end smallexample @c ..................................................... @c SECTION @c ..................................................... @node cf.motd, cf.users, cf.site, Example configuration file @section cf.motd @cindex @file{cf.motd} @w{} @smallexample ################################################################## # # cf.motd # # This file is used to set the message of the day file on # each host # ################################################################## ##### # # BEGIN cf.motd # ##### control: # # This points to the file containing general text # masterfile = ( /iu/nexus/local/iu/etc/motd-master ) local_message = ( /etc/motd.local ) editfiles: @{ /etc/motd BeginGroupIfFileIsNewer "$(masterfile)" EmptyEntireFilePlease InsertFile "$(masterfile)" InsertFile "$(local_message)" PrependIfNoSuchLine "This system is running $(class):$(arch)" EndGroup @} ##### # # BEGIN cf.motd # ##### @end smallexample @c ..................................................... @c SECTION @c ..................................................... @node cf.users, cf.solaris, cf.motd, Example configuration file @section cf.users Whether or not you perform any special services for users, with or without their consent is entirely a matter of local policy. In a school or college situation, users are often uncooperative and some are even irresponsible. This file shows you what you could do in an environment with inexperienced users, but please don't feel as though you have to be this totalitarian. @w{} @smallexample ################################################################# # # cf.users - for iu.hioslo.no # # This file contains user specific actions # ################################################################# ### # # BEGIN cf.users # ### ignore: robot tidy: longjob:: # # Some users just don't understand what they are doing # and this is safest, allbeit totalitarian # home pat=.rhosts age=0 # # Tidy up users' home dirs # home pat=core r=inf age=0 home pat=a.out r=inf age=1 home p=*% r=inf age=2 home p=*~ r=inf age=2 home p=#* r=inf age=1 home p=*.dvi r=inf age=14 type=ctime home p=*.log r=inf age=2 home p=Log.* r=inf age=3 home p=CKP r=inf age=1 home p=BAK r=inf age=1 home p=log r=inf age=0 home p=*.o r=inf age=0 home p=*.aux r=inf age=3 home p=*.zip r=inf age=7 home/.deleted p=* r=inf age=0 home/.wastebacket p=* r=inf age=14 home/www p=*~ r=inf age=1 # # Clear the big cache files netscape creates # home/.netscape-cache p=cache????* r=inf age=0 home/.MCOM-cache p=cache????* r=inf age=0 home/.netscape/cache p=* r=inf age=0 ################################################################# files: AllHomeServers.longjob.rest:: # # Check users files are not writable to the world # and there are no stale links (pointing nowhere) # home mode=o-w recurse=inf action=fixall # links=tidy home/.xsession mode=755 action=fixall home/.cshrc mode=755 action=fixall ################################################################# copy: Hr00.longjob:: # # Make sure each user has an up to date standard # setup. Cshrc just sources in a big standard file # which is kept in ~user/../.setupfiles/cshrc # to reduce disk wastage # $(masterfiles)/lib/Cshrc dest=home/.cshrc $(masterfiles)/lib/tkgrc dest=home/.tkgrc $(masterfiles)/lib/fvwm2rc dest=home/.fvwm2rc ### # # END cf.users # ### @end smallexample @c ..................................................... @c SECTION @c ..................................................... @node cf.solaris, cf.linux, cf.users, Example configuration file @section cf.solaris @w{} @smallexample ################################################################# # # cf.solaris - for iu.hioslo.no # # This file contains Solaris specific patches # ################################################################# ### # # BEGIN cf.solaris # ### directories: # # httpd/netscape want this to exist for some bizarre reason # /usr/lib/X11/nls ################################################################ tidy: /var/log pattern=syslog.* age=0 MailHub:: /var/mail pattern=lp age=0 ################################################################# files: # # If this doesn't exist fork will not work and the # system will not even be able to run the /etc/rc # scripts at boottime # /etc/system o=root g=root m=644 action=touch /var/log/syslog o=root m=666 action=touch ############################################################# copy: # # Some standard setup files, can't link because # machine won't boot if their not on / partition. # /local/bin/tcsh dest=/bin/tcsh mode=755 /local/iu/etc/nsswitch.standalone dest=/etc/nsswitch.conf # # Our named server uses a newer BIND # Put this here so that it will be preserved under # Solaris reinstallation # NameServers:: /local/iu/sbin/in.named dest=/usr/sbin/in.named mode=555 /local/iu/sbin/in.named.reload dest=/usr/sbin/in.named.reload mode=555 /local/iu/sbin/in.named.restart dest=/usr/sbin/in.named.restart mode=555 /local/iu/sbin/in.ndc dest=/usr/sbin/in.ndc mode=555 /local/iu/sbin/named-xfer dest=/usr/sbin/named-xfer mode=555 /local/iu/lib/nslookup.help dest=/usr/lib/nslookup.help mode=444 any:: /local/iu/lib/libresolv.a dest=/usr/lib/libresolv.a mode=444 /local/iu/lib/libresolv.so.2 dest=/usr/lib/libresolv.so.2 mode=444 /local/bin/nslookup dest=/usr/sbin/nslookup mode=444 ############################################################## editfiles: @{ /etc/netmasks AppendIfNoSuchLine "128.39 255.255.255.0" @} @{ /etc/defaultrouter AppendIfNoSuchLine "128.39.89.1" @} @{ /usr/openwin/lib/app-defaults/XConsole AppendIfNoSuchLine "XConsole.autoRaise: on" @} # # CERT security patch for vold vulnerability # @{ /etc/rmmount.conf HashCommentLinesContaining "action cdrom" HashCommentLinesContaining "action floppy" @} ############################################################## disable: /etc/.login type=file /etc/aliases # # These files are ENORMOUS, don't let them fill the disk # Wednesday:: /var/lp/logs/lpsched rotate=empty /var/adm/wtmpx rotate=empty /var/adm/wtmp rotate=empty ############################################################## files: /etc/passwd m=0644 o=root g=other action=fixplain /etc/shadow m=0600 o=root g=other action=fixplain /etc/defaultrouter m=0644 o=root g=other action=touch /var/adm/wtmpx m=0664 o=adm g=adm action=touch /var/adm/wtmp m=0644 o=root g=adm action=touch /var/adm/utmp m=0644 o=root g=adm action=fixplain /var/adm/utmpx m=0664 o=adm g=adm action=fixplain /tmp m=1777 action=fixdirs ############################################################## disable: # # CERT security patch # /usr/openwin/bin/kcms_calibrate /usr/openwin/bin/kcms_configure /usr/bin/admintool ################################################################ shellcommands: AllBinaryServers.Saturday.longjob.Hr00:: # # Make sure the man -k / apropos data are up to date # "/usr/bin/catman -M /local/man" "/usr/bin/catman -M /local/X11R5/man" "/usr/bin/catman -M /usr/man" "/usr/bin/catman -M /local/gnu/man" "/usr/bin/catman -M /usr/openwin/share/man" "/usr/bin/catman -M /local/X11R5/man" "/usr/bin/catman -M /usr/share/man" ################################################################ editfiles: # # A painless way to add an rc.local script to the rc files # under Solaris without having to fight though inittab # @{ /etc/rc3.d/S15nfs.server AppendIfNoSuchLine "sh /local/iu/etc/rc.local" @} # # umask defined when inetd starts is inherited by all subprocesses # including ftpd which saves with mode 666 (!) unless we do this # @{ /etc/rc2.d/S72inetsvc PrependIfNoSuchLine "umask 022" @} ### # # END cf.solaris # ### @end smallexample @c ..................................................... @c SECTION @c ..................................................... @node cf.linux, cf.freebsd, cf.solaris, Example configuration file @section cf.linux @w{} @smallexample ################################################################# # # cf.linux - for iu.hioslo.no # # This file contains debian linux specific patches # ################################################################# ### # # BEGIN cf.linux # ### files: /etc/printcap m=644 o=root action=fixplain # # Cert advisories # /bin/mount m=755 o=root action=fixall /bin/umount m=755 o=root action=fixall ####################################################################### disable: # # Cert advisories # /sbin/dip-3.3.7n ######################################################################## links: /local/bin/tcsh -> /bin/tcsh /local/lib/mail -> /$(site)/$(main_server)/local/lib/mail ######################################################################## editfiles: # # Samba default mode needs to be set... # @{ /etc/smb.conf ReplaceAll "700" With "644" @} # # Linux date is very stupid and needs a very careful # TZ definition, otherwise it loses # @{ /etc/csh.cshrc AppendIfNoSuchLine "setenv TZ 'MET-1MET DST-2,M3.5.0/2,M10.5.0/3'" @} # # resolv+ ordering # @{ /etc/host.conf PrependIfNoSuchLine "order bind" @} # # Should have been configured already (!) # @{ /etc/ld.so.conf AppendIfNoSuchLine "/usr/X11R6/lib" @} # # Kill annoying messages # @{ /etc/cron.daily/standard HashCommentLinesContaining "security" @} ######################################################################### shellcommands: Hr00:: # # Find/locate database # "/usr/bin/updatedb" ### # # END cf.linux # ### @end smallexample @c ..................................................... @c SECTION @c ..................................................... @node cf.freebsd, cfservd.conf, cf.linux, Example configuration file @section cf.freebsd / cf.netbsd FreeBSD, OpenBSD and NetBSD are sufficiently similar to have a single file for all. @smallexample ################################################################# # # cf.bsd - for iu.hioslo.no # # This file contains bsd specific patches # ################################################################# ### # # BEGIN cf.bsd # ### links: /usr/spool -> /var/spool /local/bin/tcsh -> /bin/tcsh /local/bin/perl -> /usr/bin/perl /usr/lib/sendmail -> /usr/sbin/sendmail ################################################################# files: /usr/tmp mode=1777 owner=root action=fixall ################################################################# editfiles: # # Comment out all lines to shut up this annoying cfengine-like # script, which sends mail every day!!! # @{ /etc/crontab HashCommentLinesContaining "daily" HashCommentLinesContaining "weekly" HashCommentLinesContaining "monthly" @} ################################################################# copy: $(masterfiles)/etc/printcap.client dest=/etc/printcap mode=0644 ######################################################################### shellcommands: Hr00:: "/usr/libexec/locate.updatedb" "/usr/bin/makewhatis /usr/share/man:/usr/X11R6/man" ### # # END cf.bsd # ### @end smallexample @c ..................................................... @c SECTION @c ..................................................... @node cfservd.conf, , cf.freebsd, Example configuration file @section cfservd.conf tutorial @cindex @file{cf.site} @w{} @smallexample ######################################################### # # This is a cfservd config file # ######################################################### # # Could import cf.groups here and use a structure like # in cfengine.conf, cf.main, cf.groups # control: public = ( /usr/local/publicfiles ) almost_public = ( /usr/local/almostpublicfiles ) cfrunCommand = ( /iu/nexus/ud/mark/comp/Tests/cfrun-command ) MaxConnections = ( 10 ) ######################################################### admit: # or grant: $(public) * $(almost_public) *.iu.hioslo.no *.gnu.ai.mit.edu /etc/passwd *.iu.hioslo.no # # Who can exec cfengine remotely? # $(cfrunCommand) *.iu.hioslo.no ######################################################### deny: $(public)/special *.moneyworld.com @end smallexample @c ********************************************************************** @c INDEX @c ********************************************************************** @node Variable Index, Concept Index, Example configuration file, Top @unnumbered Variable Index @printindex vr @node Concept Index, FAQ Index, Variable Index, Top @unnumbered Concept Index @printindex cp @node FAQ Index, , Concept Index, Top @unnumbered FAQ Index @printindex mb @ifhtml @html @end html @end ifhtml @contents @ifhtml @html @end html @end ifhtml @bye cfengine-2.2.10/doc/cfetoolinfo.80000644000175000001440000001417510261007225013437 00000000000000.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "CFETOOLINFO 1" .TH CFETOOLINFO 1 "2004-09-21" "perl v5.8.4" "User Contributed Perl Documentation" .SH "NAME" cfetool info \- Get information about a database .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBcfetool\fR \fBinfo\fR \fIname\fR [\fB\-\-path\fR|\fB\-p\fR\ \fIdirectory\ name\fR] [\fB\-\-daily\fR|\fB\-d\fR] [\fB\-\-weekly\fR|\fB\-w\fR] [\fB\-\-yearly\fR|\fB\-y\fR] [\fB\-\-verbose\fR|\fB\-v\fR] [\fB\-\-help\fR|\fB\-h\fR] .SH "DESCRIPTION" .IX Header "DESCRIPTION" Prints out some basic information about the specified database, including: the location of the database, the location of the histogram file (if there is one), the step interval, the database age, the time it was last updated, and the current overall average and variation. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-\-path\fR|\fB\-p\fR \fIdirectory name\fR" 4 .IX Item "--path|-p directory name" The directory in which to find the database folder. If this argument is not provided, the current working directory will be assumed. .IP "\fB\-\-daily\fR|\fB\-d\fR" 4 .IX Item "--daily|-d" Provide information about the daily averages database. .IP "\fB\-\-weekly\fR|\fB\-w\fR" 4 .IX Item "--weekly|-w" Provide information about the weekly averages database. .IP "\fB\-\-yearly\fR|\fB\-y\fR" 4 .IX Item "--yearly|-y" Provide information about the yearly averages database. .IP "\fB\-\-verbose\fR|\fB\-v\fR" 4 .IX Item "--verbose|-v" Print details of the command's execution to the standard output stream. .IP "\fB\-\-help\fR|\fB\-h\fR" 4 .IX Item "--help|-h" Prints a short help message and then exits. .SH "EXAMPLE" .IX Header "EXAMPLE" .Vb 1 \& % cfetool info temperature --path /my/path .Ve .PP .Vb 7 \& Weekly average database: \& Database Location: /my/path/temperature/weekly.db \& Histogram file: /my/path/temperature/weekly.hist \& Step: 10 minutes \& Database Age: 0.000992 weeks (1 steps) \& Last update: Mon Sep 13 16:20:40 2004 (1095117640) \& Current average: 7.105000, Var: 38.280217 .Ve .SH "AUTHORS" .IX Header "AUTHORS" The code and documentation were contributed by Stanford Linear Accelerator Center, a department of Stanford University. This documentation was written by .IP "Elizabeth Cassell and" 4 .IX Item "Elizabeth Cassell and" .PD 0 .IP "Alf Wachsmann " 4 .IX Item "Alf Wachsmann " .PD .SH "COPYRIGHT AND DISCLAIMER" .IX Header "COPYRIGHT AND DISCLAIMER" .Vb 3 \& Copyright 2004 Alf Wachsmann and \& Elizabeth Cassell \& All rights reserved. .Ve cfengine-2.2.10/doc/cfetoolcheck.80000644000175000001440000002422710261007103013553 00000000000000.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "CFETOOLCHECK 1" .TH CFETOOLCHECK 1 "2004-09-21" "perl v5.8.4" "User Contributed Perl Documentation" .SH "NAME" cfetool check \- Check a new value against the averages currently in the database .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBcfetool\fR \fBcheck\fR \fIname\fR \&\fB\-\-value\fR|\fB\-V\fR\ \fIvalue\fR [\fB\-\-path\fR|\fB\-p\fR\ \fIdirectory\ name\fR] [\fB\-\-time\fR|\fB\-t\fR\ \fIseconds\fR] [\fB\-\-daily\fR|\fB\-d\fR] [\fB\-\-weekly\fR|\fB\-w\fR] [\fB\-\-yearly\fR|\fB\-y\fR] [\fB\-\-histograms\fR|\fB\-H\fR] [\fB\-\-verbose\fR|\fB\-v\fR] [\fB\-\-help\fR|\fB\-h\fR] .SH "DESCRIPTION" .IX Header "DESCRIPTION" Takes a new value and checks it against the averages currently in the database specified by \fIname\fR, located at the path specified by the \fB\-p\fR argument, or the current working directory if the \fB\-p\fR argument is ommitted. The value will be associated with the current time, unless the \fB\-t\fR option is given. The output indicates how much higher or lower the new value is compared to the averages in the database, in terms of the number of standard deviations. .PP The \fB\-d\fR, \fB\-w\fR and \fB\-y\fR options specify the databases to check the new value against. If all three options are omitted, only the weekly database will be accessed. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-\-value\fR|\fB\-v\fR \fIvalue\fR" 4 .IX Item "--value|-v value" Specifies the new value to check against the database averages. .IP "\fB\-\-path\fR|\fB\-p\fR \fIdirectory name\fR" 4 .IX Item "--path|-p directory name" The directory in which the database specified by \fIname\fR can be found. .IP "\fB\-\-time\fR|\fB\-t\fR" 4 .IX Item "--time|-t" The time the value was collected, in seconds since epoch (January 1st, 1970). If this argument is omitted, the current time will be used. .IP "\fB\-\-daily\fR|\fB\-d\fR" 4 .IX Item "--daily|-d" Check the new value against the daily averages database. .IP "\fB\-\-weekly\fR|\fB\-w\fR" 4 .IX Item "--weekly|-w" Check the new value against the weekly averages database. .IP "\fB\-\-yearly\fR|\fB\-y\fR" 4 .IX Item "--yearly|-y" Check the new value against the yearly averages database. .IP "\fB\-\-histograms\fR|\fB\-H\fR" 4 .IX Item "--histograms|-H" Check which histogram bucket the new value would fall into. The histogram is divided into 64 buckets, which represent distances from the mean value. Bucket 64 represents two standard deviations above the expected value, and bucket 0 represents two standard deviations below the expected value. .IP "\fB\-\-verbose\fR|\fB\-v\fR" 4 .IX Item "--verbose|-v" Print details of the command's execution to the standard output stream. .IP "\fB\-\-help\fR|\fB\-h\fR" 4 .IX Item "--help|-h" Print a short help message and then exit. .SH "OUTPUT" .IX Header "OUTPUT" Before exiting, \f(CW\*(C`cfetool check\*(C'\fR will print one line to the standard output stream, in the following format: .PP yrly=\fIynum\fR,bkt=\fIybkt\fR;wkly=\fIwnum\fR,bkt=\fIwbkt\fR;dly=\fIdnum\fR,bkt=\fIdbkt\fR .PP \&\fIybkt\fR, \fIwbkt\fR and \fIdbkt\fR represent the histogram bucket the given value falls into, and will be 0 for databases that are not being checked against, and if there is no histogram file or the \fB\-H\fR option was not specified. .PP \&\fIynum\fR, \fIwnum\fR and \fIdnum\fR will be either the number 0 if the corresponding database was not updated, or a code indicating the state of the given statistic, as compared to an average of equivalent earlier times, as specified below: .PP .Vb 27 \& code high|low|normal meaning \& ------------------------------------------------------------- \& -2 - no sigma variation \& ------------------------------------------------------------- \& -4 low within noise threshold, and within \& -5 normal 2 standard deviations from \& -6 high expected value \& ------------------------------------------------------------- \& -14 low microanomaly: within noise \& -15 normal threshold, but 2 or more standard \& -16 high deviations from expected value \& ------------------------------------------------------------- \& -24 low normal; within 1 standard deviation \& -25 normal from the expected value \& -26 high \& ------------------------------------------------------------- \& -34 low dev1; more than 1 standard \& -35 normal deviation from the expected \& -36 high value \& ------------------------------------------------------------ \& -44 low dev2; more than 2 standard \& -45 normal deviations from the expected \& -46 high value \& ------------------------------------------------------------- \& -54 low anomaly; more than 3 standard \& -55 normal deviations from the expected \& -56 high value .Ve .PP Where \*(L"low\*(R" indicates that the current value is below both the expected value for the current time position, and the global average value. \*(L"high\*(R" indicates that the current value is above those values. \*(L"normal\*(R" indicates that the current value is within the range of expected values. .PP \&\f(CW\*(C`cfetool check\*(C'\fR also exits with a code corresponding to the above table. If more than one database is being checked against, the most negative result from all checks is returned, and the individual results must be obtained from the standard output stream, as described above. .SH "EXAMPLE" .IX Header "EXAMPLE" .Vb 2 \& % cfetool check temperature --path /my/path --value 20 --histograms \& yrly=0,bkt=0;wkly=-6,bkt=51;dly=0,bkt=0 .Ve .PP Checks the value 20 against the weekly temperature database and histogram files located in \fB/my/path/\fR using the current time. The output indicates that the new value given was within cfetool's noise threshold, and also within 2 standard deviations of the previous average stored in the weekly database. .SH "AUTHORS" .IX Header "AUTHORS" The code and documentation were contributed by Stanford Linear Accelerator Center, a department of Stanford University. This documentation was written by .IP "Elizabeth Cassell and" 4 .IX Item "Elizabeth Cassell and" .PD 0 .IP "Alf Wachsmann " 4 .IX Item "Alf Wachsmann " .PD .SH "COPYRIGHT AND DISCLAIMER" .IX Header "COPYRIGHT AND DISCLAIMER" .Vb 3 \& Copyright 2004 Alf Wachsmann and \& Elizabeth Cassell \& All rights reserved. .Ve cfengine-2.2.10/doc/Makefile.am0000644000175000001440000000400011133653435013066 00000000000000# Info used in building the MAN files man_MANS = cfengine.8 cfagent.8 cfenvd.8 cfenvgraph.8 cfexecd.8 cfkey.8 cfrun.8 cfservd.8 cfshow.8 cfetoolcheck.8 cfetooldump.8 cfetoolimport.8 cfetoolupdate.8 cfetoolcreate.8 cfetoolgraph.8 cfetoolinfo.8 # Info used in building the Info files info_TEXINFOS = cfengine-Reference.texinfo cfengine-Tutorial.texinfo infofiles = $(info_TEXINFOS:.texinfo=.info) MAKEINFOHTML = $(MAKEINFO) --html --no-split --css-include=cfcomdoc.css # Info used in building and installing HTML files htmlfiles = $(info_TEXINFOS:.texinfo=.html) htmldir = $(pkgdatadir)/html html_DATA = $(htmlfiles) # Info used in building and installing Postscript files psfiles = $(info_TEXINFOS:.texinfo=.ps) pdffiles = $(info_TEXINFOS:.texinfo=.pdf) dvifiles = $(info_TEXINFOS:.texinfo=.dvi) docdir = $(pkgdatadir)/doc doc_DATA = $(psfiles) $(pdffiles) # Make sure these get distributed with everything else. EXTRA_DIST = cfagent.8 cfenvd.8 cfenvgraph.8 cfexecd.8 cfkey.8 cfrun.8 cfservd.8 cfengine.8 cfshow.8 cfetoolcheck.8 cfetooldump.8 cfetoolimport.8 cfetoolupdate.8 cfetoolcreate.8 cfetoolgraph.8 cfetoolinfo.8 cfetoolcheck.8 cfetooldump.8 cfetoolimport.8 cfetoolupdate.8 cfetoolcreate.8 cfetoolgraph.8 cfetoolinfo.8 texinfo.tex $(htmlfiles) $(infofiles) $(pdffiles) SUFFIXES = html latex pdf ps dvi %.html : %.texinfo ${MAKEINFO} -I $(srcdir) --html --no-split $< %.dvi : %.latex ${LATEX} $< %.dvi : %.texinfo ${TEXI2DVI} $< %.pdf : %.ps ${PS2PDF} $< # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = $(htmlfiles) $(psfiles) $(pdffiles) # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = *.log *.aux *.mbs *.mb *.info* # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in mdate-sh cfengine-2.2.10/doc/cfetoolgraph.80000644000175000001440000001557710261007212013610 00000000000000.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "CFETOOLGRAPH 1" .TH CFETOOLGRAPH 1 "2004-09-21" "perl v5.8.4" "User Contributed Perl Documentation" .SH "NAME" cfetoolgraph \- create graphs from a cfetool database .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBcfetoolgraph\fR \fIname\fR [\fB\-\-path\fR|\fB\-p\fR\ \fIdirectory\ name\fR] [\fB\-\-daily\fR|\fB\-d\fR] [\fB\-\-weekly\fR|\fB\-w\fR] [\fB\-\-yearly\fR|\fB\-y\fR] [\fB\-\-timestamps\fR|\fB\-T\fR] [\fB\-\-resolution\fR|\fB\-r\fR] [\fB\-\-help\fR|\fB\-h\fR] .SH "DESCRIPTION" .IX Header "DESCRIPTION" The cfetoolgraph command dumps graphs of averages for visual inspection of the normal state database. The files are in a format viewable by \f(CW\*(C`gnuplot\*(C'\fR or \&\f(CW\*(C`xgmr\*(C'\fR or other graphical plotting program. .PP The command generates three or four files in a subdirectory of the database directory with a name beginning with either \f(CW\*(C`daily\*(C'\fR, \f(CW\*(C`weekly\*(C'\fR or \f(CW\*(C`yearly\*(C'\fR, then \f(CW\*(C`\-\*(C'\fR, then either \f(CW\*(C`snapshot\*(C'\fR or the current time, if the \fB\-T\fR option is used. The files are named \f(CW\*(C`average\*(C'\fR, \f(CW\*(C`stddev\*(C'\fR, and \f(CW\*(C`graph\*(C'\fR. The \f(CW\*(C`graph\*(C'\fR file contains both the averages and standard deviations, useful for plotting with error bars. .PP If a histogram file is present, a fourth file named \f(CW\*(C`distr\*(C'\fR will also be created, plotting the distribution of fluctuations about the mean value. .PP If the \fB\-d\fR, \fB\-w\fR and \fB\-y\fR options are all omitted, the default is to only graph the weekly database. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-\-path\fR|\fB\-p\fR \fIdirectory name\fR" 4 .IX Item "--path|-p directory name" The directory in which the database specified by \fIname\fR can be found. .IP "\fB\-\-daily\fR|\fB\-d\fR" 4 .IX Item "--daily|-d" Graph the daily averages database. .IP "\fB\-\-weekly\fR|\fB\-w\fR" 4 .IX Item "--weekly|-w" Graph the weekly averages database. .IP "\fB\-\-yearly\fR|\fB\-y\fR" 4 .IX Item "--yearly|-y" Graph the yearly averages database. .IP "\fB\-\-timestamps\fR|\fB\-T\fR" 4 .IX Item "--timestamps|-T" Time-stamp the output filenames with the current time, in order to give a unique name. .IP "\fB\-\-resolution\fR|\fB\-r\fR" 4 .IX Item "--resolution|-r" Generate high resolution data (), instead of averaging data over periods of one hour to generate simpler and smoother graphs. .IP "\fB\-\-help\fR|\fB\-h\fR" 4 .IX Item "--help|-h" Prints a short help message and then exits. .SH "EXAMPLE" .IX Header "EXAMPLE" .Vb 1 \& % cfetoolgraph temperature --path /my/path --resolution .Ve .PP Create graph files of the weekly database in high resolution in the \&\f(CW\*(C`/my/path/temperature/weekly\-snapshot\*(C'\fR directory. .SH "AUTHORS" .IX Header "AUTHORS" The code and documentation were contributed by Stanford Linear Accelerator Center, a department of Stanford University. This documentation was written by .IP "Elizabeth Cassell and" 4 .IX Item "Elizabeth Cassell and" .PD 0 .IP "Alf Wachsmann " 4 .IX Item "Alf Wachsmann " .PD .SH "COPYRIGHT AND DISCLAIMER" .IX Header "COPYRIGHT AND DISCLAIMER" .Vb 3 \& Copyright 2004 Alf Wachsmann and \& Elizabeth Cassell \& All rights reserved. .Ve cfengine-2.2.10/README0000644000175000001440000000461210202123447011145 00000000000000-*- text -*- CFENGINE version 2 ------------------- Cfengine is a suite of programs for setting up and maintaining BSD and System-5-like operating system optionally attached to a TCP/IP network. You can think of cfengine as a very high level language and a self-learning software agent---much higher level than Perl or shell: a single statement can result in many hundreds of operations being performed on multiple hosts. Cfengine is good at performing a lot of common system administration tasks, and allows you to build on its strengths with your own scripts. You can also use it as a netwide front-end for cron. The main purpose of cfengine is to allow you to create a single, central system configuration which will define how every host on your network should be configured in an intuitive way. An interpreter/agent runs on every host on your network and parses the master file (or file-set); the configuration of each host is checked against this file and then, if you request it, any deviations from the defined configuration are fixed automatically. You do not have to mention every host specifically by name in order to configure them : instead you can refer to the properties which distinguish hosts from one another. Cfengine uses a flexible system of ``classes'' which helps you to single out a specific group of hosts with a single statement. New features in cfengine 2: * Program restructuring and rationalization. * All network connections are now mutually authenticated by public/private key methods, regardless of whether encryption is used to make communication private. * Improved network transfer efficiency. * Automated anomaly detection. * Improved reporting and scheduling mechanisms, based on recent research. Cfengine is written mainly by Mark Burgess at Oslo University College in Norway. Bug reports to bug-cfengine@gnu.org (News: gnu.cfengine.bug) General help to help-cfengine@gnu.org (News: gnu.cfengine.help) Official web site is at http://www.cfengine.org at Oslo University College. INSTALLATION ------------ To compile this program, you simply follow the standard GNU configure rules. At its simpleist, to build and install CFEngine in /usr/local, this would be: configure make make install Please read the detailed information at http://www.cfengine.org Users with mixed solaris/sparc mileux and new gcc, will need to compile on older machines with CFLAGS="-g -O2 -mv8" MB 2002 cfengine-2.2.10/AUTHORS0000644000175000001440000000107010202123437011327 00000000000000CFEngine Design and Development =============================== Mark Burgess Mark.Burgess@iu.hio.no Automake/Autoconf Setup ======================= David Masterson David.Masterson@kla-tencor.com cfrun modifications =================== Bas van der Vlies Andy Mayhew Windows port ============= Bjørn Gustafson and Jørgen Kjensli did the inital port to NT using cygwin Martin Andrews supplied support for NT filenames and some bugfixes, he also provide a number of other suggestions and patches over time. Miscellaneous patches ===================== Bryan S. Blankcfengine-2.2.10/COPYING0000644000175000001440000004356710202123462011331 00000000000000 This program is provided under the terms of the GNU public license (below), with explicit permission to link with the OpenSSL library. (http://www.openssl.org) On some systems, code under the Frontier Artistic License (/pub/snprintf) might become compiled. This is compatible with the GPL. 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) 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) year 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. cfengine-2.2.10/NEWS0000644000175000001440000000000010202123462010744 00000000000000cfengine-2.2.10/config.sub0000744000175000001440000007054310202123447012254 00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-03-07' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. # # This file 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. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS $0 [OPTION] ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit 0;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis) os= basic_machine=$1 ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ | c4x | clipper \ | d10v | d30v | dsp16xx \ | fr30 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ | m32r | m68000 | m68k | m88k | mcore \ | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ | mips64vr4100 | mips64vr4100el | mips64vr4300 \ | mips64vr4300el | mips64vr5000 | mips64vr5000el \ | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ | mipsisa32 | mipsisa64 \ | mn10200 | mn10300 \ | ns16k | ns32k \ | openrisc | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic80 | tron \ | v850 | v850e \ | we32k \ | x86 | xscale | xstormy16 | xtensa \ | z8k) basic_machine=$basic_machine-unknown ;; m6811 | m68hc11 | m6812 | m68hc12) # Motorola 68HC11/12. basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | arm-* | armbe-* | armle-* | armv*-* \ | avr-* \ | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c54x-* \ | clipper-* | cydra-* \ | d10v-* | d30v-* \ | elxsi-* \ | f30[01]-* | f700-* | fr30-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ | m32r-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; c90) basic_machine=c90-cray os=-unicos ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; crds | unos) basic_machine=m68k-crds ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; # I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; mingw32) basic_machine=i386-pc os=-mingw32 ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; mmix*) basic_machine=mmix-knuth os=-mmixware ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; msdos) basic_machine=i386-pc os=-msdos ;; mvs) basic_machine=i370-ibm os=-mvs ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; or32 | or32-*) basic_machine=or32-unknown os=-coff ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon) basic_machine=i686-pc ;; pentiumii | pentium2) basic_machine=i686-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3d) basic_machine=alpha-cray os=-unicos ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; windows32) basic_machine=i386-pc os=-windows32-msvcrt ;; xps | xps100) basic_machine=xps100-honeywell ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh3 | sh4 | sh3eb | sh4eb) basic_machine=sh-unknown ;; sh64) basic_machine=sh64-unknown ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; c4x*) basic_machine=c4x-none os=-coff ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto*) os=-nto-qnx ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 # This also exists in the configure program, but was not the # default. # os=-sunos4 ;; m68*-cisco) os=-aout ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-ibm) os=-aix ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -ptx*) vendor=sequent ;; -vxsim* | -vxworks*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit 0 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: cfengine-2.2.10/compile0000744000175000001440000000717311045561061011652 00000000000000#! /bin/sh # Wrapper for compilers which do not understand `-c -o'. scriptversion=2005-05-14.22 # Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. # Written by Tom Tromey . # # 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand `-c -o'. Remove `-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file `INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; esac ofile= cfile= eat= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as `compile cc -o foo foo.c'. # So we strip `-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no `-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # `.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'` # Create the lock directory. # Note: use `[/.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: cfengine-2.2.10/acinclude.m40000644000175000001440000001710710202124173012456 00000000000000dnl From http://www.gnu.org/software/ac-archive/Installed_Packages/acx_pthread.html dnl modified to set CPPFLAGS AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_SAVE AC_LANG_C acx_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS$PTHREAD_CPPFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $PTHREAD_CPPFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # pthread: Linux, etcetera # --thread-safe: KAI C++ case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthread or # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" PTHREAD_CPPFLAGS="$flag" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" save_CPPFLAGS="$CPPFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CPPFLAGS="$CFLAGS $PTHREAD_CPPFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" PTHREAD_CPPFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CFLAGS $PTHREAD_CPPFLAGS" # Detect AIX lossage: threads are created detached by default # and the JOINABLE attribute has a nonstandard name (UNDETACHED). AC_MSG_CHECKING([for joinable pthread attribute]) AC_TRY_LINK([#include ], [int attr=PTHREAD_CREATE_JOINABLE;], ok=PTHREAD_CREATE_JOINABLE, ok=unknown) if test x"$ok" = xunknown; then AC_TRY_LINK([#include ], [int attr=PTHREAD_CREATE_UNDETACHED;], ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) fi if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, [Define to the necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_RESULT(${ok}) if test x"$ok" = xunknown; then AC_MSG_WARN([we do not know how to create joinable pthreads]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; # -D_REENTRANT is actually implied by -pthread in Tru64 5.1, # at least. *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" PTHREAD_CPPFLAGS="$flag $PTHREAD_CPPFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" CPPFLAGS="$save_CPPFLAGS" # More AIX lossage: must compile with cc_r AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, [${CC}]) else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CPPFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi AC_LANG_RESTORE ])dnl ACX_PTHREAD cfengine-2.2.10/src/0000777000175000001440000000000011170173454011145 500000000000000cfengine-2.2.10/src/cfservd.c0000644000175000001440000027220511162761300012663 00000000000000 /* Copyright (C) 1995- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Cfservd : remote server daemon */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include "cfservd.h" #include #include /*******************************************************************/ /* GLOBAL VARIABLES */ /*******************************************************************/ int CLOCK_DRIFT = 3600; /* 1hr */ int CFD_MAXPROCESSES = 0; int ACTIVE_THREADS = 0; int NO_FORK = false; int MULTITHREAD = false; int CHECK_RFC931 = false; int CFD_INTERVAL = 0; int DENYBADCLOCKS = true; int MULTIPLECONNS = false; int TRIES = 0; int MAXTRIES = 5; int LOGCONNS = false; int LOGENCRYPT = false; struct option CFDOPTIONS[] = { { "help",no_argument,0,'h' }, { "debug",optional_argument,0,'d' }, { "verbose",no_argument,0,'v' }, { "file",required_argument,0,'f' }, { "no-fork",no_argument,0,'F' }, { "parse-only",no_argument,0,'p'}, { "ld-library-path",required_argument,0,'L'}, { NULL,0,0,0 } }; struct Item *CONNECTIONLIST = NULL; /*******************************************************************/ /* Functions internal to cfservd.c */ /*******************************************************************/ void CheckOptsAndInit (int argc,char **argv); void CheckVariables (void); void Syntax (void); void SummarizeParsing (void); void StartServer (int argc, char **argv); int OpenReceiverChannel (void); void PurgeOldConnections (struct Item **list,time_t now); void SpawnConnection (int sd_reply, char *ipaddr); void CheckFileChanges (int argc, char **argv, int sd); void *HandleConnection (struct cfd_connection *conn); int BusyWithConnection (struct cfd_connection *conn); void *ExitCleanly (int signum); int MatchClasses (struct cfd_connection *conn); void DoExec (struct cfd_connection *conn, char *sendbuffer, char *args); int GetCommand (char *str); int VerifyConnection (struct cfd_connection *conn, char *buf); void RefuseAccess (struct cfd_connection *conn, char *sendbuffer, int size, char *errormsg); int AccessControl (char *filename, struct cfd_connection *conn, int encrypt); int CheckStoreKey (struct cfd_connection *conn, RSA *key); int StatFile (struct cfd_connection *conn, char *sendbuffer, char *filename); void CfGetFile (struct cfd_get_arg *args); void CompareLocalChecksum (struct cfd_connection *conn, char *sendbuffer, char *recvbuffer); int CfOpenDirectory (struct cfd_connection *conn, char *sendbuffer, char *dirname); int CfSecOpenDirectory (struct cfd_connection *conn, char *sendbuffer, char *dirname); void Terminate (int sd); void DeleteAuthList (struct Auth *ap); int AllowedUser (char *user); void ReplyNothing (struct cfd_connection *conn); struct cfd_connection *NewConn (int sd); void DeleteConn (struct cfd_connection *conn); time_t SecondsTillAuto (void); void SetAuto (int seconds); int cfscanf (char *in, int len1, int len2, char *out1, char *out2, char *out3); int AuthenticationDialogue (struct cfd_connection *conn,char *buffer, int buffersize); char *MapAddress (char *addr); int IsWildKnownHost (RSA *oldkey,RSA *newkey,char *addr,char *user); void AddToKeyDB (RSA *key,char *addr); int SafeOpen (char *filename); void SafeClose (int fd); int WordHere(char *args, char *pos, char *word); in_addr_t GetInetAddr (char *host); /*******************************************************************/ /* Level 0 : Main */ /*******************************************************************/ int main (int argc,char **argv) { CheckOptsAndInit(argc,argv); ParseInputFile(VINPUTFILE,true); /* We call CfOpenLog again so, if we configure SyslogFacility, we open syslog again */ closelog(); CfOpenLog(); CheckVariables(); SummarizeParsing(); if (PARSEONLY) { exit(0); } StartServer(argc,argv); /* Never exit here */ return 0; } /********************************************************************/ /* Level 1 */ /********************************************************************/ void CheckOptsAndInit(int argc,char **argv) { extern char *optarg; int optindex = 0; char ld_library_path[CF_BUFSIZE],vbuff[CF_BUFSIZE]; int c; SetContext("server"); sprintf(VPREFIX, "cfservd"); CfOpenLog(); strcpy(VINPUTFILE,CFD_INPUT); strcpy(CFLOCK,"cfservd"); OUTPUT[0] = '\0'; /* * HvB: Bas van der Vlies */ BINDINTERFACE[0] = '\0'; CfenginePort(); StrCfenginePort(); SetSignals(); ISCFENGINE = false; /* Switch for the parser */ PARSEONLY = false; ld_library_path[0] = '\0'; InstallObject("server"); AddClassToHeap("any"); /* This is a reserved word / wildcard */ while ((c=getopt_long(argc,argv,"L:d:f:vmhpFV",CFDOPTIONS,&optindex)) != EOF) { switch ((char) c) { case 'f': strncpy(VINPUTFILE,optarg,CF_BUFSIZE-1); MINUSF = true; break; case 'd': switch ((optarg==NULL)?3:*optarg) { case '1': D1 = true; break; case '2': D2 = true; break; default: DEBUG = true; break; } NO_FORK = true; printf("cfservd: Debug mode: running in foreground\n"); break; case 'v': VERBOSE = true; break; case 'V': printf("GNU %s-%s daemon\n%s\n",PACKAGE,VERSION,COPYRIGHT); printf("This program is covered by the GNU Public License and may be\n"); printf("copied free of charge. No warrenty is implied.\n\n"); exit(0); break; case 'p': PARSEONLY = true; break; case 'F': NO_FORK = true; break; case 'L': Verbose("Setting LD_LIBRARY_PATH=%s\n",optarg); snprintf(ld_library_path,CF_BUFSIZE-1,"LD_LIBRARY_PATH=%s",optarg); putenv(ld_library_path); break; case 'm': /* No longer needed */ break; default: Syntax(); exit(1); } } LOGGING = true; /* Do output to syslog */ IDClasses(); SetReferenceTime(true); GetNameInfo(); GetInterfaceInfo(); GetV6InterfaceInfo(); if ((CFINITSTARTTIME = time((time_t *)NULL)) == -1) { CfLog(cferror,"Couldn't read system clock\n","time"); } if ((CFSTARTTIME = time((time_t *)NULL)) == -1) { CfLog(cferror,"Couldn't read system clock\n","time"); } /* XXX Initialize workdir for non privileged users */ strcpy(CFWORKDIR,WORKDIR); #ifndef NT if (getuid() > 0) { char *homedir; if ((homedir = getenv("HOME")) != NULL) { strcpy(CFWORKDIR,homedir); strcat(CFWORKDIR,"/.cfagent"); } } #endif snprintf(vbuff,CF_BUFSIZE,"%s/test",CFWORKDIR); MakeDirectoriesFor(vbuff,'y'); strncpy(VLOGDIR,CFWORKDIR,CF_BUFSIZE-1); strncpy(VLOCKDIR,CFWORKDIR,CF_BUFSIZE-1); VIFELAPSED = CF_EXEC_IFELAPSED; VEXPIREAFTER = CF_EXEC_EXPIREAFTER; strcpy(VDOMAIN,"undefined.domain"); VCANONICALFILE = strdup(CanonifyName(VINPUTFILE)); VREPOSITORY = strdup("\0"); LISTSEPARATOR = ','; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); CheckWorkDirectories(); RandomSeed(); LoadSecretKeys(); } /*******************************************************************/ void CheckVariables() { struct stat statbuf; int i; char ebuff[CF_EXPANDSIZE]; #ifdef HAVE_PTHREAD_H CfLog(cfinform,"cfservd Multithreaded version",""); #else CfLog(cfinform,"cfservd Single threaded version",""); #endif strncpy(VFQNAME,VSYSNAME.nodename,CF_MAXVARSIZE-1); if ((CFDSTARTTIME = time((time_t *)NULL)) == -1) { printf("Couldn't read system clock\n"); } if (OptionIs(CONTEXTID,"CheckIdent", true)) { CHECK_RFC931 = true; } if (OptionIs(CONTEXTID,"DenyBadClocks", false)) { DENYBADCLOCKS = false; } if (OptionIs(CONTEXTID,"LogAllConnections", true)) { LOGCONNS = true; } if (OptionIs(CONTEXTID,"LogEncryptedTransfers", true)) { LOGENCRYPT = true; } if (OptionIs(CONTEXTID,"Auditing",true)) { AUDIT = true; } if (GetMacroValue(CONTEXTID,"ChecksumDatabase")) { snprintf(ebuff,CF_BUFSIZE,"%s/%s",CFWORKDIR,CF_CHKDB); /* CHECKSUMDB = strdup(ebuff);*/ CHECKSUMDB = NULL; Verbose("Checksum database is no longer used in cfservd\n"); } memset(CFRUNCOMMAND,0,CF_BUFSIZE); if (GetMacroValue(CONTEXTID,"cfrunCommand")) { ExpandVarstring("$(cfrunCommand)",ebuff,NULL); if (*ebuff != '/') { FatalError("$(cfrunCommand) does not expand to an absolute filename\n"); } sscanf(ebuff,"%4095s",CFRUNCOMMAND); Debug("cfrunCommand is %s\n",CFRUNCOMMAND); if (stat(CFRUNCOMMAND,&statbuf) == -1) { FatalError("$(cfrunCommand) points to a non-existent file\n"); } } if (GetMacroValue(CONTEXTID,"MaxConnections")) { ExpandVarstring("$(MaxConnections)",ebuff,NULL); Debug("$(MaxConnections) Expanded to %s\n",ebuff); CFD_MAXPROCESSES = atoi(ebuff); MAXTRIES = CFD_MAXPROCESSES / 3; /* How many attempted connections over max before we commit suicide? */ if ((CFD_MAXPROCESSES < 1) || (CFD_MAXPROCESSES > 10000)) { FatalError("cfservd MaxConnections with silly value"); } } else { CFD_MAXPROCESSES = 10; MAXTRIES = 5; } CFD_INTERVAL = 0; Debug("MaxConnections = %d\n",CFD_MAXPROCESSES); CHECKSUMUPDATES = true; if (OptionIs(CONTEXTID,"ChecksumUpdates", false)) { CHECKSUMUPDATES = false; } i = 0; strncpy(ebuff,ToLowerStr(VDOMAIN),127); if (StrStr(VSYSNAME.nodename,ebuff)) { strncpy(VFQNAME,VSYSNAME.nodename,CF_MAXVARSIZE-1); while(VSYSNAME.nodename[i++] != '.') { } strncpy(VUQNAME,VSYSNAME.nodename,i-1); } else { snprintf(VFQNAME,CF_BUFSIZE,"%s.%s",VSYSNAME.nodename,ToLowerStr(VDOMAIN)); strncpy(VUQNAME,VSYSNAME.nodename,CF_MAXVARSIZE-1); } /* * HvB: Bas van der Vlies * bind to only one interface */ if (GetMacroValue(CONTEXTID,"BindToInterface")) { ExpandVarstring("$(BindToInterface)",ebuff,NULL); strncpy(BINDINTERFACE,ebuff, CF_BUFSIZE-1); Debug("$(BindToInterface) Expanded to %s\n",BINDINTERFACE); } } /*******************************************************************/ void SummarizeParsing() { struct Auth *ptr; struct Item *ip,*ipr; if (VERBOSE || DEBUG || D2 || D3) { ListDefinedClasses(); } if (DEBUG || D2 || D3) { printf("ACCESS GRANTED ----------------------:\n\n"); for (ptr = VADMIT; ptr != NULL; ptr=ptr->next) { printf("Path: %s (encrypt=%d)\n",ptr->path,ptr->encrypt); for (ip = ptr->accesslist; ip != NULL; ip=ip->next) { printf(" Admit: %s root=",ip->name); for (ipr = ptr->maproot; ipr !=NULL; ipr=ipr->next) { printf("%s,",ipr->name); } printf("\n"); } } printf("ACCESS DENIAL ------------------------ :\n\n"); for (ptr = VDENY; ptr != NULL; ptr=ptr->next) { printf("Path: %s\n",ptr->path); for (ip = ptr->accesslist; ip != NULL; ip=ip->next) { printf(" Deny: %s\n",ip->name); } } printf("Host IPs allowed connection access :\n\n"); for (ip = NONATTACKERLIST; ip != NULL; ip=ip->next) { printf("IP: %s\n",ip->name); } printf("Host IPs denied connection access :\n\n"); for (ip = ATTACKERLIST; ip != NULL; ip=ip->next) { printf("IP: %s\n",ip->name); } printf("Host IPs allowed multiple connection access :\n\n"); for (ip = MULTICONNLIST; ip != NULL; ip=ip->next) { printf("IP: %s\n",ip->name); } printf("Host IPs from whom we shall accept public keys on trust :\n\n"); for (ip = TRUSTKEYLIST; ip != NULL; ip=ip->next) { printf("IP: %s\n",ip->name); } printf("Host IPs from NAT which we don't verify :\n\n"); for (ip = SKIPVERIFY; ip != NULL; ip=ip->next) { printf("IP: %s\n",ip->name); } printf("Dynamical Host IPs (e.g. DHCP) whose bindings could vary over time :\n\n"); for (ip = DHCPLIST; ip != NULL; ip=ip->next) { printf("IP: %s\n",ip->name); } } if (ERRORCOUNT > 0) { FatalError("Execution terminated after parsing due to errors in program"); } } /*******************************************************************/ void StartServer(int argc,char **argv) { char ipaddr[CF_MAXVARSIZE],intime[64]; int sd,sd_reply; fd_set rset; time_t now; struct timeval timeout; int ret_val; #if defined(HAVE_GETADDRINFO) int addrlen=sizeof(struct sockaddr_in6); struct sockaddr_in6 cin; #else int addrlen=sizeof(struct sockaddr_in); struct sockaddr_in cin; #endif if ((sd = OpenReceiverChannel()) == -1) { CfLog(cferror,"Unable to start server",""); exit(1); } signal(SIGINT,(void*)ExitCleanly); signal(SIGTERM,(void*)ExitCleanly); signal(SIGHUP,SIG_IGN); signal(SIGPIPE,SIG_IGN); signal(SIGCHLD,SIG_IGN); signal(SIGUSR1,HandleSignal); signal(SIGUSR2,HandleSignal); if (listen(sd,queuesize) == -1) { CfLog(cferror,"listen failed","listen"); exit(1); } Verbose("Listening for connections ...\n"); if ((!NO_FORK) && (fork() != 0)) { snprintf(OUTPUT,CF_BUFSIZE*2,"cfservd starting %.24s\n",ctime(&CFDSTARTTIME)); CfLog(cfinform,OUTPUT,""); closelog(); exit(0); } if (!NO_FORK) { ActAsDaemon(sd); } WritePID("cfservd.pid"); /* Andrew Stribblehill -- close sd on exec */ fcntl(sd, F_SETFD, FD_CLOEXEC); while (true) { if (ACTIVE_THREADS == 0) { CheckFileChanges(argc,argv,sd); } FD_ZERO(&rset); FD_SET(sd,&rset); timeout.tv_sec = 10; /* Set a 10 second timeout for select */ timeout.tv_usec = 0; ret_val = select((sd+1),&rset,NULL,NULL,&timeout); if (ret_val == -1) /* Error received from call to select */ { if (errno == EINTR) { continue; } else { CfLog(cferror, "select failed", "select"); exit(1); } } else if (!ret_val) /* No data waiting, we must have timed out! */ { continue; } if ((sd_reply = accept(sd,(struct sockaddr *)&cin,&addrlen)) != -1) { memset(ipaddr,0,CF_MAXVARSIZE); snprintf(ipaddr,CF_MAXVARSIZE-1,"%s",sockaddr_ntop((struct sockaddr *)&cin)); Debug("Obtained IP address of %s on socket %d from accept\n",ipaddr,sd_reply); if ((NONATTACKERLIST != NULL) && !IsFuzzyItemIn(NONATTACKERLIST,MapAddress(ipaddr))) /* Allowed Subnets */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Denying connection from non-authorized IP %s\n",ipaddr); CfLog(cferror,OUTPUT,""); close(sd_reply); continue; } if (IsFuzzyItemIn(ATTACKERLIST,MapAddress(ipaddr))) /* Denied Subnets */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Denying connection from non-authorized IP %s\n",ipaddr); CfLog(cferror,OUTPUT,""); close(sd_reply); continue; } if ((now = time((time_t *)NULL)) == -1) { now = 0; } PurgeOldConnections(&CONNECTIONLIST,now); if (!IsFuzzyItemIn(MULTICONNLIST,MapAddress(ipaddr))) { if (IsItemIn(CONNECTIONLIST,MapAddress(ipaddr))) { snprintf(OUTPUT,CF_BUFSIZE*2,"Denying repeated connection from %s\n",ipaddr); CfLog(cferror,OUTPUT,""); close(sd_reply); continue; } } if (LOGCONNS) { snprintf(OUTPUT,CF_BUFSIZE*2,"Accepting connection from %s\n",ipaddr); CfLog(cfinform,OUTPUT,""); } snprintf(intime,63,"%d",(int)now); #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock"); return; } #endif PrependItem(&CONNECTIONLIST,MapAddress(ipaddr),intime); #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","pthread_mutex_unlock"); return; } #endif SpawnConnection(sd_reply,ipaddr); } } } /*******************************************************************************/ in_addr_t GetInetAddr(char *host) { struct in_addr addr; struct hostent *hp; addr.s_addr = inet_addr(host); if ((addr.s_addr == INADDR_NONE) || (addr.s_addr == 0)) { if ((hp = gethostbyname(host)) == 0) { snprintf(OUTPUT,CF_BUFSIZE,"\nhost not found: %s\n",host); FatalError(OUTPUT); } if (hp->h_addrtype != AF_INET) { snprintf(OUTPUT,CF_BUFSIZE,"unexpected address family: %d\n",hp->h_addrtype); FatalError(OUTPUT); } if (hp->h_length != sizeof(addr)) { snprintf(OUTPUT,CF_BUFSIZE,"unexpected address length %d\n",hp->h_length); FatalError(OUTPUT); } memcpy((char *) &addr, hp->h_addr, hp->h_length); } return (addr.s_addr); } /*********************************************************************/ /* Level 2 */ /*********************************************************************/ int OpenReceiverChannel() { int sd; int yes=1; char *ptr = NULL; struct linger cflinger; #if defined(HAVE_GETADDRINFO) struct addrinfo query,*response,*ap; #else struct sockaddr_in sin; #endif cflinger.l_onoff = 1; cflinger.l_linger = 60; #if defined(HAVE_GETADDRINFO) memset(&query,0,sizeof(struct addrinfo)); query.ai_flags = AI_PASSIVE; query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; /* * HvB : Bas van der Vlies */ if (BINDINTERFACE[0] != '\0' ) { ptr = BINDINTERFACE; } if (getaddrinfo(ptr,STR_CFENGINEPORT,&query,&response) != 0) { CfLog(cferror,"DNS/service lookup failure","getaddrinfo"); return -1; } sd = -1; for (ap = response ; ap != NULL; ap=ap->ai_next) { if ((sd = socket(ap->ai_family,ap->ai_socktype,ap->ai_protocol)) == -1) { continue; } if (setsockopt(sd, SOL_SOCKET,SO_REUSEADDR,(char *)&yes,sizeof (int)) == -1) { CfLog(cferror,"Socket options were not accepted","setsockopt"); exit(1); } if (setsockopt(sd, SOL_SOCKET, SO_LINGER,(char *)&cflinger,sizeof (struct linger)) == -1) { CfLog(cferror,"Socket options were not accepted","setsockopt"); exit(1); } if (bind(sd,ap->ai_addr,ap->ai_addrlen) == 0) { Debug("Bound to address %s on %s=%d\n",sockaddr_ntop(ap->ai_addr),CLASSTEXT[VSYSTEMHARDCLASS],VSYSTEMHARDCLASS); if (VSYSTEMHARDCLASS == openbsd || VSYSTEMHARDCLASS == freebsd || VSYSTEMHARDCLASS == netbsd || VSYSTEMHARDCLASS == dragonfly) { continue; /* *bsd doesn't map ipv6 addresses */ } else { break; } } CfLog(cferror,"Could not bind server address","bind"); close(sd); sd = -1; } if (sd < 0) { CfLog(cferror,"Couldn't open bind an open socket\n",""); exit(1); } if (response != NULL) { freeaddrinfo(response); } #else memset(&sin,0,sizeof(sin)); if (BINDINTERFACE[0] != '\0' ) { sin.sin_addr.s_addr = GetInetAddr(BINDINTERFACE); } else { sin.sin_addr.s_addr = INADDR_ANY; } sin.sin_port = (unsigned short)SHORT_CFENGINEPORT; sin.sin_family = AF_INET; if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1) { CfLog(cferror,"Couldn't open socket","socket"); exit (1); } if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, sizeof (int)) == -1) { CfLog(cferror,"Couldn't set socket options","sockopt"); exit (1); } if (setsockopt(sd, SOL_SOCKET, SO_LINGER, (char *) &cflinger, sizeof (struct linger)) == -1) { CfLog(cferror,"Couldn't set socket options","sockopt"); exit (1); } if (bind(sd,(struct sockaddr *)&sin,sizeof(sin)) == -1) { CfLog(cferror,"Couldn't bind to socket","bind"); exit(1); } #endif return sd; } /*********************************************************************/ /* Level 3 */ /*********************************************************************/ void Syntax() { int i; printf("GNU cfengine daemon: server module\n%s-%s\n%s\n",PACKAGE,VERSION,COPYRIGHT); printf("\n"); printf("Options:\n\n"); for (i=0; CFDOPTIONS[i].name != NULL; i++) { printf("--%-20s (-%c)\n",CFDOPTIONS[i].name,(char)CFDOPTIONS[i].val); } printf("\nBug reports to bug-cfengine@cfengine.org\n"); printf("General help to help-cfengine@cfengine.org\n"); printf("Info & fixes at http://www.cfengine.org\n"); } /*********************************************************************/ void PurgeOldConnections(struct Item **list,time_t now) /* Some connections might not terminate properly. These should be cleaned every couple of hours. That should be enough to prevent spamming. */ { struct Item *ip; int then=0; if (list == NULL) { return; } Debug("Purging Old Connections...\n"); #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock"); return; } #endif for (ip = *list; ip != NULL; ip=ip->next) { sscanf(ip->classes,"%d",&then); if (now > then + 7200) { DeleteItem(list,ip); snprintf(OUTPUT,CF_BUFSIZE*2,"Purging IP address %s from connection list\n",ip->name); CfLog(cfverbose,OUTPUT,""); } } #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","pthread_mutex_unlock"); return; } #endif Debug("Done purging\n"); } /*********************************************************************/ void SpawnConnection(int sd_reply,char *ipaddr) { struct cfd_connection *conn; #ifdef HAVE_PTHREAD_H pthread_t tid; #endif conn = NewConn(sd_reply); strncpy(conn->ipaddr,ipaddr,CF_MAX_IP_LEN-1); Verbose("New connection...(from %s/%d)\n",conn->ipaddr,sd_reply); #if defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD Verbose("Spawning new thread...\n"); pthread_attr_init(&PTHREADDEFAULTS); pthread_attr_setdetachstate(&PTHREADDEFAULTS,PTHREAD_CREATE_DETACHED); #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE pthread_attr_setstacksize(&PTHREADDEFAULTS,(size_t)1024*1024); #endif if (pthread_create(&tid,&PTHREADDEFAULTS,(void *)HandleConnection,(void *)conn) != 0) { CfLog(cferror,"pthread_create failed","create"); HandleConnection(conn); } pthread_attr_destroy(&PTHREADDEFAULTS); #else /* Can't fork here without getting a zombie unless we do some complex waiting? */ Verbose("Single threaded...\n"); HandleConnection(conn); #endif } /**************************************************************/ void CheckFileChanges(int argc,char **argv,int sd) { struct stat newstat; char filename[CF_BUFSIZE],*sp; memset(&newstat,0,sizeof(struct stat)); memset(filename,0,CF_BUFSIZE); if ((sp=getenv(CF_INPUTSVAR)) != NULL) { if (!IsAbsoluteFileName(VINPUTFILE)) /* Don't prepend to absolute names */ { strncpy(filename,sp,CF_BUFSIZE-1); AddSlash(filename); } } else { if ((*VINPUTFILE != '.') && !IsAbsoluteFileName(VINPUTFILE)) /* Don't prepend to absolute names */ { strncpy(filename,CFWORKDIR,CF_BUFSIZE-1); AddSlash(filename); strncat(filename,"inputs/",CF_BUFSIZE-1-strlen(filename)); } } strncat(filename,VINPUTFILE,CF_BUFSIZE-1-strlen(filename)); if (stat(filename,&newstat) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Input file %s missing or busy..\n",filename); CfLog(cferror,OUTPUT,filename); sleep(5); return; } Debug("Checking file updates on %s (%x/%x)\n",filename, newstat.st_mtime, CFDSTARTTIME); if (CFDSTARTTIME < newstat.st_mtime) { snprintf(OUTPUT,CF_BUFSIZE*2,"Rereading config files %s..\n",filename); CfLog(cfinform,OUTPUT,""); /* Free & reload -- lock this to avoid access errors during reload */ DeleteItemList(VHEAP); DeleteItemList(VNEGHEAP); DeleteItemList(TRUSTKEYLIST); DeleteItemList(VIMPORT); DeleteItemList(SKIPVERIFY); DeleteItemList(DHCPLIST); DeleteItemList(ATTACKERLIST); DeleteItemList(NONATTACKERLIST); DeleteItemList(MULTICONNLIST); DeleteAuthList(VADMIT); DeleteAuthList(VDENY); strcpy(VDOMAIN,"undefined.domain"); VADMIT = VADMITTOP = NULL; VDENY = VDENYTOP = NULL; VHEAP = VNEGHEAP = NULL; VIMPORT = NULL; TRUSTKEYLIST = NULL; SKIPVERIFY = NULL; DHCPLIST = NULL; ATTACKERLIST = NULL; NONATTACKERLIST = NULL; MULTICONNLIST = NULL; BlankHashTable("server"); AddClassToHeap("any"); GetNameInfo(); GetInterfaceInfo(); GetV6InterfaceInfo(); ParseInputFile(VINPUTFILE,true); CheckVariables(); SummarizeParsing(); } } /*********************************************************************/ /* Level 4 */ /*********************************************************************/ void *HandleConnection(struct cfd_connection *conn) { #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) #ifdef HAVE_PTHREAD_SIGMASK sigset_t sigmask; sigemptyset(&sigmask); pthread_sigmask(SIG_BLOCK,&sigmask,NULL); #endif if (conn == NULL) { Debug("Null connection\n"); return NULL; } if (pthread_mutex_lock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock"); DeleteConn(conn); return NULL; } ACTIVE_THREADS++; if (pthread_mutex_unlock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","unlock"); } if (ACTIVE_THREADS >= CFD_MAXPROCESSES) { if (pthread_mutex_lock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock"); DeleteConn(conn); return NULL; } ACTIVE_THREADS--; if (TRIES++ > MAXTRIES) /* When to say we're hung / apoptosis threshold */ { CfLog(cferror,"Server seems to be paralyzed. DOS attack? Committing apoptosis...",""); ExitCleanly(0); } if (pthread_mutex_unlock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","unlock"); } snprintf(OUTPUT,CF_BUFSIZE,"Too many threads (>=%d) -- increase MaxConnections?",CFD_MAXPROCESSES); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE,"BAD: Server is currently too busy -- increase MaxConnections or Splaytime?"); SendTransaction(conn->sd_reply,OUTPUT,0,CF_DONE); DeleteConn(conn); return NULL; } TRIES = 0; /* As long as there is activity, we're not stuck */ #endif while (BusyWithConnection(conn)) { } #if defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD Debug("Terminating thread...\n"); if (pthread_mutex_lock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock"); DeleteConn(conn); return NULL; } ACTIVE_THREADS--; if (pthread_mutex_unlock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","unlock"); } #endif DeleteConn(conn); return NULL; } /*********************************************************************/ int BusyWithConnection(struct cfd_connection *conn) /* This is the protocol section. Here we must */ /* check that the incoming data are sensible */ /* and extract the information from the message */ { time_t tloc, trem = 0; char recvbuffer[CF_BUFSIZE+CF_BUFEXT], sendbuffer[CF_BUFSIZE],check[CF_BUFSIZE]; char filename[CF_BUFSIZE],buffer[CF_BUFSIZE],args[CF_BUFSIZE],out[CF_BUFSIZE]; long time_no_see = 0; unsigned int len=0; int drift, plainlen, received; struct cfd_get_arg get_args; memset(recvbuffer,0,CF_BUFSIZE+CF_BUFEXT); memset(&get_args,0,sizeof(get_args)); if ((received = ReceiveTransaction(conn->sd_reply,recvbuffer,NULL)) == -1) { return false; } if (strlen(recvbuffer) == 0) { Debug("cfservd terminating NULL transmission!\n"); return false; } Debug("Received: [%s] on socket %d\n",recvbuffer,conn->sd_reply); switch (GetCommand(recvbuffer)) { case cfd_exec: memset(args,0,CF_BUFSIZE); sscanf(recvbuffer,"EXEC %[^\n]",args); if (!conn->id_verified) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (!AllowedUser(conn->username)) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (!conn->rsa_auth) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (!AccessControl(CFRUNCOMMAND,conn,false)) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (!MatchClasses(conn)) { Terminate(conn->sd_reply); return false; } DoExec(conn,sendbuffer,args); Terminate(conn->sd_reply); return false; case cfd_version: if (! conn->id_verified) { RefuseAccess(conn,sendbuffer,0,recvbuffer); } snprintf(conn->output,CF_BUFSIZE,"OK: %s",VERSION); SendTransaction(conn->sd_reply,conn->output,0,CF_DONE); return conn->id_verified; case cfd_cauth: conn->id_verified = VerifyConnection(conn,(char *)(recvbuffer+strlen("CAUTH "))); if (! conn->id_verified) { RefuseAccess(conn,sendbuffer,0,recvbuffer); } return conn->id_verified; /* are we finished yet ? */ case cfd_sauth: /* This is where key agreement takes place */ if (! conn->id_verified) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (!AuthenticationDialogue(conn,recvbuffer,received)) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } return true; case cfd_get: memset(filename,0,CF_BUFSIZE); sscanf(recvbuffer,"GET %d %[^\n]",&(get_args.buf_size),filename); if (get_args.buf_size < 0 || get_args.buf_size > CF_BUFSIZE) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (! conn->id_verified) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (!AccessControl(filename,conn,false)) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return true; } memset(sendbuffer,0,CF_BUFSIZE); if (get_args.buf_size >= CF_BUFSIZE) { get_args.buf_size = 2048; } get_args.connect = conn; get_args.encrypt = false; get_args.replybuff = sendbuffer; get_args.replyfile = filename; CfGetFile(&get_args); return true; case cfd_sget: memset(buffer,0,CF_BUFSIZE); sscanf(recvbuffer,"SGET %u %d",&len,&(get_args.buf_size)); if (len >= sizeof(out) || received != len+CF_PROTO_OFFSET) { Verbose("Protocol error SGET\n"); RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } plainlen = DecryptString(recvbuffer+CF_PROTO_OFFSET,buffer,conn->session_key,len); cfscanf(buffer,strlen("GET"),strlen("dummykey"),check,sendbuffer,filename); if (strcmp(check,"GET") != 0) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return true; } if (get_args.buf_size < 0 || get_args.buf_size > 8192) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (get_args.buf_size >= CF_BUFSIZE) { get_args.buf_size = 2048; } Debug("Confirm decryption, and thus validity of caller\n"); Debug("SGET %s with blocksize %d\n",filename,get_args.buf_size); if (! conn->id_verified) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (!AccessControl(filename,conn,true)) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } memset(sendbuffer,0,CF_BUFSIZE); get_args.connect = conn; get_args.encrypt = true; get_args.replybuff = sendbuffer; get_args.replyfile = filename; CfGetFile(&get_args); return true; case cfd_sopendir: memset(buffer,0,CF_BUFSIZE); sscanf(recvbuffer,"SOPENDIR %u",&len); if (len >= sizeof(out) || received != len+CF_PROTO_OFFSET) { Verbose("Protocol error OPENDIR: %d\n",len); RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (conn->session_key == NULL) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } memcpy(out,recvbuffer+CF_PROTO_OFFSET,len); plainlen = DecryptString(out,recvbuffer,conn->session_key,len); if (strncmp(recvbuffer,"OPENDIR",7) !=0) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return true; } memset(filename,0,CF_BUFSIZE); sscanf(recvbuffer,"OPENDIR %[^\n]",filename); if (! conn->id_verified) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (!AccessControl(filename,conn,true)) /* opendir don't care about privacy */ { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } CfSecOpenDirectory(conn,sendbuffer,filename); return true; case cfd_opendir: memset(filename,0,CF_BUFSIZE); sscanf(recvbuffer,"OPENDIR %[^\n]",filename); if (! conn->id_verified) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (!AccessControl(filename,conn,true)) /* opendir don't care about privacy */ { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } CfOpenDirectory(conn,sendbuffer,filename); return true; case cfd_ssynch: memset(buffer,0,CF_BUFSIZE); sscanf(recvbuffer,"SSYNCH %u",&len); if (len >= sizeof(out) || received != len+CF_PROTO_OFFSET) { Verbose("Protocol error SSYNCH: %d\n",len); RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } if (conn->session_key == NULL) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } memcpy(out,recvbuffer+CF_PROTO_OFFSET,len); plainlen = DecryptString(out,recvbuffer,conn->session_key,len); if (strncmp(recvbuffer,"SYNCH",5) !=0) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return true; } /* roll through, no break */ case cfd_synch: if (! conn->id_verified) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } memset(filename,0,CF_BUFSIZE); sscanf(recvbuffer,"SYNCH %ld STAT %[^\n]",&time_no_see,filename); trem = (time_t) time_no_see; if (time_no_see == 0 || filename[0] == '\0') { break; } if ((tloc = time((time_t *)NULL)) == -1) { sprintf(conn->output,"Couldn't read system clock\n"); CfLog(cfinform,conn->output,"time"); SendTransaction(conn->sd_reply,"BAD: clocks out of synch",0,CF_DONE); return true; } drift = (int)(tloc-trem); if (!AccessControl(filename,conn,true)) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return true; } if (DENYBADCLOCKS && (drift*drift > CLOCK_DRIFT*CLOCK_DRIFT)) { snprintf(conn->output,CF_BUFSIZE*2,"BAD: Clocks are too far unsynchronized %ld/%ld\n",(long)tloc,(long)trem); CfLog(cfinform,conn->output,""); SendTransaction(conn->sd_reply,conn->output,0,CF_DONE); return true; } else { Debug("Clocks were off by %ld\n",(long)tloc-(long)trem); StatFile(conn,sendbuffer,filename); } return true; case cfd_smd5: memset(buffer,0,CF_BUFSIZE); sscanf(recvbuffer,"SMD5 %u",&len); if (len >= sizeof(out) || received != len+CF_PROTO_OFFSET) { Debug("Decryption error: %d\n",len); RefuseAccess(conn,sendbuffer,0,recvbuffer); return true; } memcpy(out,recvbuffer+CF_PROTO_OFFSET,len); plainlen = DecryptString(out,recvbuffer,conn->session_key,len); if (strncmp(recvbuffer,"MD5",3) !=0) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return false; } /* roll through, no break */ case cfd_md5: if (! conn->id_verified) { RefuseAccess(conn,sendbuffer,0,recvbuffer); return true; } memset(filename,0,CF_BUFSIZE); memset(args,0,CF_BUFSIZE); CompareLocalChecksum(conn,sendbuffer,recvbuffer); return true; } sprintf (sendbuffer,"BAD: Request denied\n"); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); CfLog(cfinform,"Closing connection\n",""); return false; } /**************************************************************/ void *ExitCleanly(int signum) { #ifdef HAVE_PTHREAD_H /* Do we care about this? for (i = 0; i < MAXTHREAD ; i++) { if (THREADS[i] != NULL) { pthread_join(THREADS[i],(void **)NULL); } } */ #endif HandleSignal(signum); unlink(PIDFILE); return NULL; } /**************************************************************/ /* Level 4 */ /**************************************************************/ int MatchClasses(struct cfd_connection *conn) { char recvbuffer[CF_BUFSIZE]; struct Item *classlist = NULL, *ip; int count = 0; Debug("Match classes\n"); while (true && (count < 10)) /* arbitrary check to avoid infinite loop, DoS attack*/ { count++; if (ReceiveTransaction(conn->sd_reply,recvbuffer,NULL) == -1) { if (errno == EINTR) { continue; } } Debug("Got class buffer %s\n",recvbuffer); if (strncmp(recvbuffer,CFD_TERMINATOR,strlen(CFD_TERMINATOR)) == 0) { if (count == 1) { Debug("No classes were sent, assuming no restrictions...\n"); return true; } break; } classlist = SplitStringAsItemList(recvbuffer,' '); for (ip = classlist; ip != NULL; ip=ip->next) { if (IsDefinedClass(ip->name)) { Debug("Class %s matched, accepting...\n",ip->name); DeleteItemList(classlist); return true; } if (strncmp(ip->name,CFD_TERMINATOR,strlen(CFD_TERMINATOR)) == 0) { Verbose("No classes matched, rejecting....\n"); ReplyNothing(conn); DeleteItemList(classlist); return false; } } } ReplyNothing(conn); Verbose("No classes matched, rejecting....\n"); DeleteItemList(classlist); return false; } /******************************************************************/ void DoExec(struct cfd_connection *conn,char *sendbuffer,char *args) { char ebuff[CF_EXPANDSIZE], line[CF_BUFSIZE], *sp; int print = false,i, opt=false; FILE *pp; if ((CFSTARTTIME = time((time_t *)NULL)) == -1) { CfLog(cferror,"Couldn't read system clock\n","time"); } if (GetMacroValue(CONTEXTID,"cfrunCommand") == NULL) { Verbose("cfservd exec request: no cfrunCommand defined\n"); sprintf(sendbuffer,"Exec request: no cfrunCommand defined\n"); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); return; } for (sp = args; *sp != '\0'; sp++) /* Blank out -K -f */ { if ((WordHere(args,sp,"-K") == true) || (WordHere(args,sp,"-f") == true)) { *sp = ' '; *(sp+1) = ' '; } else if (WordHere(args,sp,"--no-lock") == true) { for (i = 0; i < 9; i++) { *(sp+i) = ' '; } } else if (WordHere(args,sp,"--file") == true) { for (i = 0; i < 7; i++) { *(sp+i) = ' '; } } } ExpandVarstring("$(cfrunCommand) --no-splay --inform",ebuff,""); if (strlen(ebuff)+strlen(args)+6 > CF_BUFSIZE) { snprintf(sendbuffer,CF_BUFSIZE,"Command line too long with args: %s\n",ebuff); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); ReleaseCurrentLock(); return; } else { if ((args != NULL) & (strlen(args) > 0)) { strcat(ebuff," "); strncat(ebuff,args,CF_BUFSIZE-strlen(ebuff)); snprintf(sendbuffer,CF_BUFSIZE,"cfservd Executing %s\n",ebuff); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); } } snprintf(conn->output,CF_BUFSIZE,"Executing command %s\n",ebuff); CfLog(cfinform,conn->output,""); if ((pp = cfpopen(ebuff,"r")) == NULL) { snprintf(conn->output,CF_BUFSIZE,"Couldn't open pipe to command %s\n",ebuff); CfLog(cferror,conn->output,"pipe"); snprintf(sendbuffer,CF_BUFSIZE,"Unable to run %s\n",ebuff); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); ReleaseCurrentLock(); return; } while (!feof(pp)) { if (ferror(pp)) { fflush(pp); break; } ReadLine(line,CF_BUFSIZE,pp); if (ferror(pp)) { fflush(pp); break; } print = false; for (sp = line; *sp != '\0'; sp++) { if (! isspace((int)*sp)) { print = true; break; } } if (print) { snprintf(sendbuffer,CF_BUFSIZE,"%s\n",line); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); } } cfpclose(pp); /* ReleaseCurrentLock(); */ } /**************************************************************/ int GetCommand (char *str) { int i; char op[CF_BUFSIZE]; sscanf(str,"%4095s",op); for (i = 0; PROTOCOL[i] != NULL; i++) { if (strcmp(op,PROTOCOL[i])==0) { return i; } } return -1; } /*********************************************************************/ int VerifyConnection(struct cfd_connection *conn,char buf[CF_BUFSIZE]) /* Try reverse DNS lookup and RFC931 username lookup to check the authenticity. */ { char ipstring[CF_MAXVARSIZE], fqname[CF_MAXVARSIZE], username[CF_MAXVARSIZE]; char dns_assert[CF_MAXVARSIZE],ip_assert[CF_MAXVARSIZE]; int matched = false; struct passwd *pw; #if defined(HAVE_GETADDRINFO) struct addrinfo query, *response=NULL, *ap; int err; #else struct sockaddr_in raddr; int i,j,len = sizeof(struct sockaddr_in); struct hostent *hp = NULL; struct Item *ip_aliases = NULL, *ip_addresses = NULL; #endif Debug("Connecting host identifies itself as %s\n",buf); memset(ipstring,0,CF_MAXVARSIZE); memset(fqname,0,CF_MAXVARSIZE); memset(username,0,CF_MAXVARSIZE); sscanf(buf,"%255s %255s %255s",ipstring,fqname,username); Debug("(ipstring=[%s],fqname=[%s],username=[%s],socket=[%s])\n",ipstring,fqname,username,conn->ipaddr); strncpy(dns_assert,ToLowerStr(fqname),CF_MAXVARSIZE-1); strncpy(ip_assert,ipstring,CF_MAXVARSIZE-1); /* It only makes sense to check DNS by reverse lookup if the key had to be accepted on trust. Once we have a positive key ID, the IP address is irrelevant fr authentication... We can save a lot of time by not looking this up ... */ if ((conn->trust == false) || IsFuzzyItemIn(SKIPVERIFY,MapAddress(conn->ipaddr))) { snprintf(conn->output,CF_BUFSIZE*2,"Allowing %s to connect without (re)checking ID\n",ip_assert); CfLog(cfverbose,conn->output,""); Verbose("Non-verified Host ID is %s (Using skipverify)\n",dns_assert); strncpy(conn->hostname,dns_assert,CF_MAXVARSIZE); Verbose("Non-verified User ID seems to be %s (Using skipverify)\n",username); strncpy(conn->username,username,CF_MAXVARSIZE); if ((pw=getpwnam(username)) == NULL) /* Keep this inside mutex */ { printf("username was"); conn->uid = -2; } else { conn->uid = pw->pw_uid; } LastSeen(dns_assert,cf_accept); return true; } if (strcmp(ip_assert,MapAddress(conn->ipaddr)) != 0) { Verbose("IP address mismatch between client's assertion (%s) and socket (%s) - untrustworthy connection\n",ip_assert,conn->ipaddr); return false; } if (strlen(dns_assert) == 0) { Verbose("DNS asserted name was empty - untrustworthy connection\n"); return false; } if (strcmp(dns_assert,"skipident") == 0) { Verbose("DNS asserted name was withheld before key exchange - untrustworthy connection\n"); return false; } Verbose("Socket caller address appears honest (%s matches %s)\n",ip_assert,MapAddress(conn->ipaddr)); snprintf(conn->output,CF_BUFSIZE,"Socket originates from %s=%s\n",ip_assert,dns_assert); CfLog(cfverbose,conn->output,""); Debug("Attempting to verify honesty by looking up hostname (%s)\n",dns_assert); /* Do a reverse DNS lookup, like tcp wrappers to see if hostname matches IP */ #if defined(HAVE_GETADDRINFO) Debug("Using v6 compatible lookup...\n"); memset(&query,0,sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; query.ai_flags = AI_PASSIVE; if ((err=getaddrinfo(dns_assert,NULL,&query,&response)) != 0) { snprintf(conn->output,CF_BUFSIZE,"Unable to lookup %s (%s)",dns_assert,gai_strerror(err)); CfLog(cferror,conn->output,""); } for (ap = response; ap != NULL; ap = ap->ai_next) { Debug("CMP: %s %s\n",MapAddress(conn->ipaddr),sockaddr_ntop(ap->ai_addr)); if (strcmp(MapAddress(conn->ipaddr),sockaddr_ntop(ap->ai_addr)) == 0) { Debug("Found match\n"); matched = true; } } if (response != NULL) { freeaddrinfo(response); } #else Debug("IPV4 hostnname lookup on %s\n",dns_assert); # ifdef HAVE_PTHREAD_H if (pthread_mutex_lock(&MUTEX_HOSTNAME) != 0) { CfLog(cferror,"pthread_mutex_lock failed","unlock"); exit(1); } # endif if ((hp = gethostbyname(dns_assert)) == NULL) { Verbose("cfservd Couldn't look up name %s\n",fqname); Verbose(" Make sure that fully qualified names can be looked up at your site!\n"); Verbose(" i.e. www.cfengine.org, not just www. If you use NIS or /etc/hosts\n"); Verbose(" make sure that the full form is registered too as an alias!\n"); snprintf(OUTPUT,CF_BUFSIZE,"DNS lookup of %s failed",dns_assert); CfLog(cflogonly,OUTPUT,"gethostbyname"); matched = false; } else { matched = true; Debug("Looking for the peername of our socket...\n"); if (getpeername(conn->sd_reply,(struct sockaddr *)&raddr,&len) == -1) { CfLog(cferror,"Couldn't get socket address\n","getpeername"); matched = false; } Verbose("Looking through hostnames on socket with IPv4 %s\n",sockaddr_ntop((struct sockaddr *)&raddr)); for (i = 0; hp->h_addr_list[i]; i++) { Verbose("Reverse lookup address found: %d\n",i); if (memcmp(hp->h_addr_list[i],(char *)&(raddr.sin_addr),sizeof(raddr.sin_addr)) == 0) { Verbose("Canonical name matched host's assertion - id confirmed as %s\n",dns_assert); break; } } if (hp->h_addr_list[0] != NULL) { Verbose("Checking address number %d for non-canonical names (aliases)\n",i); for (j = 0; hp->h_aliases[j] != NULL; j++) { Verbose("Comparing [%s][%s]\n",hp->h_aliases[j],ip_assert); if (strcmp(hp->h_aliases[j],ip_assert) == 0) { Verbose("Non-canonical name (alias) matched host's assertion - id confirmed as %s\n",dns_assert); break; } } if ((hp->h_addr_list[i] != NULL) && (hp->h_aliases[j] != NULL)) { snprintf(conn->output,CF_BUFSIZE,"Reverse hostname lookup failed, host claiming to be %s was %s\n",buf,sockaddr_ntop((struct sockaddr *)&raddr)); CfLog(cflogonly,conn->output,""); Verbose("%s",conn->output); matched = false; } else { Verbose("Reverse lookup succeeded\n"); } } else { snprintf(conn->output,CF_BUFSIZE,"No name was registered in DNS for %s - reverse lookup failed\n",dns_assert); CfLog(cflogonly,conn->output,""); Verbose("%s",conn->output); matched = false; } } if ((pw=getpwnam(username)) == NULL) /* Keep this inside mutex */ { printf("username was"); conn->uid = -2; } else { conn->uid = pw->pw_uid; } # ifdef HAVE_PTHREAD_H if (pthread_mutex_unlock(&MUTEX_HOSTNAME) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","unlock"); exit(1); } # endif #endif if (!matched) { snprintf(conn->output,CF_BUFSIZE,"Failed on DNS reverse lookup of %s\n",dns_assert); CfLog(cflogonly,conn->output,"gethostbyname"); Verbose("%s",conn->output); snprintf(conn->output,CF_BUFSIZE,"Client sent: %s",buf); CfLog(cflogonly,conn->output,""); return false; } Verbose("Host ID is %s\n",dns_assert); strncpy(conn->hostname,dns_assert,CF_MAXVARSIZE-1); LastSeen(dns_assert,cf_accept); Verbose("User ID seems to be %s\n",username); strncpy(conn->username,username,CF_MAXVARSIZE-1); return true; } /**************************************************************/ int AllowedUser(char *user) { if (IsItemIn(ALLOWUSERLIST,user)) { Verbose("User %s granted connection privileges\n",user); return true; } Verbose("User %s is not allowed on this server\n",user); return false; } /**************************************************************/ int AccessControl(char *filename,struct cfd_connection *conn,int encrypt) { struct Auth *ap; int access = false; char realname[CF_BUFSIZE],path[CF_BUFSIZE],lastnode[CF_BUFSIZE],*sp; struct stat statbuf; Debug("AccessControl(%s)\n",filename); memset(realname,0,CF_BUFSIZE); /* Separate path first, else this breaks for lastnode = symlink */ for (sp = filename; *sp != '\0'; sp++) /*fix filename to not have windows slashes */ { if (*sp == FILE_SEPARATOR) { *sp = '/'; } } strncpy(path,filename,CF_BUFSIZE-1); strncpy(lastnode,ReadLastNode(filename),CF_BUFSIZE-1); ChopLastNode(path); /* Eliminate links from path */ #ifdef HAVE_REALPATH if (realpath(path,realname) == NULL) { snprintf(conn->output,CF_BUFSIZE*2,"Couldn't resolve filename %s from host %s\n",filename,conn->hostname); CfLog(cfverbose,conn->output,"lstat"); CfLog(cflogonly,conn->output,"lstat"); return false; } #else CompressPath(realname,path); /* in links.c */ #endif /* Rejoin the last node and stat the real thing */ AddSlash(realname); strcat(realname,lastnode); if (lstat(realname,&statbuf) == -1) { snprintf(conn->output,CF_BUFSIZE*2,"Couldn't stat filename %s (i.e. %s) from host %s\n",filename,realname,conn->hostname); CfLog(cfverbose,conn->output,"lstat"); /*CfLog(cflogonly,conn->output,"lstat"); */ return false; } Debug("AccessControl, match(%s,%s) encrypt request=%d\n",realname,conn->hostname,encrypt); if (VADMIT == NULL) { Verbose("cfservd access list is empty, no files are visible\n"); return false; } conn->maproot = false; for (ap = VADMIT; ap != NULL; ap=ap->next) { int res = false; Debug("Examining rule in access list (%s,%s)?\n",realname,ap->path); if ((strlen(realname) > strlen(ap->path)) && strncmp(ap->path,realname,strlen(ap->path)) == 0 && realname[strlen(ap->path)] == '/') { res = true; /* Substring means must be a / to link, else just a substring og filename */ } if (strcmp(ap->path,realname) == 0) { res = true; /* Exact match means single file to admit */ } if (res) { Debug("Found a matching rule in access list (%s in %s)\n",realname,ap->path); if (stat(ap->path,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Warning cannot stat file object %s in admit/grant, or access list refers to dangling link\n",ap->path); CfLog(cflogonly,OUTPUT,""); continue; } if (!encrypt && (ap->encrypt == true)) { snprintf(conn->output,CF_BUFSIZE,"File %s requires encrypt connection...will not serve\n",ap->path); CfLog(cferror,conn->output,""); access = false; } else { Debug("Checking whether to map root privileges..\n"); if (IsWildItemIn(ap->maproot,conn->hostname) || IsWildItemIn(ap->maproot,MapAddress(conn->ipaddr)) || IsFuzzyItemIn(ap->maproot,MapAddress(conn->ipaddr))) { conn->maproot = true; Verbose("Mapping root privileges\n"); } else { Verbose("No root privileges granted\n"); } if (IsWildItemIn(ap->accesslist,conn->hostname) || IsWildItemIn(ap->accesslist,MapAddress(conn->ipaddr)) || IsFuzzyItemIn(ap->accesslist,MapAddress(conn->ipaddr))) { access = true; Debug("Access privileges - match found\n"); } } break; } } for (ap = VDENY; ap != NULL; ap=ap->next) { if (strncmp(ap->path,realname,strlen(ap->path)) == 0) { if (IsWildItemIn(ap->accesslist,conn->hostname) || IsWildItemIn(ap->accesslist,MapAddress(conn->ipaddr)) || IsFuzzyItemIn(ap->accesslist,MapAddress(conn->ipaddr))) { access = false; snprintf(conn->output,CF_BUFSIZE*2,"Host %s explicitly denied access to %s\n",conn->hostname,realname); CfLog(cfverbose,conn->output,""); break; } } } if (access) { snprintf(conn->output,CF_BUFSIZE*2,"Host %s granted access to %s\n",conn->hostname,realname); CfLog(cfverbose,conn->output,""); if (encrypt && LOGENCRYPT) { /* Log files that were marked as requiring encryption */ CfLog(cfloginform,conn->output,""); } } else { snprintf(conn->output,CF_BUFSIZE*2,"Host %s denied access to %s\n",conn->hostname,realname); CfLog(cfverbose,conn->output,""); CfLog(cfloginform,conn->output,""); } if (!conn->rsa_auth) { CfLog(cfverbose,"Cannot map root access without RSA authentication",""); conn->maproot = false; /* only public files accessible */ /* return false; */ } return access; } /**************************************************************/ int AuthenticationDialogue(struct cfd_connection *conn,char *recvbuffer, int recvlen) { char in[CF_BUFSIZE],*out, *decrypted_nonce; BIGNUM *counter_challenge = NULL; unsigned char digest[EVP_MAX_MD_SIZE+1]; unsigned int crypt_len, nonce_len = 0,encrypted_len = 0; char sauth[10], iscrypt ='n'; int len = 0,keylen; unsigned long err; RSA *newkey; if (PRIVKEY == NULL || PUBKEY == NULL) { CfLog(cferror,"No public/private key pair exists, create one with cfkey\n",""); return false; } /* proposition C1 */ /* Opening string is a challenge from the client (some agent) */ sauth[0] = '\0'; sscanf(recvbuffer,"%s %c %d %d",sauth,&iscrypt,&crypt_len,&nonce_len); if (crypt_len == 0 || nonce_len == 0 || strlen(sauth) == 0) { CfLog(cfinform,"Protocol format error in authentation from IP %s\n",conn->hostname); return false; } if (nonce_len > CF_NONCELEN*2) { CfLog(cfinform,"Protocol deviant authentication nonce from %s\n",conn->hostname); return false; } if (crypt_len > 2*CF_NONCELEN) { CfLog(cfinform,"Protocol abuse in unlikely cipher from %s\n",conn->hostname); return false; } /* Check there is no attempt to read past the end of the received input */ if (recvbuffer+CF_RSA_PROTO_OFFSET+nonce_len > recvbuffer+recvlen) { CfLog(cfinform,"Protocol consistency error in authentation from IP %s\n",conn->hostname); return false; } if ((strcmp(sauth,"SAUTH") != 0) || (nonce_len == 0) || (crypt_len == 0)) { CfLog(cfinform,"Protocol error in RSA authentation from IP %s\n",conn->hostname); return false; } Debug("Challenge encryption = %c, nonce = %d, buf = %d\n",iscrypt,nonce_len,crypt_len); #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_lock failed","lock"); } #endif if ((decrypted_nonce = malloc(crypt_len)) == NULL) { FatalError("memory failure"); } if (iscrypt == 'y') { if (RSA_private_decrypt(crypt_len,recvbuffer+CF_RSA_PROTO_OFFSET,decrypted_nonce,PRIVKEY,RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","lock"); } #endif snprintf(conn->output,CF_BUFSIZE,"Private decrypt failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,conn->output,""); free(decrypted_nonce); return false; } } else { if (nonce_len > crypt_len) { #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","lock"); } #endif snprintf(conn->output,CF_BUFSIZE,"Illegal challenge\n"); CfLog(cferror,conn->output,""); free(decrypted_nonce); return false; } memcpy(decrypted_nonce,recvbuffer+CF_RSA_PROTO_OFFSET,nonce_len); } #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","lock"); } #endif /* Client's ID is now established by key or trusted, reply with md5 */ ChecksumString(decrypted_nonce,nonce_len,digest,'m'); free(decrypted_nonce); /* Get the public key from the client */ #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_lock failed","lock"); } #endif newkey = RSA_new(); #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_lock failed","lock"); } #endif /* proposition C2 */ if ((len = ReceiveTransaction(conn->sd_reply,recvbuffer,NULL)) == -1) { CfLog(cfinform,"Protocol error 1 in RSA authentation from IP %s\n",conn->hostname); RSA_free(newkey); return false; } if (len == 0) { CfLog(cfinform,"Protocol error 2 in RSA authentation from IP %s\n",conn->hostname); RSA_free(newkey); return false; } if ((newkey->n = BN_mpi2bn(recvbuffer,len,NULL)) == NULL) { err = ERR_get_error(); snprintf(conn->output,CF_BUFSIZE,"Private decrypt failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,conn->output,""); RSA_free(newkey); return false; } /* proposition C3 */ if ((len=ReceiveTransaction(conn->sd_reply,recvbuffer,NULL)) == -1) { CfLog(cfinform,"Protocol error 3 in RSA authentation from IP %s\n",conn->hostname); RSA_free(newkey); return false; } if (len == 0) { CfLog(cfinform,"Protocol error 4 in RSA authentation from IP %s\n",conn->hostname); RSA_free(newkey); return false; } if ((newkey->e = BN_mpi2bn(recvbuffer,len,NULL)) == NULL) { err = ERR_get_error(); snprintf(conn->output,CF_BUFSIZE,"Private decrypt failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,conn->output,""); RSA_free(newkey); return false; } if (DEBUG||D2) { RSA_print_fp(stdout,newkey,0); } if (!CheckStoreKey(conn,newkey)) /* conceals proposition S1 */ { if (!conn->trust) { RSA_free(newkey); return false; } } /* Reply with md5 of original challenge */ /* proposition S2 */ SendTransaction(conn->sd_reply,digest,16,CF_DONE); /* Send counter challenge to be sure this is a live session */ counter_challenge = BN_new(); BN_rand(counter_challenge,256,0,0); nonce_len = BN_bn2mpi(counter_challenge,in); ChecksumString(in,nonce_len,digest,'m'); encrypted_len = RSA_size(newkey); /* encryption buffer is always the same size as n */ #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_lock failed","lock"); } #endif if ((out = malloc(encrypted_len+1)) == NULL) { FatalError("memory failure"); } #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","lock"); } #endif if (RSA_public_encrypt(nonce_len,in,out,newkey,RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); snprintf(conn->output,CF_BUFSIZE,"Public encryption failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,conn->output,""); RSA_free(newkey); free(out); return false; } /* proposition S3 */ SendTransaction(conn->sd_reply,out,encrypted_len,CF_DONE); /* if the client doesn't have our public key, send it */ if (iscrypt != 'y') { /* proposition S4 - conditional */ memset(in,0,CF_BUFSIZE); len = BN_bn2mpi(PUBKEY->n,in); SendTransaction(conn->sd_reply,in,len,CF_DONE); /* proposition S5 - conditional */ memset(in,0,CF_BUFSIZE); len = BN_bn2mpi(PUBKEY->e,in); SendTransaction(conn->sd_reply,in,len,CF_DONE); } /* Receive reply to counter_challenge */ /* proposition C4 */ memset(in,0,CF_BUFSIZE); if (ReceiveTransaction(conn->sd_reply,in,NULL) == -1) { BN_free(counter_challenge); free(out); RSA_free(newkey); return false; } if (!ChecksumsMatch(digest,in,'m')) /* replay / piggy in the middle attack ? */ { BN_free(counter_challenge); free(out); RSA_free(newkey); snprintf(conn->output,CF_BUFSIZE,"Challenge response from client %s was incorrect - ID false?",conn->ipaddr); CfLog(cfinform,conn->output,""); return false; } else { if (!conn->trust) { snprintf(conn->output,CF_BUFSIZE,"Strong authentication of client %s/%s achieved",conn->hostname,conn->ipaddr); } else { snprintf(conn->output,CF_BUFSIZE,"Weak authentication of trusted client %s/%s (key accepted on trust).\n",conn->hostname,conn->ipaddr); } CfLog(cfverbose,conn->output,""); } /* Receive random session key, blowfish style ... */ /* proposition C5 */ memset(in,0,CF_BUFSIZE); if ((keylen = ReceiveTransaction(conn->sd_reply,in,NULL)) == -1) { BN_free(counter_challenge); free(out); RSA_free(newkey); return false; } if (keylen > CF_BUFSIZE/2) { BN_free(counter_challenge); free(out); RSA_free(newkey); snprintf(conn->output,CF_BUFSIZE,"Session key length received from %s is too long",conn->ipaddr); CfLog(cfinform,conn->output,""); return false; } else { Debug("Got Blowfish size %d\n",keylen); DebugBinOut(in,keylen); } #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_lock failed","lock"); } #endif conn->session_key = malloc(CF_BLOWFISHSIZE); if (conn->session_key == NULL) { BN_free(counter_challenge); free(out); RSA_free(newkey); return false; } if (keylen == CF_BLOWFISHSIZE) /* Old, non-encrypted */ { memcpy(conn->session_key,in,CF_BLOWFISHSIZE); } else /* New encrypted */ { if (RSA_private_decrypt(keylen,in,out,PRIVKEY,RSA_PKCS1_PADDING) <= 0) { #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","lock"); } #endif err = ERR_get_error(); snprintf(conn->output,CF_BUFSIZE,"Private decrypt failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,conn->output,""); return false; } memcpy(conn->session_key,out,CF_BLOWFISHSIZE); } #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","lock"); } #endif Debug("Got a session key...\n"); DebugBinOut(conn->session_key,16); BN_free(counter_challenge); free(out); RSA_free(newkey); conn->rsa_auth = true; return true; } /**************************************************************/ int StatFile(struct cfd_connection *conn,char *sendbuffer,char *filename) /* Because we do not know the size or structure of remote datatypes,*/ /* the simplest way to transfer the data is to convert them into */ /* plain text and interpret them on the other side. */ { struct cfstat cfst; struct stat statbuf,statlinkbuf; char linkbuf[CF_BUFSIZE]; int islink = false; Debug("StatFile(%s)\n",filename); memset(&cfst,0,sizeof(struct cfstat)); if (strlen(ReadLastNode(filename)) > CF_MAXLINKSIZE) { snprintf(sendbuffer,CF_BUFSIZE*2,"BAD: Filename suspiciously long [%s]\n",filename); CfLog(cferror,sendbuffer,""); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); return -1; } if (lstat(filename,&statbuf) == -1) { snprintf(sendbuffer,CF_BUFSIZE,"BAD: unable to stat file %s",filename); CfLog(cfverbose,sendbuffer,"lstat"); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); return -1; } cfst.cf_readlink = NULL; cfst.cf_lmode = 0; cfst.cf_nlink = CF_NOSIZE; memset(linkbuf,0,CF_BUFSIZE); if (S_ISLNK(statbuf.st_mode)) { islink = true; cfst.cf_type = cf_link; /* pointless - overwritten */ cfst.cf_lmode = statbuf.st_mode & 07777; cfst.cf_nlink = statbuf.st_nlink; if (readlink(filename,linkbuf,CF_BUFSIZE-1) == -1) { sprintf(sendbuffer,"BAD: unable to read link\n"); CfLog(cferror,sendbuffer,"readlink"); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); return -1; } Debug("readlink: %s\n",linkbuf); cfst.cf_readlink = linkbuf; } if (!islink && (stat(filename,&statbuf) == -1)) { snprintf(sendbuffer,CF_BUFSIZE,"BAD: unable to stat file %s\n",filename); CfLog(cfverbose,conn->output,"stat"); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); return -1; } Debug("Getting size of link deref %s\n",linkbuf); if (islink && (stat(filename,&statlinkbuf) != -1)) /* linktype=copy used by agent */ { statbuf.st_size = statlinkbuf.st_size; statbuf.st_mode = statlinkbuf.st_mode; statbuf.st_uid = statlinkbuf.st_uid; statbuf.st_gid = statlinkbuf.st_gid; statbuf.st_mtime = statlinkbuf.st_mtime; statbuf.st_ctime = statlinkbuf.st_ctime; } if (S_ISDIR(statbuf.st_mode)) { cfst.cf_type = cf_dir; } if (S_ISREG(statbuf.st_mode)) { cfst.cf_type = cf_reg; } if (S_ISSOCK(statbuf.st_mode)) { cfst.cf_type = cf_sock; } if (S_ISCHR(statbuf.st_mode)) { cfst.cf_type = cf_char; } if (S_ISBLK(statbuf.st_mode)) { cfst.cf_type = cf_block; } if (S_ISFIFO(statbuf.st_mode)) { cfst.cf_type = cf_fifo; } cfst.cf_mode = statbuf.st_mode & 07777; cfst.cf_uid = statbuf.st_uid & 0xFFFFFFFF; cfst.cf_gid = statbuf.st_gid & 0xFFFFFFFF; cfst.cf_size = statbuf.st_size; cfst.cf_atime = statbuf.st_atime; cfst.cf_mtime = statbuf.st_mtime; cfst.cf_ctime = statbuf.st_ctime; cfst.cf_ino = statbuf.st_ino; cfst.cf_dev = statbuf.st_dev; cfst.cf_readlink = linkbuf; if (cfst.cf_nlink == CF_NOSIZE) { cfst.cf_nlink = statbuf.st_nlink; } #ifndef IRIX if (statbuf.st_size > statbuf.st_blocks * DEV_BSIZE) #else # ifdef HAVE_ST_BLOCKS if (statbuf.st_size > statbuf.st_blocks * DEV_BSIZE) # else if (statbuf.st_size > ST_NBLOCKS(statbuf) * DEV_BSIZE) # endif #endif { cfst.cf_makeholes = 1; /* must have a hole to get checksum right */ } else { cfst.cf_makeholes = 0; } memset(sendbuffer,0,CF_BUFSIZE); /* send as plain text */ Debug("OK: type=%d\n mode=%o\n lmode=%o\n uid=%d\n gid=%d\n size=%ld\n atime=%d\n mtime=%d\n", cfst.cf_type,cfst.cf_mode,cfst.cf_lmode,cfst.cf_uid,cfst.cf_gid,(long)cfst.cf_size, cfst.cf_atime,cfst.cf_mtime); snprintf(sendbuffer,CF_BUFSIZE,"OK: %d %d %d %d %d %ld %d %d %d %d %d %d %d", cfst.cf_type,cfst.cf_mode,cfst.cf_lmode,cfst.cf_uid,cfst.cf_gid,(long)cfst.cf_size, cfst.cf_atime,cfst.cf_mtime,cfst.cf_ctime,cfst.cf_makeholes,cfst.cf_ino, cfst.cf_nlink,cfst.cf_dev); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); memset(sendbuffer,0,CF_BUFSIZE); if (cfst.cf_readlink != NULL) { strcpy(sendbuffer,"OK:"); strcat(sendbuffer,cfst.cf_readlink); } else { sprintf(sendbuffer,"OK:"); } SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); return 0; } /***************************************************************/ void CfGetFile(struct cfd_get_arg *args) { int sd,fd,n_read,total=0,cipherlen,sendlen=0,count = 0; char sendbuffer[CF_BUFSIZE+1],out[CF_BUFSIZE],*filename; struct stat statbuf; uid_t uid; unsigned char iv[] = {1,2,3,4,5,6,7,8}, *key; EVP_CIPHER_CTX ctx; sd = (args->connect)->sd_reply; filename = args->replyfile; key = (args->connect)->session_key; uid = (args->connect)->uid; stat(filename,&statbuf); Debug("CfGetFile(%s on sd=%d), size=%d\n",filename,sd,statbuf.st_size); /* Now check to see if we have remote permission */ if (uid != 0 && !args->connect->maproot) /* should remote root be local root */ { if (statbuf.st_uid == uid) { Debug("Caller %s is the owner of the file\n",(args->connect)->username); } else { /* We are not the owner of the file and we don't care about groups */ if (statbuf.st_mode & S_IROTH) { Debug("Caller %s not owner of the file but permission granted\n",(args->connect)->username); } else { Debug("Caller %s is not the owner of the file\n",(args->connect)->username); RefuseAccess(args->connect,sendbuffer,args->buf_size,""); snprintf(sendbuffer,CF_BUFSIZE,"Open error of file [%s]\n",filename); CfLog(cferror,sendbuffer,"open"); snprintf(sendbuffer,CF_BUFSIZE,"%s",CF_FAILEDSTR); SendSocketStream(sd,sendbuffer,args->buf_size,0); return; } } } if (args->buf_size < SMALL_BLOCK_BUF_SIZE) { snprintf(args->connect->output,CF_BUFSIZE,"blocksize for %s was only %d\n",filename,args->buf_size); CfLog(cferror,args->connect->output,""); } if (args->encrypt) { EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit(&ctx,EVP_bf_cbc(),key,iv); } if ((fd = SafeOpen(filename)) == -1) { snprintf(sendbuffer,CF_BUFSIZE,"Open error of file [%s]\n",filename); CfLog(cferror,sendbuffer,"open"); snprintf(sendbuffer,CF_BUFSIZE,"%s",CF_FAILEDSTR); SendSocketStream(sd,sendbuffer,args->buf_size,0); } else { while(true) { memset(sendbuffer,0,CF_BUFSIZE); Debug("Now reading from disk...\n"); if ((n_read = read(fd,sendbuffer,args->buf_size)) == -1) { CfLog(cferror,"read failed in GetFile","read"); break; } Debug("Read completed..\n"); if (strncmp(sendbuffer,CF_FAILEDSTR,strlen(CF_FAILEDSTR)) == 0) { Debug("SENT FAILSTRING BY MISTAKE!\n"); } if (n_read == 0) { break; } else { int savedlen = statbuf.st_size; /* This can happen with log files /databases etc */ if (count++ % 3 == 0) /* Don't do this too often */ { Debug("Restatting %s\n",filename); stat(filename,&statbuf); } if (statbuf.st_size != savedlen) { snprintf(sendbuffer,CF_BUFSIZE,"%s%s: %s",CF_CHANGEDSTR1,CF_CHANGEDSTR2,filename); if (SendSocketStream(sd,sendbuffer,args->buf_size,0) == -1) { CfLog(cfverbose,"Send failed in GetFile","send"); } Debug("Aborting transfer after %d: file is changing rapidly at source.\n",total); break; } if ((savedlen - total)/args->buf_size > 0) { sendlen = args->buf_size; } else if (savedlen != 0) { sendlen = (savedlen - total); } } total += n_read; if (args->encrypt) { if (!EVP_EncryptUpdate(&ctx,out,&cipherlen,sendbuffer,n_read)) { close(fd); return; } if (cipherlen) { if (SendTransaction(sd,out,cipherlen,CF_MORE) == -1) { CfLog(cfverbose,"Send failed in GetFile","send"); break; } } } else { Debug("Sending data on socket (%d)\n",sendlen); if (SendSocketStream(sd,sendbuffer,sendlen,0) == -1) { CfLog(cfverbose,"Send failed in GetFile","send"); break; } Debug("Sending complete...\n"); } } if (args->encrypt) { if (!EVP_EncryptFinal(&ctx,out,&cipherlen)) { close(fd); return; } Debug("Cipher len of extra data is %d\n",cipherlen); SendTransaction(sd,out,cipherlen,CF_DONE); EVP_CIPHER_CTX_cleanup(&ctx); } close(fd); } Debug("Done with GetFile()\n"); } /**************************************************************/ void CompareLocalChecksum(struct cfd_connection *conn,char *sendbuffer,char *recvbuffer) { unsigned char digest[EVP_MAX_MD_SIZE+1]; char filename[CF_BUFSIZE]; char *sp; int i; /* TODO - when safe change this to sha2 */ sscanf(recvbuffer,"MD5 %[^\n]",filename); sp = recvbuffer + strlen(recvbuffer) + CF_SMALL_OFFSET; for (i = 0; i < CF_MD5_LEN; i++) { digest[i] = *sp++; } Debug("CompareLocalChecksums(%s,%s)\n",filename,ChecksumPrint('m',digest)); memset(sendbuffer,0,CF_BUFSIZE); if (ChecksumChanged(filename,digest,cfverbose,true,'m')) { sprintf(sendbuffer,"%s",CFD_TRUE); Debug("Checksums didn't match\n"); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); } else { sprintf(sendbuffer,"%s",CFD_FALSE); Debug("Checksums matched ok\n"); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); } } /**************************************************************/ int CfOpenDirectory(struct cfd_connection *conn,char *sendbuffer,char *dirname) { DIR *dirh; struct dirent *dirp; int offset; Debug("CfOpenDirectory(%s)\n",dirname); if (*dirname != '/') { sprintf(sendbuffer,"BAD: request to access a non-absolute filename\n"); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); return -1; } if ((dirh = opendir(dirname)) == NULL) { Debug("cfengine, couldn't open dir %s\n",dirname); snprintf(sendbuffer,CF_BUFSIZE,"BAD: cfengine, couldn't open dir %s\n",dirname); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); return -1; } /* Pack names for transmission */ memset(sendbuffer,0,CF_BUFSIZE); offset = 0; for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (strlen(dirp->d_name)+1+offset >= CF_BUFSIZE - CF_MAXLINKSIZE) { SendTransaction(conn->sd_reply,sendbuffer,offset+1,CF_MORE); offset = 0; memset(sendbuffer,0,CF_BUFSIZE); } strncpy(sendbuffer+offset,dirp->d_name,CF_MAXLINKSIZE); offset += strlen(dirp->d_name) + 1; /* + zero byte separator */ } strcpy(sendbuffer+offset,CFD_TERMINATOR); SendTransaction(conn->sd_reply,sendbuffer,offset+2+strlen(CFD_TERMINATOR),CF_DONE); Debug("END CfOpenDirectory(%s)\n",dirname); closedir(dirh); return 0; } /**************************************************************/ int CfSecOpenDirectory(struct cfd_connection *conn,char *sendbuffer,char *dirname) { DIR *dirh; struct dirent *dirp; int offset,cipherlen; char out[CF_BUFSIZE]; Debug("CfSecOpenDirectory(%s)\n",dirname); if (*dirname != '/') { sprintf(sendbuffer,"BAD: request to access a non-absolute filename\n"); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); return -1; } if ((dirh = opendir(dirname)) == NULL) { Debug("cfengine, couldn't open dir %s\n",dirname); snprintf(sendbuffer,CF_BUFSIZE,"BAD: cfengine, couldn't open dir %s\n",dirname); SendTransaction(conn->sd_reply,sendbuffer,0,CF_DONE); return -1; } /* Pack names for transmission */ memset(sendbuffer,0,CF_BUFSIZE); offset = 0; for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (strlen(dirp->d_name)+1+offset >= CF_BUFSIZE - CF_MAXLINKSIZE) { cipherlen = EncryptString(sendbuffer,out,CONN->session_key,offset+1); SendTransaction(conn->sd_reply,out,cipherlen,CF_MORE); offset = 0; memset(sendbuffer,0,CF_BUFSIZE); memset(out,0,CF_BUFSIZE); } strncpy(sendbuffer+offset,dirp->d_name,CF_MAXLINKSIZE); offset += strlen(dirp->d_name) + 1; /* + zero byte separator */ } strcpy(sendbuffer+offset,CFD_TERMINATOR); cipherlen = EncryptString(sendbuffer,out,conn->session_key,offset+2+strlen(CFD_TERMINATOR)); SendTransaction(conn->sd_reply,out,cipherlen,CF_DONE); Debug("END CfSecOpenDirectory(%s)\n",dirname); closedir(dirh); return 0; } /***************************************************************/ void Terminate(int sd) { char buffer[CF_BUFSIZE]; memset(buffer,0,CF_BUFSIZE); strcpy(buffer,CFD_TERMINATOR); if (SendTransaction(sd,buffer,strlen(buffer)+1,CF_DONE) == -1) { CfLog(cfverbose,"","send"); Verbose("Unable to reply with terminator...\n"); } } /***************************************************************/ void DeleteAuthList(struct Auth *ap) { if (ap != NULL) { DeleteAuthList(ap->next); ap->next = NULL; DeleteItemList(ap->accesslist); free((char *)ap); } } /***************************************************************/ /* Level 5 */ /***************************************************************/ int WordHere(char *args, char *pos, char *word) /* * Returns true if the current position 'pos' in buffer * 'args' corresponds to the word 'word'. Words are * separated by spaces. */ { size_t len; if (pos < args) { return false; } len = strlen(word); if (strncmp(pos, word, len) != 0) { return false; } if (pos == args) { return true; } else if (*(pos-1) == ' ' && (pos[len] == ' ' || pos[len] == '\0')) { return true; } else { return false; } } /**************************************************************/ void RefuseAccess(struct cfd_connection *conn,char *sendbuffer,int size,char *errmesg) { char *hostname, *username, *ipaddr; static char *def = "?"; if (strlen(conn->hostname) == 0) { hostname = def; } else { hostname = conn->hostname; } if (strlen(conn->username) == 0) { username = def; } else { username = conn->username; } if (strlen(conn->ipaddr) == 0) { ipaddr = def; } else { ipaddr = conn->ipaddr; } snprintf(sendbuffer,CF_BUFSIZE,"%s",CF_FAILEDSTR); SendTransaction(conn->sd_reply,sendbuffer,size,CF_DONE); snprintf(sendbuffer,CF_BUFSIZE,"From (host=%s,user=%s,ip=%s)",hostname,username,ipaddr); CfLog(cfinform,sendbuffer,""); if (strlen(errmesg) > 0) { snprintf(OUTPUT,CF_BUFSIZE,"ID from connecting host: (%s)",errmesg); if (LOGCONNS) { CfLog(cfloginform,OUTPUT,""); } else { CfLog(cfverbose,OUTPUT,""); } } } /***************************************************************/ void ReplyNothing(struct cfd_connection *conn) { char buffer[CF_BUFSIZE]; snprintf(buffer,CF_BUFSIZE,"Hello %s (%s), nothing relevant to do here...\n\n",conn->hostname,conn->ipaddr); if (SendTransaction(conn->sd_reply,buffer,0,CF_DONE) == -1) { CfLog(cferror,"","send"); } } /***************************************************************/ char *MapAddress(char *unspec_address) { /* Is the address a mapped ipv4 over ipv6 address */ if (strncmp(unspec_address,"::ffff:",7) == 0) { return (char *)(unspec_address+7); } else { return unspec_address; } } /***************************************************************/ int CheckStoreKey(struct cfd_connection *conn,RSA *key) { RSA *savedkey; char keyname[CF_MAXVARSIZE]; if (OptionIs(CONTEXTID,"HostnameKeys",true)) { snprintf(keyname,CF_MAXVARSIZE,"%s-%s",conn->username,conn->hostname); } else { snprintf(keyname,CF_MAXVARSIZE,"%s-%s",conn->username,MapAddress(conn->ipaddr)); } if (savedkey = HavePublicKey(keyname)) { Verbose("A public key was already known from %s/%s - no trust required\n",conn->hostname,conn->ipaddr); Verbose("Adding IP %s to SkipVerify - no need to check this if we have a key\n",conn->ipaddr); PrependItem(&SKIPVERIFY,MapAddress(conn->ipaddr),NULL); if ((BN_cmp(savedkey->e,key->e) == 0) && (BN_cmp(savedkey->n,key->n) == 0)) { Verbose("The public key identity was confirmed as %s@%s\n",conn->username,conn->hostname); SendTransaction(conn->sd_reply,"OK: key accepted",0,CF_DONE); RSA_free(savedkey); return true; } else { /* If we find a key, but it doesn't match, see if we permit dynamical IP addressing */ if ((DHCPLIST != NULL) && IsFuzzyItemIn(DHCPLIST,MapAddress(conn->ipaddr))) { int result; result = IsWildKnownHost(savedkey,key,MapAddress(conn->ipaddr),conn->username); RSA_free(savedkey); if (result) { SendTransaction(conn->sd_reply,"OK: key accepted",0,CF_DONE); } else { SendTransaction(conn->sd_reply,"BAD: keys did not match",0,CF_DONE); } return result; } else /* if not, reject it */ { Verbose("The new public key does not match the old one! Spoofing attempt!\n"); SendTransaction(conn->sd_reply,"BAD: keys did not match",0,CF_DONE); RSA_free(savedkey); return false; } } return true; } else if ((DHCPLIST != NULL) && IsFuzzyItemIn(DHCPLIST,MapAddress(conn->ipaddr))) { /* If the host is expected to have a dynamic address, check for the key */ if ((DHCPLIST != NULL) && IsFuzzyItemIn(DHCPLIST,MapAddress(conn->ipaddr))) { int result; result = IsWildKnownHost(savedkey,key,MapAddress(conn->ipaddr),conn->username); RSA_free(savedkey); if (result) { SendTransaction(conn->sd_reply,"OK: key accepted",0,CF_DONE); } else { SendTransaction(conn->sd_reply,"BAD: keys did not match",0,CF_DONE); } return result; } } /* Finally, if we're still here, we should consider trusting a new key ... */ if ((TRUSTKEYLIST != NULL) && IsFuzzyItemIn(TRUSTKEYLIST,MapAddress(conn->ipaddr))) { Verbose("Host %s/%s was found in the list of hosts to trust\n",conn->hostname,conn->ipaddr); conn->trust = true; /* conn->maproot = false; ?? */ SendTransaction(conn->sd_reply,"OK: unknown key was accepted on trust",0,CF_DONE); SavePublicKey(keyname,key); AddToKeyDB(key,MapAddress(conn->ipaddr)); return true; } else { Verbose("No previous key found, and unable to accept this one on trust\n"); SendTransaction(conn->sd_reply,"BAD: key could not be accepted on trust",0,CF_DONE); return false; } } /***************************************************************/ int IsWildKnownHost(RSA *oldkey,RSA *newkey,char *mipaddr,char *username) /* This builds security from trust only gradually with DHCP - takes time! But what else are we going to do? ssh doesn't have this problem - it just asks the user interactively. We can't do that ... */ { DBT key,value; DB *dbp; int trust = false; char keyname[CF_MAXVARSIZE]; char keydb[CF_MAXVARSIZE]; snprintf(keyname,CF_MAXVARSIZE,"%s-%s",username,mipaddr); snprintf(keydb,CF_MAXVARSIZE,"%s/ppkeys/dynamic",CFWORKDIR); Debug("The key does not match a known key but the host could have a dynamic IP...\n"); if ((TRUSTKEYLIST != NULL) && IsFuzzyItemIn(TRUSTKEYLIST,mipaddr)) { Debug("We will accept a new key for this IP on trust\n"); trust = true; } else { Debug("Will not accept this key, unless we have seen it before\n"); } /* If the host is allowed to have a variable IP range, we can accept the new key on trust for the given IP address provided we have seen the key before. Check for it in a database .. */ Debug("Checking to see if we have seen the key before..\n"); if ((errno = db_create(&dbp,NULL,0)) != 0) { sprintf(OUTPUT,"Couldn't open average database %s\n",keydb); CfLog(cferror,OUTPUT,"db_open"); return false; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,keydb,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,keydb,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { sprintf(OUTPUT,"Couldn't open average database %s\n",keydb); CfLog(cferror,OUTPUT,"db_open"); return false; } memset(&key,0,sizeof(newkey)); memset(&value,0,sizeof(value)); key.data = newkey; key.size = sizeof(RSA); if ((errno = dbp->get(dbp,NULL,&key,&value,0)) != 0) { Debug("The new key is not previously known, so we need to use policy for trusting the host %s\n",mipaddr); if (trust) { Debug("Policy says to trust the changed key from %s and note that it could vary in future\n",mipaddr); memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); key.data = newkey; key.size = sizeof(RSA); value.data = mipaddr; value.size = strlen(mipaddr)+1; if ((errno = dbp->put(dbp,NULL,&key,&value,0)) != 0) { dbp->err(dbp,errno,NULL); } DeletePublicKey(keyname); } else { Debug("Found no grounds for trusting this new from %s\n",mipaddr); } } else { snprintf(OUTPUT,CF_BUFSIZE,"Public key was previously owned by %s now by %s - updating\n",value.data,mipaddr); CfLog(cfverbose,OUTPUT,""); Debug("Now trusting this new key, because we have seen it before\n"); DeletePublicKey(keyname); trust = true; } /* save this new key in the database, for future reference, regardless of whether we accept, but only change IP if trusted */ SavePublicKey(keyname,newkey); dbp->close(dbp,0); chmod(keydb,0644); return trust; } /***************************************************************/ void AddToKeyDB(RSA *newkey,char *mipaddr) { DBT key,value; DB *dbp; char keydb[CF_MAXVARSIZE]; snprintf(keydb,CF_MAXVARSIZE,"%s/ppkeys/dynamic",CFWORKDIR); if ((DHCPLIST != NULL) && IsFuzzyItemIn(DHCPLIST,mipaddr)) { /* Cache keys in the db as we see them is there are dynamical addresses */ if ((errno = db_create(&dbp,NULL,0)) != 0) { sprintf(OUTPUT,"Couldn't open average database %s\n",keydb); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,keydb,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,keydb,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { sprintf(OUTPUT,"Couldn't open average database %s\n",keydb); CfLog(cferror,OUTPUT,"db_open"); return; } memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); key.data = newkey; key.size = sizeof(RSA); value.data = mipaddr; value.size = strlen(mipaddr)+1; if ((errno = dbp->put(dbp,NULL,&key,&value,0)) != 0) { dbp->err(dbp,errno,NULL); } dbp->close(dbp,0); chmod(keydb,0644); } } /***************************************************************/ /* Toolkit/Class: conn */ /***************************************************************/ struct cfd_connection *NewConn(int sd) /* construct */ { struct cfd_connection *conn; #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_lock failed","lock"); } #endif conn = (struct cfd_connection *) malloc(sizeof(struct cfd_connection)); #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","lock"); } #endif if (conn == NULL) { CfLog(cferror,"Unable to allocate conn","malloc"); ExitCleanly(0); } conn->sd_reply = sd; conn->id_verified = false; conn->rsa_auth = false; conn->trust = false; conn->hostname[0] = '\0'; conn->ipaddr[0] = '\0'; conn->username[0] = '\0'; conn->session_key = NULL; Debug("*** New socket [%d]\n",sd); return conn; } /***************************************************************/ void DeleteConn(struct cfd_connection *conn) /* destruct */ { Debug("***Closing socket %d from %s\n",conn->sd_reply,conn->ipaddr); close(conn->sd_reply); if (conn->session_key != NULL) { free(conn->session_key); } if (conn->ipaddr != NULL) { #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock"); DeleteConn(conn); return; } #endif DeleteItemMatching(&CONNECTIONLIST,MapAddress(conn->ipaddr)); #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","pthread_mutex_unlock"); DeleteConn(conn); return; } #endif } free ((char *)conn); } /***************************************************************/ /* ERS */ /***************************************************************/ int SafeOpen(char *filename) { int fd; #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock"); } #endif fd = open(filename,O_RDONLY); #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","pthread_mutex_unlock"); } #endif return fd; } /***************************************************************/ void SafeClose(int fd) { #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock"); } #endif close(fd); #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_SYSCALL) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","pthread_mutex_unlock"); } #endif } /***************************************************************/ int cfscanf(char *in,int len1,int len2,char *out1,char *out2,char *out3) { int len3=0; char *sp; sp = in; memcpy(out1,sp,len1); out1[len1]='\0'; sp += len1 + 1; memcpy(out2,sp,len2); sp += len2 + 1; len3=strlen(sp); memcpy(out3,sp,len3); out3[len3]='\0'; return (len1 + len2 + len3 + 2); } /* EOF */ cfengine-2.2.10/src/item-file.c0000644000175000001440000002024010577465344013112 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*********************************************************************/ /* */ /* TOOLKIT: the "item file extension" object for cfengine */ /* */ /*********************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ int LoadItemList(struct Item **liststart,char *file) { FILE *fp; struct stat statbuf; if (stat(file,&statbuf) == -1) { if (DONTDO) { snprintf(OUTPUT,CF_BUFSIZE*2,"Currently no file %s to edit\n",file); CfLog(cfverbose,OUTPUT,""); return false; } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't stat %s - no file to edit\n",file); CfLog(cfverbose,OUTPUT,"stat"); return false; } } if ((EDITFILESIZE != 0) &&(statbuf.st_size > EDITFILESIZE)) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is bigger than the limit \n",file); CfLog(cfinform,OUTPUT,""); return(false); } if (! S_ISREG(statbuf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s is not a plain file\n",file); CfLog(cfinform,OUTPUT,""); return false; } if ((fp = fopen(file,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't read file %s for editing\n",file); CfLog(cfinform,OUTPUT,"fopen"); return false; } memset(VBUFF,0,CF_BUFSIZE); while(!feof(fp)) { ReadLine(VBUFF,CF_BUFSIZE,fp); if (!feof(fp) || (strlen(VBUFF) != 0)) { AppendItem(liststart,VBUFF,NULL); } VBUFF[0] = '\0'; } fclose(fp); return (true); } /*********************************************************************/ int SaveItemList(struct Item *liststart,char *file,char *repository) { struct Item *ip; struct stat statbuf; char new[CF_BUFSIZE],backup[CF_BUFSIZE]; FILE *fp; mode_t mask; char stamp[CF_BUFSIZE]; time_t STAMPNOW; STAMPNOW = time((time_t *)NULL); #ifdef WITH_SELINUX int selinux_enabled=0; security_context_t scontext=NULL; selinux_enabled = (is_selinux_enabled()>0); if(selinux_enabled) { /* get current security context */ getfilecon(file, &scontext); } #endif if (stat(file,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't stat %s, which needed editing!\n",file); CfLog(cferror,OUTPUT,""); CfLog(cferror,"Check definition in program - is file NFS mounted?\n\n",""); return false; } strcpy(new,file); strcat(new,CF_EDITED); strcpy(backup,file); sprintf(stamp, "_%d_%s", CFSTARTTIME, CanonifyName(ctime(&STAMPNOW))); if (IMAGEBACKUP == 's') { strcat(backup,stamp); } strcat(backup,CF_SAVED); unlink(new); /* Just in case of races */ if ((fp = fopen(new,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't write file %s after editing\n",new); CfLog(cferror,OUTPUT,""); return false; } for (ip = liststart; ip != NULL; ip=ip->next) { fprintf(fp,"%s\n",ip->name); } if (fclose(fp) == -1) { CfLog(cferror,"Unable to close file while writing","fclose"); return false; } if (ISCFENGINE && (ACTION == editfiles)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Edited file %s \n",file); CfLog(cfinform,OUTPUT,""); } if (IMAGEBACKUP != 'n') { if (! IsItemIn(VREPOSLIST,new)) { if (rename(file,backup) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error while renaming backup %s\n",file); CfLog(cfverbose,OUTPUT,"rename "); unlink(new); return false; } else if (Repository(backup,repository)) { unlink(backup); } } } if (rename(new,file) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error while renaming %s\n",file); CfLog(cfverbose,OUTPUT,"rename"); return false; } mask = umask(0); chmod(file,statbuf.st_mode); /* Restore file permissions etc */ chown(file,statbuf.st_uid,statbuf.st_gid); umask(mask); #ifdef WITH_SELINUX if(selinux_enabled) { /* restore file context */ setfilecon(file,scontext); } #endif return true; } /*********************************************************************/ int CompareToFile(struct Item *liststart,char *file) /* returns true if file on disk is identical to file in memory */ { FILE *fp; struct stat statbuf; struct Item *ip = liststart; unsigned char *finmem = NULL, fdata; unsigned long fip = 0, tmplen, idx; Debug("CompareToFile(%s)\n",file); if (stat(file,&statbuf) == -1) { return false; } if (liststart == NULL) { return false; } for (ip = liststart; ip != NULL; ip=ip->next) { tmplen = strlen(ip->name); if ((finmem = realloc(finmem, fip+tmplen+1)) == NULL) { Debug("CompareToFile(%s): can't realloc() memory\n",file); free(finmem); return false; } memcpy(finmem+fip, ip->name, tmplen); fip += tmplen; *(finmem+fip++) = '\n'; } if (statbuf.st_size != fip) { Debug("CompareToFile(%s): sizes are different: MEM:(%u) FILE:(%u)\n",file, fip, statbuf.st_size); free(finmem); return false; } if ((fp = fopen(file,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't read file %s for editing\n",file); CfLog(cferror,OUTPUT,"fopen"); free(finmem); return false; } for (idx = 0; idx < fip; idx++) { if (fread(&fdata, 1, 1, fp) != 1) { Debug("CompareToFile(%s): non-zero fread() before file-in-mem finished at %u-th byte MEM:(0x%x/%c)\n",file, idx, *(finmem+idx), *(finmem+idx)); free(finmem); fclose(fp); return false; } if (fdata != *(finmem+idx)) { Debug("CompareToFile(%s): difference found at %u-th byte MEM:(0x%x/%c) != FILE:(0x%x/%c)\n",file, idx, *(finmem+idx), *(finmem+idx), fdata, fdata); free(finmem); fclose(fp); return false; } } free(finmem); fclose(fp); return (true); } /*********************************************************************/ void InsertFileAfter (struct Item **filestart,struct Item *ptr,char *string) { struct Item *ip; char *sp; FILE *fp; char linebuf[CF_BUFSIZE]; EditVerbose("Edit: Inserting file %s \n",string); if ((fp=fopen(string,"r")) == NULL) { Verbose("Could not open file %s\n",string); return; } while(!feof(fp) && ReadLine(linebuf,CF_BUFSIZE,fp)) { if ((ip = (struct Item *)malloc(sizeof(struct Item))) == NULL) { CfLog(cferror,"","Can't allocate memory in InsertItemAfter()"); FatalError(""); } if ((sp = malloc(strlen(linebuf)+1)) == NULL) { CfLog(cferror,"","Can't allocate memory in InsertItemAfter()"); FatalError(""); } if (CURRENTLINEPTR == NULL) { if (*filestart == NULL) { *filestart = ip; ip->next = NULL; } else { ip->next = (*filestart)->next; (*filestart)->next = ip; } strcpy(sp,linebuf); ip->name = sp; ip->classes = NULL; CURRENTLINEPTR = ip; CURRENTLINENUMBER = 1; } else { ip->next = CURRENTLINEPTR->next; CURRENTLINEPTR->next = ip; CURRENTLINEPTR=ip; CURRENTLINENUMBER++; strcpy(sp,linebuf); ip->name = sp; ip->classes = NULL; } } NUMBEROFEDITS++; fclose(fp); return; } cfengine-2.2.10/src/crypto.c0000644000175000001440000002347311131053527012551 00000000000000/* Copyright (C) 1999 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: crypto.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include "../pub/global.h" /**********************************************************************/ void RandomSeed() { static unsigned char digest[EVP_MAX_MD_SIZE+1]; struct stat statbuf; /* Use the system database as the entropy source for random numbers */ Debug("RandomSeed() work directory is %s\n",VLOGDIR); snprintf(VBUFF,CF_BUFSIZE,"%s/randseed",VLOGDIR); if (stat(VBUFF,&statbuf) == -1) { snprintf(AVDB,CF_MAXVARSIZE-1,"%s/state/%s",CFWORKDIR,CF_AVDB_FILE); } else { strncpy(AVDB,VBUFF,CF_MAXVARSIZE-1); } Verbose("Looking for a source of entropy in %s\n",AVDB); if (!RAND_load_file(AVDB,-1)) { snprintf(OUTPUT,CF_BUFSIZE,"Could not read sufficient randomness from %s\n",AVDB); CfLog(cfverbose,OUTPUT,""); } while (!RAND_status()) { MD5Random(digest); RAND_seed((void *)digest,16); } } /*********************************************************************/ void LoadSecretKeys() { FILE *fp; static char *passphrase = "Cfengine passphrase"; unsigned long err; if ((fp = fopen(CFPRIVKEYFILE,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't find a private key (%s) - use cfkey to get one",CFPRIVKEYFILE); CfLog(cfinform,OUTPUT,"open"); return; } if ((PRIVKEY = PEM_read_RSAPrivateKey(fp,(RSA **)NULL,NULL,passphrase)) == NULL) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Error reading Private Key = %s\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); PRIVKEY = NULL; fclose(fp); return; } fclose(fp); Verbose("Loaded %s\n",CFPRIVKEYFILE); if ((fp = fopen(CFPUBKEYFILE,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't find a public key (%s) - use cfkey to get one",CFPUBKEYFILE); CfLog(cferror,OUTPUT,"fopen"); return; } if ((PUBKEY = PEM_read_RSAPublicKey(fp,NULL,NULL,passphrase)) == NULL) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Error reading Private Key = %s\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); PUBKEY = NULL; fclose(fp); return; } Verbose("Loaded %s\n",CFPUBKEYFILE); fclose(fp); if (BN_num_bits(PUBKEY->e) < 2 || !BN_is_odd(PUBKEY->e)) { FatalError("RSA Exponent too small or not odd"); } } /*********************************************************************/ RSA *HavePublicKey(char *name) { char filename[CF_BUFSIZE],*sp; struct stat statbuf; static char *passphrase = "public"; unsigned long err; FILE *fp; RSA *newkey = NULL; Debug("HavePublickey(%s)\n",name); if (!IsPrivileged()) { Verbose("\n(Non privileged user...)\n\n"); if ((sp = getenv("HOME")) == NULL) { FatalError("You do not have a HOME variable pointing to your home directory"); } snprintf(filename,CF_BUFSIZE,"%s/.cfagent/ppkeys/%s.pub",sp,name); } else { snprintf(filename,CF_BUFSIZE,"%s/ppkeys/%s.pub",CFWORKDIR,name); } if (stat(filename,&statbuf) == -1) { Debug("Did not have key %s\n",name); return NULL; } else { if ((fp = fopen(filename,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't find a public key (%s) - use cfkey to get one",filename); CfLog(cferror,OUTPUT,"open"); return NULL; } if ((newkey = PEM_read_RSAPublicKey(fp,NULL,NULL,passphrase)) == NULL) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Error reading Private Key = %s\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); fclose(fp); return NULL; } Verbose("Loaded %s\n",filename); fclose(fp); if (BN_num_bits(newkey->e) < 2 || !BN_is_odd(newkey->e)) { FatalError("RSA Exponent too small or not odd"); } return newkey; } } /*********************************************************************/ void SavePublicKey(char *name,RSA *key) { char filename[CF_BUFSIZE],*sp; struct stat statbuf; FILE *fp; int err; Debug("SavePublicKey %s\n",name); if (!IsPrivileged()) { Verbose("\n(Non privileged user...)\n\n"); if ((sp = getenv("HOME")) == NULL) { FatalError("You do not have a HOME variable pointing to your home directory"); } snprintf(filename,CF_BUFSIZE,"%s/.cfagent/ppkeys/%s.pub",sp,name); } else { snprintf(filename,CF_BUFSIZE,"%s/ppkeys/%s.pub",CFWORKDIR,name); } if (stat(filename,&statbuf) != -1) { return; } Verbose("Saving public key %s\n",filename); if ((fp = fopen(filename, "w")) == NULL ) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to write a public key %s",filename); CfLog(cferror,OUTPUT,"fopen"); return; } if (!PEM_write_RSAPublicKey(fp,key)) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Error saving public key %s = %s\n",filename,ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); } fclose(fp); } /*********************************************************************/ void DeletePublicKey(name) char *name; { char filename[CF_BUFSIZE],*sp; if (!IsPrivileged()) { Verbose("\n(Non privileged user...)\n\n"); if ((sp = getenv("HOME")) == NULL) { FatalError("You do not have a HOME variable pointing to your home directory"); } snprintf(filename,CF_BUFSIZE,"%s/.cfagent/ppkeys/%s.pub",sp,name); } else { snprintf(filename,CF_BUFSIZE,"%s/ppkeys/%s.pub",CFWORKDIR,name); } unlink(filename); } /*********************************************************************/ void MD5Random(unsigned char digest[EVP_MAX_MD_SIZE+1]) /* Make a decent random number by crunching some system states & garbage through MD5. We can use this as a seed for pseudo random generator */ { unsigned char buffer[CF_BUFSIZE]; char pscomm[CF_BUFSIZE]; char uninitbuffer[100]; int md_len; const EVP_MD *md; EVP_MD_CTX context; FILE *pp; Verbose("Looking for a random number seed...\n"); md = EVP_get_digestbyname("md5"); EVP_DigestInit(&context,md); Verbose("...\n"); snprintf(buffer,CF_BUFSIZE,"%d%d%25s",(int)CFSTARTTIME,(int)digest,VFQNAME); EVP_DigestUpdate(&context,buffer,CF_BUFSIZE); snprintf(pscomm,CF_BUFSIZE,"%s %s",VPSCOMM[VSYSTEMHARDCLASS],VPSOPTS[VSYSTEMHARDCLASS]); if ((pp = cfpopen(pscomm,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open the process list with command %s\n",pscomm); CfLog(cferror,OUTPUT,"popen"); } while (!feof(pp)) { ReadLine(buffer,CF_BUFSIZE,pp); EVP_DigestUpdate(&context,buffer,CF_BUFSIZE); } uninitbuffer[99] = '\0'; snprintf(buffer,CF_BUFSIZE-1,"%ld %s",time(NULL),uninitbuffer); EVP_DigestUpdate(&context,buffer,CF_BUFSIZE); cfpclose(pp); EVP_DigestFinal(&context,digest,&md_len); } /*********************************************************************/ void GenerateRandomSessionKey() { BIGNUM *bp; /* Hardcode blowfish for now - it's fast */ bp = BN_new(); BN_rand(bp,CF_BLOWFISHSIZE,0,0); CONN->session_key = (unsigned char *)bp; } /*********************************************************************/ int EncryptString(char *in,char *out,unsigned char *key,int plainlen) { int cipherlen, tmplen; unsigned char iv[8] = {1,2,3,4,5,6,7,8}; EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit(&ctx,EVP_bf_cbc(),key,iv); if (!EVP_EncryptUpdate(&ctx,out,&cipherlen,in,plainlen)) { return -1; } if (!EVP_EncryptFinal(&ctx,out+cipherlen,&tmplen)) { return -1; } cipherlen += tmplen; EVP_CIPHER_CTX_cleanup(&ctx); return cipherlen; } /*********************************************************************/ int DecryptString(char *in,char *out,unsigned char *key,int cipherlen) { int plainlen, tmplen; unsigned char iv[8] = {1,2,3,4,5,6,7,8}; EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); EVP_DecryptInit(&ctx,EVP_bf_cbc(),key,iv); if (!EVP_DecryptUpdate(&ctx,out,&plainlen,in,cipherlen)) { return -1; } if (!EVP_DecryptFinal(&ctx,out+plainlen,&tmplen)) { return -1; } plainlen += tmplen; EVP_CIPHER_CTX_cleanup(&ctx); return plainlen; } /*********************************************************************/ void DebugBinOut(char *buffer,int len) { char *sp; int check = 0; Debug("BinaryBuffer(%d)[",len); for (sp = buffer; (sp < buffer+len); sp++) { check++; Debug("%x",*sp); } Debug("] = %d\n",check); } /*********************************************************************/ char *KeyPrint(RSA *pubkey) { unsigned char digest[EVP_MAX_MD_SIZE+1]; int i; for (i = 0; i < EVP_MAX_MD_SIZE+1; i++) { digest[i] = 0; } ChecksumString((char *)pubkey,sizeof(BIGNUM)-4,digest,'m'); return ChecksumPrint('m',digest); } cfengine-2.2.10/src/edittools.c0000644000175000001440000016520211053054350013232 00000000000000 /* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /********************************************************************/ /* */ /* EDITING of simple textfiles (Toolkit) */ /* */ /********************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /********************************************************************/ /* EDIT Data structure routines */ /********************************************************************/ void WrapDoEditFile(struct Edit *ptr,char *filename) { struct stat statbuf,statbuf2; char linkname[CF_BUFSIZE]; char realname[CF_BUFSIZE]; Debug("WrapDoEditFile(%s,%s)\n",ptr->fname,filename); if (lstat(filename,&statbuf) != -1) { if (S_ISLNK(statbuf.st_mode)) { EditVerbose("File %s is a link, editing real file instead\n",filename); memset(linkname,0,CF_BUFSIZE); memset(realname,0,CF_BUFSIZE); if (readlink(filename,linkname,CF_BUFSIZE-1) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot read link %s\n",filename); CfLog(cferror,OUTPUT,"readlink"); return; } if (linkname[0] != '/') { strcpy(realname,filename); ChopLastNode(realname); AddSlash(realname); } if (BufferOverflow(realname,linkname)) { snprintf(OUTPUT,CF_BUFSIZE*2,"(culprit %s in editfiles)\n",filename); CfLog(cferror,OUTPUT,""); return; } if (stat(filename,&statbuf2) != -1) { if (statbuf2.st_uid != statbuf.st_uid) { /* Link to /etc/passwd? ouch! */ snprintf(OUTPUT,CF_BUFSIZE*2,"Forbidden to edit a link to another user's file with privilege (%s)",filename); CfLog(cfinform,OUTPUT,""); return; } } strcat(realname,linkname); if (!FileObjectFilter(realname,&statbuf2,ptr->filters,editfiles)) { Debug("Skipping filtered editfile %s\n",filename); return; } DoEditFile(ptr,realname); return; } else { if (!FileObjectFilter(filename,&statbuf,ptr->filters,editfiles)) { Debug("Skipping filtered editfile %s\n",filename); return; } DoEditFile(ptr,filename); return; } } else { if (!FileObjectFilter(filename,&statbuf,ptr->filters,editfiles)) { Debug("Skipping filtered editfile %s\n",filename); return; } DoEditFile(ptr,filename); } } /********************************************************************/ void DoEditFile(struct Edit *ptr,char *filename) /* Many of the functions called here are defined in the */ /* item.c toolkit since they operate on linked lists */ { struct Edlist *ep, *loopstart, *loopend, *ThrowAbort(); struct Item *filestart = NULL, *newlineptr = NULL; char currenteditscript[CF_BUFSIZE], searchstr[CF_BUFSIZE], expdata[CF_EXPANDSIZE]; char *sp, currentitem[CF_MAXVARSIZE]; struct stat tmpstat; char spliton = ':'; int todo = 0, potentially_outstanding = false; FILE *loop_fp = NULL; int DeleteItemNotContaining(),DeleteItemNotStarting(),DeleteItemNotMatching(); int global_replace = -1, ifel=-1,expaf=-1; int ifelapsed=VIFELAPSED,expireafter=VEXPIREAFTER; Debug("DoEditFile(%s)\n",filename); filestart = NULL; currenteditscript[0] = '\0'; searchstr[0] = '\0'; memset(EDITBUFF,0,CF_BUFSIZE); AUTOCREATED = false; IMAGEBACKUP = 's'; if (IgnoredOrExcluded(editfiles,filename,ptr->inclusions,ptr->exclusions)) { Debug("Skipping excluded file %s\n",filename); return; } for (ep = ptr->actions; ep != NULL; ep=ep->next) { if (!IsExcluded(ep->classes)) { todo++; } switch (ep->code) { case EditIfElapsed: ifel = atoi(ep->data); if (ifel > 0) { ifelapsed = ifel; } break; case EditExpireAfter: expaf = atoi(ep->data); if (expaf > 0) { expireafter = expaf; } break; } } if (todo == 0) /* Because classes are stored per edit, not per file */ { return; } if (!GetLock(ASUniqueName("editfile"),CanonifyName(filename),ifelapsed,expireafter,VUQNAME,CFSTARTTIME)) { ptr->done = 'y'; return; } if (ptr->binary == 'y') { BinaryEditFile(ptr,filename); ReleaseCurrentLock(); return; } CheckEditSwitches(filename,ptr); if (! LoadItemList(&filestart,filename)) { if (ptr->warn == 'y') { CfLog(cfverbose,"File was marked for editing\n",""); } ReleaseCurrentLock(); return; } NUMBEROFEDITS = 0; EDITVERBOSE = VERBOSE; CURRENTLINENUMBER = 1; CURRENTLINEPTR = filestart; strcpy(COMMENTSTART,"# "); strcpy(COMMENTEND,""); EDITGROUPLEVEL = 0; SEARCHREPLACELEVEL = 0; FOREACHLEVEL = 0; loopstart = NULL; Verbose("Begin editing %s\n",filename); ep = ptr->actions; while (ep != NULL) { if (IsExcluded(ep->classes)) { ep = ep->next; potentially_outstanding = true; continue; } ExpandVarstring(ep->data,expdata,NULL); Debug2("Edit action: %s\n",VEDITNAMES[ep->code]); switch(ep->code) { case NoEdit: case EditInform: case LogAudit: case EditBackup: case EditLog: case EditUmask: case AutoCreate: case WarnIfFileMissing: case EditInclude: case EditExclude: case EditFilter: case DefineClasses: case ElseDefineClasses: case EditIfElapsed: case EditExpireAfter: case EditSplit: break; case EditUseShell: if (strcmp(expdata,"false") == 0) { ptr->useshell = 'n'; } break; case DefineInGroup: if (EDITGROUPLEVEL < 1) { yyerror("DefineInGroup used outside edit-group"); break; } for (sp = expdata; *sp != '\0'; sp++) { currentitem[0] = '\0'; sscanf(sp,"%[^,:.]",currentitem); sp += strlen(currentitem); AddClassToHeap(currentitem); } break; case CatchAbort: EditVerbose("Caught Exception\n"); break; case SplitOn: spliton = *(expdata); EditVerbose("Split lines by %c\n",spliton); break; case DeleteLinesStarting: while (DeleteItemStarting(&filestart,expdata)) { } break; case DeleteLinesContaining: while (DeleteItemContaining(&filestart,expdata)) { } break; case DeleteLinesNotStarting: while (DeleteItemNotStarting(&filestart,expdata)) { } break; case DeleteLinesNotContaining: while (DeleteItemNotContaining(&filestart,expdata)) { } break; case DeleteLinesStartingFileItems: case DeleteLinesContainingFileItems: case DeleteLinesMatchingFileItems: case DeleteLinesNotStartingFileItems: case DeleteLinesNotContainingFileItems: case DeleteLinesNotMatchingFileItems: if (!DeleteLinesWithFileItems(&filestart,expdata,ep->code)) { goto abort; } break; case DeleteLinesAfterThisMatching: if ((filestart == NULL) || (CURRENTLINEPTR == NULL)) { break; } else if (CURRENTLINEPTR->next != NULL) { while (DeleteItemMatching(&(CURRENTLINEPTR->next),expdata)) { } } break; case DeleteLinesMatching: while (DeleteItemMatching(&filestart,expdata)) { } break; case DeleteLinesNotMatching: while (DeleteItemNotMatching(&filestart,expdata)) { } break; case Append: AppendItem(&filestart,expdata,NULL); break; case AppendIfNoSuchLine: if (!IsItemIn(filestart,expdata)) { AppendItem(&filestart,expdata,NULL); } break; case AppendIfNoSuchLinesFromFile: if (!AppendLinesFromFile(&filestart,expdata)) { goto abort; } break; case SetLine: strncpy(EDITBUFF,expdata,CF_BUFSIZE); EditVerbose("Set current line to %s\n",EDITBUFF); break; case AppendIfNoLineMatching: Debug("AppendIfNoLineMatching : %s\n",EDITBUFF); if (strcmp(EDITBUFF,"") == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"SetLine not set when calling AppendIfNoLineMatching %s\n",expdata); CfLog(cferror,OUTPUT,""); break; } if (strcmp(expdata,"ThisLine") == 0) { if (LocateNextItemMatching(filestart,EDITBUFF) == NULL) { AppendItem(&filestart,EDITBUFF,NULL); } break; } if (LocateNextItemMatching(filestart,expdata) == NULL) { AppendItem(&filestart,EDITBUFF,NULL); } break; case Prepend: PrependItem(&filestart,expdata,NULL); break; case PrependIfNoSuchLine: if (! IsItemIn(filestart,expdata)) { PrependItem(&filestart,expdata,NULL); } break; case PrependIfNoLineMatching: if (strcmp(EDITBUFF,"") == 0) { snprintf(OUTPUT,CF_BUFSIZE,"SetLine not set when calling PrependIfNoLineMatching %s\n",expdata); CfLog(cferror,OUTPUT,""); break; } if (LocateNextItemMatching(filestart,expdata) == NULL) { PrependItem(&filestart,EDITBUFF,NULL); } break; case WarnIfNoSuchLine: if ((PASS == 1) && (LocateNextItemMatching(filestart,expdata) == NULL)) { printf("Warning, file %s has no line matching %s\n",filename,expdata); } break; case WarnIfLineMatching: if ((PASS == 1) && (LocateNextItemMatching(filestart,expdata) != NULL)) { printf("Warning, file %s has a line matching %s\n",filename,expdata); } break; case WarnIfNoLineMatching: if ((PASS == 1) && (LocateNextItemMatching(filestart,expdata) == NULL)) { printf("Warning, file %s has a no line matching %s\n",filename,expdata); } break; case WarnIfLineStarting: if ((PASS == 1) && (LocateNextItemStarting(filestart,expdata) != NULL)) { printf("Warning, file %s has a line starting %s\n",filename,expdata); } break; case WarnIfNoLineStarting: if ((PASS == 1) && (LocateNextItemStarting(filestart,expdata) == NULL)) { printf("Warning, file %s has no line starting %s\n",filename,expdata); } break; case WarnIfLineContaining: if ((PASS == 1) && (LocateNextItemContaining(filestart,expdata) != NULL)) { printf("Warning, file %s has a line containing %s\n",filename,expdata); } break; case WarnIfNoLineContaining: if ((PASS == 1) && (LocateNextItemContaining(filestart,expdata) == NULL)) { printf("Warning, file %s has no line containing %s\n",filename,expdata); } break; case SetCommentStart: strncpy(COMMENTSTART,expdata,CF_MAXVARSIZE); COMMENTSTART[CF_MAXVARSIZE-1] = '\0'; break; case SetCommentEnd: strncpy(COMMENTEND,expdata,CF_MAXVARSIZE); COMMENTEND[CF_MAXVARSIZE-1] = '\0'; break; case CommentLinesMatching: while (CommentItemMatching(&filestart,expdata,COMMENTSTART,COMMENTEND)) { } break; case CommentLinesStarting: while (CommentItemStarting(&filestart,expdata,COMMENTSTART,COMMENTEND)) { } break; case CommentLinesContaining: while (CommentItemContaining(&filestart,expdata,COMMENTSTART,COMMENTEND)) { } break; case HashCommentLinesContaining: while (CommentItemContaining(&filestart,expdata,"# ","")) { } break; case HashCommentLinesStarting: while (CommentItemStarting(&filestart,expdata,"# ","")) { } break; case HashCommentLinesMatching: while (CommentItemMatching(&filestart,expdata,"# ","")) { } break; case SlashCommentLinesContaining: while (CommentItemContaining(&filestart,expdata,"//","")) { } break; case SlashCommentLinesStarting: while (CommentItemStarting(&filestart,expdata,"//","")) { } break; case SlashCommentLinesMatching: while (CommentItemMatching(&filestart,expdata,"//","")) { } break; case PercentCommentLinesContaining: while (CommentItemContaining(&filestart,expdata,"%","")) { } break; case PercentCommentLinesStarting: while (CommentItemStarting(&filestart,expdata,"%","")) { } break; case PercentCommentLinesMatching: while (CommentItemMatching(&filestart,expdata,"%","")) { } break; case ResetSearch: if (!ResetEditSearch(expdata,filestart)) { printf("ResetSearch Failed in %s, aborting editing\n",filename); goto abort; } break; case LocateLineMatching: if (CURRENTLINEPTR == NULL) { newlineptr = NULL; } else { newlineptr = LocateItemMatchingRegExp(CURRENTLINEPTR,expdata); } if (newlineptr == NULL) { EditVerbose("LocateLineMatchingRegexp failed in %s, aborting editing\n",filename); ep = ThrowAbort(ep); } break; case InsertLine: if (filestart == NULL) { AppendItem(&filestart,expdata,NULL); } else { InsertItemAfter(&filestart,CURRENTLINEPTR,expdata); } break; case InsertFile: InsertFileAfter(&filestart,CURRENTLINEPTR,expdata); break; case IncrementPointer: if (! IncrementEditPointer(expdata,filestart)) /* edittools */ { printf ("IncrementPointer failed in %s, aborting editing\n",filename); ep = ThrowAbort(ep); } break; case ReplaceLineWith: if (!ReplaceEditLineWith(expdata)) { printf("Aborting edit of file %s\n",filename); continue; } break; case ExpandVariables: if (!ExpandAllVariables(filestart)) { printf("Aborting edit of file %s\n",filename); continue; } break; case DeleteToLineMatching: if (! DeleteToRegExp(&filestart,expdata)) { EditVerbose("Nothing matched DeleteToLineMatching regular expression\n"); EditVerbose("Aborting file editing of %s.\n" ,filename); ep = ThrowAbort(ep); } break; case DeleteNLines: if (! DeleteSeveralLines(&filestart,expdata)) { EditVerbose("Could not delete %s lines from file\n",expdata); EditVerbose("Aborting file editing of %s.\n",filename); ep = ThrowAbort(ep); } break; case HashCommentToLineMatching: if (! CommentToRegExp(&filestart,expdata,"#","")) { EditVerbose("Nothing matched HashCommentToLineMatching regular expression\n"); EditVerbose("Aborting file editing of %s.\n",filename); ep = ThrowAbort(ep); } break; case PercentCommentToLineMatching: if (! CommentToRegExp(&filestart,expdata,"%","")) { EditVerbose("Nothing matched PercentCommentToLineMatching regular expression\n"); EditVerbose("Aborting file editing of %s.\n",filename); ep = ThrowAbort(ep); } break; case CommentToLineMatching: if (! CommentToRegExp(&filestart,expdata,COMMENTSTART,COMMENTEND)) { EditVerbose("Nothing matched CommentToLineMatching regular expression\n"); EditVerbose("Aborting file editing of %s.\n",filename); ep = ThrowAbort(ep); } break; case UnCommentToLineMatching: if (! UnCommentToRegExp(&filestart,expdata,COMMENTSTART,COMMENTEND)) { EditVerbose("Nothing matched UnCommentToLineMatching regular expression\n"); EditVerbose("Aborting file editing of %s.\n",filename); ep = ThrowAbort(ep); } break; case CommentNLines: if (! CommentSeveralLines(&filestart,expdata,COMMENTSTART,COMMENTEND)) { EditVerbose("Could not comment %s lines from file\n",expdata); EditVerbose("Aborting file editing of %s.\n",filename); ep = ThrowAbort(ep); } break; case UnCommentNLines: if (! UnCommentSeveralLines(&filestart,expdata,COMMENTSTART,COMMENTEND)) { EditVerbose("Could not comment %s lines from file\n",expdata); EditVerbose("Aborting file editing of %s.\n",filename); ep = ThrowAbort(ep); } break; case UnCommentLinesContaining: while (UnCommentItemContaining(&filestart,expdata,COMMENTSTART,COMMENTEND)) { } break; case UnCommentLinesMatching: while (UnCommentItemMatching(&filestart,expdata,COMMENTSTART,COMMENTEND)) { } break; case SetScript: strncpy(currenteditscript, expdata, CF_BUFSIZE); currenteditscript[CF_BUFSIZE-1] = '\0'; break; case RunScript: if (! RunEditScript(expdata,filename,&filestart,ptr)) { printf("Aborting further edits to %s\n",filename); ep = ThrowAbort(ep); } break; case RunScriptIfNoLineMatching: if (! LocateNextItemMatching(filestart,expdata)) { if (! RunEditScript(currenteditscript,filename,&filestart,ptr)) { printf("Aborting further edits to %s\n",filename); ep = ThrowAbort(ep); } } break; case RunScriptIfLineMatching: if (LocateNextItemMatching(filestart,expdata)) { if (! RunEditScript(currenteditscript,filename,&filestart,ptr)) { printf("Aborting further edits to %s\n",filename); ep = ThrowAbort(ep); } } break; case EmptyEntireFilePlease: EditVerbose("Emptying entire file\n"); DeleteItemList(filestart); filestart = NULL; CURRENTLINEPTR = NULL; CURRENTLINENUMBER=0; NUMBEROFEDITS++; break; case GotoLastLine: GotoLastItem(filestart); break; case BreakIfLineMatches: if (CURRENTLINEPTR == NULL || CURRENTLINEPTR->name == NULL ) { EditVerbose("(BreakIfLIneMatches - no match for %s - file empty)\n",expdata); break; } if (LineMatches(CURRENTLINEPTR->name,expdata)) { EditVerbose("Break! %s\n",expdata); goto abort; } break; case BeginGroupIfNoMatch: if (CURRENTLINEPTR == NULL || CURRENTLINEPTR->name == NULL ) { EditVerbose("(Begin Group - no match for %s - file empty)\n",expdata); break; } if (LineMatches(CURRENTLINEPTR->name,expdata)) { EditVerbose("(Begin Group - skipping %s)\n",expdata); ep = SkipToEndGroup(ep,filename); } else { EditVerbose("(Begin Group - no match for %s)\n",expdata); EDITGROUPLEVEL++; } break; case BeginGroupIfMatch: if (CURRENTLINEPTR == NULL || CURRENTLINEPTR->name == NULL ) { EditVerbose("(Begin Group - no match for %s - file empty)\n",expdata); break; } if (LineMatches(CURRENTLINEPTR->name,expdata)) { EditVerbose("(Begin Group - match for %s)\n",expdata); EDITGROUPLEVEL++; } else { EditVerbose("(Begin Group - skipping %s)\n",expdata); ep = SkipToEndGroup(ep,filename); } break; case BeginGroupIfNoLineMatching: if (LocateItemMatchingRegExp(filestart,expdata) != 0) { EditVerbose("(Begin Group - skipping %s)\n",expdata); ep = SkipToEndGroup(ep,filename); } else { EditVerbose("(Begin Group - no line matching %s)\n",expdata); EDITGROUPLEVEL++; } break; case BeginGroupIfLineMatching: if (LocateItemMatchingRegExp(filestart,expdata) == 0) { EditVerbose("(Begin Group - skipping %s)\n",expdata); ep = SkipToEndGroup(ep,filename); } else { EditVerbose("(Begin Group - line matching %s)\n",expdata); EDITGROUPLEVEL++; } break; case BeginGroupIfNoLineContaining: if (LocateNextItemContaining(filestart,expdata) != 0) { EditVerbose("(Begin Group - skipping, string matched)\n"); ep = SkipToEndGroup(ep,filename); } else { EditVerbose("(Begin Group - no line containing %s)\n",expdata); EDITGROUPLEVEL++; } break; case BeginGroupIfLineContaining: if (LocateNextItemContaining(filestart,expdata) == 0) { EditVerbose("(Begin Group - skipping, string matched)\n"); ep = SkipToEndGroup(ep,filename); } else { EditVerbose("(Begin Group - line containing %s)\n",expdata); EDITGROUPLEVEL++; } break; case BeginGroupIfNoSuchLine: if (IsItemIn(filestart,expdata)) { EditVerbose("(Begin Group - skipping, line exists)\n"); ep = SkipToEndGroup(ep,filename); } else { EditVerbose("(Begin Group - no line %s)\n",expdata); EDITGROUPLEVEL++; } break; case BeginGroupIfFileIsNewer: if ((!AUTOCREATED) && (!FileIsNewer(filename,expdata))) { EditVerbose("(Begin Group - skipping, file is older)\n"); while(ep->code != EndGroup) { ep=ep->next; } } else { EditVerbose("(Begin Group - new file %s)\n",expdata); EDITGROUPLEVEL++; } break; case BeginGroupIfDefined: if (!IsExcluded(expdata)) { EditVerbose("(Begin Group - class %s defined)\n", expdata); EDITGROUPLEVEL++; } else { EditVerbose("(Begin Group - class %s not defined - skipping)\n", expdata); ep = SkipToEndGroup(ep,filename); } break; case BeginGroupIfNotDefined: if (IsExcluded(expdata)) { EDITGROUPLEVEL++; EditVerbose("(Begin Group - class %s not defined)\n", expdata); } else { EditVerbose("(Begin Group - class %s defined - skipping)\n", expdata); ep = SkipToEndGroup(ep,filename); } break; case BeginGroupIfFileExists: if (stat(expdata,&tmpstat) == -1) { EditVerbose("(Begin Group - file unreadable/no such file - skipping)\n"); ep = SkipToEndGroup(ep,filename); } else { EditVerbose("(Begin Group - found file %s)\n",expdata); EDITGROUPLEVEL++; } break; case EndGroup: EditVerbose("(End Group)\n"); EDITGROUPLEVEL--; break; case ReplaceAll: strncpy(searchstr,expdata,CF_BUFSIZE); global_replace = true; break; case ReplaceFirst: strncpy(searchstr,expdata,CF_BUFSIZE); global_replace = false; break; case With: switch(global_replace) { case true: if (!GlobalReplace(&filestart,searchstr,expdata)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error editing file %s",filename); CfLog(cferror,OUTPUT,""); } break; case false: if (!SingleReplace(&filestart,searchstr,expdata)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error editing file %s",filename); CfLog(cferror,OUTPUT,""); } break; default: snprintf(OUTPUT,CF_BUFSIZE*2,"Internal error editing file %s: found With without finding ReplaceAll or ReplaceFirst first!!?",filename); CfLog(cferror,OUTPUT,""); } global_replace = -1; break; case FixEndOfLine: DoFixEndOfLine(filestart,expdata); break; case AbortAtLineMatching: EDABORTMODE = true; strncpy(VEDITABORT,expdata,CF_BUFSIZE); break; case UnsetAbort: EDABORTMODE = false; break; case AutoMountDirectResources: HandleAutomountResources(&filestart,expdata); break; case ForEachLineIn: if (loopstart == NULL) { loopstart = ep; if ((loop_fp = fopen(expdata,"r")) == NULL) { EditVerbose("Couldn't open %s\n",expdata); while(ep->code != EndLoop) /* skip over loop */ { ep = ep->next; } break; } EditVerbose("Starting ForEach loop with %s\n",expdata); continue; } else { if (!feof(loop_fp)) { memset(EDITBUFF,0,CF_BUFSIZE); while (ReadLine(EDITBUFF,CF_BUFSIZE,loop_fp)) /* Like SetLine */ { if (strlen(EDITBUFF) == 0) { EditVerbose("ForEachLineIn skipping blank line"); continue; } break; } if (strlen(EDITBUFF) == 0) { EditVerbose("EndForEachLineIn\n"); fclose(loop_fp); loopstart = NULL; while(ep->code != EndLoop) { ep = ep->next; } EditVerbose("EndForEachLineIn, set current line to: %s\n",EDITBUFF); } Debug("ForeachLine: %s\n",EDITBUFF); } else { EditVerbose("EndForEachLineIn"); fclose(loop_fp); loopstart = NULL; while(ep->code != EndLoop) { ep = ep->next; } } } break; case EndLoop: loopend = ep; ep = loopstart; continue; case ReplaceLinesMatchingField: ReplaceWithFieldMatch(&filestart,expdata,EDITBUFF,spliton,filename); break; case AppendToLineIfNotContains: if (CURRENTLINEPTR == NULL) { PrependItem(&filestart,expdata,NULL); } else { AppendToLine(CURRENTLINEPTR,expdata,filename); } break; default: snprintf(OUTPUT,CF_BUFSIZE*2,"Unknown action in editing of file %s\n",filename); CfLog(cferror,OUTPUT,""); break; } ep = ep->next; } abort : EditVerbose("End editing %s\n",filename); EditVerbose(".....................................................................\n"); EDITVERBOSE = false; EDABORTMODE = false; if (DONTDO || CompareToFile(filestart,filename)) { EditVerbose("Unchanged file: %s\n",filename); NUMBEROFEDITS = 0; } if ((! DONTDO) && (NUMBEROFEDITS > 0)) { snprintf(OUTPUT,CF_BUFSIZE,"Saving edit changes to file %s",filename); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); SaveItemList(filestart,filename,ptr->repository); AddEditfileClasses(ptr,true); } else { AddEditfileClasses(ptr,false); } ResetOutputRoute('d','d'); ReleaseCurrentLock(); DeleteItemList(filestart); if (!potentially_outstanding) { ptr->done = 'y'; } } /********************************************************************/ int IncrementEditPointer(char *str,struct Item *liststart) { int i,n = 0; struct Item *ip; sscanf(str,"%d", &n); if (n == 0) { printf("Illegal increment value: %s\n",str); return false; } Debug("IncrementEditPointer(%d)\n",n); if (CURRENTLINEPTR == NULL) /* is prev undefined, set to line 1 */ { if (liststart == NULL) { EditVerbose("cannot increment line pointer in empty file\n"); return true; } else { CURRENTLINEPTR=liststart; CURRENTLINENUMBER=1; } } if (n < 0) { if (CURRENTLINENUMBER + n < 1) { EditVerbose("pointer decrements to before start of file!\n"); EditVerbose("pointer stopped at start of file!\n"); CURRENTLINEPTR=liststart; CURRENTLINENUMBER=1; return true; } i = 1; for (ip = liststart; ip != CURRENTLINEPTR; ip=ip->next, i++) { if (i == CURRENTLINENUMBER + n) { CURRENTLINENUMBER += n; CURRENTLINEPTR = ip; Debug2("Current line (%d) starts: %20.20s ...\n",CURRENTLINENUMBER,CURRENTLINEPTR->name); return true; } } } for (i = 0; i < n; i++) { if (CURRENTLINEPTR->next != NULL) { CURRENTLINEPTR = CURRENTLINEPTR->next; CURRENTLINENUMBER++; EditVerbose("incrementing line pointer to line %d\n",CURRENTLINENUMBER); } else { EditVerbose("inc pointer failed, still at %d\n",CURRENTLINENUMBER); } } Debug2("Current line starts: %20s ...\n",CURRENTLINEPTR->name); return true; } /********************************************************************/ int ResetEditSearch (char *str,struct Item *list) { int i = 1 ,n = -1; struct Item *ip; sscanf(str,"%d", &n); if (n < 1) { printf("Illegal reset value: %s\n",str); return false; } for (ip = list; (i < n) && (ip != NULL); ip=ip->next, i++) { } if (i < n || ip == NULL) { printf("Search for (%s) begins after end of file!!\n",str); return false; } EditVerbose("resetting pointers to line %d\n",n); CURRENTLINENUMBER = n; CURRENTLINEPTR = ip; return true; } /********************************************************************/ int ReplaceEditLineWith (char *string) { char *sp; if (strcmp(string,CURRENTLINEPTR->name) == 0) { EditVerbose("ReplaceLineWith - line does not need correction.\n"); return true; } if ((sp = malloc(strlen(string)+1)) == NULL) { printf("Memory allocation failed in ReplaceEditLineWith, aborting edit.\n"); return false; } EditVerbose("Replacing line %d with %10s...\n",CURRENTLINENUMBER,string); strcpy(sp,string); free (CURRENTLINEPTR->name); CURRENTLINEPTR->name = sp; NUMBEROFEDITS++; return true; } /********************************************************************/ int ExpandAllVariables (struct Item *list) { char *sp; int i = 1; struct Item *ip; for (ip = list; ip != NULL; ip=ip->next, i++) { if ((sp = malloc(CF_EXPANDSIZE)) == NULL) { printf("Memory allocation failed in ExpandEditLineVariables, aborting edit.\n"); return false; } memset( sp, 0, CF_EXPANDSIZE); ExpandVarstring(ip->name,sp,NULL); if (strcmp(sp,ip->name) == 0) { continue; } EditVerbose("Expanded line %d to %10s...\n",i,sp); free (ip->name); ip->name = sp; NUMBEROFEDITS++; } return true; } /********************************************************************/ int RunEditScript (char *script,char *fname,struct Item **filestart,struct Edit *ptr) { FILE *pp; char buffer[CF_BUFSIZE]; if (script == NULL) { printf("No script defined for with SetScript\n"); return false; } if (DONTDO) { return true; } if (NUMBEROFEDITS > 0) { SaveItemList(*filestart,fname,ptr->repository); snprintf(OUTPUT,CF_BUFSIZE,"Saved file changes to %s",fname); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); AddEditfileClasses(ptr,true); } else { AddEditfileClasses(ptr,false); } DeleteItemList(*filestart); snprintf(buffer,CF_BUFSIZE,"%s %s %s 2>&1",script,fname,CLASSTEXT[VSYSTEMHARDCLASS]); EditVerbose("Running command: %s\n",buffer); switch (ptr->useshell) { case 'y': pp = cfpopen_sh(buffer,"r"); break; default: pp = cfpopen(buffer,"r"); break; } if (pp == NULL) { printf("Edit script %s failed to open.\n",buffer); snprintf(OUTPUT,CF_BUFSIZE,"Failed edit script %s",buffer); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_FAIL); return false; } while (!feof(pp)) { char buffer[CF_BUFSIZE]; ReadLine(buffer,CF_BUFSIZE-1,pp); if (!feof(pp)) { EditVerbose("%s\n",buffer); } } cfpclose(pp); *filestart = 0; if (! LoadItemList(filestart,fname)) { if (ptr->warn == 'y') { snprintf(OUTPUT,CF_BUFSIZE,"File %s did not exist and was marked for editing"); CfLog(cferror,OUTPUT,""); } return false; } NUMBEROFEDITS = 0; CURRENTLINENUMBER = 1; CURRENTLINEPTR = *filestart; return true; } /************************************************************/ void DoFixEndOfLine(struct Item *list,char *type) /* Assumes that CF_EXTRASPC macro allows enough space */ /* in the allocated strings to add a few characters */ { struct Item *ip; char *sp; int gotCR; EditVerbose("Checking end of line conventions: type = %s\n",type); if (strcmp("unix",type) == 0 || strcmp("UNIX",type) == 0) { for (ip = list; ip != NULL; ip=ip->next) { for (sp = ip->name; *sp != '\0'; sp++) { if (*sp == (char)13) { *sp = '\0'; NUMBEROFEDITS++; } } } return; } if (strcmp("dos",type) == 0 || strcmp("DOS",type) == 0) { for (ip = list; ip != NULL; ip = ip->next) { gotCR = false; for (sp = ip->name; *sp !='\0'; sp++) { if (*sp == (char)13) { gotCR = true; } } if (!gotCR) { *sp = (char)13; *(sp+1) = '\0'; NUMBEROFEDITS++; } } return; } printf("Unknown file format: %s\n",type); } /**************************************************************/ void HandleAutomountResources(struct Item **filestart,char *opts) { struct Mountables *mp; char buffer[CF_BUFSIZE]; char *sp; for (mp = VMOUNTABLES; mp != NULL; mp=mp->next) { for (sp = mp->filesystem; *sp != ':'; sp++) { } sp++; snprintf(buffer,CF_BUFSIZE,"%s\t%s\t%s",sp,opts,mp->filesystem); if (LocateNextItemContaining(*filestart,sp) == NULL) { AppendItem(filestart,buffer,""); NUMBEROFEDITS++; } else { EditVerbose("have a server for %s\n",sp); } } } /**************************************************************/ void CheckEditSwitches(char *filename,struct Edit *ptr) { struct stat statbuf; struct Edlist *ep; char inform, log; char expdata[CF_EXPANDSIZE]; int fd; struct Edlist *actions = ptr->actions; #ifdef WITH_SELINUX int selinux_enabled=0; security_context_t scontext=NULL; selinux_enabled = (is_selinux_enabled()>0); #endif PARSING = true; if (INFORM) { inform = 'y'; } else { inform = 'n'; } if (LOGGING) { log = 'y'; } else { log = 'n'; } for (ep = actions; ep != NULL; ep=ep->next) { if (IsExcluded(ep->classes)) { continue; } ExpandVarstring(ep->data,expdata,NULL); switch(ep->code) { case AutoCreate: if (!DONTDO) { mode_t mask; if (stat(filename,&statbuf) == -1) { Debug("Setting umask to %o\n",ptr->umask); mask=umask(ptr->umask); #ifdef WITH_SELINUX if(selinux_enabled) { /* use default security context when creating destination file */ matchpathcon(filename,0,&scontext); Debug("Setting SELinux context to: %s\n", scontext); setfscreatecon(scontext); } #endif if ((fd = creat(filename,0644)) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to create file %s\n",filename); CfLog(cfinform,OUTPUT,"creat"); } else { AUTOCREATED = true; close(fd); } snprintf(OUTPUT,CF_BUFSIZE*2,"Creating file %s, mode %o\n",filename,(0644 & ~ptr->umask)); CfLog(cfinform,OUTPUT,""); umask(mask); #ifdef WITH_SELINUX if (selinux_enabled) { /* set create context back to default */ setfscreatecon(NULL); freecon(scontext); } #endif break; } } else { if (stat(filename,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Should create and edit file %s, mode %o\n",filename,(0644 & ~ptr->umask)); CfLog(cfinform,OUTPUT,""); } } break; case EditBackup: if (strcmp("false",ToLowerStr(expdata)) == 0 || strcmp("off",ToLowerStr(expdata)) == 0) { IMAGEBACKUP = 'n'; } if (strcmp("single",ToLowerStr(expdata)) == 0 || strcmp("one",ToLowerStr(expdata)) == 0) { IMAGEBACKUP = 'y'; } if (strcmp("timestamp",ToLowerStr(expdata)) == 0 || strcmp("stamp",ToLowerStr(expdata)) == 0) { IMAGEBACKUP = 's'; } break; case EditLog: if (strcmp(ToLowerStr(expdata),"true") == 0 || strcmp(ToLowerStr(expdata),"on") == 0) { log = 'y'; break; } if (strcmp(ToLowerStr(expdata),"false") == 0 || strcmp(ToLowerStr(expdata),"off") == 0) { log = 'n'; break; } break; case EditInform: if (strcmp(ToLowerStr(expdata),"true") == 0 || strcmp(ToLowerStr(expdata),"on") == 0) { inform = 'y'; break; } if (strcmp(ToLowerStr(expdata),"false") == 0 || strcmp(ToLowerStr(expdata),"off") == 0) { inform = 'n'; break; } case LogAudit: if (strcmp(ToLowerStr(expdata),"true") == 0 || strcmp(ToLowerStr(expdata),"on") == 0) { ptr->logaudit = 'y'; break; } if (strcmp(ToLowerStr(expdata),"false") == 0 || strcmp(ToLowerStr(expdata),"off") == 0) { ptr->logaudit = 'n'; break; } break; } } PARSING = false; ResetOutputRoute(log,inform); } /**************************************************************/ /* Level 3 */ /**************************************************************/ void AddEditfileClasses (struct Edit *list,int editsdone) { char *sp, currentitem[CF_MAXVARSIZE]; struct Edlist *ep; if (editsdone) { for (ep = list->actions; ep != NULL; ep=ep->next) { if (IsExcluded(ep->classes)) { continue; } if (ep->code == DefineClasses) { Debug("AddEditfileClasses(%s)\n",ep->data); for (sp = ep->data; *sp != '\0'; sp++) { currentitem[0] = '\0'; sscanf(sp,"%[^,:.]",currentitem); sp += strlen(currentitem); AddClassToHeap(currentitem); } } } } else { for (ep = list->actions; ep != NULL; ep=ep->next) { if (IsExcluded(ep->classes)) { continue; } if (ep->code == ElseDefineClasses) { Debug("Entering AddEditfileClasses(%s)\n",ep->data); sp = ep->data; while(*sp != '\0') { currentitem[0] = '\0'; sscanf(sp,"%[^,:.]",currentitem); sp += strlen(currentitem); AddClassToHeap(currentitem); if (strlen(sp) > 0) { sp++; } } } } } if (ep == NULL) { return; } } /**************************************************************/ int DeleteLinesWithFileItems(struct Item **filestart,char *infile,enum editnames code) { struct Item *ip,*ipc,*infilelist = NULL; int slen, matches=0; int positive=false; if (!LoadItemList(&infilelist,infile)) { snprintf(OUTPUT,CF_BUFSIZE,"Cannot open file iterator %s in editfiles - aborting editing",infile); CfLog(cferror,OUTPUT,""); return false; } for (ip = *filestart; ip != NULL; ip = ip->next) { Verbose("Looking at line with %s\n",ip->name); positive = false; switch (code) { case DeleteLinesStartingFileItems: positive = true; case DeleteLinesNotStartingFileItems: matches = 0; for (ipc = infilelist; ipc != NULL; ipc=ipc->next) { Chop(ipc->name); slen = IntMin(strlen(ipc->name),strlen(ip->name)); if (strncmp(ipc->name,ip->name,slen) == 0) { Debug("Matched with %s\n",ipc->name); matches++; } } if (positive && (matches > 0)) { Debug("%s POS matched %s\n",VEDITNAMES[code],ip->name); DeleteItem(filestart,ip); } else if (!positive && matches == 0) { Debug("%s NEG matched %s\n",VEDITNAMES[code],ip->name); DeleteItem(filestart,ip); } break; case DeleteLinesContainingFileItems: positive = true; case DeleteLinesNotContainingFileItems: matches = 0; for (ipc = infilelist; ipc != NULL; ipc=ipc->next) { Chop(ipc->name); if (strstr(ipc->name,ip->name) == 0) { matches++; } else if(strstr(ip->name,ipc->name) == 0) { matches++; } } if (positive && (matches > 0)) { Debug("%s matched %s\n",VEDITNAMES[code],ip->name); DeleteItem(filestart,ip); } else if (!positive &&matches == 0) { Debug("%s matched %s\n",VEDITNAMES[code],ip->name); DeleteItem(filestart,ip); } break; case DeleteLinesMatchingFileItems: positive = true; case DeleteLinesNotMatchingFileItems: Verbose("%s not implemented (yet)\n",VEDITNAMES[code]); break; } } DeleteItemList(infilelist); return true; } /**************************************************************/ int AppendLinesFromFile(struct Item **filestart,char *filename) { FILE *fp; char buffer[CF_BUFSIZE]; if ((fp=fopen(filename,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Editfiles could not read file %s\n",filename); CfLog(cferror,OUTPUT,"fopen"); return false; } while (!feof(fp)) { buffer[0] = '\0'; fgets(buffer,CF_BUFSIZE-1,fp); Chop(buffer); if (!IsItemIn(*filestart,buffer)) { AppendItem(filestart,buffer,NULL); } } fclose(fp); return true; } /**************************************************************/ struct Edlist *ThrowAbort(struct Edlist *from) { struct Edlist *ep, *last = NULL; for (ep = from; ep != NULL; ep=ep->next) { if (ep->code == CatchAbort) { return ep; } last = ep; } return last; } /**************************************************************/ struct Edlist *SkipToEndGroup(struct Edlist *ep,char *filename) { int level = -1; while(ep != NULL) { switch (ep->code) { case BeginGroupIfMatch: case BeginGroupIfNoMatch: case BeginGroupIfNoLineMatching: case BeginGroupIfLineMatching: case BeginGroupIfNoSuchLine: case BeginGroupIfFileIsNewer: case BeginGroupIfFileExists: case BeginGroupIfLineContaining: case BeginGroupIfNoLineContaining: case BeginGroupIfDefined: case BeginGroupIfNotDefined: level ++; } Debug(" skip: %s (%d)\n",VEDITNAMES[ep->code],level); if (ep->code == EndGroup) { if (level == 0) { return ep; } level--; } if (ep->next == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Missing EndGroup in %s",filename); CfLog(cferror,OUTPUT,""); break; } ep=ep->next; } return ep; } /**************************************************************/ int BinaryEditFile(struct Edit *ptr,char *filename) { char expdata[CF_EXPANDSIZE],search[CF_BUFSIZE]; struct Edlist *ep; struct stat statbuf; void *memseg; EditVerbose("Begin (binary) editing %s\n",filename); NUMBEROFEDITS = 0; search[0] = '\0'; if (stat(filename,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't stat %s\n",filename); CfLog(cfverbose,OUTPUT,"stat"); return false; } if ((EDITBINFILESIZE != 0) &&(statbuf.st_size > EDITBINFILESIZE)) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is bigger than the limit \n",filename); CfLog(cfinform,OUTPUT,""); return(false); } if (! S_ISREG(statbuf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s is not a plain file\n",filename); CfLog(cfinform,OUTPUT,""); return false; } if ((memseg = malloc(statbuf.st_size+CF_BUFFERMARGIN)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to load file %s into memory",filename); CfLog(cferror,OUTPUT,"malloc"); return false; } LoadBinaryFile(filename,statbuf.st_size,memseg); ep = ptr->actions; while (ep != NULL) { if (IsExcluded(ep->classes)) { ep = ep->next; continue; } ExpandVarstring(ep->data,expdata,NULL); Debug2("Edit action: %s\n",VEDITNAMES[ep->code]); switch(ep->code) { case WarnIfContainsString: WarnIfContainsRegex(memseg,statbuf.st_size,expdata,filename); break; case WarnIfContainsFile: WarnIfContainsFilePattern(memseg,statbuf.st_size,expdata,filename); break; case EditMode: break; case ReplaceAll: Debug("Replace %s\n",expdata); strncpy(search,expdata,CF_BUFSIZE); break; case With: if (strcmp(expdata,search) == 0) { Verbose("Search and replace patterns are identical in binary edit %s\n",filename); break; } if (BinaryReplaceRegex(memseg,statbuf.st_size,search,expdata,filename)) { NUMBEROFEDITS++; } break; default: snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot use %s in a binary edit (%s)",VEDITNAMES[ep->code],filename); CfLog(cferror,OUTPUT,""); } ep=ep->next; } if ((! DONTDO) && (NUMBEROFEDITS > 0)) { SaveBinaryFile(filename,statbuf.st_size,memseg,ptr->repository); AddEditfileClasses(ptr,true); } else { AddEditfileClasses(ptr,false); } free(memseg); EditVerbose("End editing %s\n",filename); EditVerbose(".....................................................................\n"); return true; } /**************************************************************/ /* Level 4 */ /**************************************************************/ int LoadBinaryFile(char *source,off_t size,void *memseg) { int sd,n_read; char buf[CF_BUFSIZE]; off_t n_read_total = 0; char *ptr; Debug("LoadBinaryFile(%s,%d)\n",source,size); if ((sd = open(source,O_RDONLY)) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't copy %s!\n",source); CfLog(cfinform,OUTPUT,"open"); return false; } ptr = memseg; while (true) { if ((n_read = read (sd,buf,CF_BUFSIZE)) == -1) { if (errno == EINTR) { continue; } close(sd); return false; } memcpy(ptr,buf,n_read); ptr += n_read; if (n_read < CF_BUFSIZE) { break; } n_read_total += n_read; } close(sd); return true; } /**************************************************************/ int SaveBinaryFile(char *file,off_t size,void *memseg,char *repository) /* If we do this, we screw up checksums anyway, so no need to preserve unix holes here ...*/ { int dd; char new[CF_BUFSIZE],backup[CF_BUFSIZE]; Debug("SaveBinaryFile(%s,%d)\n",file,size); Verbose("Saving %s\n",file); strcpy(new,file); strcat(new,CF_NEW); strcpy(backup,file); strcat(backup,CF_EDITED); unlink(new); /* To avoid link attacks */ if ((dd = open(new,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600)) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Copy %s security - failed attempt to exploit a race? (Not copied)\n",file); CfLog(cfinform,OUTPUT,"open"); return false; } cf_full_write (dd,(char *)memseg,size); close(dd); if (! IsItemIn(VREPOSLIST,new)) { if (rename(file,backup) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error while renaming backup %s\n",file); CfLog(cferror,OUTPUT,"rename "); unlink(new); return false; } else if (Repository(backup,repository)) { if (rename(new,file) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error while renaming %s\n",file); CfLog(cferror,OUTPUT,"rename"); return false; } unlink(backup); return true; } } if (rename(new,file) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error while renaming %s\n",file); CfLog(cferror,OUTPUT,"rename"); return false; } return true; } /**************************************************************/ void WarnIfContainsRegex(void *memseg,off_t size,char *data,char *filename) { off_t sp; regex_t rx,rxcache; regmatch_t pmatch; Debug("WarnIfContainsRegex(%s)\n",data); for (sp = 0; sp < (off_t)(size-strlen(data)); sp++) { if (memcmp((char *) memseg+sp,data,strlen(data)) == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING! File %s contains literal string %.255s",filename,data); CfLog(cferror,OUTPUT,""); return; } } if (CfRegcomp(&rxcache,data,REG_EXTENDED) != 0) { return; } for (sp = 0; sp < (off_t)(size-strlen(data)); sp++) { memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,(char *)memseg+sp,1,&pmatch,0) == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING! File %s contains regular expression %.255s",filename,data); CfLog(cferror,OUTPUT,""); regfree(&rx); return; } } } /**************************************************************/ void WarnIfContainsFilePattern(void *memseg,off_t size,char *data,char *filename) { off_t sp; struct stat statbuf; char *pattern; Debug("WarnIfContainsFile(%s)\n",data); if (stat(data,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s cannot be opened",data); CfLog(cferror,OUTPUT,"stat"); return; } if (! S_ISREG(statbuf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s cannot be used as a binary pattern",data); CfLog(cferror,OUTPUT,""); return; } if (statbuf.st_size > size) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is larger than the search file, ignoring",data); CfLog(cfinform,OUTPUT,""); return; } if ((pattern = malloc(statbuf.st_size+CF_BUFFERMARGIN)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s cannot be loaded",data); CfLog(cferror,OUTPUT,""); return; } if (!LoadBinaryFile(data,statbuf.st_size,pattern)) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s cannot be opened",data); CfLog(cferror,OUTPUT,"stat"); return; } for (sp = 0; sp < (off_t)(size-statbuf.st_size); sp++) { if (memcmp((char *) memseg+sp,pattern,statbuf.st_size-1) == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING! File %s contains the contents of reference file %s",filename,data); CfLog(cferror,OUTPUT,""); free(pattern); return; } } free(pattern); } /**************************************************************/ int BinaryReplaceRegex(void *memseg,off_t size,char *search,char *replace,char *filename) { off_t sp,spr; regex_t rx,rxcache; regmatch_t pmatch; int match = false; Debug("BinaryReplaceRegex(%s,%s,%s)\n",search,replace,filename); if (CfRegcomp(&rxcache,search,REG_EXTENDED) != 0) { return false; } for (sp = 0; sp < (off_t)(size-strlen(replace)); sp++) { memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,(char *)(sp+(char *)memseg),1,&pmatch,0) == 0) { if (pmatch.rm_eo-pmatch.rm_so < strlen(replace)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot perform binary replacement: string doesn't fit in %s",filename); CfLog(cfverbose,OUTPUT,""); } else { Verbose("Replacing [%s] with [%s] at %d\n",search,replace,sp); match = true; strncpy((char *)memseg+sp+(off_t)pmatch.rm_so,replace,strlen(replace)); Verbose("Padding character is %c\n",PADCHAR); if ( pmatch.rm_so + strlen(replace) - pmatch.rm_eo >= pmatch.rm_eo ) { Verbose("ReplaceAll: replacement is smaller than match: padding replacement with %d chars!! (pad char is \"%c\")\n",pmatch.rm_eo - ( pmatch.rm_so + strlen(replace)), PADCHAR); } for (spr = (pmatch.rm_so+strlen(replace)); spr < pmatch.rm_eo; spr++) { *((char *)memseg+spr+sp) = PADCHAR; /* default space */ } sp += pmatch.rm_eo - pmatch.rm_so - 1; } } else { sp += strlen(replace); } } regfree(&rx); return match; } cfengine-2.2.10/src/cfetoolgraph.c0000644000175000001440000004770511045561210013707 00000000000000/* cfetool for GNU Copyright (C) 2001- Free Software Foundation, Inc. This file is part of GNU cfetool - an addition to GNU cfengine. It is written by Elizabeth Cassell and Alf Wachsmann, Stanford Linear Accelerator Center (SLAC), SLAC Computing Services, 2575 Sand Hill Road M/S 97, Menlo Park, CA 94025, USA. GNU cfengine is written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: cfetoolgraph.c */ /* */ /* Description: Standalone UI for Long term state registry */ /* */ /*****************************************************************************/ #include "../pub/getopt.h" #include "cf.defs.h" #include "cf.extern.h" #include "cfetooldefs.h" #include #include struct option GRAPHOPTIONS[] = { {"path", required_argument, 0, 'p'}, {"help", no_argument, 0, 'h'}, {"timestamps", no_argument, 0, 'T'}, {"resolution", no_argument, 0, 'r'}, {"no-scaling", no_argument, 0, 'n'}, {"weekly", no_argument, 0, 'w'}, {"daily", no_argument, 0, 'd'}, {"yearly", no_argument, 0, 'y'}, {NULL, 0, 0, 0} }; int weekly = false; int daily = false; int yearly = false; char *NAME; char LOCATION[CF_BUFSIZE]; char *PROG_NAME; char FILENAME[CF_BUFSIZE]; char PATHNAME[CF_BUFSIZE]; int INTERVAL; int TITLES = false; int TIMESTAMPS = false; int HIRES = false; int NOSCALING = true; int STEP; unsigned int HISTOGRAM[24][CF_GRAINS]; int SMOOTHHISTOGRAM[24][CF_GRAINS]; static struct Average ENTRY, MAX, MIN, DET; char TIMEKEY[64], FLNAME[CF_BUFSIZE], DIRNAME[CF_BUFSIZE], *sp; double AGE; int errno, i, j, k, count = 0, its; time_t NOW; DBT key, value; DB *DBP; FILE *FPAV = NULL, *FPVAR = NULL, *FPHIST = NULL, *FP = NULL; void ReadAverages (int dbtype); void SummarizeAverages (void); void WriteGraphFiles (int dbtype); void WriteHistogram (int dbtype); void FindHurstExponents (int dbtype); struct Average FindHurstFunction (int sameples_per_grain, int grains, int dbtype); void Syntax (void); /*********************************************************************/ int main(int argc, char **argv) { extern char *optarg; int optindex = 0; int c; char temp[CF_BUFSIZE]; memset(PATHNAME, 0, sizeof(PATHNAME)); PROG_NAME = argv[0]; if (argc < 2) { Syntax(); exit(1); } NAME = argv[1]; if(NAME[0] == '-') { Syntax(); exit(1); } argv++; argc--; while ((c = getopt_long(argc, argv, "Thtrndwyp:", GRAPHOPTIONS, &optindex)) != EOF) { switch ((char)c) { case 't': TITLES = true; break; case 'T': TIMESTAMPS = true; break; case 'r': HIRES = true; break; case 'n': NOSCALING = true; break; case 'p': strcpy(PATHNAME,optarg); break; case 'd': daily = true; break; case 'w': weekly = true; break; case 'y': yearly = true; break; default: Syntax(); exit(1); } } if(PATHNAME[0] != '\0') sprintf(LOCATION, "%s/%s", PATHNAME, NAME); else sprintf(LOCATION, "./%s", NAME); if(daily) { snprintf(FILENAME, CF_BUFSIZE, "%s/daily.db", LOCATION); ReadAverages(DAILY); SummarizeAverages(); WriteGraphFiles(DAILY); WriteHistogram(DAILY); FindHurstExponents(DAILY); } if(weekly || (!daily && !yearly)) { snprintf(FILENAME, CF_BUFSIZE, "%s/weekly.db", LOCATION); ReadAverages(WEEKLY); SummarizeAverages(); WriteGraphFiles(WEEKLY); WriteHistogram(WEEKLY); FindHurstExponents(WEEKLY); } if(yearly) { snprintf(FILENAME, CF_BUFSIZE, "%s/yearly.db", LOCATION); ReadAverages(YEARLY); SummarizeAverages(); WriteGraphFiles(YEARLY); WriteHistogram(YEARLY); FindHurstExponents(YEARLY); } printf("Done. Graph files created in directory:\n%s\n", DIRNAME); return 0; } /*****************************************************************************/ void ReadAverages(int dbtype) { int begin_time = 0; int total_time = 0; switch(dbtype) { case DAILY: begin_time = MONDAY_MORNING; total_time = ONE_DAY; break; case YEARLY: begin_time = JANUARY_FIRST; total_time = ONE_YEAR; break; default: /* weekly */ begin_time = MONDAY_MORNING; total_time = ONE_WEEK; break; } printf("\nLooking for database %s\n", FILENAME); printf("\nFinding MAXimum values...\n\n"); if ((errno = db_create(&DBP, NULL, 0)) != 0) { printf("Couldn't create average database %s\n", FILENAME); exit(1); } #ifdef CF_OLD_DB if ((errno = (DBP->open)(DBP, FILENAME, NULL, DB_BTREE, DB_RDONLY, 0644)) != 0) #else if ((errno = (DBP->open)(DBP, NULL, FILENAME, NULL, DB_BTREE, DB_RDONLY, 0644)) != 0) #endif { printf("Couldn't open average database %s\n", FILENAME); DBP->err(DBP, errno, NULL); exit(1); } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); key.data = "STEP"; key.size = strlen("STEP") + 1; if ((errno = DBP->get(DBP, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { DBP->err(DBP, errno, NULL); DBP->close(DBP, 0); return; } } if (value.data != NULL) { STEP = *(int *)(value.data); } else { fprintf(stderr, "Database has no STEP\n"); exit(1); } INTERVAL = 60 * STEP; MAX.expect = 0.01; MAX.var = 0.01; MIN.expect = 9999.0; MIN.var = 9999.0; for (NOW = begin_time; NOW < begin_time + total_time; NOW += INTERVAL) { memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); memset(&ENTRY, 0, sizeof(ENTRY)); strcpy(TIMEKEY, GenTimeKey2(NOW, dbtype)); key.data = TIMEKEY; key.size = strlen(TIMEKEY) + 1; if ((errno = DBP->get(DBP, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { DBP->err(DBP, errno, NULL); exit(1); } } if (value.data != NULL) { memcpy(&ENTRY, value.data, sizeof(ENTRY)); if (fabs(ENTRY.expect) > MAX.expect) { MAX.expect = fabs(ENTRY.expect); } if (fabs(ENTRY.expect) < MIN.expect) { MIN.expect = fabs(ENTRY.expect); } if (fabs(ENTRY.var) > MAX.var) { MAX.var = fabs(ENTRY.var); } } } DBP->close(DBP, 0); } /*****************************************************************************/ void SummarizeAverages() { printf (" x yN (Variable content)\n---------------------------------------------------------\n"); printf(" 1. MAX = %10f - %10f u %10f\n", MIN.expect, MAX.expect, sqrt(MAX.var)); if ((errno = db_create(&DBP, NULL, 0)) != 0) { printf("Couldn't open average database %s\n", FILENAME); exit(1); } #ifdef CF_OLD_DB if ((errno = (DBP->open)(DBP, FILENAME, NULL, DB_BTREE, DB_RDONLY, 0644)) != 0) #else if ((errno = (DBP->open)(DBP, NULL, FILENAME, NULL, DB_BTREE, DB_RDONLY, 0644)) != 0) #endif { printf("Couldn't open average database %s\n", FILENAME); exit(1); } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); key.data = "DATABASE_AGE"; key.size = strlen("DATABASE_AGE") + 1; if ((errno = DBP->get(DBP, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { DBP->err(DBP, errno, NULL); exit(1); } } if (value.data != NULL) { AGE = *(double *)(value.data); printf("\n\nDATABASE_AGE %.4f (weeks), %lf intervals\n\n", AGE / CF_WEEK * INTERVAL, AGE); } } /*****************************************************************************/ void WriteGraphFiles(int dbtype) { int begin_time = 0; int total_time = 0; switch(dbtype) { case DAILY: begin_time = MONDAY_MORNING; total_time = ONE_DAY; break; case YEARLY: begin_time = JANUARY_FIRST; total_time = ONE_YEAR; break; default: /* weekly */ begin_time = MONDAY_MORNING; total_time = ONE_WEEK; break; } if (TIMESTAMPS) { if ((NOW = time((time_t *) NULL)) == -1) { printf("Couldn't read system clock\n"); } switch(dbtype) { case DAILY: sprintf(DIRNAME, "%s/daily-%s", LOCATION, ctime(&NOW)); break; case YEARLY: sprintf(DIRNAME, "%s/yearly-%s", LOCATION, ctime(&NOW)); break; default: /* weekly */ sprintf(DIRNAME, "%s/weekly-%s", LOCATION, ctime(&NOW)); break; } for (sp = DIRNAME; *sp != '\0'; sp++) { if (isspace((int)*sp)) { *sp = '_'; } } } else { switch(dbtype) { case DAILY: sprintf(DIRNAME, "%s/daily-snapshot", LOCATION); break; case YEARLY: sprintf(DIRNAME, "%s/yearly-snapshot", LOCATION); break; default: /* weekly */ sprintf(DIRNAME, "%s/weekly-snapshot", LOCATION); break; } } printf("Creating directory %s\n", DIRNAME); if (mkdir(DIRNAME, 0755) == -1) { perror("mkdir"); printf("Aborting\n"); exit(0); } printf("Writing data to directory %s\n ", DIRNAME); sprintf(FLNAME, "%s/average", DIRNAME); if ((FPAV = fopen(FLNAME, "w")) == NULL) { perror("fopen"); exit(1); } sprintf(FLNAME, "%s/stddev", DIRNAME); if ((FPVAR = fopen(FLNAME, "w")) == NULL) { perror("fopen"); exit(1); } sprintf(FLNAME,"%s/graph", DIRNAME); if ((FP = fopen(FLNAME,"w")) == NULL) { perror("fopen"); exit(1); } if (HIRES) { its = 1; } else { its = 12; } count = 0; NOW = begin_time; memset(&ENTRY, 0, sizeof(ENTRY)); while (NOW < begin_time + total_time) { for (j = 0; j < its; j++) { memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); strcpy(TIMEKEY, GenTimeKey2(NOW, dbtype)); key.data = TIMEKEY; key.size = strlen(TIMEKEY) + 1; if ((errno = DBP->get(DBP, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { DBP->err(DBP, errno, NULL); exit(1); } } if (value.data != NULL) { memcpy(&DET, value.data, sizeof(DET)); ENTRY.expect += DET.expect / (double)its; ENTRY.var += DET.var / (double)its; if (NOSCALING) { MAX.expect = 1; } if (j == its - 1) { fprintf(FPAV, "%d %f\n", count++, ENTRY.expect / MAX.expect); fprintf(FPVAR, "%d %f\n", count, sqrt(ENTRY.var) / MAX.expect); fprintf(FP,"%d %f %f\n",count,ENTRY.expect/MAX.expect,sqrt(ENTRY.var)/MAX.expect); memset(&ENTRY, 0, sizeof(ENTRY)); } } NOW += INTERVAL; } } DBP->close(DBP, 0); fclose(FPAV); fclose(FPVAR); } /*****************************************************************************/ void WriteHistogram(int dbtype) { int numdays=0; int position, day; int weekly[CF_GRAINS]; /* Finally, look at the histogram */ printf("Writing histogram file now!\n"); for (i = 0; i < 24; i++) { for (k = 0; k < CF_GRAINS; k++) { HISTOGRAM[i][k] = 0; } } switch(dbtype) { case DAILY: snprintf(FLNAME, CF_BUFSIZE, "%s/daily.hist", LOCATION); break; case YEARLY: snprintf(FLNAME, CF_BUFSIZE, "%s/yearly.hist", LOCATION); break; default: /* weekly */ snprintf(FLNAME, CF_BUFSIZE, "%s/weekly.hist", LOCATION); break; } if ((FPHIST = fopen(FLNAME, "r")) == NULL) { printf("Unable to load histogram data\n"); return; } for (position = 0; position < CF_GRAINS; position++) { fscanf(FPHIST, "%d ", &position); for (day = 0; day < 24; day++) { fscanf(FPHIST, "%d ", &(HISTOGRAM[day][position])); } weekly[position] = 0; } fclose(FPHIST); switch(dbtype) { case DAILY: numdays = 24; break; case YEARLY: numdays = 12; break; default: /* weekly */ numdays = 7; break; } if (!HIRES) { /* Smooth daily and weekly histograms */ for (k = 1; k < CF_GRAINS - 1; k++) { for (i = 0; i < numdays; i++) { SMOOTHHISTOGRAM[i][k] = ((double) (HISTOGRAM[i][k - 1] + HISTOGRAM[i][k] + HISTOGRAM[i][k + 1])) / 3.0; } } } else { for (k = 0; k < CF_GRAINS; k++) { for (i = 0; i < numdays; i++) { SMOOTHHISTOGRAM[i][k] = (double)HISTOGRAM[i][k]; } } } sprintf(FLNAME, "%s/distr", DIRNAME); if ((FPHIST = fopen(FLNAME, "w")) == NULL) { perror("fopen"); exit(1); } /* Plot daily and weekly histograms */ for (k = 0; k < CF_GRAINS; k++) { int a; for (i = 0; i < numdays; i++) { weekly[k] += (int)(SMOOTHHISTOGRAM[i][k] + 0.5); } fprintf(FPHIST, "%d %d\n", k, weekly[k]); } fclose(FPHIST); printf("Done writing histogram file (%s)\n", FLNAME); } /*****************************************************************************/ void FindHurstExponents(int dbtype) { int delta_t[5], grains[5], i, j; int samples_per_grain[5]; double dilatation, uncertainty; struct Average H[5], M[5], h2; /* Dilatation intervals */ delta_t[0] = INTERVAL * 2; delta_t[1] = 3600; delta_t[2] = 6 * 3600; delta_t[3] = 24 * 3600; delta_t[4] = CF_WEEK; memset(&h2, 0, sizeof(struct Average)); for (i = 0; i < 5; i++) { grains[i] = CF_WEEK / delta_t[i]; samples_per_grain[i] = delta_t[i] / INTERVAL; H[i] = FindHurstFunction(samples_per_grain[i], grains[i], dbtype); } printf ("\n============================================================================\n"); printf("Fluctuation measures - Hurst exponent estimates\n"); printf ("============================================================================\n"); for (i = 1; i < 5; i++) { dilatation = (double)delta_t[i] / (double)delta_t[0]; M[i].expect = log(H[i].expect / H[0].expect) / log(dilatation); printf(" M[%d] = %f\n", i, M[i].expect); h2.expect += M[i].expect * M[i].expect / 4.0; uncertainty = 1.0 / fabs(1.0 / H[i].expect - 1.0 / H[0].expect) * sqrt(MAX.var / log(dilatation)) / (MAX.expect * 2.0); } printf("\n\nESTIMATED RMS HURST EXPONENTS...\n\n"); printf("Hurst exponent = %.1f u %.2f - order of mag\n", sqrt(h2.expect), uncertainty); } /*****************************************************************************/ char *CanonifyName(char *str) { static char buffer[CF_BUFSIZE]; char *sp; memset(buffer, 0, CF_BUFSIZE); strcpy(buffer, str); for (sp = buffer; *sp != '\0'; sp++) { if (!isalnum((int)*sp) || *sp == '.') { *sp = '_'; } } return buffer; } /*********************************************************************/ struct Average FindHurstFunction(int samples_per_grain, int grains, int dbtype) /* Find the average of (max-min) over all intervals of width delta_t */ { static struct Average lmin, lmax, av; int control = 0; int begin_time = 0; int total_time = 0; switch(dbtype) { case DAILY: begin_time = MONDAY_MORNING; total_time = ONE_DAY; break; case YEARLY: begin_time = JANUARY_FIRST; total_time = ONE_YEAR; break; default: /* weekly */ begin_time = MONDAY_MORNING; total_time = ONE_WEEK; break; } if ((errno = db_create(&DBP, NULL, 0)) != 0) { printf("Couldn't create average database %s\n", FILENAME); exit(1); } #ifdef CF_OLD_DB if ((errno = (DBP->open)(DBP, FILENAME, NULL, DB_BTREE, DB_RDONLY, 0644)) != 0) #else if ((errno = (DBP->open)(DBP, NULL, FILENAME, NULL, DB_BTREE, DB_RDONLY, 0644)) != 0) #endif { printf("Couldn't open average database %s\n", FILENAME); DBP->err(DBP, errno, NULL); exit(1); } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); memset(&av, 0, sizeof(av)); lmax.expect = 0.01; lmin.expect = 9999.0; count = 0; for (NOW = begin_time; NOW < begin_time + total_time; NOW += INTERVAL) { memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); memset(&ENTRY, 0, sizeof(ENTRY)); strcpy(TIMEKEY, GenTimeKey2(NOW, dbtype)); key.data = TIMEKEY; key.size = strlen(TIMEKEY) + 1; if ((errno = DBP->get(DBP, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { DBP->err(DBP, errno, NULL); exit(1); } } count++; if (value.data != NULL) { memcpy(&ENTRY, value.data, sizeof(ENTRY)); if (false) /* This conformal scaling has no effect on the Hurst * parameter expect div by zero errors! */ { ENTRY.expect = ENTRY.expect / sqrt(ENTRY.var); } if (fabs(ENTRY.expect) > lmax.expect) { lmax.expect = fabs(ENTRY.expect); } if (fabs(ENTRY.expect) < lmin.expect) { lmin.expect = fabs(ENTRY.expect); } } /* For each grain, find the difference of the max and min values for * final average */ if (count == samples_per_grain) { count = 0; control += samples_per_grain; /* av += lmax - lmin; */ av.expect += (lmax.expect - lmin.expect) / (double)grains; lmax.expect = 0.01; lmin.expect = 9999.0; } } printf("Scanned %d grains of size %d for Hurst function\n", control, samples_per_grain); DBP->close(DBP, 0); return (av); } /*****************************************************************************/ void Syntax() { int i; printf("Syntax:\n\n"); printf("%s name", PROG_NAME); for (i = 0; GRAPHOPTIONS[i].name != NULL; i++) { printf(" (--%s|-%c)", GRAPHOPTIONS[i].name, (char)GRAPHOPTIONS[i].val); } printf("\n"); } /*********************************************************************/ char *GenTimeKey2(time_t now, int dbtype) { char str[64]; sprintf(str, "%s", ctime(&now)); return ConvTimeKey2(str, dbtype); } /*********************************************************************/ char *ConvTimeKey2(char *str, int dbtype) { int i, hr, min, timeinmins; char buf1[10], buf2[10], buf3[10], buf4[10], buf5[10], buf[10], out[10]; char minbuf[10]; char *timekey; timekey = calloc(64, sizeof(char)); sscanf(str, "%s %s %s %s %s", buf1, buf2, buf3, buf4, buf5); timekey[0] = '\0'; /* Day */ switch(dbtype) { case DAILY: break; case YEARLY: sprintf(timekey, "%s%s:", buf2, buf3); break; default: /* weekly */ sprintf(timekey, "%s:", buf1); break; } /* Hours */ sscanf(buf4, "%d:%d", &hr, &min); timeinmins = 60*hr + min; if(STEP == 1) sprintf(minbuf, "%04d", timeinmins / STEP ); else if (STEP < 15) sprintf(minbuf, "%03d", timeinmins / STEP ); else if (STEP < 145) sprintf(minbuf, "%02d", timeinmins / STEP ); else sprintf(minbuf, "%d", timeinmins / STEP ); strcat(timekey, minbuf); return timekey; } /*********************************************************************/ cfengine-2.2.10/src/client.c0000644000175000001440000005362410573557733012531 00000000000000/* Copyright (C) 1995- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo University College, 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, 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 */ /*******************************************************************/ /* */ /* File Image copying */ /* */ /* client part for remote copying */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ /* Level 1 */ /*********************************************************************/ int OpenServerConnection(struct Image *ip) { char server[CF_EXPANDSIZE]; if (strcmp(ip->server,"localhost") == 0) { AUTHENTICATED = true; return true; } AUTHENTICATED = false; ExpandVarstring(ip->server,server,NULL); if (CONN->sd == CF_NOT_CONNECTED) { Debug("Opening server connnection to %s\n",server); if (!RemoteConnect(server,ip->forceipv4,SHORT_CFENGINEPORT,STR_CFENGINEPORT)) { CfLog(cfinform,"Couldn't open a socket","socket"); if (CONN->sd != CF_NOT_CONNECTED) { CloseServerConnection(); } AUTHENTICATED = false; return false; } Debug("Remote IP set to %s\n",CONN->remoteip); if (!IdentifyForVerification(CONN->sd,CONN->localip,CONN->family)) { snprintf(OUTPUT,CF_BUFSIZE,"Id-authentication for %s failed\n",VFQNAME); CfLog(cferror,OUTPUT,""); errno = EPERM; CloseServerConnection(); AUTHENTICATED = false; return false; } if (ip->compat == 'y') { CfLog(cfinform,"WARNING: the connection to %s is not offering key authentication\n",""); CfLog(cfinform,"WARNING: oldserver=true is a TEMPORARY measure only\n",""); } else if (!KeyAuthentication(ip)) { snprintf(OUTPUT,CF_BUFSIZE,"Authentication dialogue with %s failed\n",server); CfLog(cferror,OUTPUT,""); errno = EPERM; CloseServerConnection(); AUTHENTICATED = false; return false; } /*CheckRemoteVersion();*/ AUTHENTICATED = true; return true; } else { Debug("Server connection to %s already open on %d\n",server,CONN->sd); } AUTHENTICATED = true; /*CheckRemoteVersion();*/ return true; } /*********************************************************************/ void CloseServerConnection() { Debug("Closing current connection\n"); close(CONN->sd); CONN->sd = CF_NOT_CONNECTED; if (CONN->session_key != NULL) { free(CONN->session_key); CONN->session_key = NULL; } } /*********************************************************************/ int cf_rstat(char *file,struct stat *buf,struct Image *ip,char *stattype) /* If a link, this reads readlink and sends it back in the same package. It then caches the value for each copy command */ { char sendbuffer[CF_BUFSIZE]; char recvbuffer[CF_BUFSIZE]; char in[CF_BUFSIZE],out[CF_BUFSIZE]; struct cfstat cfst; int ret,tosend,cipherlen; time_t tloc; Debug("cf_rstat(%s,%s)\n",file,stattype); memset(recvbuffer,0,CF_BUFSIZE); if (strlen(file) > CF_BUFSIZE-30) { CfLog(cferror,"Filename too long",""); return -1; } ret = GetCachedStatData(file,buf,ip,stattype); if (ret != 0) { return ret; } if ((tloc = time((time_t *)NULL)) == -1) { CfLog(cferror,"Couldn't read system clock\n",""); } sendbuffer[0] = '\0'; if (ip->encrypt == 'y') { if (CONN->session_key == NULL) { CfLog(cferror,"Cannot do encrypted copy without keys (use cfkey)",""); return -1; } snprintf(in,CF_BUFSIZE-1,"SYNCH %d STAT %s",tloc,file); cipherlen = EncryptString(in,out,CONN->session_key,strlen(in)+1); snprintf(sendbuffer,CF_BUFSIZE-1,"SSYNCH %d",cipherlen); memcpy(sendbuffer+CF_PROTO_OFFSET,out,cipherlen); tosend = cipherlen+CF_PROTO_OFFSET; } else { snprintf(sendbuffer,CF_BUFSIZE,"SYNCH %d STAT %s",tloc,file); tosend = strlen(sendbuffer); } if (SendTransaction(CONN->sd,sendbuffer,tosend,CF_DONE) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Transmission failed/refused talking to %.255s:%.255s in stat",ip->server,file); CfLog(cfinform,OUTPUT,"send"); return -1; } if (ReceiveTransaction(CONN->sd,recvbuffer,NULL) == -1) { return -1; } if (strstr(recvbuffer,"unsynchronized")) { CfLog(cferror,"Clocks differ too much to do copy by date (security)",""); CfLog(cferror,recvbuffer+4,""); return -1; } if (BadProtoReply(recvbuffer)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Server returned error: %s\n",recvbuffer+4); CfLog(cfverbose,OUTPUT,""); errno = EPERM; return -1; } if (OKProtoReply(recvbuffer)) { long d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12=0,d13=0; sscanf(recvbuffer,"OK: %1ld %5ld %14ld %14ld %14ld %14ld %14ld %14ld %14ld %14ld %14ld %14ld %14ld", &d1,&d2,&d3,&d4,&d5,&d6,&d7,&d8,&d9,&d10,&d11,&d12,&d13); cfst.cf_type = (enum cf_filetype) d1; cfst.cf_mode = (mode_t) d2; cfst.cf_lmode = (mode_t) d3; cfst.cf_uid = (uid_t) d4; cfst.cf_gid = (gid_t) d5; cfst.cf_size = (off_t) d6; cfst.cf_atime = (time_t) d7; cfst.cf_mtime = (time_t) d8; cfst.cf_ctime = (time_t) d9; cfst.cf_makeholes = (char) d10; ip->makeholes = (char) d10; cfst.cf_ino = d11; cfst.cf_nlink = d12; cfst.cf_dev = d13; /* Use %?d here to avoid memory overflow attacks */ Debug("Mode = %d,%d\n",d2,d3); Debug("OK: type=%d\n mode=%o\n lmode=%o\n uid=%d\n gid=%d\n size=%ld\n atime=%d\n mtime=%d ino=%d nlnk=%d, dev=%d\n", cfst.cf_type,cfst.cf_mode,cfst.cf_lmode,cfst.cf_uid,cfst.cf_gid,(long)cfst.cf_size, cfst.cf_atime,cfst.cf_mtime,cfst.cf_ino,cfst.cf_nlink,cfst.cf_dev); memset(recvbuffer,0,CF_BUFSIZE); if (ReceiveTransaction(CONN->sd,recvbuffer,NULL) == -1) { return -1; } Debug("Linkbuffer: %s\n",recvbuffer); if (strlen(recvbuffer) > 3) { cfst.cf_readlink = strdup(recvbuffer+3); } else { cfst.cf_readlink = NULL; } switch (cfst.cf_type) { case cf_reg: cfst.cf_mode |= (mode_t) S_IFREG; break; case cf_dir: cfst.cf_mode |= (mode_t) S_IFDIR; break; case cf_char: cfst.cf_mode |= (mode_t) S_IFCHR; break; case cf_fifo: cfst.cf_mode |= (mode_t) S_IFIFO; break; case cf_sock: cfst.cf_mode |= (mode_t) S_IFSOCK; break; case cf_block: cfst.cf_mode |= (mode_t) S_IFBLK; break; case cf_link: cfst.cf_mode |= (mode_t) S_IFLNK; break; } cfst.cf_filename = strdup(file); cfst.cf_server = strdup(ip->server); if ((cfst.cf_filename == NULL) ||(cfst.cf_server) == NULL) { FatalError("Memory allocation in cf_rstat"); } cfst.cf_failed = false; if (cfst.cf_lmode != 0) { cfst.cf_lmode |= (mode_t) S_IFLNK; } CacheData(&cfst,ip); if ((cfst.cf_lmode != 0) && (strcmp(stattype,"link") == 0)) { buf->st_mode = cfst.cf_lmode; } else { buf->st_mode = cfst.cf_mode; } buf->st_uid = cfst.cf_uid; buf->st_gid = cfst.cf_gid; buf->st_size = cfst.cf_size; buf->st_mtime = cfst.cf_mtime; buf->st_ctime = cfst.cf_ctime; buf->st_atime = cfst.cf_atime; buf->st_ino = cfst.cf_ino; buf->st_dev = cfst.cf_dev; buf->st_nlink = cfst.cf_nlink; return 0; } snprintf(OUTPUT,CF_BUFSIZE*2,"Transmission refused or failed statting %s\nGot: %s\n",file,recvbuffer); CfLog(cferror,OUTPUT,""); errno = EPERM; return -1; } /*********************************************************************/ CFDIR *cf_ropendir(char *dirname,struct Image *ip) { char sendbuffer[CF_BUFSIZE]; char recvbuffer[CF_BUFSIZE]; char in[CF_BUFSIZE]; char out[CF_BUFSIZE]; int n, done=false, cipherlen = 0,plainlen = 0,tosend; CFDIR *cfdirh; char *sp; Debug("CfOpenDir(%s:%s)\n",ip->server,dirname); if (strlen(dirname) > CF_BUFSIZE - 20) { CfLog(cferror,"Directory name too long",""); return NULL; } if ((cfdirh = (CFDIR *)malloc(sizeof(CFDIR))) == NULL) { CfLog(cferror,"Couldn't allocate memory in cf_ropendir\n",""); exit(1); } cfdirh->cf_list = NULL; cfdirh->cf_listpos = NULL; cfdirh->cf_dirh = NULL; if ((ip->encrypt == 'y') && FULLENCRYPT) { if (CONN->session_key == NULL) { CfLog(cferror,"Cannot do encrypted copy without keys (use cfkey)",""); return NULL; } snprintf(in,CF_BUFSIZE,"OPENDIR %s",dirname); cipherlen = EncryptString(in,out,CONN->session_key,strlen(in)+1); snprintf(sendbuffer,CF_BUFSIZE-1,"SOPENDIR %d",cipherlen); memcpy(sendbuffer+CF_PROTO_OFFSET,out,cipherlen); tosend = cipherlen+CF_PROTO_OFFSET; } else { snprintf(sendbuffer,CF_BUFSIZE,"OPENDIR %s",dirname); tosend = strlen(sendbuffer); } if (SendTransaction(CONN->sd,sendbuffer,tosend,CF_DONE) == -1) { free((char *)cfdirh); return NULL; } while (!done) { if ((n = ReceiveTransaction(CONN->sd,recvbuffer,NULL)) == -1) { if (errno == EINTR) { continue; } free((char *)cfdirh); return NULL; } if (n == 0) { break; } if (ip->encrypt == 'y' && FULLENCRYPT) { memcpy(in,recvbuffer,n); plainlen = DecryptString(in,recvbuffer,CONN->session_key,n); } if (FailedProtoReply(recvbuffer)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Network access to %s:%s denied\n",ip->server,dirname); CfLog(cfinform,OUTPUT,""); free((char *)cfdirh); return NULL; } if (BadProtoReply(recvbuffer)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s\n",recvbuffer+4); CfLog(cfinform,OUTPUT,""); free((char *)cfdirh); return NULL; } for (sp = recvbuffer; *sp != '\0'; sp++) { if (strncmp(sp,CFD_TERMINATOR,strlen(CFD_TERMINATOR)) == 0) /* End transmission */ { cfdirh->cf_listpos = cfdirh->cf_list; return cfdirh; } AppendItem(&(cfdirh->cf_list),sp,NULL); while(*sp != '\0') { sp++; } } } cfdirh->cf_listpos = cfdirh->cf_list; return cfdirh; } /*********************************************************************/ void FlushClientCache(struct Image *ip) { if (ip->cache) { free(ip->cache); ip->cache = NULL; } } /*********************************************************************/ int CompareMD5Net(char *file1,char *file2,struct Image *ip) { static unsigned char d[CF_MD5_LEN]; char *sp,sendbuffer[CF_BUFSIZE],recvbuffer[CF_BUFSIZE],in[CF_BUFSIZE],out[CF_BUFSIZE]; int i,tosend,cipherlen; ChecksumFile(file2,d,'m'); /* send md5 to the server for comparison */ Debug("Send digest of %s to server, %s\n",file2,ChecksumPrint('m',d)); memset(recvbuffer,0,CF_BUFSIZE); if (ip->encrypt == 'y') { snprintf(in,CF_BUFSIZE,"MD5 %s",file1); sp = in + strlen(in) + CF_SMALL_OFFSET; for (i = 0; i < CF_MD5_LEN; i++) { *sp++ = d[i]; } cipherlen = EncryptString(in,out,CONN->session_key,strlen(in)+CF_SMALL_OFFSET+CF_MD5_LEN); snprintf(sendbuffer,CF_BUFSIZE,"SMD5 %d",cipherlen); memcpy(sendbuffer+CF_PROTO_OFFSET,out,cipherlen); tosend = cipherlen + CF_PROTO_OFFSET; } else { snprintf(sendbuffer,CF_BUFSIZE,"MD5 %s",file1); sp = sendbuffer + strlen(sendbuffer) + CF_SMALL_OFFSET; for (i = 0; i < CF_MD5_LEN; i++) { *sp++ = d[i]; } tosend = strlen(sendbuffer)+CF_SMALL_OFFSET+CF_MD5_LEN; } if (SendTransaction(CONN->sd,sendbuffer,tosend,CF_DONE) == -1) { CfLog(cferror,"","send"); return false; } if (ReceiveTransaction(CONN->sd,recvbuffer,NULL) == -1) { Verbose("No answer from host, assuming checksum ok to avoid remote copy for now...\n"); return false; } if (strcmp(CFD_TRUE,recvbuffer) == 0) { Debug("MD5 mismatch: (reply - %s)\n",recvbuffer); return true; /* mismatch */ } else { Debug("MD5 matched ok: (reply - %s)\n",recvbuffer); return false; } /* Not reached */ } /*********************************************************************/ int CopyRegNet(char *source,char *new,struct Image *ip,off_t size) { int dd, buf_size,n_read = 0,toget,towrite,plainlen,more = true; int last_write_made_hole = 0, done = false,tosend,cipherlen=0,value; char *buf,in[CF_BUFSIZE],out[CF_BUFSIZE],sendbuffer[CF_BUFSIZE],cfchangedstr[265]; unsigned char iv[] = {1,2,3,4,5,6,7,8}; long n_read_total = 0; EVP_CIPHER_CTX ctx; snprintf(cfchangedstr,255,"%s%s",CF_CHANGEDSTR1,CF_CHANGEDSTR2); EVP_CIPHER_CTX_init(&ctx); if ((strlen(new) > CF_BUFSIZE-20)) { CfLog(cferror,"Filename too long",""); return false; } unlink(new); /* To avoid link attacks */ if ((dd = open(new,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0600)) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Copy %s:%s security - failed attempt to exploit a race? (Not copied)\n",ip->server,new); CfLog(cferror,OUTPUT,"open"); unlink(new); return false; } sendbuffer[0] = '\0'; buf_size = ST_BLKSIZE(dstat); if (buf_size < 2048) { buf_size = 2048; } if (ip->encrypt == 'y') { snprintf(in,CF_BUFSIZE-CF_PROTO_OFFSET,"GET dummykey %s",source); cipherlen = EncryptString(in,out,CONN->session_key,strlen(in)+1); snprintf(sendbuffer,CF_BUFSIZE,"SGET %4d %4d",cipherlen,buf_size); memcpy(sendbuffer+CF_PROTO_OFFSET,out,cipherlen); tosend=cipherlen+CF_PROTO_OFFSET; EVP_DecryptInit(&ctx,EVP_bf_cbc(),CONN->session_key,iv); } else { snprintf(sendbuffer,CF_BUFSIZE,"GET %d %s",buf_size,source); tosend=strlen(sendbuffer); } if (SendTransaction(CONN->sd,sendbuffer,tosend,CF_DONE) == -1) { CfLog(cferror,"Couldn't send","send"); close(dd); return false; } buf = (char *) malloc(CF_BUFSIZE + sizeof(int)); /* Note CF_BUFSIZE not buf_size !! */ n_read_total = 0; while (!done) { cipherlen = 0; if ((size - n_read_total)/buf_size > 0) { toget = towrite = buf_size; } else if (size != 0) { towrite = (size - n_read_total); if (ip->compat == 'y') { toget = buf_size; } else { toget = towrite; } } else { toget = towrite = 0; } if (ip->encrypt == 'y') { if (more) { if ((cipherlen = ReceiveTransaction(CONN->sd,buf,&more)) == -1) { return false; } } else { break; /* Already written last encrypted buffer */ } } else { if ((n_read = RecvSocketStream(CONN->sd,buf,toget,0)) == -1) { if (errno == EINTR) { continue; } CfLog(cferror,"Error in socket stream","recv"); close(dd); free(buf); return false; } } /* If the first thing we get is an error message, break. */ if (n_read_total == 0 && strncmp(buf,CF_FAILEDSTR,strlen(CF_FAILEDSTR)) == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Network access to %s:%s denied\n",ip->server,source); if (ip->encrypt != 'y') { RecvSocketStream(CONN->sd,buf,buf_size-n_read,0); /* flush rest of transaction */ } CfLog(cfinform,OUTPUT,""); close(dd); free(buf); return false; } if (strncmp(buf,cfchangedstr,strlen(cfchangedstr)) == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s:%s changed while copying\n",ip->server,source); RecvSocketStream(CONN->sd,buf,buf_size-n_read,0); /* flush rest of transaction */ CfLog(cfinform,OUTPUT,""); close(dd); free(buf); return false; } value = -1; /* Check for mismatch between encryption here and on server - can lead to misunderstanding*/ sscanf(buf,"t %d",&value); if ((value > 0) && strncmp(buf+CF_INBAND_OFFSET,"BAD: ",5) == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Network access to cleartext %s:%s denied\n",ip->server,source); CfLog(cfinform,OUTPUT,""); close(dd); free(buf); return false; } if (ip->encrypt == 'y') { if (!EVP_DecryptUpdate(&ctx,(unsigned char *)sendbuffer,&plainlen,(unsigned char*)buf,cipherlen)) { Debug("Decryption failed\n"); return false; } memcpy(buf,sendbuffer,plainlen); n_read = towrite = plainlen; } if (ip->encrypt != 'y') { if (n_read == 0) { break; } if (n_read == size) { if (n_read_total == 0 && strncmp(buf,CF_FAILEDSTR,size) == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Network access to %s:%s denied\n",ip->server,source); CfLog(cfinform,OUTPUT,""); close(dd); free(buf); return false; } } } /* if (n_read < toget) { snprintf(OUTPUT,CF_BUFSIZE*2,"Network error getting %s:%s\n",ip->server,source); CfLog(cfinform,OUTPUT,""); close(dd); free(buf); return false; } */ n_read_total += towrite; /* n_read; */ if (ip->encrypt == 'n') { if (n_read_total >= (long)size) /* Handle EOF without closing socket */ { done = true; } } if (!EmbeddedWrite(new,dd,buf,ip,towrite,&last_write_made_hole,n_read)) { snprintf(OUTPUT,CF_BUFSIZE,"Local disk write failed copying %s:%s to %s\n",ip->server,source,new); CfLog(cferror,OUTPUT,""); free(buf); unlink(new); close(dd); FlushToEnd(CONN->sd,size - n_read_total); EVP_CIPHER_CTX_cleanup(&ctx); return false; } } if (ip->encrypt == 'y') /* final crypto cleanup */ { if (!EVP_DecryptFinal(&ctx,buf,&plainlen)) { Debug("Final decrypt failed\n"); return false; } if (!EmbeddedWrite(new,dd,buf,ip,plainlen,&last_write_made_hole,n_read)) { snprintf(OUTPUT,CF_BUFSIZE,"Local disk write failed copying %s:%s to %s\n",ip->server,source,new); CfLog(cferror,OUTPUT,""); free(buf); unlink(new); close(dd); FlushToEnd(CONN->sd,size - n_read_total); EVP_CIPHER_CTX_cleanup(&ctx); return false; } } /* If the file ends with a `hole', something needs to be written at the end. Otherwise the kernel would truncate the file at the end of the last write operation. Write a null character and truncate it again. */ if (last_write_made_hole) { if (cf_full_write (dd,"",1) < 0 || ftruncate (dd,n_read_total) < 0) { CfLog(cferror,"cfengine: full_write or ftruncate error in CopyReg\n",""); free(buf); unlink(new); close(dd); FlushToEnd(CONN->sd,size - n_read_total); EVP_CIPHER_CTX_cleanup(&ctx); return false; } } Debug("End of CopyNetReg\n"); close(dd); free(buf); EVP_CIPHER_CTX_cleanup(&ctx); return true; } /*********************************************************************/ /* Level 2 */ /*********************************************************************/ int GetCachedStatData(char *file,struct stat *statbuf,struct Image *ip,char *stattype) { struct cfstat *sp; Debug("GetCachedStatData(%s)\n",file); for (sp = ip->cache; sp != NULL; sp=sp->next) { if ((strcmp(ip->server,sp->cf_server) == 0) && (strcmp(file,sp->cf_filename) == 0)) { if (sp->cf_failed) /* cached failure from cfopendir */ { errno = EPERM; Debug("Cached failure to stat\n"); return -1; } if ((strcmp(stattype,"link") == 0) && (sp->cf_lmode != 0)) { statbuf->st_mode = sp->cf_lmode; } else { statbuf->st_mode = sp->cf_mode; } statbuf->st_uid = sp->cf_uid; statbuf->st_gid = sp->cf_gid; statbuf->st_size = sp->cf_size; statbuf->st_atime = sp->cf_atime; statbuf->st_mtime = sp->cf_mtime; statbuf->st_ctime = sp->cf_ctime; statbuf->st_ino = sp->cf_ino; statbuf->st_nlink = sp->cf_nlink; Debug("Found in cache\n"); return true; } } Debug("Did not find in cache\n"); return false; } /*********************************************************************/ void CacheData(struct cfstat *data,struct Image *ip) { struct cfstat *sp; if ((sp = (struct cfstat *) malloc(sizeof(struct cfstat))) == NULL) { CfLog(cferror,"Memory allocation faliure in CacheData()\n",""); return; } memcpy(sp,data,sizeof(struct cfstat)); sp->next = ip->cache; ip->cache = sp; } /*********************************************************************/ void FlushToEnd(int sd,int toget) { int i; char buffer[2]; snprintf(OUTPUT,CF_BUFSIZE*2,"Flushing rest of file...%d bytes\n",toget); CfLog(cfinform,OUTPUT,""); for (i = 0; i < toget; i++) { recv(sd,buffer,1,0); /* flush to end of current file */ } } cfengine-2.2.10/src/popen.c0000644000175000001440000004274711144464130012357 00000000000000 /* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: popen.c */ /* */ /* Created: Tue Dec 2 02:14:16 1997 */ /* */ /* popen replacement for POSIX 2 avoiding shell piggyback */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" # if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) extern pthread_attr_t PTHREADDEFAULTS; extern pthread_mutex_t MUTEX_COUNT; extern pthread_mutex_t MUTEX_HOSTNAME; # endif pid_t *CHILD; int MAXFD = 20; /* Max number of simultaneous pipes */ /*****************************************************************************/ FILE *cfpopen(char *command,char *type) { static char arg[CF_MAXSHELLARGS][CF_BUFSIZE]; int i, argc, pd[2]; char **argv; pid_t pid; FILE *pp = NULL; Debug("cfpopen(%s)\n",command); if ((*type != 'r' && *type != 'w') || (type[1] != '\0')) { errno = EINVAL; return NULL; } #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_unlock"); return NULL; } #endif if (CHILD == NULL) /* first time */ { if ((CHILD = calloc(MAXFD,sizeof(pid_t))) == NULL) { #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) pthread_mutex_unlock(&MUTEX_COUNT); #endif return NULL; } } #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","pthread_mutex_unlock"); return NULL; } #endif if (pipe(pd) < 0) /* Create a pair of descriptors to this process */ { return NULL; } if ((pid = fork()) == -1) { return NULL; } signal(SIGCHLD,SIG_DFL); ALARM_PID = (pid != 0 ? pid : -1); if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1],1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1],2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0],0); close(pd[0]); } } for (i = 0; i < MAXFD; i++) { if (CHILD[i] > 0) { close(i); } } argc = SplitCommand(command,arg); argv = (char **) malloc((argc+1)*sizeof(char *)); if (argv == NULL) { FatalError("Out of memory"); } for (i = 0; i < argc; i++) { argv[i] = arg[i]; } argv[i] = (char *) NULL; if (execv(arg[0],argv) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't run %s",arg[0]); CfLog(cferror,OUTPUT,"execv"); } free((char *)argv); _exit(1); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0],type)) == NULL) { /* Don't leave zombies. */ cfpwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1],type)) == NULL) { /* Don't leave zombies. */ cfpwait(pid); return NULL; } } if (fileno(pp) >= MAXFD) { snprintf(OUTPUT,CF_BUFSIZE,"File descriptor %d of child %d higher than MAXFD, check for defunct children", fileno(pp), pid); CfLog(cferror,OUTPUT,""); } else { CHILD[fileno(pp)] = pid; } return pp; } return NULL; /* Cannot reach here */ } /*****************************************************************************/ FILE *cfpopensetuid(char *command,char *type,uid_t uid,gid_t gid,char *chdirv,char *chrootv) { static char arg[CF_MAXSHELLARGS][CF_BUFSIZE]; int i, argc, pd[2]; char **argv; pid_t pid; FILE *pp = NULL; Debug("cfpopensetuid(%s,%s,%d,%d)\n",command,type,uid,gid); if ((*type != 'r' && *type != 'w') || (type[1] != '\0')) { errno = EINVAL; return NULL; } if (CHILD == NULL) /* first time */ { if ((CHILD = calloc(MAXFD,sizeof(pid_t))) == NULL) { return NULL; } } if (pipe(pd) < 0) /* Create a pair of descriptors to this process */ { return NULL; } if ((pid = fork()) == -1) { return NULL; } ALARM_PID = (pid != 0 ? pid : -1); if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1],1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1],2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0],0); close(pd[0]); } } for (i = 0; i < MAXFD; i++) { if (CHILD[i] > 0) { close(i); } } argc = SplitCommand(command,arg); argv = (char **) malloc((argc+1)*sizeof(char *)); if (argv == NULL) { FatalError("Out of memory"); } for (i = 0; i < argc; i++) { argv[i] = arg[i]; } argv[i] = (char *) NULL; if (chrootv && strlen(chrootv) != 0) { if (chroot(chrootv) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't chroot to %s\n",chrootv); CfLog(cferror,OUTPUT,"chroot"); free((char *)argv); return NULL; } } if (chdirv && strlen(chdirv) != 0) { if (chdir(chdirv) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't chdir to %s\n",chdirv); CfLog(cferror,OUTPUT,"chdir"); free((char *)argv); return NULL; } } if (!CfSetUid(uid,gid)) { free((char *)argv); _exit(1); } if (execv(arg[0],argv) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't run %s",arg[0]); CfLog(cferror,OUTPUT,"execv"); } free((char *)argv); _exit(1); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0],type)) == NULL) { /* Don't leave zombies. */ cfpwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1],type)) == NULL) { /* Don't leave zombies. */ cfpwait(pid); return NULL; } } if (fileno(pp) >= MAXFD) { snprintf(OUTPUT,CF_BUFSIZE,"File descriptor %d of child %d higher than MAXFD, check for defunct children", fileno(pp), pid); CfLog(cferror,OUTPUT,""); } else { CHILD[fileno(pp)] = pid; } return pp; } return NULL; /* cannot reach here */ } /*****************************************************************************/ /* Shell versions of commands - not recommended for security reasons */ /*****************************************************************************/ FILE *cfpopen_sh(char *command,char *type) { int i,pd[2]; pid_t pid; FILE *pp = NULL; Debug("cfpopen(%s)\n",command); if ((*type != 'r' && *type != 'w') || (type[1] != '\0')) { errno = EINVAL; return NULL; } if (CHILD == NULL) /* first time */ { if ((CHILD = calloc(MAXFD,sizeof(pid_t))) == NULL) { return NULL; } } if (pipe(pd) < 0) /* Create a pair of descriptors to this process */ { return NULL; } if ((pid = fork()) == -1) { return NULL; } ALARM_PID = (pid != 0 ? pid : -1); if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1],1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1],2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0],0); close(pd[0]); } } for (i = 0; i < MAXFD; i++) { if (CHILD[i] > 0) { close(i); } } execl("/bin/sh","sh","-c",command,NULL); _exit(1); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0],type)) == NULL) { /* Don't leave zombies. */ cfpwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1],type)) == NULL) { /* Don't leave zombies. */ cfpwait(pid); return NULL; } } if (fileno(pp) >= MAXFD) { snprintf(OUTPUT,CF_BUFSIZE,"File descriptor %d of child %d higher than MAXFD, check for defunct children", fileno(pp), pid); CfLog(cferror,OUTPUT,""); } else { CHILD[fileno(pp)] = pid; } return pp; } return NULL; } /******************************************************************************/ FILE *cfpopen_shsetuid(char *command,char *type,uid_t uid,gid_t gid,char *chdirv,char *chrootv) { int i,pd[2]; pid_t pid; FILE *pp = NULL; Debug("cfpopen_shsetuid(%s,%s,%d,%d)\n",command,type,uid,gid); if ((*type != 'r' && *type != 'w') || (type[1] != '\0')) { errno = EINVAL; return NULL; } if (CHILD == NULL) /* first time */ { if ((CHILD = calloc(MAXFD,sizeof(pid_t))) == NULL) { return NULL; } } if (pipe(pd) < 0) /* Create a pair of descriptors to this process */ { return NULL; } if ((pid = fork()) == -1) { return NULL; } ALARM_PID = (pid != 0 ? pid : -1); if (pid == 0) { switch (*type) { case 'r': close(pd[0]); /* Don't need output from parent */ if (pd[1] != 1) { dup2(pd[1],1); /* Attach pp=pd[1] to our stdout */ dup2(pd[1],2); /* Merge stdout/stderr */ close(pd[1]); } break; case 'w': close(pd[1]); if (pd[0] != 0) { dup2(pd[0],0); close(pd[0]); } } for (i = 0; i < MAXFD; i++) { if (CHILD[i] > 0) { close(i); } } if (chrootv && strlen(chrootv) != 0) { if (chroot(chrootv) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't chroot to %s\n",chrootv); CfLog(cferror,OUTPUT,"chroot"); return NULL; } } if (chdirv && strlen(chdirv) != 0) { if (chdir(chdirv) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't chdir to %s\n",chdirv); CfLog(cferror,OUTPUT,"chroot"); return NULL; } } if (!CfSetUid(uid,gid)) { _exit(1); } execl("/bin/sh","sh","-c",command,NULL); _exit(1); } else { switch (*type) { case 'r': close(pd[1]); if ((pp = fdopen(pd[0],type)) == NULL) { /* Don't leave zombies. */ cfpwait(pid); return NULL; } break; case 'w': close(pd[0]); if ((pp = fdopen(pd[1],type)) == NULL) { /* Don't leave zombies. */ cfpwait(pid); return NULL; } } if (fileno(pp) >= MAXFD) { snprintf(OUTPUT,CF_BUFSIZE,"File descriptor %d of child %d higher than MAXFD, check for defunct children", fileno(pp), pid); CfLog(cferror,OUTPUT,""); /* Don't leave zombies. */ cfpwait(pid); return NULL; } else { CHILD[fileno(pp)] = pid; } return pp; } return NULL; } /******************************************************************************/ /* Close commands */ /******************************************************************************/ int cfpwait(pid_t pid) { int status, wait_result; Debug("cfpwait - Waiting for process %d\n",pid); #ifdef HAVE_WAITPID while(waitpid(pid,&status,0) < 0) { if (errno != EINTR) { return -1; } } return status; #else while ((wait_result = wait(&status)) != pid) { if (wait_result <= 0) { snprintf(OUTPUT,CF_BUFSIZE,"Wait for child failed\n"); CfLog(cfinform,OUTPUT,"wait"); return -1; } } if (WIFSIGNALED(status)) { return -1; } if (! WIFEXITED(status)) { return -1; } return (WEXITSTATUS(status)); #endif } /*******************************************************************/ int cfpclose(FILE *pp) { int fd; pid_t pid; Debug("cfpclose(pp)\n"); if (CHILD == NULL) /* popen hasn't been called */ { return -1; } ALARM_PID = -1; fd = fileno(pp); if (fd >= MAXFD) { snprintf(OUTPUT,CF_BUFSIZE,"File descriptor %d of child higher than " "MAXFD, check for defunct children", fd); CfLog(cferror,OUTPUT,""); /* We can't wait for the specific pid as it isn't stored in CHILD. */ pid = -1; } else { if ((pid = CHILD[fd]) == 0) { return -1; } CHILD[fd] = 0; } if (fclose(pp) == EOF) { return -1; } return cfpwait(pid); } /*******************************************************************/ int CfSetUid(uid_t uid,gid_t gid) { struct passwd *pw; if (gid != (gid_t) -1) { Verbose("Changing gid to %d\n",gid); if (setgid(gid) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't set gid to %d\n",gid); CfLog(cferror,OUTPUT,"setgid"); return false; } /* Now eliminate any residual privileged groups */ if ((pw = getpwuid(uid)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to get login groups when dropping privilege to %d",uid); CfLog(cferror,OUTPUT,"initgroups"); return false; } if (initgroups(pw->pw_name, pw->pw_gid) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to set login groups when dropping privilege to %s=%d",pw->pw_name,uid); CfLog(cferror,OUTPUT,"initgroups"); return false; } } if (uid != (uid_t) -1) { Verbose("Changing uid to %d\n",uid); if (setuid(uid) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't set uid to %d\n",uid); CfLog(cferror,OUTPUT,"setuid"); return false; } } return true; } /*******************************************************************/ /* Command exec aids */ /*******************************************************************/ int SplitCommand(char *comm,char arg[CF_MAXSHELLARGS][CF_BUFSIZE]) { char *sp; int i = 0; for (sp = comm; sp < comm+strlen(comm); sp++) { if (i >= CF_MAXSHELLARGS-1) { CfLog(cferror,"Too many arguments in embedded script",""); FatalError("Use a wrapper"); } while (*sp == ' ' || *sp == '\t') { sp++; } switch (*sp) { case '\0': return(i-1); case '\"': sscanf (++sp,"%[^\"]",arg[i]); break; case '\'': sscanf (++sp,"%[^\']",arg[i]); break; case '`': sscanf (++sp,"%[^`]",arg[i]); break; default: sscanf (sp,"%s",arg[i]); break; } sp += strlen(arg[i]); i++; } return (i); } cfengine-2.2.10/src/filters.c0000644000175000001440000010442511007375415012703 00000000000000 /* cfengine for GNU Copyright (C) 1995/6,2000 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: filters.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*******************************************************************/ /* Parser */ /*******************************************************************/ void InstallFilter(char *filter) { struct Filter *ptr; int i; Debug1("InstallFilter(%s)\n",filter); if (FilterExists(filter)) { yyerror("Redefinition of existing filter"); return; } if (! IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing Edit no match\n"); return; } if ((ptr = (struct Filter *)malloc(sizeof(struct Filter))) == NULL) { FatalError("Memory Allocation failed for InstallFilterFilter() #1"); } if ((ptr->alias = strdup(filter)) == NULL) { FatalError("Memory Allocation failed for InstallFilterFilter() #2"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallFilterFilter() #3"); } if (VFILTERLISTTOP == NULL) /* First element in the list */ { VFILTERLIST = ptr; } else { VFILTERLISTTOP->next = ptr; } for (i = 0; i < NoFilter; i++) { ptr->criteria[i] = NULL; } ptr->next = NULL; ptr->defines = NULL; ptr->elsedef = NULL; VFILTERLISTTOP = ptr; } /********************************************************************/ void InstallFilterTest(char *alias,char *type,char *data) { int crit, i = -1; struct Filter *fp; char ebuff[CF_EXPANDSIZE],vbuff[CF_BUFSIZE],units='x',*sp; time_t now; if (strlen(type) == 0) { return; } Debug("InstallFilterTest(%s,%s,%s)\n",alias,type,data); if (time(&now) == -1) { FatalError("Unable to access clock"); } crit = (int) FilterActionsToCode(type); ExpandVarstring(data,ebuff,NULL); if (crit == NoFilter) { snprintf(OUTPUT,CF_BUFSIZE,"Unknown filter criterion (%s)\n",type); yyerror(OUTPUT); } else { for (fp = VFILTERLIST; fp != NULL; fp = fp->next) { if (strcmp(alias,fp->alias) == 0) { switch (crit) { case filterdefclasses: fp->defines = strdup(ebuff); break; case filterelsedef: fp->elsedef = strdup(ebuff); break; case filterresult: IsInstallable(ebuff); /* syntax check */ break; case filterfromctime: now = Date2Number(ebuff,now); break; case filtertoctime: now = Date2Number(ebuff,now); break; case filterfrommtime: now = Date2Number(ebuff,now); break; case filtertomtime: now = Date2Number(ebuff,now); break; case filterfromatime: now = Date2Number(ebuff,now); break; case filtertoatime: now = Date2Number(ebuff,now); break; case filterfromsize: case filtertosize: sscanf(ebuff,"%d%c",&i,&units); if (i < 0) { yyerror("filter size attribute with silly value (must be a non-negative number)"); } switch (units) { case 'k': case 'K': i *= 1024; break; case 'm': case 'M': i = i * 1024 * 1024; break; } sprintf(ebuff,"%d",i); break; case filterexecregex: for (sp = ebuff+strlen(ebuff)-1; (*sp != '(') && (sp > ebuff); sp--) { } sscanf(sp+1,"%256[^)]",vbuff); if (!RegexOK(vbuff)) { yyerror("Regular expression error"); } break; case filternameregex: if (!RegexOK(ebuff)) { yyerror("Regular expression error"); } break; case filterexec: /* test here */ break; case filtersymlinkto: break; } if ((fp->criteria[crit] = strdup(ebuff)) == NULL) { CfLog(cferror,"Couldn't allocate filter memory","strdup"); FatalError("Dying.."); } else { return; } } } } } /********************************************************************/ void CheckFilters() { struct Filter *fp; time_t t; if (time(&t) == -1) { FatalError("Clock unavailable"); } for (fp = VFILTERLIST; fp != NULL; fp = fp->next) { if (fp->criteria[filterresult] == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"No result specified for filter %s",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency error"); } if ((fp->criteria[filterfromctime]!=NULL && fp->criteria[filtertoctime]==NULL) || (fp->criteria[filterfromctime]==NULL && fp->criteria[filtertoctime]!=NULL)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Incomplete ctime limit specification of filter %s",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } if ((fp->criteria[filterfromatime]!=NULL && fp->criteria[filtertoatime]==NULL) || (fp->criteria[filterfromatime]==NULL && fp->criteria[filtertoatime]!=NULL)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Incomplete atime limit specification of filter %s",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } if ((fp->criteria[filterfrommtime]!=NULL && fp->criteria[filtertomtime]==NULL) || (fp->criteria[filterfrommtime]==NULL && fp->criteria[filtertomtime]!=NULL)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Incomplete mtime limit specification of filter %s",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } if ((fp->criteria[filterfromstime]!=NULL && fp->criteria[filtertostime]==NULL) || (fp->criteria[filterfromstime]==NULL && fp->criteria[filtertostime]!=NULL)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Incomplete stime limit specification of filter %s",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } if ((fp->criteria[filterfromttime]!=NULL && fp->criteria[filtertottime]==NULL) || (fp->criteria[filterfromttime]==NULL && fp->criteria[filtertottime]!=NULL)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Incomplete ttime limit specification of filter %s",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } if ((fp->criteria[filterfromsize]!=NULL && fp->criteria[filtertosize]==NULL) || (fp->criteria[filterfromsize]==NULL && fp->criteria[filtertosize]!=NULL)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Incomplete size limit specification of filter %s",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } if (fp->criteria[filterfromatime] != NULL) { if (Date2Number(fp->criteria[filterfromatime],t) > Date2Number(fp->criteria[filtertoatime],t)) { snprintf(OUTPUT,CF_BUFSIZE*2,"To/From atimes silly in filter %s (from > to)",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } } if (fp->criteria[filterfromctime] != NULL) { if (Date2Number(fp->criteria[filterfromctime],t) > Date2Number(fp->criteria[filtertoctime],t)) { snprintf(OUTPUT,CF_BUFSIZE*2,"To/From ctimes silly in filter %s (from > to)",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } } if (fp->criteria[filterfrommtime] != NULL) { if (Date2Number(fp->criteria[filterfrommtime],t) > Date2Number(fp->criteria[filtertomtime],t)) { snprintf(OUTPUT,CF_BUFSIZE*2,"To/From mtimes silly in filter %s (from > to)",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } } if (fp->criteria[filterfromstime] != NULL) { if (Date2Number(fp->criteria[filterfromstime],t) > Date2Number(fp->criteria[filtertostime],t)) { snprintf(OUTPUT,CF_BUFSIZE*2,"To/From stimes silly in filter %s (from > to)",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } } if (fp->criteria[filterfromttime] != NULL) { if (Date2Number(fp->criteria[filterfromttime],t) > Date2Number(fp->criteria[filtertottime],t)) { snprintf(OUTPUT,CF_BUFSIZE*2,"To/From ttimes silly in filter %s (from > to)",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } if (strncmp(fp->criteria[filterfromttime],"accumulated",strlen("accumulated")) != 0) { yyerror("Must use accumulated time in FromTtime"); } if (strncmp(fp->criteria[filtertottime],"accumulated",strlen("accumulated")) != 0) { if (strcmp(fp->criteria[filtertottime],"inf") != 0) { yyerror("Must use accumulated time in ToTtime"); } } } if (fp->criteria[filterfromsize] != NULL) { if (strcmp(fp->criteria[filterfromsize],fp->criteria[filtertosize]) > 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"To/From size is silly in filter %s (from > to)",fp->alias); CfLog(cferror,OUTPUT,""); FatalError("Consistency errors"); } } } } /********************************************************************/ enum filternames FilterActionsToCode(char *filtertype) { int i; Debug("FilterActionsToCode(%s)\n",filtertype); if (filtertype[strlen(filtertype)-1] != ':') { yyerror("Syntax error in filter type"); return NoFilter; } filtertype[strlen(filtertype)-1] = '\0'; for (i = 0; VFILTERNAMES[i] != '\0'; i++) { if (strcmp(VFILTERNAMES[i],filtertype) == 0) { return (enum filternames) i; } } return (NoFilter); } /*******************************************************************/ int FilterExists(char *name) { struct Filter *ptr; for (ptr=VFILTERLIST; ptr != NULL; ptr=ptr->next) { if (strcmp(ptr->alias,name) == 0) { return true; } } return false; } /*********************************************************************/ time_t Date2Number(char *string,time_t now) /* FromCtime: "date(1999,2,22,0,0,0)" FromMtime: "tminus(0,0,2,0,0,0)" */ { char type[CF_SMALLBUF],datestr[CF_SMALLBUF]; int year=-1,month=-1,day=-1,hr=-1,min=-1,sec=-1; time_t time; struct tm tmv; if (string == NULL || strlen (string) == 0) { return now; } if (strcmp(string,"now") == 0) { return now; } if (strcmp(string,"inf")==0) { return (time_t) (now|0x0FFFFFFF); /* time_t is signed long, assumes 64 bits */ } sscanf(string,"%15[^(](%d,%d,%d,%d,%d,%d)",type,&year,&month,&day,&hr,&min,&sec); if (year*month*day*hr*min*sec < 0) { yyerror("Bad relative time specifier, should be type(year,month,day,hr,min,sec)"); return now; } if (strcmp(type,"date")==0) { if (year < 1970 || year > 3000) { yyerror("Year value is silly (1970-3000)"); return now; } if (month < 1 || month > 12) { yyerror("Month value is silly (1-12)"); return now; } if (day < 1 || day > 31) { yyerror("Day value is silly (1-31)"); return now; } if (hr > 23) { yyerror("Hour value is silly (0-23)"); return now; } if (min > 59) { yyerror("Minute value is silly (0-59)"); return now; } if (sec > 59) { yyerror("Second value is silly (0-59)"); return now; } Debug("Time is %s or (y=%d,m=%d,d=%d,h=%d,m=%d,s=%d)\n",datestr,year,month,day,hr,min,sec); tmv.tm_year = year - 1900; tmv.tm_mon = month -1; tmv.tm_mday = day; tmv.tm_hour = hr; tmv.tm_min = min; tmv.tm_sec = sec; tmv.tm_isdst= -1; if ((time=mktime(&tmv))== -1) { yyerror("Illegal time value"); return now; } Debug("Time computed from input was: %s\n",ctime(&time)); return time; } else if (strcmp(type,"tminus")==0) { if (year > 30) { yyerror("Relative Year value is silly (0-30 year ago)"); return now; } Debug("Time is %s or (y=%d,m=%d,d=%d,h=%d,m=%d,s=%d)\n",datestr,year,month,day,hr,min,sec); time = CFSTARTTIME; time -= sec; time -= min * 60; time -= hr * 3600; time -= day * 24 * 3600; time -= month * 30 * 24 * 3600; time -= year * 365 * 24 * 3600; Debug("Total negative offset = %.1f minutes\n",(double)(CFSTARTTIME-time)/60.0); Debug("Time computed from input was: %s\n",ctime(&time)); return time; } else if (strcmp(type,"accumulated")==0) { sscanf(string,"%8[^(](%d,%d,%d,%d,%d,%d)",type,&year,&month,&day,&hr,&min,&sec); if (year*month*day*hr*min*sec < 0) { yyerror("Bad cumulative time specifier, should be type(year,month,day,hr,min,sec)"); return now; } time = 0; time += sec; time += min * 60; time += hr * 3600; time += day * 24 * 3600; time += month * 30 * 24 * 3600; time += year * 365 * 24 * 3600; return time; } yyerror("Illegal time specifier"); return now; } /*******************************************************************/ /* Filter code */ /* These functions return true if the input survives the filters */ /* Several filters are ANDed together.... */ /*******************************************************************/ int ProcessFilter(char *proc,struct Item *filterlist,char **names,int *start,int *end) { struct Item *tests = NULL; struct Filter *fp; int result = true, tmpres, i; char *line[CF_PROCCOLS]; Debug("ProcessFilter(%.6s...)\n",proc); if (filterlist == NULL) { return true; } if (strlen(proc) == 0) { return false; } SplitLine(proc,names,start,end,line); for (fp = VFILTERLIST; fp != NULL; fp=fp->next) { if (IsItemIn(filterlist,fp->alias)) { Debug ("Applying filter %s\n",fp->alias); if (fp->criteria[filterresult] == NULL) { fp->criteria[filterresult] = strdup("Owner.PID.PPID.PGID.RSize.VSize.Status.Command.TTime.STime.TTY.Priority.Threads"); } DoProc(&tests,fp->criteria,names,line); if (tmpres = EvaluateORString(fp->criteria[filterresult],tests,0)) { AddMultipleClasses(fp->defines); } else { AddMultipleClasses(fp->elsedef); } result &= tmpres; } } for (i = 0; i < CF_PROCCOLS; i++) { if (line[i] != NULL) { free(line[i]); } } DeleteItemList(tests); return result; } /*******************************************************************/ int FileObjectFilter(char *file,struct stat *lstatptr,struct Item *filterlist,enum actions context) { struct Item *tests = NULL; struct Filter *fp; int result = true, tmpres; Debug("FileObjectFilter(%s)\n",file); if (filterlist == NULL) { return true; } for (fp = VFILTERLIST; fp != NULL; fp=fp->next) { if (IsItemIn(filterlist,fp->alias)) { Debug ("Applying filter %s\n",fp->alias); if (fp->criteria[filterresult] == NULL) { fp->criteria[filterresult] = strdup("Type.Owner.Group.Mode.Ctime.Mtime.Atime.Size.ExecRegex.NameRegex.IsSymLinkTo.ExecProgram"); } DoFilter(&tests,fp->criteria,lstatptr,file); if (tmpres = EvaluateORString(fp->criteria[filterresult],tests,0)) { AddMultipleClasses(fp->defines); } else { AddMultipleClasses(fp->elsedef); } result &= tmpres; } } DeleteItemList(tests); Debug("Filter result on %s was %d\n",file,result); return result; } /*******************************************************************/ void DoFilter(struct Item **attr,char **crit,struct stat *lstatptr,char *filename) { if (crit[filtertype] != NULL) { if (FilterTypeMatch(lstatptr,crit[filtertype])) { PrependItem(attr,"Type",""); } } if (crit[filterowner] != NULL) { if (FilterOwnerMatch(lstatptr,crit[filterowner])) { PrependItem(attr,"Owner",""); } } if (crit[filtergroup] != NULL) { if (FilterGroupMatch(lstatptr,crit[filtergroup])) { PrependItem(attr,"Group",""); } } if (crit[filtermode] != NULL) { if (FilterModeMatch(lstatptr,crit[filtermode])) { PrependItem(attr,"Mode",""); } } if (crit[filterfromatime] != NULL) { if (FilterTimeMatch(lstatptr->st_atime,crit[filterfromatime],crit[filtertoatime])) { PrependItem(attr,"Atime",""); } } if (crit[filterfromctime] != NULL) { if (FilterTimeMatch(lstatptr->st_ctime,crit[filterfromctime],crit[filtertoctime])) { PrependItem(attr,"Ctime",""); } } if (crit[filterfrommtime] != NULL) { if (FilterTimeMatch(lstatptr->st_mtime,crit[filterfrommtime],crit[filtertomtime])) { PrependItem(attr,"Mtime",""); } } if (crit[filternameregex] != NULL) { if (FilterNameRegexMatch(filename,crit[filternameregex])) { PrependItem(attr,"NameRegex",""); } } if ((crit[filtersymlinkto] != NULL) && (S_ISLNK(lstatptr->st_mode))) { if (FilterIsSymLinkTo(filename,crit[filtersymlinkto])) { PrependItem(attr,"IsSymLinkTo",""); } } if (crit[filterexecregex] != NULL) { if (FilterExecRegexMatch(filename,crit[filterexecregex])) { PrependItem(attr,"ExecRegex",""); } } if (crit[filterexec] != NULL) { if (FilterExecMatch(filename,crit[filterexec])) { PrependItem(attr,"ExecProgram",""); } } } /*******************************************************************/ void DoProc(struct Item **attr,char **crit,char **names,char **line) { if (crit[filterowner] != NULL) { if (FilterProcMatch("UID","USER",crit[filterowner],names,line)) { PrependItem(attr,"Owner",""); } } else { PrependItem(attr,"Owner",""); } if (crit[filterpid] != NULL) { if (FilterProcMatch("PID","PID",crit[filterpid],names,line)) { PrependItem(attr,"PID",""); } } else { PrependItem(attr,"PID",""); } if (crit[filterppid] != NULL) { if (FilterProcMatch("PPID","PPID",crit[filterppid],names,line)) { PrependItem(attr,"PPID",""); } } else { PrependItem(attr,"PPID",""); } if (crit[filterpgid] != NULL) { if (FilterProcMatch("PGID","PGID",crit[filterpgid],names,line)) { PrependItem(attr,"PGID",""); } } else { PrependItem(attr,"PGID",""); } if (crit[filtersize] != NULL) { if (FilterProcMatch("SZ","VSZ",crit[filtersize],names,line)) { PrependItem(attr,"VSize",""); } } else { PrependItem(attr,"VSize",""); } if (crit[filterrsize] != NULL) { if (FilterProcMatch("RSS","RSS",crit[filterrsize],names,line)) { PrependItem(attr,"RSize",""); } } else { PrependItem(attr,"RSize",""); } if (crit[filterstatus] != NULL) { if (FilterProcMatch("S","STAT",crit[filterstatus],names,line)) { PrependItem(attr,"Status",""); } } else { PrependItem(attr,"Status",""); } if (crit[filtercmd] != NULL) { if (FilterProcMatch("CMD","COMMAND",crit[filtercmd],names,line)) { PrependItem(attr,"Command",""); } } else { PrependItem(attr,"Command",""); } if (crit[filterfromttime] != NULL) { if (FilterProcTTimeMatch("TIME","TIME",crit[filterfromttime],crit[filtertottime],names,line)) { PrependItem(attr,"TTime",""); } } else { PrependItem(attr,"TTime",""); } if (crit[filterfromstime] != NULL) { if (FilterProcSTimeMatch("STIME","START",crit[filterfromstime],crit[filtertostime],names,line)) { PrependItem(attr,"STime",""); } } else { PrependItem(attr,"STime",""); } if (crit[filtertty] != NULL) { if (FilterProcMatch("TTY","TTY",crit[filtertty],names,line)) { PrependItem(attr,"TTY",""); } } else { PrependItem(attr,"TTY",""); } if (crit[filterpriority] != NULL) { if (FilterProcMatch("NI","PRI",crit[filterpriority],names,line)) { PrependItem(attr,"Priority",""); } } else { PrependItem(attr,"Priority",""); } if (crit[filterthreads] != NULL) { if (FilterProcMatch("NLWP","NLWP",crit[filterthreads],names,line)) { PrependItem(attr,"Threads",""); } } else { PrependItem(attr,"Threads",""); } } /*******************************************************************/ int FilterTypeMatch(struct stat *lstatptr,char *crit) { struct Item *attrib = NULL; if (S_ISLNK(lstatptr->st_mode)) { PrependItem(&attrib,"link",""); } if (S_ISREG(lstatptr->st_mode)) { PrependItem(&attrib,"reg",""); PrependItem(&attrib,"file",""); } if (S_ISDIR(lstatptr->st_mode)) { PrependItem(&attrib,"dir",""); } if (S_ISFIFO(lstatptr->st_mode)) { PrependItem(&attrib,"fifo",""); } if (S_ISSOCK(lstatptr->st_mode)) { PrependItem(&attrib,"socket",""); } if (S_ISCHR(lstatptr->st_mode)) { PrependItem(&attrib,"char",""); } if (S_ISBLK(lstatptr->st_mode)) { PrependItem(&attrib,"block",""); } #ifdef HAVE_DOOR_CREATE if (S_ISDOOR(lstatptr->st_mode)) { PrependItem(&attrib,"door",""); } #endif if (EvaluateORString(crit,attrib,0)) { DeleteItemList(attrib); return true; } else { DeleteItemList(attrib); return false; } } /*******************************************************************/ int FilterProcMatch(char *name1,char *name2,char *expr,char **names,char **line) { int i; regex_t rx; regmatch_t pmatch; Debug("FilterProcMatch(%s,%s,%s,<%x>,<%x>)\n",name1,name2,expr,names,line); if (CfRegcomp(&rx,expr,REG_EXTENDED) != 0) { return false; } for (i = 0; names[i] != NULL; i++) { if ((strcmp(names[i],name1) == 0) || (strcmp(names[i],name2) == 0)) { Debug("Match (%s) to (%s)\n",expr,line[i]); if (regexec(&rx,line[i],1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(line[i]))) { regfree(&rx); return true; } } Debug("No match of (%s) to (%s)\n",expr,line[i]); regfree(&rx); return false; } } regfree(&rx); return false; } /*******************************************************************/ int FilterProcSTimeMatch(char *name1,char *name2,char *fromexpr,char *toexpr,char **names,char **line) { int i; time_t fromtime,totime, now = CFSTARTTIME,pstime; char year[5],month[4],hr[3],min[3],day[3],timestr[256]; memset(year,0,5); strcpy(year,VYEAR); memset(month,0,4); strcpy(month,VMONTH); memset(day,0,3); strcpy(day,VDAY); memset(hr,0,3); strcpy(hr,VHR); memset(min,0,3); strcpy(min,VMINUTE); fromtime = Date2Number(fromexpr,now); totime = Date2Number(toexpr,now); for (i = 0; names[i] != NULL; i++) { if ((strcmp(names[i],name1) == 0) || (strcmp(names[i],name2) == 0)) { if (strstr(line[i],":")) /* Hr:Min:Sec */ { sscanf(line[i],"%2[^:]:%2[^:]:",hr,min); snprintf(timestr,256,"date(%s,%d,%s,%s,%s,0)",year,Month2Number(month),day,hr,min); } else /* date Month */ { sscanf(line[i],"%3[a-zA-Z] %2[0-9]",month,day); snprintf(timestr,256,"date(%s,%d,%s,%s,%s,0)",year,Month2Number(month),day,hr,min); } if (Month2Number(month) < 0) { continue; } pstime = Date2Number(timestr,now); Debug("Stime %s converted to %s\n",timestr,ctime(&pstime)); return ((fromtime < pstime) && (pstime < totime)); } } return false; } /*******************************************************************/ /* * HvB: Bas van der Vlies * Parse different TTime values */ void ParseTTime(char *line, char *time_str) { int day=0, hr=0, min=0, sec=0; int r; if (strstr(line,":")) /* day-Hr:Min:Sec */ { /* * first check the long fromat * day-hr:min:sec (posix) * hr:min:sec (posix) * min:sec (old) */ if ((r = sscanf(line,"%d-%d:%d:%d",&day,&hr,&min,&sec)) == 4) { snprintf(time_str,256,"accumulated(0,0,%d,%d,%d,%d)",day,hr,min,sec); } else if ((r = sscanf(line,"%d:%d:%d",&hr,&min,&sec)) == 3 ) { snprintf(time_str,256,"accumulated(0,0,0,%d,%d,%d)",hr,min,sec); } else if ((r = sscanf(line,"%d:%d",&min,&sec)) == 2) { /* Removed test - apparent bug if (min > 59) { day = min / (24 * 60); hr = (min - (day * 24 * 60)) / (60); min = min % 60; } */ day = min / (24 * 60); hr = (min - (day * 24 * 60)) / (60); min = min % 60; snprintf(time_str,256,"accumulated(0,0,%d,%d,%d,%d)",day,hr,min,sec); } } } /*******************************************************************/ int FilterProcTTimeMatch(char *name1,char *name2,char *fromexpr,char *toexpr,char **names,char **line) { int i; time_t fromtime,totime,now = CFSTARTTIME,pstime = CFSTARTTIME; char timestr[256]; fromtime = Date2Number(fromexpr,now); totime = Date2Number(toexpr,now); for (i = 0; names[i] != NULL; i++) { if ((strcmp(names[i],name1) == 0) || (strcmp(names[i],name2) == 0)) { memset(timestr,0,sizeof(timestr)); ParseTTime(line[i], timestr); Debug("ParseTTime = %s\n",timestr); pstime = Date2Number(timestr,now); return ((fromtime < pstime) && (pstime < totime)); } } return false; } /*******************************************************************/ int FilterOwnerMatch(struct stat *lstatptr,char *crit) { struct Item *attrib = NULL; char buffer[CF_SMALLBUF]; struct passwd *pw; sprintf(buffer,"%d",lstatptr->st_uid); PrependItem(&attrib,buffer,""); if ((pw = getpwuid(lstatptr->st_uid)) != NULL) { PrependItem(&attrib,pw->pw_name,""); } else { PrependItem(&attrib,"none",""); } if (EvaluateORString(crit,attrib,0)) { DeleteItemList(attrib); return true; } else { DeleteItemList(attrib); return false; } } /*******************************************************************/ int FilterGroupMatch(struct stat *lstatptr,char *crit) { struct Item *attrib = NULL; char buffer[CF_SMALLBUF]; struct group *gr; sprintf(buffer,"%d",lstatptr->st_gid); PrependItem(&attrib,buffer,""); if ((gr = getgrgid(lstatptr->st_gid)) != NULL) { PrependItem(&attrib,gr->gr_name,""); } else { PrependItem(&attrib,"none",""); } if (EvaluateORString(crit,attrib,0)) { DeleteItemList(attrib); return true; } else { DeleteItemList(attrib); return false; } } /*******************************************************************/ int FilterModeMatch(struct stat *lstatptr,char *crit) { mode_t plusmask,minusmask,newperm; ParseModeString(crit,&plusmask,&minusmask); newperm = (lstatptr->st_mode & 07777); newperm |= plusmask; newperm &= ~minusmask; Debug("FilterModeMatch %s -> (+%o,-%o/%o) = %d \n",crit,plusmask,minusmask,lstatptr->st_mode &07777,((newperm & 07777) == (lstatptr->st_mode & 07777))); return ((newperm & 07777) == (lstatptr->st_mode & 07777)); } /*******************************************************************/ int FilterTimeMatch(time_t stattime,char *from,char *to) { time_t fromtime,totime, now = CFSTARTTIME; fromtime = Date2Number(from,now); totime = Date2Number(to,now); return ((fromtime < stattime) && (stattime < totime)); } /*******************************************************************/ int FilterNameRegexMatch(char *filename,char *crit) { regex_t rx; regmatch_t pmatch; if (CfRegcomp(&rx,crit,REG_EXTENDED) != 0) { return false; } if (regexec(&rx,filename,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(filename))) { regfree(&rx); return true; } } regfree(&rx); return false; } /*******************************************************************/ int FilterExecRegexMatch(char *filename,char *crit) { regex_t rx; regmatch_t pmatch; char buffer[CF_BUFSIZE],expr[CF_BUFSIZE],line[CF_BUFSIZE],ebuff[CF_EXPANDSIZE],*sp; FILE *pp; AddMacroValue(CONTEXTID,"this",filename); ExpandVarstring(crit,ebuff,NULL); DeleteMacro(CONTEXTID,"this"); memset(buffer,0,CF_BUFSIZE); memset(line,0,CF_BUFSIZE); memset(expr,0,CF_BUFSIZE); for (sp = ebuff+strlen(ebuff)-1; (*sp != '(') && (sp > ebuff); sp--) { } sscanf(sp+1,"%256[^)]",expr); strncpy(buffer,ebuff,(int)(sp-ebuff)); if (CfRegcomp(&rx,expr,REG_EXTENDED) != 0) { return false; } if ((pp = cfpopen(buffer,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open pipe to command %s\n",buffer); CfLog(cferror,OUTPUT,"cfpopen"); return false; } ReadLine(line,CF_BUFSIZE,pp); /* One buffer only */ cfpclose(pp); if (regexec(&rx,line,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(line))) { regfree(&rx); return true; } } regfree(&rx); return false; } /*******************************************************************/ int FilterIsSymLinkTo(char *filename,char *crit) { regex_t rx; regmatch_t pmatch; char buffer[CF_BUFSIZE]; if (CfRegcomp(&rx,crit,REG_EXTENDED) != 0) { return false; } memset(buffer,0,CF_BUFSIZE); if (readlink(filename,buffer,CF_BUFSIZE-1) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to read link %s in filter",filename); CfLog(cferror,OUTPUT,"readlink"); regfree(&rx); return false; } if (regexec(&rx,buffer,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(buffer))) { regfree(&rx); return true; } } regfree(&rx); return false; } /*******************************************************************/ int FilterExecMatch(char *filename,char *crit) /* command can include $(this) for the name of the file */ { char ebuff[CF_EXPANDSIZE]; AddMacroValue(CONTEXTID,"this",filename); ExpandVarstring(crit,ebuff,NULL); DeleteMacro(CONTEXTID,"this"); Debug("Executing filter command [%s]\n",ebuff); if (ShellCommandReturnsZero(ebuff,false)) { return true; } else { return false; } } /*******************************************************************/ void GetProcessColumns(char *proc,char **names,int *start,int *end) { char *sp,title[16]; int col,offset = 0; for (col = 0; col < CF_PROCCOLS; col++) { start[col] = end[col] = -1; names[col] = NULL; } col = 0; for (sp = proc; *sp != '\0'; sp++) { offset = sp - proc; if (isspace((int)*sp)) { if (start[col] != -1) { Debug("End of %s is %d\n",title,offset-1); end[col++] = offset - 1; if (col > CF_PROCCOLS - 1) { CfLog(cferror,"Column overflow in process table",""); break; } } continue; } else if (start[col] == -1) { start[col] = offset; sscanf(sp,"%15s",title); Debug("Start of %s is %d\n",title,offset); names[col] = strdup(title); Debug("Col[%d]=%s\n",col,names[col]); } } if (end[col] == -1) { Debug("End of %s is %d\n",title,offset); end[col] = offset; } } /*******************************************************************/ void SplitLine(char *proc,char **names,int *start,int *end,char **line) { int i,s,e; Debug("SplitLine(%s)\n",proc); for (i = 0; i < CF_PROCCOLS; i++) { line[i] = NULL; } for (i = 0; names[i] != NULL; i++) { for (s = start[i]; (s >= 0) && !isspace((int)*(proc+s)); s--) { } if (s < 0) { s = 0; } while (isspace((int)proc[s])) { s++; } if (strcmp(names[i],"CMD") == 0 || strcmp(names[i],"COMMAND") == 0) { e = strlen(proc); } else { for (e = end[i]; (e <= end[i]+10) && !isspace((int)*(proc+e)); e++) { } while (isspace((int)proc[e])) { if (e > 0) { e--; } } } if (s <= e) { line[i] = (char *)malloc(e-s+2); memset(line[i],0,(e-s+2)); strncpy(line[i],(char *)(proc+s),(e-s+1)); } else { line[i] = (char *)malloc(1); line[i][0] = '\0'; } Debug(" %s=(%s) of [%s]\n",names[i],line[i],proc); } Debug("------------------------------------\n"); } cfengine-2.2.10/src/cfetooldefs.h0000644000175000001440000000051510574547416013542 00000000000000 #define DAILY 1 #define WEEKLY 2 #define YEARLY 3 #define MONDAY_MORNING 345600 #define JANUARY_FIRST 63072000 #define ONE_YEAR 31536000 #define ONE_DAY 86400 #define ONE_WEEK 604800 struct Average { double expect; double var; }; char *GenTimeKey2 (time_t now, int dbtype); char *ConvTimeKey2 (char *str, int dbtype); cfengine-2.2.10/src/expand-image.c0000644000175000001440000002313310672315172013567 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /*****************************************************************************/ /* */ /* File: expand-image.c */ /* */ /*****************************************************************************/ void RecursiveImage(struct Image *ip,char *from,char *to,int maxrecurse) { struct stat statbuf, deststatbuf; char newfrom[CF_BUFSIZE]; char newto[CF_BUFSIZE]; int save_uid, save_gid, succeed; struct Item *namecache = NULL; struct Item *ptr; struct cfdirent *dirp; CFDIR *dirh; if (maxrecurse == 0) /* reached depth limit */ { Debug2("MAXRECURSE ran out, quitting at level %s with endlist = %d\n",from,ip->next); return; } Debug2("RecursiveImage(%s,lev=%d,next=%d)\n",from,maxrecurse,ip->next); if (IgnoreFile(from,"",ip->ignores)) { Verbose("Ignoring directory %s\n",from); return; } if (strlen(from) == 0) /* Check for root dir */ { from = "/"; } /* Check that dest dir exists before starting */ strncpy(newto,to,CF_BUFSIZE-2); AddSlash(newto); if (strcmp(ip->action,"warn") != 0) { if (! MakeDirectoriesFor(newto,ip->forcedirs)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to make directory for %s in copy: %s to %s\n",newto,ip->path,ip->destination); CfLog(cferror,OUTPUT,""); return; } } if ((dirh = cfopendir(from,ip)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"copy can't open directory [%s]\n",from); CfLog(cfverbose,OUTPUT,""); return; } for (dirp = cfreaddir(dirh,ip); dirp != NULL; dirp = cfreaddir(dirh,ip)) { if (!SensibleFile(dirp->d_name,from,ip)) { continue; } if (ip->purge == 'y') /* Do not purge this file */ { AppendItem(&namecache,dirp->d_name,NULL); } if (IgnoreFile(from,dirp->d_name,ip->ignores)) { continue; } strncpy(newfrom,from,CF_BUFSIZE-2); /* Assemble pathname */ AddSlash(newfrom); strncpy(newto,to,CF_BUFSIZE-2); AddSlash(newto); if (BufferOverflow(newfrom,dirp->d_name)) { printf(" culprit: RecursiveImage\n"); cfclosedir(dirh); return; } strncat(newfrom,dirp->d_name,CF_BUFSIZE-2); if (BufferOverflow(newto,dirp->d_name)) { printf(" culprit: RecursiveImage\n"); cfclosedir(dirh); return; } strcat(newto,dirp->d_name); if (TRAVLINKS || ip->linktype == 'n') { /* No point in checking if there are untrusted symlinks here, since this is from a trusted source, by defintion */ if (cfstat(newfrom,&statbuf,ip) == -1) { Verbose("%s: (Can't stat %s)\n",VPREFIX,newfrom); continue; } } else { if (cflstat(newfrom,&statbuf,ip) == -1) { Verbose("%s: (Can't stat %s)\n",VPREFIX,newfrom); continue; } } if ((ip->xdev =='y') && DeviceChanged(statbuf.st_dev)) { Verbose("Skipping %s on different device\n",newfrom); continue; } if (!FileObjectFilter(newfrom,&statbuf,ip->filters,image)) { continue; } if (!S_ISDIR(statbuf.st_mode) && IgnoredOrExcluded(image,dirp->d_name,ip->inclusions,ip->exclusions)) { continue; } if (!S_ISDIR(statbuf.st_mode)) { succeed = 0; if (IsItemIn(VEXCLUDECACHE,newto)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Skipping single-copied file %s class %s\n",newto,ip->classes); CfLog(cfverbose,OUTPUT,""); continue; } } if (S_ISDIR(statbuf.st_mode)) { if (TRAVLINKS) { CfLog(cfverbose,"Traversing directory links during copy is too dangerous, pruned",""); continue; } memset(&deststatbuf,0,sizeof(struct stat)); save_uid = (ip->uid)->uid; save_gid = (ip->gid)->gid; if ((ip->uid)->uid == (uid_t)-1) /* Preserve uid and gid */ { (ip->uid)->uid = statbuf.st_uid; } if ((ip->gid)->gid == (gid_t)-1) { (ip->gid)->gid = statbuf.st_gid; } if (stat(newto,&deststatbuf) == -1) { mkdir(newto,statbuf.st_mode); if (stat(newto,&deststatbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",newto); CfLog(cferror,OUTPUT,"stat"); continue; } } CheckCopiedFile(ip->cf_findertype,newto,&deststatbuf,&statbuf,ip); (ip->uid)->uid = save_uid; (ip->gid)->gid = save_gid; Verbose("Opening %s->%s\n",newfrom,newto); RecursiveImage(ip,newfrom,newto,maxrecurse-1); } else { CheckImage(newfrom,newto,ip); } } if (ip->purge == 'y') { /* inclusions not exclusions, since exclude from purge means include */ PurgeFiles(namecache,to,ip->inclusions); DeleteItemList(namecache); } DeleteCompressedArray(ip->inode_cache); ip->inode_cache = NULL; cfclosedir(dirh); } /*********************************************************************/ void CheckHomeImages(struct Image *ip) { DIR *dirh, *dirh2; struct dirent *dirp, *dirp2; char username[CF_MAXVARSIZE]; char homedir[CF_BUFSIZE],dest[CF_BUFSIZE]; struct passwd *pw; struct group *gr; struct stat statbuf; struct Item *itp; int request_uid = ip->uid->uid; /* save if -1 */ int request_gid = ip->gid->gid; /* save if -1 */ if (!MountPathDefined()) { printf("%s: mountpattern is undefined\n",VPREFIX); return; } if (cfstat(ip->path,&statbuf,ip) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Master file %s doesn't exist for copying\n",ip->path); CfLog(cferror,OUTPUT,""); return; } for (itp = VMOUNTLIST; itp != NULL; itp=itp->next) { if (IsExcluded(itp->classes)) { continue; } if ((dirh = opendir(itp->name)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",itp->name); CfLog(cfverbose,OUTPUT,"opendir"); return; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,itp->name,NULL)) { continue; } strcpy(homedir,itp->name); AddSlash(homedir); strcat(homedir,dirp->d_name); if (! IsHomeDir(homedir)) { continue; } if ((dirh2 = opendir(homedir)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",homedir); CfLog(cfverbose,OUTPUT,"opendir"); return; } for (dirp2 = readdir(dirh2); dirp2 != NULL; dirp2 = readdir(dirh2)) { if (!SensibleFile(dirp2->d_name,homedir,NULL)) { continue; } strcpy(username,dirp2->d_name); strcpy(dest,homedir); AddSlash(dest); strcat(dest,dirp2->d_name); if (strlen(ip->destination) > 4) { AddSlash(dest); if (strlen(ip->destination) < 6) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error in home/copy to %s",ip->destination); CfLog(cferror,OUTPUT,""); return; } else { strcat(dest,(ip->destination)+strlen("home/")); } } if (request_uid == -1) { if ((pw = getpwnam(username)) == NULL) { Debug2("cfengine: directory corresponds to no user %s - ignoring\n",username); continue; } else { Debug2("(Setting user id to %s)\n",pw->pw_name); } ip->uid->uid = pw->pw_uid; } if (request_gid == -1) { if ((pw = getpwnam(username)) == NULL) { Debug2("cfengine: directory corresponds to no user %s - ignoring\n",username); continue; } if ((gr = getgrgid(pw->pw_gid)) == NULL) { Debug2("cfengine: no group defined for group id %d - ignoring\n",pw->pw_gid); continue; } else { Debug2("(Setting group id to %s)\n",gr->gr_name); } ip->gid->gid = gr->gr_gid; } CheckImage(ip->path,dest,ip); } closedir(dirh2); } closedir(dirh); } } cfengine-2.2.10/src/varstring.c0000644000175000001440000006050011006552343013241 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ /* Varstring: variable names */ /*********************************************************************/ char *VVNAMES[] = { "version", "faculty", "site", "host", "fqhost", "ipaddress", "binserver", "sysadm", "domain", "timezone", "netmask", "nfstype", "sensiblesize", "sensiblecount", "editfilesize", "editbinfilesize", "actionsequence", "mountpattern", "homepattern", "addclasses", "addinstallable", "schedule", "access", "class", "arch", "ostype", "date", "year", "month", "day", "hr", "min", "allclasses", "excludecopy", "singlecopy", "autodefine", "excludelink", "copylinks", "linkcopies", "repository", "spc", "tab", "lf", "cr", "n", "dblquote", "colon", "quote", "dollar", "repchar", "split", "underscoreclasses", "interfacename", "expireafter", "ifelapsed", "fileextensions", "suspiciousnames", "spooldirectories", "allowconnectionsfrom", /* nonattackers */ "denyconnectionsfrom", "allowmultipleconnectionsfrom", "methodparameters", "methodname", "methodpeers", "trustkeysfrom", "dynamicaddresses", "allowusers", "skipverify", "defaultcopytype", "allowredefinitionof", "defaultpkgmgr", /* For packages */ "abortclasses", "ignoreinterfaceregex", NULL }; /*********************************************************************/ /* TOOLKIT : Varstring expansion */ /*********************************************************************/ int TrueVar(char *var) { char buff[CF_EXPANDSIZE]; char varbuf[CF_MAXVARSIZE]; if (GetMacroValue(CONTEXTID,var)) { snprintf(varbuf,CF_MAXVARSIZE,"$(%s)",var); ExpandVarstring(varbuf,buff,NULL); if (strcmp(ToLowerStr(buff),"on") == 0) { return true; } if (strcmp(ToLowerStr(buff),"true") == 0) { return true; } } return false; } /*********************************************************************/ int CheckVarID(char *var) { char *sp; Debug("CheckVarID(%s)\n",var); for (sp = var; *sp != '\0'; sp++) { if (isalnum((int)*sp)) { } else if ((*sp == '_') || (*sp == '[') || (*sp == ']') || (*sp == '.')) { } else { snprintf(OUTPUT,CF_BUFSIZE,"Non identifier character (%c) in variable identifier (%s) - ",*sp,var); yyerror(OUTPUT); return false; } } return true; } /*********************************************************************/ int IsVarString(char *str) { char *sp; char left = 'x', right = 'x'; int dollar = false; int bracks = 0, vars = 0; Debug1("IsVarString(%s) - syntax verify\n",str); for (sp = str; *sp != '\0' ; sp++) /* check for varitems */ { switch (*sp) { case '$': if (*(sp+1) == '{' || *(sp+1) == '(') { dollar = true; } break; case '(': case '{': if (dollar) { left = *sp; bracks++; } break; case ')': case '}': if (dollar) { bracks--; right = *sp; } break; } if (left == '(' && right == ')' && dollar && (bracks == 0)) { vars++; dollar=false; } if (left == '{' && right == '}' && dollar && (bracks == 0)) { vars++; dollar = false; } } if (bracks != 0) { yyerror("Incomplete variable syntax or bracket mismatch (varstring)"); return false; } Debug("Found %d variables in (%s)\n",vars,str); return vars; } /*********************************************************************/ char *ExtractInnerVarString(char *str,char *substr) { char *sp; int bracks = 1; Debug1("ExtractInnerVarString( %s ) - syntax verify\n",str); memset(substr,0,CF_BUFSIZE); /* Start this from after the opening $( */ for (sp = str+2; *sp != '\0' ; sp++) /* check for varitems */ { switch (*sp) { case '(': case '{': bracks++; break; case ')': case '}': bracks--; break; default: if (isalnum((int)*sp) || IsIn(*sp,"_[]$.:-")) { } else { Debug("Illegal character found: '%c'\n", *sp); yyerror("Illegal character somewhere in variable or nested expansion"); } } if (bracks == 0) { strncpy(substr,str+2,sp-str-2); Debug("Returning substring value %s\n",substr); return substr; } } if (bracks != 0) { yyerror("Incomplete variable syntax or bracket mismatch (InnerVarstring)"); return false; } return sp-1; } /*********************************************************************/ char *ExtractOuterVarString(char *str,char *substr) /* Should only by applied on str[0] == '$' */ { char *sp; int dollar = false; int bracks = 0, onebrack = false; int nobracks = true; Debug("ExtractOuterVarString(%s) - syntax verify\n",str); memset(substr,0,CF_BUFSIZE); for (sp = str; *sp != '\0' ; sp++) /* check for varitems */ { switch (*sp) { case '$': dollar = true; switch (*(sp+1)) { case '(': case '{': break; default: /* Stray dollar not a variable */ return NULL; } break; case '(': case '{': bracks++; onebrack = true; nobracks = false; break; case ')': case '}': bracks--; break; } if (dollar && (bracks == 0) && onebrack) { strncpy(substr,str,sp-str+1); Debug("Extracted outer variable |%s|\n",substr); return substr; } } if (dollar == false) { return str; /* This is not a variable*/ } if (bracks != 0) { yyerror("Incomplete variable syntax or bracket mismatch (OuterVarstring)"); return NULL; } /* Return pointer to first position in string (shouldn't happen) as long as we only call this function from the first $ position */ return str; } /*********************************************************************/ int ExpandVarstring(char *string,char buffer[CF_EXPANDSIZE],char *bserver) { char *sp,*env; int varstring = false; char currentitem[CF_EXPANDSIZE],temp[CF_BUFSIZE],name[CF_MAXVARSIZE]; int len,increment; time_t tloc; memset(buffer,0,CF_EXPANDSIZE); if (string == 0 || strlen(string) == 0) { return false; } Debug("ExpandVarstring( %s )\n",string); for (sp = string; /* No exit */ ; sp++) /* check for varitems */ { char var[CF_BUFSIZE]; memset(var,0,CF_BUFSIZE); increment = 0; if (*sp == '\0') { break; } memset(currentitem,0,CF_EXPANDSIZE); sscanf(sp,"%[^$]",currentitem); if (ExpandOverflow(buffer,currentitem)) { FatalError("Can't expand varstring"); } strcat(buffer,currentitem); sp += strlen(currentitem); Debug("Add |%s| to str, waiting at |%s|\n",buffer,sp); if (*sp == '\0') { break; } if (*sp == '$') { switch (*(sp+1)) { case '(': ExtractOuterVarString(sp,var); varstring = ')'; break; case '{': ExtractOuterVarString(sp,var); varstring = '}'; break; default: strcat(buffer,"$"); continue; } } memset(currentitem,0,CF_EXPANDSIZE); temp[0] = '\0'; ExtractInnerVarString(sp,temp); if (strstr(temp,"$")) { Debug("Nested variables - %s\n",temp); ExpandVarstring(temp,currentitem,""); CheckVarID(currentitem); } else { strncpy(currentitem,temp,CF_BUFSIZE-1); } increment = strlen(var) - 1; Debug("Scanning variable %s\n",currentitem); switch (ScanVariable(currentitem)) { case cfversionvar: if (ExpandOverflow(buffer,VERSION)) { FatalError("Can't expand varstring"); } strcat(buffer,VERSION); break; case cffaculty: case cfsite: if (VFACULTY[0] == '\0') { yyerror("faculty/site undefined variable"); } if (ExpandOverflow(buffer,VFACULTY)) { FatalError("Can't expand varstring"); } strcat(buffer,VFACULTY); break; case cfhost: if (strlen(VUQNAME) == 0) { if (ExpandOverflow(buffer,VDEFAULTBINSERVER.name)) { FatalError("Can't expand varstring"); } strcat(buffer,VDEFAULTBINSERVER.name); } else { if (ExpandOverflow(buffer,VUQNAME)) { FatalError("Can't expand varstring"); } strcat(buffer,VUQNAME); } break; case cffqhost: if (ExpandOverflow(buffer,VFQNAME)) { FatalError("Can't expand varstring"); } strcat(buffer,VFQNAME); break; case cfnetmask: if (ExpandOverflow(buffer,VNETMASK)) { FatalError("Can't expand varstring"); } strcat(buffer,VNETMASK); break; case cfipaddr: if (ExpandOverflow(buffer,VIPADDRESS)) { FatalError("Can't expand varstring"); } strcat(buffer,VIPADDRESS); break; case cfbinserver: if (ACTION != links && ACTION != required) { yyerror("Inappropriate use of variable binserver"); FatalError("Bad variable"); } if (ExpandOverflow(buffer,"$(binserver)")) { FatalError("Can't expand varstring"); } strcat(buffer,"$(binserver)"); break; case cfsysadm: if (VSYSADM[0] == '\0') { yyerror("sysadm undefined variable"); } if (ExpandOverflow(buffer,VSYSADM)) { FatalError("Can't expand varstring"); } strcat(buffer,VSYSADM); break; case cfdomain: if (VDOMAIN[0] == '\0') { yyerror("domain undefined variable"); } if (ExpandOverflow(buffer,VDOMAIN)) { FatalError("Can't expandvarstring"); } strcat(buffer,ToLowerStr(VDOMAIN)); break; case cfnfstype: if (ExpandOverflow(buffer,VNFSTYPE)) { FatalError("Can't expandvarstring"); } strcat(buffer,VNFSTYPE); break; case cftimezone: if (VTIMEZONE == NULL) { yyerror("timezone undefined variable"); } if (ExpandOverflow(buffer,VTIMEZONE->name)) { FatalError("Can't expandvarstring"); } strcat(buffer,VTIMEZONE->name); break; case cfclass: if (ExpandOverflow(buffer,CLASSTEXT[VSYSTEMHARDCLASS])) { FatalError("Can't expandvarstring"); } strcat(buffer,CLASSTEXT[VSYSTEMHARDCLASS]); break; case cfarch: if (ExpandOverflow(buffer,VARCH)) { FatalError("Can't expandvarstring"); } strcat(buffer,VARCH); break; case cfarch2: if (ExpandOverflow(buffer,VARCH2)) { FatalError("Can't expandvarstring"); } strcat(buffer,VARCH2); break; case cfdate: if ((tloc = time((time_t *)NULL)) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't read system clock\n"); CfLog(cferror,"Couldn't read clock","time"); } if (ExpandOverflow(buffer,ctime(&tloc))) { FatalError("Can't expandvarstring"); } else { strcat(buffer,Space2Score(ctime(&tloc))); Chop(buffer); } break; case cfyear: if (ExpandOverflow(buffer,VYEAR)) { FatalError("Can't expandvarstring"); } else { strcat(buffer,VYEAR); } break; case cfmonth: if (ExpandOverflow(buffer,VMONTH)) { FatalError("Can't expandvarstring"); } else { strcat(buffer,VMONTH); } break; case cfday: if (ExpandOverflow(buffer,VDAY)) { FatalError("Can't expandvarstring"); } else { strcat(buffer,VDAY); } break; case cfhr: if (ExpandOverflow(buffer,VHR)) { FatalError("Can't expandvarstring"); } else { strcat(buffer,VHR); } break; case cfmin: if (ExpandOverflow(buffer,VMINUTE)) { FatalError("Can't expandvarstring"); } else { strcat(buffer,VMINUTE); } break; case cfallclass: if (strlen(ALLCLASSBUFFER) == 0) { snprintf(name,CF_MAXVARSIZE,"$(%s)",currentitem); strcat(buffer,name); } if (ExpandOverflow(buffer,ALLCLASSBUFFER)) { FatalError("Can't expandvarstring"); } strcat(buffer,ALLCLASSBUFFER); break; case cfspc: if (ExpandOverflow(buffer," ")) { FatalError("Can't expandvarstring"); } strcat(buffer," "); break; case cftab: if (ExpandOverflow(buffer," ")) { FatalError("Can't expandvarstring"); } strcat(buffer,"\t"); break; case cflf: if (ExpandOverflow(buffer," ")) { FatalError("Can't expandvarstring"); } strcat(buffer,"\012"); break; case cfcr: if (ExpandOverflow(buffer," ")) { FatalError("Can't expandvarstring"); } strcat(buffer,"\015"); break; case cfn: if (ExpandOverflow(buffer," ")) { FatalError("Can't expandvarstring"); } strcat(buffer,"\n"); break; case cfdblquote: if (ExpandOverflow(buffer," ")) { FatalError("Can't expandvarstring"); } strcat(buffer,"\""); break; case cfquote: if (ExpandOverflow(buffer," ")) { FatalError("Can't expandvarstring"); } strcat(buffer,"\'"); break; case cfcolon: if (ExpandOverflow(buffer," ")) { FatalError("Can't expandvarstring"); } strcat(buffer,":"); break; case cfdollar: if (!PARSING) { if (ExpandOverflow(buffer," ")) { FatalError("Can't expandvarstring"); } strcat(buffer,"$"); } else { if (ExpandOverflow(buffer,"$(dollar)")) { FatalError("Can't expandvarstring"); } strcat(buffer,"$(dollar)"); } break; case cfrepchar: if (ExpandOverflow(buffer," ")) { FatalError("Can't expandvarstring"); } len = strlen(buffer); buffer[len] = REPOSCHAR; buffer[len+1] = '\0'; break; case cfrepos: if (VREPOSITORY != NULL) { if (ExpandOverflow(buffer,VREPOSITORY)) { FatalError("Can't expandvarstring"); } strcat(buffer,VREPOSITORY); } break; case cflistsep: if (ExpandOverflow(buffer,"")) { FatalError("Can't expandvarstring"); } len = strlen(buffer); buffer[len] = LISTSEPARATOR; buffer[len+1] = '\0'; break; default: if ((env = GetMacroValue(CONTEXTID,currentitem)) != NULL) { if (ExpandOverflow(buffer,env)) { FatalError("Can't expandvarstring"); } strcat(buffer,env); Debug("Expansion gave (%s), len = %d\n",buffer,strlen(currentitem)); break; } Debug("Currently non existent variable $(%s)\n",currentitem); if (varstring == '}') { snprintf(name,CF_MAXVARSIZE,"${%s}",currentitem); } else { snprintf(name,CF_MAXVARSIZE,"$(%s)",currentitem); } strcat(buffer,name); } sp += increment; currentitem[0] = '\0'; } Debug("Returning varstring (%s)\n",buffer); return varstring; } /*********************************************************************/ int ExpandVarbinserv(char *string,char *buffer,char *bserver) { char *sp; char varstring = false; char currentitem[CF_EXPANDSIZE], scanstr[6]; Debug("ExpandVarbinserv %s, ",string); if (bserver != NULL) { Debug("(Binserver is %s)\n",bserver); } buffer[0] = '\0'; for (sp = string; /* No exit */ ; sp++) /* check for varitems */ { currentitem[0] = '\0'; sscanf(sp,"%[^$]",currentitem); strcat(buffer,currentitem); sp += strlen(currentitem); if (*sp == '$') { switch (*(sp+1)) { case '(': varstring = ')'; break; case '{': varstring = '}'; break; default: strcat(buffer,"$"); continue; } sp++; } currentitem[0] = '\0'; if (*sp == '\0') { break; } else { sprintf(scanstr,"%%[^%c]",varstring); /* select the correct terminator */ sscanf(++sp,scanstr,currentitem); /* reduce item */ switch (ScanVariable(currentitem)) { case cfbinserver: if (ExpandOverflow(buffer,bserver)) { FatalError("Can't expand varstring"); } strcat(buffer,bserver); break; } sp += strlen(currentitem); currentitem[0] = '\0'; } } return varstring; } /*********************************************************************/ enum vnames ScanVariable(char *name) { int i = nonexistentvar; for (i = 0; VVNAMES[i] != '\0'; i++) { if (strcmp(VVNAMES[i],ToLowerStr(name)) == 0) { return (enum vnames) i; } } return (enum vnames) i; } /*********************************************************************/ struct Item *SplitVarstring(char *string) /* Splits a string containing a separator like : into a linked list of separate items, */ { struct Item *liststart = NULL, *ip; char *sp; char before[CF_BUFSIZE],var[CF_BUFSIZE],exp[CF_EXPANDSIZE]; int i = 0; Debug("SplitVarstring([%s])\n",string); if (strlen(string) == 0) { AppendItem(&liststart,string,NULL); return liststart; } for (sp = string; (*sp != '\0') ; sp++,i++) { var[0] = '\0'; exp[0] = '\0'; if (*sp == '$') { if (ExtractOuterVarString(sp,var)) { before[i] = '\0'; if (strlen(before) > 0) { AppendItem(&liststart,before,NULL); } ExpandVarstring(var,exp,NULL); AppendItem(&liststart,exp,NULL); sp += strlen(var)-1; before[0] = '\0'; i = -1; } else { before[i] = *sp; } } else { before[i] = *sp; } } before[i] = '\0'; if (strlen(before) > 0) { AppendItem(&liststart,before,NULL); } return liststart; } /*********************************************************************/ struct Item *SplitString(char *string,char sep) /* Splits a string containing a separator like : into a linked list of separate items, */ { struct Item *liststart = NULL; char *sp; char before[CF_BUFSIZE]; int i = 0; Debug("SplitString([%s],%c=%d)\n",string,sep,sep); for (sp = string; (*sp != '\0') ; sp++,i++) { before[i] = *sp; if (*sp == sep) { /* Check the listsep is not escaped*/ if ((sp > string) && (*(sp-1) != '\\')) { before[i] = '\0'; AppendItem(&liststart,before,NULL); i = -1; } else if ((sp > string) && (*(sp-1) == '\\')) { i--; before[i] = sep; } else { before[i] = '\0'; AppendItem(&liststart,before,NULL); i = -1; } } } before[i] = '\0'; AppendItem(&liststart,before,""); return liststart; } /*********************************************************/ int IsListVar(char *name,char sep) { char test[CF_EXPANDSIZE]; char *sp; ExpandVarstring(name,test,NULL); for (sp = test; *sp != '\0'; sp++) { if (*sp == sep) { return true; } } return false; } /*********************************************************************/ int VarListLen(char *name, char sep) { int count = 0; char *sp; for (sp = name; *sp != '\0'; sp++) { if (*sp == sep) { count++; } } return count+1; } /*********************************************************************/ void GetSepElement(char *from,char *to,int index,char sep) { char *sps,*spe; char buf[CF_BUFSIZE]; int i; strcpy(buf,from); sps = buf; for (i = 0; i < index; i++) { while ((*sps != sep) && (*sps != '\0')) { sps++; } if (*sps == ':') { sps++; } } if (*sps == '\0') { strncpy(to,from,CF_BUFSIZE-1); return; } if (*sps == ':') { strncpy(to,sps+1,CF_BUFSIZE-1); } else { strncpy(to,sps,CF_BUFSIZE-1); } spe = to; while ((*spe != sep) && (*spe != '\0')) { spe++; } *spe = '\0'; Debug("Extracted [%s] from [%s]\n",to,from); } cfengine-2.2.10/src/expand-files.c0000644000175000001440000001067410662303616013614 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /*****************************************************************************/ /* */ /* File: expand-files.c */ /* */ /*****************************************************************************/ int RecursiveCheck(char *name,int recurse,int rlevel,struct File *ptr,struct stat *sb) { DIR *dirh; int goback; struct dirent *dirp; char pcwd[CF_BUFSIZE]; struct stat statbuf; if (recurse == -1) { return false; } if (rlevel > CF_RECURSION_LIMIT) { snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING: Very deep nesting of directories (>%d deep): %s (Aborting files)",rlevel,name); CfLog(cferror,OUTPUT,""); return false; } memset(pcwd,0,CF_BUFSIZE); Debug("RecursiveCheck(%s,+%o,-%o)\n",name,ptr->plus,ptr->minus); if (!DirPush(name,sb)) { return false; } if ((dirh = opendir(".")) == NULL) { if (lstat(name,&statbuf) != -1) { CheckExistingFile("*",name,&statbuf,ptr); } return true; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,name,NULL)) { continue; } if (IgnoreFile(name,dirp->d_name,ptr->ignores)) { continue; } strcpy(pcwd,name); /* Assemble pathname */ AddSlash(pcwd); if (BufferOverflow(pcwd,dirp->d_name)) { closedir(dirh); return true; } strcat(pcwd,dirp->d_name); if (lstat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"RecursiveCheck was looking at %s when this happened:\n",pcwd); CfLog(cfverbose,OUTPUT,"lstat"); continue; } if (TRAVLINKS) { if (lstat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",pcwd); CfLog(cfinform,OUTPUT,"stat"); continue; } if (S_ISLNK(statbuf.st_mode) && (statbuf.st_mode != getuid())) { snprintf(OUTPUT,CF_BUFSIZE,"File %s is an untrusted link. cfagent will not follow it with a destructive operation (tidy)",pcwd); continue; } if (stat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"RecursiveCheck was working on %s when this happened:\n",pcwd); CfLog(cferror,OUTPUT,"stat"); continue; } } if (ptr->xdev =='y' && DeviceChanged(statbuf.st_dev)) { Verbose("Skipping %s on different device\n",pcwd); continue; } if (S_ISLNK(statbuf.st_mode)) /* should we ignore links? */ { CheckExistingFile("*",pcwd,&statbuf,ptr); continue; } if (S_ISDIR(statbuf.st_mode)) { if (IsMountedFileSystem(&statbuf,pcwd,rlevel)) { continue; } else { if ((ptr->recurse > 1) || (ptr->recurse == CF_INF_RECURSE)) { CheckExistingFile("*",pcwd,&statbuf,ptr); goback = RecursiveCheck(pcwd,recurse-1,rlevel+1,ptr,&statbuf); DirPop(goback,name,sb); } else { CheckExistingFile("*",pcwd,&statbuf,ptr); } } } else { CheckExistingFile("*",pcwd,&statbuf,ptr); } } closedir(dirh); return true; } cfengine-2.2.10/src/2Dlist.c0000644000175000001440000001705010756631655012404 00000000000000/* cfengine for GNU Copyright (C) 1995/6 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*********************************************************************/ /* */ /* TOOLKIT: the "2Dlist" object library for cfengine */ /* uses (inherits) item.c */ /* */ /*********************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /* private */ #define TD_wrapped 1 #define TD_nowrap 2 /*********************************************************************/ /* TOOLKIT : 2D list */ /*********************************************************************/ /* The 2D structure is a list of varstring fragments each of which contains one variable. Each variable could be a list, and the list variables are expanded into the ilist members of the 2D list. The trick in extracting data is how the increment function works..*/ /*********************************************************************/ void Set2DList(struct TwoDimList *list) { struct TwoDimList *tp; Debug1("Set2DLIst()\n"); for (tp = list; tp != NULL; tp=tp->next) { tp->current = tp->ilist; } } /*********************************************************************/ char *Get2DListEnt(struct TwoDimList *list) /* return a path string in static data, like getent in NIS */ { static char entry[CF_EXPANDSIZE]; struct TwoDimList *tp; char seps[2]; if (EndOfTwoDimList(list)) { return NULL; } Debug1("Get2DListEnt()\n"); memset(entry,0,CF_BUFSIZE); for (tp = list; tp != NULL; tp=tp->next) { if (tp->current != NULL) { if (strlen(entry)+strlen((tp->current)->name) < CF_EXPANDSIZE - CF_BUFFERMARGIN) { strcat(entry,(tp->current)->name); } else { FatalError("Buffer overflow during variable expansion"); } } } Debug("Get2DListEnt returns %s\n",entry); if (list->tied) { TieIncrementTwoDimList(list); } else { IncrementTwoDimList(list); } return entry; } /*********************************************************************/ void Build2DListFromVarstring(struct TwoDimList **TwoDimlist, char *varstring, char sep, short tied) { struct Item *ip, *basis; char *sp; Debug1("Build2DListFromVarstring([%s],sep=[%c])\n",varstring,sep); if (varstring == NULL) { AppendTwoDimItem(TwoDimlist,NULL); return; } if (sp = strchr(varstring,sep)) { if (sp == varstring || (sp > varstring && *(sp-1) != '\\')) { snprintf(OUTPUT,CF_BUFSIZE,"Warning: varstring \"%s\" contains the list iterator \'%c\' - you should escape these close to non-separator characters so they don't get lost! (e.g. /bin/echo\\%c )",varstring,sep,sep); CfLog(cferror,OUTPUT,""); } } basis = SplitVarstring(varstring); for (ip = basis; ip != NULL; ip=ip->next) { /* Expand the list variables in each slot */ AppendTwoDimItem(TwoDimlist,SplitString(ip->name,sep)); } if (TwoDimlist && *TwoDimlist) { /* Policy for expansion of lists */ (*TwoDimlist)->tied = tied; } } /*********************************************************************/ int IncrementTwoDimList (struct TwoDimList *from) /* This works be recursive descent from left to right, like a mileometer */ { struct TwoDimList *tp; Debug1("IncrementTwoDimList()\n"); for (tp = from; tp != NULL; tp=tp->next) { if (tp->is2d) { break; /* first fragment with more than one value in list */ } } if (tp == NULL) { return TD_wrapped; /* End of cycle */ } /* Current points to our position in the sublist of each fragment */ if (IncrementTwoDimList(tp->next) == TD_wrapped) { tp->current = (tp->current)->next; if (tp->current == NULL) { /* Wrap to beginning again, count round robins to check eolist */ tp->current = tp->ilist; tp->rounds++; return TD_wrapped; } else { return TD_nowrap; } } return TD_nowrap; /* Shouldn't get here */ } /*********************************************************************/ int TieIncrementTwoDimList (struct TwoDimList *from) { struct TwoDimList *tp; /* March all pointers in time */ for (tp = from; tp != NULL; tp=tp->next) { if (tp->is2d) { tp->current = tp->current->next; if (tp->current == NULL) { /* Signal the round robin cycle ends */ tp->rounds = 1; } } else { tp->rounds = 1; } } return TD_wrapped; /* Means nothing here */ } /*********************************************************************/ int EndOfTwoDimList(struct TwoDimList *list) /* bool */ /* returns true if the leftmost list variable has cycled */ /* i.e. rounds is > 0 for the first is-2d list item */ { struct TwoDimList *lp, *tp = NULL; int i = 0, done = true; for (lp = list; lp != NULL; lp=lp->next) { if (lp->is2d) { tp = lp; } if (lp->rounds == 0) { done = false; } } if (done || (list == NULL)) { return true; } if (tp == NULL) /* Need a case when there are no lists! */ { if (list->rounds == 0) { list->rounds = 1; return false; } else { return true; } } if (tp->rounds > 0) { return true; } else { return false; } } /*********************************************************************/ void AppendTwoDimItem(struct TwoDimList **liststart,struct Item *itemlist) { struct TwoDimList *ip, *lp; Debug("\nAppendTwoDimItem()\n"); if (liststart == NULL) { Debug("SOFTWARE ERROR in AppendTwoDimItem()\n "); return; } if ((ip = (struct TwoDimList *)malloc(sizeof(struct TwoDimList))) == NULL) { CfLog(cferror,"AppendTwoDimItem","malloc"); FatalError(""); } if (*liststart == NULL) { *liststart = ip; } else { for (lp = *liststart; lp->next != NULL; lp=lp->next) { } lp->next = ip; } ip->ilist = itemlist; ip->current = itemlist; /* init to start of list - steps through these */ ip->next = NULL; ip->rounds = 0; ip->tied = 0; if (itemlist == NULL || itemlist->next == NULL) { ip->is2d = false; } else { ip->is2d = true; /* List has more than one element */ } } /*********************************************************************/ void Delete2DList(struct TwoDimList *item) { if (item != NULL) { Delete2DList(item->next); item->next = NULL; DeleteItemList(item->ilist); free((char *)item); } } cfengine-2.2.10/src/sockaddr.c0000644000175000001440000001120210761474333013020 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: sockaddr.c */ /* */ /* Created: Fri Jan 23 21:07:05 2004 */ /* */ /* Author: > */ /* */ /* Revision: $Id$ */ /* */ /* Description: */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include "../pub/global.h" /*****************************************************************************/ /* TOOLKIT */ /* INET independent address/struct conversion routines */ /*****************************************************************************/ char *sockaddr_ntop(struct sockaddr *sa) { #if defined(HAVE_GETADDRINFO) static char addrbuf[INET6_ADDRSTRLEN]; void *addr; #else static char addrbuf[20]; struct in_addr addr; #endif switch (sa->sa_family) { case AF_INET: Debug("IPV4 address\n"); snprintf(addrbuf,20,"%.19s",inet_ntoa(((struct sockaddr_in *)sa)->sin_addr)); break; #ifdef AF_LOCAL case AF_LOCAL: Debug("Local socket\n") ; strcpy(addrbuf, "127.0.0.1") ; break; #endif #if defined(HAVE_GETADDRINFO) case AF_INET6: Debug("IPV6 address\n"); addr = &((struct sockaddr_in6 *)sa)->sin6_addr; inet_ntop(sa->sa_family,addr,addrbuf,sizeof(addrbuf)); break; #endif default: Debug("Address family was %d\n",sa->sa_family); FatalError("Software failure in sockaddr_ntop\n"); } Debug("sockaddr_ntop(%s)\n",addrbuf); return addrbuf; } /*****************************************************************************/ /* Example: struct sockaddr_in *p; struct sockaddr_in6 *p6; p = (struct sockaddr_in *) sockaddr_pton(AF_INET,"128.39.89.10"); p6 = (struct sockaddr_in6 *) sockaddr_pton(AF_INET6,"2001:700:700:3:290:27ff:fea2:477b"); printf("Coded %s\n",sockaddr_ntop((struct sockaddr *)p)); */ /*****************************************************************************/ void *sockaddr_pton(int af,void *src) { int err; #if defined(HAVE_GETADDRINFO) static struct sockaddr_in6 adr6; #endif static struct sockaddr_in adr; switch (af) { case AF_INET: memset(&adr,0,sizeof(adr)); adr.sin_family = AF_INET; adr.sin_addr.s_addr = inet_addr(src); Debug("Coded ipv4 %s\n",sockaddr_ntop((struct sockaddr *)&adr)); return (void *)&adr; #if defined(HAVE_GETADDRINFO) case AF_INET6: memset(&adr6,0,sizeof(adr6)); adr6.sin6_family = AF_INET6; err = inet_pton(AF_INET6,src,&(adr6.sin6_addr)); if (err > 0) { Debug("Coded ipv6 %s\n",sockaddr_ntop((struct sockaddr *)&adr6)); return (void *)&adr6; } else { return NULL; } break; #endif default: Debug("Address family was %d\n",af); FatalError("Software failure in sockaddr_pton\n"); } return NULL; } cfengine-2.2.10/src/cfrun.c0000644000175000001440000005315611144464127012355 00000000000000/* Copyright (C) 1995,96,97 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Cfengine : remote client example */ /* */ /* Mark Burgess 1997 */ /* modified : Bas van der Vlies 1998 */ /* modified : Andrew Mayhew 2000 */ /* modified : Mark 2002, Bas 2002 */ /* modified : Jochen Reinwand 2002 */ /* */ /*******************************************************************/ #define FileVerbose if (VERBOSE || DEBUG || D2) fprintf #include "cf.defs.h" #include "cf.extern.h" enum fileoutputlevels { fopl_normal, fopl_error, fopl_inform }; int MAXCHILD = 1; int FileFlag = 0; int TRUSTALL = false; enum fileoutputlevels OUTPUTLEVEL = fopl_normal; char OUTPUTDIR[CF_BUFSIZE]; char INCLUDEFILE[CF_BUFSIZE]; struct Item *VCFRUNCLASSES = NULL; struct Item *VCFRUNOPTIONHOSTS = NULL; struct Item *VCFRUNHOSTLIST = NULL; char VCFRUNHOSTS[CF_BUFSIZE] = "cfrun.hosts"; char CFRUNOPTIONS[CF_BUFSIZE]; char CFLOCK[CF_BUFSIZE] = "dummy"; /*******************************************************************/ /* Functions internal to cfrun.c */ /*******************************************************************/ void CheckOptsAndInit (int argc,char **argv); int PollServer (char *host, char *options, int storeinfile); void SendClassData (int sd, char *sendbuffer); void CheckAccess (char *users); void cfrunSyntax (void); void ReadCfrunConf (char* cfg_fic); int ParseHostname (char *hostname, char *new_hostname); void FileOutput (FILE *fp, enum fileoutputlevels level, char *message); /*******************************************************************/ /* Level 0 : Main */ /*******************************************************************/ int main (int argc,char **argv) { struct Item *ip; int i=0; int status; int pid; SetContext("cfrun"); CheckOptsAndInit(argc,argv); ip = VCFRUNHOSTLIST; while (ip != NULL) { if (i < MAXCHILD) { if (fork() == 0) /* child */ { ALARM_PID = -1; printf("cfrun(%d): .......... [ Hailing %s ] ..........\n",i,ip->name); Debug("pid = %d i = %d\n", getpid(), i); if (PollServer(ip->name,ip->classes, FileFlag)) { Verbose("Connection with %s completed\n\n",ip->name); } else { Verbose("Connection refused...\n\n"); } exit(0); } else { /* parent */ i++; } } else { pid = wait(&status); Debug("wait result pid = %d number %d\n", pid, i); i--; } if ( i < MAXCHILD ) { ip = ip->next; } } while (i > 0) { pid = wait(&status); Debug("Child pid = %d ended\n", pid); i--; } exit(0); return 0; } /********************************************************************/ /* Level 1 */ /********************************************************************/ void CheckOptsAndInit(int argc,char **argv) { int optgroup = 0, i; struct Item *ip; /* Separate command args into options and classes */ memset(CFRUNOPTIONS,0,CF_BUFSIZE); for (i = 1; i < argc; i++) { if (optgroup == 0) { if (strncmp(argv[i],"-h",2) == 0) { cfrunSyntax(); } else if (strncmp(argv[i],"-f",2) == 0) { i++; if ((i >= argc) || (strncmp(argv[i],"-",1) == 0)) { printf("Error: No filename listed after -f option.\n"); cfrunSyntax(); exit(0); } memset(VCFRUNHOSTS,0,CF_BUFSIZE); strncat(VCFRUNHOSTS,argv[i],CF_BUFSIZE-1-strlen(VCFRUNHOSTS)); Debug("cfrun: cfrun file = %s\n",VCFRUNHOSTS); } else if (strncmp(argv[i],"-d",2) == 0) { DEBUG = true; VERBOSE = true; } else if (strncmp(argv[i],"-v",2) == 0) { VERBOSE=true; } else if (strncmp(argv[i],"-T",2) == 0) { TRUSTALL = true; } else if (strncmp(argv[i],"-S",2) == 0) { SILENT = true; } else if (strncmp(argv[i],"--",2) == 0) { optgroup++; } else if (argv[i][0] == '-') { printf("Error: Unknown option.\n"); cfrunSyntax(); exit(0); } else { AppendItem(&VCFRUNOPTIONHOSTS,argv[i],NULL); /* Restrict run hosts */ } } else if (optgroup == 1) { if (strncmp(argv[i],"--",2) == 0) { optgroup++; } else { strncat(CFRUNOPTIONS,argv[i],CF_BUFSIZE-1-strlen(CFRUNOPTIONS)); strncat(CFRUNOPTIONS," ",CF_BUFSIZE-1-strlen(CFRUNOPTIONS)); } } else { AppendItem(&VCFRUNCLASSES,argv[i],""); } } Debug("CFRUNOPTIONS string: %s\n",CFRUNOPTIONS); for (ip = VCFRUNCLASSES; ip != NULL; ip=ip->next) { Debug("Class item: %s\n",ip->name); } /* XXX Initialize workdir for non privileged users */ strcpy(CFWORKDIR,WORKDIR); #ifndef NT if (getuid() > 0) { char *homedir; if ((homedir = getenv("HOME")) != NULL) { strncpy(CFWORKDIR,homedir,CF_BUFSIZE-16); strcat(CFWORKDIR,"/.cfagent"); } } #endif ReadCfrunConf(VCFRUNHOSTS); GetNameInfo(); CfenginePort(); StrCfenginePort(); Debug("FQNAME = %s, WORKDIR = %s\n",VFQNAME,WORKDIR); sprintf(VPREFIX,"cfrun:%s",VFQNAME); /* Read hosts file */ umask(077); strcpy(VLOCKDIR,CFWORKDIR); strcpy(VLOGDIR,CFWORKDIR); OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); CheckWorkDirectories(); LoadSecretKeys(); RandomSeed(); } /********************************************************************/ int PollServer(char *host,char *options,int storeinfile) { struct hostent *hp; struct sockaddr_in raddr; char sendbuffer[CF_BUFSIZE],recvbuffer[CF_BUFSIZE]; char filebuffer[CF_BUFSIZE],parsed_host[CF_BUFSIZE]; char reply[8]; struct servent *server; int err,n_read,first,port; char *sp,forceipv4='n'; void *gotkey; FILE *fp; struct Image addresses; #ifdef HAVE_GETADDRINFO struct addrinfo query, *response=NULL, *ap; #endif char strport[16]; CONN = NewAgentConn(); if (storeinfile) { sprintf(filebuffer, "%s/%s", OUTPUTDIR, host); if ((fp = fopen(filebuffer, "w")) == NULL) { return false; } } else { fp = stdout; } port = ParseHostname(host,parsed_host); FileVerbose(fp, "Connecting to server %s to port %d with options %s %s\n",parsed_host,port,options,CFRUNOPTIONS); #ifdef HAVE_GETADDRINFO Debug("Using v6 compatible lookup...\n"); if (port) { snprintf(strport,15,"%u",port); } else { snprintf(strport,15,"%s",STR_CFENGINEPORT); } memset(&query,0,sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; query.ai_flags = AI_PASSIVE; if ((err = getaddrinfo(parsed_host,strport,&query,&response)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to lookup %s (%s)",parsed_host,gai_strerror(err)); CfLog(cferror,OUTPUT,""); } for (ap = response; ap != NULL; ap = ap->ai_next) { snprintf(CONN->remoteip,CF_MAX_IP_LEN,"%s",sockaddr_ntop(ap->ai_addr)); break; } if (response != NULL) { freeaddrinfo(response); } #else if ((hp = gethostbyname(parsed_host)) == NULL) { printf("Unknown host: %s\n", parsed_host); printf("Make sure that fully qualified names can be looked up at your site!\n"); printf("i.e. www.gnu.org, not just www. If you use NIS or /etc/hosts\n"); printf("make sure that the full form is registered too as an alias!\n"); FileOutput(fp, fopl_error, "Unknown host\n"); exit(1); } memset(&raddr,0,sizeof(raddr)); if (port) { raddr.sin_port = htons(port); } else { CfenginePort(); raddr.sin_port = SHORT_CFENGINEPORT; } raddr.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; raddr.sin_family = AF_INET; snprintf(CONN->remoteip,CF_MAX_IP_LEN,"%s",inet_ntoa(raddr.sin_addr)); #endif addresses.trustkey = 'n'; addresses.encrypt = 'n'; addresses.server = strdup(parsed_host); snprintf(sendbuffer,CF_BUFSIZE,"root-%s",parsed_host); gotkey = HavePublicKey(sendbuffer); if (!gotkey) { snprintf(sendbuffer,CF_BUFSIZE,"root-%s",CONN->remoteip); gotkey = HavePublicKey(sendbuffer); } if (!gotkey) { if (TRUSTALL) { printf("Accepting public key from %s\n",parsed_host); FileOutput(fp, fopl_inform, "Accepting public key from host\n"); addresses.trustkey = 'y'; } else { printf("WARNING - You do not have a public key from host %s = %s\n",host,CONN->remoteip); printf(" Do you want to accept one on trust? (yes/no)\n\n--> "); while (true) { fgets(reply,8,stdin); Chop(reply); if (strcmp(reply,"yes")==0) { addresses.trustkey = 'y'; break; } else if (strcmp(reply,"no")==0) { break; } else { printf("Please reply yes or no...(%s)\n",reply); } } } } if (!RemoteConnect(parsed_host,forceipv4,port,strport)) { snprintf(OUTPUT,CF_BUFSIZE,"No response hailing %s\n",parsed_host); CfLog(cferror,OUTPUT,"socket"); FileOutput(fp, fopl_error,OUTPUT); if (CONN->sd != CF_NOT_CONNECTED) { close(CONN->sd); CONN->sd = CF_NOT_CONNECTED; } free(addresses.server); return false; } if (!IdentifyForVerification(CONN->sd,CONN->localip,CONN->family)) { snprintf(OUTPUT,CF_BUFSIZE,"Hail succeeded, but unable to open channel to %s\n",parsed_host); CfLog(cferror,OUTPUT,"socket"); FileOutput(fp, fopl_error,OUTPUT); close(CONN->sd); errno = EPERM; free(addresses.server); return false; } if (!KeyAuthentication(&addresses)) { snprintf(OUTPUT,CF_BUFSIZE,"Key-authentication for %s failed\n",VFQNAME); CfLog(cferror,OUTPUT,""); FileOutput(fp, fopl_error, "Key-authentication failed\n"); errno = EPERM; close(CONN->sd); free(addresses.server); return false; } snprintf(sendbuffer,CF_BUFSIZE,"EXEC %s %s",options,CFRUNOPTIONS); if (SendTransaction(CONN->sd,sendbuffer,0,CF_DONE) == -1) { printf("Transmission rejected"); FileOutput(fp, fopl_error, "Transmission rejected\n"); close(CONN->sd); free(addresses.server); return false; } SendClassData(CONN->sd,sendbuffer); FileVerbose(fp, "%s replies..\n\n",parsed_host); first = true; while (true) { memset(recvbuffer,0,CF_BUFSIZE); if ((n_read = ReceiveTransaction(CONN->sd,recvbuffer,NULL)) == -1) { if (errno == EINTR) { continue; } close(CONN->sd); free(addresses.server); return true; } if ((sp = strstr(recvbuffer,CFD_TERMINATOR)) != NULL) { *sp = '\0'; fprintf(fp,"%s",recvbuffer); break; } if ((sp = strstr(recvbuffer,"BAD:")) != NULL) { *sp = '\0'; fprintf(fp,"%s",recvbuffer+4); } if (n_read == 0) { if (!first) { fprintf(fp,"\n"); } break; } if (strlen(recvbuffer) == 0) { continue; } if (strstr(recvbuffer,"too soon")) { FileVerbose(fp,"%s",recvbuffer); } if (strstr(recvbuffer,"cfXen")) { fprintf(fp,"- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n"); continue; } if (first) { fprintf(fp,"\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n"); } first = false; fprintf(fp,"%s",recvbuffer); } if (!first) { fprintf(fp,"- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n"); } close(CONN->sd); free(addresses.server); return true; } /********************************************************************/ /* Level 2 */ /********************************************************************/ void ReadCfrunConf(char* cfg_fic) { char filename[CF_BUFSIZE], *sp; char buffer[CF_MAXVARSIZE], options[CF_BUFSIZE], line[CF_BUFSIZE]; FILE *fp; struct Item *ip; memset(filename,0,CF_BUFSIZE); if (!strchr(VCFRUNHOSTS, '/')) { if ((sp=getenv(CF_INPUTSVAR)) != NULL) { strcpy(filename,sp); if (filename[strlen(filename)-1] != '/') { strcat(filename,"/"); } } else { snprintf(filename, CF_BUFSIZE, "%s/inputs/", CFWORKDIR); } } strcat(filename,cfg_fic); if ((fp = fopen(filename,"r")) == NULL) /* Open root file */ { printf("Unable to open %s\n",filename); return; } while (!feof(fp)) { memset(buffer,0,CF_MAXVARSIZE); memset(options,0,CF_BUFSIZE); memset(line,0,CF_BUFSIZE); ReadLine(line,CF_BUFSIZE,fp); if (strncmp(line,"domain",6) == 0) { sscanf(line,"domain = %295[^# \n]",VDOMAIN); Verbose("Domain name = %s\n",VDOMAIN); continue; } if (strncmp(line,"hostnamekeys",6) == 0) { char buf[256]; buf[0] = '\0'; sscanf(line,"hostnamekeys = %255[^# \n]",buf); Verbose("Hostname keys\n"); if (strcmp(buf,"yes") == 0||strcmp(buf,"true") == 0) { AddMacroValue(CONTEXTID,"HostnameKeys","true"); } continue; } if (strncmp(line,"maxchild", strlen("maxchild")) == 0) { sscanf(line,"maxchild = %295[^# \n]", buffer); if ( (MAXCHILD = atoi(buffer)) == 0 ) { MAXCHILD = 1; } Verbose("cfrun: maxchild = %d\n", MAXCHILD); continue; } if (strncmp(line,"outputdir", strlen("outputdir")) == 0) { sscanf(line,"outputdir = %295[^# \n]", OUTPUTDIR); Verbose("cfrun: outputdir = %s\n", OUTPUTDIR); if ( opendir(OUTPUTDIR) == NULL) { printf("Directory %s does not exists\n", OUTPUTDIR); exit(1); } FileFlag=1; continue; } if (strncmp(line,"outputlevel", strlen("outputlevel")) == 0) { sscanf(line,"outputlevel = %295[^# \n]", buffer); if (strncmp(buffer,"inform", strlen("inform")) == 0) { OUTPUTLEVEL = fopl_inform; Verbose("cfrun: outputlevel = inform"); } else if (strncmp(buffer,"error", strlen("error")) == 0) { OUTPUTLEVEL = fopl_error; Verbose("cfrun: outputlevel = error"); } else if (strncmp(buffer,"normal", strlen("normal")) == 0) { OUTPUTLEVEL = fopl_normal; Verbose("cfrun: outputlevel = normal"); } else { printf("Invalid outputlevel: %s\n", OUTPUTDIR); } continue; } if (strncmp(line,"include", strlen("include")) == 0) { sscanf(line,"include = %295[^# \n]", INCLUDEFILE); Verbose("cfrun: include = %s\n", INCLUDEFILE); ReadCfrunConf(INCLUDEFILE); continue; } if (strncmp(line,"access",6) == 0) { for (sp = line; (*sp != '=') && (*sp != '\0'); sp++) { } if (*sp == '\0' || *(++sp) == '\0') { continue; } CheckAccess(sp); continue; } if (strncmp(line,"bindtointerface",strlen("bindtointerface")) == 0) { sscanf(line,"bindtointerface = %295[^# \n]",BINDINTERFACE); Verbose("Bind interface = %s\n",BINDINTERFACE); continue; } sscanf(line,"%295s %[^#\n]",buffer,options); if (buffer[0] == '#') { continue; } if (strlen(buffer) == 0) { continue; } if (VCFRUNOPTIONHOSTS != NULL && !IsItemIn(VCFRUNOPTIONHOSTS,buffer)) { Verbose("Skipping host %s\n",buffer); continue; } if ((!strstr(buffer,".")) && (strlen(VDOMAIN) > 0)) { strcat(buffer,"."); strcat(buffer,VDOMAIN); } if (!IsItemIn(VCFRUNHOSTLIST,buffer)) { AppendItem(&VCFRUNHOSTLIST,buffer,options); } } for (ip = VCFRUNHOSTLIST; ip != NULL; ip=ip->next) { Debug("host item: %s (%s)\n",ip->name,ip->classes); } fclose(fp); } /********************************************************************/ int ParseHostname(char *hostname,char *new_hostname) { int port=5308; sscanf(hostname,"%[^:]:%d", new_hostname, &port); return(port); } /********************************************************************/ void SendClassData(int sd,char *sendbuffer) { struct Item *ip; int used; char *sp; sp = sendbuffer; used = 0; memset(sendbuffer,0,CF_BUFSIZE); for (ip = VCFRUNCLASSES; ip != NULL; ip = ip->next) { if (used + strlen(ip->name) +2 > CF_BUFSIZE) { if (SendTransaction(sd,sendbuffer,0,CF_DONE) == -1) { perror("send"); return; } used = 0; sp = sendbuffer; memset(sendbuffer,0,CF_BUFSIZE); } strncat(sendbuffer,ip->name,CF_BUFSIZE-CF_BUFFERMARGIN); strcat(sendbuffer," "); sp += strlen(ip->name)+1; used += strlen(ip->name)+1; } if (used + strlen(CFD_TERMINATOR) +2 > CF_BUFSIZE) { if (SendTransaction(sd,sendbuffer,0,CF_DONE) == -1) { perror("send"); return; } used = 0; sp = sendbuffer; memset(sendbuffer,0,CF_BUFSIZE); } sprintf(sp, "%s", CFD_TERMINATOR); if (SendTransaction(sd,sendbuffer,0,CF_DONE) == -1) { perror("send"); return; } } /********************************************************************/ void CheckAccess(char *users) { char id[CF_MAXVARSIZE], *sp; struct passwd *pw; int uid,myuid; myuid = getuid(); if (myuid == 0) { return; } for (sp = users; *sp != '\0'; sp++) { id[0] = '\0'; sscanf(sp,"%295[^,:]",id); sp += strlen(id); if (isalpha((int)id[0])) { if ((pw = getpwnam(id)) == NULL) { printf("cfrun: No such user (%s) in password database\n",id); continue; } if (pw->pw_uid == myuid) { return; } } else { uid = atoi(id); if (uid == myuid) { return; } } } printf("cfrun: you have not been granted permission to run cfrun\n"); exit(0); } /********************************************************************/ void FileOutput(FILE *fp,enum fileoutputlevels level,char *message) { switch (level) { case fopl_inform: if (OUTPUTLEVEL >= fopl_inform) { fprintf(fp, "cfrun: INFORM: %s", message); } break; case fopl_error: if (OUTPUTLEVEL >= fopl_error) { fprintf(fp, "cfrun: ERROR: %s", message); } break; /* Default is to do nothing. That's right for "normal"! */ } return; } /********************************************************************/ void cfrunSyntax() { printf("Usage: cfrun [-f cfrun.hosts|-h|-d|-S|-T|-v] [-- OPTIONS [-- CLASSES]]\n\n"); printf("-f cfrun.hosts\tcfrun file to read in list of hosts (see below for syntax.)\n"); printf("-h\t\tGet this help message.\n"); printf("-d\t\tDebug mode, turns on verbose as well.\n"); printf("-S\t\tSilent mode.\n"); printf("-T\t\tTrust all incoming public keys.\n"); printf("-v\t\tVerbose mode.\n"); printf("-- OPTIONS\tArguments to be passed to host application.\n"); printf("-- CLASSES\tClasses to be defined for the hosts.\n\n"); printf("e.g. cfrun -- -- linux Run on all linux machines\n"); printf(" cfrun -- -p Ping and parse on all hosts\n"); printf(" cfrun host1 host2 -- -p Ping and parse on named hosts\n"); printf(" cfrun -v -- -p Ping all, local verbose\n"); printf(" cfrun -v -- -k -- solaris Local verbose, all solaris, but no copy\n\n"); printf("cfrun.hosts file syntax:\n"); printf("# starts a comment\n"); printf("include = [file]\t# External cfrun.hosts file to include.\n"); printf("domain = [domain]\t# Domain to use for connection(s).\n"); printf("maxchild = [num]\t# Maximum number of children to spawn during run.\n"); printf("outputdir = [dir]\t# Directory where to put host output files.\n"); printf("access = [user]\t\t# User allowed to do cfrun?\n"); printf("[host]\t\t\t# One host per line list to cycle through.\n"); printf("\t\t\t# Only the hosts are required for cfrun to operate.\n"); exit(0); } cfengine-2.2.10/src/item.c0000644000175000001440000006742410761474333012205 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*********************************************************************/ /* */ /* TOOLKIT: the "item" object library for cfengine */ /* */ /*********************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ /* TOOLKIT : Item list */ /*********************************************************************/ int ListLen(struct Item *list) { int count = 0; struct Item *ip; Debug("Check ListLen\n"); for (ip = list; ip != NULL; ip=ip->next) { count++; } return count; } /*********************************************************************/ struct Item *String2List(char *string) { struct Item *liststart = NULL; AppendItem(&liststart,string,""); return liststart; } /*********************************************************************/ int ByteSizeList(struct Item *list) { int count = 0; struct Item *ip; for (ip = list; ip != NULL; ip=ip->next) { count+=strlen(ip->name); } return count; } /*********************************************************************/ int IsItemIn(struct Item *list,char *item) { struct Item *ptr; if ((item == NULL) || (strlen(item) == 0)) { return true; } for (ptr = list; ptr != NULL; ptr=ptr->next) { if (strcmp(ptr->name,item) == 0) { return(true); } } return(false); } /*********************************************************************/ int GetItemListCounter(struct Item *list,char *item) { struct Item *ptr; if ((item == NULL) || (strlen(item) == 0)) { return -1; } for (ptr = list; ptr != NULL; ptr=ptr->next) { if (strcmp(ptr->name,item) == 0) { return ptr->counter; } } return -1; } /*********************************************************************/ void IncrementItemListCounter(struct Item *list,char *item) { struct Item *ptr; if ((item == NULL) || (strlen(item) == 0)) { return; } for (ptr = list; ptr != NULL; ptr=ptr->next) { if (strcmp(ptr->name,item) == 0) { ptr->counter++; return; } } } /*********************************************************************/ void SetItemListCounter(struct Item *list,char *item,int value) { struct Item *ptr; if ((item == NULL) || (strlen(item) == 0)) { return; } for (ptr = list; ptr != NULL; ptr=ptr->next) { if (strcmp(ptr->name,item) == 0) { ptr->counter = value; return; } } } /*********************************************************************/ int IsFuzzyItemIn(struct Item *list,char *item) /* This is for matching ranges of IP addresses, like CIDR e.g. Range1 = ( 128.39.89.250/24 ) Range2 = ( 128.39.89.100-101 ) */ { struct Item *ptr; Debug("\nFuzzyItemIn(LIST,%s)\n",item); if ((item == NULL) || (strlen(item) == 0)) { return true; } for (ptr = list; ptr != NULL; ptr=ptr->next) { Debug(" Try FuzzySetMatch(%s,%s)\n",ptr->name,item); if (FuzzySetMatch(ptr->name,item) == 0) { return(true); } } return(false); } /*********************************************************************/ void CopyList (struct Item **dest, struct Item *source) /* Copy or concat lists */ { struct Item *ip; if (*dest != NULL) { FatalError("CopyList - list not initialized"); } if (source == NULL) { return; } for (ip = source; ip != NULL; ip = ip ->next) { AppendItem(dest,ip->name,ip->classes); } } /*********************************************************************/ struct Item *ConcatLists (struct Item *list1,struct Item *list2) /* Notes: * Refrain from freeing list2 after using ConcatLists * list1 must have at least one element in it */ { struct Item *endOfList1; if (list1 == NULL) { FatalError("ConcatLists: first argument must have at least one element"); } for (endOfList1=list1; endOfList1->next!=NULL; endOfList1=endOfList1->next) { } endOfList1->next = list2; return list1; } /*********************************************************************/ void PrependItem (struct Item **liststart,char *itemstring,char *classes) { struct Item *ip; char *sp,*spe = NULL; if (!PARSING && (ACTION == editfiles)) { snprintf(OUTPUT,CF_BUFSIZE,"Prepending [%s]\n",itemstring); CfLog(cfinform,OUTPUT,""); } else { EditVerbose("Prepending [%s]\n",itemstring); } if ((ip = (struct Item *)malloc(sizeof(struct Item))) == NULL) { CfLog(cferror,"","malloc"); FatalError(""); } if ((sp = malloc(strlen(itemstring)+2)) == NULL) { CfLog(cferror,"","malloc"); FatalError(""); } if ((classes != NULL) && (spe = malloc(strlen(classes)+2)) == NULL) { CfLog(cferror,"","malloc"); FatalError(""); } strcpy(sp,itemstring); ip->name = sp; ip->next = *liststart; ip->counter = 0; *liststart = ip; if (classes != NULL) { strcpy(spe,classes); ip->classes = spe; } else { ip->classes = NULL; } NUMBEROFEDITS++; } /*********************************************************************/ void AppendItems (struct Item **liststart,char *itemstring,char *classes) { char *sp; char currentitem[CF_MAXVARSIZE],local[CF_MAXVARSIZE]; if ((itemstring == NULL) || strlen(itemstring) == 0) { return; } memset(local,0,CF_MAXVARSIZE); strncpy(local,itemstring,CF_MAXVARSIZE-1); /* split and iteratate across the list with space and comma sep */ for (sp = local ; *sp != '\0'; sp++) { /* find our separating character */ memset(currentitem,0,CF_MAXVARSIZE); sscanf(sp,"%250[^ ,\n\t]",currentitem); if (strlen(currentitem) == 0) { continue; } /* add it to whatever list we're operating on */ Debug("Appending %s\n",currentitem); AppendItem(liststart,currentitem,classes); /* and move up to the next list */ sp += strlen(currentitem); } } /*********************************************************************/ void AppendItem (struct Item **liststart,char *itemstring,char *classes) { struct Item *ip, *lp; char *sp,*spe = NULL; if (!PARSING && (ACTION == editfiles)) { snprintf(OUTPUT,CF_BUFSIZE,"Appending [%s]\n",itemstring); CfLog(cfinform,OUTPUT,""); } else { EditVerbose("Appending [%s]\n",itemstring); } if ((ip = (struct Item *)malloc(sizeof(struct Item))) == NULL) { CfLog(cferror,"","malloc"); FatalError(""); } if ((sp = malloc(strlen(itemstring)+CF_EXTRASPC)) == NULL) { CfLog(cferror,"","malloc"); FatalError(""); } if (*liststart == NULL) { *liststart = ip; } else { for (lp = *liststart; lp->next != NULL; lp=lp->next) { } lp->next = ip; } if ((classes != NULL) && (spe = malloc(strlen(classes)+2)) == NULL) { CfLog(cferror,"","malloc"); FatalError(""); } strcpy(sp,itemstring); ip->name = sp; ip->next = NULL; ip->counter = 0; if (classes != NULL) { strcpy(spe,classes); ip->classes = spe; } else { ip->classes = NULL; } NUMBEROFEDITS++; } /*********************************************************************/ void InstallItem (struct Item **liststart,char *itemstring,char *classes,int ifelapsed,int expireafter) { struct Item *ip, *lp; char *sp,*spe = NULL; if (!PARSING && (ACTION == editfiles)) { snprintf(OUTPUT,CF_BUFSIZE,"Appending [%s]\n",itemstring); CfLog(cfinform,OUTPUT,""); } else { EditVerbose("Appending [%s]\n",itemstring); } if ((ip = (struct Item *)malloc(sizeof(struct Item))) == NULL) { CfLog(cferror,"","malloc"); FatalError(""); } if ((sp = malloc(strlen(itemstring)+CF_EXTRASPC)) == NULL) { CfLog(cferror,"","malloc"); FatalError(""); } if (*liststart == NULL) { *liststart = ip; } else { for (lp = *liststart; lp->next != NULL; lp=lp->next) { } lp->next = ip; } if ((classes!= NULL) && (spe = malloc(strlen(classes)+2)) == NULL) { CfLog(cferror,"","malloc"); FatalError(""); } strcpy(sp,itemstring); if (PIFELAPSED != -1) { ip->ifelapsed = PIFELAPSED; } else { ip->ifelapsed = ifelapsed; } if (PEXPIREAFTER != -1) { ip->expireafter = PEXPIREAFTER; } else { ip->expireafter = expireafter; } ip->name = sp; ip->next = NULL; if (classes != NULL) { strcpy(spe,classes); ip->classes = spe; } else { ip->classes = NULL; } ip->logaudit = AUDITP; ip->audit = AUDITPTR; ip->lineno = LINENUMBER; NUMBEROFEDITS++; } /*********************************************************************/ void DeleteItemList(struct Item *item) /* delete starting from item */ { if (item != NULL) { DeleteItemList(item->next); item->next = NULL; if (item->name != NULL) { Debug("Unappending %s\n",item->name); free (item->name); } if (item->classes != NULL) { free (item->classes); } free((char *)item); } } /*********************************************************************/ void DeleteItem(struct Item **liststart,struct Item *item) { struct Item *ip, *sp; if (item != NULL) { EditVerbose("Delete Item: %s\n",item->name); if (item->name != NULL) { free(item->name); } if (item->classes != NULL) { free(item->classes); } sp = item->next; if (item == *liststart) { *liststart = sp; } else { for (ip = *liststart; ip->next != item; ip=ip->next) { } ip->next = sp; } free((char *)item); NUMBEROFEDITS++; } } /*********************************************************************/ void DebugListItemList(struct Item *liststart) { struct Item *ptr; for (ptr = liststart; ptr != NULL; ptr=ptr->next) { printf("CFDEBUG: [%s]\n",ptr->name); } } /*********************************************************************/ int ItemListsEqual(struct Item *list1,struct Item *list2) { struct Item *ip1, *ip2; ip1 = list1; ip2 = list2; while (true) { if ((ip1 == NULL) && (ip2 == NULL)) { return true; } if ((ip1 == NULL) || (ip2 == NULL)) { return false; } if (strcmp(ip1->name,ip2->name) != 0) { return false; } ip1 = ip1->next; ip2 = ip2->next; } } /*********************************************************************/ /* Fuzzy Match */ /*********************************************************************/ int FuzzyMatchParse(char *s) { char *sp; short isCIDR = false, isrange = false, isv6 = false, isv4 = false, isADDR = false; char address[CF_ADDRSIZE]; int mask,count = 0; Debug("Check ParsingIPRange(%s)\n",s); for (sp = s; *sp != '\0'; sp++) /* Is this an address or hostname */ { if (!isxdigit((int)*sp)) { isADDR = false; break; } if (*sp == ':') /* Catches any ipv6 address */ { isADDR = true; break; } if (isdigit((int)*sp)) /* catch non-ipv4 address - no more than 3 digits */ { count++; if (count > 3) { isADDR = false; break; } } else { count = 0; } } if (! isADDR) { return true; } if (strstr(s,"/") != 0) { isCIDR = true; } if (strstr(s,"-") != 0) { isrange = true; } if (strstr(s,".") != 0) { isv4 = true; } if (strstr(s,":") != 0) { isv6 = true; } if (isv4 && isv6) { yyerror("Mixture of IPv6 and IPv4 addresses"); return false; } if (isCIDR && isrange) { yyerror("Cannot mix CIDR notation with xx-yy range notation"); return false; } if (isv4 && isCIDR) { if (strlen(s) > 4+3*4+1+2) /* xxx.yyy.zzz.mmm/cc */ { yyerror("IPv4 address looks too long"); return false; } address[0] = '\0'; mask = 0; sscanf(s,"%16[^/]/%d",address,&mask); if (mask < 8) { snprintf(OUTPUT,CF_BUFSIZE,"Mask value %d in %s is less than 8",mask,s); yyerror(OUTPUT); return false; } if (mask > 30) { snprintf(OUTPUT,CF_BUFSIZE,"Mask value %d in %s is silly (> 30)",mask,s); yyerror(OUTPUT); return false; } } if (isv4 && isrange) { long i, from = -1, to = -1; char *sp1,buffer1[CF_MAX_IP_LEN]; sp1 = s; for (i = 0; i < 4; i++) { buffer1[0] = '\0'; sscanf(sp1,"%[^.]",buffer1); sp1 += strlen(buffer1)+1; if (strstr(buffer1,"-")) { sscanf(buffer1,"%ld-%ld",&from,&to); if (from < 0 || to < 0) { yyerror("Error in IP range - looks like address, or bad hostname"); return false; } if (to < from) { yyerror("Bad IP range"); return false; } } } } if (isv6 && isCIDR) { char address[CF_ADDRSIZE]; int mask,blocks; if (strlen(s) < 20) { yyerror("IPv6 address looks too short"); return false; } if (strlen(s) > 42) { yyerror("IPv6 address looks too long"); return false; } address[0] = '\0'; mask = 0; sscanf(s,"%40[^/]/%d",address,&mask); blocks = mask/8; if (mask % 8 != 0) { CfLog(cferror,"Cannot handle ipv6 masks which are not 8 bit multiples (fix me)",""); return false; } if (mask > 15) { yyerror("IPv6 CIDR mask is too large"); return false; } } return true; } /*********************************************************************/ int FuzzySetMatch(char *s1,char *s2) /* Match two IP strings - with : or . in hex or decimal s1 is the test string, and s2 is the reference e.g. FuzzySetMatch("128.39.74.10/23","128.39.75.56") == 0 */ { short isCIDR = false, isrange = false, isv6 = false, isv4 = false; char address[CF_ADDRSIZE]; int mask; unsigned long a1,a2; if (strstr(s1,"/") != 0) { isCIDR = true; } if (strstr(s1,"-") != 0) { isrange = true; } if (strstr(s1,".") != 0) { isv4 = true; } if (strstr(s1,":") != 0) { isv6 = true; } if (strstr(s2,".") != 0) { isv4 = true; } if (strstr(s2,":") != 0) { isv6 = true; } if (isv4 && isv6) { /* This is just wrong */ return -1; } if (isCIDR && isrange) { snprintf(OUTPUT,CF_BUFSIZE,"Cannot mix CIDR notation with xxx-yyy range notation: %s",s1); CfLog(cferror,OUTPUT,""); return -1; } if (!(isv6 || isv4)) { snprintf(OUTPUT,CF_BUFSIZE,"Not a valid address range - or not a fully qualified name: %s",s1); CfLog(cferror,OUTPUT,""); return -1; } if (!(isrange||isCIDR)) { return strncmp(s1,s2,strlen(s1)); /* do partial string match */ } if (isv4) { struct sockaddr_in addr1,addr2; int shift; memset(&addr1,0,sizeof(struct sockaddr_in)); memset(&addr2,0,sizeof(struct sockaddr_in)); if (isCIDR) { address[0] = '\0'; mask = 0; sscanf(s1,"%16[^/]/%d",address,&mask); shift = 32 - mask; memcpy(&addr1,(struct sockaddr_in *) sockaddr_pton(AF_INET,address),sizeof(struct sockaddr_in)); memcpy(&addr2,(struct sockaddr_in *) sockaddr_pton(AF_INET,s2),sizeof(struct sockaddr_in)); a1 = htonl(addr1.sin_addr.s_addr); a2 = htonl(addr2.sin_addr.s_addr); a1 = a1 >> shift; a2 = a2 >> shift; if (a1 == a2) { return 0; } else { return -1; } } else { long i, from = -1, to = -1, cmp = -1; char *sp1,*sp2,buffer1[CF_MAX_IP_LEN],buffer2[CF_MAX_IP_LEN]; sp1 = s1; sp2 = s2; for (i = 0; i < 4; i++) { if (sscanf(sp1,"%[^.]",buffer1) <= 0) { break; } sp1 += strlen(buffer1)+1; sscanf(sp2,"%[^.]",buffer2); sp2 += strlen(buffer2)+1; if (strstr(buffer1,"-")) { sscanf(buffer1,"%ld-%ld",&from,&to); sscanf(buffer2,"%ld",&cmp); if (from < 0 || to < 0) { Debug("Couldn't read range\n"); return -1; } if ((from > cmp) || (cmp > to)) { Debug("Out of range %d > %d > %d (range %s)\n",from,cmp,to,buffer2); return -1; } } else { sscanf(buffer1,"%ld",&from); sscanf(buffer2,"%ld",&cmp); if (from != cmp) { Debug("Unequal\n"); return -1; } } Debug("Matched octet %s with %s\n",buffer1,buffer2); } Debug("Matched IP range\n"); return 0; } } #if defined(HAVE_GETADDRINFO) if (isv6) { struct sockaddr_in6 addr1,addr2; int blocks, i; memset(&addr1,0,sizeof(struct sockaddr_in6)); memset(&addr2,0,sizeof(struct sockaddr_in6)); if (isCIDR) { address[0] = '\0'; mask = 0; sscanf(s1,"%40[^/]/%d",address,&mask); blocks = mask/8; if (mask % 8 != 0) { CfLog(cferror,"Cannot handle ipv6 masks which are not 8 bit multiples (fix me)",""); return -1; } memcpy(&addr1,(struct sockaddr_in6 *) sockaddr_pton(AF_INET6,address),sizeof(struct sockaddr_in6)); memcpy(&addr2,(struct sockaddr_in6 *) sockaddr_pton(AF_INET6,s2),sizeof(struct sockaddr_in6)); for (i = 0; i < blocks; i++) /* blocks < 16 */ { if (addr1.sin6_addr.s6_addr[i] != addr2.sin6_addr.s6_addr[i]) { return -1; } } return 0; } else { long i, from = -1, to = -1, cmp = -1; char *sp1,*sp2,buffer1[CF_MAX_IP_LEN],buffer2[CF_MAX_IP_LEN]; sp1 = s1; sp2 = s2; for (i = 0; i < 8; i++) { sscanf(sp1,"%[^:]",buffer1); sp1 += strlen(buffer1)+1; sscanf(sp2,"%[^:]",buffer2); sp2 += strlen(buffer2)+1; if (strstr(buffer1,"-")) { sscanf(buffer1,"%lx-%lx",&from,&to); sscanf(buffer2,"%lx",&cmp); if (from < 0 || to < 0) { return -1; } if ((from >= cmp) || (cmp > to)) { printf("%x < %x < %x\n",from,cmp,to); return -1; } } else { sscanf(buffer1,"%ld",&from); sscanf(buffer2,"%ld",&cmp); if (from != cmp) { return -1; } } } return 0; } } #endif return -1; } /*********************************************************************/ /* Host Match */ /* written by steve rader */ /*********************************************************************/ int FuzzyHostParse(char *arg1,char *arg2) /* * do something like... * if ( $s !~ /^.*?\,\d+\-\d+$/ ) { return false; } * return true; */ { struct Item *args; long start = -1, end = -1, where = -1; int n; n = sscanf(arg2,"%ld-%ld%n",&start,&end,&where); if ( n != 2 ) { /* all other syntax errors */ yyerror("HostRange() syntax error: second arg should have X-Y format where X and Y are decimal numbers"); return false; } return true; } /*********************************************************************/ int FuzzyHostMatch(char *arg0, char* arg1, char *refhost) /* * do something like... * if ( $refhost !~ /(\d+)$/ ) { * return 1; # failure: refhost doesn't end in numeral * } * $hostnum = $1; * if ( $hostnum < $args[1] || $hostnum > $args[2] ) { * return 1; # failure: refhost hostnum not in range * } * $refhost =~ s/^(.*)\d.*$/$1/; * if ( $refhost ne $args[0] ) { * return 1; # failure: hostname doesn't match basename * } * return 0; # success */ { struct Item *args; char *sp, refbase[CF_MAXVARSIZE]; long cmp = -1, start = -1, end = -1; char buf1[CF_BUFSIZE], buf2[CF_BUFSIZE]; strncpy(refbase,refhost,CF_MAXVARSIZE-1); sp = refbase + strlen(refbase) - 1; while ( isdigit((int)*sp) ) { sp--; } sp++; sscanf(sp,"%ld",&cmp); *sp = '\0'; Debug("SRDEBUG FuzzyHostMatch: split refhost=%s into refbase=%s and cmp=%d\n",refhost,refbase,cmp); if (cmp < 0) { return 1; } if (strlen(refbase) == 0) { return 1; } sscanf(arg1,"%ld-%ld",&start,&end); if ( cmp < start || cmp > end ) { Debug("SRDEBUG Failed on numberical range (%d < %d < %d)\n",end,cmp,start); return 1; } strncpy(buf1,ToLowerStr(refbase),CF_BUFSIZE-1); strncpy(buf2,ToLowerStr(arg0),CF_BUFSIZE-1); if (strcmp(buf1,buf2) != 0) { Debug("SRDEBUG Failed on name (%s != %s)\n",buf1,buf2); return 1; } return 0; } /*********************************************************************/ /* String Handling */ /*********************************************************************/ struct Item *SplitStringAsItemList(char *string,char sep) /* Splits a string containing a separator like : into a linked list of separate items, */ { struct Item *liststart = NULL; char format[9], *sp; char node[CF_MAXVARSIZE]; Debug("SplitStringAsItemList(%s,%c)\n",string,sep); sprintf(format,"%%255[^%c]",sep); /* set format string to search */ for (sp = string; *sp != '\0'; sp++) { memset(node,0,CF_MAXVARSIZE); sscanf(sp,format,node); if (strlen(node) == 0) { continue; } sp += strlen(node)-1; AppendItem(&liststart,node,NULL); if (*sp == '\0') { break; } } return liststart; } /*******************************************************************/ /* Borrowed this algorithm from merge-sort implementation */ struct Item *SortItemListNames(struct Item *list) /* Alphabetical */ { struct Item *p, *q, *e, *tail, *oldhead; int insize, nmerges, psize, qsize, i; if (list == NULL) { return NULL; } insize = 1; while (true) { p = list; oldhead = list; /* only used for circular linkage */ list = NULL; tail = NULL; nmerges = 0; /* count number of merges we do in this pass */ while (p) { nmerges++; /* there exists a merge to be done */ /* step `insize' places along from p */ q = p; psize = 0; for (i = 0; i < insize; i++) { psize++; q = q->next; if (!q) { break; } } /* if q hasn't fallen off end, we have two lists to merge */ qsize = insize; /* now we have two lists; merge them */ while (psize > 0 || (qsize > 0 && q)) { /* decide whether next element of merge comes from p or q */ if (psize == 0) { /* p is empty; e must come from q. */ e = q; q = q->next; qsize--; } else if (qsize == 0 || !q) { /* q is empty; e must come from p. */ e = p; p = p->next; psize--; } else if (strcmp(p->name, q->name) <= 0) { /* First element of p is lower (or same); * e must come from p. */ e = p; p = p->next; psize--; } else { /* First element of q is lower; e must come from q. */ e = q; q = q->next; qsize--; } /* add the next element to the merged list */ if (tail) { tail->next = e; } else { list = e; } tail = e; } /* now p has stepped `insize' places along, and q has too */ p = q; } tail->next = NULL; /* If we have done only one merge, we're finished. */ if (nmerges <= 1) /* allow for nmerges==0, the empty list case */ { return list; } /* Otherwise repeat, merging lists twice the size */ insize *= 2; } } /*******************************************************************/ /* Borrowed this algorithm from merge-sort implementation */ struct Item *SortItemListCounters(struct Item *list) /* Biggest first */ { struct Item *p, *q, *e, *tail, *oldhead; int insize, nmerges, psize, qsize, i; if (list == NULL) { return NULL; } insize = 1; while (true) { p = list; oldhead = list; /* only used for circular linkage */ list = NULL; tail = NULL; nmerges = 0; /* count number of merges we do in this pass */ while (p) { nmerges++; /* there exists a merge to be done */ /* step `insize' places along from p */ q = p; psize = 0; for (i = 0; i < insize; i++) { psize++; q = q->next; if (!q) { break; } } /* if q hasn't fallen off end, we have two lists to merge */ qsize = insize; /* now we have two lists; merge them */ while (psize > 0 || (qsize > 0 && q)) { /* decide whether next element of merge comes from p or q */ if (psize == 0) { /* p is empty; e must come from q. */ e = q; q = q->next; qsize--; } else if (qsize == 0 || !q) { /* q is empty; e must come from p. */ e = p; p = p->next; psize--; } else if (p->counter > q->counter) { /* First element of p is higher (or same); * e must come from p. */ e = p; p = p->next; psize--; } else { /* First element of q is lower; e must come from q. */ e = q; q = q->next; qsize--; } /* add the next element to the merged list */ if (tail) { tail->next = e; } else { list = e; } tail = e; } /* now p has stepped `insize' places along, and q has too */ p = q; } tail->next = NULL; /* If we have done only one merge, we're finished. */ if (nmerges <= 1) /* allow for nmerges==0, the empty list case */ { return list; } /* Otherwise repeat, merging lists twice the size */ insize *= 2; } } cfengine-2.2.10/src/functions.c0000644000175000001440000013534711073407032013244 00000000000000/* Copyright (C) 1995- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: functions.c */ /* */ /* There is a protocol to these function calls - must return a val/class */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include /*********************************************************************/ int IsBuiltinFunction(char *item) { char name[CF_MAXVARSIZE],args[CF_BUFSIZE]; char c1 = '?',c2 = '?' ; Debug("IsBuiltinFunction(%s)\n",item); name[0] = '\0'; args[0] = '\0'; if (*item == '!') { item++; } sscanf(item,"%255[!a-zA-Z0-9_]%c%255[^)]%c",name,&c1,args,&c2); if (c1 != '(' || c2 != ')') { if (PARSING) { yyerror("Empty or bad function argument"); } return false; } Debug("IsBuiltinFunction: %s(%s)\n",name,args); if (strlen(args) == 0) { if (PARSING) { yyerror("Empty function argument"); } return false; } else { } return true; } /*********************************************************************/ char *EvaluateFunction(char *f,char *value) { enum builtin fn; char *sp,name[CF_MAXVARSIZE],args[CF_EXPANDSIZE]; int negated = false,count = 1; if (*f == '!') { negated = true; f++; } sscanf(f,"%255[^(]",name); strncpy(args,f+strlen(name)+1,CF_EXPANDSIZE); for (sp = args; *sp != '\0'; sp++) { if (*sp == '(') { count++; } if (*sp == ')') { count--; if (count == 0) { *sp = '\0'; } } } Debug("HandleFunction: %s(%s)\n",name,args); switch (fn = FunctionStringToCode(name)) { case fn_randomint: GetRandom(args,value); break; case fn_newerthan: case fn_accessedbefore: case fn_changedbefore: HandleCompareStat(fn,args,value); break; case fn_fileexists: case fn_isdir: case fn_islink: case fn_isplain: HandleStatInfo(fn,args,value); break; case fn_execresult: HandleFunctionExec(args,value,false); break; case fn_execshellresult: HandleFunctionExec(args,value,true); break; case fn_returnszero: HandleReturnsZero(args,value,false); break; case fn_returnszeroshell: HandleReturnsZero(args,value,true); break; case fn_iprange: HandleIPRange(args,value); break; case fn_hostrange: HandleHostRange(args,value); break; case fn_isdefined: HandleIsDefined(args,value); break; case fn_strcmp: HandleStrCmp(args,value); break; case fn_greaterthan: HandleGreaterThan(args,value,'+'); break; case fn_lessthan: HandleGreaterThan(args,value,'-'); break; case fn_regcmp: HandleRegCmp(args,value); break; case fn_classregex: HandleClassRegex(args,value); break; case fn_showstate: HandleShowState(args,value); break; case fn_friendstat: HandleFriendStatus(args,value); break; case fn_readfile: HandleReadFile(args,value); break; case fn_printfile: HandlePrintFile(args,value); break; case fn_readarray: HandleReadArray(args,value); break; case fn_readtcp: HandleReadTCP(args,value); break; case fn_readtable: HandleReadTable(args,value); break; case fn_readlist: HandleReadList(args,value); break; case fn_selectpl: HandleSelectPLeader(args,value); break; case fn_selectpn: case fn_selectpna: HandleSelectPGroup(args,value); break; case fn_syslog: HandleSyslogFn(args,value); break; case fn_userexists: HandleUserExists(args,value); break; case fn_groupexists: HandleGroupExists(args,value); break; case fn_setstate: HandleSetState(args,value); break; case fn_unsetstate: HandleUnsetState(args,value); break; case fn_module: HandlePrepModule(args,value); break; case fn_adj: HandleAssociation(args,value); break; case fn_returnvars: if (ScopeIsMethod()) { HandleReturnValues(args,value); ACTIONPENDING = false; } else { snprintf(OUTPUT,CF_BUFSIZE,"Function %s can only be used within a private method context",f); yyerror(OUTPUT); } break; case fn_returnclasses: if (ScopeIsMethod()) { HandleReturnClasses(args,value); ACTIONPENDING = false; } else { snprintf(OUTPUT,CF_BUFSIZE,"Function %s can only be used within a private method context",f); yyerror(OUTPUT); } break; default: snprintf(OUTPUT,CF_BUFSIZE,"No such builtin function %s\n",f); CfLog(cferror,OUTPUT,""); } if (negated) { if (strcmp(value,CF_NOCLASS) == 0) { strcpy(value,CF_ANYCLASS); return value; } if (strcmp(value,CF_ANYCLASS) == 0) { strcpy(value,CF_NOCLASS); return value; } } return value; } /*********************************************************************/ /* level 2 */ /*********************************************************************/ enum builtin FunctionStringToCode(char *str) { char *sp; int i; enum builtin fn; Debug("FunctionStringToCode(%s)\n",str); fn = nofn; for (sp = str; *sp != '\0'; sp++) { *sp = ToLower(*sp); if (*sp == ':') { *sp = '\0'; } } for (i = 1; BUILTINS[i] != NULL; i++) { if (strcmp(BUILTINS[i],str) == 0) { fn = (enum builtin) i; break; } } if (fn == nofn) { snprintf(OUTPUT,CF_BUFSIZE,"Internal function (%s) not recognized",str); yyerror(OUTPUT); FatalError("Could not parse function"); } return (enum builtin) i; } /*********************************************************************/ void GetRandom(char *args,char *value) { int result,from=-1,to=-1; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; if (ACTION != control) { yyerror("Use of RandomInt(a,b) outside of variable assignment"); } FunctionArgs(args,argv,2); from = atoi(argv[0]); to = atoi(argv[1]); if ((from < 0) || (to < 0) || (from == to)) { yyerror("RandomInt(a,b) must have different non-negative arguments < INT_MAX"); return; } if (from > to) { yyerror("RandomInt(a,b) - b was less than a"); return; } result = from + (int)(drand48()*(double)(to-from)); Debug("RandomInt(%u)\n",result); snprintf(value,CF_BUFSIZE,"%u",result); } /*********************************************************************/ void HandleStatInfo(enum builtin fn,char *args,char *value) { struct stat statbuf; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,1); if (lstat(argv[0],&statbuf) == -1) { strcpy(value,CF_NOCLASS); return; } else { if (fn == fn_fileexists) { strcpy(value,CF_ANYCLASS); return; } } strcpy(value,CF_NOCLASS); switch(fn) { case fn_isdir: if (S_ISDIR(statbuf.st_mode)) { strcpy(value,CF_ANYCLASS); return; } break; case fn_islink: if (S_ISLNK(statbuf.st_mode)) { strcpy(value,CF_ANYCLASS); return; } break; case fn_isplain: if (S_ISREG(statbuf.st_mode)) { strcpy(value,CF_ANYCLASS); return; } break; } strcpy(value,CF_NOCLASS); } /*********************************************************************/ void HandleIPRange(char *args,char *value) { struct Item *ip; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,1); if (strchr(argv[0],',')) { yyerror("Illegal argument to unary class-function"); return; } strcpy(value,CF_NOCLASS); if (!FuzzyMatchParse(argv[0])) { return; } for (ip = IPADDRESSES; ip != NULL; ip = ip->next) { Debug("Checking IP Range against iface %s\n",VIPADDRESS); if (FuzzySetMatch(argv[0],ip->name) == 0) { Debug("IPRange Matched\n"); strcpy(value,CF_ANYCLASS); return; } } Debug("Checking IP Range against RDNS %s\n",VIPADDRESS); if (FuzzySetMatch(argv[0],VIPADDRESS) == 0) { Debug("IPRange Matched\n"); strcpy(value,CF_ANYCLASS); return; } Debug("IPRange did not match\n"); strcpy(value,CF_NOCLASS); } /*********************************************************************/ void HandleHostRange(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,2); if (!FuzzyHostParse(argv[0],argv[1])) { strcpy(value,CF_NOCLASS); return; } Debug("SRDEBUG FuzzyHostParse(%s,%s) succeeded for %s\n",argv[0],argv[1],VUQNAME); if (FuzzyHostMatch(argv[0],argv[1],VUQNAME) == 0) { Debug("SRDEBUG FuzzyHostMatch(%s,%s,%s) succeeded\n",argv[0],argv[1],VUQNAME); strcpy(value,CF_ANYCLASS); } else { Debug("SRDEBUG FuzzyHostMatch(%s,%s,%s) failed\n",argv[0],argv[1],VUQNAME); strcpy(value,CF_NOCLASS); } return; } /*********************************************************************/ void HandleCompareStat(enum builtin fn,char *args,char *value) { struct stat frombuf,tobuf; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,2); strcpy(value,CF_NOCLASS); if (stat(argv[0],&frombuf) == -1) { return; } if (stat(argv[1],&tobuf) == -1) { return; } switch(fn) { case fn_newerthan: if (frombuf.st_mtime < tobuf.st_mtime) { strcpy(value,CF_ANYCLASS); return; } break; case fn_accessedbefore: if (frombuf.st_atime < tobuf.st_atime) { strcpy(value,CF_ANYCLASS); return; } break; case fn_changedbefore: if (frombuf.st_ctime < tobuf.st_ctime) { strcpy(value,CF_ANYCLASS); return; } break; } strcpy(value,CF_NOCLASS); } /*********************************************************************/ void HandleFunctionExec(char *args,char *value,int useshell) { char command[CF_MAXVARSIZE]; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,1); if (ACTION != control) { yyerror("Use of Exec[Shell]Result(s) outside of variable assignment"); } if (PARSEONLY || QUERYVARS) { Verbose("Not executing Exec[Shell]Result for parse-only or query-vars\n"); return; } if (*argv[0] == '/') { strncpy(command,argv[0],CF_MAXVARSIZE); GetExecOutput(command,value,useshell); Chop(value); value[CF_MAXVARSIZE-1] = '\0'; /* Truncate to CF_MAXVARSIZE */ } else { snprintf(OUTPUT,CF_BUFSIZE,"Exec[Shell]Result(%s) must specify an absolute path",argv[0]); yyerror(OUTPUT); } } /*********************************************************************/ void HandleReturnsZero(char *args,char *value,int useshell) { char command[CF_BUFSIZE]; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; if (ACTION != groups) { yyerror("Use of ReturnsZero(s) outside of class assignment"); } FunctionArgs(args,argv,1); Debug("HandleReturnsZero(%s)\n",argv); if (*argv[0] == '/') { strncpy(command,argv[0],CF_BUFSIZE); if (ShellCommandReturnsZero(command,useshell)) { strcpy(value,CF_ANYCLASS); return; } } else { yyerror("ExecResult(/command) must specify an absolute path"); } strcpy(value,CF_NOCLASS); } /*********************************************************************/ void HandleIsDefined(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,1); if (ACTION != groups) { yyerror("Use of IsDefined(s) outside of class assignment"); } Debug("HandleIsDefined(%s)\n",argv[0]); if (GetMacroValue(CONTEXTID,argv[0])) { strcpy(value,CF_ANYCLASS); return; } strcpy(value,CF_NOCLASS); } /*********************************************************************/ void HandleSyslogFn(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; int priority = LOG_ERR; FunctionArgs(args,argv,2); value[0] = '\0'; if (PARSING) { strcpy(value,"doinstall"); return; } if (strcmp(argv[0],"LOG_EMERG") == 0) { priority = LOG_EMERG; } else if (strcmp(argv[0],"LOG_ALERT") == 0) { priority = LOG_ALERT; } else if (strcmp(argv[0],"LOG_CRIT") == 0) { priority = LOG_CRIT; } else if (strcmp(argv[0],"LOG_NOTICE") == 0) { priority = LOG_NOTICE; } else if (strcmp(argv[0],"LOG_WARNING") == 0) { priority = LOG_WARNING; } else if (strcmp(argv[0],"LOG_ERR") == 0) { priority = LOG_ERR; } else { snprintf(OUTPUT,CF_BUFSIZE,"Unknown syslog priority (%s) - changing to LOG_ERR",argv[0]); CfLog(cferror,OUTPUT,""); priority = LOG_ERR; } Debug("Alerting to syslog(%s,%s)\n",argv[0],argv[1]); if (!DONTDO) { syslog(priority," %s",argv[1]); } } /*********************************************************************/ void HandleStrCmp(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,2); if (strcmp(argv[0],argv[1]) == 0) { strcpy(value,CF_ANYCLASS); } else { strcpy(value,CF_NOCLASS); } } /*********************************************************************/ void HandleGreaterThan(char *args,char *value,char ch) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; double a = CF_NOVAL,b = CF_NOVAL; FunctionArgs(args,argv,2); sscanf(argv[0],"%lf",&a); sscanf(argv[1],"%lf",&b); if ((a != CF_NOVAL) && (b != CF_NOVAL)) { Debug("%s and %s are numerical\n",argv[0],argv[1]); if (ch == '+') { if (a > b) { strcpy(value,CF_ANYCLASS); } else { strcpy(value,CF_NOCLASS); } return; } else { if (a < b) { strcpy(value,CF_ANYCLASS); } else { strcpy(value,CF_NOCLASS); } return; } } Debug("%s and %s are NOT numerical\n",argv[0],argv[1]); if (strcmp(argv[0],argv[1]) > 0) { if (ch == '+') { strcpy(value,CF_ANYCLASS); } else { strcpy(value,CF_NOCLASS); } } else { if (ch == '+') { strcpy(value,CF_NOCLASS); } else { strcpy(value,CF_ANYCLASS); } } } /*********************************************************************/ void HandleRegCmp(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; struct Item *list = NULL, *ret; FunctionArgs(args,argv,2); if (ACTION != groups) { yyerror("Function RegCmp() used outside of classes/groups"); return; } Debug("List source = (%d)[%s]\n",strlen(argv[1]),argv[1]); list = SplitStringAsItemList(argv[1],LISTSEPARATOR); ret = LocateNextItemMatching(list,argv[0]); if (ret != NULL) { strcpy(value,CF_ANYCLASS); } else { strcpy(value,CF_NOCLASS); } DeleteItemList(list); } /*********************************************************************/ void HandleClassRegex(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; struct Item *list = NULL, *ret; FunctionArgs(args,argv,1); if (ACTION != groups) { yyerror("Function ClassMatch() used outside of classes/groups"); return; } /* Exclude classes that might become define, only those at start */ if (ret = LocateNextItemMatching(VHEAP,argv[0])) { } else if (ret = LocateNextItemMatching(VADDCLASSES,argv[0])) { } if (ret != NULL) { strcpy(value,CF_ANYCLASS); } else { strcpy(value,CF_NOCLASS); } DeleteItemList(list); } /*********************************************************************/ void HandleReadFile(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; int i,val = 0; FILE *fp; FunctionArgs(args,argv,2); val = atoi(argv[1]); if ((fp = fopen(argv[0],"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open ReadFile(%s)\n",argv[0]); CfLog(cferror,OUTPUT,"fopen"); return; } if (val > CF_BUFSIZE - CF_BUFFERMARGIN) { snprintf(OUTPUT,CF_BUFSIZE,"ReadFile() will not read more than %d bytes",CF_BUFSIZE - CF_BUFFERMARGIN); CfLog(cferror,OUTPUT,""); fclose(fp); return; } memset(value,0,CF_BUFSIZE); fread(value,val,1,fp); for (i = val+1; i >= 0; i--) { if (value[i] == EOF) { value[i] = '\0'; break; } } fclose(fp); } /*********************************************************************/ void HandleReadArray(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; char *sp,*filename=argv[0],*maxbytes=argv[4],*formattype=argv[1]; char *commentchar=argv[3],*sepchar=argv[2],buffer[CF_BUFSIZE]; int i=0,val = 0,read = 0; struct Item *list = NULL,*ip; FILE *fp; FunctionArgs(args,argv,5); val = atoi(maxbytes); if ((fp = fopen(filename,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open ReadFile(%s)\n",filename); CfLog(cferror,OUTPUT,"fopen"); return; } if (strlen(sepchar) > 1) { yyerror("List separator declared is not a single character in ReadArray"); } while (!feof(fp)) { memset(buffer,0,CF_BUFSIZE); fgets(buffer,CF_BUFSIZE,fp); list = NULL; if ((read > val) && (val > 0)) { Verbose("Breaking off file read after %d bytes\n",read); break; } read += strlen(buffer); if (strlen(commentchar) > 0) { for (sp = buffer; sp < buffer+strlen(buffer); sp++) /* Remove comments */ { if (strncmp(sp,commentchar,strlen(commentchar)) == 0) { *sp = '\0'; break; } } } Chop(buffer); if (strlen(buffer) == 0) { continue; } if (strcmp(formattype,"autokey") == 0) { Debug("AUTOKEY: %s(%s)\n",CURRENTITEM,buffer); list = SplitStringAsItemList(buffer,*sepchar); for (ip = list; ip != NULL; ip=ip->next) { char lvalue[CF_BUFSIZE]; i++; Debug("Setting %s[%d] = %s\n",CURRENTITEM,i,ip->name); snprintf(lvalue,CF_BUFSIZE-1,"%s[%d]",CURRENTITEM,i); InstallControlRValue(lvalue,ip->name); snprintf(value,CF_BUFSIZE-1,"CF_ASSOCIATIVE_ARRAY%s",args); } } else if (strcmp(formattype,"textkey") == 0) { char lvalue[CF_BUFSIZE], rvalue[CF_BUFSIZE]; Debug("TEXTKEY: %s(%s)\n",CURRENTITEM,buffer); list = SplitStringAsItemList(buffer,*sepchar); if (ListLen(list) > 2) { Verbose("Warning: ReadArray() file format in %s is more than two elements (does this matter?)\n",filename); } if (ListLen(list) < 2) { yyerror("ReadArray() file format has too few elements for textkey\n"); } if (list->name != NULL) { snprintf(lvalue,CF_BUFSIZE-1,"%s[%s]",CURRENTITEM,list->name); if (list->next != NULL && list->next->name != NULL) { Debug("Setting %s[%s] = %s\n",lvalue,list->next->name); InstallControlRValue(lvalue,list->next->name); } else { yyerror("Too few data in input file\n"); } } snprintf(value,CF_BUFSIZE-1,"CF_ASSOCIATIVE_ARRAY%s",args); } else { yyerror("No such file format specifier"); } DeleteItemList(list); } fclose(fp); snprintf(value,CF_BUFSIZE-1,"CF_ASSOCIATIVE_ARRAY%s",args); } /*********************************************************************/ void HandleReadTable(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; char *sp,*filename=argv[0],*maxbytes=argv[4],*formattype=argv[1]; char *commentchar=argv[3],*sepchar=argv[2],buffer[CF_BUFSIZE]; int i=0,j=0,val = 0,read = 0; struct Item *list = NULL,*ip; FILE *fp; FunctionArgs(args,argv,5); val = atoi(maxbytes); if ((fp = fopen(filename,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open ReadFile(%s)\n",filename); CfLog(cferror,OUTPUT,"fopen"); return; } if (strlen(sepchar) > 1) { yyerror("List separator declared is not a single character in ReadTable"); } while (!feof(fp)) { memset(buffer,0,CF_BUFSIZE); fgets(buffer,CF_BUFSIZE,fp); i++; j=0; if ((read > val) && (val > 0)) { Verbose("Breaking off file read after %d bytes\n",read); break; } read += strlen(buffer); if (strlen(commentchar) > 0) { for (sp = buffer; sp < buffer+strlen(buffer); sp++) /* Remove comments */ { if (strncmp(sp,commentchar,strlen(commentchar)) == 0) { *sp = '\0'; break; } } } Chop(buffer); if (strlen(buffer) == 0) { continue; } if (strcmp(formattype,"autokey") == 0) { Debug("AUTOKEY: %s(%s)\n",CURRENTITEM,buffer); list = SplitStringAsItemList(buffer,*sepchar); for (ip = list; ip != NULL; ip=ip->next) { char lvalue[CF_BUFSIZE]; j++; Debug("Setting %s[%d][%d] = %s\n",CURRENTITEM,i,j,ip->name); snprintf(lvalue,CF_BUFSIZE-1,"%s[%d][%d]",CURRENTITEM,i,j); InstallControlRValue(lvalue,ip->name); snprintf(value,CF_BUFSIZE-1,"CF_ASSOCIATIVE_ARRAY%s",args); } } else if (strcmp(formattype,"textkey") == 0) { char argv[CF_MAXFARGS][CF_EXPANDSIZE],lvalue[CF_BUFSIZE]; if (!FunctionArgs(buffer,argv,3)) { break; } Debug("Setting %s[%s] = %s\n",CURRENTITEM,argv[0],argv[1]); snprintf(lvalue,CF_BUFSIZE-1,"%s[%s][%s]",CURRENTITEM,argv[0],argv[1]); InstallControlRValue(lvalue,argv[2]); snprintf(value,CF_BUFSIZE-1,"CF_ASSOCIATIVE_ARRAY%s",args); } else { yyerror("No such file format specifier"); } } fclose(fp); snprintf(value,CF_BUFSIZE-1,"CF_ASSOCIATIVE_ARRAY%s",args); } /*********************************************************************/ void HandleReadList(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; char *sp,*filename=argv[0],*maxbytes=argv[3],*formattype=argv[1]; char *commentchar=argv[2],buffer[CF_BUFSIZE]; int val = 0; struct Item *list = NULL,*ip; FILE *fp; FunctionArgs(args,argv,4); val = atoi(maxbytes); if (strcmp(formattype,"lines") != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Unknown format type in ReadList(%s)",args); CfLog(cferror,OUTPUT,""); } if ((fp = fopen(filename,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open ReadFile(%s)\n",filename); CfLog(cferror,OUTPUT,"fopen"); return; } while (!feof(fp)) { memset(buffer,0,CF_BUFSIZE); fgets(buffer,CF_BUFSIZE,fp); if (strlen(commentchar) > 0) { for (sp = buffer; sp < buffer+strlen(buffer); sp++) /* Remove comments */ { if (strncmp(sp,commentchar,strlen(commentchar)) == 0) { *sp = '\0'; break; } } } Chop(buffer); if (strlen(buffer) > 0) { PrependItem(&list,buffer,NULL); } } fclose(fp); for (ip = list; ip != NULL; ip=ip->next) { if (ip->name == NULL) { continue; } if (strlen(value) + strlen(ip->name) > CF_BUFSIZE) { snprintf(OUTPUT,CF_BUFSIZE,"Variable size exceeded in ReadList(%s)", args); CfLog(cferror,OUTPUT,""); return; } snprintf(value+strlen(value),CF_BUFSIZE,"%s%c",ip->name,LISTSEPARATOR); Verbose(" %s (added peer) = %s\n",ip->name,value); } value[strlen(value)-1] = '\0'; } /*********************************************************************/ void HandleReadTCP(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; char *sp,*hostnameip=argv[0],*maxbytes=argv[3],*port=argv[1]; char *sendstring=argv[2],buffer[CF_BUFSIZE]; int val = 0, n_read = 0; short portnum; FunctionArgs(args,argv,4); val = atoi(maxbytes); portnum = (short) atoi(port); if (val > CF_BUFSIZE-1) { snprintf(OUTPUT,CF_BUFSIZE,"Too many bytes to read from TCP port %s@%s",port,hostnameip); CfLog(cferror,OUTPUT,""); } Debug("Want to read %d bytes from port %d at %s\n",val,portnum,hostnameip); if (PARSEONLY || QUERYVARS) { Verbose("Not attempting TCP connection for parse-only or query-vars\n"); return; } CONN = NewAgentConn(); if (!RemoteConnect(hostnameip,'n',portnum,port)) { CfLog(cferror,"Couldn't open a tcp socket","socket"); if (CONN->sd != CF_NOT_CONNECTED) { close(CONN->sd); CONN->sd = CF_NOT_CONNECTED; } DeleteAgentConn(CONN); return; } if (strlen(sendstring) > 0) { if (SendSocketStream(CONN->sd,sendstring,strlen(sendstring),0) == -1) { DeleteAgentConn(CONN); return; } } if ((n_read = recv(CONN->sd,value,val,0)) == -1) { } close(CONN->sd); DeleteAgentConn(CONN); /* value set to result */ } /*********************************************************************/ void HandleSelectPLeader(char *args,char *value) { FILE *fp; char machine[MAXHOSTNAMELEN],first[MAXHOSTNAMELEN]; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; char *filename=argv[0],*commentchar=argv[1]; char *policy=argv[2],*size=argv[3]; struct Item *list = NULL,*ip; int i,psize = -1, count, leader,done = false; FunctionArgs(args,argv,4); psize = atoi(size); first[0] = '\0'; if (psize < 2) { strcpy(value,"silly"); CfLog(cferror,"Partitioning of size < 2 is silly",""); return; } Verbose("Searching for my peer group in %s with partition size %d\n",filename,psize); if (!((strcmp("random",policy) == 0) || (strcmp("first",policy) == 0))) { strcpy(value,"silly"); CfLog(cferror,"Partition leader policy is first/random only",""); return; } if ((fp = fopen(filename,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open ReadFile(%s)\n",filename); CfLog(cferror,OUTPUT,"fopen"); return; } count = 0; while (!feof(fp)) { char buffer[CF_BUFSIZE]; memset(buffer,0,CF_BUFSIZE); fgets(buffer,CF_BUFSIZE-1,fp); if (strlen(commentchar) > 0) { for (i = 0; i < strlen(buffer); i++) /* Remove comments */ { if (strncmp((char *)(buffer+i),commentchar,strlen(commentchar)) == 0) { buffer[i] = '\0'; break; } } } memset(machine,0,MAXHOSTNAMELEN-1); sscanf(buffer,"%255s",machine); if (strlen(machine) == 0) { continue; } if (strstr(machine,"=")) { Debug("Skipping what looks like an embedded assignment (%s)\n",machine); continue; } if (strlen(first) == 0) { strncpy(first,machine,MAXHOSTNAMELEN-1); } if ((count == psize) || ((count > 0) && feof(fp))) { int len, this = 0; done = false; if (IsItemIn(list,VUQNAME)||IsItemIn(list,VFQNAME)||IsItemIn(list,VIPADDRESS)) { /* This is my peer group */ Verbose("Found my peer group:\n"); len = ListLen(list); if (strcmp(policy,"random") == 0) { leader = (int)(drand48()*(double)(len)); } else { leader = 0; } for (ip = list; ip != NULL; ip=ip->next) { if (leader == this) { Verbose(" %s (leader)\n",ip->name); if (strlen(ip->name) > 0) { strncpy(value,ip->name,MAXHOSTNAMELEN-1); } else { strncpy(value,first,MAXHOSTNAMELEN-1); } done = true; } else { Verbose(" %s (peer)\n",ip->name); } this++; } } else { Debug("Not my peer group:"); for (ip = list; ip != NULL; ip=ip->next) { Debug(" %s",ip->name); } Verbose("\n"); } count = 0; DeleteItemList(list); list = NULL; if (done) { break; } } count++; PrependItem(&list,machine,NULL); } if (!done) { strncpy(value,first,MAXHOSTNAMELEN-1); /* Fill up blanks in peer groups */ } if (list != NULL) { DeleteItemList(list); } fclose(fp); } /*********************************************************************/ void HandleSelectPGroup(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE],machine[MAXHOSTNAMELEN],first[MAXHOSTNAMELEN]; char *filename=argv[0],*commentchar=argv[1]; char *policy=argv[2],*size=argv[3]; struct Item *list = NULL,*ip; int i,psize = -1, count,done = false,len = 0; FILE *fp; FunctionArgs(args,argv,4); psize = atoi(size); first[0] = '\0'; value[0] = '\0'; if (psize < 2) { strcpy(value,"silly"); CfLog(cferror,"Partitioning of size < 2 is silly",""); return; } Verbose("Searching for my peer group neighbours in %s with partition size %d\n",filename,psize); if (!(strcmp("random",policy) == 0 || strcmp("first",policy) == 0)) { strcpy(value,"silly"); CfLog(cferror,"Partition leader policy is first/random only",""); return; } if ((fp = fopen(filename,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open ReadFile(%s)\n",filename); CfLog(cferror,OUTPUT,"fopen"); return; } count = 0; while (!feof(fp)) { char buffer[CF_BUFSIZE]; memset(buffer,0,CF_BUFSIZE); fgets(buffer,CF_BUFSIZE,fp); if (strlen(commentchar) > 0) { for (i = 0; i < strlen(buffer); i++) /* Remove comments */ { if (strncmp((char *)(buffer+i),commentchar,strlen(commentchar)) == 0) { buffer[i] = '\0'; break; } } } machine[0] = '\0'; sscanf(buffer,"%255s",machine); if (strlen(machine) == 0) { continue; } if (strstr(machine,"=")) { Debug("Skipping what looks like an embedded assignment (%s)\n",machine); continue; } if (strlen(first) == 0) { strncpy(first,machine,MAXHOSTNAMELEN-1); } if ((count == psize) || ((count > 0) && feof(fp))) { done = false; len = 0; if (IsItemIn(list,VUQNAME)||IsItemIn(list,VFQNAME)||IsItemIn(list,VIPADDRESS)) { /* This is my peer group */ Verbose("Found my peer group:\n"); for (ip = list; ip != NULL; ip=ip->next) { if ((strcmp(ip->name,VFQNAME) != 0) && (strcmp(ip->name,VIPADDRESS) != 0)) { if (strlen(value) + strlen(ip->name) + 1 > CF_BUFSIZE) { snprintf(OUTPUT,CF_BUFSIZE,"Variable size exceeded in SelectPartitionNeighbours(%s)", args); CfLog(cferror,OUTPUT,""); return; } snprintf(value+len,CF_BUFSIZE,"%s%c",ip->name,LISTSEPARATOR); Verbose(" %s (added peer) = %s\n",ip->name,value); len += strlen(ip->name)+1; } done = true; } value[strlen(value)-1] = '\0'; /* Remove last separator from list */ } else { Debug("Not my peer group:"); for (ip = list; ip != NULL; ip=ip->next) { Debug(" %s",ip->name); } Verbose("\n"); } count = 0; DeleteItemList(list); list = NULL; if (done) { break; } } count++; PrependItem(&list,machine,NULL); } if (!done) { strncat(value,first,MAXHOSTNAMELEN-1); /* Fill up blanks in peer groups */ } fclose(fp); } /*********************************************************************/ void HandleReturnValues(char *args,char *value) { struct Item *ip; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,1); Verbose("This is a method with return value list: (%s)\n",argv[0]); for (ip = SplitStringAsItemList(argv[0],','); ip != NULL; ip=ip->next) { AppendItem(&METHODRETURNVARS,ip->name,CLASSBUFF); } strcpy(value,"noinstall"); } /*********************************************************************/ void HandleReturnClasses(char *args,char *value) { struct Item *ip; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,1); Verbose("This is a method with return class list: %s\n",argv[0]); for (ip = SplitStringAsItemList(argv[0],','); ip != NULL; ip=ip->next) { AppendItem(&METHODRETURNCLASSES,argv[0],CLASSBUFF); } strcpy(value,"noinstall"); } /*********************************************************************/ void HandleShowState(char *args,char *value) { struct stat statbuf; char buffer[CF_BUFSIZE],vbuff[CF_BUFSIZE]; struct Item *addresses = NULL,*saddresses = NULL,*ip; FILE *fp; int i = 0, tot=0, min_signal_diversity = 1,conns=1; int maxlen = 0,count; double *dist = NULL, S = 0.0; char *offset = NULL; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,1); if ((ACTION != alerts) && PARSING) { yyerror("Use of ShowState(type) outside of alert declaration"); } Debug("ShowState(%s)\n",args); if (PARSING) { strcpy(value,"doinstall"); return; } snprintf(buffer,CF_BUFSIZE-1,"%s/state/cf_%s",CFWORKDIR,argv[0]); if (stat(buffer,&statbuf) == 0) { if ((fp = fopen(buffer,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open state memory %s\n",buffer); CfLog(cfinform, OUTPUT,"fopen"); return; } while(!feof(fp)) { char local[CF_BUFSIZE],remote[CF_BUFSIZE]; buffer[0] = local[0] = remote[0] = '\0'; memset(vbuff,0,CF_BUFSIZE); fgets(buffer,CF_BUFSIZE,fp); if (strlen(buffer) > 0) { Verbose("%s: (%2d) %s",VPREFIX,conns,buffer); if (IsSocketType(argv[0])) { if (strncmp(argv[0],"incoming",8) == 0 || strncmp(argv[0],"outgoing",8) == 0) { if (strncmp(buffer,"tcp",3) == 0) { sscanf(buffer,"%*s %*s %*s %s %s",local,remote); /* linux-like */ } else { sscanf(buffer,"%s %s",local,remote); /* solaris-like */ } strncpy(vbuff,remote,CF_BUFSIZE-1); DePort(vbuff); } } else if (IsTCPType(argv[0])) { count = 1; sscanf(buffer,"%d %[^\n]",&count,remote); AppendItem(&addresses,remote,""); SetItemListCounter(addresses,remote,count); conns += count; continue; } else { /* If we get here this is a process thing */ if (offset == NULL) { if (offset = strstr(buffer,"CMD")) { } else if (offset = strstr(buffer,"COMMAND")) { } if (offset == NULL) { continue; } } strncpy(vbuff,offset,CF_BUFSIZE-1); Chop(vbuff); } if (!IsItemIn(addresses,vbuff)) { conns++; AppendItem(&addresses,vbuff,""); IncrementItemListCounter(addresses,vbuff); } else { conns++; IncrementItemListCounter(addresses,vbuff); } } } fclose(fp); conns--; printf("%s: -----------------------------------------------------------------------------------\n",VPREFIX); printf("%s: In the last 40 minutes, the peak state was q = %d:\n",VPREFIX,conns); if (IsSocketType(argv[0])||IsTCPType(argv[0])) { if (addresses != NULL) { printf(" {\n"); } for (ip = addresses; ip != NULL; ip=ip->next) { tot+=ip->counter; buffer[0] = '\0'; sscanf(ip->name,"%s",buffer); if (!IsIPV4Address(buffer) && !IsIPV6Address(buffer)) { Verbose("\nRejecting address %s\n",ip->name); continue; } printf(" DNS key: %s = %s (%d/%d)\n",buffer,IPString2Hostname(buffer),ip->counter,conns); if (strlen(ip->name) > maxlen) { maxlen = strlen(ip->name); } } if (addresses != NULL) { printf(" -\n"); } } else { for (ip = addresses; ip != NULL; ip=ip->next) { tot+=ip->counter; } } saddresses = SortItemListCounters(addresses); for (ip = saddresses; ip != NULL; ip=ip->next) { int s; if (maxlen > 17) /* ipv6 */ { printf(" Frequency: %-40s|",ip->name); } else { printf(" Frequency: %-17s|",ip->name); } for (s = 0; (s < ip->counter) && (s < 50); s++) { if (s < 48) { putchar('*'); } else { putchar('+'); } } printf(" \t(%d/%d)\n",ip->counter,conns); } if (addresses != NULL) { printf(" }\n"); } dist = (double *) malloc((tot+1)*sizeof(double)); if (conns > min_signal_diversity) { for (i = 0,ip = addresses; ip != NULL; i++,ip=ip->next) { dist[i] = ((double)(ip->counter))/((double)tot); S -= dist[i]*log(dist[i]); } printf(" -\n Scaled entropy of addresses = %.1f %%\n",S/log((double)tot)*100.0); printf(" (Entropy = 0 for single source, 100 for flatly distributed source)\n -\n"); } printf("%s: -----------------------------------------------------------------------------------\n",VPREFIX); snprintf(buffer,CF_BUFSIZE,"State of %s peaked at %s\n",argv[0],ctime(&statbuf.st_mtime)); strcpy(value,buffer); } else { snprintf(buffer,CF_BUFSIZE,"State parameter %s is not known or recorded\n",argv[0]); strcpy(value,buffer); } DeleteItemList(addresses); if (dist) { free((char *)dist); } } /*********************************************************************/ void HandleFriendStatus(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; int time = -1; if ((ACTION != alerts) && PARSING) { yyerror("Use of FriendStatus(type) outside of alert declaration"); } FunctionArgs(args,argv,1); if (PARSING) { strcpy(value,"doinstall"); return; } time = atoi(argv[0]); if (time >= 0) { CheckFriendConnections(time); CheckFriendReliability(); } strcpy(value,""); /* No reply */ } /*********************************************************************/ void HandlePrintFile(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FILE *fp; int max = -1, lines = 0, count = 0; if ((ACTION != alerts) && PARSING) { yyerror("Use of PrintFile(name) outside of alert declaration"); } FunctionArgs(args,argv,2); if (PARSING) { strcpy(value,"doinstall"); return; } max = atoi(argv[1]); if (max < 0) { snprintf(OUTPUT,CF_BUFSIZE,"Max lines argument to PrintFile(%s,%d) cannot be read\n",argv[0],max); CfLog(cferror,OUTPUT,""); max = 2; } if ((fp = fopen(argv[0],"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"File argument to PrintFile(%s,%d) cannot be read\n",argv[0],max); CfLog(cferror,OUTPUT,""); strcpy(value,""); /* No reply */ return; } snprintf(OUTPUT,CF_BUFSIZE,"PrintFile(%s,%d lines)\n",argv[0],max); CfLog(cfinform,OUTPUT,""); while (!feof(fp) && (lines < max)) { fgets(OUTPUT,CF_BUFSIZE,fp); lines++; printf("%s",OUTPUT); OUTPUT[0] = '\0'; } fclose(fp); strcpy(value,""); /* No reply */ } /*********************************************************************/ void HandleSetState(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; char *name=argv[0],*ttlbuf=argv[1],*policy=argv[2]; unsigned int ttl = 0; value[0] = '\0'; FunctionArgs(args,argv,3); ttl = atoi(ttlbuf); Debug("HandleSetState(%s,%d,%s)\n",name,ttl,policy); if (ttl == 0) { yyerror("No expiry date set on persistent class"); return; } if (strcmp(ToLowerStr(policy),"preserve") == 0) { if (!PARSING && !DONTDO) { AddPersistentClass(name,ttl,cfpreserve); } } else if (strcmp(ToLowerStr(policy),"reset") == 0) { if (!PARSING & !DONTDO) { AddPersistentClass(name,ttl,cfreset); } } else { yyerror("Unknown update policy"); } } /*********************************************************************/ void HandleUnsetState(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; value[0] = '\0'; FunctionArgs(args,argv,1); Debug("HandleUnsetState(%s)\n",argv[0]); DeletePersistentClass(argv[0]); } /*********************************************************************/ void HandlePrepModule(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE]; char ebuff[CF_EXPANDSIZE]; ExpandVarstring(args,ebuff,NULL); value[0] = '\0'; FunctionArgs(ebuff,argv,2); Debug("PrepModule(%s,%s)\n",argv[0],argv[1]); BuildClassEnvironment(); if (CheckForModule(argv[0],argv[1])) { strcpy(value,CF_ANYCLASS); } else { strcpy(value,CF_NOCLASS); } } /*********************************************************************/ void HandleAssociation(char *args,char *value) { char argv[CF_MAXFARGS][CF_EXPANDSIZE],lvalue[CF_BUFSIZE]; value[0] = '\0'; FunctionArgs(args,argv,2); Debug("HandleAssociation(%s <-> %s)\n",argv[0],argv[1]); snprintf(lvalue,CF_BUFSIZE-1,"%s[%s]",CURRENTITEM,argv[0]); InstallControlRValue(lvalue,argv[1]); snprintf(value,CF_BUFSIZE-1,"CF_ASSOCIATIVE_ARRAY%s",args); } /*********************************************************************/ void HandleUserExists(char *args,char *value) { struct passwd *pw; uid_t uid = -1; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,1); if (strchr(argv[0],',')) { yyerror("Illegal argument to unary class-function"); return; } if (isdigit((int)*argv[0])) { sscanf(argv[0],"%d",&uid); if (uid < 0) { yyerror("Illegal user id"); } if ((pw = getpwuid(uid)) == NULL) { strcpy(value,CF_NOCLASS); return; } } else if ((pw = getpwnam(argv[0])) == NULL) { strcpy(value,CF_NOCLASS); return; } strcpy(value,CF_ANYCLASS); } /*********************************************************************/ void HandleGroupExists(char *args,char *value) { struct group *gp; gid_t gid = -1; char argv[CF_MAXFARGS][CF_EXPANDSIZE]; FunctionArgs(args,argv,1); if (strchr(argv[0],',')) { yyerror("Illegal argument to unary class-function"); return; } if (isdigit((int)*argv[0])) { sscanf(argv[0],"%d",&gid); if (gid < 0) { yyerror("Illegal group id"); } if ((gp = getgrgid(gid)) == NULL) { strcpy(value,CF_NOCLASS); return; } } else if ((gp = getgrnam(argv[0])) == NULL) { strcpy(value,CF_NOCLASS); return; } strcpy(value,CF_ANYCLASS); } /*********************************************************************/ /* Level 3 */ /*********************************************************************/ int FunctionArgs(char *args,char arg[CF_MAXFARGS][CF_EXPANDSIZE],int number) { char *sp,*start[CF_MAXFARGS],exbuf[CF_EXPANDSIZE]; int count = 0, i; struct Item *ip = NULL, *ipp; if (number > CF_MAXFARGS) { FatalError("Software error: too many function arguments"); } ip = ListFromArgs(args); if (DEBUG) { DebugListItemList(ip); } count = ListLen(ip); if (count != number) { if (PARSING) { snprintf(OUTPUT,CF_BUFSIZE,"Function requires %d argument items",number); yyerror(OUTPUT); } else { snprintf(OUTPUT,CF_BUFSIZE,"Assignment (%s) with format error - %d/%d expected args",args,count,number); CfLog(cferror,OUTPUT,""); } return false; } ipp = ip; for (i = 0; i < number; i++) { ExpandVarstring(ipp->name,exbuf,NULL); strncpy(arg[i],exbuf,CF_EXPANDSIZE); Debug("ARG[%d] %s\n",i,arg[i]); ipp = ipp->next; } DeleteItemList(ip); return true; } /*********************************************************************/ int FileFormat(char *args,char arg[CF_MAXFARGS][CF_EXPANDSIZE],int number,char sep) { char *sp,*start[CF_MAXFARGS],exbuf[CF_EXPANDSIZE]; int count = 0, i; struct Item *ip = NULL, *ipp; if (number > CF_MAXFARGS) { FatalError("Software error: too many file columns in FileFormat"); } ip = ListFromArgs(args); if (DEBUG) { DebugListItemList(ip); } count = ListLen(ip); if (count != number) { if (PARSING) { snprintf(OUTPUT,CF_BUFSIZE,"File format requires %d items",number); yyerror(OUTPUT); } else { snprintf(OUTPUT,CF_BUFSIZE,"Assignment (%s) with format error - %d/%d expected args",args,count,number); CfLog(cferror,OUTPUT,""); } return false; } ipp = ip; for (i = 0; i < number; i++) { ExpandVarstring(ipp->name,exbuf,NULL); strncpy(arg[i],exbuf,CF_EXPANDSIZE); Debug("ARG[%d] %s\n",i,arg[i]); ipp = ipp->next; } DeleteItemList(ip); return true; } cfengine-2.2.10/src/comparray.c0000644000175000001440000000612110202123551013206 00000000000000/* Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Compressed Arrays */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*******************************************************************/ int FixCompressedArrayValue(int i,char *value,struct CompressedArray **start) { struct CompressedArray *ap; char *sp; for (ap = *start; ap != NULL; ap = ap->next) { if (ap->key == i) { /* value already fixed */ return false; } } Debug("FixCompressedArrayValue(%d,%s)\n",i,value); if ((ap = (struct CompressedArray *)malloc(sizeof(struct CompressedArray))) == NULL) { CfLog(cferror,"Can't allocate memory in SetCompressedArray()","malloc"); FatalError(""); } if ((sp = malloc(strlen(value)+2)) == NULL) { CfLog(cferror,"Can't allocate memory in SetCompressedArray()","malloc"); FatalError(""); } strcpy(sp,value); ap->key = i; ap->value = sp; ap->next = *start; *start = ap; return true; } /*******************************************************************/ void DeleteCompressedArray(struct CompressedArray *start) { if (start != NULL) { DeleteCompressedArray(start->next); start->next = NULL; if (start->value != NULL) { free(start->value); } free(start); } } /*******************************************************************/ int CompressedArrayElementExists(struct CompressedArray *start,int key) { struct CompressedArray *ap; Debug("CompressedArrayElementExists(%d)\n",key); for (ap = start; ap !=NULL; ap = ap->next) { if (ap->key == key) { return true; } } return false; } /*******************************************************************/ char *CompressedArrayValue(struct CompressedArray *start,int key) { struct CompressedArray *ap; for (ap = start; ap != NULL; ap = ap->next) { if (ap->key == key) { return ap->value; } } return NULL; } cfengine-2.2.10/src/locks.c0000644000175000001440000004455211015460561012346 00000000000000/* cfengine for GNU Copyright (C) 1995,2001 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*********************************************************************/ /* */ /* TOOLKIT : Locks and Signals */ /* */ /*********************************************************************/ /* A log file of the run times is kept for each host separately. This records each atomic lock and the time at which it completed, for use in computing the elapsed time. The file format is: %s time:operation:operand Each operation (independently of operand) has a "last" inode which keeps the time at which is last completed, for use in calculating IfElapsed. The idea here is that the elapsed time is from the time at which the last operation of this type FINISHED. This is different from a lock (which is used to allow several sub operations to coexist). Here we are limiting activity in general to avoid "spamming". Each atomic operation (including operand) has a lock. The removal of this lock causes the "last" file to be updated. This is used to actually prevent execution of an atom which is already being executed. If this lock has existed for longer than the ExpireAfter time, the process owning the lock is killed and the lock is re-established. The lock file contains the pid. This is robust to hanging locks and can be thought of as a garbage collection mechanism for these locks. Last files are just inodes (empty files) so they use no disk. The locks (which never exceed the no of running processes) contain the pid. */ #include "cf.defs.h" #include "cf.extern.h" # include DB *DBP; /********************************************************************/ void PreLockState() { strcpy(CFLOCK,"pre-lock-state"); } /********************************************************************/ void SaveExecLock() { strcpy(SAVELOCK,CFLOCK); } /********************************************************************/ void RestoreExecLock() { strcpy(CFLOCK,SAVELOCK); } /********************************************************************/ void WritePID(char *filename) { FILE *fp; char *sp; if (!IsPrivileged()) { Verbose("\n(Non privileged user...)\n\n"); if ((sp = getenv("HOME")) == NULL) { FatalError("You do not have a HOME variable pointing to your home directory"); } snprintf(PIDFILE,CF_BUFSIZE-1,"%s/%s",sp,filename); } else { snprintf(PIDFILE,CF_BUFSIZE-1,"%s/%s",WORKDIR,filename); } if ((fp = fopen(PIDFILE,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not write to PID file %s\n",filename); CfLog(cfinform,OUTPUT,"fopen"); return; } fprintf(fp,"%d\n",getpid()); fclose(fp); } /********************************************************************/ void HandleSignal(int signum) { if (signum != SIGCHLD) { snprintf(OUTPUT,CF_BUFSIZE*2,"Received signal %d (%s) while doing [%s]",signum,SIGNALS[signum],CFLOCK); Chop(OUTPUT); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"Logical start time %s ",ctime(&CFSTARTTIME)); Chop(OUTPUT); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"This sub-task started really at %s\n",ctime(&CFINITSTARTTIME)); CfLog(cferror,OUTPUT,""); fflush(stdout); if (signum == SIGTERM || signum == SIGINT || signum == SIGHUP || signum == SIGSEGV || signum == SIGKILL|| signum == SIGPIPE) { unlink(PIDFILE); ReleaseCurrentLock(); CloseAuditLog(); closelog(); exit(0); } else if (signum == SIGUSR1) { DEBUG= true; D2= true; } else if (signum == SIGUSR2) { DEBUG= false; D2= false; } else /* zombie cleanup - how hard does it have to be? */ { } /* Reset the signal handler */ signal(signum,HandleSignal); } } /************************************************************************/ void InitializeLocks() { int errno; if (IGNORELOCK) { return; } snprintf(LOCKDB,CF_BUFSIZE,"%s/cfengine_lock_db",CFWORKDIR); if ((errno = db_create(&DBP,NULL,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open lock database %s\n",LOCKDB); CfLog(cferror,OUTPUT,"db_open"); IGNORELOCK = true; return; } #ifdef CF_OLD_DB if ((errno = (DBP->open)(DBP,LOCKDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (DBP->open)(DBP,NULL,LOCKDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open lock database %s\n",LOCKDB); CfLog(cferror,OUTPUT,"db_open"); IGNORELOCK = true; return; } } /************************************************************************/ void CloseLocks() { if (IGNORELOCK) { return; } DBP->close(DBP,0); } /************************************************************************/ int GetLock(char *operator,char *operand,int ifelapsed,int expireafter,char *host,time_t now) { unsigned int pid; int i, err, sum=0; time_t lastcompleted = 0, elapsedtime; char c_operator[CF_BUFSIZE],c_operand[CF_BUFSIZE],cc_operator[CF_BUFSIZE],cc_operand[CF_BUFSIZE]; if (now == 0) { if ((now = time((time_t *)NULL)) == -1) { printf("Couldn't read system clock\n"); } return true; } Debug("GetLock(%s,%s,time=%d), ExpireAfter=%d, IfElapsed=%d\n",operator,operand,now,expireafter,ifelapsed); memset(CFLOCK,0,CF_BUFSIZE); memset(CFLAST,0,CF_BUFSIZE); /* Make local copy in case CanonifyName called - not re-entrant - best fix for now */ strncpy(c_operator,operator,CF_BUFSIZE-1); strncpy(c_operand,operand,CF_BUFSIZE-1); strncpy(cc_operator,CanonifyName(c_operator),CF_BUFSIZE-1); strncpy(cc_operand,CanonifyName(c_operand),CF_BUFSIZE-1); for (i = 0; operator[i] != '\0'; i++) { sum = (CF_MACROALPHABET * sum + operator[i]) % CF_HASHTABLESIZE; } for (i = 0; operand[i] != '\0'; i++) { sum = (CF_MACROALPHABET * sum + operand[i]) % CF_HASHTABLESIZE; } snprintf(CFLOG,CF_BUFSIZE,"%s/cfengine.%.40s.runlog",VLOGDIR,host); snprintf(CFLOCK,CF_BUFSIZE,"lock.%.100s.%.40s.%s.%.100s_%d",VCANONICALFILE,host,cc_operator,cc_operand,sum); snprintf(CFLAST,CF_BUFSIZE,"last.%.100s.%.40s.%s.%.100s_%d",VCANONICALFILE,host,cc_operator,cc_operand,sum); if (IGNORELOCK) { return true; } if (strlen(CFLOCK) > MAX_FILENAME) { CFLOCK[MAX_FILENAME] = '\0'; /* most nodenames are 255 chars or less */ } if (strlen(CFLAST) > MAX_FILENAME) { CFLAST[MAX_FILENAME] = '\0'; /* most nodenames are 255 chars or less */ } /* Look for non-existent (old) processes */ lastcompleted = GetLastLock(); elapsedtime = (time_t)(now-lastcompleted) / 60; if (elapsedtime < 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Another cfengine seems to have done [%s.%s] since I started (elapsed=%d)\n",operator,operand,elapsedtime); CfLog(cfverbose,OUTPUT,""); return false; } if (elapsedtime < ifelapsed) { snprintf(OUTPUT,CF_BUFSIZE*2,"Nothing promised for [%s.%s] (%u/%u minutes elapsed)\n",operator,operand,elapsedtime,ifelapsed); CfLog(cfverbose,OUTPUT,""); return false; } /* Look for existing (current) processes */ lastcompleted = CheckOldLock(); elapsedtime = (time_t)(now-lastcompleted) / 60; if (lastcompleted != 0) { if (elapsedtime >= expireafter) { snprintf(OUTPUT,CF_BUFSIZE*2,"Lock %s expired (after %u/%u minutes)\n",CFLOCK,elapsedtime,expireafter); CfLog(cfinform,OUTPUT,""); pid = GetLockPid(CFLOCK); if (pid == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Illegal pid in corrupt lock %s - ignoring lock\n",CFLOCK); CfLog(cferror,OUTPUT,""); } else { Verbose("Trying to kill expired process, pid %d\n",pid); err = 0; if ((err = kill(pid,SIGINT)) == -1) { sleep(1); err=0; if ((err = kill(pid,SIGTERM)) == -1) { sleep(5); err=0; if ((err = kill(pid,SIGKILL)) == -1) { sleep(1); } } } if (err == 0 || errno == ESRCH) { LockLog(pid,"Lock expired, process killed",operator,operand); unlink(CFLOCK); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to kill expired cfagent process %d from lock %s, exiting this time..\n",pid,CFLOCK); CfLog(cferror,OUTPUT,"kill"); FatalError(""); } } } else { Verbose("Couldn't obtain lock for %s (already running!)\n",CFLOCK); return false; } } SetLock(); return true; } /************************************************************************/ void ReleaseCurrentLock() { if (IGNORELOCK) { return; } Debug("ReleaseCurrentLock(%s)\n",CFLOCK); if (strlen(CFLAST) == 0) { return; } if (DeleteLock(CFLOCK) == -1) { Debug("Unable to remove lock %s\n",CFLOCK); return; } if (PutLock(CFLAST) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to create %s\n",CFLAST); CfLog(cferror,OUTPUT,"creat"); return; } LockLog(getpid(),"Lock removed normally ",CFLOCK,""); strcpy(CFLOCK,"no_active_lock"); } /************************************************************************/ int CountActiveLocks() /* Count the number of active locks == number of cfengines running */ { int count = 0; DBT key,value; DBC *dbcp; struct LockData entry; time_t elapsedtime; Debug("CountActiveLocks()\n"); if (IGNORELOCK) { return 1; } memset(&value,0,sizeof(value)); memset(&key,0,sizeof(key)); InitializeLocks(); if ((errno = DBP->cursor(DBP, NULL, &dbcp, 0)) != 0) { CfLog(cfverbose,"Couldn't dump lock db",""); return -1; } while ((errno = dbcp->c_get(dbcp, &key, &value, DB_NEXT)) == 0) { if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); elapsedtime = (time_t)(CFSTARTTIME-entry.time) / 60; if (elapsedtime >= VEXPIREAFTER) { Debug("LOCK-DB-EXPIRED: %s %s\n",ctime(&(entry.time)),key.data); continue; } Debug("LOCK-DB-DUMP : %s %s\n",ctime(&(entry.time)),key.data); if (strncmp(key.data,"lock",4) == 0) { count++; } } } CloseLocks(); Debug("Found %d active/concurrent cfengines",count); return count; } /************************************************************************/ /* Level 2 */ /************************************************************************/ time_t GetLastLock() { time_t mtime; Debug("GetLastLock()\n"); if ((mtime = GetLockTime(CFLAST)) == -1) { /* Do this to prevent deadlock loops from surviving if IfElapsed > T_sched */ if (PutLock(CFLAST) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to lock %s\n",CFLAST); CfLog(cferror,OUTPUT,""); return 0; } return 0; } else { return mtime; } } /************************************************************************/ time_t CheckOldLock() { time_t mtime; Debug("CheckOldLock(%s)\n",CFLOCK); if ((mtime = GetLockTime(CFLOCK)) == -1) { Debug("Unable to find lock data %s\n",CFLOCK); return 0; } else { Debug("Lock %s last ran at %s\n",CFLOCK,ctime(&mtime)); return mtime; } } /************************************************************************/ void SetLock() { Debug("SetLock(%s)\n",CFLOCK); if (PutLock(CFLOCK) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"GetLock: can't open new lock file %s\n",CFLOCK); CfLog(cferror,OUTPUT,"fopen"); FatalError(""); } } /**********************************************************************/ void SetSignals() { int i; SIGNALS[SIGHUP] = strdup("SIGHUP"); SIGNALS[SIGINT] = strdup("SIGINT"); SIGNALS[SIGTRAP] = strdup("SIGTRAP"); SIGNALS[SIGKILL] = strdup("SIGKILL"); SIGNALS[SIGPIPE] = strdup("SIGPIPE"); SIGNALS[SIGCONT] = strdup("SIGCONT"); SIGNALS[SIGABRT] = strdup("SIGABRT"); SIGNALS[SIGSTOP] = strdup("SIGSTOP"); SIGNALS[SIGQUIT] = strdup("SIGQUIT"); SIGNALS[SIGTERM] = strdup("SIGTERM"); SIGNALS[SIGCHLD] = strdup("SIGCHLD"); SIGNALS[SIGUSR1] = strdup("SIGUSR1"); SIGNALS[SIGUSR2] = strdup("SIGUSR2"); SIGNALS[SIGBUS] = strdup("SIGBUS"); SIGNALS[SIGSEGV] = strdup("SIGSEGV"); for (i = 0; i < highest_signal; i++) { if (SIGNALS[i] == NULL) { SIGNALS[i] = strdup("NOSIG"); } } } /************************************************************************/ /* Level 3 */ /************************************************************************/ int PutLock(char *name) { DBT key,value; struct LockData entry; Debug("PutLock(%s)\n",name); memset(&value,0,sizeof(value)); memset(&key,0,sizeof(key)); key.data = name; key.size = strlen(name)+1; InitializeLocks(); if (IGNORELOCK) { return 0; } if ((errno = DBP->del(DBP,NULL,&key,0)) != 0) { Debug("Found no lock [%s]: %s\n",name,db_strerror(errno)); } key.data = name; key.size = strlen(name)+1; entry.pid = getpid(); entry.time = time((time_t *)NULL); value.data = &entry; value.size = sizeof(entry); #if defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD if (pthread_mutex_lock(&MUTEX_LOCK) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock"); } #endif if ((errno = DBP->put(DBP,NULL,&key,&value,0)) != 0) { CfLog(cferror,"put failed","db->put"); CloseLocks(); return -1; } #if defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD if (pthread_mutex_unlock(&MUTEX_LOCK) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","unlock"); } #endif CloseLocks(); return 0; } /************************************************************************/ int DeleteLock(char *name) { DBT key; if (strcmp(name,"pre-lock-state") == 0) { return 0; } memset(&key,0,sizeof(key)); key.data = name; key.size = strlen(name)+1; #if defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD if (pthread_mutex_lock(&MUTEX_LOCK) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock"); } #endif InitializeLocks(); if ((errno = DBP->del(DBP,NULL,&key,0)) != 0) { Debug("Unable to delete lock [%s]: %s\n",name,db_strerror(errno)); } #if defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD if (pthread_mutex_unlock(&MUTEX_LOCK) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","unlock"); } #endif CloseLocks(); return 0; } /************************************************************************/ time_t GetLockTime(char *name) { DBT key,value; struct LockData entry; memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); memset(&entry,0,sizeof(entry)); key.data = name; key.size = strlen(name)+1; InitializeLocks(); if ((errno = DBP->get(DBP,NULL,&key,&value,0)) != 0) { CloseLocks(); return -1; } if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); CloseLocks(); return entry.time; } CloseLocks(); return -1; } /************************************************************************/ pid_t GetLockPid(char *name) { DBT key,value; struct LockData entry; memset(&value,0,sizeof(value)); memset(&key,0,sizeof(key)); key.data = name; key.size = strlen(name)+1; InitializeLocks(); if ((errno = DBP->get(DBP,NULL,&key,&value,0)) != 0) { CloseLocks(); return -1; } if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); CloseLocks(); return entry.pid; } CloseLocks(); return -1; } /************************************************************************/ void LockLog(int pid,char *str,char *operator,char *operand) { FILE *fp; char buffer[CF_MAXVARSIZE]; struct stat statbuf; time_t tim; Debug("LockLog(%s)\n",str); if ((fp = fopen(CFLOG,"a")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open lock-log file %s\n",CFLOG); CfLog(cferror,OUTPUT,"fopen"); FatalError(""); } if ((tim = time((time_t *)NULL)) == -1) { Debug("Cfengine: couldn't read system clock\n"); } sprintf(buffer,"%s",ctime(&tim)); Chop(buffer); fprintf(fp,"%s:%s:pid=%d:%s:%s\n",buffer,str,pid,operator,operand); fclose(fp); if (stat(CFLOG,&statbuf) != -1) { if (statbuf.st_size > CFLOGSIZE) { Verbose("Rotating lock-runlog file\n"); RotateFiles(CFLOG,2); } } } /************************************************************************/ void ExtractOpLock(char *op) { char *sp, lastch = 'x'; int i = 0, dots = 0; int offset = strlen("lock...")+strlen(VCANONICALFILE)+strlen(VUQNAME); for (sp = CFLOCK+offset; *sp != '\0'; sp++) { switch (*sp) { case '_': if (lastch == '_') { break; } else { op[i] = '/'; } break; case '.': dots++; op[i] = *sp; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': dots = 9; break; default: op[i] = *sp; break; } lastch = *sp; i++; if (dots > 1) { break; } } op[i] = '\0'; } cfengine-2.2.10/src/alerts.c0000644000175000001440000000570210645367567012543 00000000000000/* Copyright (C) 1995-2000 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: alerts.c */ /* */ /* Created: Sun Feb 2 20:26:21 2003 */ /* */ /* Author: > */ /* */ /* Revision: $Id$ */ /* */ /* Description: */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*******************************************************************/ void DoAlerts() { struct Item *ip; char ebuffer[CF_EXPANDSIZE]; Banner("Alerts"); for (ip = VALERTS; ip != NULL; ip=ip->next) { if (IsDefinedClass(ip->classes)) { if (!GetLock(ASUniqueName("alert"),CanonifyName(ip->name),ip->ifelapsed,ip->expireafter,VUQNAME,CFSTARTTIME)) { continue; } if (IsBuiltinFunction(ip->name)) { memset(ebuffer,0,CF_EXPANDSIZE); strncpy(ebuffer,EvaluateFunction(ip->name,ebuffer),CF_EXPANDSIZE-1); if (strlen(ebuffer) > 0) { printf("%s: %s\n",VPREFIX,ebuffer); } } else { ExpandVarstring(ip->name,ebuffer,NULL); CfLog(cferror,ebuffer,""); } ReleaseCurrentLock(); } else { Debug("Not evaluating %s::%s\n",ip->name,ip->classes); } } } cfengine-2.2.10/src/ipname.c0000644000175000001440000001246311077645430012510 00000000000000/* Copyright (C) 1995- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: ipname.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*****************************************************************************/ void StrCfenginePort() { struct servent *server; if ((server = getservbyname(CFENGINE_SERVICE,"tcp")) == NULL) { CfLog(cflogonly,"Couldn't get cfengine service, using default","getservbyname"); snprintf(STR_CFENGINEPORT,15,"5308"); } else { snprintf(STR_CFENGINEPORT,15,"%d",ntohs(server->s_port)); } Debug("Setting cfengine old port to %s\n",STR_CFENGINEPORT); } /*****************************************************************************/ char *Hostname2IPString(char *hostname) { static char ipbuffer[CF_SMALLBUF]; int err; #if defined(HAVE_GETADDRINFO) struct addrinfo query, *response, *ap; memset(&query,0,sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; memset(ipbuffer,0,CF_SMALLBUF-1); if ((err = getaddrinfo(hostname,NULL,&query,&response)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to lookup hostname (%s) or cfengine service: %s",hostname,gai_strerror(err)); CfLog(cferror,OUTPUT,""); return hostname; } for (ap = response; ap != NULL; ap = ap->ai_next) { strncpy(ipbuffer,sockaddr_ntop(ap->ai_addr),64); Debug("Found address (%s) for host %s\n",ipbuffer,hostname); if (strlen(ipbuffer) == 0) { snprintf(ipbuffer,CF_SMALLBUF-1,"Empty IP result for %s",hostname); } freeaddrinfo(response); return ipbuffer; } #else struct hostent *hp; struct sockaddr_in cin; memset(&cin,0,sizeof(cin)); memset(ipbuffer,0,CF_SMALLBUF-1); if ((hp = gethostbyname(hostname)) != NULL) { cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; strncpy(ipbuffer,inet_ntoa(cin.sin_addr),CF_SMALLBUF-1); Verbose("Found address (%s) for host %s\n",ipbuffer,hostname); return ipbuffer; } #endif snprintf(ipbuffer,CF_SMALLBUF-1,"Unknown IP %s",hostname); return ipbuffer; } /*****************************************************************************/ char *IPString2Hostname(char *ipaddress) { static char hostbuffer[MAXHOSTNAMELEN]; int err; #if defined(HAVE_GETADDRINFO) struct addrinfo query, *response, *ap; memset(&query,0,sizeof(query)); memset(&response,0,sizeof(response)); query.ai_flags = AI_CANONNAME; memset(hostbuffer,0,MAXHOSTNAMELEN); if ((err = getaddrinfo(ipaddress,NULL,&query,&response)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to lookup IP address (%s): %s",ipaddress,gai_strerror(err)); CfLog(cflogonly,OUTPUT,""); snprintf(hostbuffer,MAXHOSTNAMELEN-1,"(Non registered IP)"); return hostbuffer; } for (ap = response; ap != NULL; ap = ap->ai_next) { if ((err = getnameinfo(ap->ai_addr,ap->ai_addrlen,hostbuffer,MAXHOSTNAMELEN,0,0,0)) != 0) { snprintf(hostbuffer,MAXHOSTNAMELEN-1,"(Non registered IP)"); freeaddrinfo(response); return hostbuffer; } Debug("Found address (%s) for host %s\n",hostbuffer,ipaddress); freeaddrinfo(response); return hostbuffer; } snprintf(hostbuffer,MAXHOSTNAMELEN-1,"(Non registered IP)"); #else struct hostent *hp; struct sockaddr_in myaddr; struct in_addr iaddr; memset(hostbuffer,0,MAXHOSTNAMELEN); if ((iaddr.s_addr = inet_addr(ipaddress)) != -1) { hp = gethostbyaddr((void *)&iaddr,sizeof(struct sockaddr_in),AF_INET); if ((hp == NULL) || (hp->h_name == NULL)) { strcpy(hostbuffer,"(Non registered IP)"); return hostbuffer; } strncpy(hostbuffer,hp->h_name,MAXHOSTNAMELEN-1); } else { strcpy(hostbuffer,"(non registered IP)"); } #endif return hostbuffer; } /*****************************************************************************/ char *IPString2UQHostname(char *ipaddress) /* Return an unqualified hostname */ { static char hostbuffer[MAXHOSTNAMELEN]; char *sp; strcpy(hostbuffer,IPString2Hostname(ipaddress)); for (sp = hostbuffer; *sp != '\0'; sp++) { if (*sp == '.') { *sp = '\0'; break; } } return hostbuffer; } cfengine-2.2.10/src/patches.c0000644000175000001440000002000510741250450012644 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*********************************************************/ /* patches.c */ /* */ /* Contains any fixes which need to be made because of */ /* lack of OS support on a given platform */ /* These are conditionally compiled, pending extensions */ /* or developments in the OS concerned. */ /*********************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************/ int IntMin (int a,int b) { if (a > b) { return b; } else { return a; } } /*********************************************************/ char *StrStr(char *a,char *b) /* Case insensitive match */ { char buf1[CF_BUFSIZE],buf2[CF_BUFSIZE]; strncpy(buf1,ToLowerStr(a),CF_BUFSIZE-1); strncpy(buf2,ToLowerStr(b),CF_BUFSIZE-1); return strstr(buf1,buf2); } /*********************************************************/ int StrnCmp(char *a,char *b,size_t n) /* Case insensitive match */ { char buf1[CF_BUFSIZE],buf2[CF_BUFSIZE]; strncpy(buf1,ToLowerStr(a),CF_BUFSIZE-1); strncpy(buf2,ToLowerStr(b),CF_BUFSIZE-1); return strncmp(buf1,buf2,n); } /*********************************************************/ #ifndef HAVE_GETNETGRENT #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif /*********************************************************/ int setnetgrent(netgroup) const char *netgroup; { return 0; } /**********************************************************/ int getnetgrent(a,b,c) char **a, **b, **c; { *a=NULL; *b=NULL; *c=NULL; return 0; } /***********************************************************/ void endnetgrent() { } #endif #ifndef HAVE_UNAME #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif /***********************************************************/ /* UNAME is missing on some weird OSes */ /***********************************************************/ int uname (struct utsname *sys) { char buffer[CF_BUFSIZE], *sp; if (gethostname(buffer,CF_BUFSIZE) == -1) { perror("gethostname"); exit(1); } strcpy(sys->nodename,buffer); if (strcmp(buffer,AUTOCONF_HOSTNAME) != 0) { Verbose("This binary was complied on a different host (%s).\n",AUTOCONF_HOSTNAME); Verbose("This host does not have uname, so I can't tell if it is the exact same OS\n"); } strcpy(sys->sysname,AUTOCONF_SYSNAME); strcpy(sys->release,"cfengine-had-to-guess"); strcpy(sys->machine,"missing-uname(2)"); strcpy(sys->version,"unknown"); /* Extract a version number if possible */ for (sp = sys->sysname; *sp != '\0'; sp++) { if (isdigit(*sp)) { strcpy(sys->release,sp); strcpy(sys->version,sp); *sp = '\0'; break; } } return (0); } #endif /***********************************************************/ /* strstr() missing on old BSD systems */ /***********************************************************/ #ifndef HAVE_STRSTR #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif char *strstr(char *s1,char *s2) { char *sp; for (sp = s1; *sp != '\0'; sp++) { if (*sp != *s2) { continue; } if (strncmp(sp,s2,strlen(s2))== 0) { return sp; } } return NULL; } #endif /***********************************************************/ /* strdup() missing on old BSD systems */ /***********************************************************/ #ifndef HAVE_STRDUP char *strdup(char *str) { char *sp; if (str == NULL) { return NULL; } if ((sp = malloc(strlen(str)+1)) == NULL) { perror("malloc"); return NULL; } strcpy(sp,str); return sp; } #endif #ifndef HAVE_STRSEP char *strsep(char **stringp, const char *delim) { return strtok(*stringp,delim); } #endif /***********************************************************/ /* strrchr() missing on old BSD systems */ /***********************************************************/ #ifndef HAVE_STRRCHR char *strrchr(char *str,char ch) { char *sp; if (str == NULL) { return NULL; } if (strlen(str) == 0) { return NULL; } for (sp = str+strlen(str)-1; sp > str; sp--) { if (*sp == ch) { return *sp; } } return NULL; } #endif /***********************************************************/ /* strerror() missing on systems */ /***********************************************************/ #ifndef HAVE_STRERROR char *strerror(int err) { static char buffer[20]; sprintf(buffer,"Error number %d\n",err); return buffer; } #endif /***********************************************************/ /* putenv() missing on old BSD systems */ /***********************************************************/ #ifndef HAVE_PUTENV #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif int putenv(char *s) { Verbose("(This system does not have putenv: cannot update CFALLCLASSES\n"); return 0; } #endif /***********************************************************/ /* seteuid/gid() missing on some on posix systems */ /***********************************************************/ #ifndef HAVE_SETEUID #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif int seteuid (uid_t uid) { #ifdef HAVE_SETREUID return setreuid(-1,uid); #else Verbose("(This system does not have setreuid (patches.c)\n"); return -1; #endif } #endif /***********************************************************/ #ifndef HAVE_SETEGID #if !defined __STDC__ || !__STDC__ /* This is a separate conditional since some stdc systems reject `defined (const)'. */ # ifndef const # define const # endif #endif int setegid (gid_t gid) { #ifdef HAVE_SETREGID return setregid(-1,gid); #else Verbose("(This system does not have setregid (patches.c)\n"); return -1; #endif } #endif /*******************************************************************/ #ifndef HAVE_DRAND48 double drand48(void) { return (double)random(); } #endif #ifndef HAVE_DRAND48 void srand48(long seed) { srandom((unsigned int)seed); } #endif /*******************************************************************/ int IsPrivileged() { #ifdef NT return true; #else return (getuid() == 0); #endif } /*******************************************************************/ #ifndef HAVE_LIBRT int clock_gettime(clockid_t clock_id,struct timespec *tp) { static time_t now; now = time(NULL); tp->tv_sec = (time_t)now; tp->tv_nsec = 0; return 0; } #endif cfengine-2.2.10/src/cfenvd.c0000644000175000001440000001227211071703612012471 00000000000000/* Copyright (C) 2001- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: cfenvd.c */ /* */ /* Description: Long term state registry */ /* */ /* Based in part on results of the ECG project, by Mark, Sigmund Straumsnes */ /* and Hårek Haugerud, Oslo University College 1998 */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" struct option CFDENVOPTIONS[] = { {"help",no_argument,0,'h'}, {"debug",optional_argument,0,'d'}, {"verbose",no_argument,0,'v'}, {"no-fork",no_argument,0,'F'}, {"histograms",no_argument,0,'H'}, {"tcpdump",no_argument,0,'T'}, {NULL,0,0,0} }; extern int NO_FORK; extern int HISTO; extern short TCPDUMP; /*******************************************************************/ /* Prototypes */ /*******************************************************************/ void CheckOpts(int argc,char **argv); void Syntax (void); /*******************************************************************/ /* Level 0 : Main */ /*******************************************************************/ int main (int argc,char **argv) { CheckOpts(argc,argv); MonInitialize(); GetNameInfo(); GetInterfaceInfo(); GetV6InterfaceInfo(); StartServer(argc,argv); return 0; } /********************************************************************/ /* Level 1 */ /********************************************************************/ void CheckOpts(int argc,char **argv) { extern char *optarg; int optindex = 0; int c; umask(077); sprintf(VPREFIX,"cfenvd"); openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,LOG_DAEMON); strcpy(CFLOCK,"cfenvd"); SetContext("cfenvd"); IGNORELOCK = false; OUTPUT[0] = '\0'; while ((c=getopt_long(argc,argv,"d:vhHFVT",CFDENVOPTIONS,&optindex)) != EOF) { switch ((char) c) { case 'd': switch ((optarg==NULL)?3:*optarg) { case '1': D1 = true; break; case '2': D2 = true; break; default: DEBUG = true; break; } NO_FORK = true; printf("cfenvd: Debug mode: running in foreground\n"); break; case 'v': VERBOSE = true; break; case 'V': printf("GNU %s-%s daemon\n%s\n",PACKAGE,VERSION,COPYRIGHT); printf("This program is covered by the GNU Public License and may be\n"); printf("copied free of charge. No warrenty is implied.\n\n"); exit(0); break; case 'F': NO_FORK = true; break; case 'H': HISTO = true; break; case 'T': TCPDUMP = true; break; default: Syntax(); exit(1); } } LOGGING = true; /* Do output to syslog */ SetReferenceTime(false); SetStartTime(false); SetSignals(); signal (SIGTERM,HandleSignal); /* Signal Handler */ signal (SIGHUP,HandleSignal); signal (SIGINT,HandleSignal); signal (SIGPIPE,HandleSignal); signal (SIGSEGV,HandleSignal); signal (SIGUSR1,HandleSignal); signal (SIGUSR2,HandleSignal); } /*******************************************************************************/ void Syntax() { int i; printf("GNU cfengine environment daemon\n%s-%s\n%s\n",PACKAGE,VERSION,COPYRIGHT); printf("\n"); printf("Options:\n\n"); for (i=0; CFDENVOPTIONS[i].name != NULL; i++) { printf("--%-20s (-%c)\n",CFDENVOPTIONS[i].name,(char)CFDENVOPTIONS[i].val); } printf("\nBug reports to bug-cfengine@cfengine.org\n"); printf("General help to help-cfengine@cfengine.org\n"); printf("Info & fixes at http://www.cfengine.org\n"); } cfengine-2.2.10/src/env_monitor.c0000644000175000001440000017406711070670415013601 00000000000000/* Copyright (C) 2001- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: env_monitor.c */ /* */ /*****************************************************************************/ /* This file is hard-linked in cf2 and cf3 - for consistent maintenance */ #include "cf.defs.h" #include "cf.extern.h" #ifdef HAVE_SYS_LOADAVG_H # include #else # define LOADAVG_5MIN 1 #endif #include /*****************************************************************************/ /* Globals */ /*****************************************************************************/ unsigned int HISTOGRAM[CF_OBSERVABLES][7][CF_GRAINS]; int HISTO = false; /* persistent observations */ double THIS[CF_OBSERVABLES]; /* New from 2.1.21 replacing above - current observation */ /* Work */ int SLEEPTIME = 2.5 * 60; /* Should be a fraction of 5 minutes */ int BATCH_MODE = false; double ITER = 0.0; /* Iteration since start */ double AGE,WAGE; /* Age and weekly age of database */ char OUTPUT[CF_BUFSIZE*2]; char BATCHFILE[CF_BUFSIZE]; char STATELOG[CF_BUFSIZE]; char ENVCF_NEW[CF_BUFSIZE]; char ENVCF[CF_BUFSIZE]; short ACPI = false; short LMSENSORS = false; short SCLI = false; short TCPDUMP = false; short TCPPAUSE = false; FILE *TCPPIPE; struct Averages LOCALAV; struct Item *ALL_INCOMING = NULL; struct Item *ALL_OUTGOING = NULL; struct Item *NETIN_DIST[CF_NETATTR]; struct Item *NETOUT_DIST[CF_NETATTR]; /* Leap Detection vars */ double LDT_BUF[CF_OBSERVABLES][LDT_BUFSIZE]; double LDT_SUM[CF_OBSERVABLES]; double LDT_AVG[CF_OBSERVABLES]; double CHI_LIMIT[CF_OBSERVABLES]; double CHI[CF_OBSERVABLES]; double LDT_MAX[CF_OBSERVABLES]; int LDT_POS = 0; int LDT_FULL = false; /* Entropy etc */ double ENTROPY = 0.0; double LAST_HOUR_ENTROPY = 0.0; double LAST_DAY_ENTROPY = 0.0; struct Item *PREVIOUS_STATE = NULL; struct Item *ENTROPIES = NULL; int NO_FORK = false; double FORGETRATE = 0.6; int LASTQ[CF_OBSERVABLES]; /*******************************************************************/ /* Prototypes */ /*******************************************************************/ void MonInitialize(void); void StartServer (int argc, char **argv); void *ExitCleanly (void); void yyerror (char *s); void RotateFiles (char *s, int n); void GetDatabaseAge (void); void LoadHistogram (void); void GetQ (void); char *GetTimeKey (void); struct Averages EvalAvQ (char *timekey); void ArmClasses (struct Averages newvals,char *timekey); void OpenSniffer(void); void Sniff(void); void GatherProcessData (void); void GatherCPUData (void); void GatherDiskData (void); void GatherLoadData (void); void GatherSocketData (void); void GatherSNMPData(void); void GatherSensorData(void); void LeapDetection (void); struct Averages *GetCurrentAverages (char *timekey); void UpdateAverages (char *timekey, struct Averages newvals); void UpdateDistributions (char *timekey, struct Averages *av); double WAverage (double newvals,double oldvals, double age); double SetClasses (char *name,double variable,double av_expect,double av_var,double localav_expect,double localav_var,struct Item **classlist,char *timekey); void SetVariable (char *name,double now, double average, double stddev, struct Item **list); void RecordChangeOfState (struct Item *list,char *timekey); double RejectAnomaly (double new,double av,double var,double av2,double var2); void SetEntropyClasses (char *service,struct Item *list,char *inout); void AnalyzeArrival (char *tcpbuffer); void ZeroArrivals (void); void CfenvTimeOut (void); void IncrementCounter (struct Item **list,char *name); void SaveTCPEntropyData (struct Item *list,int i, char *inout); void ConvertDatabase(void); int GetFileGrowth(char *filename,enum observables index); int GetAcpi(void); int GetLMSensors(void); /****************************************************************/ void MonInitialize() { int i,j,k; struct stat statbuf; /* XXX Initialize workdir for non privileged users */ strcpy(CFWORKDIR,WORKDIR); #ifndef NT if (getuid() > 0) { char *homedir; if ((homedir = getenv("HOME")) != NULL) { strcpy(CFWORKDIR,homedir); strcat(CFWORKDIR,"/.cfagent"); } } #endif sprintf(VBUFF,"%s/test",CFWORKDIR); MakeDirectoriesFor(VBUFF,'y'); sprintf(VBUFF,"%s/state/test",CFWORKDIR); MakeDirectoriesFor(VBUFF,'y'); strncpy(VLOCKDIR,CFWORKDIR,CF_BUFSIZE-1); strncpy(VLOGDIR,CFWORKDIR,CF_BUFSIZE-1); for (i = 0; i < ATTR; i++) { sprintf(VBUFF,"%s/state/cf_incoming.%s",CFWORKDIR,ECGSOCKS[i].name); CreateEmptyFile(VBUFF); sprintf(VBUFF,"%s/state/cf_outgoing.%s",CFWORKDIR,ECGSOCKS[i].name); CreateEmptyFile(VBUFF); } for (i = 0; i < CF_NETATTR; i++) { NETIN_DIST[i] = NULL; NETOUT_DIST[i] = NULL; } sprintf(VBUFF,"%s/state/cf_users",CFWORKDIR); CreateEmptyFile(VBUFF); snprintf(AVDB,CF_MAXVARSIZE,"%s/state/%s",CFWORKDIR,CF_AVDB_FILE); snprintf(STATELOG,CF_BUFSIZE,"%s/state/%s",CFWORKDIR,CF_STATELOG_FILE); snprintf(ENVCF_NEW,CF_BUFSIZE,"%s/state/%s",CFWORKDIR,CF_ENVNEW_FILE); snprintf(ENVCF,CF_BUFSIZE,"%s/state/%s",CFWORKDIR,CF_ENV_FILE); if (!BATCH_MODE) { GetDatabaseAge(); for (i = 0; i < CF_OBSERVABLES; i++) { LOCALAV.Q[i].expect = 0.0; LOCALAV.Q[i].var = 0.0; LOCALAV.Q[i].q = 0.0; } } for (i = 0; i < 7; i++) { for (j = 0; j < CF_OBSERVABLES; j++) { for (k = 0; k < CF_GRAINS; k++) { HISTOGRAM[i][j][k] = 0; } } } for (i = 0; i < CF_OBSERVABLES; i++) { CHI[i] = 0; CHI_LIMIT[i] = 0.1; LDT_AVG[i] = 0; LDT_SUM[i] = 0; LASTQ[i] = 0; for (j = 0; j < LDT_BUFSIZE; j++) { LDT_BUF[i][j]; } } srand((unsigned int)time(NULL)); LoadHistogram(); ConvertDatabase(); /* Look for local sensors */ if (stat("/proc/acpi/thermal_zone",&statbuf) != -1) { Debug("Found an acpi service\n"); ACPI = true; } if (stat("/usr/bin/sensors",&statbuf) != -1) { if (statbuf.st_mode & 0111) { Debug("Found an lmsensor system\n"); LMSENSORS = true; } } Debug("Finished with initialization.\n"); } /*********************************************************************/ /* Level 2 */ /*********************************************************************/ void GetDatabaseAge() { int err_no; DBT key,value; DB *dbp; if ((err_no = db_create(&dbp,NULL,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't initialize average database %s\n",AVDB); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((err_no = (dbp->open)(dbp,AVDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((err_no = (dbp->open)(dbp,NULL,AVDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { AGE = WAGE = 0; snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open average database %s\n",AVDB); CfLog(cferror,OUTPUT,"db_open"); return; } chmod(AVDB,0644); memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); key.data = "DATABASE_AGE"; key.size = strlen("DATABASE_AGE")+1; if ((err_no = dbp->get(dbp,NULL,&key,&value,0)) != 0) { if (err_no != DB_NOTFOUND) { dbp->err(dbp,err_no,NULL); dbp->close(dbp,0); return; } } if (value.data != NULL) { AGE = *(double *)(value.data); WAGE = AGE / CF_WEEK * CF_MEASURE_INTERVAL; Debug("\n\nPrevious DATABASE_AGE %f\n\n",AGE); } else { Debug("No previous AGE\n"); AGE = 0.0; } dbp->close(dbp,0); } /*********************************************************************/ void LoadHistogram() { FILE *fp; int position,i,day; if (HISTO) { char filename[CF_BUFSIZE]; snprintf(filename,CF_BUFSIZE,"%s/state/histograms",CFWORKDIR); if ((fp = fopen(filename,"r")) == NULL) { CfLog(cfverbose,"Unable to load histogram data","fopen"); return; } for (position = 0; position < CF_GRAINS; position++) { fscanf(fp,"%d ",&position); for (i = 0; i < CF_OBSERVABLES; i++) { for (day = 0; day < 7; day++) { fscanf(fp,"%d ",&(HISTOGRAM[i][day][position])); } } } fclose(fp); } } /*********************************************************************/ void StartServer(int argc,char **argv) { char *timekey; struct Averages averages; int i; if ((!NO_FORK) && (fork() != 0)) { sprintf(OUTPUT,"cfenvd: starting\n"); CfLog(cfinform,OUTPUT,""); exit(0); } if (!NO_FORK) { ActAsDaemon(0); } WritePID("cfenvd.pid"); VCANONICALFILE = strdup("db"); if (!GetLock("cfenvd","daemon",0,1,"localhost",(time_t)time(NULL))) { return; } OpenSniffer(); while (true) { GetQ(); timekey = GetTimeKey(); averages = EvalAvQ(timekey); LeapDetection(); ArmClasses(averages,timekey); ZeroArrivals(); if (TCPDUMP) { Sniff(); } else { sleep(SLEEPTIME); } ITER++; } } /*********************************************************************/ /* Level 3 */ /*********************************************************************/ void CfenvTimeOut() { alarm(0); TCPPAUSE = true; Verbose("Time out\n"); } /*********************************************************************/ void ConvertDatabase() /* 2.1.11 introduces a new db format - this converts */ { struct stat statbuf; char filename[CF_BUFSIZE],new[CF_BUFSIZE],timekey[CF_BUFSIZE]; int i,errno,now; DBT key,value; DB *dbp; static struct OldAverages oldentry; static struct Averages newentry; snprintf(filename,CF_BUFSIZE-1,"%s/state/%s",CFWORKDIR,CF_OLDAVDB_FILE); snprintf(new,CF_BUFSIZE-1,"%s/state/%s",CFWORKDIR,CF_AVDB_FILE); if (stat(new,&statbuf) != -1) { return; } if (stat(filename,&statbuf) == -1) { return; } printf("Found old database %s\n",filename); if ((errno = db_create(&dbp,NULL,0)) != 0) { printf("Couldn't create average database %s\n",filename); exit(1); } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,filename,NULL,DB_BTREE,DB_RDONLY,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,filename,NULL,DB_BTREE,DB_RDONLY,0644)) != 0) #endif { printf("Couldn't open average database %s\n",filename); dbp->err(dbp,errno,NULL); exit(1); } memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); for (now = CF_MONDAY_MORNING; now < CF_MONDAY_MORNING+CF_WEEK; now += CF_MEASURE_INTERVAL) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); memset(&oldentry,0,sizeof(oldentry)); memset(&newentry,0,sizeof(newentry)); strcpy(timekey,GenTimeKey(now)); key.data = timekey; key.size = strlen(timekey)+1; if ((errno = dbp->get(dbp,NULL,&key,&value,0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp,errno,NULL); exit(1); } } if (value.data != NULL) { memcpy(&oldentry,value.data,sizeof(oldentry)); newentry.Q[ob_users].expect = oldentry.expect_number_of_users; newentry.Q[ob_rootprocs].expect = oldentry.expect_rootprocs; newentry.Q[ob_otherprocs].expect = oldentry.expect_otherprocs; newentry.Q[ob_diskfree].expect = oldentry.expect_diskfree; newentry.Q[ob_loadavg].expect = oldentry.expect_loadavg; newentry.Q[ob_rootprocs].expect = oldentry.expect_rootprocs; newentry.Q[ob_netbiosns_in].expect = oldentry.expect_incoming[0]; newentry.Q[ob_netbiosns_out].expect = oldentry.expect_outgoing[0]; newentry.Q[ob_netbiosdgm_in].expect = oldentry.expect_incoming[1]; newentry.Q[ob_netbiosdgm_out].expect = oldentry.expect_outgoing[1]; newentry.Q[ob_netbiosssn_in].expect = oldentry.expect_incoming[2]; newentry.Q[ob_netbiosssn_out].expect = oldentry.expect_outgoing[2]; newentry.Q[ob_irc_in].expect = oldentry.expect_incoming[3]; newentry.Q[ob_irc_out].expect = oldentry.expect_outgoing[3]; newentry.Q[ob_cfengine_in].expect = oldentry.expect_incoming[4]; newentry.Q[ob_cfengine_out].expect = oldentry.expect_outgoing[4]; newentry.Q[ob_nfsd_in].expect = oldentry.expect_incoming[5]; newentry.Q[ob_nfsd_out].expect = oldentry.expect_outgoing[5]; newentry.Q[ob_smtp_in].expect = oldentry.expect_incoming[6]; newentry.Q[ob_smtp_out].expect = oldentry.expect_outgoing[6]; newentry.Q[ob_www_in].expect = oldentry.expect_incoming[7]; newentry.Q[ob_www_out].expect = oldentry.expect_outgoing[7]; newentry.Q[ob_ftp_in].expect = oldentry.expect_incoming[8]; newentry.Q[ob_ftp_out].expect = oldentry.expect_outgoing[8]; newentry.Q[ob_ssh_in].expect = oldentry.expect_incoming[9]; newentry.Q[ob_ssh_out].expect = oldentry.expect_outgoing[9]; newentry.Q[ob_wwws_in].expect = oldentry.expect_incoming[10]; newentry.Q[ob_wwws_out].expect = oldentry.expect_outgoing[10]; newentry.Q[ob_icmp_in].expect = oldentry.expect_incoming[11]; newentry.Q[ob_icmp_out].expect = oldentry.expect_outgoing[11]; newentry.Q[ob_udp_in].expect = oldentry.expect_incoming[12]; newentry.Q[ob_udp_out].expect = oldentry.expect_outgoing[12]; newentry.Q[ob_dns_in].expect = oldentry.expect_incoming[13]; newentry.Q[ob_dns_out].expect = oldentry.expect_outgoing[13]; newentry.Q[ob_tcpsyn_in].expect = oldentry.expect_incoming[14]; newentry.Q[ob_tcpsyn_out].expect = oldentry.expect_outgoing[14]; newentry.Q[ob_tcpack_in].expect = oldentry.expect_incoming[15]; newentry.Q[ob_tcpack_out].expect = oldentry.expect_outgoing[15]; newentry.Q[ob_tcpfin_in].expect = oldentry.expect_incoming[16]; newentry.Q[ob_tcpfin_out].expect = oldentry.expect_outgoing[16]; newentry.Q[ob_tcpmisc_in].expect = oldentry.expect_incoming[17]; newentry.Q[ob_tcpmisc_out].expect = oldentry.expect_outgoing[17]; newentry.Q[ob_users].var = oldentry.var_number_of_users; newentry.Q[ob_rootprocs].var = oldentry.var_rootprocs; newentry.Q[ob_otherprocs].var = oldentry.var_otherprocs; newentry.Q[ob_diskfree].var = oldentry.var_diskfree; newentry.Q[ob_loadavg].var = oldentry.var_loadavg; newentry.Q[ob_rootprocs].var = oldentry.var_rootprocs; newentry.Q[ob_netbiosns_in].var = oldentry.var_incoming[0]; newentry.Q[ob_netbiosns_out].var = oldentry.var_outgoing[0]; newentry.Q[ob_netbiosdgm_in].var = oldentry.var_incoming[1]; newentry.Q[ob_netbiosdgm_out].var = oldentry.var_outgoing[1]; newentry.Q[ob_netbiosssn_in].var = oldentry.var_incoming[2]; newentry.Q[ob_netbiosssn_out].var = oldentry.var_outgoing[2]; newentry.Q[ob_irc_in].var = oldentry.var_incoming[3]; newentry.Q[ob_irc_out].var = oldentry.var_outgoing[3]; newentry.Q[ob_cfengine_in].var = oldentry.var_incoming[4]; newentry.Q[ob_cfengine_out].var = oldentry.var_outgoing[4]; newentry.Q[ob_nfsd_in].var = oldentry.var_incoming[5]; newentry.Q[ob_nfsd_out].var = oldentry.var_outgoing[5]; newentry.Q[ob_smtp_in].var = oldentry.var_incoming[6]; newentry.Q[ob_smtp_out].var = oldentry.var_outgoing[6]; newentry.Q[ob_www_in].var = oldentry.var_incoming[7]; newentry.Q[ob_www_out].var = oldentry.var_outgoing[7]; newentry.Q[ob_ftp_in].var = oldentry.var_incoming[8]; newentry.Q[ob_ftp_out].var = oldentry.var_outgoing[8]; newentry.Q[ob_ssh_in].var = oldentry.var_incoming[9]; newentry.Q[ob_ssh_out].var = oldentry.var_outgoing[9]; newentry.Q[ob_wwws_in].var = oldentry.var_incoming[10]; newentry.Q[ob_wwws_out].var = oldentry.var_outgoing[10]; newentry.Q[ob_icmp_in].var = oldentry.var_incoming[11]; newentry.Q[ob_icmp_out].var = oldentry.var_outgoing[11]; newentry.Q[ob_udp_in].var = oldentry.var_incoming[12]; newentry.Q[ob_udp_out].var = oldentry.var_outgoing[12]; newentry.Q[ob_dns_in].var = oldentry.var_incoming[13]; newentry.Q[ob_dns_out].var = oldentry.var_outgoing[13]; newentry.Q[ob_tcpsyn_in].var = oldentry.var_incoming[14]; newentry.Q[ob_tcpsyn_out].var = oldentry.var_outgoing[14]; newentry.Q[ob_tcpack_in].var = oldentry.var_incoming[15]; newentry.Q[ob_tcpack_out].var = oldentry.var_outgoing[15]; newentry.Q[ob_tcpfin_in].var = oldentry.var_incoming[16]; newentry.Q[ob_tcpfin_out].var = oldentry.var_outgoing[16]; newentry.Q[ob_tcpmisc_in].var = oldentry.var_incoming[17]; newentry.Q[ob_tcpmisc_out].var = oldentry.var_outgoing[17]; UpdateAverages(timekey,newentry); } } dbp->close(dbp,0); unlink(filename); printf("Converted and removed old database\n"); } /*********************************************************************/ void OpenSniffer() { char tcpbuffer[CF_BUFSIZE]; if (TCPDUMP) { struct stat statbuf; char buffer[CF_MAXVARSIZE]; sscanf(CF_TCPDUMP_COMM,"%s",buffer); if (stat(buffer,&statbuf) != -1) { if ((TCPPIPE = cfpopen(CF_TCPDUMP_COMM,"r")) == NULL) { TCPDUMP = false; } /* Skip first banner */ fgets(tcpbuffer,CF_BUFSIZE-1,TCPPIPE); } else { TCPDUMP = false; } } } /*********************************************************************/ void Sniff() { int i; char tcpbuffer[CF_BUFSIZE]; Verbose("Reading from tcpdump...\n"); memset(tcpbuffer,0,CF_BUFSIZE); signal(SIGALRM,(void *)CfenvTimeOut); alarm(SLEEPTIME); TCPPAUSE = false; while (!feof(TCPPIPE)) { if (TCPPAUSE) { break; } fgets(tcpbuffer,CF_BUFSIZE-1,TCPPIPE); if (TCPPAUSE) { break; } if (strstr(tcpbuffer,"tcpdump:")) /* Error message protect sleeptime */ { Debug("Error - (%s)\n",tcpbuffer); alarm(0); TCPDUMP = false; break; } AnalyzeArrival(tcpbuffer); } signal(SIGALRM,SIG_DFL); TCPPAUSE = false; fflush(TCPPIPE); } /*********************************************************************/ void GetQ() { int i; Debug("========================= GET Q ==============================\n"); ENTROPIES = NULL; GatherProcessData(); GatherCPUData(); GatherLoadData(); GatherDiskData(); GatherSocketData(); GatherSNMPData(); GatherSensorData(); } /*********************************************************************/ char *GetTimeKey() { time_t now; char str[CF_SMALLBUF]; if ((now = time((time_t *)NULL)) == -1) { exit(1); } sprintf(str,"%s",ctime(&now)); return ConvTimeKey(str); } /*********************************************************************/ struct Averages EvalAvQ(char *t) { struct Averages *currentvals,newvals; int i; double This[CF_OBSERVABLES],delta2; if ((currentvals = GetCurrentAverages(t)) == NULL) { CfLog(cferror,"Error reading average database",""); exit(1); } /* Discard any apparently anomalous behaviour before renormalizing database */ for (i = 0; i < CF_OBSERVABLES; i++) { double delta2; newvals.Q[i].q = THIS[i]; LOCALAV.Q[i].q = THIS[i]; /* Periodic */ This[i] = RejectAnomaly(THIS[i],currentvals->Q[i].expect,currentvals->Q[i].var,LOCALAV.Q[i].expect,LOCALAV.Q[i].var); Debug("Current %s.q %lf\n",OBS[i][0],currentvals->Q[i].q); Debug("Current %s.var %lf\n",OBS[i][0],currentvals->Q[i].var); Debug("Current %s.ex %lf\n",OBS[i][0],currentvals->Q[i].expect); Debug("THIS[%s] = %lf\n",OBS[i][0],THIS[i]); Debug("This[%s] = %lf\n",OBS[i][0],This[i]); newvals.Q[i].expect = WAverage(This[i],currentvals->Q[i].expect,WAGE); LOCALAV.Q[i].expect = WAverage(newvals.Q[i].expect,LOCALAV.Q[i].expect,ITER); delta2 = (This[i] - currentvals->Q[i].expect)*(This[i] - currentvals->Q[i].expect); newvals.Q[i].var = WAverage(delta2,currentvals->Q[i].var,WAGE); LOCALAV.Q[i].var = WAverage(newvals.Q[i].var,LOCALAV.Q[i].var,ITER); Verbose("New %s.q %lf\n",OBS[i][0],newvals.Q[i].q); Verbose("New %s.var %lf\n",OBS[i][0],newvals.Q[i].var); Verbose("New %s.ex %lf\n",OBS[i][0],newvals.Q[i].expect); Verbose("%s = %lf -> (%f#%f) local [%f#%f]\n",OBS[i][0],This[i],newvals.Q[i].expect,sqrt(newvals.Q[i].var),LOCALAV.Q[i].expect,sqrt(LOCALAV.Q[i].var)); if (This[i] > 0) { Verbose("Storing %.2f in %s\n",This[i],OBS[i][0]); } } UpdateAverages(t,newvals); if (WAGE > CFGRACEPERIOD) { UpdateDistributions(t,currentvals); /* Distribution about mean */ } return newvals; } /*********************************************************************/ void LeapDetection() { int i,j; double n1,n2,d; double padding = 0.2; if (++LDT_POS >= LDT_BUFSIZE) { LDT_POS = 0; if (!LDT_FULL) { snprintf(OUTPUT,CF_BUFSIZE,"LDT Buffer full at %d\n",LDT_BUFSIZE); CfLog(cfloginform,OUTPUT,""); LDT_FULL = true; } } for (i = 0; i < CF_OBSERVABLES; i++) { /* Note AVG should contain n+1 but not SUM, hence funny increments */ LDT_AVG[i] = LDT_AVG[i] + THIS[i]/((double)LDT_BUFSIZE + 1.0); d = (double)(LDT_BUFSIZE * (LDT_BUFSIZE + 1)) * LDT_AVG[i]; if (LDT_FULL && (LDT_POS == 0)) { n2 = (LDT_SUM[i] - (double)LDT_BUFSIZE * LDT_MAX[i]); if (d < 0.001) { CHI_LIMIT[i] = 0.5; } else { CHI_LIMIT[i] = padding + sqrt(n2*n2/d); } LDT_MAX[i] = 0.0; } if (THIS[i] > LDT_MAX[i]) { LDT_MAX[i] = THIS[i]; } n1 = (LDT_SUM[i] - (double)LDT_BUFSIZE * THIS[i]); if (d < 0.001) { CHI[i] = 0.0; } else { CHI[i] = sqrt(n1*n1/d); } LDT_AVG[i] = LDT_AVG[i] - LDT_BUF[i][LDT_POS]/((double)LDT_BUFSIZE + 1.0); LDT_BUF[i][LDT_POS] = THIS[i]; LDT_SUM[i] = LDT_SUM[i] - LDT_BUF[i][LDT_POS] + THIS[i]; } } /*********************************************************************/ void ArmClasses(struct Averages av,char *timekey) { double sigma; struct Item *classlist = NULL, *ip; int i,j,k,pos; FILE *fp; char buff[CF_BUFSIZE],ldt_buff[CF_BUFSIZE]; static int anomaly[CF_OBSERVABLES][LDT_BUFSIZE]; static double anomaly_chi[CF_OBSERVABLES]; static double anomaly_chi_limit[CF_OBSERVABLES]; Debug("Arm classes for %s\n",timekey); for (i = 0; i < CF_OBSERVABLES; i++) { sigma = SetClasses(OBS[i][0],THIS[i],av.Q[i].expect,av.Q[i].var,LOCALAV.Q[i].expect,LOCALAV.Q[i].var,&classlist,timekey); SetVariable(OBS[i][0],THIS[i],av.Q[i].expect,sigma,&classlist); /* LDT */ ldt_buff[0] = '\0'; anomaly[i][LDT_POS] = false; if (!LDT_FULL) { anomaly[i][LDT_POS] = false; anomaly_chi[i] = 0.0; anomaly_chi_limit[i] = 0.0; } if (LDT_FULL && (CHI[i] > CHI_LIMIT[i])) { anomaly[i][LDT_POS] = true; /* Remember the last anomaly value */ anomaly_chi[i] = CHI[i]; anomaly_chi_limit[i] = CHI_LIMIT[i]; snprintf(OUTPUT,CF_BUFSIZE,"LDT(%d) in %s chi = %.2f thresh %.2f \n",LDT_POS,OBS[i][0],CHI[i],CHI_LIMIT[i]); if (VERBOSE) { CfLog(cfloginform,OUTPUT,""); } Verbose(OUTPUT); snprintf(OUTPUT,CF_BUFSIZE,"LDT_BUF (%s): Rot ",OBS[i][0]); /* Last printed element is now */ for (j = LDT_POS+1, k = 0; k < LDT_BUFSIZE; j++,k++) { if (j == LDT_BUFSIZE) /* Wrap */ { j = 0; } if (anomaly[i][j]) { snprintf(buff,CF_BUFSIZE," *%.2f*",LDT_BUF[i][j]); } else { snprintf(buff,CF_BUFSIZE," %.2f",LDT_BUF[i][j]); } strcat(OUTPUT,buff); strcat(ldt_buff,buff); } strcat(OUTPUT,"\n"); if (VERBOSE) { CfLog(cfloginform,OUTPUT,""); } Verbose(OUTPUT); if (THIS[i] > av.Q[i].expect) { snprintf(OUTPUT,CF_BUFSIZE,"%s_high_ldt",OBS[i][0]); } else { snprintf(OUTPUT,CF_BUFSIZE,"%s_high_ldt",OBS[i][0]); } AppendItem(&classlist,OUTPUT,"2"); AddPersistentClass(OUTPUT,CF_PERSISTENCE,cfpreserve); } else { for (j = LDT_POS+1, k = 0; k < LDT_BUFSIZE; j++,k++) { if (j == LDT_BUFSIZE) /* Wrap */ { j = 0; } if (anomaly[i][j]) { snprintf(buff,CF_BUFSIZE," *%.2f*",LDT_BUF[i][j]); } else { snprintf(buff,CF_BUFSIZE," %.2f",LDT_BUF[i][j]); } strcat(ldt_buff,buff); } } snprintf(buff,CF_MAXVARSIZE,"ldtbuf_%s=%s",OBS[i][0],ldt_buff); AppendItem(&classlist,buff,""); snprintf(buff,CF_MAXVARSIZE,"ldtchi_%s=%.2f",OBS[i][0],anomaly_chi[i]); AppendItem(&classlist,buff,""); snprintf(buff,CF_MAXVARSIZE,"ldtlimit_%s=%.2f",OBS[i][0],anomaly_chi_limit[i]); AppendItem(&classlist,buff,""); } /* Publish class list */ unlink(ENVCF_NEW); if ((fp = fopen(ENVCF_NEW,"a")) == NULL) { DeleteItemList(PREVIOUS_STATE); PREVIOUS_STATE = classlist; return; } for (ip = classlist; ip != NULL; ip=ip->next) { fprintf(fp,"%s\n",ip->name); } DeleteItemList(PREVIOUS_STATE); PREVIOUS_STATE = classlist; for (ip = ENTROPIES; ip != NULL; ip=ip->next) { fprintf(fp,"%s\n",ip->name); } DeleteItemList(ENTROPIES); fclose(fp); rename(ENVCF_NEW,ENVCF); } /*********************************************************************/ void AnalyzeArrival(char *arrival) /* This coarsely classifies TCP dump data */ { char src[CF_BUFSIZE],dest[CF_BUFSIZE], flag = '.', *arr; int isme_dest, isme_src; src[0] = dest[0] = '\0'; if (strstr(arrival,"listening")) { return; } Chop(arrival); /* Most hosts have only a few dominant services, so anomalies will show up even in the traffic without looking too closely. This will apply only to the main interface .. not multifaces New format in tcpdump IP (tos 0x10, ttl 64, id 14587, offset 0, flags [DF], proto TCP (6), length 692) 128.39.89.232.22 > 84.215.40.125.48022: P 1546432:1547072(640) ack 1969 win 1593 IP (tos 0x0, ttl 251, id 14109, offset 0, flags [DF], proto UDP (17), length 115) 84.208.20.110.53 > 192.168.1.103.32769: 45266 NXDomain 0/1/0 (87) arp who-has 192.168.1.1 tell 192.168.1.103 arp reply 192.168.1.1 is-at 00:1d:7e:28:22:c6 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.1.103 > 128.39.89.10: ICMP echo request, id 48474, seq 1, length 64 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto ICMP (1), length 84) 192.168.1.103 > 128.39.89.10: ICMP echo request, id 48474, seq 2, length 64 */ for (arr = strstr(arrival,"length"); arr != NULL && *arr != ')'; arr++) { } if (arr == NULL) { arr = arrival; } else { arr++; } if (strstr(arrival,"proto TCP") || strstr(arrival,"ack")) { sscanf(arr,"%s %*c %s %c ",src,dest,&flag); DePort(src); DePort(dest); isme_dest = IsInterfaceAddress(dest); isme_src = IsInterfaceAddress(src); switch (flag) { case 'S': Debug("%1.1f: TCP new connection from %s to %s - i am %s\n",ITER,src,dest,VIPADDRESS); if (isme_dest) { THIS[ob_tcpsyn_in]++; IncrementCounter(&(NETIN_DIST[tcpsyn]),src); } else if (isme_src) { THIS[ob_tcpsyn_out]++; IncrementCounter(&(NETOUT_DIST[tcpsyn]),dest); } break; case 'F': Debug("%1.1f: TCP end connection from %s to %s\n",ITER,src,dest); if (isme_dest) { THIS[ob_tcpfin_in]++; IncrementCounter(&(NETIN_DIST[tcpfin]),src); } else if (isme_src) { THIS[ob_tcpfin_out]++; IncrementCounter(&(NETOUT_DIST[tcpfin]),dest); } break; default: Debug("%1.1f: TCP established from %s to %s\n",ITER,src,dest); if (isme_dest) { THIS[ob_tcpack_in]++; IncrementCounter(&(NETIN_DIST[tcpack]),src); } else if (isme_src) { THIS[ob_tcpack_out]++; IncrementCounter(&(NETOUT_DIST[tcpack]),dest); } break; } } else if (strstr(arrival,".53")) { sscanf(arr,"%s %*c %s %c ",src,dest,&flag); DePort(src); DePort(dest); isme_dest = IsInterfaceAddress(dest); isme_src = IsInterfaceAddress(src); Debug("%1.1f: DNS packet from %s to %s\n",ITER,src,dest); if (isme_dest) { THIS[ob_dns_in]++; IncrementCounter(&(NETIN_DIST[dns]),src); } else if (isme_src) { THIS[ob_dns_out]++; IncrementCounter(&(NETOUT_DIST[tcpack]),dest); } } else if (strstr(arrival,"proto UDP")) { sscanf(arr,"%s %*c %s %c ",src,dest,&flag); DePort(src); DePort(dest); isme_dest = IsInterfaceAddress(dest); isme_src = IsInterfaceAddress(src); Debug("%1.1f: UDP packet from %s to %s\n",ITER,src,dest); if (isme_dest) { THIS[ob_udp_in]++; IncrementCounter(&(NETIN_DIST[udp]),src); } else if (isme_src) { THIS[ob_udp_out]++; IncrementCounter(&(NETOUT_DIST[udp]),dest); } } else if (strstr(arrival,"proto ICMP")) { sscanf(arr,"%s %*c %s %c ",src,dest,&flag); DePort(src); DePort(dest); isme_dest = IsInterfaceAddress(dest); isme_src = IsInterfaceAddress(src); Debug("%1.1f: ICMP packet from %s to %s\n",ITER,src,dest); if (isme_dest) { THIS[ob_icmp_in]++; IncrementCounter(&(NETIN_DIST[icmp]),src); } else if (isme_src) { THIS[ob_icmp_out]++; IncrementCounter(&(NETOUT_DIST[icmp]),src); } } else { Debug("%1.1f: Miscellaneous undirected packet (%.100s)\n",ITER,arrival); THIS[ob_tcpmisc_in]++; /* Here we don't know what source will be, but .... */ sscanf(arrival,"%s",src); if (!isdigit((int)*src)) { Debug("Assuming continuation line...\n"); return; } DePort(src); if (strstr(arrival,".138")) { snprintf(dest,CF_BUFSIZE-1,"%s NETBIOS",src); } else if (strstr(arrival,".2049")) { snprintf(dest,CF_BUFSIZE-1,"%s NFS",src); } else { strncpy(dest,src,60); } IncrementCounter(&(NETIN_DIST[tcpmisc]),dest); } } /*********************************************************************/ /* Level 4 */ /*********************************************************************/ void GatherProcessData() { FILE *pp; char pscomm[CF_BUFSIZE]; char user[CF_MAXVARSIZE]; struct Item *list = NULL; snprintf(pscomm,CF_BUFSIZE,"%s %s",VPSCOMM[VSYSTEMHARDCLASS],VPSOPTS[VSYSTEMHARDCLASS]); if ((pp = cfpopen(pscomm,"r")) == NULL) { return; } ReadLine(VBUFF,CF_BUFSIZE,pp); while (!feof(pp)) { ReadLine(VBUFF,CF_BUFSIZE,pp); sscanf(VBUFF,"%s",user); if (!IsItemIn(list,user)) { PrependItem(&list,user,NULL); THIS[ob_users]++; } if (strcmp(user,"root") == 0) { THIS[ob_rootprocs]++; } else { THIS[ob_otherprocs]++; } } cfpclose(pp); snprintf(VBUFF,CF_MAXVARSIZE,"%s/state/cf_users",CFWORKDIR); SaveItemList(list,VBUFF,"none"); DeleteItemList(list); Verbose("(Users,root,other) = (%d,%d,%d)\n",THIS[ob_users],THIS[ob_rootprocs],THIS[ob_otherprocs]); } /*****************************************************************************/ void GatherCPUData() { double q,dq; char name[CF_MAXVARSIZE],cpuname[CF_MAXVARSIZE],buf[CF_BUFSIZE]; int count,userticks=0,niceticks=0,systemticks=0,idle=0,iowait=0,irq=0,softirq=0; int total_time = 1; FILE *fp; enum observables index = ob_spare; if ((fp=fopen("/proc/stat","r")) == NULL) { Verbose("Didn't find proc data\n"); return; } Verbose("Reading /proc/stat utilization data -------\n"); count = 0; while (!feof(fp)) { fgets(buf,CF_BUFSIZE,fp); sscanf(buf,"%s%d%d%d%d%d%d%d",&cpuname,&userticks,&niceticks,&systemticks,&idle,&iowait,&irq,&softirq); snprintf(name,16,"cpu%d",count); total_time = (userticks+niceticks+systemticks+idle); q = 100.0 * (double)(total_time - idle); if (strncmp(cpuname,name,strlen(name)) == 0) { Verbose("Found CPU %d\n",count); switch (count++) { case 0: index = ob_cpu0; break; case 1: index = ob_cpu1; break; case 2: index = ob_cpu2; break; case 3: index = ob_cpu3; break; default: index = ob_spare; Verbose("Error reading proc/stat\n"); continue; } } else if (strncmp(cpuname,"cpu",3) == 0) { Verbose("Found aggregate CPU\n",count); index = ob_cpuall; } else { Verbose("Found nothing (%s)\n",cpuname); index = ob_spare; fclose(fp); return; } dq = (q - LASTQ[index])/(double)total_time; /* % Utilization */ THIS[index] = dq; LASTQ[index] = q; Verbose("Set %s=%d to %.1f after %d 100ths of a second \n",OBS[index][1],index,q,total_time); } fclose(fp); } /*****************************************************************************/ void GatherDiskData() { char accesslog[CF_BUFSIZE]; char errorlog[CF_BUFSIZE]; char syslog[CF_BUFSIZE]; char messages[CF_BUFSIZE]; Verbose("Gathering disk data\n"); THIS[ob_diskfree] = GetDiskUsage("/",cfpercent); Verbose("Disk free = %d %%\n",THIS[ob_diskfree]); /* Here would should have some detection based on OS type VSYSTEMHARDCLASS */ switch(VSYSTEMHARDCLASS) { linuxx: default: strcpy(accesslog,"/var/log/apache2/access_log"); strcpy(errorlog,"/var/log/apache2/error_log"); strcpy(syslog,"/var/log/syslog"); strcpy(messages,"/var/log/messages"); } THIS[ob_webaccess] = GetFileGrowth(accesslog,ob_webaccess); Verbose("Webaccess = %d %%\n",THIS[ob_webaccess]); THIS[ob_weberrors] = GetFileGrowth(errorlog,ob_weberrors); Verbose("Web error = %d %%\n",THIS[ob_weberrors]); THIS[ob_syslog] = GetFileGrowth(syslog,ob_syslog); Verbose("Syslog = %d %%\n",THIS[ob_syslog]); THIS[ob_messages] = GetFileGrowth(messages,ob_messages); Verbose("Messages = %d %%\n",THIS[ob_messages]); } /*****************************************************************************/ void GatherLoadData() { double load[4] = {0,0,0,0}, sum = 0.0; int i,n = 1; Debug("GatherLoadData\n\n"); #ifdef HAVE_GETLOADAVG if ((n = getloadavg(load,LOADAVG_5MIN)) == -1) { THIS[ob_loadavg] = 0.0; } else { for (i = 0; i < n; i++) { Debug("Found load average to be %lf of %d samples\n", load[i],n); sum += load[i]; } } #endif /* Scale load average by 100 to make it visible */ THIS[ob_loadavg] = (int) (100.0 * sum); Verbose("100 x Load Average = %d\n",THIS[ob_loadavg]); } /*****************************************************************************/ void GatherSocketData() { FILE *pp; char local[CF_BUFSIZE],remote[CF_BUFSIZE],comm[CF_BUFSIZE]; struct Item *in[ATTR],*out[ATTR]; char *sp; int i; Debug("GatherSocketData()\n"); for (i = 0; i < ATTR; i++) { in[i] = out[i] = NULL; } if (ALL_INCOMING != NULL) { DeleteItemList(ALL_INCOMING); ALL_INCOMING = NULL; } if (ALL_OUTGOING != NULL) { DeleteItemList(ALL_OUTGOING); ALL_OUTGOING = NULL; } sscanf(VNETSTAT[VSYSTEMHARDCLASS],"%s",comm); strcat(comm," -n"); if ((pp = cfpopen(comm,"r")) == NULL) { return; } while (!feof(pp)) { memset(local,0,CF_BUFSIZE); memset(remote,0,CF_BUFSIZE); ReadLine(VBUFF,CF_BUFSIZE,pp); if (strstr(VBUFF,"UNIX")) { break; } if (!strstr(VBUFF,".")) { continue; } /* Different formats here ... ugh.. */ if (strncmp(VBUFF,"tcp",3) == 0) { sscanf(VBUFF,"%*s %*s %*s %s %s",local,remote); /* linux-like */ } else { sscanf(VBUFF,"%s %s",local,remote); /* solaris-like */ } if (strlen(local) == 0) { continue; } for (sp = local+strlen(local); (*sp != '.') && (sp > local); sp--) { } sp++; if ((strlen(sp) < 5) &&!IsItemIn(ALL_INCOMING,sp)) { PrependItem(&ALL_INCOMING,sp,NULL); } for (sp = remote+strlen(remote); (sp >= remote) && !isdigit((int)*sp); sp--) { } sp++; if ((strlen(sp) < 5) && !IsItemIn(ALL_OUTGOING,sp)) { PrependItem(&ALL_OUTGOING,sp,NULL); } for (i = 0; i < ATTR; i++) { char *spend; for (spend = local+strlen(local)-1; isdigit((int)*spend); spend--) { } spend++; if (strcmp(spend,ECGSOCKS[i].portnr) == 0) { THIS[ECGSOCKS[i].in]++; AppendItem(&in[i],VBUFF,""); } for (spend = remote+strlen(remote)-1; (sp >= remote) && isdigit((int)*spend); spend--) { } spend++; if (strcmp(spend,ECGSOCKS[i].portnr) == 0) { THIS[ECGSOCKS[i].out]++; AppendItem(&out[i],VBUFF,""); } } } cfpclose(pp); /* Now save the state for ShowState() alert function IFF the state is not smaller than the last or at least 40 minutes older. This mirrors the persistence of the maxima classes */ for (i = 0; i < ATTR; i++) { struct stat statbuf; time_t now = time(NULL); Debug("save incoming %s\n",ECGSOCKS[i].name); snprintf(VBUFF,CF_MAXVARSIZE,"%s/state/cf_incoming.%s",CFWORKDIR,ECGSOCKS[i].name); if (stat(VBUFF,&statbuf) != -1) { if ((ByteSizeList(in[i]) < statbuf.st_size) && (now < statbuf.st_mtime+40*60)) { Verbose("New state %s is smaller, retaining old for 40 mins longer\n",ECGSOCKS[i].name); DeleteItemList(in[i]); continue; } } SetEntropyClasses(ECGSOCKS[i].name,in[i],"in"); SaveItemList(in[i],VBUFF,"none"); DeleteItemList(in[i]); Debug("Saved in netstat data in %s\n",VBUFF); } for (i = 0; i < ATTR; i++) { struct stat statbuf; time_t now = time(NULL); Debug("save outgoing %s\n",ECGSOCKS[i].name); snprintf(VBUFF,CF_MAXVARSIZE,"%s/state/cf_outgoing.%s",CFWORKDIR,ECGSOCKS[i].name); if (stat(VBUFF,&statbuf) != -1) { if ((ByteSizeList(out[i]) < statbuf.st_size) && (now < statbuf.st_mtime+40*60)) { Verbose("New state %s is smaller, retaining old for 40 mins longer\n",ECGSOCKS[i].name); DeleteItemList(out[i]); continue; } } SetEntropyClasses(ECGSOCKS[i].name,out[i],"out"); SaveItemList(out[i],VBUFF,"none"); Debug("Saved out netstat data in %s\n",VBUFF); DeleteItemList(out[i]); } for (i = 0; i < CF_NETATTR; i++) { struct stat statbuf; time_t now = time(NULL); Debug("save incoming %s\n",TCPNAMES[i]); snprintf(VBUFF,CF_MAXVARSIZE,"%s/state/cf_incoming.%s",CFWORKDIR,TCPNAMES[i]); if (stat(VBUFF,&statbuf) != -1) { if ((ByteSizeList(NETIN_DIST[i]) < statbuf.st_size) && (now < statbuf.st_mtime+40*60)) { Verbose("New state %s is smaller, retaining old for 40 mins longer\n",TCPNAMES[i]); DeleteItemList(NETIN_DIST[i]); NETIN_DIST[i] = NULL; continue; } } SaveTCPEntropyData(NETIN_DIST[i],i,"in"); SetEntropyClasses(TCPNAMES[i],NETIN_DIST[i],"in"); DeleteItemList(NETIN_DIST[i]); NETIN_DIST[i] = NULL; } for (i = 0; i < CF_NETATTR; i++) { struct stat statbuf; time_t now = time(NULL); Debug("save outgoing %s\n",TCPNAMES[i]); snprintf(VBUFF,CF_MAXVARSIZE,"%s/state/cf_outgoing.%s",CFWORKDIR,TCPNAMES[i]); if (stat(VBUFF,&statbuf) != -1) { if ((ByteSizeList(NETOUT_DIST[i]) < statbuf.st_size) && (now < statbuf.st_mtime+40*60)) { Verbose("New state %s is smaller, retaining old for 40 mins longer\n",TCPNAMES[i]); DeleteItemList(NETOUT_DIST[i]); NETOUT_DIST[i] = NULL; continue; } } SaveTCPEntropyData(NETOUT_DIST[i],i,"out"); SetEntropyClasses(TCPNAMES[i],NETOUT_DIST[i],"out"); DeleteItemList(NETOUT_DIST[i]); NETOUT_DIST[i] = NULL; } } /*****************************************************************************/ void GatherSNMPData() { char snmpbuffer[CF_BUFSIZE]; FILE *pp; /* This is for collecting known counters. */ if (SCLI) { struct stat statbuf; char buffer[CF_MAXVARSIZE]; sscanf(CF_SCLI_COMM,"%s",buffer); if (stat(buffer,&statbuf) != -1) { if ((pp = cfpopen(CF_SCLI_COMM,"r")) == NULL) { return; } /* Skip first banner */ fgets(snmpbuffer,CF_BUFSIZE-1,pp); } } } /*****************************************************************************/ struct Averages *GetCurrentAverages(char *timekey) { int err_no; DBT key,value; DB *dbp; static struct Averages entry; if ((err_no = db_create(&dbp,NULL,0)) != 0) { sprintf(OUTPUT,"Couldn't initialize average database %s\n",AVDB); CfLog(cferror,OUTPUT,"db_open"); return NULL; } #ifdef CF_OLD_DB if ((err_no = (dbp->open)(dbp,AVDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((err_no = (dbp->open)(dbp,NULL,AVDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { sprintf(OUTPUT,"Couldn't open average database %s\n",AVDB); CfLog(cferror,OUTPUT,"db_open"); return NULL; } memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); memset(&entry,0,sizeof(entry)); key.data = timekey; key.size = strlen(timekey)+1; if ((err_no = dbp->get(dbp,NULL,&key,&value,0)) != 0) { if (err_no != DB_NOTFOUND) { dbp->err(dbp,err_no,NULL); dbp->close(dbp,0); return NULL; } } AGE++; WAGE = AGE / CF_WEEK * CF_MEASURE_INTERVAL; if (value.data != NULL) { int i; memcpy(&entry,value.data,sizeof(entry)); for (i = 0; i < CF_OBSERVABLES; i++) { Debug("Previous values (%lf,..) for time index %s\n\n",entry.Q[i].expect,timekey); } dbp->close(dbp,0); return &entry; } else { Debug("No previous value for time index %s\n",timekey); dbp->close(dbp,0); return &entry; } } /*****************************************************************************/ void UpdateAverages(char *timekey,struct Averages newvals) { int err_no; DBT key,value; DB *dbp; if ((err_no = db_create(&dbp,NULL,0)) != 0) { sprintf(OUTPUT,"Couldn't open average database %s\n",AVDB); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((err_no = (dbp->open)(dbp,AVDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((err_no = (dbp->open)(dbp,NULL,AVDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { sprintf(OUTPUT,"Couldn't open average database %s\n",AVDB); CfLog(cferror,OUTPUT,"db_open"); return; } memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); key.data = timekey; key.size = strlen(timekey)+1; value.data = &newvals; value.size = sizeof(newvals); if ((err_no = dbp->put(dbp,NULL,&key,&value,0)) != 0) { dbp->err(dbp,err_no,NULL); dbp->close(dbp,0); return; } memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); value.data = &AGE; value.size = sizeof(double); key.data = "DATABASE_AGE"; key.size = strlen("DATABASE_AGE")+1; if ((err_no = dbp->put(dbp,NULL,&key,&value,0)) != 0) { dbp->err(dbp,err_no,NULL); dbp->close(dbp,0); return; } dbp->close(dbp,0); } /*****************************************************************************/ void UpdateDistributions(char *timekey,struct Averages *av) { int position; int day,i,time_to_update = true; /* Take an interval of 4 standard deviations from -2 to +2, divided into CF_GRAINS parts. Centre each measurement on CF_GRAINS/2 and scale each measurement by the std-deviation for the current time. */ if (HISTO) { time_to_update = (int) (3600.0*rand()/(RAND_MAX+1.0)) > 2400; day = Day2Number(timekey); for (i = 0; i < CF_OBSERVABLES; i++) { position = CF_GRAINS/2 + (int)(0.5+(THIS[i] - av->Q[i].expect)*CF_GRAINS/(4*sqrt((av->Q[i].var)))); if (0 <= position && position < CF_GRAINS) { HISTOGRAM[i][day][position]++; } } if (time_to_update) { FILE *fp; char filename[CF_BUFSIZE]; snprintf(filename,CF_BUFSIZE,"%s/state/histograms",CFWORKDIR); if ((fp = fopen(filename,"w")) == NULL) { CfLog(cferror,"Unable to save histograms","fopen"); return; } for (position = 0; position < CF_GRAINS; position++) { fprintf(fp,"%u ",position); for (i = 0; i < CF_OBSERVABLES; i++) { for (day = 0; day < 7; day++) { fprintf(fp,"%u ",HISTOGRAM[i][day][position]); } } fprintf(fp,"\n"); } fclose(fp); } } } /*****************************************************************************/ double WAverage(double anew,double aold,double age) /* For a couple of weeks, learn eagerly. Otherwise variances will be way too large. Then downplay newer data somewhat, and rely on experience of a couple of months of data ... */ { double av; double wnew,wold; if (FORGETRATE > 0.9 || FORGETRATE < 0.1) { FORGETRATE = 0.7; } if (age < 2.0) /* More aggressive learning for young database */ { wnew = FORGETRATE; wold = (1.0-FORGETRATE); } else { wnew = (1.0-FORGETRATE); wold = FORGETRATE; } av = (wnew*anew + wold*aold)/(wnew+wold); return av; } /*****************************************************************************/ double SetClasses(char * name,double variable,double av_expect,double av_var,double localav_expect,double localav_var,struct Item **classlist,char *timekey) { char buffer[CF_BUFSIZE],buffer2[CF_BUFSIZE]; double dev,delta,sigma,ldelta,lsigma,sig; Debug("\n SetClasses(%s,X=%f,avX=%f,varX=%f,lavX=%f,lvarX=%f,%s)\n",name,variable,av_expect,av_var,localav_expect,localav_var,timekey); delta = variable - av_expect; sigma = sqrt(av_var); ldelta = variable - localav_expect; lsigma = sqrt(localav_var); sig = sqrt(sigma*sigma+lsigma*lsigma); Debug(" delta = %f,sigma = %f, lsigma = %f, sig = %f\n",delta,sigma,lsigma,sig); if (sigma == 0.0 || lsigma == 0.0) { Debug(" No sigma variation .. can't measure class\n"); return sig; } Debug("Setting classes for %s...\n",name); if (fabs(delta) < cf_noise_threshold) /* Arbitrary limits on sensitivity */ { Debug(" Sensitivity too high ..\n"); buffer[0] = '\0'; strcpy(buffer,name); if ((delta > 0) && (ldelta > 0)) { strcat(buffer,"_high"); } else if ((delta < 0) && (ldelta < 0)) { strcat(buffer,"_low"); } else { strcat(buffer,"_normal"); } dev = sqrt(delta*delta/(1.0+sigma*sigma)+ldelta*ldelta/(1.0+lsigma*lsigma)); if (dev > 2.0*sqrt(2.0)) { strcpy(buffer2,buffer); strcat(buffer2,"_microanomaly"); AppendItem(classlist,buffer2,"2"); AddPersistentClass(buffer2,CF_PERSISTENCE,cfpreserve); } return sig; /* Granularity makes this silly */ } else { buffer[0] = '\0'; strcpy(buffer,name); if ((delta > 0) && (ldelta > 0)) { strcat(buffer,"_high"); } else if ((delta < 0) && (ldelta < 0)) { strcat(buffer,"_low"); } else { strcat(buffer,"_normal"); } dev = sqrt(delta*delta/(1.0+sigma*sigma)+ldelta*ldelta/(1.0+lsigma*lsigma)); if (dev <= sqrt(2.0)) { strcpy(buffer2,buffer); strcat(buffer2,"_normal"); AppendItem(classlist,buffer2,"0"); } else { strcpy(buffer2,buffer); strcat(buffer2,"_dev1"); AppendItem(classlist,buffer2,"0"); } /* Now use persistent classes so that serious anomalies last for about 2 autocorrelation lengths, so that they can be cross correlated and seen by normally scheduled cfagent processes ... */ if (dev > 2.0*sqrt(2.0)) { strcpy(buffer2,buffer); strcat(buffer2,"_dev2"); AppendItem(classlist,buffer2,"2"); AddPersistentClass(buffer2,CF_PERSISTENCE,cfpreserve); } if (dev > 3.0*sqrt(2.0)) { strcpy(buffer2,buffer); strcat(buffer2,"_anomaly"); AppendItem(classlist,buffer2,"3"); AddPersistentClass(buffer2,CF_PERSISTENCE,cfpreserve); } return sig; } } /*****************************************************************************/ void SetVariable(char *name,double value,double average,double stddev,struct Item **classlist) { char var[CF_BUFSIZE]; sprintf(var,"value_%s=%d",name,(int)value); AppendItem(classlist,var,""); sprintf(var,"average_%s=%1.1f",name,average); AppendItem(classlist,var,""); sprintf(var,"stddev_%s=%1.1f",name,stddev); AppendItem(classlist,var,""); } /*****************************************************************************/ void RecordChangeOfState(struct Item *classlist,char *timekey) { } /*****************************************************************************/ void ZeroArrivals() { int i; for (i = 0; i < CF_OBSERVABLES; i++) { THIS[i] = 0; } } /*****************************************************************************/ double RejectAnomaly(double new,double average,double variance,double localav,double localvar) { double dev = sqrt(variance+localvar); /* Geometrical average dev */ double delta; int bigger; if (average == 0) { return new; } if (new > big_number) { return average; } if ((new-average)*(new-average) < cf_noise_threshold*cf_noise_threshold) { return new; } if (new - average > 0) { bigger = true; } else { bigger = false; } /* This routine puts some inertia into the changes, so that the system doesn't respond to every little change ... IR and UV cutoff */ delta = sqrt((new-average)*(new-average)+(new-localav)*(new-localav)); if (delta > 4.0*dev) /* IR */ { srand48((unsigned int)time(NULL)); if (drand48() < 0.7) /* 70% chance of using full value - as in learning policy */ { return new; } else { if (bigger) { return average+2.0*dev; } else { return average-2.0*dev; } } } else { Verbose("Value accepted\n"); return new; } } /***************************************************************/ /* Level 5 */ /***************************************************************/ void SetEntropyClasses(char *service,struct Item *list,char *inout) { struct Item *ip, *addresses = NULL; char local[CF_BUFSIZE],remote[CF_BUFSIZE],class[CF_BUFSIZE],vbuff[CF_BUFSIZE], *sp; int i = 0, min_signal_diversity = 1,total=0; double *p = NULL, S = 0.0, percent = 0.0; if (IsSocketType(service)) { for (ip = list; ip != NULL; ip=ip->next) { if (strlen(ip->name) > 0) { if (strncmp(ip->name,"tcp",3) == 0) { sscanf(ip->name,"%*s %*s %*s %s %s",local,remote); /* linux-like */ } else { sscanf(ip->name,"%s %s",local,remote); /* solaris-like */ } strncpy(vbuff,remote,CF_BUFSIZE-1); for (sp = vbuff+strlen(vbuff)-1; isdigit((int)*sp); sp--) { } *sp = '\0'; if (!IsItemIn(addresses,vbuff)) { total++; AppendItem(&addresses,vbuff,""); IncrementItemListCounter(addresses,vbuff); } else { total++; IncrementItemListCounter(addresses,vbuff); } } } if (total > min_signal_diversity) { p = (double *) malloc((total+1)*sizeof(double)); for (i = 0,ip = addresses; ip != NULL; i++,ip=ip->next) { p[i] = ((double)(ip->counter))/((double)total); S -= p[i]*log(p[i]); } percent = S/log((double)total)*100.0; free(p); } } else { int classes = 0; total = 0; for (ip = list; ip != NULL; ip=ip->next) { total += (double)(ip->counter); } p = (double *)malloc(sizeof(double)*total); for (ip = list; ip != NULL; ip=ip->next) { p[classes++] = ip->counter/total; } for (i = 0; i < classes; i++) { S -= p[i] * log(p[i]); } if (classes > 1) { percent = S/log((double)classes)*100.0; } else { percent = 0; } free(p); } if (percent > 90) { snprintf(class,CF_MAXVARSIZE,"entropy_%s_%s_high",service,inout); AppendItem(&ENTROPIES,class,""); } else if (percent < 20) { snprintf(class,CF_MAXVARSIZE,"entropy_%s_%s_low",service,inout); AppendItem(&ENTROPIES,class,""); } else { snprintf(class,CF_MAXVARSIZE,"entropy_%s_%s_medium",service,inout); AppendItem(&ENTROPIES,class,""); } DeleteItemList(addresses); } /***************************************************************/ void SaveTCPEntropyData(struct Item *list,int i,char *inout) { struct Item *ip; FILE *fp; char filename[CF_BUFSIZE]; Verbose("TCP Save %s\n",TCPNAMES[i]); if (list == NULL) { Verbose("No %s-%s events\n",TCPNAMES[i],inout); return; } if (strncmp(inout,"in",2) == 0) { snprintf(filename,CF_BUFSIZE-1,"%s/state/cf_incoming.%s",CFWORKDIR,TCPNAMES[i]); } else { snprintf(filename,CF_BUFSIZE-1,"%s/state/cf_outgoing.%s",CFWORKDIR,TCPNAMES[i]); } Verbose("TCP Save %s\n",filename); if ((fp = fopen(filename,"w")) == NULL) { Verbose("Unable to write datafile %s\n",filename); return; } for (ip = list; ip != NULL; ip=ip->next) { fprintf(fp,"%d %s\n",ip->counter,ip->name); } fclose(fp); } /***************************************************************/ void IncrementCounter(struct Item **list,char *name) { if (!IsItemIn(*list,name)) { AppendItem(list,name,""); IncrementItemListCounter(*list,name); } else { IncrementItemListCounter(*list,name); } } /***************************************************************/ int GetFileGrowth(char *filename,enum observables index) { struct stat statbuf; size_t q, dq; if (stat(filename,&statbuf) == -1) { return 0; } q = statbuf.st_size; Verbose("GetFileGrowth(%s) = %d\n",filename,q); dq = q - LASTQ[index]; if (LASTQ[index] == 0) { LASTQ[index] = q; return dq/10; /* arbitrary spike mitigation */ } LASTQ[index] = q; return dq; } /******************************************************************************/ /* Motherboard sensors - how to standardize this somehow * /* We're mainly interested in temperature and power consumption, but only the */ /* temperature is generally available. Several temperatures exist too ... */ /******************************************************************************/ void GatherSensorData() { char buffer[CF_BUFSIZE]; Debug("GatherSensorData()\n"); switch(VSYSTEMHARDCLASS) { case linuxx: /* Search for acpi first, then lmsensors */ if (ACPI && GetAcpi()) { return; } if (LMSENSORS && GetLMSensors()) { return; } break; case solaris: break; } } /******************************************************************************/ int GetAcpi() { DIR *dirh; FILE *fp; struct dirent *dirp; int count = 0; char path[CF_BUFSIZE],buf[CF_BUFSIZE],index[4]; double temp = 0; Debug("ACPI temperature\n"); if ((dirh = opendir("/proc/acpi/thermal_zone")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",path); CfLog(cfverbose,OUTPUT,"opendir"); return false; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,path,NULL)) { continue; } snprintf(path,CF_BUFSIZE,"/proc/acpi/thermal_zone/%s/temperature",dirp->d_name); if ((fp = fopen(path,"r")) == NULL) { printf("Couldn't open %s\n",path); continue; } fgets(buf,CF_BUFSIZE-1,fp); sscanf(buf,"%*s %lf",&temp); for (count = 0; count < 4; count++) { snprintf(index,2,"%d",count); if (strstr(dirp->d_name,index)) { switch (count) { case 0: THIS[ob_temp0] = temp; break; case 1: THIS[ob_temp1] = temp; break; case 2: THIS[ob_temp2] = temp; break; case 3: THIS[ob_temp3] = temp; break; } Debug("Set temp%d to %f\n",count,temp); } } fclose(fp); } closedir(dirh); return true; } /******************************************************************************/ int GetLMSensors() { FILE *pp; struct Item *ip,*list = NULL; double temp = 0; char name[CF_BUFSIZE]; int count; THIS[ob_temp0] = 0.0; THIS[ob_temp1] = 0.0; THIS[ob_temp2] = 0.0; THIS[ob_temp3] = 0.0; if ((pp = cfpopen("/usr/bin/sensors","r")) == NULL) { LMSENSORS = false; /* Broken */ return false; } ReadLine(VBUFF,CF_BUFSIZE,pp); while (!feof(pp)) { ReadLine(VBUFF,CF_BUFSIZE,pp); if (strstr(VBUFF,"Temp")||strstr(VBUFF,"temp")) { PrependItem(&list,VBUFF,NULL); } } cfpclose(pp); if (ListLen(list) > 0) { Debug("LM Sensors seemed to return ok data\n"); } else { return false; } /* lmsensor names are hopelessly inconsistent - so try a few things */ for (ip = list; ip != NULL; ip=ip->next) { for (count = 0; count < 4; count++) { snprintf(name,16,"CPU%d Temp:",count); if (strncmp(ip->name,name,strlen(name)) == 0) { sscanf(ip->name,"%*[^:]: %lf",&temp); switch (count) { case 0: THIS[ob_temp0] = temp; break; case 1: THIS[ob_temp1] = temp; break; case 2: THIS[ob_temp2] = temp; break; case 3: THIS[ob_temp3] = temp; break; } Debug("Set temp%d to %f from what looks like cpu temperature\n",count,temp); } } } if (THIS[ob_temp0] != 0) { /* We got something plausible */ return true; } /* Alternative name Core x: */ for (ip = list; ip != NULL; ip=ip->next) { for (count = 0; count < 4; count++) { snprintf(name,16,"Core %d:",count); if (strncmp(ip->name,name,strlen(name)) == 0) { sscanf(ip->name,"%*[^:]: %lf",&temp); switch (count) { case 0: THIS[ob_temp0] = temp; break; case 1: THIS[ob_temp1] = temp; break; case 2: THIS[ob_temp2] = temp; break; case 3: THIS[ob_temp3] = temp; break; } Debug("Set temp%d to %f from what looks like core temperatures\n",count,temp); } } } if (THIS[ob_temp0] != 0) { /* We got something plausible */ return true; } for (ip = list; ip != NULL; ip=ip->next) { if (strncmp(ip->name,"CPU Temp:",strlen("CPU Temp:")) == 0 ) { sscanf(ip->name,"%*[^:]: %lf",&temp); Debug("Setting temp0 to CPU Temp\n"); THIS[ob_temp0] = temp; } if (strncmp(ip->name,"M/B Temp:",strlen("M/B Temp:")) == 0 ) { sscanf(ip->name,"%*[^:]: %lf",&temp); Debug("Setting temp0 to M/B Temp\n"); THIS[ob_temp1] = temp; } if (strncmp(ip->name,"Sys Temp:",strlen("Sys Temp:")) == 0 ) { sscanf(ip->name,"%*[^:]: %lf",&temp); Debug("Setting temp0 to Sys Temp\n"); THIS[ob_temp2] = temp; } if (strncmp(ip->name,"AUX Temp:",strlen("AUX Temp:")) == 0 ) { sscanf(ip->name,"%*[^:]: %lf",&temp); Debug("Setting temp0 to AUX Temp\n"); THIS[ob_temp3] = temp; } } if (THIS[ob_temp0] != 0) { /* We got something plausible */ return true; } /* Alternative name Core x: */ for (ip = list; ip != NULL; ip=ip->next) { for (count = 0; count < 4; count++) { snprintf(name,16,"temp%d:",count); if (strncmp(ip->name,name,strlen(name)) == 0) { sscanf(ip->name,"%*[^:]: %lf",&temp); switch (count) { case 0: THIS[ob_temp0] = temp; break; case 1: THIS[ob_temp1] = temp; break; case 2: THIS[ob_temp2] = temp; break; case 3: THIS[ob_temp3] = temp; break; } Debug("Set temp%d to %f\n",count,temp); } } } /* Give up? */ DeleteItemList(list); return true; } cfengine-2.2.10/src/package.c0000644000175000001440000020666611140415201012622 00000000000000/* cfengine for GNU Copyright (C) 2003 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo The contributions in this file have been made by volunteers and only checked for serious errors by Mark Burgess. The orginal code was written by Red Hat Linux and has since been modified by a number of others. 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, 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 "cf.defs.h" #include "cf.extern.h" /****************************************************************************/ int BuildCommandLine (char *resolvedcmd, char* rawcmd, struct Item *pkglist ); int RPMPackageCheck (char *package, char *version, enum cmpsense cmp); int RPMPackageList (char *package, char *version, enum cmpsense cmp, struct Item **pkglist); int DPKGPackageCheck (char *package, char *version, enum cmpsense cmp); int DPKGPackageList (char *package, char *version, enum cmpsense cmp, struct Item **pkglist); int SUNPackageCheck (char *package, char *version, enum cmpsense cmp); int SUNPackageList (char *package, char *version, enum cmpsense cmp, struct Item **pkglist); void ParseSUNVR(char * vr, int *major, int *minor, int *micro, char **revis); int PortagePackageCheck (char *package, char *version, enum cmpsense cmp); int PortagePackageList (char *package, char *version, enum cmpsense cmp, struct Item **pkglist); int AIXPackageCheck (char *package, char *version, enum cmpsense cmp); int AIXPackageList (char *package, char *version, enum cmpsense cmp, struct Item **pkglist); void ParseAIXVR(char * vr, int *ver, int *release, int *maint, int *fix); int FreeBSDPackageCheck (char *package, char *version, enum cmpsense cmp); int FreeBSDPackageList (char *package, char *version, enum cmpsense cmp, struct Item **pkglist); int rpmvercmp(const char *a, const char *b); void ParseEVR(char * evr, const char **ep, const char **vp, const char **rp); int xislower(int c); int xisupper(int c); int xisalpha(int c); int xisalnum(int c); int xisdigit(int c); /****************************************************************************/ /* Make sure we are insensitive to the locale so everyone gets the * same experience from these. */ int xislower(int c) { return (c >= 'a' && c <= 'z'); } int xisupper(int c) { return (c >= 'A' && c <= 'Z'); } int xisalpha(int c) { return (xislower(c) || xisupper(c)); } int xisdigit(int c) { return (c >= '0' && c <= '9'); } int xisalnum(int c) { return (xisalpha(c) || xisdigit(c)); } /***********************************************************************************/ /* This is moved here to allow do.c to be ignorant of the various package managers */ int PackageCheck(struct Package *ptr,char* package, enum pkgmgrs pkgmgr, char *version,enum cmpsense cmp) { int match=0; switch(pkgmgr) { case pkgmgr_rpm: match = RPMPackageCheck(package, version, cmp); break; case pkgmgr_dpkg: match = DPKGPackageCheck(package, version, cmp); break; case pkgmgr_sun: match = SUNPackageCheck(package, version, cmp); break; case pkgmgr_aix: match = AIXPackageCheck(package, version, cmp); break; case pkgmgr_portage: match = PortagePackageCheck(package, version, cmp); break; case pkgmgr_freebsd: match = FreeBSDPackageCheck(package, version, cmp); break; default: /* UGH! This should *never* happen. GetPkgMgr() and * InstallPackagesItem() should have caught this before it * was ever installed!!! * */ snprintf(OUTPUT,CF_BUFSIZE,"Internal error! Tried to check package %s in an unknown database: %d. This should never happen!\n", package, pkgmgr); CfLog(cferror,OUTPUT,""); break; } return match; } /************************************************************************/ int PackageList(struct Package *ptr,char* package, enum pkgmgrs pkgmgr, char *version,enum cmpsense cmp, struct Item **pkglist) { int match=0; switch(pkgmgr) { case pkgmgr_rpm: match = RPMPackageList(package, version, cmp, pkglist); break; case pkgmgr_dpkg: match = DPKGPackageList(package, version, cmp, pkglist); break; case pkgmgr_sun: match = SUNPackageList(package, version, cmp, pkglist); break; case pkgmgr_aix: match = AIXPackageList(package, version, cmp, pkglist); break; case pkgmgr_portage: match = PortagePackageList(package, version, cmp, pkglist); break; case pkgmgr_freebsd: match = FreeBSDPackageList(package, version, cmp, pkglist); break; default: /* This should *never* happen. GetPkgMgr() and * InstallPackagesItem() should have caught this before it * was ever installed!!! * */ snprintf(OUTPUT,CF_BUFSIZE,"Internal error! Tried to check package %s in an unknown database: %d. This should never happen!\n", package, pkgmgr); CfLog(cferror,OUTPUT,""); break; } return match; } /*********************************************************************************/ int InstallPackage(struct Package *ptr,enum pkgmgrs pkgmgr, struct Item **pkglist) { char rawinstcmd[CF_BUFSIZE]; /* Make the instcmd twice the normal buffer size since the package list limit is CF_BUFSIZE so this can obviously get larger! */ char instcmd[CF_BUFSIZE*2]; char line[CF_BUFSIZE]; FILE *pp; int result = 0; Debug("Entering InstallPackage.\n"); switch(pkgmgr) { case pkgmgr_rpm: if (!GetMacroValue(CONTEXTID,"RPMInstallCommand")) { CfLog(cferror,"RPMInstallCommand NOT Set. Package Installation Not Possible!\n",""); return 0; } strncpy(rawinstcmd, GetMacroValue(CONTEXTID,"RPMInstallCommand"),CF_BUFSIZE); break; case pkgmgr_dpkg: if (!GetMacroValue(CONTEXTID,"DPKGInstallCommand")) { CfLog(cferror,"DPKGInstallCommand NOT Set. Package Installation Not Possible!\n",""); return 0; } strncpy(rawinstcmd, GetMacroValue(CONTEXTID,"DPKGInstallCommand"),CF_BUFSIZE); break; case pkgmgr_sun: if (!GetMacroValue(CONTEXTID,"SUNInstallCommand")) { CfLog(cferror,"SUNInstallCommand NOT Set. Package Installation Not Possible!\n",""); return 0; } strncpy(rawinstcmd, GetMacroValue(CONTEXTID,"SUNInstallCommand"),CF_BUFSIZE); break; case pkgmgr_aix: if (!GetMacroValue(CONTEXTID,"AIXInstallCommand")) { CfLog(cferror,"AIXInstallCommand NOT Set. Package Installation Not Possible!\n",""); return 0; } strncpy(rawinstcmd, GetMacroValue(CONTEXTID,"AIXInstallCommand"),CF_BUFSIZE); break; case pkgmgr_portage: if (!GetMacroValue(CONTEXTID,"PortageInstallCommand")) { CfLog(cferror,"PortageInstallCommand NOT Set. Package Installation Not Possible!\n","packages"); return 0; } strncpy(rawinstcmd, GetMacroValue(CONTEXTID,"PortageInstallCommand"),CF_BUFSIZE); break; case pkgmgr_freebsd: if (!GetMacroValue(CONTEXTID,"FreeBSDInstallCommand")) { CfLog(cferror,"FreeBSDInstallCommand NOT Set. Package Installation Not Possible!\n",""); return 0; } strncpy(rawinstcmd, GetMacroValue(CONTEXTID,"FreeBSDInstallCommand"),CF_BUFSIZE); break; default: snprintf(OUTPUT,CF_BUFSIZE,"Unknown package manager %d\n",pkgmgr); CfLog(cferror,OUTPUT,""); break; } if (BuildCommandLine(instcmd,rawinstcmd,*pkglist)) { snprintf(OUTPUT,CF_BUFSIZE,"Installing package(s) using '%s'\n", instcmd); CfLog(cfinform,OUTPUT,""); if (DONTDO) { Verbose("--skipping because DONTDO is enabled.\n"); result = 1; } else { if ((pp = cfpopen(instcmd, "r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't exec package installer %s",instcmd); CfLog(cfinform,OUTPUT,"popen"); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_FAIL); return 0; } while (!feof(pp)) { ReadLine(line,CF_BUFSIZE-1,pp); snprintf(OUTPUT,CF_BUFSIZE,"%s",line); CfLog(cfinform,OUTPUT,""); } if (cfpclose(pp) != 0) { CfLog(cfinform,"Package install command was not successful.\n\n","popen"); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,"Package installer did not exit properly",CF_FAIL); result = 0; } else { snprintf(OUTPUT,CF_BUFSIZE,"Packages installed: %s",instcmd); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); result = 1; } } } else { CfLog(cferror,"Unable to evaluate package manager command.\n",""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,"Unable to evaluate package manager",CF_NOP); result = 0; } return result; } /************************************************************************************/ int UpgradePackage(struct Package *ptr,char *name, enum pkgmgrs pkgmgr, char* version, enum cmpsense cmp) { struct Item *removelist = NULL; struct Item *addlist = NULL; int result = 0; Verbose("Package upgrade for %s: %s\n", PKGMGRTEXT[pkgmgr], name ); if ((ptr->pkgmgr == pkgmgr_freebsd) || (ptr->pkgmgr == pkgmgr_sun)) { /* Handle package managers with independant removes/installs */ PackageList(ptr,name,pkgmgr,version,cmp,&removelist); if (RemovePackage(ptr,pkgmgr,&removelist)) { AppendItem(&addlist, name, NULL); result = InstallPackage(ptr,pkgmgr,&addlist); } else { CfLog(cfinform,"Package cannot be upgraded because the old version was not removed.\n\n",""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,"Package not upgraded - another version in the way",CF_FAIL); result = 0; } } else { /* Handle package managers that do atomic upgrades */ AppendItem(&addlist, name, NULL); result = InstallPackage(ptr,pkgmgr,&addlist); } DeleteItemList(removelist); DeleteItemList(addlist); return result; } /************************************************************************************/ int RemovePackage(struct Package *ptr,enum pkgmgrs pkgmgr, struct Item **pkglist) { char rawdelcmd[CF_BUFSIZE]; char delcmd[CF_BUFSIZE*2]; char line[CF_BUFSIZE]; FILE *pp; int result = 0; if (pkglist == NULL) { CfLog(cferror,"RemovePackage: no packages to remove.\n",""); return 0; } switch(pkgmgr) { case pkgmgr_rpm: if (!GetMacroValue(CONTEXTID,"RPMRemoveCommand")) { CfLog(cferror,"RPMRemoveCommand NOT set, using default!\n",""); strncpy(rawdelcmd, "/bin/rpm -e %s", CF_BUFSIZE - 1); } else { strncpy(rawdelcmd, GetMacroValue(CONTEXTID,"RPMRemoveCommand"), CF_BUFSIZE - 1); } break; case pkgmgr_sun: if (!GetMacroValue(CONTEXTID,"SunRemoveCommand")) { CfLog(cferror,"SunRemoveCommand NOT set, using default!\n",""); strncpy(rawdelcmd, "/usr/sbin/pkgrm -n %s", CF_BUFSIZE - 1); } else { strncpy(rawdelcmd, GetMacroValue(CONTEXTID,"SunRemoveCommand"), CF_BUFSIZE - 1); } break; case pkgmgr_dpkg: if (!GetMacroValue(CONTEXTID,"DPKGRemoveCommand")) { CfLog(cferror,"DPKGRemoveCommand NOT Set. Package Removal Not Possible!\n",""); } else { strncpy(rawdelcmd, GetMacroValue(CONTEXTID,"DPKGRemoveCommand"), CF_BUFSIZE - 1); } break; case pkgmgr_freebsd: if (!GetMacroValue(CONTEXTID,"FreeBSDRemoveCommand")) { strncpy(rawdelcmd, "/usr/sbin/pkg_delete %s", CF_BUFSIZE - 1); } else { strncpy(rawdelcmd, GetMacroValue(CONTEXTID,"FreeBSDRemoveCommand"), CF_BUFSIZE - 1); } break; case pkgmgr_portage: if (!GetMacroValue(CONTEXTID,"PortageRemoveCommand")) { strncpy(rawdelcmd, "/usr/bin/emerge -C %s", CF_BUFSIZE - 1); } else { strncpy(rawdelcmd, GetMacroValue(CONTEXTID,"PortageRemoveCommand"), CF_BUFSIZE - 1); } break; default: CfLog(cferror,"RemovePackage: Package removal not yet implemented for this package manager.\n","p"); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,"No support for package removal",CF_NOP); break; } if (BuildCommandLine( delcmd, rawdelcmd, *pkglist)) { snprintf(OUTPUT,CF_BUFSIZE,"Removing package(s) using '%s'\n", delcmd); CfLog(cfinform,OUTPUT,""); if (DONTDO) { Verbose("--skipping because \"-n\" (dryrun) option is enabled.\n"); result = 1; } else { if ((pp = cfpopen(delcmd, "r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not execute package removal command %s\n",delcmd); CfLog(cferror,OUTPUT,"popen"); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_FAIL); return 0; } while (!feof(pp)) { ReadLine(line,CF_BUFSIZE-1,pp); snprintf(OUTPUT,CF_BUFSIZE,"%s\n",line); CfLog(cfinform,OUTPUT,""); } if (cfpclose(pp) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Could not execute package removal command %s\n",delcmd); CfLog(cferror,OUTPUT,"popen"); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_FAIL); result = 0; } else { snprintf(OUTPUT,CF_BUFSIZE,"Package removal succeeded (%s)\n",delcmd); CfLog(cfinform,OUTPUT,"popen"); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); result = 1; } } } else { CfLog(cferror,"Unable to evaluate package manager command.\n",""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,"Could not evaluate package manager",CF_FAIL); result = 0; } return result; } /****************************************************************************/ int BuildCommandLine(char *resolvedcmd, char *rawcmd, struct Item *pkglist ) { struct Item *package; char *cmd_tail; FILE *pp; char *ptr, *cmd_ptr; int cmd_args = 0; int cmd_tail_len = 0; int original_len; int result; for (ptr = rawcmd, cmd_args = 1; NULL != ptr; ptr = strchr(++ptr, ' ')) { ++cmd_args; } if (cmd_tail = strstr(rawcmd, "%s")) { *cmd_tail = '\0'; cmd_tail += 2; cmd_tail_len = strlen(cmd_tail); --cmd_args; } strncpy(resolvedcmd, rawcmd, CF_BUFSIZE*2); Verbose("Package manager will be invoked as %s\n", resolvedcmd); /* Iterator through package list until we reach the maximum number that cfpopen can take */ original_len = strlen(resolvedcmd); cmd_ptr = &resolvedcmd[original_len]; for (package = pkglist; package != NULL; package = package->next) { Debug("BuildCommandLine(): Processing package %s at location %d.\n", package->name, &package ); if (cmd_args == CF_MAXSHELLARGS) { snprintf(OUTPUT,CF_BUFSIZE,"Skipping package %s (reached CF_MAXSHELLARGS)\n", package->name); CfLog(cfinform,OUTPUT,""); } else if (cmd_ptr - resolvedcmd + strlen(package->name) + 2 > CF_BUFSIZE*2) { snprintf(OUTPUT,CF_BUFSIZE,"Skipping package %s (max buffer size)\n", package->name); CfLog(cfinform,OUTPUT,""); } else { Verbose("BuildCommandLine(): Adding package '%s' to the list.\n", package->name); strncpy(cmd_ptr, package->name, &resolvedcmd[CF_BUFSIZE*2] - cmd_ptr); cmd_ptr += strlen(package->name); *cmd_ptr++ = ' '; ++cmd_args; } } /* If the revised command line is the same, we have nothing to do. */ if (cmd_ptr == &resolvedcmd[original_len]) { result = 0; Verbose("No packages to install.\n"); } else { /* Have a full command line, so remove trailing space */ *--cmd_ptr = '\0'; /* Append the tail if necessary. */ if (cmd_tail_len > 0) { strncpy(cmd_ptr, cmd_tail, &resolvedcmd[CF_BUFSIZE*2] - cmd_ptr); } result = 1; } return result; } /*********************************************************************/ /* RPM */ /* returns: 1 - found a match * 0 - found no match */ /*********************************************************************/ int RPMPackageCheck(char *package,char *version,enum cmpsense cmp) { FILE *pp; struct Item *evrlist = NULL; struct Item *evr; int epochA = 0; /* What is installed. Assume 0 if we don't get one. */ int epochB = 0; /* What we are looking for. Assume 0 if we don't get one. */ const char *eA = NULL; /* What is installed */ const char *eB = NULL; /* What we are looking for */ const char *vA = NULL; /* What is installed */ const char *vB = NULL; /* What we are looking for */ const char *rA = NULL; /* What is installed */ const char *rB = NULL; /* What we are looking for */ enum cmpsense result; int match = 0; char tver1[CF_BUFSIZE]; char tver2[CF_BUFSIZE]; if (GetMacroValue(CONTEXTID,"RPMcommand")) { snprintf(VBUFF,CF_BUFSIZE,"%s -q --queryformat \"%%{EPOCH}:%%{VERSION}-%%{RELEASE}\\n\" %s",GetMacroValue(CONTEXTID,"RPMcommand"),package); } else { snprintf(VBUFF,CF_BUFSIZE,"/bin/rpm -q --queryformat \"%%{EPOCH}:%%{VERSION}-%%{RELEASE}\\n\" %s", package); } if ((pp = cfpopen(VBUFF, "r")) == NULL) { Verbose("Could not execute the RPM command. Assuming package not installed.\n"); return 0; } while(!feof(pp)) { *VBUFF = '\0'; ReadLine(VBUFF,CF_BUFSIZE,pp); if (*VBUFF != '\0') { AppendItem(&evrlist,VBUFF,""); } } /* Non-zero exit status means that we could not find the package, so * Zero the list and bail. */ if (cfpclose(pp) != 0) { DeleteItemList(evrlist); evrlist = NULL; } if (evrlist == NULL) { Verbose("RPM Package %s not installed.\n", package); return 0; } Verbose("Requesting %s %s %s\n", package, CMPSENSETEXT[cmp],(version[0] ? version : "ANY")); /* If no version was specified, just return 1, because if we got this far * some package by that name exists. */ if (!version[0]) { DeleteItemList(evrlist); return 1; } /* Parse the EVR we are looking for once at the start */ memset( tver1, 0, CF_BUFSIZE ); strncpy( tver1, version, CF_BUFSIZE - 1 ); ParseEVR( tver1, &eB, &vB, &rB); /* The rule here will be: if any package in the list matches, then the * first one to match wins, and we bail out. */ for (evr = evrlist; evr != NULL; evr=evr->next) { char *evrstart; evrstart = evr->name; result = cmpsense_eq; /* RPM returns the string "(none)" for the epoch if there is none * instead of the number 0. This will cause ParseEVR() to misinterpret * it as part of the version component, since epochs must be numeric. * If we get "(none)" at the start of the EVR string, we must be careful * to replace it with a 0 and reset evrstart to where the 0 is. Ugh. */ if (!strncmp(evrstart, "(none)", strlen("(none)"))) { /* We have no EVR in the installed package. Fudge it. */ evrstart = strchr(evrstart, ':') - 1; *evrstart = '0'; } Verbose("RPMCheckPackage(): Trying installed version %s\n", evrstart); memset( tver2, 0, CF_BUFSIZE ); strncpy( tver2, evrstart, CF_BUFSIZE - 1 ); ParseEVR( tver2, &eA, &vA, &rA); epochA = atol(eA); /* The above code makes sure we always have this. */ if (eB && *eB) /* the B side is what the user entered. Better check. */ { epochB = atol(eB); } /* First try the epoch. */ if (epochA > epochB) { result = cmpsense_gt; } if (epochA < epochB) { result = cmpsense_lt; } /* If that did not decide it, try version. We must *always* have * a version string. That's just the way it is.*/ if (result == cmpsense_eq) { switch (rpmvercmp(vA, vB)) { case 1: result = cmpsense_gt; break; case -1: result = cmpsense_lt; break; } } /* if we wind up here, everything rides on the release if both have it. * RPM always stores a release internally in the database, so the A side * will have it. It's just a matter of whether or not the user cares * about it at this point. */ if ((result == cmpsense_eq) && (rB && *rB)) { switch (rpmvercmp(rA, rB)) { case 1: result = cmpsense_gt; break; case -1: result = cmpsense_lt; break; } } Verbose("Comparison result: %s\n",CMPSENSETEXT[result]); switch(cmp) { case cmpsense_gt: match = (result == cmpsense_gt); break; case cmpsense_ge: match = (result == cmpsense_gt || result == cmpsense_eq); break; case cmpsense_lt: match = (result == cmpsense_lt); break; case cmpsense_le: match = (result == cmpsense_lt || result == cmpsense_eq); break; case cmpsense_eq: match = (result == cmpsense_eq); break; case cmpsense_ne: match = (result != cmpsense_eq); break; } /* If we find a match, just return it now, and don't bother checking * anything else RPM returned, if it returns multiple packages */ if (match) { DeleteItemList(evrlist); return 1; } } /* If we manage to make it out of the loop, we did not find a match. */ DeleteItemList(evrlist); return 0; } /*********************************************************************/ int RPMPackageList (char *package, char *version, enum cmpsense cmp, struct Item **pkglist) { FILE *pp; struct Item *evrlist = NULL; struct Item *evr; int epochA = 0; /* What is installed. Assume 0 if we don't get one. */ int epochB = 0; /* What we are looking for. Assume 0 if we don't get one. */ const char *eA = NULL; /* What is installed */ const char *eB = NULL; /* What we are looking for */ const char *vA = NULL; /* What is installed */ const char *vB = NULL; /* What we are looking for */ const char *rA = NULL; /* What is installed */ const char *rB = NULL; /* What we are looking for */ enum cmpsense result; int match = 0; int matchcnt = 0; int cmdresult = 0; char *tmpp; char line[CF_BUFSIZE]; char tver1[CF_BUFSIZE]; char tver2[CF_BUFSIZE]; char tpack[CF_BUFSIZE]; Verbose ("RPMPackageList(): Requested version %s %s of %s \n", CMPSENSETEXT[cmp],(version[0] ? version : "ANY"), package ); /* find out whats installed */ if (GetMacroValue(CONTEXTID,"RPMcommand")) { snprintf(VBUFF,CF_BUFSIZE,"%s -q --queryformat \"%%{EPOCH}:%%{VERSION}-%%{RELEASE}\\n\" %s",GetMacroValue(CONTEXTID,"RPMcommand"),package); } else { snprintf(VBUFF,CF_BUFSIZE,"/bin/rpm -q --queryformat \"%%{EPOCH}:%%{VERSION}-%%{RELEASE}\\n\" %s", package); } if ((pp = cfpopen(VBUFF, "r")) == NULL) { Verbose("Could not execute the RPM command. Assuming package not installed.\n"); return -1; } while(!feof(pp)) { *line = '\0'; ReadLine( line, CF_BUFSIZE, pp ); Debug("PackageList: read line %s\n", line); if (*line != '\0') { AppendItem( &evrlist, line, "" ); } } cmdresult = cfpclose(pp); /* Non-zero exit status means that we could not find the package, so * Zero the list and bail. */ if ( cmdresult != 0 ) { DeleteItemList(evrlist); evrlist = NULL; } if (evrlist == NULL) { /* this return is okay, we would returned 0 if we had parsed the whole list * and found no matches */ Verbose("RPM Package %s not installed.\n", package); return 0; } /* Parse the EVR we are looking for once at the start */ memset( tver1, 0, CF_BUFSIZE ); strncpy( tver1, version, CF_BUFSIZE - 1 ); ParseEVR( tver1, &eB, &vB, &rB); /* * The evrlist list contains the lines of output from the * rpm -q --queryformat "%{EPOCH}:%%{VERSION}-%%{RELEASE}\n" * command. These will be version of requested package installed on * on the system. In the loop, use the value of result and the ParseEVR * function to determine if the installed package fits the selection * criteria specified in the cfengine config file */ for (evr = evrlist; evr != NULL; evr=evr->next) { char *evrstart; evrstart = evr->name; result = cmpsense_eq; /* * RPM returns the string "(none)" for the epoch if there is none * instead of the number 0. This will cause ParseEVR() to misinterpret * it as part of the version component, since epochs must be numeric. * If we get "(none)" at the start of the EVR string, we must be careful * to replace it with a 0 and reset evrstart to where the 0 is. Ugh. */ if (!strncmp(evrstart, "(none)", strlen("(none)"))) { /* We have no Epoch in the installed package, force it to "0". */ evrstart = strchr(evrstart, ':') - 1; *evrstart = '0'; } Verbose("RPMPackageList(): " "Checking installed version %s against requested version %s\n", evrstart, version ); memset( tver2, 0, CF_BUFSIZE ); strncpy( tver2, evrstart, CF_BUFSIZE - 1 ); ParseEVR( tver2, &eA, &vA, &rA); epochA = atol(eA); /* The above code makes sure we always have this. */ if (eB && *eB) /* the B side is what the user entered. Better check. */ { epochB = atol(eB); } /* First try the epoch. */ if (epochA > epochB) { result = cmpsense_gt; } if (epochA < epochB) { result = cmpsense_lt; } /* If that did not decide it, try version. We must *always* have * a version string. That's just the way it is.*/ if (result == cmpsense_eq) { switch (rpmvercmp(vA, vB)) { case 1: result = cmpsense_gt; break; case -1: result = cmpsense_lt; break; } } /* if we wind up here, everything rides on the release if both have it. * RPM always stores a release internally in the database, so the A side * will have it. It's just a matter of whether or not the user cares * about it at this point. */ if ((result == cmpsense_eq) && (rB && *rB)) { switch (rpmvercmp(rA, rB)) { case 1: result = cmpsense_gt; break; case -1: result = cmpsense_lt; break; } } Verbose("Comparison result: %s\n",CMPSENSETEXT[result]); switch(cmp) { case cmpsense_gt: match = (result == cmpsense_gt); break; case cmpsense_ge: match = (result == cmpsense_gt || result == cmpsense_eq); break; case cmpsense_lt: match = (result == cmpsense_lt); break; case cmpsense_le: match = (result == cmpsense_lt || result == cmpsense_eq); break; case cmpsense_eq: match = (result == cmpsense_eq); break; case cmpsense_ne: match = (result != cmpsense_eq); break; } /* * If we find a match, build a string with the package name, version and * release using the approprieate delimiters and put it on the list */ if (match) { matchcnt++; /* point to the colon after the epoch and make it a dash for creating the pacakge name with the version and revsion */ tmpp = strchr( evrstart, ':' ); tmpp[0] = '-'; /* concatenate the package name and version-revision */ memset( tpack, 0, CF_BUFSIZE ); strncpy( tpack, package, CF_BUFSIZE - 1 ); strncat( tpack, tmpp, CF_BUFSIZE - 1 - strlen(tpack) ); /* append the string with pkgname, version and revision to pkglist */ AppendItem( pkglist, tpack, NULL ); } } Debug("RPMPackageList(): " "Found %d installed version(s) of %s that met match criteria\n", matchcnt, package); /* Once we manage to make it out of the loop, * if pkglist is NULL, we did not find a match. */ if ( *pkglist == NULL ) { return 0; } else { return 1; } } /*********************************************************************/ /* Debian */ /*********************************************************************/ int DPKGPackageCheck(char *package,char *version,enum cmpsense cmp) { FILE *pp; struct Item *evrlist = NULL; struct Item *evr; char *evrstart; enum cmpsense result; int match = 0; char tmpBUFF[CF_BUFSIZE]; Verbose ("Package: %s\n",package); /* check that the package exists in the package database */ snprintf (VBUFF, CF_BUFSIZE, "LC_ALL=C /usr/bin/apt-cache policy %s 2>&1 | " \ "grep -v \"W: Unable to locate package \"", package); if ((pp = cfpopen_sh(VBUFF, "r")) == NULL) { Verbose ("Could not execute APT-command (apt-cache).\n"); return 0; } while (!feof (pp)) { *VBUFF = '\0'; ReadLine (VBUFF, CF_BUFSIZE, pp); } if (cfpclose (pp) != 0) { Verbose ("The package %s did not exist in the package database.\n",package); return 0; } /* check what version is installed on the system (if any) */ snprintf (VBUFF, CF_BUFSIZE, "LC_ALL=C /usr/bin/apt-cache policy %s", package); /* * HvB: cfopen to cfopen_sh, fix bug for packages without version number */ if ((pp = cfpopen_sh(VBUFF, "r")) == NULL) { Verbose ("Could not execute APT-command (apt-cache policy).\n"); return 0; } while (!feof (pp)) { *VBUFF = '\0'; ReadLine (VBUFF, CF_BUFSIZE, pp); if (*VBUFF != '\0') { if (sscanf (VBUFF, " Installed: %s", tmpBUFF) > 0) { AppendItem (&evrlist, tmpBUFF, ""); } } } if (cfpclose (pp) != 0) { Verbose ("Something impossible happened... ('grep' exited abnormally).\n"); DeleteItemList (evrlist); return 0; } /* Assume that there is only one package in the list */ evr = evrlist; if (evr == NULL) { /* We did not find a match, and returns */ DeleteItemList (evrlist); return 0; } evrstart = evr->name; /* if version value is "(null)", the packages was not installed -> the package has no version and dpkg --compare-versions will treat "" as "no version" */ if (strncmp (evrstart, "(none)", strlen ("(none)")) == 0) { sprintf (evrstart, "\"\""); /* RB 34.02.06: * Set compare result to nothing when (not)installed version is none * because else we might return True for package check * if checking without version/cmp statement. * * Or else it will cause us to assume package is installed * while it is actually not. */ result = cmpsense_none; } else { result = cmpsense_eq; } if (strncmp (version, "(none)", strlen ("(none)")) == 0) { sprintf (version, "\"\""); } /* the evrstart shall be a version number which we will compare to version using '/usr/bin/dpkg --compare-versions' */ /* check if installed version is gt version */ snprintf (VBUFF, CF_BUFSIZE, "/usr/bin/dpkg --compare-versions %s gt %s", evrstart, version); if ((pp = cfpopen (VBUFF, "r")) == NULL) { Verbose ("Could not execute DPKG-command.\n"); return 0; } while (!feof (pp)) { *VBUFF = '\0'; ReadLine (VBUFF, CF_BUFSIZE, pp); } /* if dpkg --compare-versions exits with zero result the condition was satisfied, else not satisfied */ if (cfpclose (pp) == 0) { result = cmpsense_gt; } /* check if installed version is lt version */ snprintf (VBUFF, CF_BUFSIZE, "/usr/bin/dpkg --compare-versions %s lt %s", evrstart, version); if ((pp = cfpopen (VBUFF, "r")) == NULL) { Verbose ("Could not execute DPKG-command.\n"); return 0; } while (!feof (pp)) { *VBUFF = '\0'; ReadLine (VBUFF, CF_BUFSIZE, pp); } /* if dpkg --compare-versions exits with zero result the condition was satisfied, else not satisfied */ if (cfpclose (pp) == 0) { result = cmpsense_lt; } Verbose ("Comparison result: %s\n", CMPSENSETEXT[result]); switch (cmp) { case cmpsense_gt: match = (result == cmpsense_gt); break; case cmpsense_ge: match = (result == cmpsense_gt || result == cmpsense_eq); break; case cmpsense_lt: match = (result == cmpsense_lt); break; case cmpsense_le: match = (result == cmpsense_lt || result == cmpsense_eq); break; case cmpsense_eq: match = (result == cmpsense_eq); break; case cmpsense_ne: match = (result != cmpsense_eq); break; } if (match) { DeleteItemList (evrlist); return 1; } /* if we manage to make it here, we did not find a match */ DeleteItemList (evrlist); return 0; } /*********************************************************************/ int DPKGPackageList (char *package, char *version, enum cmpsense cmp, struct Item **pkglist) { /* Rather than re-checking packages, assume the package name is * installed since the DPKGPackageCheck was positive. This is * possible since Cfengine+dpkg doesn't support granular version * install/removes */ AppendItem(pkglist,package,""); return 1; } /*********************************************************************/ /* Sun - pkginfo/pkgadd/pkgrm */ /*********************************************************************/ /* * On solaris a package that can be installed is a file or a * directory on disk. An installed package isn't, it's just a name. * So in these functions below, the dirname of the package argument is * stripped so that we can handle requests about installed packages. * The last '-' is the delimiter between the package name and the version. */ int SUNPackageCheck(char *package,char *version,enum cmpsense cmp) { FILE *pp; char tmpBUFF[CF_BUFSIZE]; struct Item *evrlist = NULL; struct Item *evr; char *evrstart; enum cmpsense result; int match = 0; char tmppkg[CF_BUFSIZE]; char *pkgname; char *pkgversion; int majorA = 0; int majorB = 0; int minorA = 0; int minorB = 0; int microA = 0; int microB = 0; char *revisA = NULL; char *revisB = NULL; /* The parsing below modifies one of our arguments, so copy it first */ strncpy(tmppkg, package, CF_BUFSIZE-1); tmppkg[CF_BUFSIZE-1] = 0; if ((pkgname = strrchr(tmppkg, '/')) != NULL) { *pkgname = '\0'; pkgname++; } else { pkgname = tmppkg; } if ((pkgversion = strrchr(pkgname, '-')) != NULL) { *pkgversion = '\0'; } Verbose ("Package: %s\n",pkgname); /* check that the package exists in the package database */ snprintf (VBUFF, CF_BUFSIZE, "/usr/bin/pkginfo -i -q %s", pkgname); if ((pp = cfpopen (VBUFF, "r")) == NULL) { Verbose ("Could not execute pkginfo -i -q.\n"); return 0; } while (!feof (pp)) { *VBUFF = '\0'; ReadLine (VBUFF, CF_BUFSIZE, pp); } if (cfpclose (pp) != 0) { Verbose ("The package %s did not exist in the package database.\n",pkgname); return 0; } /* If no version was specified, we're just checking if the package * is present, not for a particular number, and we can skip the * version number fetch and check. */ if (!*version) { return 1; } /* check what version is installed on the system (if any) */ snprintf (VBUFF, CF_BUFSIZE, "/usr/bin/pkginfo -i -l %s", pkgname); if ((pp = cfpopen (VBUFF, "r")) == NULL) { Verbose ("Could not execute pkginfo -i -l.\n"); return 0; } while (!feof (pp)) { *VBUFF = '\0'; ReadLine (VBUFF, CF_BUFSIZE, pp); if (*VBUFF != '\0') { if (sscanf (VBUFF, " VERSION: %s", tmpBUFF) > 0) { AppendItem (&evrlist, tmpBUFF, ""); } } } if (cfpclose (pp) != 0) { Verbose ("pkginfo -i -l exited abnormally.\n"); DeleteItemList (evrlist); return 0; } /* Parse the Sun Version we are looking for once at the start */ ParseSUNVR(version, &majorB, &minorB, µB, &revisB); /* The rule here will be: if any package in the list matches, then the * first one to match wins, and we bail out. */ for (evr = evrlist; evr != NULL; evr=evr->next) { char *evrstart; evrstart = evr->name; /* Start out assuming the comparison will be equal. */ result = cmpsense_eq; ParseSUNVR(evrstart, &majorA, &minorA, µA, &revisA); /* Compare the major versions. */ if (majorA > majorB) { result = cmpsense_gt; } if (majorA < majorB) { result = cmpsense_lt; } /* If the major versions are the same, check the minor versions. */ if (result == cmpsense_eq) { if(minorA > minorB) { result = cmpsense_gt; } if(minorA < minorB) { result = cmpsense_lt; } /* If the minor versions match, compare the micro versions. */ if (result == cmpsense_eq) { if (microA > microB) { result = cmpsense_gt; } if (microA < microB) { result = cmpsense_lt; } } /* If the micro versions match, compare the revisions. */ if (result == cmpsense_eq) { if (strncasecmp(revisA ? revisA : "", revisB ? revisB : "", CF_BUFSIZE) > 0) { result = cmpsense_gt; } if (strncasecmp(revisA ? revisA : "", revisB ? revisB : "", CF_BUFSIZE) < 0) { result = cmpsense_lt; } } } switch(cmp) { case cmpsense_gt: match = (result == cmpsense_gt); break; case cmpsense_ge: match = (result == cmpsense_gt || result == cmpsense_eq); break; case cmpsense_lt: match = (result == cmpsense_lt); break; case cmpsense_le: match = (result == cmpsense_lt || result == cmpsense_eq); break; case cmpsense_eq: match = (result == cmpsense_eq); break; case cmpsense_ne: match = (result != cmpsense_eq); break; } if (match) { DeleteItemList(evrlist); return 1; } } /* If we made it out of the loop, there were no matches. */ DeleteItemList(evrlist); return 0; } /*********************************************************************/ int SUNPackageList (char *package, char *version, enum cmpsense cmp, struct Item **pkglist) { FILE *pp; struct Item *evrlist = NULL; struct Item *evr; int match = 0, result; char line[CF_BUFSIZE]; char tmppkg[CF_BUFSIZE]; char *pkgname; char *pkgversion; char tmpBUFF[CF_BUFSIZE]; int majorA = 0; int majorB = 0; int minorA = 0; int minorB = 0; int microA = 0; int microB = 0; char *revisA = NULL; char *revisB = NULL; /* The parsing below modifies one of our arguments, so copy it first */ strncpy(tmppkg, package, CF_BUFSIZE-1); tmppkg[CF_BUFSIZE-1] = 0; if ((pkgname = strrchr(tmppkg, '/')) != NULL) { *pkgname = '\0'; pkgname++; } else { pkgname = tmppkg; } if ((pkgversion = strrchr(pkgname, '-')) != NULL) { *pkgversion = '\0'; } Debug("SUNPackageList(): Requested version %s %s of %s\n", CMPSENSETEXT[cmp],(version[0] ? version : "ANY"), pkgname); /* If no version was specified, we're just checking if the package * is present, not for a particular number, so >0 will match. */ if (!*version) { cmp = cmpsense_gt; version[0] = '0'; version[1] = 0; } /* check what version is installed on the system (if any) */ snprintf (VBUFF, CF_BUFSIZE, "/usr/bin/pkginfo -i -l %s", pkgname); Verbose("SUNPackageList(): Running /usr/bin/pkginfo -i -l %s\n", pkgname); if ((pp = cfpopen (VBUFF, "r")) == NULL) { Verbose ("Could not execute pkginfo -i -l.\n"); return 0; } while (!feof (pp)) { *VBUFF = '\0'; ReadLine (VBUFF, CF_BUFSIZE, pp); if (*VBUFF != '\0') { if (sscanf (VBUFF, " VERSION: %s", tmpBUFF) > 0) { Debug("SUNPackageList: found package version %s\n", tmpBUFF); AppendItem(&evrlist,tmpBUFF,""); } } } if (cfpclose (pp) != 0) { Verbose ("pkginfo -i -l exited abnormally.\n"); DeleteItemList (evrlist); return 0; } /* Parse the Sun Version we are looking for once at the start */ ParseSUNVR(version, &majorB, &minorB, µB, &revisB); /* The rule here will be: if any package in the list matches, then the * first one to match wins, and we bail out. */ for (evr = evrlist; evr != NULL; evr=evr->next) { char *evrstart; evrstart = evr->name; /* Start out assuming the comparison will be equal. */ result = cmpsense_eq; ParseSUNVR(evrstart, &majorA, &minorA, µA, &revisA); /* Compare the major versions. */ if (majorA > majorB) { result = cmpsense_gt; } if (majorA < majorB) { result = cmpsense_lt; } /* If the major versions are the same, check the minor versions. */ if (result == cmpsense_eq) { if(minorA > minorB) { result = cmpsense_gt; } if(minorA < minorB) { result = cmpsense_lt; } /* If the minor versions match, compare the micro versions. */ if (result == cmpsense_eq) { if (microA > microB) { result = cmpsense_gt; } if (microA < microB) { result = cmpsense_lt; } } } /* If the micro versions match, compare the revisions. */ if (result == cmpsense_eq) { if (strncasecmp(revisA ? revisA : "", revisB ? revisB : "", CF_BUFSIZE) > 0) { result = cmpsense_gt; } if (strncasecmp(revisA ? revisA : "", revisB ? revisB : "", CF_BUFSIZE) < 0) { result = cmpsense_lt; } } switch(cmp) { case cmpsense_gt: match = (result == cmpsense_gt); break; case cmpsense_ge: match = (result == cmpsense_gt || result == cmpsense_eq); break; case cmpsense_lt: match = (result == cmpsense_lt); break; case cmpsense_le: match = (result == cmpsense_lt || result == cmpsense_eq); break; case cmpsense_eq: match = (result == cmpsense_eq); break; case cmpsense_ne: match = (result != cmpsense_eq); break; } if (match) { AppendItem(pkglist, pkgname, NULL); DeleteItemList(evrlist); return 1; } } /* If we made it out of the loop, there were no matches. */ DeleteItemList(evrlist); return 0; } /*********************************************************************/ /* Sun's manual pages say that the version number is a major, minor, * and optional micro version number. This code checks for that. * It will not handle other arbitrary and strange values people might * put in like "2.6d.12a" or "1.11 beta" or "pre-release 7" * Note that Sun uses REV= revision numbers appended to the * version string. These are handled correctly. *********************************************************************/ void ParseSUNVR (char *vr, int *major, int *minor, int *micro, char **revis) { char *tmpcpy = strdup(vr); char *startMinor = NULL; char *startMicro = NULL; char *startRev = NULL; char *p = NULL; *major = 0; *minor = 0; *micro = 0; *revis = NULL; /* Break the copy in to major, minor, and micro. */ for(p = tmpcpy; *p; p++) { if (*p == '.') { *p = '\0'; if (startMinor == NULL) { startMinor = p+1; } else if (startMicro == NULL) { startMicro = p+1; } else if (startRev == NULL) { startRev = p+1; break; /* stop parsing, because the revision contains '.' chars */ } } } *major = atoi(tmpcpy); if (startMinor) { *minor = atoi(startMinor); } if (startMicro) { *micro = atoi(startMicro); } if (startRev) { *revis = startRev; } free(tmpcpy); } /*********************************************************************/ /* AIX - lslpp/installp */ /*********************************************************************/ int AIXPackageCheck(char *package,char *version,enum cmpsense cmp) { FILE *pp; struct Item *evrlist = NULL; struct Item *evr; char *evrstart; enum cmpsense result; int match = 0; char tmpBUFF[CF_BUFSIZE]; char *vs, *ve; int verA = 0; int verB = 0; int releaseA = 0; int releaseB = 0; int maintA = 0; int maintB = 0; int fixA = 0; int fixB = 0; Verbose ("Package: %s\n",package); /* check that the package exists in the package database */ /* we're using -l here so that RPM pkgs aren't included. These should be treated seperatly */ snprintf(VBUFF, CF_BUFSIZE, "/usr/bin/lslpp -qcl %s", package); if ((pp = cfpopen (VBUFF, "r")) == NULL) { Verbose ("Could not execute lslpp -qcl.\n"); return 0; } while (!feof (pp)) { *VBUFF = '\0'; ReadLine (VBUFF, CF_BUFSIZE, pp); } if (cfpclose (pp) != 0) { Verbose ("The package %s did not exist in the package database.\n",package); return 0; } /* If no version was specified, we're just checking if the package * is present, not for a particular number, and we can skip the * version number fetch and check. */ if (!*version) { return 1; } /* check what version is installed on the system (if any) */ /* now that we know its installed and not an rpm we can use -L to consolidate the Usr and ROOT portions for the version check */ snprintf (VBUFF, CF_BUFSIZE, "/usr/bin/lslpp -qcL %s", package); if ((pp = cfpopen (VBUFF, "r")) == NULL) { Verbose ("Could not execute lslpp -qcL.\n"); return 0; } while (!feof (pp)) { *VBUFF = '\0'; ReadLine (VBUFF, CF_BUFSIZE, pp); if (*VBUFF != '\0') { /* find third field of : delimited string */ if (sscanf (VBUFF, "%*[^:]:%*[^:]:%[^:]:%*s",tmpBUFF) > 0) { AppendItem (&evrlist, tmpBUFF, ""); } } } if (cfpclose (pp) != 0) { Verbose ("lslpp -qcL exited abnormally.\n"); DeleteItemList (evrlist); return 0; } /* Parse the AIX Version we are looking for once at the start */ ParseAIXVR(version, &verB, &releaseB, &maintB, &fixB); /* The rule here will be: if any package in the list matches, then the * first one to match wins, and we bail out. */ for (evr = evrlist; evr != NULL; evr=evr->next) { char *evrstart; evrstart = evr->name; result = cmpsense_eq; ParseAIXVR(evrstart, &verA, &releaseA, &maintA, &fixA); if (verA > verB) { result = cmpsense_gt; } if(verA < verB) { result = cmpsense_lt; } if (result == cmpsense_eq) { if (releaseA > releaseB) { result = cmpsense_gt; } if (releaseA < releaseB) { result = cmpsense_lt; } if (result == cmpsense_eq) { if (maintA > maintB) { result = cmpsense_gt; } if (maintA < maintB) { result = cmpsense_lt; } /* If the maint versions match, compare the fix level */ if (result == cmpsense_eq) { if (fixA > fixB) { result = cmpsense_gt; } if (fixA < fixB) { result = cmpsense_lt; } } } } switch(cmp) { case cmpsense_gt: match = (result == cmpsense_gt); break; case cmpsense_ge: match = (result == cmpsense_gt || result == cmpsense_eq); break; case cmpsense_lt: match = (result == cmpsense_lt); break; case cmpsense_le: match = (result == cmpsense_lt || result == cmpsense_eq); break; case cmpsense_eq: match = (result == cmpsense_eq); break; case cmpsense_ne: match = (result != cmpsense_eq); break; } if (match) { DeleteItemList(evrlist); return 1; } } /* If we made it out of the loop, there were no matches. */ DeleteItemList(evrlist); return 0; } /*********************************************************************/ int AIXPackageList(char *package, char *version, enum cmpsense cmp, struct Item **pkglist) { return 0; /* not implemented yet */ } /*********************************************************************/ /* AIX docs describe the version as: * Version.Release.Maintenance/Modification.Fix (V.R.M.F). * any non digits [0-9] in these fields will be ignored and only the * numeric digits will be extracted. standalone non-digits will be * treated as 0 for the entire field. V.R.M.F shouldn't contain any * non numeric data (this is enforced by IBM tools like mkinstallp) /*********************************************************************/ void ParseAIXVR(char * vr, int *ver, int *release, int *maint, int *fix) { int v,r,m,f; *ver = 0; *release = 0; *maint = 0; *fix = 0; if (sscanf(vr,"%d.%*s",&v) > 0) { *ver = v; } if (sscanf(vr,"%*[^.].%d.%*s",&r) > 0) { *release = r; } if (sscanf(vr,"%*[^.].%*[^.].%d.%*s",&m) > 0) { *maint = m; } if (sscanf(vr,"%*[^.].%*[^.].%*[^.].%d%*s",&f) > 0) { *fix = f; } } /*********************************************************************/ /* Gentoo Portage */ /*********************************************************************/ int PortagePackageCheck(char *package,char *version,enum cmpsense cmp) { FILE *pp; struct Item *ebuildlist = NULL; struct Item *ebuild = NULL; int match = 0; char *result = NULL; char pkgname[CF_BUFSIZE] = {0}; char *nameptr = NULL; /* Create a working copy of the name */ strncpy(pkgname, package, CF_BUFSIZE - 1); /* Test if complete package atom was given */ if (pkgname[0] == '=' || pkgname[0] == '<' || pkgname[0] == '>') { /* Strip version */ nameptr = strchr(pkgname, '/'); if (nameptr == NULL) { /* Package does not include category, which is fine */ nameptr = pkgname; } while (!xisdigit(nameptr[1])) { nameptr = strchr(++nameptr, '-'); if (nameptr == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to parse version from %s!\n",pkgname); CfLog(cferror,OUTPUT,""); return -1; } } nameptr[0] = '\0'; /* Strip comparison operator (or rather, seek past) */ nameptr = pkgname; while (!xisalpha(nameptr[0])) { ++nameptr; } } else { nameptr = pkgname; } /* Search for installed versions of package */ snprintf(VBUFF,CF_BUFSIZE,"/usr/bin/qlist -IevC %s",nameptr); if ((pp = cfpopen(VBUFF, "r")) == NULL) { CfLog(cferror,"Could not execute the qlist command. Is portage-utils installed?\n",""); return -1; } while(!feof(pp)) { *VBUFF = '\0'; ReadLine(VBUFF,CF_BUFSIZE,pp); if (*VBUFF != '\0') { AppendItem(&ebuildlist,VBUFF,""); } } cfpclose(pp); if (ebuildlist == NULL) { Verbose("PortagePackageCheck(): Package %s not installed.\n", nameptr); return 0; } Verbose("PortagePackageCheck(): Requested %s %s %s\n", nameptr, CMPSENSETEXT[cmp],(version[0] ? version : "ANY")); /* If no version was specified, return successful (found something) */ if (!version[0]) { DeleteItemList(ebuildlist); return 1; } /* Iterate through all installed versions until match is found */ for (ebuild = ebuildlist; ebuild != NULL; ebuild=ebuild->next) { Verbose("PortagePackageCheck(): Trying installed version %s\n", ebuild->name); /* Run comparison tool to do the grunt work */ snprintf(VBUFF,CF_BUFSIZE,"/usr/bin/qatom -cC %s %s-%s", ebuild->name, nameptr, version); if ((pp = cfpopen(VBUFF, "r")) == NULL) { CfLog(cferror,"Could not execute the qatom command. Is portage-utils installed?\n",""); continue; } if (feof(pp)) { snprintf(OUTPUT,CF_BUFSIZE,"Internal error! No output from %s.",VBUFF); CfLog(cferror,OUTPUT,""); continue; } /* Format of output is `package < package' */ *VBUFF = '\0'; ReadLine(VBUFF,CF_BUFSIZE,pp); Verbose("PortagePackageCheck(): Result %s\n",VBUFF); cfpclose(pp); /* Find first space, give up otherwise */ result = strchr(VBUFF, ' '); if (result == NULL) continue; /* Relocate to right of space (the comparison symbol) */ ++result; switch(cmp) { case cmpsense_gt: match = (*result == *CMPSENSEOPERAND[cmpsense_gt]); break; case cmpsense_ge: match = (*result == *CMPSENSEOPERAND[cmpsense_gt] || *result == *CMPSENSEOPERAND[cmpsense_eq]); break; case cmpsense_lt: match = (*result == *CMPSENSEOPERAND[cmpsense_lt]); break; case cmpsense_le: match = (*result == *CMPSENSEOPERAND[cmpsense_lt] || *result == *CMPSENSEOPERAND[cmpsense_eq]); break; case cmpsense_eq: match = (*result == *CMPSENSEOPERAND[cmpsense_eq]); break; case cmpsense_ne: match = (*result != *CMPSENSEOPERAND[cmpsense_eq]); break; } /* Return successful on finding a match */ if (match) { DeleteItemList(ebuildlist); return 1; } } /* No match found, return false */ DeleteItemList(ebuildlist); return 0; } /*********************************************************************/ int PortagePackageList(char *package, char *version, enum cmpsense cmp, struct Item **pkglist) { FILE *pp; struct Item *ebuildlist = NULL; struct Item *ebuild = NULL; int match = 0; int nummatches = 0; char *result = NULL; char pkgname[CF_BUFSIZE] = {0}; char pkgatom[CF_BUFSIZE] = {0}; char *nameptr = NULL; /* Create a working copy of the name */ strncpy(pkgname, package, CF_BUFSIZE - 1); /* Test if complete package atom was given */ if (pkgname[0] == '=' || pkgname[0] == '<' || pkgname[0] == '>') { /* Strip version */ nameptr = strchr(pkgname, '/'); if (nameptr == NULL) { /* Package does not include category, which is fine */ nameptr = pkgname; } while (!xisdigit(nameptr[1])) { nameptr = strchr(++nameptr, '-'); if (nameptr == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to parse version from %s!\n",pkgname); CfLog(cferror,OUTPUT,""); return -1; } } nameptr[0] = '\0'; /* Strip comparison operator (or rather, seek past) */ nameptr = pkgname; while (!xisalpha(nameptr[0])) { ++nameptr; } } else { nameptr = pkgname; } /* Search for installed versions of package */ snprintf(VBUFF,CF_BUFSIZE,"/usr/bin/qlist -IevC %s",nameptr); if ((pp = cfpopen(VBUFF, "r")) == NULL) { CfLog(cferror,"Could not execute the qlist command. Is portage-utils installed?\n",""); return -1; } while(!feof(pp)) { *VBUFF = '\0'; ReadLine(VBUFF,CF_BUFSIZE,pp); if (*VBUFF != '\0') { AppendItem(&ebuildlist,VBUFF,""); } } cfpclose(pp); if (ebuildlist == NULL) { Verbose("PortagePackageList(): Package %s not installed.\n", nameptr); return 0; } Verbose("PortagePackageList(): Requested %s %s %s\n", nameptr, CMPSENSETEXT[cmp],(version[0] ? version : "ANY")); /* Iterate through all installed versions and register matches */ for (ebuild = ebuildlist; ebuild != NULL; ebuild=ebuild->next) { Verbose("PortagePackageList(): Trying installed version %s\n", ebuild->name); /* If no version was specified, register ebuild */ if (!version[0]) { strncpy(pkgatom, "=", CF_BUFSIZE - 1); strncat(pkgatom, ebuild->name, CF_BUFSIZE - 2); snprintf(OUTPUT,CF_BUFSIZE,"Package atom matches: %s\n",pkgatom); AppendItem(pkglist,pkgatom,""); ++nummatches; continue; } /* Run comparison tool to do the grunt work */ snprintf(VBUFF,CF_BUFSIZE,"/usr/bin/qatom -cC %s %s-%s", ebuild->name, nameptr, version); if ((pp = cfpopen(VBUFF, "r")) == NULL) { CfLog(cferror,"Could not execute the qatom command. Is portage-utils installed?\n",""); continue; } if (feof(pp)) { snprintf(OUTPUT,CF_BUFSIZE,"Internal error! No output from %s.",VBUFF); CfLog(cferror,OUTPUT,""); continue; } /* Format of output is `package < package' */ *VBUFF = '\0'; ReadLine(VBUFF,CF_BUFSIZE,pp); Verbose("PortagePackageList(): Result %s\n",VBUFF); cfpclose(pp); /* Find first space, give up otherwise */ result = strchr(VBUFF, ' '); if (result == NULL) continue; /* Relocate to right of space (the comparison symbol) */ ++result; switch(cmp) { case cmpsense_gt: match = (*result == *CMPSENSEOPERAND[cmpsense_gt]); break; case cmpsense_ge: match = (*result == *CMPSENSEOPERAND[cmpsense_gt] || *result == *CMPSENSEOPERAND[cmpsense_eq]); break; case cmpsense_lt: match = (*result == *CMPSENSEOPERAND[cmpsense_lt]); break; case cmpsense_le: match = (*result == *CMPSENSEOPERAND[cmpsense_lt] || *result == *CMPSENSEOPERAND[cmpsense_eq]); break; case cmpsense_eq: match = (*result == *CMPSENSEOPERAND[cmpsense_eq]); break; case cmpsense_ne: match = (*result != *CMPSENSEOPERAND[cmpsense_eq]); break; } /* Register ebuild on finding a match */ if (match) { strncpy(pkgatom, "=", CF_BUFSIZE - 1); strncat(pkgatom, ebuild->name, CF_BUFSIZE - 2); snprintf(OUTPUT,CF_BUFSIZE,"Package atom matches: %s\n",pkgatom); AppendItem(pkglist,pkgatom,""); ++nummatches; continue; } } DeleteItemList(ebuildlist); /* Return whether matches found */ return nummatches > 0 ? 1 : 0; } /*********************************************************************/ /* FreeBSD - pkg_info/pkg_add/pkg_delete */ /*********************************************************************/ int FreeBSDPackageCheck(char *package,char *version,enum cmpsense cmp) { FILE *pp; int match = 0; int result; char line[CF_BUFSIZE]; char pkgname[CF_BUFSIZE]; char *pkgversion; /* The package to compare must contain a version number * The version starts after the last '-' in the pkgname */ strncpy(pkgname, package, CF_BUFSIZE - 1); pkgversion = strrchr(pkgname, '-'); if (pkgversion) { /* insert a null to remove version for comparison */ *pkgversion = '\0'; } Debug("FreeBSDPackageCheck(): Requested version %s %s of %s\n", CMPSENSETEXT[cmp],(version[0] ? version : "ANY"), pkgname); if (!*version) { cmp = cmpsense_gt; version[0] = '0'; version[1] = 0; } /* check what version is installed on the system (if any) */ Verbose("FreeBSDPackageCheck(): Running /usr/sbin/pkg_info -qE '%s%s%s'\n", pkgname, CMPSENSEOPERAND[cmp], version); snprintf (VBUFF, CF_BUFSIZE, "/usr/sbin/pkg_info -qE '%s%s%s'", pkgname, CMPSENSEOPERAND[cmp], version); if ((pp = cfpopen (VBUFF, "r")) == NULL) { CfLog(cferror,"FATAL: Could not execute pkg_info.\n","popen"); return -1; } while (!feof (pp)) { *VBUFF = '\0'; ReadLine (line, CF_BUFSIZE - 1, pp); snprintf(OUTPUT,CF_BUFSIZE,"%s\n",line); } result = cfpclose( pp ); switch( result ) { case 0: Verbose ("FreeBSDPackageCheck(): %s %s %s is installed on this system.\n", pkgname, CMPSENSETEXT[cmp],(version[0] ? version : "ANY") ); match = 1; break; case 1: Verbose ("FreeBSDPackageCheck(): %s %s %s is not installed on this system.\n", pkgname, CMPSENSETEXT[cmp],(version[0] ? version : "ANY") ); match = 0; break; case 256: Verbose ("FreeBSDPackageCheck(): %s %s %s is not installed on this system.\n", pkgname, CMPSENSETEXT[cmp],(version[0] ? version : "ANY") ); match = 0; break; default: Verbose ("FreeBSDPackageCheck(): error running package query: %d\n", result ); match = -1; break; } return match; } /***********************************************************************/ int FreeBSDPackageList(char *package, char *version, enum cmpsense cmp, struct Item **pkglist) { FILE *pp; int match = 0, result; char line[CF_BUFSIZE]; char pkgname[CF_BUFSIZE]; char *pkgversion; /* The package name is derived by stripping off the version number */ strncpy(pkgname, package, CF_BUFSIZE - 1); pkgversion = strrchr(pkgname, '-'); if( pkgversion ) { *pkgversion = '\0'; } Debug("FreeBSDPackageCheck(): Requested version %s %s of %s\n", CMPSENSETEXT[cmp],(version[0] ? version : "ANY"), pkgname); /* If no version was specified, we're just checking if the package * is present, not for a particular number, so >0 will match. */ if (!*version) { cmp = cmpsense_gt; version[0] = '0'; version[1] = 0; } Verbose("FreeBSDPackageList(): Running /usr/sbin/pkg_info -E '%s%s%s'\n", pkgname, CMPSENSEOPERAND[cmp], version); snprintf (VBUFF, CF_BUFSIZE, "/usr/sbin/pkg_info -E '%s%s%s'", pkgname, CMPSENSEOPERAND[cmp], version); if ((pp = cfpopen (VBUFF, "r")) == NULL) { Verbose ("Could not execute pkg_info.\n"); return -1; } while (!feof (pp)) { *VBUFF = '\0'; ReadLine (line, CF_BUFSIZE - 1, pp); Debug("PackageList: read line %s\n",line); if( strlen(line) > 1 ) { snprintf(OUTPUT,CF_BUFSIZE,"Package to remove: %s\n",line); AppendItem(pkglist,line,""); } } result = cfpclose( pp ); switch( result ) { case 0: Verbose ("FreeBSDPackageList(): %s %s %s is installed on this system.\n", pkgname, CMPSENSETEXT[cmp],(version[0] ? version : "ANY") ); match=1; break; case 1: Verbose ("FreeBSDPackageList(): %s %s %s is not installed on this system.\n", pkgname, CMPSENSETEXT[cmp],(version[0] ? version : "ANY") ); match=0; break; case 256: Verbose ("FreeBSDPackageList(): %s %s %s is not installed on this system.\n", pkgname, CMPSENSETEXT[cmp],(version[0] ? version : "ANY") ); match=0; break; default: Verbose ("FreeBSDPackageList(): error running package query: %d\n", result ); match=-1; break; } return match; } /*********************************************************************/ /* RPM Version string comparison logic * * ParseEVR and rpmvercmp are taken directly from the rpm 4.1 sources. * ParseEVR is taken from the parseEVR routine in lib/rpmds.c and rpmvercmp * is taken from llib/rpmvercmp.c */ /* compare alpha and numeric segments of two versions */ /* return 1: a is newer than b */ /* 0: a and b are the same version */ /* -1: b is newer than a */ /*********************************************************************/ int rpmvercmp(const char * a, const char * b) { char oldch1, oldch2; char * str1, * str2; char * one, * two; char *s1,*s2; int rc; int isnum; /* easy comparison to see if versions are identical */ if (!strcmp(a, b)) { return 0; } one = str1 = s1 = strdup(a); two = str2 = s2 = strdup(b); /* loop through each version segment of str1 and str2 and compare them */ while (*one && *two) { while (*one && !xisalnum(*one)) one++; while (*two && !xisalnum(*two)) two++; str1 = one; str2 = two; /* grab first completely alpha or completely numeric segment */ /* leave one and two pointing to the start of the alpha or numeric */ /* segment and walk str1 and str2 to end of segment */ if (xisdigit(*str1)) { while (*str1 && xisdigit(*str1)) str1++; while (*str2 && xisdigit(*str2)) str2++; isnum = 1; } else { while (*str1 && xisalpha(*str1)) str1++; while (*str2 && xisalpha(*str2)) str2++; isnum = 0; } /* save character at the end of the alpha or numeric segment */ /* so that they can be restored after the comparison */ oldch1 = *str1; *str1 = '\0'; oldch2 = *str2; *str2 = '\0'; /* take care of the case where the two version segments are */ /* different types: one numeric, the other alpha (i.e. empty) */ if (one == str1) { free(s1); free(s2); return -1; /* arbitrary */ } if (two == str2) { free(s1); free(s2); return -1; } if (isnum) { /* this used to be done by converting the digit segments */ /* to ints using atoi() - it's changed because long */ /* digit segments can overflow an int - this should fix that. */ /* throw away any leading zeros - it's a number, right? */ while (*one == '0') one++; while (*two == '0') two++; /* whichever number has more digits wins */ if (strlen(one) > strlen(two)) { free(s1); free(s2); return 1; } if (strlen(two) > strlen(one)) { free(s1); free(s2); return -1; } } /* strcmp will return which one is greater - even if the two */ /* segments are alpha or if they are numeric. don't return */ /* if they are equal because there might be more segments to */ /* compare */ rc = strcmp(one, two); if (rc) { free(s1); free(s2); if (rc > 0) { return 1; } if (rc < 0) { return -1; } } /* restore character that was replaced by null above */ *str1 = oldch1; one = str1; *str2 = oldch2; two = str2; } /* this catches the case where all numeric and alpha segments have */ /* compared identically but the segment sepparating characters were */ /* different */ if ((!*one) && (!*two)) { free(s1); free(s2); return 0; } /* whichever version still has characters left over wins */ if (!*one) { free(s1); free(s2); return -1; } else { free(s1); free(s2); return 1; } } /*************************************************************************/ /** * Split EVR into epoch, version, and release components. * @param evr [epoch:]version[-release] string * @retval *ep pointer to epoch * @retval *vp pointer to version * @retval *rp pointer to release */ void ParseEVR(char * evr,const char ** ep,const char ** vp,const char ** rp) { const char *epoch; const char *version; /* assume only version is present */ const char *release; char *s, *se; s = evr; while (*s && xisdigit(*s)) { s++; /* s points to epoch terminator */ } se = strrchr(s, '-'); /* se points to version terminator */ if (*s == ':') { epoch = evr; *s++ = '\0'; version = s; if (*epoch == '\0') epoch = "0"; } else { epoch = NULL; /* XXX disable epoch compare if missing */ version = evr; } if (se) { *se++ = '\0'; release = se; } else { release = NULL; } if (ep) *ep = epoch; if (vp) *vp = version; if (rp) *rp = release; } cfengine-2.2.10/src/filenames.c0000644000175000001440000004333011124427763013177 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*********************************************************************/ /* */ /* TOOLKITS: "sharable" library */ /* */ /*********************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ /* Level 1 */ /*********************************************************************/ int IsIn(char c,char *str) { char *sp; for(sp = str; *sp != '\0'; sp++) { if (*sp == c) { return true; } } return false; } /*********************************************************************/ int IsAbsoluteFileName(char *f) { #ifdef NT if (IsFileSep(f[0]) && IsFileSep(f[1])) { return true; } if ( isalpha(f[0]) && f[1] == ':' && IsFileSep(f[2]) ) { return true; } #endif if (*f == '/') { return true; } return false; } /*******************************************************************/ int RootDirLength(char *f) /* Return length of Initial directory in path - */ { #ifdef NT int len; if (IsFileSep(f[0]) && IsFileSep(f[1])) { /* UNC style path */ /* Skip over host name */ for (len=2; !IsFileSep(f[len]); len++) { if (f[len] == '\0') { return len; } } /* Skip over share name */ for (len++; !IsFileSep(f[len]); len++) { if (f[len] == '\0') { return len; } } /* Skip over file separator */ len++; return len; } if ( isalpha(f[0]) && f[1] == ':' && IsFileSep(f[2]) ) { return 3; } #endif if (*f == '/') { return 1; } return 0; } /*******************************************************************/ void AddSlash(char *str) { char *sp, *sep = FILE_SEPARATOR_STR; int f = false ,b = false; if (str == NULL) { return; } /* Try to see what convention is being used for filenames in case this is a cross-system copy from Win/Unix */ for (sp = str; *sp != '\0'; sp++) { switch (*sp) { case '/': f = true; break; case '\\': b = true; break; default: break; } } if (f && !b) { sep = "/"; } else if (b && !f) { sep = "\\"; } if (!IsFileSep(str[strlen(str)-1])) { strcat(str,sep); } } /*********************************************************************/ void DeleteSlash(char *str) { if ((strlen(str)== 0) || (str == NULL)) { return; } if (strcmp(str,"/") == 0) { return; } if (IsFileSep(str[strlen(str)-1])) { str[strlen(str)-1] = '\0'; } } /*********************************************************************/ void DeleteNewline(char *str) { if ((strlen(str)== 0) || (str == NULL)) { return; } /* !!! remove carriage return too? !!! */ if (str[strlen(str)-1] == '\n') { str[strlen(str)-1] = '\0'; } } /*********************************************************************/ char *LastFileSeparator(char *str) /* Return pointer to last file separator in string, or NULL if string does not contains any file separtors */ { char *sp; /* Walk through string backwards */ sp = str + strlen(str) - 1; while (sp >= str) { if (IsFileSep(*sp)) { return sp; } sp--; } return NULL; } /*********************************************************************/ int ChopLastNode(char *str) /* Chop off trailing node name (possible blank) starting from last character and removing up to the first / encountered e.g. /a/b/c -> /a/b /a/b/ -> /a/b */ { char *sp; int ret; if ((sp = LastFileSeparator(str)) == NULL) { ret = false; } else { *sp = '\0'; ret = true; } if (strlen(str) == 0) { AddSlash(str); } return ret; } /*********************************************************************/ char *CanonifyName(char *str) { static char buffer[CF_BUFSIZE]; char *sp; memset(buffer,0,CF_BUFSIZE); strcpy(buffer,str); for (sp = buffer; *sp != '\0'; sp++) { if (!isalnum((int)*sp) || *sp == '.') { *sp = '_'; } } return buffer; } /*********************************************************************/ char *Space2Score(char *str) { static char buffer[CF_BUFSIZE]; char *sp; memset(buffer,0,CF_BUFSIZE); strcpy(buffer,str); for (sp = buffer; *sp != '\0'; sp++) { if (*sp == ' ') { *sp = '_'; } } return buffer; } /*********************************************************************/ char *ASUniqueName(char *str) /* generates a unique action sequence name */ { static char buffer[CF_BUFSIZE]; struct Item *ip; memset(buffer,0,CF_BUFSIZE); strcpy(buffer,str); for (ip = VADDCLASSES; ip != NULL; ip=ip->next) { if (strlen(buffer)+strlen(ip->name)+3 > CF_MAXLINKSIZE) { break; } strcat(buffer,"."); strcat(buffer,ip->name); } return buffer; } /*********************************************************************/ char *ReadLastNode(char *str) /* Return the last node of a pathname string */ { char *sp; if ((sp = LastFileSeparator(str)) == NULL) { return str; } else { return sp + 1; } } /*********************************************************************/ int MakeDirectoriesFor(char *file,char force) /* Make all directories which underpin file */ { char *sp,*spc; char currentpath[CF_BUFSIZE]; char pathbuf[CF_BUFSIZE]; struct stat statbuf; mode_t mask; int rootlen; char Path_File_Separator; #ifdef DARWIN /* Keeps track of if dealing w. resource fork */ int rsrcfork; rsrcfork = 0; char * tmpstr; #endif if (!IsAbsoluteFileName(file)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Will not create directories for a relative filename (%s). Has no invariant meaning\n",file); CfLog(cferror,OUTPUT,""); return false; } strncpy(pathbuf,file,CF_BUFSIZE-1); /* local copy */ #ifdef DARWIN /* Dealing w. a rsrc fork? */ if (strstr(pathbuf, _PATH_RSRCFORKSPEC) != NULL) { rsrcfork = 1; } #endif /* skip link name */ sp = LastFileSeparator(pathbuf); if (sp == NULL) { sp = pathbuf; } *sp = '\0'; DeleteSlash(pathbuf); if (lstat(pathbuf,&statbuf) != -1) { if (S_ISLNK(statbuf.st_mode)) { Verbose("%s: INFO: %s is a symbolic link, not a true directory!\n",VPREFIX,pathbuf); } if (force == 'y') /* force in-the-way directories aside */ { if (!S_ISDIR(statbuf.st_mode)) /* if the dir exists - no problem */ { if (ISCFENGINE) { struct Tidy tp; struct TidyPattern tpat; struct stat sbuf; if (DONTDO) { return true; } strcpy(currentpath,pathbuf); DeleteSlash(currentpath); strcat(currentpath,".cf-moved"); snprintf(OUTPUT,CF_BUFSIZE,"Moving obstructing file/link %s to %s to make directory",pathbuf,currentpath); CfLog(cferror,OUTPUT,""); /* If cfagent, remove an obstructing backup object */ if (lstat(currentpath,&sbuf) != -1) { if (S_ISDIR(sbuf.st_mode)) { tp.maxrecurse = 2; tp.tidylist = &tpat; tp.next = NULL; tp.path = currentpath; tpat.recurse = CF_INF_RECURSE; tpat.age = 0; tpat.size = 0; tpat.pattern = strdup("*"); tpat.classes = strdup("any"); tpat.defines = NULL; tpat.elsedef = NULL; tpat.dirlinks = 'y'; tpat.travlinks = 'n'; tpat.rmdirs = 'y'; tpat.searchtype = 'a'; tpat.log = 'd'; tpat.inform = 'd'; tpat.next = NULL; RecursiveTidySpecialArea(currentpath,&tp,CF_INF_RECURSE,&sbuf); free(tpat.pattern); free(tpat.classes); if (rmdir(currentpath) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't remove directory %s while trying to remove a backup\n",currentpath); CfLog(cfinform,OUTPUT,"rmdir"); } } else { if (unlink(currentpath) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't remove file/link %s while trying to remove a backup\n",currentpath); CfLog(cfinform,OUTPUT,"rmdir"); } } } /* And then move the current object out of the way...*/ if (rename(pathbuf,currentpath) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Warning. The object %s is not a directory.\n",pathbuf); CfLog(cfinform,OUTPUT,""); CfLog(cfinform,"Could not make a new directory or move the block","rename"); return(false); } } } else { if (! S_ISLNK(statbuf.st_mode) && ! S_ISDIR(statbuf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Warning. The object %s is not a directory.\n",pathbuf); CfLog(cfinform,OUTPUT,""); CfLog(cfinform,"Cannot make a new directory without deleting it!\n\n",""); return(false); } } } } /* Now we can make a new directory .. */ currentpath[0] = '\0'; rootlen = RootDirLength(sp); strncpy(currentpath, file, rootlen); for (sp = file+rootlen, spc = currentpath+rootlen; *sp != '\0'; sp++) { if (!IsFileSep(*sp) && *sp != '\0') { *spc = *sp; spc++; } else { Path_File_Separator = *sp; *spc = '\0'; if (strlen(currentpath) == 0) { } else if (stat(currentpath,&statbuf) == -1) { Debug2("cfengine: Making directory %s, mode %o\n",currentpath,DEFAULTMODE); if (! DONTDO) { mask = umask(0); if (mkdir(currentpath,DEFAULTMODE) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to make directories to %s\n",file); CfLog(cferror,OUTPUT,"mkdir"); umask(mask); return(false); } umask(mask); } } else { if (! S_ISDIR(statbuf.st_mode)) { #ifdef DARWIN /* Ck if rsrc fork */ if (rsrcfork) { tmpstr = malloc(CF_BUFSIZE); strncpy(tmpstr, currentpath, CF_BUFSIZE); strncat(tmpstr, _PATH_FORKSPECIFIER, CF_BUFSIZE); /* Cfengine removed terminating slashes */ DeleteSlash(tmpstr); if (strncmp(tmpstr, pathbuf, CF_BUFSIZE) == 0) { free(tmpstr); return(true); } free(tmpstr); } #endif snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot make %s - %s is not a directory! (use forcedirs=true)\n",pathbuf,currentpath); CfLog(cferror,OUTPUT,""); return(false); } } /* *spc = FILE_SEPARATOR; */ *spc = Path_File_Separator; spc++; } } Debug("Directory for %s exists. Okay\n",file); return(true); } /*********************************************************************/ int BufferOverflow(char *str1,char *str2) /* Should be an inline ! */ { int len = strlen(str2); if ((strlen(str1)+len) > (CF_BUFSIZE - CF_BUFFERMARGIN)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Buffer overflow constructing string. Increase CF_BUFSIZE macro.\n"); CfLog(cferror,OUTPUT,""); printf("%s: Tried to add %s to %s\n",VPREFIX,str2,str1); return true; } return false; } /*********************************************************************/ int ExpandOverflow(char *str1,char *str2) /* Should be an inline ! */ { int len = strlen(str2); if ((strlen(str1)+len) > (CF_EXPANDSIZE - CF_BUFFERMARGIN)) { snprintf(OUTPUT,CF_BUFSIZE,"Expansion overflow constructing string. Increase CF_EXPANDSIZE macro.\n"); CfLog(cferror,OUTPUT,""); printf("%s: Tried to add %s to %s\n",VPREFIX,str2,str1); return true; } return false; } /*********************************************************************/ void Chop(char *str) /* remove trailing spaces */ { int i; if ((str == NULL) || (strlen(str) == 0)) { return; } if (strlen(str) > CF_BUFSIZE) { CfLog(cferror,"Chop was called on a string that seemed to have no terminator",""); return; } for (i = strlen(str)-1; isspace((int)str[i]); i--) { str[i] = '\0'; } } /*********************************************************************/ int CompressPath(char *dest,char *src) { char *sp; char node[CF_BUFSIZE]; int nodelen; int rootlen; Debug2("CompressPath(%s,%s)\n",dest,src); memset(dest,0,CF_BUFSIZE); rootlen = RootDirLength(src); strncpy(dest,src,rootlen); for (sp = src+rootlen; *sp != '\0'; sp++) { if (IsFileSep(*sp)) { continue; } for (nodelen = 0; sp[nodelen] != '\0' && !IsFileSep(sp[nodelen]); nodelen++) { if (nodelen > CF_MAXLINKSIZE) { CfLog(cferror,"Link in path suspiciously large",""); return false; } } strncpy(node, sp, nodelen); node[nodelen] = '\0'; sp += nodelen - 1; if (strcmp(node,".") == 0) { continue; } if (strcmp(node,"..") == 0) { if (!ChopLastNode(dest)) { Debug("cfengine: used .. beyond top of filesystem!\n"); return false; } continue; } else { AddSlash(dest); } if (BufferOverflow(dest,node)) { return false; } strcat(dest,node); } return true; } /*********************************************************************/ /* TOOLKIT : String */ /*********************************************************************/ char ToLower (char ch) { if (isdigit((int)ch) || ispunct((int)ch)) { return(ch); } if (islower((int)ch)) { return(ch); } else { return(ch - 'A' + 'a'); } } /*********************************************************************/ char ToUpper (char ch) { if (isdigit((int)ch) || ispunct((int)ch)) { return(ch); } if (isupper((int)ch)) { return(ch); } else { return(ch - 'a' + 'A'); } } /*********************************************************************/ char *ToUpperStr (char *str) { static char buffer[CF_BUFSIZE]; int i; memset(buffer,0,CF_BUFSIZE); if (strlen(str) >= CF_BUFSIZE) { char *tmp; tmp = malloc(40+strlen(str)); sprintf(tmp,"String too long in ToUpperStr: %s",str); FatalError(tmp); } for (i = 0; (str[i] != '\0') && (i < CF_BUFSIZE-1); i++) { buffer[i] = ToUpper(str[i]); } buffer[i] = '\0'; return buffer; } /*********************************************************************/ char *ToLowerStr (char *str) { static char buffer[CF_BUFSIZE]; int i; memset(buffer,0,CF_BUFSIZE); if (strlen(str) >= CF_BUFSIZE-1) { char *tmp; tmp = malloc(40+strlen(str)); snprintf(tmp,CF_BUFSIZE-1,"String too long in ToLowerStr: %s",str); FatalError(tmp); } for (i = 0; (str[i] != '\0') && (i < CF_BUFSIZE-1); i++) { buffer[i] = ToLower(str[i]); } buffer[i] = '\0'; return buffer; } /*********************************************************************/ void CreateEmptyFile(char *name) { int tempfd; /* FILE *fp; if ((fp = fopen(name,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Cannot create file %s",name); CfLog(cfverbose,OUTPUT,"fopen"); return; } fclose(fp); */ if (unlink(name) == -1) { Debug("Pre-existing object %s could not be removed or was not there\n",VLOGFILE); } if ((tempfd = open(name, O_CREAT|O_EXCL|O_WRONLY,0600)) < 0) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open a file %s\n",VLOGFILE); CfLog(cfverbose,OUTPUT,"open"); } close(tempfd); } /*********************************************************************/ cfengine-2.2.10/src/cfshow.c0000644000175000001440000011240411046321476012521 00000000000000/*****************************************************************************/ /* */ /* File: cfshow.c */ /* */ /* Created: Wed Sep 22 16:47:23 2004 */ /* */ /* Author: Mark */ /* */ /* Description: Print data from the Berkeeley databases in reable form */ /* */ /*****************************************************************************/ #include "../pub/getopt.h" #include "cf.defs.h" #include "cf.extern.h" /*******************************************************************/ /* GLOBAL VARIABLES */ /*******************************************************************/ struct option CFSHOPTIONS[] = { { "help",no_argument,0,'h' }, { "debug",optional_argument,0,'d' }, { "verbose",no_argument,0,'v' }, { "locks",no_argument,0,'l'}, { "last-seen",no_argument,0,'s'}, { "performance",no_argument,0,'p'}, { "checksum",no_argument,0,'c'}, { "active",no_argument,0,'a'}, { "classes",no_argument,0,'C'}, { "version",no_argument,0,'V'}, { "html",no_argument,0,'H'}, { "xml",no_argument,0,'X'}, { "purge",no_argument,0,'P'}, { "audit",no_argument,0,'A'}, { "regex",required_argument,0,'r'}, { "filename",required_argument,0,'f'}, { NULL,0,0,0 } }; enum databases { cf_db_lastseen, cf_db_locks, cf_db_active, cf_db_checksum, cf_db_performance, cf_db_audit, cf_db_classes, cf_db_regex }; enum databases TODO = -1; #define CF_ACTIVE 1 #define CF_INACTIVE 0 /*******************************************************************/ struct CEnt /* For sorting */ { char name[256]; char date[32]; double q; double d; }; /*******************************************************************/ enum cf_formatindex { cfb, cfe, }; enum cf_format { cfx_entry, cfx_event, cfx_host, cfx_pm, cfx_ip, cfx_date, cfx_q, cfx_av, cfx_dev, cfx_version, cfx_ref, cfx_filename, cfx_index }; short XML = false; char *CFX[][2] = { "\n","\n\n", "\n","\n\n", "\n","\n\n", "\n","\n\n", "\n","\n\n", "\n","\n\n", "\n","\n\n", "\n","\n\n", "\n","\n\n", "\n","\n\n", "\n","\n\n", "\n","\n\n", "\n","\n\n", NULL,NULL }; short HTML = false; char *CFH[][2] = { "","\n\n", "","\n", "","\n", "","\n", "","\n", "","\n", "","\n", "","\n", "","\n", "","\n", "","\n", "","\n", "","\n", NULL,NULL }; /*******************************************************************/ /* Functions internal to cfshow.c */ /*******************************************************************/ void CheckOptsAndInit (int argc,char **argv); void Syntax (void); void PrintDB(void); void ShowLastSeen(void); void ShowChecksums(void); void ShowClasses(void); void ShowRegex(char *regex); void ShowLocks(int active); void ShowPerformance(void); void ShowCurrentAudit(void); char *ChecksumDump(unsigned char digest[EVP_MAX_MD_SIZE+1]); char *Format(char *s,int width); int CompareClasses(const void *a, const void *b); /*******************************************************************/ /* Level 0 : Main */ /*******************************************************************/ int main (int argc,char **argv) { CheckOptsAndInit(argc,argv); PrintDB(); return 0; } /********************************************************************/ /* Level 1 */ /********************************************************************/ void CheckOptsAndInit(int argc,char **argv) { extern char *optarg; int optindex = 0; int c; PURGE = 'n'; AUDIT = false; while ((c=getopt_long(argc,argv,"AChdvaVlr:f:scpPXH",CFSHOPTIONS,&optindex)) != EOF) { switch ((char) c) { case 'd': switch ((optarg==NULL)?3:*optarg) { case '1': D1 = true; break; case '2': D2 = true; break; default: DEBUG = true; break; } VERBOSE = true; printf("cfshow Debug mode: running in foreground\n"); break; case 'v': VERBOSE = true; break; case 'V': printf("GNU %s-%s db tool\n%s\n",PACKAGE,VERSION,COPYRIGHT); printf("This program is covered by the GNU Public License and may be\n"); printf("copied free of charge. No warrenty is implied.\n\n"); exit(0); break; case 'a': TODO = cf_db_active; break; case 'A': AUDIT = true; TODO = cf_db_audit; break; case 'l': TODO = cf_db_locks; break; case 's': TODO = cf_db_lastseen; break; case 'c': TODO = cf_db_checksum; break; case 'C': TODO = cf_db_classes; break; case 'p': TODO = cf_db_performance; break; case 'X': XML = true; break; case 'H': HTML = true; break; case 'P': PURGE = 'y'; break; case'f': strncpy(VINPUTFILE,optarg, CF_BUFSIZE-1); VINPUTFILE[CF_BUFSIZE-1] = '\0'; MINUSF = true; printf("Looking for %s\n",VINPUTFILE); break; case 'r': ShowRegex(optarg); TODO = cf_db_regex; break; default: Syntax(); exit(1); } } strcpy(CFWORKDIR,WORKDIR); #ifndef NT if (getuid() > 0) { char *homedir; if ((homedir = getenv("HOME")) != NULL) { strcpy(CFWORKDIR,homedir); strcat(CFWORKDIR,"/.cfagent"); } } #endif GetNameInfo(); strcpy(VFQNAME,VSYSNAME.nodename); } /********************************************************************/ void PrintDB() { switch (TODO) { case cf_db_lastseen: ShowLastSeen(); break; case cf_db_locks: ShowLocks(CF_INACTIVE); break; case cf_db_active: ShowLocks(CF_ACTIVE); break; case cf_db_checksum: ShowChecksums(); break; case cf_db_performance: ShowPerformance(); break; case cf_db_audit: ShowCurrentAudit(); break; case cf_db_classes: ShowClasses(); break; default: break; } } /*********************************************************************/ /* Level 2 */ /*********************************************************************/ void Syntax() { int i; printf("GNU cfengine db tool\n%s-%s\n%s\n",PACKAGE,VERSION,COPYRIGHT); printf("\n"); printf("Options:\n\n"); for (i=0; CFSHOPTIONS[i].name != NULL; i++) { printf("--%-20s (-%c)\n",CFSHOPTIONS[i].name,(char)CFSHOPTIONS[i].val); } printf("\nBug reports to bug-cfengine@cfengine.org\n"); printf("General help to help-cfengine@cfengine.org\n"); printf("Info & fixes at http://www.cfengine.org\n"); } /*******************************************************************/ void ShowLastSeen() { DBT key,value; DB *dbp; DBC *dbcp; DB_ENV *dbenv = NULL; double now = (double)time(NULL),average = 0, var = 0; double ticksperhr = (double)CF_TICKS_PER_HOUR; char name[CF_BUFSIZE],hostname[CF_BUFSIZE]; struct QPoint entry; int ret; snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); if ((errno = db_create(&dbp,dbenv,0)) != 0) { printf("Couldn't open last-seen database %s\n",name); perror("db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { printf("Couldn't open last-seen database %s\n",name); perror("db_open"); dbp->close(dbp,0); return; } if (HTML) { printf("

Peers recently seen by %s

",VFQNAME); } if (XML) { printf("\n\n"); } /* Acquire a cursor for the database. */ if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { printf("Error reading from last-seen database: "); dbp->err(dbp, ret, "DB->cursor"); return; } /* Initialize the key/data return pair. */ memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); memset(&entry, 0, sizeof(entry)); /* Walk through the database and print out the key/data pairs. */ while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { double then; time_t fthen; char tbuf[CF_BUFSIZE],addr[CF_BUFSIZE]; memcpy(&then,value.data,sizeof(then)); strcpy(hostname,(char *)key.data); if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); then = entry.q; average = (double)entry.expect; var = (double)entry.var; } else { continue; } if (PURGE == 'y') { if (now - then > CF_WEEK) { if ((errno = dbp->del(dbp,NULL,&key,0)) != 0) { CfLog(cferror,"","db_store"); } } fprintf(stderr,"Deleting expired entry for %s\n",hostname); continue; } fthen = (time_t)then; /* format date */ snprintf(tbuf,CF_BUFSIZE-1,"%s",ctime(&fthen)); tbuf[strlen(tbuf)-9] = '\0'; /* Chop off second and year */ if (strlen(hostname+1) > 15) { snprintf(addr,15,"...%s",hostname+strlen(hostname)-10); /* ipv6 */ } else { snprintf(addr,15,"%s",hostname+1); } if (XML) { printf("%s",CFX[cfx_entry][cfb]); printf("%s%c%s",CFX[cfx_pm][cfb],*hostname,CFX[cfx_pm][cfe]); printf("%s%s%s",CFX[cfx_host][cfb],IPString2Hostname(hostname+1),CFX[cfx_host][cfe]); printf("%s%s%s",CFX[cfx_ip][cfb],hostname+1,CFX[cfx_ip][cfe]); printf("%s%s%s",CFX[cfx_date][cfb],tbuf,CFX[cfx_date][cfe]); printf("%s%.2f%s",CFX[cfx_q][cfb],((double)(now-then))/ticksperhr,CFX[cfx_q][cfe]); printf("%s%.2f%s",CFX[cfx_av][cfb],average/ticksperhr,CFX[cfx_av][cfe]); printf("%s%.2f%s",CFX[cfx_dev][cfb],sqrt(var)/ticksperhr,CFX[cfx_dev][cfe]); printf("%s",CFX[cfx_entry][cfe]); } else if (HTML) { printf("%s",CFH[cfx_entry][cfb]); printf("%s%c%s",CFH[cfx_pm][cfb],*hostname,CFH[cfx_pm][cfe]); printf("%s%s%s",CFH[cfx_host][cfb],IPString2Hostname(hostname+1),CFH[cfx_host][cfe]); printf("%s%s%s",CFH[cfx_ip][cfb],hostname+1,CFH[cfx_ip][cfe]); printf("%s Last seen at %s%s",CFH[cfx_date][cfb],tbuf,CFH[cfx_date][cfe]); printf("%s %.2f hrs ago %s",CFH[cfx_q][cfb],((double)(now-then))/ticksperhr,CFH[cfx_q][cfe]); printf("%s Av %.2f hrs %s",CFH[cfx_av][cfb],average/ticksperhr,CFH[cfx_av][cfe]); printf("%s ± %.2f hrs %s",CFH[cfx_dev][cfb],sqrt(var)/ticksperhr,CFH[cfx_dev][cfe]); printf("%s",CFH[cfx_entry][cfe]); } else { printf("IP %c %25.25s %15.15s @ [%s] not seen for (%.2f) hrs, Av %.2f +/- %.2f hrs\n", *hostname, IPString2Hostname(hostname+1), addr, tbuf, ((double)(now-then))/ticksperhr, average/ticksperhr, sqrt(var)/ticksperhr); } } if (HTML) { printf("
"); } if (XML) { printf("\n"); } dbcp->c_close(dbcp); dbp->close(dbp,0); } /*******************************************************************/ void ShowPerformance() { DBT key,value; DB *dbp; DBC *dbcp; DB_ENV *dbenv = NULL; double now = (double)time(NULL),average = 0, var = 0; double ticksperminute = 60.0; char name[CF_BUFSIZE],eventname[CF_BUFSIZE]; struct Event entry; int ret; snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_PERFORMANCE); if ((errno = db_create(&dbp,dbenv,0)) != 0) { printf("Couldn't open performance database %s\n",name); perror("db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { printf("Couldn't open performance database %s\n",name); perror("db_open"); dbp->close(dbp,0); return; } /* Acquire a cursor for the database. */ if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { printf("Error reading from performance database: "); dbp->err(dbp, ret, "DB->cursor"); return; } /* Initialize the key/data return pair. */ memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); memset(&entry, 0, sizeof(entry)); if (HTML) { printf("

Peformance recently measured on %s

",VFQNAME); printf("
"); } if (XML) { printf("\n\n"); } /* Walk through the database and print out the key/data pairs. */ while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { double measure; time_t then; char tbuf[CF_BUFSIZE],addr[CF_BUFSIZE]; memcpy(&then,value.data,sizeof(then)); strcpy(eventname,(char *)key.data); if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); then = entry.t; measure = entry.Q.q/ticksperminute;; average = entry.Q.expect/ticksperminute;; var = entry.Q.var; snprintf(tbuf,CF_BUFSIZE-1,"%s",ctime(&then)); tbuf[strlen(tbuf)-9] = '\0'; /* Chop off second and year */ if (PURGE == 'y') { if (now - then > CF_WEEK) { if ((errno = dbp->del(dbp,NULL,&key,0)) != 0) { CfLog(cferror,"","db_store"); } } fprintf(stderr,"Deleting expired entry for %s\n",eventname); if (measure < 0 || average < 0 || measure > 4*CF_WEEK) { if ((errno = dbp->del(dbp,NULL,&key,0)) != 0) { CfLog(cferror,"","db_store"); } } fprintf(stderr,"Deleting entry for %s because it seems to take longer than 4 weeks to complete\n",eventname); continue; } if (XML) { printf("%s",CFX[cfx_entry][cfb]); printf("%s%s%s",CFX[cfx_event][cfb],eventname,CFX[cfx_event][cfe]); printf("%s%s%s",CFX[cfx_date][cfb],tbuf,CFX[cfx_date][cfe]); printf("%s%.4lf%s",CFX[cfx_q][cfb],measure,CFX[cfx_q][cfe]); printf("%s%.4lf%s",CFX[cfx_av][cfb],average,CFX[cfx_av][cfe]); printf("%s%.4lf%s",CFX[cfx_dev][cfb],sqrt(var)/ticksperminute,CFX[cfx_dev][cfe]); printf("%s",CFX[cfx_entry][cfe]); } else if (HTML) { printf("%s",CFH[cfx_entry][cfb]); printf("%s%s%s",CFH[cfx_event][cfb],eventname,CFH[cfx_event][cfe]); printf("%s last performed at %s%s",CFH[cfx_date][cfb],tbuf,CFH[cfx_date][cfe]); printf("%s completed in %.4lf mins %s",CFH[cfx_q][cfb],measure,CFH[cfx_q][cfe]); printf("%s Av %.4lf mins %s",CFH[cfx_av][cfb],average,CFH[cfx_av][cfe]); printf("%s ± %.4lf mins %s",CFH[cfx_dev][cfb],sqrt(var)/ticksperminute,CFH[cfx_dev][cfe]); printf("%s",CFH[cfx_entry][cfe]); } else { printf("(%7.4lf mins @ %s) Av %7.4lf +/- %7.4lf for %s \n",measure,tbuf,average,sqrt(var)/ticksperminute,eventname); } } else { continue; } } if (HTML) { printf("
"); printf("\n\n"); } if (XML) { printf("\n"); } dbcp->c_close(dbcp); dbp->close(dbp,0); } /*******************************************************************/ void ShowClasses() { DBT key,value; DB *dbp; DBC *dbcp; DB_ENV *dbenv = NULL; double now = (double)time(NULL),average = 0, var = 0; double ticksperminute = 60.0; char name[CF_BUFSIZE],eventname[CF_BUFSIZE]; struct Event entry; struct CEnt array[1024]; int ret, i; snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_CLASSUSAGE); if ((errno = db_create(&dbp,dbenv,0)) != 0) { printf("Couldn't open class database %s\n",name); perror("db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { printf("Couldn't open class database %s\n",name); perror("db_open"); dbp->close(dbp,0); return; } /* Acquire a cursor for the database. */ if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { printf("Error reading from class database: "); dbp->err(dbp, ret, "DB->cursor"); return; } /* Initialize the key/data return pair. */ memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); memset(&entry, 0, sizeof(entry)); if (HTML) { time_t now = time(NULL); printf("

Class probabilities observed on %s at %s

",VFQNAME,ctime(&now)); } if (XML) { printf("\n\n"); } /* Walk through the database and print out the key/data pairs. */ for (i = 0; i < 1024; i++) { array[i].q = -1; } i = 0; while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { double measure; time_t then; char tbuf[CF_BUFSIZE],addr[CF_BUFSIZE]; memcpy(&then,value.data,sizeof(then)); strcpy(eventname,(char *)key.data); if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); then = entry.t; measure = entry.Q.q; average = entry.Q.expect; var = entry.Q.var; snprintf(tbuf,CF_BUFSIZE-1,"%s",ctime(&then)); tbuf[strlen(tbuf)-9] = '\0'; /* Chop off second and year */ if (PURGE == 'y') { if (now - then > CF_WEEK*52) { if ((errno = dbp->del(dbp,NULL,&key,0)) != 0) { CfLog(cferror,"","db_store"); } } fprintf(stderr,"Deleting expired entry for %s\n",eventname); continue; } if (i++ < 1024) { strncpy(array[i].date,tbuf,31); strncpy(array[i].name,eventname,255); array[i].q = average; array[i].d = var; } else { break; } } } #ifdef HAVE_QSORT qsort(array,1024,sizeof(struct CEnt),CompareClasses); #endif for (i = 0; array[i].q > 0; i++) { if (XML) { printf("%s",CFX[cfx_entry][cfb]); printf("%s%s%s",CFX[cfx_event][cfb],array[i].name,CFX[cfx_event][cfe]); printf("%s%s%s",CFX[cfx_date][cfb],array[i].date,CFX[cfx_date][cfe]); printf("%s%.4f%s",CFX[cfx_av][cfb],array[i].q,CFX[cfx_av][cfe]); printf("%s%.4f%s",CFX[cfx_dev][cfb],sqrt(array[i].d),CFX[cfx_dev][cfe]); printf("%s",CFX[cfx_entry][cfe]); } else if (HTML) { printf("%s",CFH[cfx_entry][cfb]); printf("%s%s%s",CFH[cfx_event][cfb],array[i].name,CFH[cfx_event][cfe]); printf("%s last occured at %s%s",CFH[cfx_date][cfb],array[i].date,CFH[cfx_date][cfe]); printf("%s Probability %.4f %s",CFH[cfx_av][cfb],array[i].q,CFH[cfx_av][cfe]); printf("%s ± %.4f %s",CFH[cfx_dev][cfb],sqrt(array[i].d),CFH[cfx_dev][cfe]); printf("%s",CFH[cfx_entry][cfe]); } else { printf("Probability %7.4f +/- %7.4f for %s (last oberved @ %s)\n",array[i].q,sqrt(array[i].d),array[i].name,array[i].date); } } if (HTML) { printf("
"); } if (XML) { printf("\n"); } dbcp->c_close(dbcp); dbp->close(dbp,0); } /*******************************************************************/ void ShowChecksums() { DBT key,value; DB *dbp; DBC *dbcp; DB_ENV *dbenv = NULL; int ret; FILE *pp; char checksumdb[CF_BUFSIZE]; struct stat statbuf; snprintf(checksumdb,CF_BUFSIZE,"%s/%s",CFWORKDIR,CF_CHKDB); if ((errno = db_create(&dbp,dbenv,0)) != 0) { printf("Couldn't open checksum database %s\n",checksumdb); perror("db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,checksumdb,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,checksumdb,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { printf("Couldn't open checksum database %s\n",checksumdb); perror("db_open"); dbp->close(dbp,0); return; } if (HTML) { printf("

Message Digests sampled on %s

",VFQNAME); } if (XML) { printf("\n\n"); } /* Acquire a cursor for the database. */ if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { printf("Error reading from checksum database"); dbp->err(dbp, ret, "DB->cursor"); return; } /* Initialize the key/data return pair. */ memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); /* Walk through the database and print out the key/data pairs. */ while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { char type; char strtype[CF_MAXVARSIZE]; char name[CF_BUFSIZE]; struct Checksum_Value chk_val; unsigned char digest[EVP_MAX_MD_SIZE+1]; memset(digest,0,EVP_MAX_MD_SIZE+1); memset(&chk_val,0,sizeof(chk_val)); memcpy(&chk_val,value.data,sizeof(chk_val)); memcpy(digest,chk_val.mess_digest,EVP_MAX_MD_SIZE+1); strncpy(strtype,key.data,CF_MAXDIGESTNAMELEN); strncpy(name,(char *)key.data+CF_CHKSUMKEYOFFSET,CF_BUFSIZE-1); type = ChecksumType(strtype); if (XML) { printf("%s",CFX[cfx_entry][cfb]); printf("%s%s%s",CFX[cfx_event][cfb],name,CFX[cfx_event][cfe]); printf("%s%s%s",CFX[cfx_q][cfb],ChecksumPrint(type,digest),CFX[cfx_q][cfe]); printf("%s",CFX[cfx_entry][cfe]); } else if (HTML) { printf("%s",CFH[cfx_entry][cfb]); printf("%s%s%s",CFH[cfx_filename][cfb],name,CFH[cfx_filename][cfe]); printf("%s%s%s",CFH[cfx_q][cfb],ChecksumPrint(type,digest),CFH[cfx_q][cfe]); printf("%s",CFH[cfx_entry][cfe]); } else { printf("%s = ",name); printf("%s\n",ChecksumPrint(type,digest)); /* attr_digest too here*/ memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); } } if (HTML) { printf("
"); } if (XML) { printf("\n"); } dbcp->c_close(dbcp); dbp->close(dbp,0); } /*********************************************************************/ void ShowLocks (int active) { DBT key,value; DB *dbp; DBC *dbcp; DB_ENV *dbenv = NULL; int ret; char lockdb[CF_BUFSIZE]; struct LockData entry; snprintf(lockdb,CF_BUFSIZE,"%s/cfengine_lock_db",CFWORKDIR); if ((errno = db_create(&dbp,dbenv,0)) != 0) { printf("Couldn't open checksum database %s\n",lockdb); perror("db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,lockdb,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,lockdb,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { printf("Couldn't open checksum database %s\n",lockdb); perror("db_open"); dbp->close(dbp,0); return; } if (HTML) { printf("

Current lock database on %s

",VFQNAME); } if (XML) { printf("\n\n"); } /* Acquire a cursor for the database. */ if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { printf("Error reading from checksum database"); dbp->err(dbp, ret, "DB->cursor"); return; } /* Initialize the key/data return pair. */ memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); /* Walk through the database and print out the key/data pairs. */ while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { if (active) { if (strncmp("lock",(char *)key.data,4) == 0) { if (XML) { printf("%s",CFX[cfx_entry][cfb]); printf("%s%s%s",CFX[cfx_filename][cfb],(char *)key.data,CFX[cfx_filename][cfe]); printf("%s%s%s",CFX[cfx_date][cfb],ctime(&entry.time),CFX[cfx_date][cfe]); printf("%s",CFX[cfx_entry][cfe]); } else if (HTML) { printf("%s",CFH[cfx_entry][cfb]); printf("%s%s%s",CFH[cfx_filename][cfb],(char *)key.data,CFH[cfx_filename][cfe]); printf("%s%s%s",CFH[cfx_date][cfb],ctime(&entry.time),CFH[cfx_date][cfe]); printf("%s",CFH[cfx_entry][cfe]); } else { printf("%s = ",(char *)key.data); if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); printf("%s\n",ctime(&entry.time)); } } } } else { if (strncmp("last",(char *)key.data,4) == 0) { if (XML) { printf("%s",CFX[cfx_entry][cfb]); printf("%s%s%s",CFX[cfx_filename][cfb],(char *)key.data,CFX[cfx_filename][cfe]); printf("%s%s%s",CFX[cfx_date][cfb],ctime(&entry.time),CFX[cfx_date][cfe]); printf("%s",CFX[cfx_entry][cfe]); } else if (HTML) { printf("%s",CFH[cfx_entry][cfb]); printf("%s%s%s",CFH[cfx_filename][cfb],(char *)key.data,CFH[cfx_filename][cfe]); printf("%s%s%s",CFH[cfx_date][cfb],ctime(&entry.time),CFH[cfx_date][cfe]); printf("%s",CFH[cfx_entry][cfe]); } else { printf("%s = ",(char *)key.data); if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); printf("%s\n",ctime(&entry.time)); } } } } } if (HTML) { printf("
"); } if (XML) { printf("\n"); } dbcp->c_close(dbcp); dbp->close(dbp,0); } /*******************************************************************/ void ShowCurrentAudit() { char operation[CF_BUFSIZE],name[CF_BUFSIZE]; struct AuditLog entry; DB_ENV *dbenv = NULL; DBT key,value; DB *dbp; DBC *dbcp; int ret; snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_AUDITDB_FILE); if ((errno = db_create(&dbp,dbenv,0)) != 0) { printf("Couldn't open last-seen database %s\n",name); perror("db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { printf("Couldn't open audit database %s\n",name); perror("db_open"); dbp->close(dbp,0); return; } /* Acquire a cursor for the database. */ if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { printf("Error reading from last-seen database: "); dbp->err(dbp, ret, "DB->cursor"); return; } /* Initialize the key/data return pair. */ memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); memset(&entry, 0, sizeof(entry)); if (HTML) { printf("

Audit log %s

",VFQNAME); /* printf("");*/ printf(""); printf(""); printf(""); printf(""); printf(""); printf(""); } if (XML) { printf("\n\n"); } /* Walk through the database and print out the key/data pairs. */ while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { strncpy(operation,(char *)key.data,CF_BUFSIZE-1); if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); if (XML) { printf("%s",CFX[cfx_entry][cfb]); printf("%s %s %s",CFX[cfx_index][cfb],operation,CFX[cfx_index][cfe]); printf("%s %s, ",CFX[cfx_event][cfb],entry.operator); AuditStatusMessage(entry.status); printf("%s",CFX[cfx_event][cfe]); printf("%s %s %s",CFX[cfx_q][cfb],entry.comment,CFX[cfx_q][cfe]); printf("%s %s %s",CFX[cfx_date][cfb],entry.date,CFX[cfx_date][cfe]); printf("%s %s %s",CFX[cfx_av][cfb],entry.filename,CFX[cfx_av][cfe]); printf("%s %s %s",CFX[cfx_version][cfb],entry.version,CFX[cfx_version][cfe]); printf("%s %d %s",CFX[cfx_ref][cfb],entry.lineno,CFX[cfx_ref][cfe]); printf("%s",CFX[cfx_entry][cfe]); } else if (HTML) { printf("%s",CFH[cfx_entry][cfb]); /* printf("%s %s %s",CFH[cfx_index][cfb],operation,CFH[cfx_index][cfe]);*/ printf("%s %s, ",CFH[cfx_event][cfb],Format(entry.operator,40)); AuditStatusMessage(entry.status); printf("%s",CFH[cfx_event][cfe]); printf("%s %s %s",CFH[cfx_q][cfb],Format(entry.comment,40),CFH[cfx_q][cfe]); printf("%s %s %s",CFH[cfx_date][cfb],entry.date,CFH[cfx_date][cfe]); printf("%s %s %s",CFH[cfx_av][cfb],entry.filename,CFH[cfx_av][cfe]); printf("%s %s %s",CFH[cfx_version][cfb],entry.version,CFH[cfx_version][cfe]); printf("%s %d %s",CFH[cfx_ref][cfb],entry.lineno,CFH[cfx_ref][cfe]); printf("%s",CFH[cfx_entry][cfe]); if (strstr(entry.comment,"closing")) { printf(""); printf(""); printf(""); printf(""); printf(""); printf(""); printf(""); } } else { printf(". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .\n"); printf("Converge \'%s\' ",entry.operator); AuditStatusMessage(entry.status); /* Reminder */ if (strlen(entry.comment) > 0) { printf("Comment: %s\n",entry.comment); } if (strcmp(entry.filename,"Terminal") == 0) { if (strstr(entry.comment,"closing")) { printf("\n===============================================================================================\n\n"); } } else { if (strlen(entry.version) == 0) { printf("Promised in %s (unamed version last edited at %s) at/before line %d\n",entry.filename,entry.date,entry.lineno); } else { printf("Promised in %s (version %s last edited at %s) at/before line %d\n",entry.filename,entry.version,entry.date,entry.lineno); } } } } else { continue; } } if (HTML) { printf("
t-index Scan convergence Observed Promise made Promise originates in Promise version line
"); } if (XML) { printf("\n"); } dbcp->c_close(dbcp); dbp->close(dbp,0); } /*********************************************************************/ /* Level 3 */ /*********************************************************************/ char *ChecksumDump(unsigned char digest[EVP_MAX_MD_SIZE+1]) { unsigned int i; static char buffer[EVP_MAX_MD_SIZE*4]; int len = 1; for (i = 0; buffer[i] != 0; i++) { len++; } if (len == 16 || len == 20) { } else { len = 16; } switch(len) { case 20: sprintf(buffer,"SHA= "); break; case 16: sprintf(buffer,"MD5= "); break; } for (i = 0; i < len; i++) { sprintf((char *)(buffer+4+2*i),"%02x", digest[i]); } return buffer; } /*********************************************************************/ void ShowRegex(char *regex) { SetSignals(); SetReferenceTime(false); SetStartTime(true); OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); VREPOSITORY = strdup("\0"); VCANONICALFILE = strdup(VINPUTFILE); VDEFAULTBINSERVER.name = ""; AddClassToHeap("any"); PARSEONLY = INSTALLALL = true; strcpy(CFWORKDIR,WORKDIR); SetContext("cfshow"); ISCFENGINE = true; ParseInputFile(VINPUTFILE,true); ISCFENGINE = false; ListDefinedInterfaces(regex); printf("------------------------------------------------------------\n"); ListDefinedBinservers(regex); printf("------------------------------------------------------------\n"); ListDefinedHomeservers(regex); printf("------------------------------------------------------------\n"); ListDefinedHomePatterns(regex); printf("------------------------------------------------------------\n"); ListDefinedStrategies(regex); printf("------------------------------------------------------------\n"); ListACLs(); printf("------------------------------------------------------------\n"); ListFilters(regex); printf("------------------------------------------------------------\n"); ListDefinedIgnore(regex); printf("------------------------------------------------------------\n"); ListDefinedAlerts(regex); printf("------------------------------------------------------------\n"); ListDefinedDisable(regex); printf("------------------------------------------------------------\n"); ListFiles(regex); ListDefinedMakePaths(regex); printf("------------------------------------------------------------\n"); ListFileEdits(regex); printf("------------------------------------------------------------\n"); ListDefinedImages(regex); printf("------------------------------------------------------------\n"); ListDefinedLinks(regex); printf("------------------------------------------------------------\n"); ListDefinedLinkchs(regex); printf("------------------------------------------------------------\n"); ListDefinedMethods(regex); printf("------------------------------------------------------------\n"); ListDefinedMountables(regex); printf("------------------------------------------------------------\n"); ListMiscMounts(regex); printf("------------------------------------------------------------\n"); ListUnmounts(regex); printf("------------------------------------------------------------\n"); ListDefinedPackages(regex); printf("------------------------------------------------------------\n"); ListProcesses(regex); printf("------------------------------------------------------------\n"); ListDefinedRequired(regex); printf("------------------------------------------------------------\n"); ListDefinedResolvers(regex); printf("------------------------------------------------------------\n"); ListDefinedSCLI(regex); printf("------------------------------------------------------------\n"); ListDefinedScripts(regex); printf("------------------------------------------------------------\n"); ListDefinedTidy(regex); printf("------------------------------------------------------------\n"); } /*********************************************************************/ char *Format(char *s,int width) { static char buffer[CF_BUFSIZE]; char *sp; int i = 0, count = 0; for (sp = s; *sp != '\0'; sp++) { buffer[i++] = *sp; buffer[i] = '\0'; count++; if ((count > width - 5) && ispunct(*sp)) { strcat(buffer,"
"); i += strlen("
"); count = 0; } } return buffer; } /*************************************************************/ int CompareClasses(const void *a, const void *b) { struct CEnt *da = (struct CEnt *) a; struct CEnt *db = (struct CEnt *) b; return (da->q < db->q) - (da->q > db->q); } cfengine-2.2.10/src/checksums.c0000644000175000001440000001624610557213500013216 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Checksums */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*******************************************************************/ int CompareCheckSums(char *file1,char *file2,struct Image *ip,struct stat *sstat,struct stat *dstat) { static unsigned char digest1[EVP_MAX_MD_SIZE+1], digest2[EVP_MAX_MD_SIZE+1]; int i; Debug("CompareCheckSums(%s,%s)\n",file1,file2); if (sstat->st_size != dstat->st_size) { Debug("File sizes differ, no need to compute checksum\n"); return true; } Debug2("Compare checksums on %s:%s & %s\n",ip->server,file1,file2); if (strcmp(ip->server,"localhost") == 0) { ChecksumFile(file1,digest1,'m'); ChecksumFile(file2,digest2,'m'); for (i = 0; i < EVP_MAX_MD_SIZE; i++) { if (digest1[i] != digest2[i]) { Verbose("Checksum mismatch...\n"); return true; } } Debug("Files were identical\n"); return false; /* only if files are identical */ } else { return CompareMD5Net(file1,file2,ip); /* client.c */ } } /*******************************************************************/ int CompareBinarySums(char *file1,char *file2,struct Image *ip,struct stat *sstat,struct stat *dstat) /* See the md5 algorithms in pub-lib/md5.c */ /* file 1 is source */ { int fd1, fd2,bytes1,bytes2; char buff1[BUFSIZ],buff2[BUFSIZ]; Debug("CompareBinarySums(%s,%s)\n",file1,file2); if (sstat->st_size != dstat->st_size) { Debug("File sizes differ, no need to compute checksum\n"); return true; } Debug2("Compare binary sums on %s:%s & %s\n",ip->server,file1,file2); if (strcmp(ip->server,"localhost") == 0) { fd1 = open(file1, O_RDONLY|O_BINARY, 0400); fd2 = open(file2, O_RDONLY|O_BINARY, 0400); do { bytes1 = read(fd1, buff1, BUFSIZ); bytes2 = read(fd2, buff2, BUFSIZ); if ((bytes1 != bytes2) || (memcmp(buff1, buff2, bytes1) != 0)) { Verbose("Binary Comparison mismatch...\n"); close(fd2); close(fd1); return true; } } while (bytes1 > 0); close(fd2); close(fd1); return false; /* only if files are identical */ } else { Debug("Using network md5 checksum instead\n"); return CompareMD5Net(file1,file2,ip); /* client.c */ } } /*******************************************************************/ void ChecksumFile(char *filename,unsigned char digest[EVP_MAX_MD_SIZE+1],char type) { FILE *file; EVP_MD_CTX context; int len, md_len; unsigned char buffer[1024]; const EVP_MD *md = NULL; Debug2("ChecksumFile(%c,%s)\n",type,filename); if ((file = fopen (filename, "rb")) == NULL) { printf ("%s can't be opened\n", filename); } else { md = EVP_get_digestbyname(ChecksumName(type)); EVP_DigestInit(&context,md); while (len = fread(buffer,1,1024,file)) { EVP_DigestUpdate(&context,buffer,len); } EVP_DigestFinal(&context,digest,&md_len); /* Digest length stored in md_len */ fclose (file); } } /*******************************************************************/ void ChecksumList(struct Item *list,unsigned char digest[EVP_MAX_MD_SIZE+1],char type) { struct Item *ip; EVP_MD_CTX context; int md_len; const EVP_MD *md = NULL; Debug2("ChecksumList(%c)\n",type); memset(digest,0,EVP_MAX_MD_SIZE+1); md = EVP_get_digestbyname(ChecksumName(type)); EVP_DigestInit(&context,md); for (ip = list; ip != NULL; ip=ip->next) { Debug(" digesting %s\n",ip->name); EVP_DigestUpdate(&context,ip->name,strlen(ip->name)); } EVP_DigestFinal(&context,digest,&md_len); } /*******************************************************************/ void ChecksumString(char *buffer,int len,unsigned char digest[EVP_MAX_MD_SIZE+1],char type) { EVP_MD_CTX context; const EVP_MD *md = NULL; int md_len; Debug2("ChecksumString(%c)\n",type); md = EVP_get_digestbyname(ChecksumName(type)); EVP_DigestInit(&context,md); EVP_DigestUpdate(&context,(unsigned char*)buffer,len); EVP_DigestFinal(&context,digest,&md_len); } /*******************************************************************/ int ChecksumsMatch(unsigned char digest1[EVP_MAX_MD_SIZE+1],unsigned char digest2[EVP_MAX_MD_SIZE+1],char type) { int i,size = EVP_MAX_MD_SIZE; size = ChecksumSize(type); for (i = 0; i < size; i++) { if (digest1[i] != digest2[i]) { return false; } } return true; } /*********************************************************************/ char *ChecksumPrint(char type,unsigned char digest[EVP_MAX_MD_SIZE+1]) { unsigned int i; static char buffer[EVP_MAX_MD_SIZE*4]; int len = 16; switch(type) { case 's': sprintf(buffer,"SHA= "); len = 20; break; case 'm': sprintf(buffer,"MD5= "); len = 16; break; } for (i = 0; i < len; i++) { sprintf((char *)(buffer+4+2*i),"%02x", digest[i]); } return buffer; } /*********************************************************************/ char ChecksumType(char *typestr) { int i; for (i = 0; CF_DIGEST_TYPES[i][0] != NULL; i++) { if (strcmp(typestr,CF_DIGEST_TYPES[i][0]) == 0) { return *CF_DIGEST_TYPES[i][1]; } } if (PARSING) { snprintf(OUTPUT,CF_BUFSIZE,"Illegal checksum/digest type: %s",typestr); yyerror(OUTPUT); FatalError("Should be md5,sha,sha1,sha224,sha256,sha348,sha512"); } return 'x'; } /*********************************************************************/ char *ChecksumName(char type) { int i; for (i = 0; CF_DIGEST_TYPES[i][0] != NULL; i++) { if (type == *CF_DIGEST_TYPES[i][1]) { return CF_DIGEST_TYPES[i][0]; } } return NULL; } /*********************************************************************/ int ChecksumSize(char type) { int i,size = 0; for (i = 0; CF_DIGEST_TYPES[i][0] != NULL; i++) { if (type == *CF_DIGEST_TYPES[i][1]) { return CF_DIGEST_SIZES[i]; } } return size; } cfengine-2.2.10/src/cfkey.c0000644000175000001440000001512711131723630012326 00000000000000/* Copyright (C) 1999 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: cfkey.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" char CFLOCK[CF_BUFSIZE]; char USERKEYFILE[CF_BUFSIZE]; void Initialize(void); int RecursiveTidySpecialArea(char *name, struct Tidy *tp, int maxrecurse, struct stat *sb); void Syntax(void); void CheckOpts(int argc, char **argv); /*******************************************************************/ /* Command line options */ /*******************************************************************/ /* GNU STUFF FOR LATER #include "getopt.h" */ struct option OPTIONS[5] = { { "help",no_argument,0,'h' }, { "file",required_argument,0,'f' }, { "version",no_argument,0,'V' }, { "quiet",no_argument,0,'w' }, { NULL,0,0,0 } }; int main(int argc, char** argv) { unsigned long err; RSA *pair; FILE *fp; struct stat statbuf; int fd; static char *passphrase = "Cfengine passphrase"; EVP_CIPHER *cipher = EVP_des_ede3_cbc(); CheckOpts(argc, argv); Initialize(); if (stat(CFPRIVKEYFILE,&statbuf) != -1) { printf("A key file already exists at %s.\n",CFPRIVKEYFILE); return 1; } if (stat(CFPUBKEYFILE,&statbuf) != -1) { printf("A key file already exists at %s.\n",CFPUBKEYFILE); return 1; } if(VERBOSE) { printf("Making a key pair for cfengine, please wait, this could take a minute...\n"); } pair = RSA_generate_key(2048,35,NULL,NULL); if (pair == NULL) { err = ERR_get_error(); printf("Error = %s\n",ERR_reason_error_string(err)); return 1; } if (VERBOSE) { RSA_print_fp(stdout,pair,0); } fd = open(CFPRIVKEYFILE,O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { printf("Ppen %s failed: %s.",CFPRIVKEYFILE,strerror(errno)); return 1; } if ((fp = fdopen(fd, "w")) == NULL ) { printf("fdopen %s failed: %s.",CFPRIVKEYFILE, strerror(errno)); close(fd); return 1; } if (VERBOSE) { printf("Writing private key to %s\n",CFPRIVKEYFILE); } if (!PEM_write_RSAPrivateKey(fp,pair,cipher,passphrase,strlen(passphrase),NULL,NULL)) { err = ERR_get_error(); printf("Error = %s\n",ERR_reason_error_string(err)); return 1; } fclose(fp); fd = open(CFPUBKEYFILE,O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { printf("open %s failed: %s.",CFPUBKEYFILE,strerror(errno)); return 1; } if ((fp = fdopen(fd, "w")) == NULL ) { printf("fdopen %s failed: %s.",CFPUBKEYFILE, strerror(errno)); close(fd); return 1; } if (VERBOSE) { printf("Writing public key to %s\n",CFPUBKEYFILE); } if(!PEM_write_RSAPublicKey(fp,pair)) { err = ERR_get_error(); printf("Error = %s\n",ERR_reason_error_string(err)); return 1; } fclose(fp); snprintf(VBUFF,CF_BUFSIZE,"%s/randseed",VLOGDIR); RAND_write_file(VBUFF); chmod(VBUFF,0644); return 0; } /*******************************************************************/ /* Level 1 */ /*******************************************************************/ void Initialize() { umask(077); /* XXX Initialize workdir for non privileged users */ strcpy(CFWORKDIR,WORKDIR); #ifndef NT if (geteuid() != 0) { char *homedir; if ((homedir = getenv("HOME")) != NULL) { strcpy(CFWORKDIR,homedir); strcat(CFWORKDIR,"/.cfagent"); } } #endif strcpy(VLOCKDIR,CFWORKDIR); strcpy(VLOGDIR,CFWORKDIR); OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); CheckWorkDirectories(); if (USERKEYFILE[0] != '\0') { strncpy(CFPRIVKEYFILE, USERKEYFILE, CF_BUFSIZE-6); strcat(CFPRIVKEYFILE, ".priv"); strncpy(CFPUBKEYFILE, USERKEYFILE, CF_BUFSIZE-5); strcat(CFPUBKEYFILE, ".pub"); } RandomSeed(); } /*******************************************************************/ void Syntax() { int i; printf("GNU cfengine: A system configuration engine (cfkey)\n%s\n%s\n",VERSION,COPYRIGHT); printf("\n"); printf("Options:\n\n"); for (i=0; OPTIONS[i].name != NULL; i++) { printf("--%-20s (-%c)\n",OPTIONS[i].name,(char)OPTIONS[i].val); } printf("\nBug reports to bug-cfengine@cfengine.org\n"); printf("General help to help-cfengine@cfengine.org\n"); printf("Info & fixes at http://www.cfengine.org\n"); } /*****************************************************************************/ void CheckOpts(int argc,char **argv) { extern char *optarg; struct Item *actionList; char *tmp, *suffix; int optindex = 0; int c; while ((c=getopt_long(argc,argv,"f:hvVw",OPTIONS,&optindex)) != EOF) { switch ((char) c) { case 'f': strncpy(USERKEYFILE, optarg, CF_BUFSIZE-1); /* search for .priv or .pub suffix and wipe it out */ suffix = strrchr(USERKEYFILE, '.'); if (NULL != suffix && ((0 == strcmp(suffix, ".priv")) || (0 == strcmp(suffix, ".pub")))) *suffix = '\0'; break; case 'V': printf("GNU cfengine %s\n%s\n",VERSION,COPYRIGHT); printf("This program is covered by the GNU Public License and may be\n"); printf("copied free of charge. No warranty is implied.\n\n"); exit(0); case 'h': Syntax(); exit(0); case 'w': VERBOSE = false; break; default: Syntax(); exit(1); } } } cfengine-2.2.10/src/classes.c0000644000175000001440000005100110773463137012667 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* GLOBAL class default variables for cfengine */ /* These variables are what needs to be modified if you add or */ /* modify class definitions... remember also to change clsattr */ /* and search for the os types in cfengine.c (mount stuff) */ /* */ /*******************************************************************/ #include "cf.defs.h" /*********************************************************************/ /* See also "enum classes" in cf.defs.h */ char *CLASSTEXT[] = /* If you change here change enum classes too! */ { "", "", "sun4", "ultrix", "hpux", "aix", "linux", "solaris", "osf", "digital", "sun3", "irix4", "irix", "irix64", "freebsd", "solarisx86", "bsd4_3", "newsos", "netbsd", "aos", "bsdos", "nextstep", "cray", "gnu", "nt", "unix_sv", "openbsd", "sco", "darwin", "ux4800", "qnx", "dragonfly", "unused1", "unused2", "unused3", NULL }; /*********************************************************************/ /* remember to change cf.defs.h !! */ char *CLASSATTRIBUTES[CF_CLASSATTR][CF_ATTRDIM] = { /* Only as many characters */ {"-","-","-"}, /* as appear here are matched. The */ {"-","-","-"}, /* fields are sysname and machine */ {"sunos","*","4*"}, /* sun 4 */ {"ultrix","risc","4*"}, /* ultrix */ {"hp-ux","*","*"}, /* hpux */ {"aix","*","*"}, /* aix */ {"linux","*","*"}, /* linux */ {"sunos","sun4*","5*"}, /* solaris */ {"osf1","alpha","*"}, /* osf1 */ {"osf1","alpha","4*"}, /* digital */ {"sunos","sun3","4*"}, /* sun3 */ {"irix4","ip*","4*"}, /* irix4 */ {"irix", "ip*","*"}, /* irix */ {"irix64","ip*","*"}, /* irix64 */ {"freebsd","*","*"}, /* freebsd */ {"sunos","i86pc","5*"}, /* solarisx86 */ {"bsd","*","*"}, /* bsd 4.3 */ {"newsos","*","*"}, /* newsos4 */ {"netbsd","*","*"}, /* NetBSD */ {"aos","*","*"}, /* AOS */ {"bsd/os","*","*"}, /* BSDI */ {"nextstep","*","*"}, /* nextstep */ {"sn*","cray*","*"}, /* cray */ {"gnu*","*","*"}, /* gnu */ {"cygwin_nt*","*","*"}, /* NT */ {"unix_sv","*","*"}, /* Unixware */ {"openbsd","*","*"}, /* OpenBSD */ {"sco_sv","*","*"}, /* SCO */ {"darwin","*","*"}, /* Darwin, aka MacOS X */ {"ux4800","*","*"}, /* UX/4800 */ {"qnx","*","*"}, /* qnx */ {"dragonfly","*","*"}, /* dragonfly */ {"unused1","blah","blah"}, {"unused2","blah","blah"}, {"unused3","blah","blah"}, {NULL,NULL,NULL} }; /*********************************************************************/ char *VPSCOMM[CF_CLASSATTR] = { "", "", "/bin/ps", /* sun 4 */ "/bin/ps", /* ultrix */ "/bin/ps", /* hpux */ "/bin/ps", /* aix */ "/bin/ps", /* linux */ "/bin/ps", /* solaris */ "/bin/ps", /* osf1 */ "/bin/ps", /* digital */ "/bin/ps", /* sun3 */ "/bin/ps", /* irix4 */ "/bin/ps", /* irix */ "/bin/ps", /* irix64 */ "/bin/ps", /* freebsd */ "/bin/ps", /* solarisx86 */ "/bin/ps", /* bsd 4.3 */ "/bin/ps", /* newos4 */ "/bin/ps", /* netbsd */ "/bin/ps", /* AOS */ "/bin/ps", /* BSDI */ "/bin/ps", /* nextstep */ "/bin/ps", /* cray */ "/bin/ps", /* gnu */ "/bin/ps", /* NT - cygnus */ "/bin/ps", /* unixware */ "/bin/ps", /* openbsd */ "/bin/ps", /* sco */ "/bin/ps", /* darwin */ "/bin/ps", /* ux4800 */ "/bin/ps", /* qnx */ "/bin/ps", /* dragonfly */ "/bin/ps", "/bin/ps", "/bin/ps", NULL }; /*********************************************************************/ char *VPSOPTS[CF_CLASSATTR] = { "", "", "auxw", /* sun4 */ "auxw", /* ultrix */ "-ef", /* hpux */ "-ef", /* aix */ "auxw", /* linux */ "-ef", /* solaris */ "-ef", /* osf1 */ "auxw", /* digital */ "auxw", /* sun3 */ "-ef", /* irix4 */ "-ef", /* irix */ "-ef", /* irix64 */ "auxw", /* freebsd */ "-ef", /* solarisx86 */ "-ax", /* bsd 4.3 */ "auxw", /* newsos4 */ "auxw", /* netbsd */ "auxw", /* AOS */ "auxw", /* BSDI */ "auxw", /* nextstep */ "-ef", /* cray */ "auxw", /* gnu */ "-a", /* NT */ "-ef", /* Unixware */ "auxw", /* openbsd */ "-ef", /* sco */ "auxw", /* darwin */ "-ef", /* ux4800 */ "-ef", /* qnx */ "auxw", /* dragonfly */ "-", "-", "-", NULL }; /*********************************************************************/ char *VMOUNTCOMM[CF_CLASSATTR] = { "", /* see cf.defs.h */ "", "/etc/mount -va", /* sun4 */ "/etc/mount -va", /* ultrix */ "/sbin/mount -ea", /* hpux */ /*"/etc/mount -t nfs",*/ /* aix */ "/usr/sbin/mount -t nfs", /* aix */ "/bin/mount -va", /* linux */ "/usr/sbin/mount -a", /* solaris */ "/usr/sbin/mount -va", /* osf1 */ "/usr/sbin/mount -va", /* digital */ "/etc/mount -va", /* sun3 */ "/sbin/mount -va", /* irix4 */ "/sbin/mount -va", /* irix */ "/sbin/mount -va", /* irix64 */ "/sbin/mount -va", /* freebsd */ "/usr/sbin/mount -a", /* solarisx86 */ "/etc/mount -a", /* bsd 4.3 */ "/etc/mount -a", /* newsos4 */ "/sbin/mount -a", /* netbsd */ "/etc/mount -a", /* AOS */ "/sbin/mount -a", /* BSDI */ "/usr/etc/mount -a", /* nextstep */ "/etc/mount -va", /* cray */ "/bin/mount -va", /* gnu */ "/bin/sh /etc/fstab", /* NT - possible security issue */ "/sbin/mountall", /* Unixware */ "/sbin/mount", /* openbsd */ "/etc/mountall", /* sco */ "/sbin/mount -va", /* darwin */ "/sbin/mount -v", /* ux4800 */ "/bin/mount -v", /* qnx */ "/sbin/mount -va", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; /*********************************************************************/ char *VUNMOUNTCOMM[CF_CLASSATTR] = { "", /* see cf.defs.h */ "", "/etc/umount", /* sun4 */ "/etc/umount", /* ultrix */ "/sbin/umount", /* hpux */ "/etc/umount", /* aix */ "/bin/umount", /* linux */ "/etc/umount", /* solaris */ "/usr/sbin/umount", /* osf1 */ "/usr/sbin/umount", /* digital */ "/etc/umount", /* sun3 */ "/sbin/umount", /* irix4 */ "/sbin/umount", /* irix */ "/sbin/umount", /* irix64 */ "/sbin/umount", /* freebsd */ "/etc/umount", /* solarisx86 */ "/etc/umount", /* bsd4.3 */ "/etc/umount", /* newsos4 */ "/sbin/umount", /* netbsd */ "/etc/umount", /* AOS */ "/sbin/umount", /* BSDI */ "/usr/etc/umount", /* nextstep */ "/etc/umount", /* cray */ "/sbin/umount", /* gnu */ "/bin/umount", /* NT */ "/sbin/umount", /* Unixware */ "/sbin/umount", /* openbsd */ "/etc/umount", /* sco */ "/sbin/umount", /* darwin */ "/sbin/umount", /* ux4800 */ "/bin/umount", /* qnx */ "/sbin/umount", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; /*********************************************************************/ char *VMOUNTOPTS[CF_CLASSATTR] = { "", /* see cf.defs.h */ "", "bg,hard,intr", /* sun4 */ "bg,hard,intr", /* ultrix */ "bg,hard,intr", /* hpux */ "bg,hard,intr", /* aix */ "defaults", /* linux */ "bg,hard,intr", /* solaris */ "bg,hard,intr", /* osf1 */ "bg,hard,intr", /* digital */ "bg,hard,intr", /* sun3 */ "bg,hard,intr", /* irix4 */ "bg,hard,intr", /* irix */ "bg,hard,intr", /* irix64 */ "bg,intr", /* freebsd */ "bg,hard,intr", /* solarisx86 */ "bg,hard,intr", /* bsd4.3 */ "bg,hard,intr", /* newsos4 */ "-i,-b", /* netbsd */ "bg,hard,intr", /* AOS */ "bg,intr", /* BSDI */ "bg,hard,intr", /* nextstep */ "bg,hard,intr", /* cray */ "defaults", /* gnu */ "", /* NT */ "bg,hard,intr", /* Unixware */ "-i,-b", /* openbsd */ "bg,hard,intr", /* sco */ "-i,-b", /* darwin */ "bg,hard,intr", /* ux4800 */ "bg,hard,intr", /* qnx */ "bg,intr", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; /*********************************************************************/ char *VIFDEV[CF_CLASSATTR] = { "-", "-", /* see cf.defs.h */ "le0", /* sun4 */ "ln0", /* ultrix */ "lan0", /* hpux */ "en0", /* aix */ "eth0", /* linux */ "le0", /* solaris */ "ln0", /* osf1 */ "ln0", /* digital */ "le0", /* sun3 */ "ec0", /* irix4 */ "ec0", /* irix */ "ec0", /* irix64 */ "ep0", /* freebsd */ "dnet0", /* solarisx86 */ "le0", /* bsd4.3 */ "en0", /* newsos4 */ "le0", /* netbsd */ "un0", /* AOS */ "le0", /* BSDI */ "en0", /* nextstep -default */ "en0", /* cray */ "eth0", /* gnu */ "N/A", /* NT */ "unknown", /* Unixware */ "le0", /* openbsd */ "net0", /* sco */ "en0", /* darwin */ "ec0", /* ux4800 */ "en0", /* qnx */ "ep0", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; /*********************************************************************/ char *VRESOLVCONF[CF_CLASSATTR] = { "-", "-", /* see cf.defs.h */ "/etc/resolv.conf", /* sun4 */ "/etc/resolv.conf", /* ultrix */ "/etc/resolv.conf", /* hpux */ "/etc/resolv.conf", /* aix */ "/etc/resolv.conf", /* linux */ "/etc/resolv.conf", /* solaris */ "/etc/resolv.conf", /* osf1 */ "/etc/resolv.conf", /* digital */ "/etc/resolv.conf", /* sun3 */ "/usr/etc/resolv.conf", /* irix4 */ "/etc/resolv.conf", /* irix */ "/etc/resolv.conf", /* irix64 */ "/etc/resolv.conf", /* freebsd */ "/etc/resolv.conf", /* solarisx86 */ "/etc/resolv.conf", /* bsd4.3 */ "/etc/resolv.conf", /* newsos4 */ "/etc/resolv.conf", /* netbsd */ "/etc/resolv.conf", /* AOS */ "/etc/resolv.conf", /* BSDI */ "/etc/resolv.conf", /* nextstep */ "/etc/resolv.conf", /* cray */ "/etc/resolv.conf", /* gnu */ "/etc/resolv.conf", /* NT */ "/etc/resolv.conf", /* Unixware */ "/etc/resolv.conf", /* openbsd */ "/etc/resolv.conf", /* sco */ "/etc/resolv.conf", /* darwin */ "/etc/resolv.conf", /* ux4800 */ "/etc/resolv.conf", /* qnx */ "/etc/resolv.conf", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; /*********************************************************************/ char *VFSTAB[CF_CLASSATTR] = { "-", "-", /* see cf.defs.h */ "/etc/fstab", /* sun4 */ "/etc/fstab", /* ultrix */ "/etc/fstab", /* hpux */ "/etc/filesystems", /* aix */ "/etc/fstab", /* linux */ "/etc/vfstab", /* solaris */ "/etc/fstab", /* osf1 */ "/etc/fstab", /* digital */ "/etc/fstab", /* sun3 */ "/etc/fstab", /* irix4 */ "/etc/fstab", /* irix */ "/etc/fstab", /* irix64 */ "/etc/fstab", /* freebsd */ "/etc/vfstab", /* solarisx86 */ "/etc/fstab", /* bsd4.3 */ "/etc/fstab", /* newsos4 */ "/etc/fstab", /* netbsd */ "/etc/fstab", /* AOS */ "/etc/fstab", /* BSDI */ "/etc/fstab", /* nextstep */ "/etc/fstab", /* cray */ "/etc/fstab", /* gnu */ "/etc/fstab", /* NT */ "/etc/vfstab", /* Unixware */ "/etc/fstab", /* openbsd */ "/etc/default/filesys", /* sco */ "/etc/fstab", /* darwin */ "/etc/vfstab", /* ux4800 */ "/etc/fstab", /* qnx */ "/etc/fstab", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; /*********************************************************************/ char *VMAILDIR[CF_CLASSATTR] = { "-", "-", /* see cf.defs.h */ "/var/spool/mail", /* sun4 */ "/usr/spool/mail", /* ultrix */ "/var/mail", /* hpux */ "/var/spool/mail", /* aix */ "/var/spool/mail", /* linux */ "/var/mail", /* solaris */ "/usr/spool/mail", /* osf1 */ "/usr/spool/mail", /* digital */ "/var/spool/mail", /* sun3 */ "/usr/mail", /* irix4 */ "/usr/mail", /* irix */ "/usr/var/mail", /* irix64 */ "/var/mail", /* freebsd */ "/var/mail", /* solarisx86 */ "/usr/spool/mail", /* bsd4.3 */ "/usr/spool/mail", /* newsos4 */ "/var/mail", /* netbsd */ "/usr/spool/mail", /* AOS */ "/var/mail", /* BSDI */ "/usr/spool/mail", /* nextstep */ "/usr/mail", /* cray */ "/var/spool/mail", /* gnu */ "N/A", /* NT */ "/var/mail", /* Unixware */ "/var/mail", /* openbsd */ "/var/spool/mail", /* sco */ "/var/mail", /* darwin */ "/var/mail", /* ux4800 */ "/var/spool/mail", /* qnx */ "/var/mail", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; /*********************************************************************/ char *VNETSTAT[CF_CLASSATTR] = { "-", "-", "/usr/ucb/netstat -rn", /* sun4 */ "/usr/ucb/netstat -rn", /* ultrix */ "/usr/bin/netstat -rn", /* hpux */ "/usr/bin/netstat -rn", /* aix */ "/bin/netstat -rn", /* linux */ "/usr/bin/netstat -rn", /* solaris */ "/usr/sbin/netstat -rn", /* osf1 */ "/usr/sbin/netstat -rn", /* digital */ "/usr/ucb/netstat -rn", /* sun3 */ "/usr/etc/netstat -rn", /* irix4 */ "/usr/etc/netstat -rn", /* irix */ "/usr/etc/netstat -rn", /* irix64 */ "/usr/bin/netstat -rn", /* freebsd */ "/bin/netstat -rn", /* solarisx86 */ "/usr/ucb/netstat -rn", /* bsd4.3 */ "/usr/ucb/netstat -rn", /* newsos4 */ "/usr/bin/netstat -rn", /* netbsd */ "/usr/ucb/netstat -rn", /* AOS */ "/usr/sbin/netstat -rn", /* BSDI */ "/usr/ucb/netstat -rn", /* nextstep */ "/usr/ucb/netstat -rn", /* cray */ "/bin/netstat -rn", /* gnu */ "/cygdrive/c/WINNT/System32/netstat", /* NT */ "/usr/bin/netstat -rn", /* Unixware */ "/usr/bin/netstat -rn", /* openbsd */ "/usr/bin/netstat -rn", /* sco */ "/usr/sbin/netstat -rn", /* darwin */ "/usr/bin/netstat -rn", /* ux4800 */ "/usr/bin/netstat -rn", /* qnx */ "/usr/bin/netstat -rn", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; /*********************************************************************/ char *VROUTE[CF_CLASSATTR] = { "-", "-", "-", /* sun4 */ "-", /* ultrix */ "-", /* hpux */ "-", /* aix */ "/sbin/route", /* linux */ "/usr/sbin/route", /* solaris */ "-", /* osf1 */ "-", /* digital */ "-", /* sun3 */ "-", /* irix4 */ "-", /* irix */ "-", /* irix64 */ "/sbin/route", /* freebsd */ "/usr/sbin/route", /* solarisx86 */ "-", /* bsd4.3 */ "-", /* newsos4 */ "-", /* netbsd */ "-", /* AOS */ "-", /* BSDI */ "-", /* nextstep */ "-", /* cray */ "-", /* gnu */ "-", /* NT */ "-", /* Unixware */ "/sbin/route", /* openbsd */ "-", /* sco */ "/sbin/route", /* darwin */ "-", /* ux4800 */ "-", /* qnx */ "/sbin/route", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; /*********************************************************************/ char *VROUTEADDFMT[CF_CLASSATTR] = { "-", "-", "-", /* sun4 */ "-", /* ultrix */ "-", /* hpux */ "-", /* aix */ "add %s gw %s", /* linux */ "add %s %s", /* solaris */ "-", /* osf1 */ "-", /* digital */ "-", /* sun3 */ "-", /* irix4 */ "-", /* irix */ "-", /* irix64 */ "add %s %s", /* freebsd */ "add %s %s", /* solarisx86 */ "-", /* bsd4.3 */ "-", /* newsos4 */ "-", /* netbsd */ "-", /* AOS */ "-", /* BSDI */ "-", /* nextstep */ "-", /* cray */ "-", /* gnu */ "-", /* NT */ "-", /* Unixware */ "add %s %s", /* openbsd */ "-", /* sco */ "add %s %s", /* darwin */ "-", /* ux4800 */ "-", /* qnx */ "add %s %s", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; /*********************************************************************/ char *VROUTEDELFMT[CF_CLASSATTR] = { "-", "-", "-", /* sun4 */ "-", /* ultrix */ "-", /* hpux */ "-", /* aix */ "del %s", /* linux */ "delete %s", /* solaris */ "-", /* osf1 */ "-", /* digital */ "-", /* sun3 */ "-", /* irix4 */ "-", /* irix */ "-", /* irix64 */ "delete %s", /* freebsd */ "delete %s", /* solarisx86 */ "-", /* bsd4.3 */ "-", /* newsos4 */ "-", /* netbsd */ "-", /* AOS */ "-", /* BSDI */ "-", /* nextstep */ "-", /* cray */ "-", /* gnu */ "-", /* NT */ "-", /* Unixware */ "delete %s", /* openbsd */ "-", /* sco */ "delete %s", /* darwin */ "-", /* ux4800 */ "-", /* qnx */ "delete %s", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; /*********************************************************************/ char *VFILECOMM[CF_CLASSATTR] = { "-", "-", "/usr/bin/file", /* sun4 */ "/usr/bin/file", /* ultrix */ "/usr/bin/file", /* hpux */ "/usr/bin/file", /* aix */ "/usr/bin/file", /* linux */ "/usr/bin/file", /* solaris */ "/usr/bin/file", /* osf1 */ "/usr/bin/file", /* digital */ "/usr/ucb/file", /* sun3 */ "/usr/bin/file", /* irix4 */ "/usr/bin/file", /* irix */ "/usr/bin/file", /* irix64 */ "/usr/bin/file", /* freebsd */ "/usr/bin/file", /* solarisx86 */ "/usr/ucb/file", /* bsd4.3 */ "/usr/ucb/file", /* newsos4 */ "/usr/bin/file", /* netbsd */ "/usr/ucb/file", /* AOS */ "/usr/bin/file", /* BSDI */ "/usr/ucb/file", /* nextstep */ "/usr/ucb/file", /* cray */ "/usr/bin/file", /* gnu */ "/C/WINNT/System32/file", /* NT */ "/usr/bin/file", /* Unixware */ "/usr/bin/file", /* openbsd */ "/usr/bin/file", /* sco */ "/usr/bin/file", /* darwin */ "/usr/bin/file", /* ux4800 */ "/usr/bin/file", /* qnx */ "/usr/bin/file", /* dragonfly */ "unused-blah", "unused-blah", "unused-blah", NULL }; cfengine-2.2.10/src/granules.c0000644000175000001440000000560210705424654013054 00000000000000/* Copyright (C) 2001- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: granules.c */ /* */ /*****************************************************************************/ #include "../pub/getopt.h" #include "cf.defs.h" #include "cf.extern.h" #include #include /*****************************************************************************/ char *ConvTimeKey(char *str) { int i; char buf1[10],buf2[10],buf3[10],buf4[10],buf5[10],buf[10],out[10]; static char timekey[64]; sscanf(str,"%s %s %s %s %s",buf1,buf2,buf3,buf4,buf5); timekey[0] = '\0'; /* Day */ sprintf(timekey,"%s:",buf1); /* Hours */ sscanf(buf4,"%[^:]",buf); sprintf(out,"Hr%s",buf); strcat(timekey,out); /* Minutes */ sscanf(buf4,"%*[^:]:%[^:]",buf); sprintf(out,"Min%s",buf); strcat(timekey,":"); sscanf(buf,"%d",&i); switch ((i / 5)) { case 0: strcat(timekey,"Min00_05"); break; case 1: strcat(timekey,"Min05_10"); break; case 2: strcat(timekey,"Min10_15"); break; case 3: strcat(timekey,"Min15_20"); break; case 4: strcat(timekey,"Min20_25"); break; case 5: strcat(timekey,"Min25_30"); break; case 6: strcat(timekey,"Min30_35"); break; case 7: strcat(timekey,"Min35_40"); break; case 8: strcat(timekey,"Min40_45"); break; case 9: strcat(timekey,"Min45_50"); break; case 10: strcat(timekey,"Min50_55"); break; case 11: strcat(timekey,"Min55_00"); break; } return timekey; } /*****************************************************************************/ char *GenTimeKey(time_t now) { static char str[64]; sprintf(str,"%s",ctime(&now)); return ConvTimeKey(str); } cfengine-2.2.10/src/tidy.c0000644000175000001440000002100310721063356012172 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ /* */ /* Tidy object */ /* */ /*********************************************************************/ void TidyParticularFile(char *path,char *name,struct Tidy *tp,struct stat *statbuf,int is_dir,int level,int usepath) { struct TidyPattern *tlp; short savekilloldlinks = KILLOLDLINKS; Debug2("TidyParticularFile(%s,%s)\n",path,name); if (tp->tidylist == NULL) { return; } for (tlp = tp->tidylist; tlp != NULL; tlp=tlp->next) { if (IsExcluded(tlp->classes)) { continue; } ResetOutputRoute(tlp->log,tlp->inform); if (S_ISLNK(statbuf->st_mode) && is_dir && (tlp->dirlinks == 'k') && (tlp->rmdirs == 'n')) /* Keep links to directories */ { ResetOutputRoute('d','d'); continue; } savekilloldlinks = KILLOLDLINKS; if (tlp->travlinks == 'K') { KILLOLDLINKS = true; } if (S_ISLNK(statbuf->st_mode)) /* No point in checking permission on a link */ { Debug("Checking for dead links\n"); if (tlp != NULL) { KillOldLink(path,tlp->defines); tlp->tidied = true; } else { KillOldLink(path,NULL); } } KILLOLDLINKS = savekilloldlinks; if (is_dir && tlp->rmdirs == 'n') /* not allowed to rmdir */ { ResetOutputRoute('d','d'); continue; } if ((level == tp->maxrecurse) && tlp->rmdirs == 's') /* rmdir subdirs only */ { ResetOutputRoute('d','d'); continue; } if (level > tlp->recurse && tlp->recurse != CF_INF_RECURSE) { Debug2("[PATTERN %s RECURSE ENDED at %d(%d) BEFORE MAXVAL %d]\n",tlp->pattern, level,tlp->recurse,tp->maxrecurse); ResetOutputRoute('d','d'); continue; } if (IsExcluded(tlp->classes)) { ResetOutputRoute('d','d'); continue; } if (!WildMatch(tlp->pattern,name)) { Debug("Pattern did not match (first filter %s) %s\n",tlp->pattern,path); ResetOutputRoute('d','d'); continue; } if (!FileObjectFilter(path,statbuf,tlp->filters,tidy)) { Debug("Skipping filtered file %s\n",path); continue; } if (IgnoredOrExcluded(tidy,path,NULL,tp->exclusions)) { Debug("Skipping ignored/excluded file %s\n",path); continue; } if (S_ISLNK(statbuf->st_mode) && is_dir && (tlp->dirlinks == 'y')) { Debug("Link to directory, dirlinks= says delete these\n"); } else if (is_dir && !EmptyDir(path)) { Debug("Non-empty directory %s, skipping..\n",path); ResetOutputRoute('d','d'); continue; } Debug2("Matched %s to %s in %s\n",name,tlp->pattern,path); DoTidyFile(path,name,tlp,statbuf,CF_NOLOGFILE,is_dir,usepath); ResetOutputRoute('d','d'); if (!tlp->tidied) { AddMultipleClasses(tlp->elsedef); } } } /*********************************************************************/ /* Level 2 */ /*********************************************************************/ void DoTidyFile(char *path,char *name,struct TidyPattern *tlp,struct stat *statbuf,short logging_this,int isreallydir,int usepath) { time_t nowticks, fileticks = 0; int size_match = false, age_match = false; Debug2("DoTidyFile(%s,%s)\n",path,name); /* Here we can assume that we are in the right directory with chdir()! */ nowticks = time((time_t *)NULL); /* cmp time in days */ switch (tlp->searchtype) { case 'a': fileticks = statbuf->st_atime; break; case 'm': fileticks = statbuf->st_mtime; break; case 'c': fileticks = statbuf->st_ctime; break; default: printf("cfengine: Internal error in DoTidyFile()\n"); break; } if (isreallydir) { /* Directory age comparison by mtime, since examining will always alter atime */ fileticks = statbuf->st_mtime; } if ((nowticks-fileticks < 0) && (tlp->age > 0)) { snprintf(OUTPUT,CF_BUFSIZE*2,"ALERT: atime for %s is in the future. Check system clock!\n",path); CfLog(cfinform,OUTPUT,""); return; } if (tlp->size == CF_EMPTYFILE) { if (statbuf->st_size == 0) { size_match = true; } else { size_match = false; } } else { size_match = (tlp->size <= statbuf->st_size); } age_match = tlp->age*CF_TICKS_PER_DAY <= (nowticks-fileticks) || (nowticks < fileticks); if (age_match && size_match) { if (logging_this) { if (VLOGFP != NULL) { fprintf(VLOGFP,"cf: rm %s\n",path); } } if (! DONTDO) { if (S_ISDIR(statbuf->st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Deleting directory %s\n",path); CfLog(cfinform,OUTPUT,""); AuditLog(tlp->logaudit,tlp->audit,tlp->lineno,OUTPUT,CF_CHG); if (usepath) { if (rmdir(path) == -1) { Debug("Special case remove top level %s\n",path); snprintf(OUTPUT,CF_BUFSIZE,"Delete top directory %s failed\n",path); CfLog(cfinform,OUTPUT,"unlink"); } else { AddMultipleClasses(tlp->defines); tlp->tidied = true; } } else { if (rmdir(name) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Delete directory %s failed\n",path); CfLog(cfinform,OUTPUT,"unlink"); AuditLog(tlp->logaudit,tlp->audit,tlp->lineno,OUTPUT,CF_FAIL); } else { AddMultipleClasses(tlp->defines); tlp->tidied = true; } } } else { int ret=false; if (tlp->compress == 'y') { CompressFile(name); } else if ((ret = unlink(name)) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't unlink %s tidying\n",path); CfLog(cfverbose,OUTPUT,"unlink"); AuditLog(tlp->logaudit,tlp->audit,tlp->lineno,OUTPUT,CF_FAIL); } snprintf(OUTPUT,CF_BUFSIZE,"Deleting file %s\n",path); CfLog(cfinform,OUTPUT,""); AuditLog(tlp->logaudit,tlp->audit,tlp->lineno,OUTPUT,CF_CHG); snprintf(OUTPUT,CF_BUFSIZE,"Size=%d bytes, %c-age=%d days\n", statbuf->st_size,tlp->searchtype,(nowticks-fileticks)/CF_TICKS_PER_DAY); CfLog(cfverbose,OUTPUT,""); if (ret != -1) { AddMultipleClasses(tlp->defines); tlp->tidied = true; } } } else { if (tlp->compress == 'y') { printf("%s: want to compress %s\n",VPREFIX,path); } else { printf("%s: want to delete %s\n",VPREFIX,path); } } } else { Debug2("(No age match)\n"); } } /*********************************************************************/ void DeleteTidyList(struct TidyPattern *list) { if (list != NULL) { DeleteTidyList(list->next); list->next = NULL; if (list->classes != NULL) { free (list->classes); } free((char *)list); } } cfengine-2.2.10/src/copy.c0000644000175000001440000001476310202123551012176 00000000000000/* Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* File copying low level */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ void CheckForHoles(struct stat *sstat,struct Image *ip) /* Need a transparent way of getting this into CopyReg() */ /* Use a public member in struct Image */ { #ifndef IRIX if (sstat->st_size > sstat->st_blocks * DEV_BSIZE) #else # ifdef HAVE_ST_BLOCKS if (sstat->st_size > sstat->st_blocks * DEV_BSIZE) # else if (sstat->st_size > ST_NBLOCKS((*sstat)) * DEV_BSIZE) # endif #endif { ip->makeholes = 1; /* must have a hole to get checksum right */ } ip->makeholes = 0; } /*********************************************************************/ int CopyRegDisk(char *source,char *new,struct Image *ip) { int sd, dd, buf_size; char *buf, *cp; int n_read, *intp; long n_read_total = 0; int last_write_made_hole = 0; if ((sd = open(source,O_RDONLY|O_BINARY)) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Can't copy %s!\n",source); CfLog(cfinform,OUTPUT,"open"); unlink(new); return false; } unlink(new); /* To avoid link attacks */ if ((dd = open(new,O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0600)) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Copy %s:%s security - failed attempt to exploit a race? (Not copied)\n",ip->server,new); CfLog(cfinform,OUTPUT,"open"); close(sd); unlink(new); return false; } buf_size = ST_BLKSIZE(dstat); buf = (char *) malloc(buf_size + sizeof(int)); while (true) { if ((n_read = read (sd, buf, buf_size)) == -1) { if (errno == EINTR) { continue; } close(sd); close(dd); free(buf); return false; } if (n_read == 0) { break; } n_read_total += n_read; intp = 0; if (ip->makeholes) { buf[n_read] = 1; /* Sentinel to stop loop. */ /* Find first non-zero *word*, or the word with the sentinel. */ intp = (int *) buf; while (*intp++ == 0) { } /* Find the first non-zero *byte*, or the sentinel. */ cp = (char *) (intp - 1); while (*cp++ == 0) { } /* If we found the sentinel, the whole input block was zero, and we can make a hole. */ if (cp > buf + n_read) { /* Make a hole. */ if (lseek (dd, (off_t) n_read, SEEK_CUR) < 0L) { snprintf(OUTPUT,CF_BUFSIZE,"Copy failed (no space?) while doing %s to %s\n",source,new); CfLog(cferror,OUTPUT,"lseek"); free(buf); unlink(new); close(dd); close(sd); return false; } last_write_made_hole = 1; } else { /* Clear to indicate that a normal write is needed. */ intp = 0; } } if (intp == 0) { if (cf_full_write (dd, buf, n_read) < 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Copy failed (no space?) while doing %s to %s\n",source,new); CfLog(cferror,OUTPUT,""); close(sd); close(dd); free(buf); unlink(new); return false; } last_write_made_hole = 0; } } /* If the file ends with a `hole', something needs to be written at the end. Otherwise the kernel would truncate the file at the end of the last write operation. */ if (last_write_made_hole) { /* Write a null character and truncate it again. */ if (cf_full_write (dd, "", 1) < 0 || ftruncate (dd, n_read_total) < 0) { CfLog(cferror,"cfengine: full_write or ftruncate error in CopyReg\n","write"); free(buf); unlink(new); close(sd); close(dd); return false; } } close(sd); close(dd); free(buf); return true; } /*********************************************************************/ int EmbeddedWrite(char *new,int dd,char *buf,struct Image *ip,int towrite,int *last_write_made_hole,int n_read) { int *intp; char *cp; intp = 0; if (ip->makeholes) { buf[n_read] = 1; /* Sentinel to stop loop. */ /* Find first non-zero *word*, or the word with the sentinel. */ intp = (int *) buf; while (*intp++ == 0) { } /* Find the first non-zero *byte*, or the sentinel. */ cp = (char *) (intp - 1); while (*cp++ == 0) { } /* If we found the sentinel, the whole input block was zero, and we can make a hole. */ if (cp > buf + n_read) { /* Make a hole. */ if (lseek (dd,(off_t)n_read,SEEK_CUR) < 0L) { snprintf(OUTPUT,CF_BUFSIZE,"lseek in EmbeddedWrite, dest=%s\n", new); CfLog(cferror,OUTPUT,"lseek"); return false; } *last_write_made_hole = 1; } else { /* Clear to indicate that a normal write is needed. */ intp = 0; } } if (intp == 0) { if (cf_full_write (dd,buf,towrite) < 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Local disk write(%.256s) failed\n",new); CfLog(cferror,OUTPUT,"write"); CONN->error = true; return false; } *last_write_made_hole = 0; } return true; } cfengine-2.2.10/src/net.c0000644000175000001440000001133510766753756012041 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*********************************************************************/ /* */ /* TOOLKITS: network library */ /* */ /*********************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*************************************************************************/ int SendTransaction(int sd,char *buffer,int len,char status) { char work[CF_BUFSIZE]; int wlen; if (len == 0) { wlen = strlen(buffer); } else { wlen = len; } if (wlen > CF_BUFSIZE-CF_INBAND_OFFSET) { FatalError("SendTransaction software failure"); } snprintf(work,CF_INBAND_OFFSET,"%c %d",status,wlen); memcpy(work+CF_INBAND_OFFSET,buffer,wlen); Debug("Transaction Send[%s][Packed text]\n",work); if (SendSocketStream(sd,work,wlen+CF_INBAND_OFFSET,0) == -1) { return -1; } return 0; } /*************************************************************************/ int ReceiveTransaction(int sd,char *buffer,int *more) { char proto[CF_INBAND_OFFSET+1]; char status = 'x'; unsigned int len = 0; memset(proto,0,CF_INBAND_OFFSET+1); if (RecvSocketStream(sd,proto,CF_INBAND_OFFSET,0) == -1) /* Get control channel */ { return -1; } sscanf(proto,"%c %u",&status,&len); Debug("Transaction Receive [%s][%s]\n",proto,proto+CF_INBAND_OFFSET); if (len > CF_BUFSIZE - CF_INBAND_OFFSET) { snprintf(OUTPUT,CF_BUFSIZE,"Bad transaction packet -- too long (%c %d) Proto = %s ",status,len,proto); CfLog(cferror,OUTPUT,""); return -1; } if (strncmp(proto,"CAUTH",5) == 0) { Debug("Version 1 protocol connection attempted - no you don't!!\n"); return -1; } if (more != NULL) { switch(status) { case 'm': *more = true; break; default: *more = false; } } return RecvSocketStream(sd,buffer,len,0); } /*************************************************************************/ int RecvSocketStream(int sd,char buffer[CF_BUFSIZE],int toget,int nothing) { int already, got; static int fraction; Debug("RecvSocketStream(%d)\n",toget); if (toget > CF_BUFSIZE-1) { CfLog(cferror,"Bad software request for overfull buffer",""); return -1; } for (already = 0; already != toget; already += got) { got = recv(sd,buffer+already,toget-already,0); if (got == -1) { CfLog(cfverbose,"Couldn't recv","recv"); return -1; } if (got == 0) /* doesn't happen unless sock is closed */ { Debug("Transmission empty or timed out...\n"); fraction = 0; buffer[already] = '\0'; return already; } Debug(" (Concatenated %d from stream)\n",got); if (strncmp(buffer,"AUTH",4) == 0 && (already == CF_BUFSIZE)) { fraction = 0; buffer[already] = '\0'; return already; } } buffer[toget] = '\0'; return toget; } /*************************************************************************/ /* * Drop in replacement for send but includes * guaranteed whole buffer sending. * Wed Feb 28 11:30:55 GMT 2001, Morten Hermanrud, mhe@say.no */ int SendSocketStream(int sd,char buffer[CF_BUFSIZE],int tosend,int flags) { int sent,already=0; do { Debug("Attempting to send %d bytes\n",tosend-already); sent=send(sd,buffer+already,tosend-already,flags); switch(sent) { case -1: CfLog(cfverbose,"Couldn't send","send"); return -1; default: Debug("SendSocketStream, sent %d\n",sent); already += sent; break; } } while (already < tosend); return already; } /*************************************************************************/ cfengine-2.2.10/src/cfservd.h0000644000175000001440000000523710375425554012704 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ /*******************************************************************/ /* */ /* HEADER for cfd - Not generically includable! */ /* */ /*******************************************************************/ extern FILE *yyin; #define queuesize 50 #define connection 1 #define CFD_INPUT "cfservd.conf" #define CFD_SOURCE 1 #define RFC931_PORT 113 #define CFSERVD 1 #define CF_BUFEXT 128 /**********************************************************************/ struct cfd_connection { int id_verified; int rsa_auth; int synchronized; int maproot; int trust; int sd_reply; unsigned char *session_key; char hostname[CF_MAXVARSIZE]; char username[CF_MAXVARSIZE]; uid_t uid; char ipaddr[CF_MAX_IP_LEN]; char output[CF_BUFSIZE*2]; /* Threadsafe output channel */ }; struct cfd_get_arg { struct cfd_connection *connect; int encrypt; int buf_size; char *replybuff; char *replyfile; }; /*******************************************************************/ /* PARSER */ /*******************************************************************/ char CFRUNCOMMAND[CF_BUFSIZE]; time_t CFDSTARTTIME; #ifdef RE_DUP_MAX # undef RE_DUP_MAX #endif /******************************************************************* * Sunos4.1.4 need these prototypes *******************************************************************/ #if defined(SUN4) extern char *realpath(/* char *path; char resolved_path[MAXPATHLEN] */); #endif #ifndef INADDR_NONE #define INADDR_NONE ((unsigned long int) 0xffffffff) #endif cfengine-2.2.10/src/read.c0000644000175000001440000000522011006303474012132 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*===========================================================================*/ /* */ /* File: read.c */ /* */ /* Created: Mon Sep 29 09:22:33 1997 */ /* */ /* Revision: $Id$ */ /* */ /* Description: */ /* */ /*===========================================================================*/ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ int ReadLine(char *buff,int size,FILE *fp) { char ch; buff[0] = '\0'; buff[size - 1] = '\0'; /* mark end of buffer */ if (fgets(buff, size, fp) == NULL) { *buff = '\0'; /* EOF */ return false; } else { char *tmp; if ((tmp = strrchr(buff, '\n')) != NULL) { /* remove newline */ *tmp = '\0'; } else { /* The line was too long and truncated so, discard probable remainder */ while (true) { if (feof(fp)) { break; } ch = fgetc(fp); if (ch == '\n') { break; } } } } return true; } cfengine-2.2.10/src/chflags.c0000644000175000001440000001403210362016753012634 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /* This code was contributed by Andreas Klussman */ /***************************************************************/ /* Flagstring toolkit */ /***************************************************************/ /* adapted from FreeBSD /usr/src/bin/ls/stat_flags.c */ #define TEST(a, b, f) { \ if (!memcmp(a, b, sizeof(b))) { \ if (clear) { \ if (minusmask) \ *minusmask |= (f); \ } else if (plusmask) \ *plusmask |= (f); \ break; \ } \ } /***************************************************************/ void ParseFlagString(char *flagstring,u_long *plusmask,u_long *minusmask) { char *sp, *next; int clear; u_long value; value = 0; if (flagstring == NULL) { return; } Debug1("ParseFlagString(%s)\n",flagstring); for ( sp = flagstring; sp && *sp; sp = next ) { if ( next = strchr( sp, ',' )) { *next ++ = '\0'; } clear = 0; if ( sp[0] == 'n' && sp[1] == 'o' ) { clear = 1; sp += 2; } switch ( *sp ) { case 'a': TEST(sp, "arch", SF_ARCHIVED); TEST(sp, "archived", SF_ARCHIVED); goto Error; case 'd': clear = !clear; TEST(sp, "dump", UF_NODUMP); goto Error; case 'o': TEST(sp, "opaque", UF_OPAQUE); goto Error; case 's': TEST(sp, "sappnd", SF_APPEND); TEST(sp, "sappend", SF_APPEND); TEST(sp, "schg", SF_IMMUTABLE); TEST(sp, "schange", SF_IMMUTABLE); TEST(sp, "simmutable", SF_IMMUTABLE); TEST(sp, "sunlnk", SF_NOUNLINK); TEST(sp, "sunlink", SF_NOUNLINK); goto Error; case 'u': TEST(sp, "uappnd", UF_APPEND); TEST(sp, "uappend", UF_APPEND); TEST(sp, "uchg", UF_IMMUTABLE); TEST(sp, "uchange", UF_IMMUTABLE); TEST(sp, "uimmutable", UF_IMMUTABLE); TEST(sp, "uunlnk", UF_NOUNLINK); TEST(sp, "uunlink", UF_NOUNLINK); goto Error; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': sscanf(sp,"%o",&value); *plusmask = value; *minusmask = ~value & CHFLAGS_MASK; break; case '\0': break; Error: default: printf( "Invalid flag string '%s'\n", sp ); yyerror ("Invalid flag string"); return; } } Debug1("ParseFlagString:[PLUS=%o][MINUS=%o]\n",*plusmask,*minusmask); } /* CHFLAGS(1) FreeBSD General Commands Manual CHFLAGS(1) NAME chflags - change file flags SYNOPSIS chflags [-R [-H | -L | -P]] flags file ... DESCRIPTION The chflags utility modifies the file flags of the listed files as speci- fied by the flags operand. The options are as follows: -H If the -R option is specified, symbolic links on the command line are followed. (Symbolic links encountered in the tree traversal are not followed.) -L If the -R option is specified, all symbolic links are followed. -P If the -R option is specified, no symbolic links are followed. -R Change the file flags for the file hierarchies rooted in the files instead of just the files themselves. Flags are a comma separated list of keywords. The following keywords are currently defined: arch set the archived flag (super-user only) dump set the dump flag sappnd set the system append-only flag (super-user only) schg set the system immutable flag (super-user only) sunlnk set the system undeletable flag (super-user only) uappnd set the user append-only flag (owner or super-user only) uchg set the user immutable flag (owner or super-user only) uunlnk set the user undeletable flag (owner or super-user only) archived, sappend, schange, simmutable, uappend, uchange, uimmutable, sunlink, uunlink aliases for the above Putting the letters ``no'' before an option causes the flag to be turned off. For example: nodump the file should never be dumped Symbolic links do not have flags, so unless the -H or -L option is set, chflags on a symbolic link always succeeds and has no effect. The -H, -L and -P options are ignored unless the -R option is specified. In addi- tion, these options override each other and the command's actions are de- termined by the last one specified. You can use "ls -lo" to see the flags of existing files. The chflags utility exits 0 on success, and >0 if an error occurs. SEE ALSO ls(1), chflags(2), stat(2), fts(3), symlink(7) HISTORY The chflags command first appeared in 4.4BSD. BSD March 31, 1994 1 */ cfengine-2.2.10/src/cflex.c0000644000175000001440000072707011170173313012335 00000000000000 #line 3 "lex.yy.c" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; #endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart(yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart (FILE *input_file ); void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); void yy_delete_buffer (YY_BUFFER_STATE b ); void yy_flush_buffer (YY_BUFFER_STATE b ); void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); void yypop_buffer_state (void ); static void yyensure_buffer_stack (void ); static void yy_load_buffer_state (void ); static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); void *yyalloc (yy_size_t ); void *yyrealloc (void *,yy_size_t ); void yyfree (void * ); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ yyensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ yy_create_buffer(yyin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ #define yywrap(n) 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern int yylineno; int yylineno = 1; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ yyleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 40 #define YY_END_OF_BUFFER 41 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[1983] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41, 35, 14, 13, 14, 35, 35, 16, 35, 35, 26, 28, 35, 35, 35, 21, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 27, 29, 39, 39, 39, 16, 39, 39, 26, 28, 39, 39, 23, 21, 23, 39, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 27, 29, 23, 37, 37, 37, 16, 37, 37, 26, 28, 37, 37, 25, 21, 25, 37, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 27, 29, 25, 36, 36, 36, 16, 36, 36, 26, 28, 36, 36, 36, 21, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 27, 29, 38, 38, 38, 16, 38, 38, 26, 28, 38, 38, 38, 21, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 27, 29, 35, 14, 13, 35, 35, 35, 35, 35, 0, 31, 35, 16, 16, 16, 35, 0, 35, 20, 19, 35, 35, 35, 0, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 0, 31, 0, 16, 0, 20, 19, 23, 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 37, 37, 37, 37, 37, 37, 31, 37, 16, 16, 37, 37, 20, 19, 25, 24, 37, 25, 25, 37, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 36, 36, 36, 36, 36, 36, 0, 30, 36, 16, 16, 36, 0, 36, 20, 19, 36, 36, 36, 0, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 38, 38, 38, 38, 38, 38, 31, 38, 16, 16, 38, 38, 20, 19, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 35, 0, 35, 35, 35, 33, 35, 35, 22, 31, 16, 31, 17, 18, 34, 34, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 33, 0, 0, 22, 31, 16, 31, 17, 18, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 37, 37, 37, 37, 33, 37, 37, 22, 31, 16, 31, 17, 18, 34, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 36, 0, 36, 36, 36, 32, 36, 36, 22, 30, 0, 30, 16, 0, 30, 17, 18, 34, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 38, 38, 38, 38, 33, 38, 38, 22, 31, 16, 31, 17, 18, 34, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 33, 33, 35, 0, 35, 33, 35, 35, 0, 33, 35, 22, 35, 0, 33, 16, 8, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 33, 0, 33, 0, 22, 33, 16, 8, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 33, 37, 37, 33, 37, 37, 33, 37, 22, 37, 33, 16, 8, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 32, 32, 36, 0, 36, 32, 36, 36, 0, 32, 36, 22, 36, 0, 32, 30, 16, 30, 8, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 33, 38, 38, 33, 38, 38, 33, 38, 22, 38, 33, 16, 8, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 35, 0, 35, 35, 35, 35, 0, 35, 35, 35, 0, 16, 35, 35, 35, 35, 35, 35, 10, 35, 3, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 0, 0, 16, 23, 23, 23, 23, 23, 23, 10, 23, 3, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 37, 37, 37, 37, 37, 37, 37, 37, 16, 25, 25, 25, 25, 25, 25, 10, 25, 3, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 32, 0, 36, 0, 36, 36, 36, 32, 0, 36, 0, 36, 36, 32, 36, 0, 16, 36, 36, 36, 36, 36, 36, 10, 36, 3, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 38, 38, 38, 38, 38, 38, 38, 38, 16, 38, 38, 38, 38, 38, 38, 10, 38, 3, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 35, 35, 35, 35, 35, 35, 35, 35, 16, 1, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 2, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 0, 0, 0, 0, 0, 1, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 2, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 37, 37, 37, 37, 37, 37, 37, 37, 1, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 2, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 36, 36, 36, 36, 0, 0, 36, 36, 36, 36, 1, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 2, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 38, 38, 38, 38, 38, 38, 38, 38, 1, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 2, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 35, 0, 33, 35, 35, 0, 35, 33, 35, 35, 0, 33, 35, 15, 35, 35, 35, 35, 35, 35, 35, 35, 35, 6, 35, 11, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 33, 0, 0, 33, 0, 33, 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 6, 23, 11, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 37, 33, 37, 37, 37, 33, 37, 37, 33, 37, 25, 25, 25, 25, 25, 25, 25, 25, 25, 6, 25, 11, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 36, 0, 32, 36, 36, 0, 36, 32, 36, 0, 0, 0, 0, 36, 0, 32, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 6, 36, 11, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 38, 33, 38, 38, 38, 33, 38, 38, 33, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 6, 38, 11, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 35, 0, 35, 35, 35, 35, 35, 35, 0, 35, 35, 35, 35, 0, 35, 35, 15, 15, 35, 35, 7, 4, 35, 35, 35, 9, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 7, 4, 23, 23, 23, 9, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 25, 25, 7, 4, 25, 25, 25, 9, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 32, 0, 0, 32, 0, 36, 0, 36, 36, 36, 36, 36, 36, 0, 36, 36, 36, 32, 0, 36, 0, 36, 36, 36, 36, 7, 4, 36, 36, 36, 9, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 7, 4, 38, 38, 38, 9, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 36, 36, 36, 36, 36, 36, 36, 36, 0, 0, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 35, 0, 33, 35, 35, 35, 35, 12, 35, 35, 35, 35, 35, 35, 35, 33, 0, 23, 23, 23, 12, 23, 23, 23, 23, 23, 23, 23, 37, 33, 37, 25, 25, 25, 12, 25, 25, 25, 25, 25, 25, 25, 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, 32, 36, 0, 0, 0, 0, 36, 36, 36, 12, 36, 36, 36, 36, 36, 36, 36, 38, 33, 38, 38, 38, 38, 12, 38, 38, 38, 38, 38, 38, 38, 35, 0, 35, 35, 35, 35, 35, 35, 5, 0, 0, 23, 23, 23, 23, 5, 37, 37, 37, 25, 25, 25, 25, 5, 32, 0, 36, 0, 36, 36, 36, 36, 36, 36, 5, 38, 38, 38, 38, 38, 38, 38, 5, 35, 35, 35, 35, 35, 35, 0, 0, 0, 0, 23, 23, 37, 37, 37, 37, 25, 25, 0, 0, 36, 36, 36, 36, 36, 36, 38, 38, 38, 38, 38, 38, 35, 23, 25, 0, 0, 0, 0, 36, 38, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 7, 1, 1, 8, 9, 10, 11, 1, 12, 8, 13, 8, 1, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 8, 1, 16, 17, 1, 1, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 1, 19, 1, 1, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 30, 30, 43, 30, 44, 8, 45, 1, 1, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46 } ; static yyconst flex_int32_t yy_meta[47] = { 0, 1, 2, 3, 4, 5, 1, 1, 5, 1, 5, 5, 1, 1, 5, 5, 6, 1, 5, 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 5 } ; static yyconst flex_int16_t yy_base[2365] = { 0, 0, 0, 46, 0, 92, 0, 138, 0, 184, 0, 7245, 0, 229, 232, 235, 239, 258, 239, 285, 263, 330, 0, 7226, 7220, 375, 0, 276, 283, 215, 238, 264, 7212, 7206, 7196, 7198, 241, 7203, 274, 287, 7206, 288, 7200, 7193, 0, 0,10354, 302, 257, 7194, 7209, 305, 7203, 7202, 7199, 7198, 417,10354, 426, 7194, 468, 303, 328, 330, 333, 415, 419, 426, 345, 430, 494, 443, 445, 465, 472, 475,10354,10354, 356, 0, 529, 548, 286, 575, 553, 620, 0, 7196, 7195, 665, 0, 711, 318, 479, 417, 338, 294, 7186, 7179, 7169, 7170, 396, 7170, 487, 427, 7173, 530, 7168, 7162, 0, 0, 757, 0, 802, 594, 478, 848, 599, 893, 0, 7178, 7177, 938, 0, 557, 501, 456, 439, 315, 7169, 7162, 7151, 7153, 494, 7157, 564, 526, 7155, 540, 7150, 7144, 0, 0, 0, 984, 603, 610, 1030, 641, 1075, 0, 7160, 7159, 1120, 0, 621, 623, 505, 455, 427, 7151, 7145, 7134, 7135, 577, 7140, 627, 545, 7142, 752, 7132, 7126, 0, 0, 0, 613, 655, 1166, 1212, 1257, 7144, 779, 559, 0, 785, 422, 0, 757, 821, 560, 824, 7153, 7152, 1302, 7152, 832, 7135, 7121, 7118, 7125, 7114, 7107, 7120, 594, 627, 295, 7111, 7107, 485, 7105, 7103, 7100, 7094, 7098, 7102, 7089, 7084, 7081, 7098, 7085, 756, 7087, 7093, 7079, 7091, 7080, 861, 7097, 1348, 7095,10354, 632, 7075, 775, 7098, 7097, 1389, 0, 869, 880, 1431, 499, 746, 635, 599, 775, 805, 819, 767, 768, 7069, 838, 681, 797, 784, 810, 824, 846, 849, 864, 622, 888, 851, 882, 7068, 872, 249, 893, 890, 0, 1477, 1523, 1568, 7084, 1003, 0, 1008, 922, 984, 1014, 1049, 7093, 7091, 1613, 7079, 7089, 1659, 1705, 1052, 7059, 7052, 7059, 7049, 7047, 7060, 893, 902, 892, 7051, 7047, 866, 7044, 7041, 7038, 7032, 7032, 7036, 7024, 7024, 7021, 7038, 7025, 987, 7026, 7031, 7017, 7029, 7014, 0, 1750, 1796, 1841, 7031, 1058, 983, 0, 1067, 930, 1030, 1094, 989, 1097, 7040, 7039, 1886, 7039, 1063, 7022, 7009, 7006, 7009, 6993, 6990, 7003, 899, 1014, 902, 6993, 6988, 1058, 6982, 6974, 6970, 6965, 6969, 6972, 6956, 6950, 6946, 6963, 6949, 1068, 6950, 6952, 6932, 6944, 6934, 0, 1932, 1978, 2023, 6950, 1185, 0, 1190, 1076, 1166, 1196, 1231, 6958, 6953, 2068, 6947, 1234, 6917, 6915, 6921, 6910, 6904, 6912, 1074, 1078, 981, 6903, 6898, 1088, 6896, 6893, 6889, 6880, 6879, 6882, 6870, 6869, 6865, 6878, 6859, 1169, 6860, 6864, 6849, 6858, 6842, 1240, 6862, 2114, 1276, 1281, 2159, 1367, 1370, 0, 1243, 1167, 1382, 0, 0, 6866, 0, 2204, 1187, 1000, 823, 1020, 903, 1074, 1042, 1096, 1205, 1165, 1250, 1182, 1362, 634, 1211, 1192, 425, 1240, 1271, 851, 1273, 1276, 1274, 745, 1199, 1283, 1103, 1226, 1341, 1224, 1343, 1278, 1365, 1368, 2250, 1400, 1401, 6848, 1351, 1368,10354, 1390, 6822, 1404,10354,10354, 2291, 2333, 1360, 1385, 1396, 1387, 1389, 1401, 1411, 1402, 1408, 1422, 1398, 1425, 1423, 228, 1430, 1386, 1393, 1431, 1433, 1429, 1438, 1445, 1441, 1440, 1450, 1451, 803, 1447, 6825, 1466, 1470, 1405, 1471, 1499, 2379, 1509, 1542, 2424, 1545, 1505, 0, 1587, 1529, 1592, 0, 0, 6847, 2469, 1489, 1499, 1466, 1537, 1502, 1519, 1511, 1561, 1512, 1577, 1584, 1558, 1694, 1010, 1563, 1582, 1551, 1692, 1585, 1708, 1711, 1588, 1542, 1713, 1714, 1594, 1715, 1723, 1717, 1535, 1716, 1720, 1725, 1718, 1769, 6833, 2515, 1772, 1815, 2560, 1818, 1835, 0,10354, 1736, 1782, 1796, 1735, 1860, 0, 0, 6834, 2605, 1764, 1766, 1767, 1810, 1775, 1792, 1784, 1844, 1808, 1762, 1851, 1795, 1921, 1834, 1919, 1852, 1855, 1920, 1856, 1858, 1922, 1860, 1813, 1935, 1941, 1861, 1859, 1942, 1938, 1951, 1943, 1944, 1949, 1947, 1997, 2651, 2000, 2042, 2696, 2045, 2133, 0, 2012, 2003, 2136, 0, 0, 6833, 2741, 1952, 1948, 1973, 1953, 1974, 1956, 2104, 2037, 2107, 1995, 2131, 2026, 2117, 1994, 2018, 2039, 2035, 2113, 2040, 2136, 2109, 2128, 2048, 2139, 2146, 2165, 2148, 2149, 2166, 2155, 2167, 2168, 2240, 2171, 0,10354, 2189, 2262, 2786, 2272, 2286, 2308, 2268, 2311, 2320, 2282, 2343, 1726, 2330, 2278, 6817, 2806, 6785, 546, 2276, 1622, 2147, 2313, 2156, 2320, 2281, 2286, 2232, 2316, 2318, 2032, 6778, 1981, 2325, 2220, 2321, 2328, 2330, 2332, 1843, 1082, 6776, 2315, 2300, 2334, 2344, 2162, 2337, 2357, 6773, 2360, 2361, 2397, 2399, 2401, 2395, 2400, 6800, 6786, 6772, 6779, 2848, 2890, 2353, 2386, 2376, 2389, 2398, 2381, 2413, 2409, 2412, 2406, 2416, 2408, 2410, 6747, 2415, 2418, 2421, 2422, 2425, 2427, 2432, 2485, 2496, 6740, 2433, 2498, 2500, 2347, 2505, 2524, 2509, 6738, 2528, 2506, 0, 2551, 2935, 2579, 2584, 2590, 2670, 2673, 2683, 2715, 2718, 2540, 6760, 2955, 6728, 2523, 2534, 2511, 2551, 2556, 2567, 2641, 2638, 2562, 2651, 2643, 2659, 2640, 6721, 2516, 2661, 2666, 2685, 2689, 2691, 2693, 2653, 2674, 6719, 2557, 2699, 2703, 2705, 2759, 2839, 2761, 6716, 2840, 2762, 0,10354, 2865, 2851, 3000, 2871, 2907, 2912, 2785, 2883, 2931, 3010, 3013, 2187, 2879, 2859, 2887, 2789, 6727, 3033, 6700, 2879, 2704, 2770, 2882, 2857, 2820, 2888, 2884, 2903, 2908, 2919, 2912, 2892, 6690, 2913, 2918, 2889, 2967, 2970, 2979, 2983, 2765, 2992, 6683, 3059, 3056, 2995, 2997, 3050, 3068, 3052, 6680, 3070, 2989, 0, 3098, 3116, 3109, 3127, 3084, 3138, 3141, 3103, 3151, 3161, 3133, 6703, 3181, 6673, 3099, 3092, 3058, 3051, 3108, 3126, 3111, 3133, 3137, 3129, 3135, 3139, 3109, 6666, 2991, 3144, 3132, 3136, 3190, 3192, 3194, 3145, 3196, 6654, 3214, 3212, 3205, 3210, 3208, 3226, 3211, 6624, 3227, 3206, 3253, 3243, 3271, 3281, 3299, 3267, 3244, 3290, 3318, 3286, 6630, 3256, 3338, 3229, 3266, 3292, 3298, 2283, 6632, 3246, 6621, 3296, 3264, 6611, 3283, 6564, 3302, 6556, 3370, 3301, 3310, 3371, 3315, 6554, 3317, 3372, 3299, 3373, 3374, 3375, 3377, 3378, 2695, 3376, 3380, 3383, 3401, 3394, 3409, 3413, 3424, 6560, 3440, 3482, 3226, 3380, 3398, 3369, 6540, 3392, 6538, 3386, 3395, 3421, 3410, 3423, 3402, 3427, 6504, 3422, 3428, 3424, 3420, 3437, 3429, 3433, 3430, 3449, 3444, 6497, 3450, 3435, 1750, 3455, 3452, 3294, 3499, 3527, 3504, 3546, 3513, 3537, 3565, 3522, 3293, 3585, 3465, 3481, 3497, 3470, 3464, 6519, 3512, 6516, 3469, 3519, 6514, 3530, 6509, 3499, 6500, 3496, 3528, 3539, 3543, 3546, 6497, 3545, 3382, 3547, 3558, 3548, 3617, 3562, 3619, 3079, 3565, 3618, 3620, 3630, 3632, 3634, 3656, 3636, 3674, 3662, 3693, 3628, 3652, 3670, 3673, 3684, 3712, 6485, 3704, 6476, 3642, 3732, 3652, 3690, 3566, 3675, 3634, 6471, 3669, 6462, 3694, 3695, 6452, 3696, 6433, 3764, 6426, 3683, 3704, 3705, 3765, 3766, 6424, 3711, 3767, 3768, 3769, 3770, 3771, 3773, 3774, 3772, 3778, 3779, 3781, 3805, 3823, 3814, 3842, 3819, 3833, 3861, 3837, 3845, 3881, 3780, 3816, 3835, 3841, 3840, 6421, 3798, 6414, 3844, 3845, 6407, 3854, 6395, 3913, 6378, 3914, 3853, 3915, 3916, 3859, 6357, 3917, 3919, 3920, 3785, 3918, 3921, 3922, 3923, 3924, 3856, 3929, 3931, 3965, 3984, 4003, 4021, 4040, 4059, 4077, 4096, 3948, 6350, 4116, 3933, 3937, 3934, 3948, 3942, 3944, 3966, 3957, 3955, 6348, 6338, 3926, 0, 6290, 3962, 3963, 3977, 3985, 3993, 3995, 3982, 0, 4003, 4004, 3996, 4018, 3998, 4028, 4047, 4063, 4065, 4083, 4095, 4157, 4099, 6282, 4173, 4215, 3975, 2854, 4022, 4010, 4078, 4048, 4045, 3834, 6280, 4015, 3610, 4150, 4152, 4070, 3960, 4130, 3440, 4013, 4145, 4132, 4158, 4154, 4155, 4140, 4159, 4053, 4260, 4279, 4298, 4316, 4335, 4354, 4372, 4391, 6273, 4411, 4170, 4178, 4175, 4183, 4187, 4189, 4180, 4196, 4193, 6261, 6242, 4191, 0, 6235, 4188, 4198, 4195, 4201, 4222, 4192, 4206, 0, 4223, 4224, 4220, 4225, 4203, 4235, 4249, 4236, 4264, 4253, 4286, 4456, 4475, 4494, 4512, 4258, 4304, 4531, 4550, 4568, 4587, 6216, 4607, 4236, 4272, 4235, 4271, 4274, 4261, 4296, 4276, 4301, 6171, 6166, 4310, 0, 6159, 4311, 4313, 4314, 4318, 4327, 4337, 4328, 0, 4346, 4354, 4315, 4238, 4330, 4652, 4671, 4690, 4708, 4727, 4746, 4764, 4783, 6111, 6101, 4357, 4365, 4349, 4353, 4367, 4362, 4381, 4369, 4351, 6082, 6070, 4449, 6061, 6025, 4383, 4451, 4374, 4458, 4393, 4446, 4453, 5999, 4455, 4457, 4448, 4475, 4470, 4802, 4482, 4591, 4820, 4838, 4500, 4857, 4524, 4876, 4895, 4527, 4564, 4914, 5993, 4492, 4506, 5987, 5924, 4510, 4524, 0, 4497, 5917, 5877, 4372, 5858, 4526, 4540, 0, 4297, 4543, 4542, 4561, 4577, 0, 3702, 4549, 0, 4651, 4670, 4658, 4678, 4696, 4686, 4715, 4930, 4972, 4565, 4570, 4470, 4564, 4644, 4661, 4693, 5830, 4521, 5804, 4664, 4623, 4698, 4435, 4686, 5724, 4714, 4717, 4705, 4370, 4722, 4706, 5017, 4867, 5035, 5053, 5072, 4776, 5091, 5110, 4816, 5129, 5149, 4715, 4744, 4747, 4309, 4679, 4749, 5655, 4756, 5654, 4643, 5602, 4086, 4718, 4773, 4765, 4768, 4738, 5535, 4698, 4776, 4764, 4785, 4792, 4845, 4882, 4894, 4826, 5194, 4901, 4947, 5212, 5230, 4941, 5249, 4924, 5268, 4948, 4913, 4975, 4953, 5287, 4980, 4994, 5306, 5326, 4791, 4813, 4818, 4809, 4837, 4859, 5476, 4896, 5447, 4825, 5421, 4830, 4847, 4914, 4856, 4860, 4869, 5391, 4912, 4950, 4938, 4823, 4954, 5371, 5003, 5389, 5407, 5426, 5028, 5445, 5464, 5049, 5483, 5503, 4953, 5000, 5002, 4991, 5024, 5018, 5215, 5020, 5195, 4960, 5138, 4985, 5025, 5045, 5046, 5052, 5040, 5071, 5061, 5073, 4968, 4945, 5074, 5133, 5081, 5259, 5548, 5567, 5586, 5605, 5103, 5097, 5624, 5205, 5643, 5226, 5106, 5273, 5662, 0, 5052, 5682, 5002, 5009, 4989, 4774, 5053, 5089, 4943, 5109, 5174, 5179, 5023, 5181, 5086, 5105, 5103, 4491, 5201, 5238, 5275, 5293, 5309, 5291, 5310, 5377, 5395, 5218, 5414, 5724, 5766, 4812, 4800, 5111, 4902, 5162, 4727, 5354, 5359, 5362, 4648, 5363, 5105, 5203, 5233, 5226, 5382, 5436, 5487, 5811, 5830, 5849, 5868, 5457, 5887, 5560, 5906, 5572, 5620, 5925, 5945, 5182, 4651, 4596, 5229, 5276, 5284, 4550, 5351, 5406, 5416, 5216, 5432, 5265, 5347, 5286, 5379, 5433, 5463, 5593, 5647, 5612, 5631, 5741, 5594, 5749, 5990, 6009, 6028, 6047, 5783, 5655, 6066, 5788, 6085, 5479, 5574, 5807, 5601, 5835, 6104, 6124, 5245, 4489, 4390, 5343, 5414, 5440, 4279, 5632, 5634, 5708, 5381, 5711, 5459, 5442, 5546, 5462, 5716, 5878, 5897, 6169, 6188, 6207, 6226, 5918, 6245, 6002, 6264, 6014, 6062, 6283, 6303, 5467, 4207, 4149, 5415, 5527, 5638, 4060, 5723, 5731, 5734, 5515, 5740, 5581, 5640, 5600, 5539, 5741, 6348, 6367, 6386, 6405, 6424, 6443, 6462, 6481, 6500, 6519, 6538, 6557, 6577, 5543, 5595, 5616, 5645, 5647, 3997, 5692, 3960, 3760, 5749, 4737, 3631, 5837, 5856, 6035, 6092, 6108, 6176, 6194, 6214, 6233, 6252, 6271, 6287, 6619, 6661, 4868, 5742, 3563, 5758, 5760, 5780, 5765, 5782, 0, 4584, 5785, 6706, 6725, 6744, 6763, 6782, 6801, 6820, 6839, 6858, 6877, 6896, 6915, 5699, 5790, 5560, 5804, 5825, 3475, 5847, 3293, 5856, 5866, 5903, 5826, 5875, 5924, 6355, 5929, 6016, 6195, 6371, 6054, 6393, 6934, 6953, 6972, 6991, 7010, 7029, 7048, 7067, 6043, 6412, 7086, 7105, 7124, 7143, 5959, 5904, 5760, 6054, 5988, 2998, 6004, 2916, 6045, 6061, 6023, 5840, 6082, 7162, 7181, 7200, 7219, 7238, 7257, 7276, 7295, 7314, 7333, 7352, 7371, 6138, 6042, 6052, 6084, 6080, 2621, 6145, 2562, 6159, 6183, 6164, 5845, 6202, 7390, 6431, 7409, 7428, 5820, 6220, 2425, 2249, 2110, 5908, 5980, 5985, 6063, 5609, 6178, 6450, 6469, 0, 6259, 6197, 2047, 6204, 0, 0, 0, 0, 5390, 1955, 7447, 7466, 7485, 6240, 5785, 6262, 1693, 6317, 6343, 6345, 6347, 6379, 5070, 6381, 6488, 6507, 6526, 6545, 6561, 6622, 6634, 6640, 7504, 6664, 7523, 7542, 6676, 6680, 6713, 6732, 6400, 6224, 6362, 1648, 6419, 6438, 6457, 6476, 6495, 6514, 6535, 7561, 7580, 7599, 6610, 6241, 6422, 1593, 6536, 6617, 6623, 6624, 6629, 6618, 6642, 7618, 6684, 7637, 7656, 6020, 6230, 6364, 6639, 1547, 6751, 6770, 5768, 0, 0, 5887, 1504, 7675, 7694, 7713, 6643, 6659, 6673, 6200, 1380, 6789, 6808, 7732, 6827, 7751, 7770, 6667, 6683, 6699, 6360, 1338, 7789, 7808, 7827, 6724, 6701, 6720, 6396, 1279, 7846, 7865, 7884, 7903, 6440, 1184, 6846, 6865, 6884, 6903, 0, 6459, 7922, 7941, 7960, 7979, 6739, 6663, 6922, 6941, 7998, 8017, 8036, 8055, 6758, 6761, 8074, 8093, 8112, 8131, 6777, 6796, 6478, 0, 6815, 6960, 6979, 6998, 7017, 6834, 6853,10354, 8151, 8157, 8163, 8169, 8175, 8181, 8187, 1179, 8193, 8199, 1058, 8205, 8207, 982, 8213, 893, 8219, 8225, 8231, 8237, 8243, 8249, 8255, 8261, 8267, 8273, 8279, 8285, 8291, 8297, 8303, 8309, 8315, 8321, 8327, 8333, 8339, 8345, 8351, 8357, 8363, 8369, 8375, 8381, 8387, 8393, 8399, 8405, 8411, 8417, 710, 508, 8423, 8425, 8431, 440, 353, 8437, 8443, 8449, 8455, 8461, 8467, 8473, 8479, 8485, 8491, 8497, 8503, 8509, 8515, 8521, 8527, 8533, 8539, 8545, 8551, 8557, 8563, 8569, 8575, 8581, 8587, 8593, 8599, 8605, 8611, 8617, 8623, 8629, 8635, 8641, 8647, 8653, 8659, 8665, 8671, 8677, 8683, 8689, 8695, 8701, 8707, 237, 8713, 8719, 8725, 8731, 8733, 8739, 8745, 8751, 8757, 8763, 8769, 8775, 8781, 8787, 8793, 8799, 8805, 8811, 8817, 8823, 8829, 8835, 8841, 8847, 8853, 8859, 8865, 8871, 8877, 8883, 8889, 8895, 8901, 8907, 8913, 8919, 8925, 8931, 8937, 8943, 8949, 8955, 8961, 8967, 8973, 8979, 8985, 8991, 8997, 9003, 9009, 9015, 9021, 9027, 9033, 9039, 9045, 9051, 9053, 9059, 9065, 9071, 9077, 9083, 9089, 9095, 9101, 9107, 9113, 9119, 9125, 9131, 9137, 9143, 9149, 9155, 9161, 9167, 9173, 9179, 9185, 9191, 9197, 9203, 9209, 9215, 9221, 9227, 9233, 9239, 9245, 9251, 9257, 9263, 9269, 9275, 9281, 9287, 9293, 9299, 9305, 9311, 9317, 9323, 9329, 9335, 9337, 9343, 9349, 9355, 9361, 9367, 9373, 9379, 9385, 9391, 9397, 9403, 9409, 9415, 9421, 9427, 9433, 9439, 9445, 9451, 9457, 9463, 9469, 9475, 9481, 9487, 9493, 9499, 9505, 9511, 9517, 9523, 9529, 9535, 9541, 9547, 9553, 9559, 9565, 9571, 9577, 9583, 9585, 9591, 9597, 9603, 9609, 9615, 9621, 9627, 9633, 9639, 9645, 9651, 9657, 9663, 9669, 9675, 9681, 9687, 9693, 9699, 9705, 9711, 9717, 9723, 9729, 9735, 9741, 9747, 9753, 9759, 9765, 9767, 9773, 9779, 9785, 9791, 9797, 9803, 9809, 9815, 9821, 9827, 9833, 9839, 9845, 9851, 9857, 9863, 9869, 9875, 9881, 9887, 9893, 9899, 9905, 9911, 9917, 9923, 9929, 9935, 9941, 9947, 9953, 9959, 9965, 9971, 9977, 9983, 9989, 9995,10001,10007,10013,10019,10025,10027, 10033,10039,10045,10051,10057,10063,10069,10075,10081,10087, 10093,10099,10105,10111,10117,10123,10129,10135,10141,10147, 10153,10159,10165,10171,10177,10183,10189,10195,10201,10207, 10213,10219,10225,10231,10237,10243,10249,10255,10261,10263, 10269,10275,10281,10287,10293,10299,10305,10311,10317,10323, 10329,10335,10341,10347 } ; static yyconst flex_int16_t yy_def[2365] = { 0, 1982, 1, 1982, 3, 1982, 5, 1982, 7, 1982, 9, 1982, 1983, 1982, 1982, 1982, 1984, 1985, 1986, 1987, 1988, 1987, 21, 1983, 1983, 1982, 1983, 1989, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 1983, 1983, 1982, 1990, 1991, 1992, 1993, 1994, 1993, 1993, 1982, 1982, 1995, 1982, 1996, 1997, 1995, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 1982, 1982, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2003, 85, 1999, 1999, 1982, 1999, 1982, 2005, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 1999, 1999, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2011, 118, 2007, 2007, 1982, 2007, 2013, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 2007, 2007, 2014, 2015, 2016, 2017, 2018, 2019, 2018, 149, 2014, 2014, 1982, 2014, 2020, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 2014, 2014, 1983, 1982, 1982, 2021, 2022, 2023, 1983, 2024, 2025, 1983, 2024, 2026, 2027, 2026, 2028, 2029, 2028, 1983, 1983, 1982, 2030, 2031, 2032, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 2033, 2034, 2035, 1982, 1982, 2025, 2027, 2029, 1982, 1982, 2036, 2037, 2038, 2039, 2036, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 1999, 2040, 2041, 2042, 1999, 2043, 1999, 2043, 2044, 2044, 2045, 2045, 1999, 1999, 1982, 1999, 2046, 1982, 2047, 2048, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 2049, 2050, 2051, 2052, 2049, 2053, 2054, 2049, 2053, 2055, 2055, 2056, 2057, 2056, 2049, 2049, 1982, 2058, 2059, 2060, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 2061, 2062, 2063, 2064, 2061, 2065, 2061, 2065, 2066, 2066, 2067, 2067, 2061, 2061, 1982, 2068, 2069, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 2070, 2071, 2072, 2073, 2074, 2075, 2070, 2076, 2077, 2078, 2079, 2080, 2077, 2077, 2081, 2082, 1982, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 2083, 2084, 2085, 2086, 2071, 2087, 1982, 2088, 2089, 2090, 1982, 1982, 2091, 2091, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 477, 2092, 2093, 2094, 2095, 2096, 2092, 2097, 2098, 2099, 2100, 2101, 2098, 2098, 2102, 1982, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 2103, 2104, 2105, 2106, 2107, 2108, 2103, 2109, 2110, 1982, 2111, 2112, 2113, 2114, 2115, 2110, 2110, 2116, 1982, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 2117, 2118, 2119, 2120, 2121, 2117, 2122, 2123, 2124, 2125, 2126, 2123, 2123, 2127, 1982, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 2128, 1982, 2129, 2130, 2131, 2132, 2129, 2133, 2134, 2135, 2133, 2131, 2136, 2137, 2138, 2139, 2128, 1982, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 2140, 2141, 2130, 2142, 2134, 2140, 2143, 2144, 1982, 2145, 2145, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 725, 2146, 2147, 2148, 2149, 2147, 2150, 2151, 2150, 2148, 2152, 2153, 2154, 2146, 1982, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 2155, 1982, 2156, 2157, 2158, 2159, 2156, 2160, 2161, 2162, 2160, 2158, 2163, 2164, 2165, 2166, 2167, 2168, 2155, 1982, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 2169, 2170, 2171, 2172, 2170, 2173, 2174, 2173, 2171, 2175, 2176, 2177, 2169, 1982, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 2178, 2179, 2180, 2178, 2181, 2182, 2183, 2182, 2184, 2185, 2186, 2187, 1982, 925, 925, 925, 925, 925, 2188, 925, 2188, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 2189, 2179, 2190, 2183, 2191, 2192, 2193, 2193, 966, 966, 966, 966, 1982, 966, 1982, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 966, 2194, 2195, 2194, 2196, 2197, 2197, 2198, 2199, 2200, 1982, 1008, 1008, 1008, 1008, 1008, 2201, 1008, 2201, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 2202, 2203, 2204, 2205, 2203, 2206, 2205, 2207, 2208, 2209, 2210, 2208, 2210, 2211, 2212, 2213, 2212, 2214, 1982, 1060, 1060, 1060, 1060, 1060, 2215, 1060, 2215, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 2216, 2217, 2216, 2218, 2219, 2219, 2220, 2221, 2222, 1982, 1103, 1103, 1103, 1103, 1103, 2223, 1103, 2223, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 2224, 2224, 2225, 2226, 2227, 2225, 2227, 2228, 2192, 2229, 1982, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 2229, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 2230, 2230, 2231, 2232, 2233, 2231, 2233, 2234, 1982, 2235, 2235, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1982, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 1185, 2236, 2236, 2237, 2238, 2239, 2237, 2239, 2240, 2241, 1982, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 2241, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 2242, 2209, 2243, 2244, 2245, 2242, 2246, 2246, 2247, 2248, 2249, 2209, 2250, 2247, 2250, 2251, 2252, 1982, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 2252, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 2218, 2218, 2253, 2254, 2220, 2253, 2220, 2255, 2223, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 2223, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 2225, 2231, 2256, 2225, 2226, 2232, 2257, 2258, 2226, 2228, 2234, 2259, 2228, 2260, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 2261, 1147, 2261, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 2262, 2231, 2263, 2264, 2232, 2265, 2234, 2266, 2266, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1982, 1377, 1982, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 1377, 2267, 2268, 2267, 2269, 2270, 2271, 2269, 2272, 2273, 2272, 1982, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 2274, 1410, 2274, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 2275, 2275, 2276, 2277, 2247, 2276, 2278, 2247, 2279, 2277, 2280, 2281, 2279, 2282, 2276, 2282, 2283, 2284, 2283, 2285, 2284, 1982, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 2286, 1455, 2286, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 2287, 2288, 2287, 2289, 2290, 2291, 2289, 2292, 2293, 2292, 1982, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 2294, 1489, 2294, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 2295, 2262, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2299, 2300, 2297, 2302, 2303, 2302, 2298, 2304, 2304, 1982, 1531, 2305, 2305, 1531, 1531, 1531, 2305, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 2262, 2306, 2307, 2308, 2309, 2309, 2301, 2307, 2303, 2308, 2310, 2310, 1982, 1982, 1560, 1560, 1560, 1982, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 1560, 2311, 2311, 2312, 2313, 2314, 2315, 2316, 2315, 2316, 2313, 2317, 2317, 2314, 1982, 1590, 2318, 2318, 1590, 1590, 1590, 2318, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 2319, 2320, 2321, 2322, 2323, 2324, 2319, 2324, 2325, 2326, 2327, 2328, 2329, 2322, 2328, 2329, 2326, 2330, 2331, 2332, 2330, 2332, 2327, 1982, 1631, 2333, 2333, 1631, 1631, 1631, 2333, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 2334, 2334, 2335, 2336, 2337, 2338, 2339, 2338, 2339, 2336, 2340, 2340, 2337, 1982, 1662, 2341, 2341, 1662, 1662, 1662, 2341, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 2342, 2342, 2342, 2343, 2344, 2344, 2343, 2344, 2345, 2343, 2345, 2345, 1982, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 2346, 2346, 2346, 2347, 2348, 2348, 2347, 2348, 2349, 2347, 2349, 2349, 2350, 2350, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 2351, 2351, 2351, 2352, 2313, 2313, 2352, 2313, 2314, 2352, 2314, 2314, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 2319, 2320, 2323, 2331, 2321, 2321, 2322, 2323, 2325, 2325, 2325, 2353, 2326, 2326, 2353, 2326, 2330, 2331, 2327, 2353, 2327, 2327, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 2335, 2335, 2335, 2354, 2336, 2336, 2354, 2336, 2337, 2354, 2337, 2337, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 2343, 2347, 2355, 2343, 1692, 1692, 1692, 2356, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 2357, 2347, 1718, 1718, 1718, 1982, 1718, 1718, 1718, 1718, 1718, 1718, 1718, 2352, 2358, 2352, 1590, 1590, 1590, 2359, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 2320, 2320, 2320, 2360, 2323, 2323, 2360, 2323, 2353, 2360, 2361, 2353, 2331, 2360, 2331, 2331, 1631, 1631, 1631, 2362, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 2354, 2363, 2354, 1662, 1662, 1662, 2341, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 2355, 2357, 2355, 2343, 1692, 1692, 1692, 1692, 2356, 2357, 2347, 1718, 1718, 1718, 1718, 1982, 2358, 2358, 2352, 1590, 1590, 1590, 1590, 2359, 2364, 2360, 2361, 2364, 2361, 2353, 1631, 1631, 1631, 1631, 2362, 2363, 2363, 2354, 1662, 1662, 1662, 1662, 2341, 2343, 2343, 2343, 2343, 1692, 1692, 2347, 2347, 2347, 2347, 1718, 1718, 2352, 2352, 2352, 2352, 1590, 1590, 2364, 2360, 2353, 2353, 2353, 2353, 1631, 1631, 2354, 2354, 2354, 2354, 1662, 1662, 1692, 1718, 1590, 2360, 2360, 2360, 2360, 1631, 1662, 0, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982 } ; static yyconst flex_int16_t yy_nxt[10401] = { 0, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 12, 26, 12, 16, 12, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 25, 25, 37, 38, 25, 25, 39, 25, 40, 41, 42, 43, 25, 25, 44, 45, 19, 46, 13, 14, 15, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 46, 57, 46, 58, 46, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 56, 56, 69, 70, 56, 56, 71, 56, 72, 73, 74, 75, 56, 56, 76, 77, 78, 79, 13, 14, 15, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 79, 90, 79, 91, 79, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 89, 89, 102, 103, 89, 89, 104, 89, 105, 106, 107, 108, 89, 89, 109, 110, 111, 112, 13, 14, 15, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 112, 123, 112, 113, 112, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 122, 122, 134, 135, 122, 122, 136, 122, 137, 138, 139, 140, 122, 122, 141, 142, 116, 143, 13, 14, 15, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 143, 154, 143, 144, 143, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 153, 153, 165, 166, 153, 153, 167, 153, 168, 169, 170, 171, 153, 153, 172, 173, 147, 175, 175, 175, 175, 175, 175, 175, 176, 175, 174, 186, 227, 186, 200, 174, 174, 178, 174, 179, 178, 174, 174, 201, 180, 174, 174, 236, 174, 174, 182, 182, 182, 230, 183, 189, 189, 189, 210, 740, 202, 187, 183, 203, 211, 212, 231, 184, 196, 196, 196, 236, 190, 174, 174, 178, 174, 508, 186, 204, 186, 174, 174, 205, 174, 214, 183, 174, 174, 215, 180, 174, 174, 216, 174, 174, 197, 198, 218, 217, 227, 221, 228, 227, 230, 199, 222, 229, 278, 296, 196, 196, 196, 297, 233, 219, 236, 236, 223, 174, 174, 174, 243, 439, 440, 236, 174, 174, 275, 174, 345, 244, 174, 174, 346, 180, 174, 174, 227, 174, 174, 236, 236, 236, 236, 247, 236, 249, 239, 248, 245, 227, 236, 246, 227, 236, 227, 227, 236, 236, 294, 229, 253, 295, 174, 174, 174, 236, 254, 255, 177, 174, 174, 178, 174, 179, 178, 174, 174, 193, 180, 194, 174, 177, 174, 174, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 174, 174, 178, 226, 302, 186, 227, 186, 228, 227, 303, 304, 226, 229, 237, 227, 238, 228, 227, 236, 236, 180, 229, 236, 236, 250, 238, 292, 236, 310, 236, 236, 236, 391, 236, 236, 293, 392, 251, 236, 256, 697, 252, 236, 239, 261, 311, 236, 236, 236, 236, 263, 343, 239, 226, 344, 236, 227, 236, 228, 227, 186, 262, 186, 229, 237, 341, 238, 389, 264, 236, 390, 240, 241, 265, 342, 236, 236, 236, 236, 236, 242, 267, 289, 290, 236, 266, 443, 236, 306, 268, 328, 291, 307, 227, 239, 257, 308, 236, 236, 258, 444, 351, 309, 259, 338, 339, 236, 352, 353, 260, 269, 236, 477, 340, 387, 269, 269, 271, 269, 272, 271, 269, 269, 388, 273, 269, 269, 359, 269, 269, 182, 182, 182, 313, 275, 189, 189, 189, 314, 337, 337, 337, 275, 362, 360, 230, 405, 276, 363, 230, 315, 927, 280, 269, 269, 271, 269, 325, 231, 233, 364, 269, 269, 406, 269, 355, 193, 269, 269, 356, 273, 269, 269, 357, 269, 269, 324, 324, 324, 358, 325, 330, 330, 330, 397, 182, 182, 182, 325, 373, 398, 399, 186, 326, 186, 175, 175, 175, 331, 269, 269, 269, 374, 196, 196, 196, 269, 269, 435, 269, 436, 236, 269, 269, 480, 273, 269, 269, 471, 269, 269, 373, 376, 189, 189, 189, 384, 385, 401, 180, 373, 231, 402, 437, 236, 386, 403, 175, 175, 175, 378, 438, 404, 500, 269, 269, 269, 236, 694, 479, 270, 269, 269, 271, 269, 272, 271, 269, 269, 283, 284, 285, 269, 286, 269, 269, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 269, 269, 287, 269, 236, 492, 226, 270, 269, 269, 271, 269, 272, 271, 269, 269, 286, 284, 269, 269, 286, 269, 269, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 269, 269, 287, 269, 186, 180, 186, 271, 269, 269, 271, 269, 271, 271, 269, 269, 478, 284, 269, 269, 408, 269, 269, 236, 704, 409, 182, 182, 182, 473, 183, 423, 182, 182, 182, 456, 422, 410, 457, 233, 458, 481, 488, 184, 236, 236, 269, 269, 318, 184, 486, 487, 236, 318, 318, 320, 318, 321, 320, 318, 318, 236, 322, 318, 318, 494, 318, 318, 189, 189, 189, 189, 189, 189, 236, 183, 493, 236, 424, 196, 196, 196, 236, 180, 482, 190, 483, 236, 190, 753, 484, 318, 318, 320, 318, 495, 236, 183, 485, 318, 318, 236, 318, 496, 490, 318, 318, 681, 322, 318, 318, 180, 318, 318, 227, 236, 228, 227, 491, 226, 497, 229, 227, 236, 228, 227, 236, 700, 236, 229, 227, 502, 539, 227, 498, 227, 227, 318, 318, 318, 229, 236, 507, 239, 318, 318, 540, 318, 499, 236, 318, 318, 227, 322, 318, 318, 501, 318, 318, 236, 239, 503, 509, 180, 504, 236, 505, 236, 510, 186, 236, 186, 531, 533, 532, 535, 536, 186, 584, 186, 585, 534, 318, 318, 318, 588, 589, 683, 319, 318, 318, 320, 318, 321, 320, 318, 318, 334, 322, 335, 318, 319, 318, 318, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 318, 318, 320, 367, 186, 238, 186, 569, 367, 367, 369, 367, 370, 369, 367, 367, 569, 371, 367, 367, 570, 367, 367, 182, 182, 182, 573, 275, 182, 182, 182, 520, 519, 180, 189, 189, 189, 637, 638, 552, 276, 275, 553, 284, 554, 276, 367, 367, 369, 367, 186, 280, 186, 180, 367, 367, 680, 367, 586, 682, 367, 367, 788, 371, 367, 367, 587, 367, 367, 189, 189, 189, 196, 196, 196, 180, 521, 572, 324, 324, 324, 227, 325, 337, 337, 337, 280, 324, 324, 324, 275, 571, 367, 367, 367, 326, 186, 592, 186, 367, 367, 325, 367, 685, 326, 367, 367, 180, 371, 367, 367, 593, 367, 367, 330, 330, 330, 330, 330, 330, 605, 325, 635, 606, 574, 607, 633, 641, 634, 180, 636, 331, 684, 949, 331, 686, 180, 367, 367, 367, 193, 642, 707, 368, 367, 367, 369, 367, 370, 369, 367, 367, 381, 371, 382, 367, 368, 367, 367, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 367, 367, 369, 174, 186, 186, 186, 186, 174, 174, 178, 174, 179, 178, 174, 174, 180, 180, 174, 174, 226, 174, 174, 182, 182, 182, 688, 373, 182, 182, 182, 622, 621, 180, 189, 189, 189, 677, 180, 654, 374, 373, 655, 180, 656, 374, 174, 174, 178, 174, 180, 378, 679, 696, 174, 174, 180, 174, 691, 1973, 174, 174, 180, 180, 174, 174, 705, 174, 174, 189, 189, 189, 196, 196, 196, 180, 623, 180, 414, 414, 414, 182, 182, 182, 687, 183, 378, 662, 695, 710, 373, 180, 174, 174, 413, 414, 414, 414, 184, 416, 413, 180, 417, 708, 418, 413, 413, 689, 419, 413, 413, 698, 413, 420, 665, 665, 665, 690, 666, 670, 670, 670, 180, 667, 180, 180, 666, 180, 671, 180, 620, 668, 699, 703, 180, 712, 672, 413, 413, 174, 702, 701, 706, 177, 174, 174, 178, 174, 179, 178, 174, 174, 193, 180, 194, 174, 177, 174, 174, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 174, 174, 178, 414, 414, 414, 414, 568, 465, 414, 180, 466, 180, 467, 414, 414, 663, 468, 414, 414, 720, 414, 469, 414, 414, 414, 675, 675, 675, 711, 709, 180, 662, 721, 180, 676, 673, 180, 189, 189, 189, 692, 715, 236, 666, 183, 414, 414, 226, 518, 230, 227, 725, 228, 227, 190, 693, 714, 229, 237, 715, 238, 713, 231, 715, 716, 718, 230, 236, 236, 236, 727, 236, 717, 719, 742, 236, 233, 726, 236, 728, 236, 743, 729, 236, 236, 731, 733, 236, 239, 226, 236, 736, 227, 236, 228, 227, 734, 730, 732, 229, 237, 758, 238, 737, 236, 236, 735, 236, 741, 744, 739, 236, 236, 236, 746, 236, 476, 745, 738, 747, 236, 748, 236, 236, 750, 752, 751, 236, 749, 236, 239, 269, 236, 236, 284, 754, 269, 269, 271, 269, 272, 271, 269, 269, 757, 273, 269, 269, 236, 269, 269, 756, 236, 236, 414, 414, 414, 284, 775, 759, 675, 675, 675, 760, 665, 665, 665, 284, 762, 770, 284, 773, 470, 763, 269, 269, 271, 269, 762, 284, 284, 764, 269, 269, 186, 269, 186, 284, 269, 269, 774, 273, 269, 269, 777, 269, 269, 670, 670, 670, 414, 414, 414, 284, 762, 284, 766, 779, 781, 760, 284, 776, 778, 768, 767, 421, 771, 804, 797, 284, 269, 269, 511, 414, 414, 414, 284, 513, 511, 284, 514, 284, 515, 511, 511, 780, 516, 511, 511, 791, 511, 517, 182, 182, 182, 284, 275, 189, 189, 189, 284, 785, 284, 284, 275, 782, 284, 789, 783, 276, 790, 620, 284, 793, 280, 511, 511, 269, 784, 796, 800, 270, 269, 269, 271, 269, 272, 271, 269, 269, 283, 284, 285, 269, 286, 269, 269, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 269, 269, 287, 269, 929, 193, 568, 270, 269, 269, 271, 269, 272, 271, 269, 269, 286, 284, 269, 269, 286, 269, 269, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 269, 269, 287, 269, 284, 518, 284, 271, 269, 269, 271, 269, 271, 271, 269, 269, 786, 284, 269, 269, 284, 269, 269, 284, 792, 284, 284, 284, 284, 284, 284, 787, 284, 801, 721, 284, 794, 284, 806, 824, 795, 826, 799, 715, 798, 805, 269, 269, 318, 803, 808, 573, 570, 318, 318, 320, 318, 321, 320, 318, 318, 802, 322, 318, 318, 807, 318, 318, 561, 561, 561, 812, 812, 812, 322, 813, 322, 809, 322, 322, 814, 324, 324, 324, 837, 325, 236, 322, 815, 1208, 828, 318, 318, 320, 318, 186, 322, 186, 326, 318, 318, 829, 318, 830, 322, 318, 318, 322, 322, 318, 318, 832, 318, 318, 817, 817, 817, 561, 561, 561, 322, 813, 322, 818, 834, 322, 809, 825, 831, 833, 820, 819, 840, 852, 822, 822, 822, 318, 318, 560, 561, 561, 561, 823, 563, 560, 322, 564, 836, 565, 560, 560, 813, 566, 560, 560, 322, 560, 567, 330, 330, 330, 835, 322, 322, 843, 325, 322, 322, 838, 322, 322, 322, 322, 845, 948, 331, 856, 848, 839, 193, 855, 560, 560, 318, 851, 849, 846, 319, 318, 318, 320, 318, 321, 320, 318, 318, 334, 322, 335, 318, 319, 318, 318, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 318, 318, 320, 367, 322, 322, 322, 322, 367, 367, 369, 367, 370, 369, 367, 367, 841, 371, 367, 367, 322, 367, 367, 322, 850, 847, 322, 322, 322, 322, 844, 842, 322, 371, 322, 861, 322, 371, 371, 853, 1913, 371, 854, 858, 880, 860, 367, 367, 369, 367, 859, 877, 863, 857, 367, 367, 878, 367, 371, 371, 367, 367, 862, 371, 367, 367, 882, 367, 367, 414, 414, 414, 665, 665, 665, 186, 866, 186, 864, 371, 371, 867, 879, 881, 182, 182, 182, 941, 373, 868, 886, 193, 367, 367, 613, 414, 414, 414, 892, 615, 613, 374, 616, 371, 617, 613, 613, 875, 618, 613, 613, 371, 613, 619, 670, 670, 670, 414, 414, 414, 371, 866, 371, 870, 371, 371, 864, 939, 884, 893, 872, 871, 470, 371, 894, 897, 889, 613, 613, 367, 895, 901, 193, 368, 367, 367, 369, 367, 370, 369, 367, 367, 381, 371, 382, 367, 368, 367, 367, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 367, 367, 369, 413, 414, 414, 414, 371, 413, 413, 371, 413, 371, 418, 413, 413, 371, 419, 413, 413, 371, 413, 413, 675, 675, 675, 189, 189, 189, 899, 890, 371, 874, 373, 371, 883, 896, 1904, 885, 371, 887, 866, 371, 378, 900, 891, 413, 413, 174, 371, 888, 371, 371, 174, 174, 898, 174, 905, 371, 174, 174, 902, 180, 174, 174, 903, 174, 174, 371, 371, 371, 371, 908, 930, 371, 193, 904, 910, 906, 665, 665, 665, 955, 666, 193, 932, 1056, 909, 667, 907, 193, 174, 174, 174, 912, 1042, 668, 177, 174, 174, 178, 174, 179, 178, 174, 174, 193, 678, 194, 174, 177, 174, 174, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 174, 174, 178, 414, 414, 414, 414, 371, 414, 414, 943, 414, 193, 467, 414, 414, 421, 468, 414, 414, 715, 414, 414, 936, 193, 716, 914, 914, 914, 715, 915, 718, 186, 717, 186, 911, 414, 414, 414, 719, 665, 665, 665, 916, 917, 662, 414, 414, 226, 667, 180, 227, 928, 228, 227, 924, 934, 668, 723, 237, 935, 238, 670, 670, 670, 919, 919, 919, 193, 666, 1151, 671, 915, 193, 670, 670, 670, 952, 193, 672, 931, 921, 920, 671, 923, 923, 923, 933, 951, 239, 226, 672, 193, 227, 937, 228, 227, 675, 675, 675, 229, 237, 915, 238, 931, 193, 676, 193, 193, 938, 193, 944, 193, 193, 724, 666, 942, 193, 945, 953, 193, 946, 193, 947, 193, 954, 193, 931, 994, 193, 967, 239, 511, 414, 414, 414, 193, 511, 511, 236, 511, 956, 515, 511, 511, 236, 516, 511, 511, 193, 511, 511, 193, 193, 958, 465, 959, 959, 466, 961, 663, 963, 968, 718, 716, 971, 962, 969, 236, 469, 960, 719, 717, 236, 972, 511, 511, 269, 236, 970, 973, 236, 269, 269, 974, 269, 975, 979, 269, 269, 236, 273, 269, 269, 977, 269, 269, 976, 236, 978, 236, 236, 236, 981, 236, 236, 991, 236, 236, 982, 236, 983, 984, 236, 236, 985, 1903, 236, 986, 236, 269, 269, 269, 987, 236, 236, 270, 269, 269, 271, 269, 272, 271, 269, 269, 283, 772, 285, 269, 286, 269, 269, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 269, 269, 287, 560, 561, 561, 561, 988, 560, 560, 992, 560, 236, 565, 560, 560, 989, 566, 560, 560, 993, 560, 560, 236, 995, 236, 971, 236, 996, 186, 971, 186, 236, 236, 998, 1010, 236, 1012, 283, 1024, 665, 665, 665, 283, 762, 1011, 560, 560, 318, 763, 283, 236, 1007, 318, 318, 236, 318, 764, 1014, 318, 318, 283, 322, 318, 318, 1034, 318, 318, 914, 914, 914, 1018, 1000, 665, 665, 665, 1013, 1002, 283, 670, 670, 670, 763, 283, 283, 1001, 762, 1893, 766, 283, 764, 318, 318, 318, 283, 1015, 767, 319, 318, 318, 320, 318, 321, 320, 318, 318, 334, 827, 335, 318, 319, 318, 318, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 318, 318, 320, 613, 414, 414, 414, 1016, 613, 613, 1891, 613, 1017, 617, 613, 613, 1022, 618, 613, 613, 1020, 613, 613, 919, 919, 919, 670, 670, 670, 283, 1000, 283, 283, 1005, 283, 766, 414, 414, 414, 1031, 1004, 1019, 283, 767, 283, 760, 613, 613, 367, 1021, 283, 1025, 283, 367, 367, 1026, 367, 283, 1032, 367, 367, 180, 371, 367, 367, 283, 367, 367, 675, 675, 675, 923, 923, 923, 1027, 1035, 283, 770, 1028, 1063, 283, 1029, 283, 1030, 283, 1037, 762, 1036, 1171, 1000, 283, 367, 367, 367, 283, 334, 283, 368, 367, 367, 369, 367, 370, 369, 367, 367, 381, 876, 382, 367, 368, 367, 367, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 367, 367, 369, 414, 414, 414, 1038, 416, 1039, 1042, 417, 1050, 662, 569, 283, 1083, 283, 283, 1041, 1051, 334, 420, 174, 573, 1064, 334, 177, 174, 174, 178, 174, 179, 178, 174, 174, 193, 180, 194, 174, 177, 174, 174, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 925, 193, 193, 193, 174, 174, 178, 226, 1014, 1014, 227, 1042, 228, 227, 334, 1067, 1043, 229, 237, 569, 238, 812, 812, 812, 1044, 813, 1066, 1046, 1046, 1046, 814, 1047, 570, 283, 283, 1058, 1058, 1058, 815, 1053, 1053, 1053, 965, 186, 1048, 186, 1047, 1378, 239, 226, 236, 334, 227, 1047, 228, 227, 1054, 1068, 1062, 229, 237, 1069, 238, 812, 812, 812, 1059, 1049, 817, 817, 817, 1074, 814, 334, 1065, 813, 334, 818, 334, 1070, 815, 1078, 334, 334, 966, 819, 334, 817, 817, 817, 239, 414, 414, 414, 1055, 513, 818, 334, 514, 1072, 760, 1071, 334, 1076, 819, 1073, 334, 334, 1879, 517, 269, 1077, 334, 334, 270, 269, 269, 271, 269, 272, 271, 269, 269, 283, 284, 285, 269, 286, 269, 269, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 1008, 283, 283, 283, 269, 269, 287, 561, 561, 561, 1079, 563, 334, 1080, 564, 334, 809, 561, 561, 561, 822, 822, 822, 1081, 334, 567, 809, 1082, 334, 823, 1084, 1089, 1119, 1088, 334, 1093, 381, 334, 813, 318, 334, 1877, 334, 319, 318, 318, 320, 318, 321, 320, 318, 318, 334, 322, 335, 318, 319, 318, 318, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 1060, 334, 334, 334, 318, 318, 320, 1086, 1087, 1090, 1066, 1091, 1066, 670, 670, 670, 1108, 334, 381, 334, 866, 284, 870, 334, 1107, 381, 334, 665, 665, 665, 871, 866, 414, 414, 414, 334, 867, 334, 914, 914, 914, 864, 1095, 1106, 868, 414, 414, 414, 1245, 615, 1109, 1105, 616, 1111, 864, 1096, 665, 665, 665, 381, 1097, 1117, 186, 619, 186, 867, 381, 919, 919, 919, 670, 670, 670, 868, 1095, 381, 381, 1100, 381, 870, 675, 675, 675, 1112, 1099, 1102, 1113, 871, 1115, 874, 923, 923, 923, 381, 1110, 1114, 381, 1121, 866, 381, 381, 1122, 381, 381, 381, 1116, 381, 1126, 1095, 367, 1120, 381, 381, 368, 367, 367, 369, 367, 370, 369, 367, 367, 381, 371, 382, 367, 368, 367, 367, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 1103, 381, 381, 381, 367, 367, 369, 1123, 1127, 381, 1124, 381, 1125, 381, 1129, 381, 1130, 1131, 1132, 1133, 1109, 1109, 1134, 180, 381, 381, 1136, 381, 959, 381, 381, 381, 959, 381, 914, 914, 914, 1145, 915, 186, 180, 960, 962, 1185, 236, 381, 381, 1147, 919, 919, 919, 916, 414, 414, 414, 915, 416, 1152, 180, 417, 180, 662, 914, 914, 914, 920, 1137, 923, 923, 923, 420, 919, 919, 919, 1145, 1154, 186, 180, 1141, 916, 665, 665, 665, 1148, 1138, 915, 180, 1139, 920, 667, 180, 1155, 180, 180, 1149, 180, 180, 668, 1140, 670, 670, 670, 1150, 1142, 180, 1159, 1143, 1211, 671, 180, 1852, 180, 236, 1165, 1160, 1153, 672, 1144, 174, 1156, 1162, 1163, 177, 174, 174, 178, 174, 179, 178, 174, 174, 193, 1146, 194, 174, 177, 174, 174, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 174, 174, 178, 180, 180, 180, 180, 180, 180, 180, 180, 180, 1166, 180, 1164, 284, 180, 1172, 1175, 1167, 1169, 1186, 1188, 1173, 1238, 465, 236, 1158, 466, 1161, 663, 960, 1168, 1176, 1170, 1174, 1177, 236, 716, 469, 1179, 1187, 1189, 236, 1190, 1191, 717, 1178, 1180, 236, 962, 1181, 236, 718, 971, 236, 971, 1192, 1193, 236, 1194, 719, 1182, 226, 1199, 1196, 227, 236, 228, 227, 971, 1197, 1200, 1183, 237, 1201, 238, 236, 236, 236, 236, 236, 1198, 1202, 236, 236, 236, 236, 1203, 1204, 236, 1207, 236, 1206, 236, 1210, 1209, 284, 284, 1391, 236, 236, 284, 284, 239, 226, 236, 236, 227, 236, 228, 227, 236, 1224, 284, 229, 237, 1225, 238, 914, 914, 914, 1221, 1000, 914, 914, 914, 1227, 1212, 284, 284, 1850, 284, 919, 919, 919, 1001, 1222, 1223, 1184, 1000, 1001, 923, 923, 923, 284, 239, 414, 414, 414, 1004, 513, 284, 1232, 514, 1230, 760, 919, 919, 919, 1000, 284, 1226, 284, 1216, 517, 665, 665, 665, 1228, 1213, 1233, 284, 1214, 1004, 763, 284, 1229, 284, 284, 284, 284, 1234, 764, 1215, 670, 670, 670, 1237, 1217, 1236, 284, 1218, 1241, 766, 284, 1835, 1240, 284, 322, 1239, 1235, 767, 1219, 269, 1243, 1246, 1268, 270, 269, 269, 271, 269, 272, 271, 269, 269, 283, 1220, 285, 269, 286, 269, 269, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 269, 269, 287, 284, 284, 284, 284, 1249, 1252, 1252, 1250, 1254, 810, 1252, 1247, 1145, 1043, 186, 1259, 1386, 322, 1251, 1253, 236, 1044, 1248, 1253, 1242, 1244, 1046, 1046, 1046, 1260, 1047, 1050, 1046, 1046, 1046, 322, 1255, 1270, 1829, 1051, 1053, 1053, 1053, 1048, 561, 561, 561, 1047, 563, 1048, 1252, 564, 322, 809, 1053, 1053, 1053, 1054, 322, 1266, 1259, 1261, 567, 812, 812, 812, 322, 1256, 1269, 1271, 1257, 1054, 814, 322, 1058, 1058, 1058, 322, 322, 322, 815, 1258, 817, 817, 817, 180, 1262, 322, 322, 1263, 1277, 818, 1047, 1274, 322, 1273, 1267, 1278, 1279, 819, 1264, 318, 1272, 1547, 1282, 319, 318, 318, 320, 318, 321, 320, 318, 318, 334, 1265, 335, 318, 319, 318, 318, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 318, 318, 320, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 322, 1285, 1283, 1281, 322, 322, 371, 322, 1286, 1288, 1827, 371, 1291, 1275, 1284, 1292, 1280, 1322, 914, 914, 914, 1287, 1095, 1289, 371, 1290, 1293, 914, 914, 914, 1303, 1294, 919, 919, 919, 1096, 414, 414, 414, 1095, 615, 1308, 371, 616, 1096, 864, 919, 919, 919, 1099, 923, 923, 923, 1298, 619, 665, 665, 665, 1145, 1295, 186, 371, 1296, 1099, 867, 1304, 371, 371, 1095, 1305, 371, 371, 868, 1297, 670, 670, 670, 1306, 1299, 371, 371, 1300, 371, 870, 1384, 371, 1307, 236, 1310, 1315, 1328, 871, 1301, 367, 1311, 1309, 1318, 368, 367, 367, 369, 367, 370, 369, 367, 367, 381, 1302, 382, 367, 368, 367, 367, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 367, 367, 369, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 371, 1316, 180, 1319, 1320, 371, 1323, 371, 1325, 180, 180, 1145, 1312, 180, 1314, 1329, 1321, 1317, 180, 1346, 180, 1324, 1326, 1344, 180, 1355, 1330, 1327, 665, 665, 665, 180, 1138, 180, 1347, 1139, 1345, 667, 180, 180, 1350, 1348, 180, 1349, 1357, 668, 1140, 665, 665, 665, 1352, 1138, 1351, 180, 1139, 1353, 667, 1377, 180, 1389, 1826, 180, 1358, 236, 668, 1140, 1332, 1332, 1332, 180, 921, 180, 180, 917, 180, 1333, 1361, 1359, 236, 180, 180, 1362, 1363, 1334, 1336, 1336, 1336, 1360, 1337, 1364, 1365, 1385, 1366, 1338, 180, 1176, 1392, 1824, 1177, 1368, 716, 1339, 917, 670, 670, 670, 1367, 1142, 717, 1178, 1143, 1380, 671, 236, 1176, 1379, 236, 1177, 236, 716, 672, 1144, 1332, 1332, 1332, 236, 921, 717, 1178, 917, 963, 1333, 1371, 961, 1382, 1369, 620, 1372, 1383, 1334, 670, 670, 670, 1370, 1142, 1373, 961, 1143, 236, 671, 1180, 236, 1388, 1181, 1399, 718, 236, 672, 1144, 1341, 1341, 1341, 963, 719, 1182, 961, 1337, 1369, 1342, 1371, 1599, 1374, 283, 236, 1381, 1370, 1343, 921, 174, 1375, 963, 236, 177, 174, 174, 178, 174, 179, 178, 174, 174, 193, 931, 194, 174, 177, 174, 174, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 174, 174, 178, 1180, 620, 971, 1181, 1387, 718, 1390, 1393, 1394, 236, 971, 236, 1397, 719, 1182, 226, 1395, 1396, 227, 236, 228, 227, 284, 1398, 236, 971, 237, 284, 238, 236, 284, 236, 284, 236, 236, 284, 1411, 236, 236, 284, 284, 284, 1416, 284, 284, 284, 1422, 284, 284, 1410, 284, 1412, 1413, 284, 1427, 284, 239, 226, 284, 620, 227, 1415, 228, 227, 1414, 1417, 1420, 229, 237, 1418, 238, 1424, 284, 1423, 284, 284, 284, 284, 1042, 1425, 1433, 1426, 1428, 1043, 1056, 1429, 1430, 322, 322, 1432, 322, 1044, 1431, 1042, 1376, 1042, 1434, 1050, 239, 665, 665, 665, 1477, 1213, 1447, 1051, 1214, 1249, 763, 1253, 1250, 1457, 810, 322, 1259, 1455, 764, 1215, 665, 665, 665, 1251, 1213, 322, 322, 1214, 322, 763, 322, 1435, 1456, 568, 1436, 1460, 1043, 764, 1215, 1332, 1332, 1332, 1458, 1005, 1044, 1437, 1002, 1462, 1401, 1448, 322, 180, 1449, 1459, 1050, 322, 1402, 1336, 1336, 1336, 1461, 1404, 1051, 1450, 322, 322, 1405, 322, 322, 322, 1542, 1467, 322, 283, 1406, 1002, 670, 670, 670, 1463, 1217, 322, 322, 1218, 322, 766, 1594, 1465, 1471, 1476, 1468, 322, 1469, 767, 1219, 1332, 1332, 1332, 1470, 1005, 322, 1472, 1002, 371, 1401, 371, 1473, 371, 322, 1478, 1474, 371, 1402, 670, 670, 670, 371, 1217, 1475, 371, 1218, 371, 766, 371, 1492, 1490, 180, 1491, 371, 1497, 767, 1219, 1341, 1341, 1341, 371, 1494, 371, 1489, 1404, 1496, 1408, 1575, 1501, 568, 1495, 1493, 371, 236, 1409, 1005, 269, 1503, 1539, 1505, 270, 269, 269, 271, 269, 272, 271, 269, 269, 283, 1014, 285, 269, 286, 269, 269, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 269, 269, 287, 812, 812, 812, 371, 1256, 371, 371, 1257, 371, 814, 371, 1570, 371, 1506, 371, 371, 236, 815, 1258, 812, 812, 812, 1508, 1256, 1509, 1510, 1257, 371, 814, 1499, 963, 1502, 371, 961, 1507, 1369, 815, 1258, 1439, 1439, 1439, 1504, 1055, 1370, 1511, 1049, 568, 1440, 1371, 180, 1563, 236, 1512, 1372, 180, 1441, 1443, 1443, 1443, 1531, 1444, 1373, 961, 180, 1537, 1445, 1703, 180, 1521, 1521, 1521, 193, 1522, 1446, 1049, 817, 817, 817, 1371, 1262, 1374, 180, 1263, 180, 818, 1523, 1137, 1532, 1375, 963, 1535, 1540, 819, 1264, 1439, 1439, 1439, 180, 1055, 180, 180, 1049, 236, 1440, 1536, 1567, 180, 518, 1526, 1526, 1526, 1441, 817, 817, 817, 1522, 1262, 1543, 180, 1263, 1548, 818, 1561, 1544, 1541, 1527, 1141, 1562, 1545, 819, 1264, 1452, 1452, 1452, 180, 1514, 1514, 1514, 1444, 1141, 1453, 229, 1137, 1546, 1564, 236, 236, 1841, 1454, 1055, 318, 236, 1515, 518, 319, 318, 318, 320, 318, 321, 320, 318, 318, 334, 1066, 335, 318, 319, 318, 318, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 318, 318, 320, 665, 665, 665, 1179, 1295, 971, 1175, 1296, 236, 867, 1551, 1569, 518, 1552, 283, 721, 1549, 868, 1297, 665, 665, 665, 1550, 1295, 1553, 1550, 1296, 1369, 867, 236, 1554, 1598, 1565, 1568, 1725, 1370, 868, 1297, 1332, 1332, 1332, 1554, 1100, 1555, 1175, 1097, 236, 1480, 1556, 236, 283, 1557, 1179, 1372, 1566, 1481, 1336, 1336, 1336, 971, 1483, 1373, 961, 1595, 1571, 1484, 971, 971, 1605, 283, 1558, 236, 1374, 1485, 1097, 670, 670, 670, 236, 1299, 1375, 963, 1300, 236, 870, 1573, 283, 1574, 470, 283, 236, 236, 871, 1301, 1332, 1332, 1332, 1576, 1100, 236, 1591, 1097, 236, 1480, 1828, 1592, 1600, 236, 1593, 283, 1014, 1481, 670, 670, 670, 283, 1299, 1597, 283, 1300, 283, 870, 193, 1603, 1521, 1521, 1521, 283, 1584, 871, 1301, 1341, 1341, 1341, 1014, 283, 283, 1014, 1483, 283, 1487, 1585, 1212, 1606, 283, 1601, 1602, 283, 1488, 1100, 1332, 1332, 1332, 1014, 921, 1694, 283, 917, 193, 1333, 1607, 470, 334, 283, 1526, 1526, 1526, 1334, 1332, 1332, 1332, 1584, 1516, 470, 1633, 1516, 1632, 1333, 1610, 1634, 334, 1588, 1216, 1611, 334, 1334, 1336, 1336, 1336, 334, 1337, 1612, 1254, 1635, 334, 1338, 334, 1435, 1648, 1640, 1436, 334, 1043, 1339, 917, 675, 675, 675, 334, 1517, 1044, 1437, 1518, 1639, 676, 1514, 1514, 1514, 334, 1216, 1066, 1636, 1212, 1519, 1336, 1336, 1336, 334, 1524, 229, 334, 334, 1578, 1338, 1435, 1641, 1642, 1436, 1643, 1043, 334, 1339, 917, 1341, 1341, 1341, 1260, 1044, 1437, 1254, 1337, 1608, 1342, 1260, 1644, 1833, 1254, 1638, 1608, 1609, 1343, 921, 1341, 1341, 1341, 1260, 1609, 334, 1254, 1528, 1608, 1342, 1621, 1621, 1621, 1066, 1622, 1720, 1609, 1343, 921, 226, 1646, 334, 227, 334, 228, 227, 236, 1623, 1255, 229, 237, 1610, 238, 1614, 1614, 1614, 1611, 1261, 1448, 1559, 1255, 1449, 421, 1050, 1612, 1254, 1610, 334, 1625, 1066, 1615, 1051, 1450, 1066, 381, 1647, 1626, 1260, 1679, 334, 239, 226, 381, 334, 227, 1448, 228, 227, 1449, 381, 1050, 229, 237, 1610, 238, 1625, 1663, 381, 1051, 1450, 1628, 1628, 1628, 1626, 1260, 1678, 1670, 1622, 421, 1514, 1514, 1514, 1671, 1298, 381, 1560, 1294, 1629, 1261, 1664, 381, 1665, 239, 1332, 1332, 1332, 1650, 1005, 421, 381, 1002, 381, 1401, 1666, 1521, 1521, 1521, 1109, 1656, 1669, 1402, 1332, 1332, 1332, 193, 1579, 1693, 381, 1579, 381, 1401, 1657, 1294, 381, 381, 1526, 1526, 1526, 1402, 1336, 1336, 1336, 1656, 1404, 1109, 193, 1667, 1700, 1405, 381, 1530, 1672, 1660, 1298, 381, 381, 1406, 1002, 675, 675, 675, 381, 1580, 1675, 1673, 1581, 1695, 770, 1674, 1677, 381, 1179, 1109, 1109, 1175, 193, 1582, 1336, 1336, 1336, 1676, 1586, 381, 381, 1549, 931, 1405, 1554, 1920, 1521, 1521, 1521, 283, 1522, 1406, 1002, 1341, 1341, 1341, 1554, 1555, 1175, 931, 1404, 971, 1408, 1523, 1137, 193, 1557, 1179, 193, 1696, 1409, 1005, 1341, 1341, 1341, 1697, 1514, 1514, 1514, 1589, 1141, 1408, 193, 1137, 193, 1702, 236, 1719, 193, 1409, 1005, 269, 236, 1515, 620, 270, 269, 269, 271, 269, 272, 271, 269, 269, 283, 284, 285, 269, 286, 269, 269, 283, 283, 283, 283, 1590, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 269, 269, 287, 1439, 1439, 1439, 1698, 1055, 1721, 236, 1049, 1699, 1440, 1701, 1521, 1521, 1521, 620, 1684, 193, 1441, 1439, 1439, 1439, 193, 1616, 193, 283, 1616, 1743, 1440, 1523, 1137, 1704, 1713, 1526, 1526, 1526, 1441, 1443, 1443, 1443, 1522, 1444, 1557, 1179, 193, 1668, 1445, 1727, 236, 1705, 1527, 1141, 1705, 971, 1446, 1049, 822, 822, 822, 283, 1617, 1750, 1549, 1618, 1728, 823, 1514, 1514, 1514, 1744, 1680, 236, 283, 1680, 1619, 1443, 1443, 1443, 236, 1624, 1526, 1526, 1526, 1515, 1445, 1014, 1706, 1688, 334, 1707, 1778, 1369, 1446, 1049, 1452, 1452, 1452, 1527, 1141, 1370, 1708, 1444, 1551, 1453, 1371, 1552, 1014, 721, 283, 1372, 1745, 1454, 1055, 1452, 1452, 1452, 1553, 1373, 961, 283, 1630, 1551, 1453, 1371, 1552, 1374, 721, 283, 1746, 283, 1454, 1055, 318, 1375, 963, 1553, 319, 318, 318, 320, 318, 321, 320, 318, 318, 334, 322, 335, 318, 319, 318, 318, 334, 334, 334, 334, 1631, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 318, 318, 320, 1332, 1332, 1332, 1747, 1100, 1779, 1722, 1097, 334, 1480, 1709, 1723, 283, 1752, 1724, 1726, 283, 1481, 1332, 1332, 1332, 236, 1651, 1555, 1175, 1651, 236, 1480, 1710, 236, 236, 1711, 229, 1372, 1729, 1481, 1336, 1336, 1336, 1753, 1483, 1373, 1712, 1645, 283, 1484, 334, 1714, 1785, 236, 1715, 1912, 1374, 1485, 1097, 675, 675, 675, 1748, 1652, 1375, 1716, 1653, 568, 874, 1514, 1514, 1514, 1749, 1216, 1780, 283, 1212, 1654, 1336, 1336, 1336, 1804, 1658, 334, 381, 283, 1578, 1484, 1751, 1754, 1521, 1521, 1521, 568, 1584, 1485, 1097, 1341, 1341, 1341, 1447, 283, 283, 1434, 1483, 1066, 1487, 1585, 1212, 334, 1781, 334, 1787, 1755, 1488, 1100, 1341, 1341, 1341, 1760, 1514, 1514, 1514, 1661, 1730, 1487, 1788, 1730, 334, 1771, 1447, 334, 1637, 1488, 1100, 367, 381, 1578, 1803, 368, 367, 367, 369, 367, 370, 369, 367, 367, 381, 371, 382, 367, 368, 367, 367, 381, 381, 381, 381, 1662, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 367, 367, 369, 1332, 1332, 1332, 381, 1681, 1810, 1805, 1682, 931, 1333, 1604, 1066, 1521, 1521, 1521, 381, 1734, 1334, 1683, 1336, 1336, 1336, 1813, 1337, 1526, 1526, 1526, 381, 1338, 1585, 1212, 1584, 193, 1772, 334, 1625, 1339, 917, 1341, 1341, 1341, 1588, 1216, 1626, 1260, 1337, 1109, 1342, 283, 1756, 1447, 1847, 1756, 1434, 1608, 1343, 921, 675, 675, 675, 1760, 1517, 1609, 1755, 1518, 1109, 676, 518, 1760, 381, 1771, 1447, 1526, 1526, 1526, 1519, 675, 675, 675, 1738, 1517, 1761, 1434, 1518, 193, 676, 1820, 1762, 381, 1588, 1216, 1821, 1611, 1905, 1519, 1336, 1336, 1336, 193, 1685, 1612, 1254, 1686, 1757, 1338, 193, 1758, 1782, 1056, 1783, 1822, 1760, 1339, 1687, 1341, 1341, 1341, 1759, 1689, 518, 334, 1690, 334, 1342, 1761, 1434, 381, 1806, 381, 1812, 1596, 1343, 1691, 174, 193, 1823, 193, 177, 174, 174, 178, 174, 179, 178, 174, 174, 193, 180, 194, 174, 177, 174, 174, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 1692, 193, 193, 193, 193, 193, 174, 174, 178, 226, 1825, 193, 227, 1784, 228, 227, 1786, 283, 1846, 229, 237, 1789, 238, 1614, 1614, 1614, 334, 1261, 1807, 334, 1255, 1614, 1614, 1614, 334, 1763, 1808, 229, 1763, 1809, 1615, 381, 1717, 1572, 931, 1811, 1814, 1834, 1615, 381, 239, 226, 381, 229, 227, 229, 228, 227, 381, 381, 229, 229, 237, 229, 238, 1621, 1621, 1621, 193, 1622, 1621, 1621, 1621, 1951, 1767, 229, 1836, 229, 334, 1837, 229, 1874, 1623, 1255, 1839, 1014, 1718, 1623, 1255, 1628, 1628, 1628, 239, 1332, 1332, 1332, 1622, 1731, 1838, 470, 1732, 1840, 1401, 283, 1842, 1917, 1629, 1261, 283, 1848, 1402, 1733, 1336, 1336, 1336, 931, 1404, 1628, 1628, 1628, 1849, 1405, 283, 1706, 1773, 470, 1707, 1855, 1369, 1406, 1002, 1341, 1341, 1341, 1629, 1261, 1370, 1708, 1404, 193, 1408, 1882, 1706, 283, 283, 1707, 1896, 1369, 1409, 1005, 675, 675, 675, 421, 1580, 1370, 1708, 1581, 334, 770, 1514, 1514, 1514, 381, 1298, 283, 1851, 1294, 1582, 675, 675, 675, 421, 1580, 283, 1853, 1581, 1650, 770, 1514, 1514, 1514, 229, 1790, 283, 1854, 1790, 1582, 1336, 1336, 1336, 1952, 1735, 283, 1856, 1736, 1650, 1405, 1014, 1066, 1521, 1521, 1521, 931, 1656, 1406, 1737, 1341, 1341, 1341, 1857, 1739, 1538, 1857, 1740, 1610, 1408, 1657, 1294, 1534, 1611, 283, 334, 1755, 1409, 1741, 269, 193, 1612, 1254, 270, 269, 269, 271, 269, 272, 271, 269, 269, 283, 284, 285, 269, 286, 269, 269, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 1742, 283, 283, 283, 283, 283, 269, 269, 287, 1439, 1439, 1439, 931, 1764, 334, 1873, 1765, 931, 1440, 1533, 1876, 1521, 1521, 1521, 1530, 1794, 1441, 1766, 1443, 1443, 1443, 1109, 1444, 1526, 1526, 1526, 193, 1445, 1657, 1294, 1656, 193, 1610, 334, 1625, 1446, 1049, 1452, 1452, 1452, 1660, 1298, 1626, 1260, 1444, 1066, 1453, 1500, 1706, 334, 1878, 1707, 1945, 1369, 1454, 1055, 822, 822, 822, 1869, 1617, 1370, 1708, 1618, 1109, 823, 193, 1861, 334, 1771, 1447, 1526, 1526, 1526, 1619, 822, 822, 822, 1798, 1617, 1761, 1434, 1618, 1109, 823, 931, 1875, 381, 1660, 1298, 334, 1880, 1498, 1619, 1443, 1443, 1443, 381, 1768, 334, 1888, 1769, 1890, 1445, 620, 1558, 334, 1881, 1556, 193, 1830, 1446, 1770, 1452, 1452, 1452, 1889, 1774, 1831, 1550, 1775, 1710, 1453, 1109, 1711, 381, 1372, 334, 1883, 381, 1454, 1776, 318, 620, 1373, 1712, 319, 318, 318, 320, 318, 321, 320, 318, 318, 334, 322, 335, 318, 319, 318, 318, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 1777, 334, 334, 334, 334, 334, 318, 318, 320, 1332, 1332, 1332, 1466, 1791, 381, 1887, 1792, 1109, 1480, 1464, 1710, 381, 1892, 1711, 568, 1372, 1481, 1793, 1336, 1336, 1336, 1906, 1483, 1373, 1712, 381, 1894, 1484, 1558, 1757, 381, 1556, 1758, 1830, 1056, 1485, 1097, 1341, 1341, 1341, 229, 1831, 1550, 1759, 1483, 193, 1487, 229, 1710, 381, 1895, 1711, 1958, 1372, 1488, 1100, 675, 675, 675, 568, 1652, 1373, 1712, 1653, 1910, 874, 283, 1714, 381, 1897, 1715, 1911, 1374, 931, 1654, 675, 675, 675, 1421, 1652, 1375, 1716, 1653, 1014, 874, 1419, 1558, 193, 1902, 1556, 334, 1830, 1928, 1654, 1336, 1336, 1336, 193, 1795, 1831, 1550, 1796, 229, 1484, 518, 1714, 283, 381, 1715, 1936, 1374, 1485, 1797, 1341, 1341, 1341, 518, 1799, 1375, 1716, 1800, 1714, 1487, 470, 1715, 470, 1374, 1909, 283, 1918, 1488, 1801, 367, 1356, 1375, 1716, 368, 367, 367, 369, 367, 370, 369, 367, 367, 381, 371, 382, 367, 368, 367, 367, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 1802, 381, 381, 381, 381, 381, 367, 367, 369, 1332, 1332, 1332, 1354, 1681, 283, 1919, 1682, 1014, 1333, 1014, 1858, 1014, 421, 1859, 421, 1608, 1334, 1683, 1332, 1332, 1332, 1109, 1681, 1609, 1860, 1682, 1757, 1333, 931, 1758, 283, 1056, 283, 1966, 283, 1334, 1683, 1332, 1332, 1332, 1759, 1681, 1313, 1014, 1682, 1921, 1333, 334, 1862, 334, 1929, 1863, 193, 1611, 1334, 1683, 1816, 1816, 1816, 1109, 1528, 1612, 1864, 1524, 1066, 1817, 283, 1870, 283, 1972, 1871, 1109, 1625, 1818, 1516, 1336, 1336, 1336, 620, 1685, 1626, 1872, 1686, 381, 1338, 620, 1558, 334, 1066, 1556, 1276, 1830, 1339, 1687, 1336, 1336, 1336, 1066, 1685, 1831, 1550, 1686, 1066, 1338, 931, 1713, 334, 1930, 1709, 381, 1937, 1339, 1687, 1816, 1816, 1816, 1066, 1528, 1907, 1705, 1524, 1066, 1817, 229, 1908, 334, 568, 1908, 193, 1830, 1818, 1516, 1336, 1336, 1336, 568, 1685, 1831, 1550, 1686, 1066, 1338, 931, 1858, 334, 1252, 1859, 1974, 1608, 1339, 1687, 1341, 1341, 1341, 1252, 1689, 1609, 1860, 1690, 1066, 1342, 1014, 1858, 334, 1231, 1859, 193, 1608, 1343, 1691, 1816, 1816, 1816, 1014, 1528, 1609, 1860, 1524, 1014, 1817, 518, 1858, 334, 518, 1859, 1205, 1608, 1818, 1516, 1341, 1341, 1341, 1195, 1689, 1609, 1860, 1690, 1931, 1342, 1932, 1772, 334, 470, 1762, 470, 1922, 1343, 1691, 1341, 1341, 1341, 1145, 1689, 1923, 1756, 1690, 1862, 1342, 931, 1863, 1157, 1611, 334, 381, 1938, 1343, 1691, 174, 931, 1612, 1864, 177, 174, 174, 178, 174, 179, 178, 174, 174, 193, 180, 194, 174, 177, 174, 174, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 1819, 193, 193, 193, 193, 174, 174, 178, 226, 1109, 931, 227, 1862, 228, 227, 1863, 1109, 1611, 229, 237, 421, 238, 1109, 1109, 1772, 1612, 1864, 1762, 1109, 1922, 1862, 421, 381, 1863, 959, 1611, 1939, 1923, 1756, 381, 381, 1940, 1832, 1612, 1864, 381, 381, 1946, 1135, 239, 226, 381, 1957, 227, 1772, 228, 227, 1762, 1014, 1922, 971, 237, 193, 238, 381, 283, 1870, 1923, 1756, 1871, 1772, 1625, 1014, 1762, 1713, 1922, 1965, 1709, 1128, 1626, 1872, 283, 1066, 1923, 1756, 283, 1975, 1907, 1705, 334, 1118, 239, 1332, 1332, 1332, 283, 1731, 1104, 1066, 1732, 1109, 1401, 620, 1870, 1092, 334, 1871, 1085, 1625, 1402, 1733, 1332, 1332, 1332, 1075, 1731, 1626, 1872, 1732, 1109, 1401, 334, 1870, 381, 1061, 1871, 568, 1625, 1402, 1733, 1332, 1332, 1332, 1971, 1731, 1626, 1872, 1732, 1014, 1401, 1040, 1947, 381, 1033, 1947, 1023, 381, 1402, 1733, 1816, 1816, 1816, 1009, 1589, 1907, 1705, 1586, 1066, 1844, 518, 1948, 283, 997, 1949, 990, 1830, 1845, 1579, 1336, 1336, 1336, 980, 1735, 1831, 1950, 1736, 1109, 1405, 470, 1869, 334, 964, 1861, 334, 1980, 1406, 1737, 1336, 1336, 1336, 959, 1735, 1959, 1857, 1736, 663, 1405, 957, 1960, 381, 950, 1960, 940, 1922, 1406, 1737, 1816, 1816, 1816, 926, 1589, 1923, 1756, 1586, 1014, 1844, 421, 1869, 381, 1981, 1861, 428, 428, 1845, 1579, 1336, 1336, 1336, 810, 1735, 1959, 1857, 1736, 1066, 1405, 428, 1948, 283, 755, 1949, 722, 1830, 1406, 1737, 1341, 1341, 1341, 229, 1739, 1831, 1950, 1740, 1109, 1408, 428, 1948, 334, 663, 1949, 661, 1830, 1409, 1741, 1816, 1816, 1816, 660, 1589, 1831, 1950, 1586, 659, 1844, 658, 1948, 381, 657, 1949, 653, 1830, 1845, 1579, 1341, 1341, 1341, 652, 1739, 1831, 1950, 1740, 651, 1408, 650, 1948, 649, 648, 1949, 647, 1830, 1409, 1741, 1341, 1341, 1341, 646, 1739, 1831, 1950, 1740, 645, 1408, 644, 1976, 643, 640, 1976, 639, 632, 1409, 1741, 1439, 1439, 1439, 631, 1764, 1959, 1857, 1765, 630, 1440, 629, 1977, 628, 627, 1978, 428, 1922, 1441, 1766, 1439, 1439, 1439, 625, 1764, 1923, 1979, 1765, 624, 1440, 620, 1977, 612, 611, 1978, 610, 1922, 1441, 1766, 1439, 1439, 1439, 609, 1764, 1923, 1979, 1765, 608, 1440, 604, 1977, 603, 602, 1978, 601, 1922, 1441, 1766, 1866, 1866, 1866, 600, 1630, 1923, 1979, 1624, 599, 1867, 598, 1977, 597, 596, 1978, 595, 1922, 1868, 1616, 1443, 1443, 1443, 594, 1768, 1923, 1979, 1769, 591, 1445, 590, 1977, 583, 582, 1978, 581, 1922, 1446, 1770, 1443, 1443, 1443, 580, 1768, 1923, 1979, 1769, 579, 1445, 578, 569, 428, 576, 575, 568, 559, 1446, 1770, 1866, 1866, 1866, 558, 1630, 557, 556, 1624, 555, 1867, 551, 550, 549, 548, 547, 546, 545, 1868, 1616, 1443, 1443, 1443, 544, 1768, 543, 542, 1769, 541, 1445, 538, 537, 530, 529, 528, 527, 526, 1446, 1770, 1452, 1452, 1452, 525, 1774, 428, 518, 1775, 523, 1453, 522, 518, 506, 489, 475, 474, 472, 1454, 1776, 1866, 1866, 1866, 470, 1630, 229, 463, 1624, 462, 1867, 461, 460, 459, 455, 454, 453, 452, 1868, 1616, 1452, 1452, 1452, 451, 1774, 450, 449, 1775, 448, 1453, 447, 446, 445, 442, 441, 434, 433, 1454, 1776, 1452, 1452, 1452, 432, 1774, 431, 430, 1775, 429, 1453, 230, 428, 426, 425, 421, 412, 411, 1454, 1776, 1332, 1332, 1332, 407, 1791, 400, 396, 1792, 395, 1480, 394, 393, 380, 379, 366, 365, 361, 1481, 1793, 1332, 1332, 1332, 354, 1791, 350, 349, 1792, 348, 1480, 347, 333, 332, 317, 316, 312, 305, 1481, 1793, 1332, 1332, 1332, 301, 1791, 300, 299, 1792, 298, 1480, 282, 281, 230, 235, 234, 229, 229, 1481, 1793, 1816, 1816, 1816, 229, 1661, 232, 225, 1658, 224, 1885, 220, 213, 209, 208, 207, 206, 192, 1886, 1651, 1336, 1336, 1336, 191, 1795, 1982, 1982, 1796, 1982, 1484, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1485, 1797, 1336, 1336, 1336, 1982, 1795, 1982, 1982, 1796, 1982, 1484, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1485, 1797, 1816, 1816, 1816, 1982, 1661, 1982, 1982, 1658, 1982, 1885, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1886, 1651, 1336, 1336, 1336, 1982, 1795, 1982, 1982, 1796, 1982, 1484, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1485, 1797, 1341, 1341, 1341, 1982, 1799, 1982, 1982, 1800, 1982, 1487, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1488, 1801, 1816, 1816, 1816, 1982, 1661, 1982, 1982, 1658, 1982, 1885, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1886, 1651, 1341, 1341, 1341, 1982, 1799, 1982, 1982, 1800, 1982, 1487, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1488, 1801, 1341, 1341, 1341, 1982, 1799, 1982, 1982, 1800, 1982, 1487, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1488, 1801, 1816, 1816, 1816, 1982, 1528, 1982, 1982, 1524, 1982, 1817, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1818, 1516, 1899, 1899, 1899, 1982, 1688, 1982, 1982, 1684, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1900, 1680, 1816, 1816, 1816, 1982, 1901, 1982, 1982, 1901, 1982, 1817, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1818, 1516, 1816, 1816, 1816, 1982, 1589, 1982, 1982, 1586, 1982, 1844, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1845, 1579, 1899, 1899, 1899, 1982, 1738, 1982, 1982, 1734, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1915, 1730, 1816, 1816, 1816, 1982, 1916, 1982, 1982, 1916, 1982, 1844, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1845, 1579, 1866, 1866, 1866, 1982, 1630, 1982, 1982, 1624, 1982, 1867, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1868, 1616, 1925, 1925, 1925, 1982, 1773, 1982, 1982, 1767, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1926, 1763, 1866, 1866, 1866, 1982, 1927, 1982, 1982, 1927, 1982, 1867, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1868, 1616, 1816, 1816, 1816, 1982, 1661, 1982, 1982, 1658, 1982, 1885, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1886, 1651, 1899, 1899, 1899, 1982, 1798, 1982, 1982, 1794, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1934, 1790, 1816, 1816, 1816, 1982, 1935, 1982, 1982, 1935, 1982, 1885, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1886, 1651, 1899, 1899, 1899, 1982, 1688, 1982, 1982, 1684, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1900, 1680, 1899, 1899, 1899, 1982, 1941, 1982, 1982, 1941, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1900, 1680, 1816, 1816, 1816, 1982, 1942, 1982, 1982, 1943, 1982, 1817, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1818, 1944, 1899, 1899, 1899, 1982, 1738, 1982, 1982, 1734, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1915, 1730, 1899, 1899, 1899, 1982, 1953, 1982, 1982, 1953, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1915, 1730, 1816, 1816, 1816, 1982, 1954, 1982, 1982, 1955, 1982, 1844, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1845, 1956, 1925, 1925, 1925, 1982, 1773, 1982, 1982, 1767, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1926, 1763, 1925, 1925, 1925, 1982, 1961, 1982, 1982, 1961, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1926, 1763, 1866, 1866, 1866, 1982, 1962, 1982, 1982, 1963, 1982, 1867, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1868, 1964, 1899, 1899, 1899, 1982, 1798, 1982, 1982, 1794, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1934, 1790, 1899, 1899, 1899, 1982, 1967, 1982, 1982, 1967, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1934, 1790, 1816, 1816, 1816, 1982, 1968, 1982, 1982, 1969, 1982, 1885, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1886, 1970, 1816, 1816, 1816, 1982, 1942, 1982, 1982, 1943, 1982, 1817, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1818, 1944, 1816, 1816, 1816, 1982, 1942, 1982, 1982, 1943, 1982, 1817, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1818, 1944, 1816, 1816, 1816, 1982, 1942, 1982, 1982, 1943, 1982, 1817, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1818, 1944, 1816, 1816, 1816, 1982, 1942, 1982, 1982, 1943, 1982, 1817, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1818, 1944, 1816, 1816, 1816, 1982, 1954, 1982, 1982, 1955, 1982, 1844, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1845, 1956, 1816, 1816, 1816, 1982, 1954, 1982, 1982, 1955, 1982, 1844, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1845, 1956, 1816, 1816, 1816, 1982, 1954, 1982, 1982, 1955, 1982, 1844, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1845, 1956, 1816, 1816, 1816, 1982, 1954, 1982, 1982, 1955, 1982, 1844, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1845, 1956, 1866, 1866, 1866, 1982, 1962, 1982, 1982, 1963, 1982, 1867, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1868, 1964, 1866, 1866, 1866, 1982, 1962, 1982, 1982, 1963, 1982, 1867, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1868, 1964, 1866, 1866, 1866, 1982, 1962, 1982, 1982, 1963, 1982, 1867, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1868, 1964, 1866, 1866, 1866, 1982, 1962, 1982, 1982, 1963, 1982, 1867, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1868, 1964, 1816, 1816, 1816, 1982, 1968, 1982, 1982, 1969, 1982, 1885, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1886, 1970, 1816, 1816, 1816, 1982, 1968, 1982, 1982, 1969, 1982, 1885, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1886, 1970, 1816, 1816, 1816, 1982, 1968, 1982, 1982, 1969, 1982, 1885, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1886, 1970, 1816, 1816, 1816, 1982, 1968, 1982, 1982, 1969, 1982, 1885, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1886, 1970, 174, 1982, 1982, 1982, 174, 174, 177, 1982, 1982, 1982, 177, 177, 181, 181, 181, 181, 181, 181, 185, 185, 1982, 185, 185, 185, 178, 1982, 1982, 1982, 178, 178, 188, 188, 188, 188, 188, 188, 195, 195, 195, 195, 195, 195, 182, 182, 182, 182, 182, 182, 186, 186, 1982, 186, 186, 186, 189, 189, 189, 189, 189, 189, 236, 236, 196, 196, 196, 196, 196, 196, 269, 1982, 1982, 1982, 269, 269, 270, 1982, 1982, 1982, 270, 270, 274, 274, 274, 274, 274, 274, 277, 277, 1982, 277, 277, 277, 271, 1982, 1982, 1982, 271, 271, 279, 279, 279, 279, 279, 279, 288, 288, 288, 288, 288, 288, 287, 1982, 1982, 1982, 287, 287, 318, 1982, 1982, 1982, 318, 318, 319, 1982, 1982, 1982, 319, 319, 323, 323, 323, 323, 323, 323, 327, 327, 1982, 327, 327, 327, 320, 1982, 1982, 1982, 320, 320, 329, 329, 329, 329, 329, 329, 336, 336, 336, 336, 336, 336, 367, 1982, 1982, 1982, 367, 367, 368, 1982, 1982, 1982, 368, 368, 372, 372, 372, 372, 372, 372, 375, 375, 1982, 375, 375, 375, 369, 1982, 1982, 1982, 369, 369, 377, 377, 377, 377, 377, 377, 383, 383, 383, 383, 383, 383, 177, 1982, 1982, 1982, 177, 177, 178, 1982, 1982, 1982, 178, 178, 415, 415, 415, 415, 415, 415, 181, 181, 181, 181, 181, 181, 182, 182, 182, 182, 182, 182, 185, 185, 1982, 185, 185, 185, 186, 186, 1982, 186, 186, 186, 188, 188, 188, 188, 188, 188, 189, 189, 189, 189, 189, 189, 427, 1982, 1982, 427, 427, 427, 195, 195, 195, 195, 195, 195, 196, 196, 196, 196, 196, 196, 464, 464, 464, 464, 464, 464, 236, 236, 428, 1982, 1982, 428, 428, 428, 270, 1982, 1982, 1982, 270, 270, 271, 1982, 1982, 1982, 271, 271, 512, 512, 512, 512, 512, 512, 274, 274, 274, 274, 274, 274, 277, 277, 1982, 277, 277, 277, 279, 279, 279, 279, 279, 279, 524, 1982, 1982, 524, 524, 524, 287, 1982, 1982, 1982, 287, 287, 288, 288, 288, 288, 288, 288, 318, 1982, 1982, 1982, 318, 318, 319, 1982, 1982, 1982, 319, 319, 320, 1982, 1982, 1982, 320, 320, 562, 562, 562, 562, 562, 562, 323, 323, 323, 323, 323, 323, 324, 324, 324, 324, 324, 324, 327, 327, 1982, 327, 327, 327, 329, 329, 329, 329, 329, 329, 330, 330, 330, 330, 330, 330, 577, 1982, 1982, 577, 577, 577, 336, 336, 336, 336, 336, 336, 337, 337, 337, 337, 337, 337, 367, 1982, 1982, 1982, 367, 367, 368, 1982, 1982, 1982, 368, 368, 369, 1982, 1982, 1982, 369, 369, 614, 614, 614, 614, 614, 614, 372, 372, 372, 372, 372, 372, 375, 375, 1982, 375, 375, 375, 377, 377, 377, 377, 377, 377, 626, 1982, 1982, 626, 626, 626, 383, 383, 383, 383, 383, 383, 413, 413, 413, 413, 413, 413, 414, 414, 414, 414, 414, 414, 415, 415, 415, 415, 415, 415, 664, 664, 664, 664, 664, 664, 669, 669, 669, 669, 669, 669, 178, 1982, 1982, 1982, 178, 178, 674, 674, 674, 674, 674, 674, 174, 1982, 1982, 1982, 174, 174, 181, 181, 181, 181, 181, 181, 185, 185, 1982, 185, 185, 185, 188, 188, 188, 188, 188, 188, 427, 1982, 1982, 427, 427, 427, 428, 1982, 1982, 428, 428, 428, 464, 464, 464, 464, 464, 464, 665, 665, 665, 665, 665, 665, 670, 670, 670, 670, 670, 670, 675, 675, 675, 675, 675, 675, 182, 182, 182, 182, 182, 182, 186, 186, 1982, 186, 186, 186, 189, 189, 189, 189, 189, 189, 236, 236, 511, 511, 511, 511, 511, 511, 512, 512, 512, 512, 512, 512, 761, 761, 761, 761, 761, 761, 765, 765, 765, 765, 765, 765, 271, 1982, 1982, 1982, 271, 271, 769, 769, 769, 769, 769, 769, 269, 1982, 1982, 1982, 269, 269, 274, 274, 274, 274, 274, 274, 277, 277, 1982, 277, 277, 277, 279, 279, 279, 279, 279, 279, 524, 1982, 1982, 524, 524, 524, 560, 560, 560, 560, 560, 560, 561, 561, 561, 561, 561, 561, 562, 562, 562, 562, 562, 562, 811, 811, 811, 811, 811, 811, 816, 816, 816, 816, 816, 816, 320, 1982, 1982, 1982, 320, 320, 821, 821, 821, 821, 821, 821, 318, 1982, 1982, 1982, 318, 318, 324, 324, 324, 324, 324, 324, 323, 323, 323, 323, 323, 323, 327, 327, 1982, 327, 327, 327, 330, 330, 330, 330, 330, 330, 329, 329, 329, 329, 329, 329, 577, 1982, 1982, 577, 577, 577, 613, 613, 613, 613, 613, 613, 614, 614, 614, 614, 614, 614, 865, 865, 865, 865, 865, 865, 869, 869, 869, 869, 869, 869, 369, 1982, 1982, 1982, 369, 369, 873, 873, 873, 873, 873, 873, 367, 1982, 1982, 1982, 367, 367, 372, 372, 372, 372, 372, 372, 375, 375, 1982, 375, 375, 375, 377, 377, 377, 377, 377, 377, 626, 1982, 1982, 626, 626, 626, 174, 1982, 1982, 1982, 174, 174, 664, 664, 664, 664, 664, 664, 665, 665, 665, 665, 665, 665, 413, 413, 413, 413, 413, 413, 913, 913, 913, 913, 913, 913, 669, 669, 669, 669, 669, 669, 670, 670, 670, 670, 670, 670, 918, 918, 918, 918, 918, 918, 674, 674, 674, 674, 674, 674, 675, 675, 675, 675, 675, 675, 922, 922, 922, 922, 922, 922, 185, 185, 1982, 185, 185, 185, 414, 414, 414, 414, 414, 414, 914, 914, 914, 914, 914, 914, 919, 919, 919, 919, 919, 919, 923, 923, 923, 923, 923, 923, 186, 186, 1982, 186, 186, 186, 236, 236, 269, 1982, 1982, 1982, 269, 269, 761, 761, 761, 761, 761, 761, 511, 511, 511, 511, 511, 511, 999, 999, 999, 999, 999, 999, 765, 765, 765, 765, 765, 765, 1003, 1003, 1003, 1003, 1003, 1003, 769, 769, 769, 769, 769, 769, 1006, 1006, 1006, 1006, 1006, 1006, 277, 277, 1982, 277, 277, 277, 318, 1982, 1982, 1982, 318, 318, 811, 811, 811, 811, 811, 811, 812, 812, 812, 812, 812, 812, 560, 560, 560, 560, 560, 560, 1045, 1045, 1045, 1045, 1045, 1045, 816, 816, 816, 816, 816, 816, 817, 817, 817, 817, 817, 817, 1052, 1052, 1052, 1052, 1052, 1052, 821, 821, 821, 821, 821, 821, 822, 822, 822, 822, 822, 822, 1057, 1057, 1057, 1057, 1057, 1057, 324, 324, 324, 324, 324, 324, 327, 327, 1982, 327, 327, 327, 330, 330, 330, 330, 330, 330, 367, 1982, 1982, 1982, 367, 367, 865, 865, 865, 865, 865, 865, 613, 613, 613, 613, 613, 613, 1094, 1094, 1094, 1094, 1094, 1094, 869, 869, 869, 869, 869, 869, 1098, 1098, 1098, 1098, 1098, 1098, 873, 873, 873, 873, 873, 873, 1101, 1101, 1101, 1101, 1101, 1101, 375, 375, 1982, 375, 375, 375, 913, 913, 913, 913, 913, 913, 914, 914, 914, 914, 914, 914, 413, 413, 413, 413, 413, 413, 664, 664, 664, 664, 664, 664, 918, 918, 918, 918, 918, 918, 919, 919, 919, 919, 919, 919, 669, 669, 669, 669, 669, 669, 922, 922, 922, 922, 922, 922, 923, 923, 923, 923, 923, 923, 185, 185, 1982, 185, 185, 185, 174, 1982, 1982, 1982, 174, 174, 414, 414, 414, 414, 414, 414, 665, 665, 665, 665, 665, 665, 670, 670, 670, 670, 670, 670, 186, 186, 1982, 186, 186, 186, 236, 236, 999, 999, 999, 999, 999, 999, 511, 511, 511, 511, 511, 511, 761, 761, 761, 761, 761, 761, 1003, 1003, 1003, 1003, 1003, 1003, 765, 765, 765, 765, 765, 765, 1006, 1006, 1006, 1006, 1006, 1006, 277, 277, 1982, 277, 277, 277, 269, 1982, 1982, 1982, 269, 269, 561, 561, 561, 561, 561, 561, 1046, 1046, 1046, 1046, 1046, 1046, 812, 812, 812, 812, 812, 812, 1045, 1045, 1045, 1045, 1045, 1045, 560, 560, 560, 560, 560, 560, 811, 811, 811, 811, 811, 811, 1053, 1053, 1053, 1053, 1053, 1053, 817, 817, 817, 817, 817, 817, 1052, 1052, 1052, 1052, 1052, 1052, 816, 816, 816, 816, 816, 816, 1058, 1058, 1058, 1058, 1058, 1058, 1057, 1057, 1057, 1057, 1057, 1057, 327, 327, 1982, 327, 327, 327, 318, 1982, 1982, 1982, 318, 318, 1094, 1094, 1094, 1094, 1094, 1094, 613, 613, 613, 613, 613, 613, 865, 865, 865, 865, 865, 865, 1098, 1098, 1098, 1098, 1098, 1098, 869, 869, 869, 869, 869, 869, 1101, 1101, 1101, 1101, 1101, 1101, 375, 375, 1982, 375, 375, 375, 367, 1982, 1982, 1982, 367, 367, 664, 664, 664, 664, 664, 664, 1331, 1331, 1331, 1331, 1331, 1331, 1335, 1335, 1335, 1335, 1335, 1335, 669, 669, 669, 669, 669, 669, 1340, 1340, 1340, 1340, 1340, 1340, 174, 1982, 1982, 1982, 174, 174, 665, 665, 665, 665, 665, 665, 1332, 1332, 1332, 1332, 1332, 1332, 1336, 1336, 1336, 1336, 1336, 1336, 670, 670, 670, 670, 670, 670, 1341, 1341, 1341, 1341, 1341, 1341, 236, 236, 761, 761, 761, 761, 761, 761, 1400, 1400, 1400, 1400, 1400, 1400, 1403, 1403, 1403, 1403, 1403, 1403, 765, 765, 765, 765, 765, 765, 1407, 1407, 1407, 1407, 1407, 1407, 269, 1982, 1982, 1982, 269, 269, 812, 812, 812, 812, 812, 812, 822, 822, 822, 822, 822, 822, 561, 561, 561, 561, 561, 561, 1046, 1046, 1046, 1046, 1046, 1046, 811, 811, 811, 811, 811, 811, 1438, 1438, 1438, 1438, 1438, 1438, 1442, 1442, 1442, 1442, 1442, 1442, 1053, 1053, 1053, 1053, 1053, 1053, 816, 816, 816, 816, 816, 816, 1451, 1451, 1451, 1451, 1451, 1451, 318, 1982, 1982, 1982, 318, 318, 1479, 1479, 1479, 1479, 1479, 1479, 1482, 1482, 1482, 1482, 1482, 1482, 1486, 1486, 1486, 1486, 1486, 1486, 1513, 1513, 1513, 1513, 1513, 1513, 674, 674, 674, 674, 674, 674, 1520, 1520, 1520, 1520, 1520, 1520, 1525, 1525, 1525, 1525, 1525, 1525, 1529, 1529, 1982, 1529, 1529, 1529, 174, 1982, 1982, 1982, 174, 174, 1514, 1514, 1514, 1514, 1514, 1514, 675, 675, 675, 675, 675, 675, 1521, 1521, 1521, 1521, 1521, 1521, 1526, 1526, 1526, 1526, 1526, 1526, 236, 236, 1400, 1400, 1400, 1400, 1400, 1400, 1577, 1577, 1577, 1577, 1577, 1577, 1403, 1403, 1403, 1403, 1403, 1403, 769, 769, 769, 769, 769, 769, 1583, 1583, 1583, 1583, 1583, 1583, 1407, 1407, 1407, 1407, 1407, 1407, 1587, 1587, 1587, 1587, 1587, 1587, 269, 1982, 1982, 1982, 269, 269, 812, 812, 812, 812, 812, 812, 1439, 1439, 1439, 1439, 1439, 1439, 1443, 1443, 1443, 1443, 1443, 1443, 1613, 1613, 1613, 1613, 1613, 1613, 1442, 1442, 1442, 1442, 1442, 1442, 821, 821, 821, 821, 821, 821, 1620, 1620, 1620, 1620, 1620, 1620, 817, 817, 817, 817, 817, 817, 1452, 1452, 1452, 1452, 1452, 1452, 1451, 1451, 1451, 1451, 1451, 1451, 1627, 1627, 1627, 1627, 1627, 1627, 318, 1982, 1982, 1982, 318, 318, 1479, 1479, 1479, 1479, 1479, 1479, 1649, 1649, 1649, 1649, 1649, 1649, 1482, 1482, 1482, 1482, 1482, 1482, 873, 873, 873, 873, 873, 873, 1655, 1655, 1655, 1655, 1655, 1655, 1486, 1486, 1486, 1486, 1486, 1486, 1659, 1659, 1659, 1659, 1659, 1659, 367, 1982, 1982, 1982, 367, 367, 1513, 1513, 1513, 1513, 1513, 1513, 1331, 1331, 1331, 1331, 1331, 1331, 1335, 1335, 1335, 1335, 1335, 1335, 1340, 1340, 1340, 1340, 1340, 1340, 674, 674, 674, 674, 674, 674, 1520, 1520, 1520, 1520, 1520, 1520, 1521, 1521, 1521, 1521, 1521, 1521, 1525, 1525, 1525, 1525, 1525, 1525, 1526, 1526, 1526, 1526, 1526, 1526, 1529, 1529, 1982, 1529, 1529, 1529, 174, 1982, 1982, 1982, 174, 174, 1332, 1332, 1332, 1332, 1332, 1332, 1336, 1336, 1336, 1336, 1336, 1336, 1341, 1341, 1341, 1341, 1341, 1341, 675, 675, 675, 675, 675, 675, 236, 236, 1577, 1577, 1577, 1577, 1577, 1577, 1400, 1400, 1400, 1400, 1400, 1400, 1403, 1403, 1403, 1403, 1403, 1403, 1407, 1407, 1407, 1407, 1407, 1407, 769, 769, 769, 769, 769, 769, 1583, 1583, 1583, 1583, 1583, 1583, 1587, 1587, 1587, 1587, 1587, 1587, 269, 1982, 1982, 1982, 269, 269, 1614, 1614, 1614, 1614, 1614, 1614, 1439, 1439, 1439, 1439, 1439, 1439, 822, 822, 822, 822, 822, 822, 1621, 1621, 1621, 1621, 1621, 1621, 1443, 1443, 1443, 1443, 1443, 1443, 1613, 1613, 1613, 1613, 1613, 1613, 1438, 1438, 1438, 1438, 1438, 1438, 1442, 1442, 1442, 1442, 1442, 1442, 1451, 1451, 1451, 1451, 1451, 1451, 821, 821, 821, 821, 821, 821, 1620, 1620, 1620, 1620, 1620, 1620, 1628, 1628, 1628, 1628, 1628, 1628, 1452, 1452, 1452, 1452, 1452, 1452, 1627, 1627, 1627, 1627, 1627, 1627, 318, 1982, 1982, 1982, 318, 318, 1649, 1649, 1649, 1649, 1649, 1649, 1479, 1479, 1479, 1479, 1479, 1479, 1482, 1482, 1482, 1482, 1482, 1482, 1486, 1486, 1486, 1486, 1486, 1486, 873, 873, 873, 873, 873, 873, 1655, 1655, 1655, 1655, 1655, 1655, 1659, 1659, 1659, 1659, 1659, 1659, 367, 1982, 1982, 1982, 367, 367, 1331, 1331, 1331, 1331, 1331, 1331, 1815, 1815, 1815, 1815, 1815, 1815, 1335, 1335, 1335, 1335, 1335, 1335, 1340, 1340, 1340, 1340, 1340, 1340, 1332, 1332, 1332, 1332, 1332, 1332, 1816, 1816, 1816, 1816, 1816, 1816, 1336, 1336, 1336, 1336, 1336, 1336, 1341, 1341, 1341, 1341, 1341, 1341, 236, 236, 1400, 1400, 1400, 1400, 1400, 1400, 1843, 1843, 1843, 1843, 1843, 1843, 1865, 1865, 1865, 1865, 1865, 1865, 1884, 1884, 1884, 1884, 1884, 1884, 1898, 1898, 1898, 1898, 1898, 1898, 174, 1982, 1982, 1982, 174, 174, 1899, 1899, 1899, 1899, 1899, 1899, 1914, 1914, 1914, 1914, 1914, 1914, 269, 1982, 1982, 1982, 269, 269, 1866, 1866, 1866, 1866, 1866, 1866, 1924, 1924, 1924, 1924, 1924, 1924, 318, 1982, 1982, 1982, 318, 318, 1933, 1933, 1933, 1933, 1933, 1933, 1925, 1925, 1925, 1925, 1925, 1925, 11, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982 } ; static yyconst flex_int16_t yy_chk[10401] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 18, 2086, 18, 29, 16, 16, 16, 16, 16, 16, 16, 16, 29, 16, 16, 16, 491, 16, 16, 17, 17, 17, 48, 17, 20, 20, 20, 36, 491, 30, 18, 20, 30, 36, 36, 48, 17, 27, 27, 27, 266, 20, 16, 16, 16, 19, 266, 82, 31, 82, 19, 19, 31, 19, 38, 27, 19, 19, 38, 19, 19, 19, 38, 19, 19, 28, 28, 39, 38, 47, 41, 47, 47, 51, 28, 41, 47, 82, 96, 92, 92, 92, 96, 51, 39, 61, 61, 41, 19, 19, 21, 61, 205, 205, 61, 21, 21, 92, 21, 128, 61, 21, 21, 128, 21, 21, 21, 47, 21, 21, 62, 62, 63, 63, 63, 64, 64, 2039, 63, 62, 78, 63, 62, 78, 64, 78, 78, 68, 68, 95, 78, 68, 95, 21, 21, 25, 68, 68, 68, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 56, 101, 185, 56, 185, 56, 56, 101, 101, 58, 56, 56, 58, 56, 58, 58, 65, 65, 446, 58, 66, 66, 65, 2038, 94, 65, 104, 67, 67, 66, 159, 69, 69, 94, 159, 66, 67, 69, 446, 67, 69, 56, 71, 104, 71, 71, 72, 72, 72, 127, 58, 60, 127, 71, 60, 72, 60, 60, 115, 71, 115, 60, 60, 126, 60, 158, 73, 73, 158, 60, 60, 73, 126, 74, 74, 73, 75, 75, 60, 74, 93, 93, 74, 73, 208, 75, 103, 75, 115, 93, 103, 2034, 60, 70, 103, 70, 70, 70, 208, 133, 103, 70, 125, 125, 70, 133, 133, 70, 80, 241, 241, 125, 157, 80, 80, 80, 80, 80, 80, 80, 80, 157, 80, 80, 80, 136, 80, 80, 81, 81, 81, 106, 81, 84, 84, 84, 106, 124, 124, 124, 84, 138, 136, 182, 167, 81, 138, 189, 106, 681, 84, 80, 80, 80, 83, 124, 182, 189, 138, 83, 83, 167, 83, 135, 681, 83, 83, 135, 83, 83, 83, 135, 83, 83, 114, 114, 114, 135, 114, 117, 117, 117, 164, 145, 145, 145, 117, 145, 164, 164, 146, 114, 146, 175, 175, 175, 117, 83, 83, 85, 145, 155, 155, 155, 85, 85, 203, 85, 203, 244, 85, 85, 244, 85, 85, 85, 231, 85, 85, 155, 146, 148, 148, 148, 156, 156, 166, 443, 148, 231, 166, 204, 260, 156, 166, 176, 176, 176, 148, 204, 166, 260, 85, 85, 89, 243, 443, 243, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 91, 252, 252, 2033, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 111, 187, 453, 187, 111, 111, 111, 111, 111, 111, 111, 111, 111, 242, 111, 111, 111, 169, 111, 111, 242, 453, 169, 181, 181, 181, 233, 181, 187, 184, 184, 184, 220, 184, 169, 220, 233, 220, 245, 249, 181, 248, 249, 111, 111, 113, 184, 248, 248, 245, 113, 113, 113, 113, 113, 113, 113, 113, 254, 113, 113, 113, 254, 113, 113, 188, 188, 188, 190, 190, 190, 253, 188, 253, 504, 190, 195, 195, 195, 246, 432, 246, 188, 246, 255, 190, 504, 247, 113, 113, 113, 116, 255, 247, 195, 247, 116, 116, 256, 116, 256, 251, 116, 116, 432, 116, 116, 116, 449, 116, 116, 226, 251, 226, 226, 251, 238, 257, 226, 238, 257, 238, 238, 258, 449, 262, 238, 239, 262, 300, 239, 258, 239, 239, 116, 116, 118, 239, 259, 265, 1998, 118, 118, 300, 118, 259, 265, 118, 118, 226, 118, 118, 118, 261, 118, 118, 263, 238, 263, 267, 434, 263, 261, 263, 268, 268, 277, 267, 277, 295, 296, 295, 297, 297, 327, 344, 327, 344, 296, 118, 118, 122, 346, 346, 434, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 144, 278, 1996, 278, 324, 144, 144, 144, 144, 144, 144, 144, 144, 330, 144, 144, 144, 324, 144, 144, 274, 274, 274, 330, 274, 276, 276, 276, 278, 276, 431, 279, 279, 279, 392, 392, 312, 274, 279, 312, 539, 312, 276, 144, 144, 144, 147, 328, 279, 328, 433, 147, 147, 431, 147, 345, 433, 147, 147, 539, 147, 147, 147, 345, 147, 147, 280, 280, 280, 288, 288, 288, 436, 280, 328, 323, 323, 323, 1993, 323, 336, 336, 336, 280, 326, 326, 326, 288, 326, 147, 147, 149, 323, 375, 349, 375, 149, 149, 336, 149, 436, 326, 149, 149, 435, 149, 149, 149, 349, 149, 149, 329, 329, 329, 331, 331, 331, 361, 329, 391, 361, 331, 361, 390, 395, 390, 437, 391, 329, 435, 703, 331, 437, 456, 149, 149, 153, 703, 395, 456, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 177, 376, 423, 376, 423, 177, 177, 177, 177, 177, 177, 177, 177, 439, 177, 177, 177, 1990, 177, 177, 372, 372, 372, 439, 372, 374, 374, 374, 376, 374, 441, 377, 377, 377, 423, 430, 407, 372, 377, 407, 445, 407, 374, 177, 177, 177, 178, 454, 377, 430, 445, 178, 178, 438, 178, 441, 1946, 178, 178, 444, 178, 178, 178, 454, 178, 178, 378, 378, 378, 383, 383, 383, 459, 378, 457, 413, 413, 413, 422, 422, 422, 438, 422, 378, 413, 444, 459, 383, 447, 178, 178, 179, 179, 179, 179, 422, 179, 179, 440, 179, 457, 179, 179, 179, 440, 179, 179, 179, 447, 179, 179, 416, 416, 416, 440, 416, 417, 417, 417, 448, 416, 450, 452, 417, 451, 417, 461, 1940, 416, 448, 452, 455, 461, 417, 179, 179, 193, 451, 450, 455, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 228, 228, 228, 228, 1932, 228, 228, 458, 228, 460, 228, 228, 228, 468, 228, 228, 228, 468, 228, 228, 419, 419, 419, 420, 420, 420, 460, 458, 442, 419, 469, 462, 420, 419, 463, 424, 424, 424, 442, 469, 478, 420, 424, 228, 228, 236, 1921, 471, 236, 478, 236, 236, 424, 442, 463, 236, 236, 465, 236, 462, 471, 466, 465, 466, 473, 479, 493, 481, 480, 482, 465, 466, 493, 494, 473, 479, 480, 481, 488, 494, 482, 483, 485, 484, 486, 509, 236, 240, 486, 488, 240, 484, 240, 240, 487, 483, 485, 240, 240, 509, 240, 489, 487, 490, 487, 489, 492, 495, 490, 497, 492, 495, 497, 496, 240, 496, 489, 498, 498, 499, 501, 500, 501, 503, 502, 499, 500, 505, 240, 270, 502, 503, 528, 505, 270, 270, 270, 270, 270, 270, 270, 270, 508, 270, 270, 270, 507, 270, 270, 507, 508, 510, 511, 511, 511, 526, 528, 510, 517, 517, 517, 511, 513, 513, 513, 527, 513, 517, 530, 526, 1913, 513, 270, 270, 270, 271, 517, 532, 534, 513, 271, 271, 520, 271, 520, 531, 271, 271, 527, 271, 271, 271, 530, 271, 271, 514, 514, 514, 516, 516, 516, 555, 514, 529, 514, 532, 534, 516, 548, 529, 531, 516, 514, 1906, 520, 555, 548, 542, 271, 271, 272, 272, 272, 272, 537, 272, 272, 533, 272, 540, 272, 272, 272, 533, 272, 272, 272, 542, 272, 272, 519, 519, 519, 535, 519, 521, 521, 521, 541, 537, 536, 544, 521, 535, 547, 540, 536, 519, 541, 1890, 551, 544, 521, 272, 272, 283, 536, 547, 551, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 286, 683, 683, 1876, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 286, 287, 543, 1849, 538, 287, 287, 287, 287, 287, 287, 287, 287, 287, 538, 287, 287, 287, 545, 287, 287, 546, 543, 549, 550, 552, 556, 554, 559, 538, 557, 552, 675, 553, 545, 558, 557, 570, 546, 573, 550, 675, 549, 556, 287, 287, 319, 554, 559, 573, 570, 319, 319, 319, 319, 319, 319, 319, 319, 553, 319, 319, 319, 558, 319, 319, 560, 560, 560, 563, 563, 563, 588, 563, 579, 560, 580, 581, 563, 571, 571, 571, 588, 571, 995, 583, 563, 995, 579, 319, 319, 319, 320, 572, 585, 572, 571, 320, 320, 580, 320, 581, 584, 320, 320, 590, 320, 320, 320, 583, 320, 320, 564, 564, 564, 566, 566, 566, 587, 564, 582, 564, 585, 601, 566, 572, 582, 584, 566, 564, 590, 601, 567, 567, 567, 320, 320, 321, 321, 321, 321, 567, 321, 321, 592, 321, 587, 321, 321, 321, 567, 321, 321, 321, 586, 321, 321, 574, 574, 574, 586, 589, 594, 592, 574, 595, 597, 589, 598, 605, 600, 604, 594, 702, 574, 605, 597, 589, 702, 604, 321, 321, 334, 600, 598, 595, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, 368, 593, 596, 591, 599, 368, 368, 368, 368, 368, 368, 368, 368, 591, 368, 368, 368, 602, 368, 368, 607, 599, 596, 603, 606, 609, 610, 593, 591, 612, 629, 611, 610, 608, 628, 631, 602, 1842, 633, 603, 607, 631, 609, 368, 368, 368, 369, 608, 628, 612, 606, 369, 369, 629, 369, 630, 632, 369, 369, 611, 369, 369, 369, 633, 369, 369, 613, 613, 613, 615, 615, 615, 622, 615, 622, 613, 641, 637, 615, 630, 632, 621, 621, 621, 695, 621, 615, 637, 695, 369, 369, 370, 370, 370, 370, 641, 370, 370, 621, 370, 642, 370, 370, 370, 622, 370, 370, 370, 639, 370, 370, 616, 616, 616, 618, 618, 618, 644, 616, 635, 616, 643, 646, 618, 693, 635, 642, 618, 616, 1835, 650, 643, 646, 639, 370, 370, 381, 644, 650, 693, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 381, 415, 415, 415, 415, 634, 415, 415, 636, 415, 648, 415, 415, 415, 645, 415, 415, 415, 640, 415, 415, 619, 619, 619, 623, 623, 623, 648, 640, 649, 619, 623, 638, 634, 645, 1823, 636, 647, 638, 619, 651, 623, 649, 640, 415, 415, 418, 652, 638, 654, 655, 418, 418, 647, 418, 654, 657, 418, 418, 651, 418, 418, 418, 652, 418, 418, 653, 656, 658, 659, 657, 684, 661, 684, 653, 659, 655, 664, 664, 664, 709, 664, 686, 686, 822, 658, 664, 656, 709, 418, 418, 429, 661, 822, 664, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 429, 464, 464, 464, 464, 660, 464, 464, 697, 464, 697, 464, 464, 464, 1822, 464, 464, 464, 665, 464, 464, 690, 690, 665, 667, 667, 667, 670, 667, 670, 677, 665, 677, 660, 673, 673, 673, 670, 668, 668, 668, 667, 668, 673, 464, 464, 476, 668, 930, 476, 682, 476, 476, 677, 688, 668, 476, 476, 689, 476, 669, 669, 669, 671, 671, 671, 682, 669, 930, 669, 671, 688, 672, 672, 672, 706, 689, 669, 685, 672, 671, 672, 676, 676, 676, 687, 705, 476, 477, 672, 706, 477, 691, 477, 477, 674, 674, 674, 477, 477, 676, 477, 710, 685, 674, 705, 691, 692, 692, 698, 687, 698, 477, 674, 696, 696, 699, 707, 699, 700, 700, 701, 701, 708, 707, 713, 753, 710, 726, 477, 512, 512, 512, 512, 708, 512, 512, 753, 512, 711, 512, 512, 512, 726, 512, 512, 512, 711, 512, 512, 713, 714, 714, 715, 718, 716, 715, 717, 715, 719, 727, 719, 717, 730, 718, 728, 728, 715, 716, 719, 717, 731, 731, 512, 512, 515, 727, 729, 732, 729, 515, 515, 733, 515, 734, 738, 515, 515, 730, 515, 515, 515, 736, 515, 515, 735, 735, 737, 737, 733, 738, 740, 734, 732, 750, 740, 736, 741, 741, 742, 743, 742, 743, 744, 1821, 744, 745, 745, 515, 515, 525, 746, 746, 750, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 525, 562, 562, 562, 562, 747, 562, 562, 751, 562, 747, 562, 562, 562, 748, 562, 562, 562, 752, 562, 562, 748, 754, 751, 755, 752, 756, 771, 758, 771, 754, 759, 759, 775, 756, 777, 777, 789, 761, 761, 761, 789, 761, 776, 562, 562, 565, 761, 775, 755, 771, 565, 565, 758, 565, 761, 779, 565, 565, 776, 565, 565, 565, 799, 565, 565, 763, 763, 763, 783, 763, 764, 764, 764, 778, 764, 778, 765, 765, 765, 764, 779, 799, 763, 765, 1809, 765, 783, 764, 565, 565, 578, 780, 780, 765, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 578, 614, 614, 614, 614, 781, 614, 614, 1807, 614, 782, 614, 614, 614, 787, 614, 614, 614, 785, 614, 614, 766, 766, 766, 767, 767, 767, 782, 766, 787, 781, 767, 785, 767, 768, 768, 768, 796, 766, 784, 784, 767, 796, 768, 614, 614, 617, 786, 786, 790, 790, 617, 617, 791, 617, 791, 797, 617, 617, 955, 617, 617, 617, 797, 617, 617, 769, 769, 769, 770, 770, 770, 792, 800, 792, 769, 793, 831, 793, 794, 794, 795, 795, 802, 769, 801, 955, 770, 800, 617, 617, 627, 801, 831, 802, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 627, 666, 666, 666, 803, 666, 805, 817, 666, 817, 666, 826, 803, 851, 805, 808, 808, 817, 851, 666, 679, 826, 832, 832, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 679, 724, 804, 807, 724, 812, 724, 724, 835, 835, 812, 724, 724, 824, 724, 811, 811, 811, 812, 811, 834, 814, 814, 814, 811, 814, 824, 804, 807, 823, 823, 823, 811, 818, 818, 818, 724, 825, 814, 825, 818, 1187, 724, 725, 1187, 834, 725, 823, 725, 725, 818, 836, 830, 725, 725, 837, 725, 815, 815, 815, 825, 815, 816, 816, 816, 842, 815, 830, 833, 816, 833, 816, 837, 838, 815, 846, 836, 846, 725, 816, 842, 819, 819, 819, 725, 762, 762, 762, 819, 762, 819, 838, 762, 840, 762, 839, 839, 844, 819, 841, 841, 844, 1784, 762, 773, 845, 845, 840, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 773, 813, 813, 813, 847, 813, 847, 848, 813, 848, 813, 820, 820, 820, 821, 821, 821, 849, 849, 813, 820, 850, 850, 821, 852, 857, 893, 856, 863, 863, 893, 852, 821, 828, 856, 1782, 857, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 828, 854, 855, 858, 859, 860, 862, 869, 869, 869, 882, 858, 882, 860, 869, 1038, 869, 855, 881, 881, 854, 865, 865, 865, 869, 865, 872, 872, 872, 859, 865, 862, 867, 867, 867, 872, 867, 880, 865, 866, 866, 866, 1038, 866, 883, 879, 866, 885, 866, 867, 868, 868, 868, 880, 868, 891, 875, 866, 875, 868, 879, 870, 870, 870, 871, 871, 871, 868, 870, 883, 891, 871, 885, 871, 873, 873, 873, 886, 870, 875, 887, 871, 889, 873, 874, 874, 874, 884, 884, 888, 888, 895, 873, 895, 886, 896, 889, 896, 887, 890, 890, 900, 874, 877, 894, 894, 900, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 877, 897, 901, 897, 898, 898, 899, 899, 903, 901, 904, 905, 906, 907, 908, 911, 909, 926, 905, 912, 912, 907, 914, 906, 909, 904, 919, 903, 913, 913, 913, 924, 913, 924, 932, 914, 919, 967, 967, 908, 911, 926, 918, 918, 918, 913, 915, 915, 915, 918, 915, 932, 935, 915, 927, 915, 916, 916, 916, 918, 916, 922, 922, 922, 915, 920, 920, 920, 1007, 935, 1007, 937, 920, 916, 917, 917, 917, 927, 917, 922, 928, 917, 920, 917, 934, 937, 929, 949, 928, 942, 939, 917, 917, 921, 921, 921, 929, 921, 943, 942, 921, 998, 921, 945, 1749, 947, 998, 949, 943, 934, 921, 921, 925, 939, 945, 947, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 925, 941, 944, 948, 950, 951, 952, 956, 953, 954, 950, 957, 948, 1031, 958, 956, 960, 951, 953, 968, 970, 957, 1031, 959, 970, 941, 959, 944, 959, 960, 952, 961, 954, 958, 961, 968, 961, 959, 962, 969, 972, 974, 974, 975, 961, 961, 963, 972, 962, 963, 975, 963, 976, 969, 978, 977, 979, 979, 980, 963, 963, 965, 985, 982, 965, 977, 965, 965, 986, 983, 987, 965, 965, 988, 965, 985, 976, 982, 978, 984, 984, 989, 980, 983, 987, 989, 990, 991, 988, 994, 994, 993, 986, 997, 996, 1013, 1009, 1202, 1202, 991, 1017, 1012, 965, 966, 990, 993, 966, 997, 966, 966, 996, 1012, 1010, 966, 966, 1013, 966, 999, 999, 999, 1009, 999, 1001, 1001, 1001, 1017, 1001, 1024, 1011, 1747, 1022, 1003, 1003, 1003, 999, 1010, 1011, 966, 1003, 1001, 1006, 1006, 1006, 1015, 966, 1000, 1000, 1000, 1003, 1000, 1018, 1024, 1000, 1022, 1000, 1004, 1004, 1004, 1006, 1025, 1015, 1020, 1004, 1000, 1002, 1002, 1002, 1018, 1002, 1025, 1026, 1002, 1004, 1002, 1027, 1020, 1030, 1028, 1032, 1034, 1026, 1002, 1002, 1005, 1005, 1005, 1030, 1005, 1028, 1033, 1005, 1034, 1005, 1036, 1721, 1033, 1039, 1063, 1032, 1027, 1005, 1005, 1008, 1036, 1039, 1063, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1008, 1035, 1040, 1037, 1041, 1042, 1050, 1043, 1042, 1044, 1042, 1046, 1040, 1059, 1044, 1059, 1050, 1196, 1065, 1042, 1043, 1196, 1044, 1041, 1046, 1035, 1037, 1045, 1045, 1045, 1051, 1045, 1051, 1048, 1048, 1048, 1061, 1048, 1065, 1704, 1051, 1052, 1052, 1052, 1045, 1047, 1047, 1047, 1052, 1047, 1048, 1053, 1047, 1067, 1047, 1054, 1054, 1054, 1052, 1064, 1061, 1053, 1054, 1047, 1049, 1049, 1049, 1076, 1049, 1064, 1067, 1049, 1054, 1049, 1062, 1057, 1057, 1057, 1069, 1070, 1072, 1049, 1049, 1055, 1055, 1055, 1366, 1055, 1077, 1078, 1055, 1076, 1055, 1057, 1072, 1082, 1070, 1062, 1077, 1078, 1055, 1055, 1060, 1069, 1366, 1082, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1060, 1074, 1079, 1080, 1083, 1084, 1085, 1086, 1087, 1090, 1088, 1089, 1085, 1083, 1080, 1091, 1092, 1104, 1093, 1086, 1088, 1701, 1128, 1091, 1074, 1084, 1092, 1079, 1128, 1094, 1094, 1094, 1087, 1094, 1089, 1110, 1090, 1093, 1096, 1096, 1096, 1104, 1096, 1098, 1098, 1098, 1094, 1095, 1095, 1095, 1098, 1095, 1110, 1105, 1095, 1096, 1095, 1099, 1099, 1099, 1098, 1101, 1101, 1101, 1099, 1095, 1097, 1097, 1097, 1102, 1097, 1102, 1106, 1097, 1099, 1097, 1105, 1108, 1107, 1101, 1106, 1112, 1113, 1097, 1097, 1100, 1100, 1100, 1107, 1100, 1120, 1115, 1100, 1134, 1100, 1193, 1123, 1108, 1193, 1113, 1120, 1134, 1100, 1100, 1103, 1115, 1112, 1123, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1103, 1117, 1119, 1121, 1122, 1125, 1129, 1126, 1127, 1130, 1131, 1132, 1133, 1121, 1159, 1125, 1126, 1135, 1129, 1136, 1131, 1148, 1150, 1145, 1117, 1149, 1119, 1135, 1127, 1122, 1152, 1149, 1153, 1130, 1132, 1145, 1151, 1159, 1136, 1133, 1137, 1137, 1137, 1156, 1137, 1155, 1150, 1137, 1148, 1137, 1162, 1163, 1153, 1151, 1154, 1152, 1162, 1137, 1137, 1138, 1138, 1138, 1155, 1138, 1154, 1164, 1138, 1156, 1138, 1186, 1168, 1200, 1700, 1165, 1163, 1200, 1138, 1138, 1139, 1139, 1139, 1166, 1139, 1167, 1172, 1139, 1174, 1139, 1166, 1164, 1186, 1170, 1171, 1167, 1168, 1139, 1140, 1140, 1140, 1165, 1140, 1170, 1171, 1195, 1172, 1140, 1173, 1175, 1203, 1698, 1175, 1174, 1175, 1140, 1140, 1141, 1141, 1141, 1173, 1141, 1175, 1175, 1141, 1189, 1141, 1189, 1176, 1188, 1203, 1176, 1195, 1176, 1141, 1141, 1142, 1142, 1142, 1188, 1142, 1176, 1176, 1142, 1177, 1142, 1178, 1177, 1191, 1177, 1669, 1178, 1192, 1142, 1143, 1143, 1143, 1177, 1143, 1178, 1178, 1143, 1192, 1143, 1179, 1191, 1199, 1179, 1211, 1179, 1211, 1143, 1143, 1144, 1144, 1144, 1180, 1179, 1179, 1180, 1144, 1180, 1144, 1182, 1422, 1182, 1422, 1199, 1190, 1180, 1144, 1144, 1147, 1182, 1182, 1190, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1147, 1181, 1665, 1197, 1181, 1198, 1181, 1201, 1204, 1205, 1201, 1206, 1205, 1209, 1181, 1181, 1184, 1207, 1208, 1184, 1209, 1184, 1184, 1222, 1210, 1204, 1184, 1184, 1224, 1184, 1197, 1223, 1198, 1228, 1207, 1208, 1225, 1223, 1206, 1210, 1226, 1236, 1227, 1228, 1233, 1241, 1230, 1236, 1238, 1229, 1222, 1237, 1224, 1225, 1239, 1241, 1248, 1184, 1185, 1242, 1664, 1185, 1227, 1185, 1185, 1226, 1229, 1233, 1185, 1185, 1230, 1185, 1238, 1246, 1237, 1240, 1244, 1245, 1247, 1249, 1239, 1248, 1240, 1242, 1249, 1251, 1244, 1245, 1269, 1267, 1247, 1292, 1249, 1246, 1251, 1185, 1250, 1253, 1250, 1185, 1212, 1212, 1212, 1292, 1212, 1259, 1250, 1212, 1252, 1212, 1253, 1252, 1269, 1252, 1272, 1259, 1267, 1212, 1212, 1213, 1213, 1213, 1252, 1213, 1270, 1268, 1213, 1271, 1213, 1274, 1254, 1268, 1638, 1254, 1272, 1254, 1213, 1213, 1214, 1214, 1214, 1270, 1214, 1254, 1254, 1214, 1274, 1214, 1260, 1273, 1360, 1260, 1271, 1260, 1275, 1214, 1215, 1215, 1215, 1273, 1215, 1260, 1260, 1278, 1281, 1215, 1282, 1283, 1291, 1360, 1281, 1284, 1414, 1215, 1215, 1216, 1216, 1216, 1275, 1216, 1285, 1287, 1216, 1293, 1216, 1414, 1278, 1285, 1291, 1282, 1286, 1283, 1216, 1216, 1217, 1217, 1217, 1284, 1217, 1289, 1286, 1217, 1306, 1217, 1312, 1287, 1307, 1290, 1293, 1289, 1304, 1217, 1218, 1218, 1218, 1309, 1218, 1290, 1305, 1218, 1308, 1218, 1311, 1307, 1305, 1355, 1306, 1320, 1312, 1218, 1218, 1219, 1219, 1219, 1310, 1309, 1318, 1304, 1219, 1311, 1219, 1397, 1318, 1634, 1310, 1308, 1322, 1397, 1219, 1219, 1221, 1320, 1355, 1322, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1255, 1255, 1255, 1323, 1255, 1328, 1315, 1255, 1319, 1255, 1324, 1391, 1326, 1323, 1327, 1321, 1391, 1255, 1255, 1256, 1256, 1256, 1326, 1256, 1327, 1328, 1256, 1330, 1256, 1315, 1332, 1319, 1329, 1332, 1324, 1332, 1256, 1256, 1257, 1257, 1257, 1321, 1257, 1332, 1329, 1257, 1633, 1257, 1336, 1345, 1380, 1380, 1330, 1336, 1352, 1257, 1258, 1258, 1258, 1345, 1258, 1336, 1336, 1346, 1352, 1258, 1547, 1349, 1338, 1338, 1338, 1547, 1338, 1258, 1258, 1261, 1261, 1261, 1341, 1261, 1341, 1350, 1261, 1357, 1261, 1338, 1338, 1346, 1341, 1341, 1349, 1357, 1261, 1261, 1262, 1262, 1262, 1358, 1262, 1362, 1361, 1262, 1386, 1262, 1350, 1386, 1367, 1597, 1342, 1342, 1342, 1262, 1263, 1263, 1263, 1342, 1263, 1361, 1363, 1263, 1367, 1263, 1378, 1362, 1358, 1342, 1342, 1379, 1363, 1263, 1263, 1264, 1264, 1264, 1364, 1333, 1333, 1333, 1264, 1333, 1264, 1728, 1333, 1364, 1381, 1381, 1378, 1728, 1264, 1264, 1266, 1379, 1333, 1593, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1266, 1294, 1294, 1294, 1369, 1294, 1382, 1369, 1294, 1389, 1294, 1371, 1389, 1592, 1371, 1420, 1371, 1369, 1294, 1294, 1295, 1295, 1295, 1370, 1295, 1371, 1370, 1295, 1370, 1295, 1382, 1372, 1420, 1383, 1388, 1570, 1370, 1295, 1295, 1296, 1296, 1296, 1374, 1296, 1372, 1372, 1296, 1383, 1296, 1373, 1388, 1415, 1374, 1374, 1373, 1384, 1296, 1297, 1297, 1297, 1390, 1297, 1373, 1373, 1415, 1392, 1297, 1396, 1399, 1429, 1429, 1375, 1392, 1375, 1297, 1297, 1298, 1298, 1298, 1384, 1298, 1375, 1375, 1298, 1390, 1298, 1394, 1411, 1395, 1566, 1423, 1396, 1399, 1298, 1298, 1299, 1299, 1299, 1398, 1299, 1394, 1411, 1299, 1395, 1299, 1703, 1412, 1423, 1398, 1413, 1427, 1416, 1299, 1300, 1300, 1300, 1412, 1300, 1418, 1413, 1300, 1416, 1300, 1703, 1427, 1405, 1405, 1405, 1418, 1405, 1300, 1300, 1301, 1301, 1301, 1424, 1431, 1425, 1430, 1301, 1426, 1301, 1405, 1405, 1431, 1424, 1425, 1426, 1430, 1301, 1301, 1331, 1331, 1331, 1433, 1331, 1535, 1432, 1331, 1535, 1331, 1432, 1562, 1456, 1433, 1408, 1408, 1408, 1331, 1334, 1334, 1334, 1408, 1334, 1561, 1457, 1334, 1456, 1334, 1437, 1458, 1459, 1408, 1408, 1437, 1457, 1334, 1335, 1335, 1335, 1458, 1335, 1437, 1437, 1459, 1477, 1335, 1465, 1434, 1477, 1467, 1434, 1467, 1434, 1335, 1335, 1337, 1337, 1337, 1460, 1337, 1434, 1434, 1337, 1465, 1337, 1401, 1401, 1401, 1468, 1401, 1461, 1460, 1401, 1337, 1339, 1339, 1339, 1470, 1339, 1719, 1461, 1471, 1401, 1339, 1435, 1468, 1470, 1435, 1471, 1435, 1472, 1339, 1339, 1340, 1340, 1340, 1436, 1435, 1435, 1436, 1340, 1436, 1340, 1439, 1472, 1719, 1439, 1463, 1439, 1436, 1340, 1340, 1343, 1343, 1343, 1448, 1439, 1463, 1448, 1343, 1448, 1343, 1445, 1445, 1445, 1469, 1445, 1564, 1448, 1343, 1343, 1376, 1474, 1474, 1376, 1469, 1376, 1376, 1564, 1445, 1445, 1376, 1376, 1443, 1376, 1440, 1440, 1440, 1443, 1440, 1447, 1376, 1440, 1447, 1538, 1447, 1443, 1443, 1450, 1476, 1450, 1475, 1440, 1447, 1447, 1478, 1511, 1476, 1450, 1450, 1511, 1475, 1376, 1377, 1490, 1478, 1377, 1449, 1377, 1377, 1449, 1499, 1449, 1377, 1377, 1452, 1377, 1452, 1490, 1510, 1449, 1449, 1453, 1453, 1453, 1452, 1452, 1510, 1499, 1453, 1534, 1480, 1480, 1480, 1501, 1480, 1501, 1377, 1480, 1453, 1453, 1491, 1493, 1492, 1377, 1400, 1400, 1400, 1480, 1400, 1533, 1491, 1400, 1492, 1400, 1493, 1484, 1484, 1484, 1495, 1484, 1497, 1400, 1402, 1402, 1402, 1532, 1402, 1532, 1495, 1402, 1497, 1402, 1484, 1484, 1494, 1502, 1487, 1487, 1487, 1402, 1403, 1403, 1403, 1487, 1403, 1503, 1542, 1494, 1542, 1403, 1506, 1530, 1502, 1487, 1487, 1503, 1504, 1403, 1403, 1404, 1404, 1404, 1505, 1404, 1506, 1504, 1404, 1536, 1404, 1505, 1508, 1508, 1514, 1509, 1512, 1514, 1536, 1404, 1406, 1406, 1406, 1507, 1406, 1509, 1512, 1514, 1544, 1406, 1521, 1855, 1520, 1520, 1520, 1855, 1520, 1406, 1406, 1407, 1407, 1407, 1526, 1521, 1521, 1546, 1407, 1572, 1407, 1520, 1520, 1544, 1526, 1526, 1537, 1537, 1407, 1407, 1409, 1409, 1409, 1539, 1513, 1513, 1513, 1409, 1513, 1409, 1546, 1513, 1545, 1545, 1572, 1563, 1539, 1409, 1409, 1410, 1563, 1513, 1500, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1410, 1438, 1438, 1438, 1540, 1438, 1565, 1565, 1438, 1541, 1438, 1543, 1523, 1523, 1523, 1498, 1523, 1540, 1438, 1441, 1441, 1441, 1541, 1441, 1543, 1591, 1441, 1591, 1441, 1523, 1523, 1548, 1557, 1525, 1525, 1525, 1441, 1442, 1442, 1442, 1525, 1442, 1557, 1557, 1548, 1496, 1442, 1573, 1573, 1549, 1525, 1525, 1549, 1574, 1442, 1442, 1444, 1444, 1444, 1601, 1444, 1601, 1549, 1444, 1575, 1444, 1515, 1515, 1515, 1594, 1515, 1575, 1594, 1515, 1444, 1446, 1446, 1446, 1574, 1446, 1527, 1527, 1527, 1515, 1446, 1603, 1550, 1527, 1632, 1550, 1632, 1550, 1446, 1446, 1451, 1451, 1451, 1527, 1527, 1550, 1550, 1451, 1553, 1451, 1551, 1553, 1605, 1553, 1603, 1551, 1595, 1451, 1451, 1454, 1454, 1454, 1553, 1551, 1551, 1595, 1454, 1554, 1454, 1552, 1554, 1552, 1554, 1596, 1596, 1605, 1454, 1454, 1455, 1552, 1552, 1554, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455, 1479, 1479, 1479, 1598, 1479, 1635, 1567, 1479, 1635, 1479, 1555, 1568, 1604, 1604, 1569, 1571, 1598, 1479, 1481, 1481, 1481, 1567, 1481, 1555, 1555, 1481, 1568, 1481, 1556, 1569, 1571, 1556, 1841, 1556, 1576, 1481, 1482, 1482, 1482, 1606, 1482, 1556, 1556, 1473, 1606, 1482, 1642, 1558, 1642, 1576, 1558, 1841, 1558, 1482, 1482, 1483, 1483, 1483, 1599, 1483, 1558, 1558, 1483, 1466, 1483, 1577, 1577, 1577, 1600, 1577, 1636, 1599, 1577, 1483, 1485, 1485, 1485, 1666, 1485, 1636, 1666, 1600, 1577, 1485, 1602, 1607, 1583, 1583, 1583, 1464, 1583, 1485, 1485, 1486, 1486, 1486, 1608, 1602, 1607, 1608, 1486, 1644, 1486, 1583, 1583, 1637, 1637, 1645, 1645, 1608, 1486, 1486, 1488, 1488, 1488, 1625, 1578, 1578, 1578, 1488, 1578, 1488, 1647, 1578, 1644, 1625, 1625, 1647, 1462, 1488, 1488, 1489, 1663, 1578, 1663, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1489, 1516, 1516, 1516, 1673, 1516, 1673, 1667, 1516, 1693, 1516, 1428, 1646, 1585, 1585, 1585, 1667, 1585, 1516, 1516, 1517, 1517, 1517, 1678, 1517, 1587, 1587, 1587, 1678, 1517, 1585, 1585, 1587, 1693, 1626, 1646, 1626, 1517, 1517, 1518, 1518, 1518, 1587, 1587, 1626, 1626, 1518, 1675, 1518, 1744, 1609, 1614, 1744, 1609, 1614, 1609, 1518, 1518, 1519, 1519, 1519, 1628, 1519, 1609, 1614, 1519, 1677, 1519, 1421, 1611, 1675, 1628, 1628, 1588, 1588, 1588, 1519, 1522, 1522, 1522, 1588, 1522, 1611, 1611, 1522, 1694, 1522, 1694, 1612, 1677, 1588, 1588, 1695, 1612, 1828, 1522, 1524, 1524, 1524, 1828, 1524, 1612, 1612, 1524, 1610, 1524, 1695, 1610, 1639, 1610, 1640, 1696, 1621, 1524, 1524, 1528, 1528, 1528, 1610, 1528, 1419, 1639, 1528, 1640, 1528, 1621, 1621, 1668, 1668, 1676, 1676, 1417, 1528, 1528, 1531, 1696, 1697, 1697, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1531, 1559, 1699, 1699, 1559, 1641, 1559, 1559, 1643, 1742, 1742, 1559, 1559, 1648, 1559, 1613, 1613, 1613, 1641, 1613, 1670, 1643, 1613, 1615, 1615, 1615, 1648, 1615, 1671, 1720, 1615, 1672, 1613, 1670, 1559, 1393, 1702, 1674, 1679, 1720, 1615, 1671, 1559, 1560, 1672, 1722, 1560, 1723, 1560, 1560, 1674, 1679, 1725, 1560, 1560, 1909, 1560, 1620, 1620, 1620, 1702, 1620, 1623, 1623, 1623, 1909, 1623, 1724, 1722, 1726, 1779, 1723, 1729, 1779, 1620, 1620, 1725, 1743, 1560, 1623, 1623, 1627, 1627, 1627, 1560, 1579, 1579, 1579, 1627, 1579, 1724, 1387, 1579, 1726, 1579, 1847, 1729, 1847, 1627, 1627, 1743, 1745, 1579, 1579, 1580, 1580, 1580, 1819, 1580, 1629, 1629, 1629, 1746, 1580, 1745, 1705, 1629, 1385, 1705, 1753, 1705, 1580, 1580, 1581, 1581, 1581, 1629, 1629, 1705, 1705, 1581, 1819, 1581, 1788, 1706, 1746, 1753, 1706, 1813, 1706, 1581, 1581, 1582, 1582, 1582, 1356, 1582, 1706, 1706, 1582, 1788, 1582, 1649, 1649, 1649, 1813, 1649, 1748, 1748, 1649, 1582, 1584, 1584, 1584, 1354, 1584, 1750, 1750, 1584, 1649, 1584, 1650, 1650, 1650, 1912, 1650, 1751, 1751, 1650, 1584, 1586, 1586, 1586, 1912, 1586, 1754, 1754, 1586, 1650, 1586, 1752, 1778, 1655, 1655, 1655, 1824, 1655, 1586, 1586, 1589, 1589, 1589, 1755, 1589, 1353, 1755, 1589, 1757, 1589, 1655, 1655, 1348, 1757, 1752, 1778, 1755, 1589, 1589, 1590, 1824, 1757, 1757, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1590, 1616, 1616, 1616, 1825, 1616, 1777, 1777, 1616, 1826, 1616, 1347, 1781, 1657, 1657, 1657, 1344, 1657, 1616, 1616, 1617, 1617, 1617, 1325, 1617, 1659, 1659, 1659, 1825, 1617, 1657, 1657, 1659, 1826, 1758, 1781, 1758, 1617, 1617, 1618, 1618, 1618, 1659, 1659, 1758, 1758, 1618, 1787, 1618, 1317, 1707, 1783, 1783, 1707, 1902, 1707, 1618, 1618, 1619, 1619, 1619, 1771, 1619, 1707, 1707, 1619, 1803, 1619, 1902, 1761, 1787, 1771, 1771, 1660, 1660, 1660, 1619, 1622, 1622, 1622, 1660, 1622, 1761, 1761, 1622, 1316, 1622, 1827, 1780, 1803, 1660, 1660, 1785, 1785, 1314, 1622, 1624, 1624, 1624, 1804, 1624, 1780, 1804, 1624, 1806, 1624, 1313, 1708, 1786, 1786, 1708, 1827, 1708, 1624, 1624, 1630, 1630, 1630, 1805, 1630, 1708, 1708, 1630, 1709, 1630, 1303, 1709, 1806, 1709, 1789, 1789, 1805, 1630, 1630, 1631, 1302, 1709, 1709, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1631, 1651, 1651, 1651, 1280, 1651, 1802, 1802, 1651, 1812, 1651, 1277, 1710, 1808, 1808, 1710, 1276, 1710, 1651, 1651, 1652, 1652, 1652, 1829, 1652, 1710, 1710, 1810, 1810, 1652, 1711, 1759, 1812, 1711, 1759, 1711, 1759, 1652, 1652, 1653, 1653, 1653, 1834, 1711, 1711, 1759, 1653, 1829, 1653, 1836, 1712, 1811, 1811, 1712, 1920, 1712, 1653, 1653, 1654, 1654, 1654, 1265, 1654, 1712, 1712, 1654, 1834, 1654, 1920, 1713, 1814, 1814, 1713, 1836, 1713, 1903, 1654, 1656, 1656, 1656, 1235, 1656, 1713, 1713, 1656, 1846, 1656, 1232, 1714, 1820, 1820, 1714, 1874, 1714, 1874, 1656, 1658, 1658, 1658, 1903, 1658, 1714, 1714, 1658, 1833, 1658, 1231, 1715, 1846, 1888, 1715, 1888, 1715, 1658, 1658, 1661, 1661, 1661, 1220, 1661, 1715, 1715, 1661, 1716, 1661, 1194, 1716, 1183, 1716, 1833, 1848, 1848, 1661, 1661, 1662, 1161, 1716, 1716, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1662, 1680, 1680, 1680, 1158, 1680, 1850, 1850, 1680, 1851, 1680, 1852, 1756, 1853, 1157, 1756, 1146, 1756, 1680, 1680, 1681, 1681, 1681, 1124, 1681, 1756, 1756, 1681, 1760, 1681, 1904, 1760, 1851, 1760, 1852, 1931, 1853, 1681, 1681, 1682, 1682, 1682, 1760, 1682, 1118, 1854, 1682, 1856, 1682, 1931, 1762, 1875, 1875, 1762, 1904, 1762, 1682, 1682, 1683, 1683, 1683, 1116, 1683, 1762, 1762, 1683, 1873, 1683, 1854, 1772, 1856, 1939, 1772, 1114, 1772, 1683, 1683, 1684, 1684, 1684, 1111, 1684, 1772, 1772, 1684, 1939, 1684, 1109, 1816, 1873, 1081, 1816, 1075, 1816, 1684, 1684, 1685, 1685, 1685, 1073, 1685, 1816, 1816, 1685, 1878, 1685, 1945, 1830, 1877, 1877, 1830, 1889, 1889, 1685, 1685, 1686, 1686, 1686, 1071, 1686, 1830, 1830, 1686, 1879, 1686, 1952, 1831, 1878, 1068, 1831, 1945, 1831, 1686, 1686, 1687, 1687, 1687, 1066, 1687, 1831, 1831, 1687, 1880, 1687, 1973, 1857, 1879, 1058, 1857, 1952, 1857, 1687, 1687, 1688, 1688, 1688, 1056, 1688, 1857, 1857, 1688, 1881, 1688, 1029, 1858, 1880, 1023, 1858, 1973, 1858, 1688, 1688, 1689, 1689, 1689, 1021, 1689, 1858, 1858, 1689, 1019, 1689, 1016, 1859, 1881, 1014, 1859, 992, 1859, 1689, 1689, 1690, 1690, 1690, 981, 1690, 1859, 1859, 1690, 1882, 1690, 1883, 1860, 1882, 973, 1860, 971, 1860, 1690, 1690, 1691, 1691, 1691, 964, 1691, 1860, 1860, 1691, 1861, 1691, 946, 1861, 940, 1861, 1883, 1891, 1891, 1691, 1691, 1692, 938, 1861, 1861, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1692, 1717, 1887, 936, 1717, 1862, 1717, 1717, 1862, 1892, 1862, 1717, 1717, 933, 1717, 1893, 1894, 1863, 1862, 1862, 1863, 1895, 1863, 1864, 931, 1887, 1864, 923, 1864, 1896, 1863, 1863, 1892, 1896, 1897, 1717, 1864, 1864, 1893, 1894, 1905, 910, 1717, 1718, 1895, 1917, 1718, 1866, 1718, 1718, 1866, 1918, 1866, 1718, 1718, 1905, 1718, 1897, 1917, 1869, 1866, 1866, 1869, 1870, 1869, 1919, 1870, 1899, 1870, 1928, 1899, 902, 1869, 1869, 1918, 1929, 1870, 1870, 1958, 1958, 1899, 1899, 1928, 892, 1718, 1730, 1730, 1730, 1919, 1730, 878, 1930, 1730, 1937, 1730, 876, 1871, 861, 1929, 1871, 853, 1871, 1730, 1730, 1731, 1731, 1731, 843, 1731, 1871, 1871, 1731, 1938, 1731, 1930, 1872, 1937, 829, 1872, 827, 1872, 1731, 1731, 1732, 1732, 1732, 1936, 1732, 1872, 1872, 1732, 1957, 1732, 806, 1907, 1938, 798, 1907, 788, 1936, 1732, 1732, 1733, 1733, 1733, 774, 1733, 1907, 1907, 1733, 1965, 1733, 772, 1908, 1957, 757, 1908, 749, 1908, 1733, 1733, 1734, 1734, 1734, 739, 1734, 1908, 1908, 1734, 1971, 1734, 723, 1922, 1965, 722, 1922, 1966, 1966, 1734, 1734, 1735, 1735, 1735, 721, 1735, 1922, 1922, 1735, 720, 1735, 712, 1923, 1971, 704, 1923, 694, 1923, 1735, 1735, 1736, 1736, 1736, 680, 1736, 1923, 1923, 1736, 1975, 1736, 678, 1925, 1972, 1972, 1925, 626, 577, 1736, 1736, 1737, 1737, 1737, 561, 1737, 1925, 1925, 1737, 1980, 1737, 524, 1947, 1975, 506, 1947, 472, 1947, 1737, 1737, 1738, 1738, 1738, 467, 1738, 1947, 1947, 1738, 1981, 1738, 427, 1948, 1980, 414, 1948, 412, 1948, 1738, 1738, 1739, 1739, 1739, 411, 1739, 1948, 1948, 1739, 410, 1739, 409, 1949, 1981, 408, 1949, 406, 1949, 1739, 1739, 1740, 1740, 1740, 405, 1740, 1949, 1949, 1740, 404, 1740, 403, 1950, 402, 401, 1950, 400, 1950, 1740, 1740, 1741, 1741, 1741, 399, 1741, 1950, 1950, 1741, 398, 1741, 397, 1959, 396, 394, 1959, 393, 389, 1741, 1741, 1763, 1763, 1763, 388, 1763, 1959, 1959, 1763, 387, 1763, 386, 1960, 385, 384, 1960, 382, 1960, 1763, 1763, 1764, 1764, 1764, 380, 1764, 1960, 1960, 1764, 379, 1764, 371, 1976, 366, 365, 1976, 364, 1976, 1764, 1764, 1765, 1765, 1765, 363, 1765, 1976, 1976, 1765, 362, 1765, 360, 1977, 359, 358, 1977, 357, 1977, 1765, 1765, 1766, 1766, 1766, 356, 1766, 1977, 1977, 1766, 355, 1766, 354, 1978, 353, 352, 1978, 351, 1978, 1766, 1766, 1767, 1767, 1767, 350, 1767, 1978, 1978, 1767, 348, 1767, 347, 1979, 343, 342, 1979, 341, 1979, 1767, 1767, 1768, 1768, 1768, 340, 1768, 1979, 1979, 1768, 339, 1768, 338, 337, 335, 333, 332, 322, 317, 1768, 1768, 1769, 1769, 1769, 316, 1769, 315, 314, 1769, 313, 1769, 311, 310, 309, 308, 307, 306, 305, 1769, 1769, 1770, 1770, 1770, 304, 1770, 303, 302, 1770, 301, 1770, 299, 298, 294, 293, 292, 291, 290, 1770, 1770, 1773, 1773, 1773, 289, 1773, 285, 284, 1773, 282, 1773, 281, 273, 264, 250, 235, 234, 232, 1773, 1773, 1774, 1774, 1774, 229, 1774, 227, 225, 1774, 224, 1774, 223, 222, 221, 219, 218, 217, 216, 1774, 1774, 1775, 1775, 1775, 215, 1775, 214, 213, 1775, 212, 1775, 211, 210, 209, 207, 206, 202, 201, 1775, 1775, 1776, 1776, 1776, 200, 1776, 199, 198, 1776, 197, 1776, 196, 194, 192, 191, 180, 171, 170, 1776, 1776, 1790, 1790, 1790, 168, 1790, 165, 163, 1790, 162, 1790, 161, 160, 152, 151, 140, 139, 137, 1790, 1790, 1791, 1791, 1791, 134, 1791, 132, 131, 1791, 130, 1791, 129, 121, 120, 108, 107, 105, 102, 1791, 1791, 1792, 1792, 1792, 100, 1792, 99, 98, 1792, 97, 1792, 88, 87, 59, 55, 54, 53, 52, 1792, 1792, 1793, 1793, 1793, 50, 1793, 49, 43, 1793, 42, 1793, 40, 37, 35, 34, 33, 32, 24, 1793, 1793, 1794, 1794, 1794, 23, 1794, 11, 0, 1794, 0, 1794, 0, 0, 0, 0, 0, 0, 0, 1794, 1794, 1795, 1795, 1795, 0, 1795, 0, 0, 1795, 0, 1795, 0, 0, 0, 0, 0, 0, 0, 1795, 1795, 1796, 1796, 1796, 0, 1796, 0, 0, 1796, 0, 1796, 0, 0, 0, 0, 0, 0, 0, 1796, 1796, 1797, 1797, 1797, 0, 1797, 0, 0, 1797, 0, 1797, 0, 0, 0, 0, 0, 0, 0, 1797, 1797, 1798, 1798, 1798, 0, 1798, 0, 0, 1798, 0, 1798, 0, 0, 0, 0, 0, 0, 0, 1798, 1798, 1799, 1799, 1799, 0, 1799, 0, 0, 1799, 0, 1799, 0, 0, 0, 0, 0, 0, 0, 1799, 1799, 1800, 1800, 1800, 0, 1800, 0, 0, 1800, 0, 1800, 0, 0, 0, 0, 0, 0, 0, 1800, 1800, 1801, 1801, 1801, 0, 1801, 0, 0, 1801, 0, 1801, 0, 0, 0, 0, 0, 0, 0, 1801, 1801, 1815, 1815, 1815, 0, 1815, 0, 0, 1815, 0, 1815, 0, 0, 0, 0, 0, 0, 0, 1815, 1815, 1817, 1817, 1817, 0, 1817, 0, 0, 1817, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1817, 1817, 1818, 1818, 1818, 0, 1818, 0, 0, 1818, 0, 1818, 0, 0, 0, 0, 0, 0, 0, 1818, 1818, 1843, 1843, 1843, 0, 1843, 0, 0, 1843, 0, 1843, 0, 0, 0, 0, 0, 0, 0, 1843, 1843, 1844, 1844, 1844, 0, 1844, 0, 0, 1844, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1844, 1844, 1845, 1845, 1845, 0, 1845, 0, 0, 1845, 0, 1845, 0, 0, 0, 0, 0, 0, 0, 1845, 1845, 1865, 1865, 1865, 0, 1865, 0, 0, 1865, 0, 1865, 0, 0, 0, 0, 0, 0, 0, 1865, 1865, 1867, 1867, 1867, 0, 1867, 0, 0, 1867, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1867, 1867, 1868, 1868, 1868, 0, 1868, 0, 0, 1868, 0, 1868, 0, 0, 0, 0, 0, 0, 0, 1868, 1868, 1884, 1884, 1884, 0, 1884, 0, 0, 1884, 0, 1884, 0, 0, 0, 0, 0, 0, 0, 1884, 1884, 1885, 1885, 1885, 0, 1885, 0, 0, 1885, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1885, 1885, 1886, 1886, 1886, 0, 1886, 0, 0, 1886, 0, 1886, 0, 0, 0, 0, 0, 0, 0, 1886, 1886, 1898, 1898, 1898, 0, 1898, 0, 0, 1898, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1898, 1898, 1900, 1900, 1900, 0, 1900, 0, 0, 1900, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1900, 1900, 1901, 1901, 1901, 0, 1901, 0, 0, 1901, 0, 1901, 0, 0, 0, 0, 0, 0, 0, 1901, 1901, 1914, 1914, 1914, 0, 1914, 0, 0, 1914, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1914, 1914, 1915, 1915, 1915, 0, 1915, 0, 0, 1915, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1915, 1915, 1916, 1916, 1916, 0, 1916, 0, 0, 1916, 0, 1916, 0, 0, 0, 0, 0, 0, 0, 1916, 1916, 1924, 1924, 1924, 0, 1924, 0, 0, 1924, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1924, 1924, 1926, 1926, 1926, 0, 1926, 0, 0, 1926, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1926, 1926, 1927, 1927, 1927, 0, 1927, 0, 0, 1927, 0, 1927, 0, 0, 0, 0, 0, 0, 0, 1927, 1927, 1933, 1933, 1933, 0, 1933, 0, 0, 1933, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1933, 1933, 1934, 1934, 1934, 0, 1934, 0, 0, 1934, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1934, 1934, 1935, 1935, 1935, 0, 1935, 0, 0, 1935, 0, 1935, 0, 0, 0, 0, 0, 0, 0, 1935, 1935, 1941, 1941, 1941, 0, 1941, 0, 0, 1941, 0, 1941, 0, 0, 0, 0, 0, 0, 0, 1941, 1941, 1942, 1942, 1942, 0, 1942, 0, 0, 1942, 0, 1942, 0, 0, 0, 0, 0, 0, 0, 1942, 1942, 1943, 1943, 1943, 0, 1943, 0, 0, 1943, 0, 1943, 0, 0, 0, 0, 0, 0, 0, 1943, 1943, 1944, 1944, 1944, 0, 1944, 0, 0, 1944, 0, 1944, 0, 0, 0, 0, 0, 0, 0, 1944, 1944, 1953, 1953, 1953, 0, 1953, 0, 0, 1953, 0, 1953, 0, 0, 0, 0, 0, 0, 0, 1953, 1953, 1954, 1954, 1954, 0, 1954, 0, 0, 1954, 0, 1954, 0, 0, 0, 0, 0, 0, 0, 1954, 1954, 1955, 1955, 1955, 0, 1955, 0, 0, 1955, 0, 1955, 0, 0, 0, 0, 0, 0, 0, 1955, 1955, 1956, 1956, 1956, 0, 1956, 0, 0, 1956, 0, 1956, 0, 0, 0, 0, 0, 0, 0, 1956, 1956, 1961, 1961, 1961, 0, 1961, 0, 0, 1961, 0, 1961, 0, 0, 0, 0, 0, 0, 0, 1961, 1961, 1962, 1962, 1962, 0, 1962, 0, 0, 1962, 0, 1962, 0, 0, 0, 0, 0, 0, 0, 1962, 1962, 1963, 1963, 1963, 0, 1963, 0, 0, 1963, 0, 1963, 0, 0, 0, 0, 0, 0, 0, 1963, 1963, 1964, 1964, 1964, 0, 1964, 0, 0, 1964, 0, 1964, 0, 0, 0, 0, 0, 0, 0, 1964, 1964, 1967, 1967, 1967, 0, 1967, 0, 0, 1967, 0, 1967, 0, 0, 0, 0, 0, 0, 0, 1967, 1967, 1968, 1968, 1968, 0, 1968, 0, 0, 1968, 0, 1968, 0, 0, 0, 0, 0, 0, 0, 1968, 1968, 1969, 1969, 1969, 0, 1969, 0, 0, 1969, 0, 1969, 0, 0, 0, 0, 0, 0, 0, 1969, 1969, 1970, 1970, 1970, 0, 1970, 0, 0, 1970, 0, 1970, 0, 0, 0, 0, 0, 0, 0, 1970, 1970, 1983, 0, 0, 0, 1983, 1983, 1984, 0, 0, 0, 1984, 1984, 1985, 1985, 1985, 1985, 1985, 1985, 1986, 1986, 0, 1986, 1986, 1986, 1987, 0, 0, 0, 1987, 1987, 1988, 1988, 1988, 1988, 1988, 1988, 1989, 1989, 1989, 1989, 1989, 1989, 1991, 1991, 1991, 1991, 1991, 1991, 1992, 1992, 0, 1992, 1992, 1992, 1994, 1994, 1994, 1994, 1994, 1994, 1995, 1995, 1997, 1997, 1997, 1997, 1997, 1997, 1999, 0, 0, 0, 1999, 1999, 2000, 0, 0, 0, 2000, 2000, 2001, 2001, 2001, 2001, 2001, 2001, 2002, 2002, 0, 2002, 2002, 2002, 2003, 0, 0, 0, 2003, 2003, 2004, 2004, 2004, 2004, 2004, 2004, 2005, 2005, 2005, 2005, 2005, 2005, 2006, 0, 0, 0, 2006, 2006, 2007, 0, 0, 0, 2007, 2007, 2008, 0, 0, 0, 2008, 2008, 2009, 2009, 2009, 2009, 2009, 2009, 2010, 2010, 0, 2010, 2010, 2010, 2011, 0, 0, 0, 2011, 2011, 2012, 2012, 2012, 2012, 2012, 2012, 2013, 2013, 2013, 2013, 2013, 2013, 2014, 0, 0, 0, 2014, 2014, 2015, 0, 0, 0, 2015, 2015, 2016, 2016, 2016, 2016, 2016, 2016, 2017, 2017, 0, 2017, 2017, 2017, 2018, 0, 0, 0, 2018, 2018, 2019, 2019, 2019, 2019, 2019, 2019, 2020, 2020, 2020, 2020, 2020, 2020, 2021, 0, 0, 0, 2021, 2021, 2022, 0, 0, 0, 2022, 2022, 2023, 2023, 2023, 2023, 2023, 2023, 2024, 2024, 2024, 2024, 2024, 2024, 2025, 2025, 2025, 2025, 2025, 2025, 2026, 2026, 0, 2026, 2026, 2026, 2027, 2027, 0, 2027, 2027, 2027, 2028, 2028, 2028, 2028, 2028, 2028, 2029, 2029, 2029, 2029, 2029, 2029, 2030, 0, 0, 2030, 2030, 2030, 2031, 2031, 2031, 2031, 2031, 2031, 2032, 2032, 2032, 2032, 2032, 2032, 2035, 2035, 2035, 2035, 2035, 2035, 2036, 2036, 2037, 0, 0, 2037, 2037, 2037, 2040, 0, 0, 0, 2040, 2040, 2041, 0, 0, 0, 2041, 2041, 2042, 2042, 2042, 2042, 2042, 2042, 2043, 2043, 2043, 2043, 2043, 2043, 2044, 2044, 0, 2044, 2044, 2044, 2045, 2045, 2045, 2045, 2045, 2045, 2046, 0, 0, 2046, 2046, 2046, 2047, 0, 0, 0, 2047, 2047, 2048, 2048, 2048, 2048, 2048, 2048, 2049, 0, 0, 0, 2049, 2049, 2050, 0, 0, 0, 2050, 2050, 2051, 0, 0, 0, 2051, 2051, 2052, 2052, 2052, 2052, 2052, 2052, 2053, 2053, 2053, 2053, 2053, 2053, 2054, 2054, 2054, 2054, 2054, 2054, 2055, 2055, 0, 2055, 2055, 2055, 2056, 2056, 2056, 2056, 2056, 2056, 2057, 2057, 2057, 2057, 2057, 2057, 2058, 0, 0, 2058, 2058, 2058, 2059, 2059, 2059, 2059, 2059, 2059, 2060, 2060, 2060, 2060, 2060, 2060, 2061, 0, 0, 0, 2061, 2061, 2062, 0, 0, 0, 2062, 2062, 2063, 0, 0, 0, 2063, 2063, 2064, 2064, 2064, 2064, 2064, 2064, 2065, 2065, 2065, 2065, 2065, 2065, 2066, 2066, 0, 2066, 2066, 2066, 2067, 2067, 2067, 2067, 2067, 2067, 2068, 0, 0, 2068, 2068, 2068, 2069, 2069, 2069, 2069, 2069, 2069, 2070, 2070, 2070, 2070, 2070, 2070, 2071, 2071, 2071, 2071, 2071, 2071, 2072, 2072, 2072, 2072, 2072, 2072, 2073, 2073, 2073, 2073, 2073, 2073, 2074, 2074, 2074, 2074, 2074, 2074, 2075, 0, 0, 0, 2075, 2075, 2076, 2076, 2076, 2076, 2076, 2076, 2077, 0, 0, 0, 2077, 2077, 2078, 2078, 2078, 2078, 2078, 2078, 2079, 2079, 0, 2079, 2079, 2079, 2080, 2080, 2080, 2080, 2080, 2080, 2081, 0, 0, 2081, 2081, 2081, 2082, 0, 0, 2082, 2082, 2082, 2083, 2083, 2083, 2083, 2083, 2083, 2084, 2084, 2084, 2084, 2084, 2084, 2085, 2085, 2085, 2085, 2085, 2085, 2087, 2087, 2087, 2087, 2087, 2087, 2088, 2088, 2088, 2088, 2088, 2088, 2089, 2089, 0, 2089, 2089, 2089, 2090, 2090, 2090, 2090, 2090, 2090, 2091, 2091, 2092, 2092, 2092, 2092, 2092, 2092, 2093, 2093, 2093, 2093, 2093, 2093, 2094, 2094, 2094, 2094, 2094, 2094, 2095, 2095, 2095, 2095, 2095, 2095, 2096, 0, 0, 0, 2096, 2096, 2097, 2097, 2097, 2097, 2097, 2097, 2098, 0, 0, 0, 2098, 2098, 2099, 2099, 2099, 2099, 2099, 2099, 2100, 2100, 0, 2100, 2100, 2100, 2101, 2101, 2101, 2101, 2101, 2101, 2102, 0, 0, 2102, 2102, 2102, 2103, 2103, 2103, 2103, 2103, 2103, 2104, 2104, 2104, 2104, 2104, 2104, 2105, 2105, 2105, 2105, 2105, 2105, 2106, 2106, 2106, 2106, 2106, 2106, 2107, 2107, 2107, 2107, 2107, 2107, 2108, 0, 0, 0, 2108, 2108, 2109, 2109, 2109, 2109, 2109, 2109, 2110, 0, 0, 0, 2110, 2110, 2111, 2111, 2111, 2111, 2111, 2111, 2112, 2112, 2112, 2112, 2112, 2112, 2113, 2113, 0, 2113, 2113, 2113, 2114, 2114, 2114, 2114, 2114, 2114, 2115, 2115, 2115, 2115, 2115, 2115, 2116, 0, 0, 2116, 2116, 2116, 2117, 2117, 2117, 2117, 2117, 2117, 2118, 2118, 2118, 2118, 2118, 2118, 2119, 2119, 2119, 2119, 2119, 2119, 2120, 2120, 2120, 2120, 2120, 2120, 2121, 0, 0, 0, 2121, 2121, 2122, 2122, 2122, 2122, 2122, 2122, 2123, 0, 0, 0, 2123, 2123, 2124, 2124, 2124, 2124, 2124, 2124, 2125, 2125, 0, 2125, 2125, 2125, 2126, 2126, 2126, 2126, 2126, 2126, 2127, 0, 0, 2127, 2127, 2127, 2128, 0, 0, 0, 2128, 2128, 2129, 2129, 2129, 2129, 2129, 2129, 2130, 2130, 2130, 2130, 2130, 2130, 2131, 2131, 2131, 2131, 2131, 2131, 2132, 2132, 2132, 2132, 2132, 2132, 2133, 2133, 2133, 2133, 2133, 2133, 2134, 2134, 2134, 2134, 2134, 2134, 2135, 2135, 2135, 2135, 2135, 2135, 2136, 2136, 2136, 2136, 2136, 2136, 2137, 2137, 2137, 2137, 2137, 2137, 2138, 2138, 2138, 2138, 2138, 2138, 2139, 2139, 0, 2139, 2139, 2139, 2140, 2140, 2140, 2140, 2140, 2140, 2141, 2141, 2141, 2141, 2141, 2141, 2142, 2142, 2142, 2142, 2142, 2142, 2143, 2143, 2143, 2143, 2143, 2143, 2144, 2144, 0, 2144, 2144, 2144, 2145, 2145, 2146, 0, 0, 0, 2146, 2146, 2147, 2147, 2147, 2147, 2147, 2147, 2148, 2148, 2148, 2148, 2148, 2148, 2149, 2149, 2149, 2149, 2149, 2149, 2150, 2150, 2150, 2150, 2150, 2150, 2151, 2151, 2151, 2151, 2151, 2151, 2152, 2152, 2152, 2152, 2152, 2152, 2153, 2153, 2153, 2153, 2153, 2153, 2154, 2154, 0, 2154, 2154, 2154, 2155, 0, 0, 0, 2155, 2155, 2156, 2156, 2156, 2156, 2156, 2156, 2157, 2157, 2157, 2157, 2157, 2157, 2158, 2158, 2158, 2158, 2158, 2158, 2159, 2159, 2159, 2159, 2159, 2159, 2160, 2160, 2160, 2160, 2160, 2160, 2161, 2161, 2161, 2161, 2161, 2161, 2162, 2162, 2162, 2162, 2162, 2162, 2163, 2163, 2163, 2163, 2163, 2163, 2164, 2164, 2164, 2164, 2164, 2164, 2165, 2165, 2165, 2165, 2165, 2165, 2166, 2166, 2166, 2166, 2166, 2166, 2167, 2167, 0, 2167, 2167, 2167, 2168, 2168, 2168, 2168, 2168, 2168, 2169, 0, 0, 0, 2169, 2169, 2170, 2170, 2170, 2170, 2170, 2170, 2171, 2171, 2171, 2171, 2171, 2171, 2172, 2172, 2172, 2172, 2172, 2172, 2173, 2173, 2173, 2173, 2173, 2173, 2174, 2174, 2174, 2174, 2174, 2174, 2175, 2175, 2175, 2175, 2175, 2175, 2176, 2176, 2176, 2176, 2176, 2176, 2177, 2177, 0, 2177, 2177, 2177, 2178, 2178, 2178, 2178, 2178, 2178, 2179, 2179, 2179, 2179, 2179, 2179, 2180, 2180, 2180, 2180, 2180, 2180, 2181, 2181, 2181, 2181, 2181, 2181, 2182, 2182, 2182, 2182, 2182, 2182, 2183, 2183, 2183, 2183, 2183, 2183, 2184, 2184, 2184, 2184, 2184, 2184, 2185, 2185, 2185, 2185, 2185, 2185, 2186, 2186, 2186, 2186, 2186, 2186, 2187, 2187, 0, 2187, 2187, 2187, 2188, 0, 0, 0, 2188, 2188, 2189, 2189, 2189, 2189, 2189, 2189, 2190, 2190, 2190, 2190, 2190, 2190, 2191, 2191, 2191, 2191, 2191, 2191, 2192, 2192, 0, 2192, 2192, 2192, 2193, 2193, 2194, 2194, 2194, 2194, 2194, 2194, 2195, 2195, 2195, 2195, 2195, 2195, 2196, 2196, 2196, 2196, 2196, 2196, 2197, 2197, 2197, 2197, 2197, 2197, 2198, 2198, 2198, 2198, 2198, 2198, 2199, 2199, 2199, 2199, 2199, 2199, 2200, 2200, 0, 2200, 2200, 2200, 2201, 0, 0, 0, 2201, 2201, 2202, 2202, 2202, 2202, 2202, 2202, 2203, 2203, 2203, 2203, 2203, 2203, 2204, 2204, 2204, 2204, 2204, 2204, 2205, 2205, 2205, 2205, 2205, 2205, 2206, 2206, 2206, 2206, 2206, 2206, 2207, 2207, 2207, 2207, 2207, 2207, 2208, 2208, 2208, 2208, 2208, 2208, 2209, 2209, 2209, 2209, 2209, 2209, 2210, 2210, 2210, 2210, 2210, 2210, 2211, 2211, 2211, 2211, 2211, 2211, 2212, 2212, 2212, 2212, 2212, 2212, 2213, 2213, 2213, 2213, 2213, 2213, 2214, 2214, 0, 2214, 2214, 2214, 2215, 0, 0, 0, 2215, 2215, 2216, 2216, 2216, 2216, 2216, 2216, 2217, 2217, 2217, 2217, 2217, 2217, 2218, 2218, 2218, 2218, 2218, 2218, 2219, 2219, 2219, 2219, 2219, 2219, 2220, 2220, 2220, 2220, 2220, 2220, 2221, 2221, 2221, 2221, 2221, 2221, 2222, 2222, 0, 2222, 2222, 2222, 2223, 0, 0, 0, 2223, 2223, 2224, 2224, 2224, 2224, 2224, 2224, 2225, 2225, 2225, 2225, 2225, 2225, 2226, 2226, 2226, 2226, 2226, 2226, 2227, 2227, 2227, 2227, 2227, 2227, 2228, 2228, 2228, 2228, 2228, 2228, 2229, 0, 0, 0, 2229, 2229, 2230, 2230, 2230, 2230, 2230, 2230, 2231, 2231, 2231, 2231, 2231, 2231, 2232, 2232, 2232, 2232, 2232, 2232, 2233, 2233, 2233, 2233, 2233, 2233, 2234, 2234, 2234, 2234, 2234, 2234, 2235, 2235, 2236, 2236, 2236, 2236, 2236, 2236, 2237, 2237, 2237, 2237, 2237, 2237, 2238, 2238, 2238, 2238, 2238, 2238, 2239, 2239, 2239, 2239, 2239, 2239, 2240, 2240, 2240, 2240, 2240, 2240, 2241, 0, 0, 0, 2241, 2241, 2242, 2242, 2242, 2242, 2242, 2242, 2243, 2243, 2243, 2243, 2243, 2243, 2244, 2244, 2244, 2244, 2244, 2244, 2245, 2245, 2245, 2245, 2245, 2245, 2246, 2246, 2246, 2246, 2246, 2246, 2247, 2247, 2247, 2247, 2247, 2247, 2248, 2248, 2248, 2248, 2248, 2248, 2249, 2249, 2249, 2249, 2249, 2249, 2250, 2250, 2250, 2250, 2250, 2250, 2251, 2251, 2251, 2251, 2251, 2251, 2252, 0, 0, 0, 2252, 2252, 2253, 2253, 2253, 2253, 2253, 2253, 2254, 2254, 2254, 2254, 2254, 2254, 2255, 2255, 2255, 2255, 2255, 2255, 2256, 2256, 2256, 2256, 2256, 2256, 2257, 2257, 2257, 2257, 2257, 2257, 2258, 2258, 2258, 2258, 2258, 2258, 2259, 2259, 2259, 2259, 2259, 2259, 2260, 2260, 0, 2260, 2260, 2260, 2261, 0, 0, 0, 2261, 2261, 2262, 2262, 2262, 2262, 2262, 2262, 2263, 2263, 2263, 2263, 2263, 2263, 2264, 2264, 2264, 2264, 2264, 2264, 2265, 2265, 2265, 2265, 2265, 2265, 2266, 2266, 2267, 2267, 2267, 2267, 2267, 2267, 2268, 2268, 2268, 2268, 2268, 2268, 2269, 2269, 2269, 2269, 2269, 2269, 2270, 2270, 2270, 2270, 2270, 2270, 2271, 2271, 2271, 2271, 2271, 2271, 2272, 2272, 2272, 2272, 2272, 2272, 2273, 2273, 2273, 2273, 2273, 2273, 2274, 0, 0, 0, 2274, 2274, 2275, 2275, 2275, 2275, 2275, 2275, 2276, 2276, 2276, 2276, 2276, 2276, 2277, 2277, 2277, 2277, 2277, 2277, 2278, 2278, 2278, 2278, 2278, 2278, 2279, 2279, 2279, 2279, 2279, 2279, 2280, 2280, 2280, 2280, 2280, 2280, 2281, 2281, 2281, 2281, 2281, 2281, 2282, 2282, 2282, 2282, 2282, 2282, 2283, 2283, 2283, 2283, 2283, 2283, 2284, 2284, 2284, 2284, 2284, 2284, 2285, 2285, 2285, 2285, 2285, 2285, 2286, 0, 0, 0, 2286, 2286, 2287, 2287, 2287, 2287, 2287, 2287, 2288, 2288, 2288, 2288, 2288, 2288, 2289, 2289, 2289, 2289, 2289, 2289, 2290, 2290, 2290, 2290, 2290, 2290, 2291, 2291, 2291, 2291, 2291, 2291, 2292, 2292, 2292, 2292, 2292, 2292, 2293, 2293, 2293, 2293, 2293, 2293, 2294, 0, 0, 0, 2294, 2294, 2295, 2295, 2295, 2295, 2295, 2295, 2296, 2296, 2296, 2296, 2296, 2296, 2297, 2297, 2297, 2297, 2297, 2297, 2298, 2298, 2298, 2298, 2298, 2298, 2299, 2299, 2299, 2299, 2299, 2299, 2300, 2300, 2300, 2300, 2300, 2300, 2301, 2301, 2301, 2301, 2301, 2301, 2302, 2302, 2302, 2302, 2302, 2302, 2303, 2303, 2303, 2303, 2303, 2303, 2304, 2304, 0, 2304, 2304, 2304, 2305, 0, 0, 0, 2305, 2305, 2306, 2306, 2306, 2306, 2306, 2306, 2307, 2307, 2307, 2307, 2307, 2307, 2308, 2308, 2308, 2308, 2308, 2308, 2309, 2309, 2309, 2309, 2309, 2309, 2310, 2310, 2311, 2311, 2311, 2311, 2311, 2311, 2312, 2312, 2312, 2312, 2312, 2312, 2313, 2313, 2313, 2313, 2313, 2313, 2314, 2314, 2314, 2314, 2314, 2314, 2315, 2315, 2315, 2315, 2315, 2315, 2316, 2316, 2316, 2316, 2316, 2316, 2317, 2317, 2317, 2317, 2317, 2317, 2318, 0, 0, 0, 2318, 2318, 2319, 2319, 2319, 2319, 2319, 2319, 2320, 2320, 2320, 2320, 2320, 2320, 2321, 2321, 2321, 2321, 2321, 2321, 2322, 2322, 2322, 2322, 2322, 2322, 2323, 2323, 2323, 2323, 2323, 2323, 2324, 2324, 2324, 2324, 2324, 2324, 2325, 2325, 2325, 2325, 2325, 2325, 2326, 2326, 2326, 2326, 2326, 2326, 2327, 2327, 2327, 2327, 2327, 2327, 2328, 2328, 2328, 2328, 2328, 2328, 2329, 2329, 2329, 2329, 2329, 2329, 2330, 2330, 2330, 2330, 2330, 2330, 2331, 2331, 2331, 2331, 2331, 2331, 2332, 2332, 2332, 2332, 2332, 2332, 2333, 0, 0, 0, 2333, 2333, 2334, 2334, 2334, 2334, 2334, 2334, 2335, 2335, 2335, 2335, 2335, 2335, 2336, 2336, 2336, 2336, 2336, 2336, 2337, 2337, 2337, 2337, 2337, 2337, 2338, 2338, 2338, 2338, 2338, 2338, 2339, 2339, 2339, 2339, 2339, 2339, 2340, 2340, 2340, 2340, 2340, 2340, 2341, 0, 0, 0, 2341, 2341, 2342, 2342, 2342, 2342, 2342, 2342, 2343, 2343, 2343, 2343, 2343, 2343, 2344, 2344, 2344, 2344, 2344, 2344, 2345, 2345, 2345, 2345, 2345, 2345, 2346, 2346, 2346, 2346, 2346, 2346, 2347, 2347, 2347, 2347, 2347, 2347, 2348, 2348, 2348, 2348, 2348, 2348, 2349, 2349, 2349, 2349, 2349, 2349, 2350, 2350, 2351, 2351, 2351, 2351, 2351, 2351, 2352, 2352, 2352, 2352, 2352, 2352, 2353, 2353, 2353, 2353, 2353, 2353, 2354, 2354, 2354, 2354, 2354, 2354, 2355, 2355, 2355, 2355, 2355, 2355, 2356, 0, 0, 0, 2356, 2356, 2357, 2357, 2357, 2357, 2357, 2357, 2358, 2358, 2358, 2358, 2358, 2358, 2359, 0, 0, 0, 2359, 2359, 2360, 2360, 2360, 2360, 2360, 2360, 2361, 2361, 2361, 2361, 2361, 2361, 2362, 0, 0, 0, 2362, 2362, 2363, 2363, 2363, 2363, 2363, 2363, 2364, 2364, 2364, 2364, 2364, 2364, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982, 1982 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "cflex.l" #line 2 "cflex.l" /* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* LEXER for cfengine */ /* */ /* */ /*******************************************************************/ #include "cfparse.h" #include "cf.defs.h" #include "cf.extern.h" /* Note the %o %a declarations to allow more internal workspace */ #line 3519 "lex.yy.c" #define INITIAL 0 #define INCONTROL 1 #define BRACELIST 2 #define INASSIGN 3 #define CFSERVD 4 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int yylex_destroy (void ); int yyget_debug (void ); void yyset_debug (int debug_flag ); YY_EXTRA_TYPE yyget_extra (void ); void yyset_extra (YY_EXTRA_TYPE user_defined ); FILE *yyget_in (void ); void yyset_in (FILE * in_str ); FILE *yyget_out (void ); void yyset_out (FILE * out_str ); int yyget_leng (void ); char *yyget_text (void ); int yyget_lineno (void ); void yyset_lineno (int line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap (void ); #else extern int yywrap (void ); #endif #endif static void yyunput (int c,char *buf_ptr ); #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ int n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int yylex (void); #define YY_DECL int yylex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 86 "cflex.l" #line 3709 "lex.yy.c" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! YY_CURRENT_BUFFER ) { yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of yytext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1983 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 10354 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 89 "cflex.l" { DaemonOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN CFSERVD; SetAction(admit); return ADMIT; } YY_BREAK case 2: YY_RULE_SETUP #line 101 "cflex.l" { DaemonOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN CFSERVD; SetAction(admit); return ADMIT; } YY_BREAK case 3: YY_RULE_SETUP #line 112 "cflex.l" { DaemonOnly; InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN CFSERVD; SetAction(deny); return DENY; } YY_BREAK case 4: YY_RULE_SETUP #line 122 "cflex.l" { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INCONTROL; SetAction(control); return CONTROL; } YY_BREAK case 5: YY_RULE_SETUP #line 133 "cflex.l" { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(strategies); return STRATEGIES; } YY_BREAK case 6: YY_RULE_SETUP #line 143 "cflex.l" { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INCONTROL; SetAction(groups); return GROUPS; } YY_BREAK case 7: YY_RULE_SETUP #line 153 "cflex.l" { /* Synonym for groups */ Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INCONTROL; SetAction(groups); return GROUPS; } YY_BREAK case 8: YY_RULE_SETUP #line 163 "cflex.l" { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(acls); return ACL; } YY_BREAK case 9: YY_RULE_SETUP #line 175 "cflex.l" { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(filters); return FILTERS; } YY_BREAK case 10: YY_RULE_SETUP #line 187 "cflex.l" { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INITIAL; SetAction(ActionStringToCode(yytext)); return ACTIONTYPE; } YY_BREAK case 11: YY_RULE_SETUP #line 199 "cflex.l" { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INITIAL; SetAction(ActionStringToCode(yytext)); return ACTIONTYPE; } YY_BREAK case 12: YY_RULE_SETUP #line 209 "cflex.l" { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(editfiles); return EDITFILES; } YY_BREAK case 13: /* rule 13 can match eol */ YY_RULE_SETUP #line 221 "cflex.l" { LINENUMBER++; } YY_BREAK case 14: /* rule 14 can match eol */ YY_RULE_SETUP #line 225 "cflex.l" { } YY_BREAK case 15: YY_RULE_SETUP #line 228 "cflex.l" { ResetLine((char *)yytext+6); } YY_BREAK case 16: YY_RULE_SETUP #line 232 "cflex.l" { } YY_BREAK case 17: YY_RULE_SETUP #line 236 "cflex.l" { Debug1("LFARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINKCHILDREN = true; FORCELINK='y'; return LARROW; } YY_BREAK case 18: YY_RULE_SETUP #line 245 "cflex.l" { Debug1("FARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINK = true; FORCELINK='y'; return ARROW; } YY_BREAK case 19: YY_RULE_SETUP #line 253 "cflex.l" { Debug1("ARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINK = true; FORCELINK='n'; return ARROW; } YY_BREAK case 20: YY_RULE_SETUP #line 262 "cflex.l" { Debug1("LARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINKCHILDREN = true; FORCELINK='n'; return LARROW; } YY_BREAK case 21: YY_RULE_SETUP #line 271 "cflex.l" { Debug1("EQUALS %s\n",yytext); return EQUALS; } YY_BREAK case 22: YY_RULE_SETUP #line 277 "cflex.l" { Debug1("\nNEW CLASS PREDICATE:: %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ yytext[strlen((char *)yytext)-2] = '\0'; HandleClass(yytext); return PARSECLASS; } YY_BREAK case 23: YY_RULE_SETUP #line 288 "cflex.l" { Debug1("LVALUE %s\n",yytext); HandleLValue(yytext); return LVALUE; } YY_BREAK case 24: YY_RULE_SETUP #line 294 "cflex.l" { Debug1("BRACELIST-CLASSIFIER %s\n",yytext); HandleBraceObjectClassifier(yytext); return BCLASS; } YY_BREAK case 25: YY_RULE_SETUP #line 300 "cflex.l" { Debug1("BRACELIST-ID %s\n",yytext); if (ACTION == editfiles) /* Syntax different for editfiles :( */ { HandleBraceObjectClassifier(yytext); } else { HandleBraceObjectID(yytext); } return ID; } YY_BREAK case 26: YY_RULE_SETUP #line 315 "cflex.l" { Debug1("LEFTBRACK\n"); BEGIN INASSIGN; return LBRACK; } YY_BREAK case 27: YY_RULE_SETUP #line 321 "cflex.l" { bzero(FILTERNAME,CF_BUFSIZE); /* Reset */ bzero(STRATEGYNAME,CF_BUFSIZE); /* Reset */ Debug1("LBRACE\n"); return LBRACE; } YY_BREAK case 28: YY_RULE_SETUP #line 329 "cflex.l" { Debug1("RIGHTBRACK\n\n"); /* If this is a method, load the received arguments as soon as possible */ if (!GOTMETHODARGS && (METHODARGS != NULL)) { Verbose("This looks like a private method, adding parameters.\n"); CheckForMethod(); GOTMETHODARGS = true; } BEGIN INCONTROL; return RBRACK; } YY_BREAK case 29: YY_RULE_SETUP #line 345 "cflex.l" { Debug1("RBRACE\n"); if (EDITGROUPLEVEL != 0) { yyerror("Editfiles Begin/End mismatch before or at line"); } if (SEARCHREPLACELEVEL != 0) { yyerror("ReplaceAll/With mismatch before or at line"); } if (FOREACHLEVEL != 0) { yyerror("ForEachLineIn/EndLoop mismatch before or at line"); } InstallPending(ACTION); InitializeAction(); return RBRACE; } YY_BREAK case 30: /* rule 30 can match eol */ YY_RULE_SETUP #line 371 "cflex.l" { char *sp = NULL; int less = 0; Debug1("RVAL-QSTRING %s\n",yytext); if ((sp = malloc(strlen(yytext)+1)) == NULL) { FatalError("Malloc failure in parsing"); } if((less = RemoveEscapeSequences(yytext,sp)) > 0) { Debug1("QSTRING-LESS %d\n",less); yyless(less); } switch (ACTION) { case control: InstallControlRValue(CURRENTITEM,sp); free(sp); return RVALUE; case groups: HandleGroupRValue(sp); free(sp); return RVALUE; } } YY_BREAK case 31: /* rule 31 can match eol */ YY_RULE_SETUP #line 401 "cflex.l" { char *sp = NULL; int less = 0; Debug1("QSTRING %s\n",yytext); if ((sp = malloc(strlen(yytext)+1)) == NULL) { FatalError("Malloc failure in parsing"); } if ((less = RemoveEscapeSequences(yytext,sp)) > 0) { Debug1("QSTRING-LESS %d\n",less); yyless(less); } HandleQuotedString(sp); free(sp); return QSTRING; } YY_BREAK case 32: /* rule 32 can match eol */ YY_RULE_SETUP #line 422 "cflex.l" { Debug1("RVAL-FUNCTION %s\n",yytext); HandleFunctionObject(yytext); return FUNCTION; } YY_BREAK case 33: /* rule 33 can match eol */ YY_RULE_SETUP #line 430 "cflex.l" { Debug1("FUNCTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ if (ACTION == alerts) { ACTIONPENDING = true; } HandleFunctionObject(yytext); return FUNCTION; } YY_BREAK case 34: YY_RULE_SETUP #line 445 "cflex.l" { Debug1("\nOPTION %s\n",yytext); HandleOption(yytext); return OPTION; } YY_BREAK case 35: YY_RULE_SETUP #line 451 "cflex.l" { Debug1("VAROBJ %s\n",yytext); if ((ACTION_IS_LINK || ACTION_IS_LINKCHILDREN) && (strlen(LINKTO)==0)) { Debug("Pending link destination...\n"); } else { /* Check anomalour process syntax */ if (ACTION == processes && (strcmp(ToLowerStr(yytext),"restart") == 0 || HAVE_RESTART || strcmp(ToLowerStr(yytext),"setoptionstring") == 0)) { } else if (ACTIONPENDING) { InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ } } IsVarString(yytext); /* Syntax check */ HandleVarObject(yytext); return VAROBJ; } YY_BREAK case 36: YY_RULE_SETUP #line 478 "cflex.l" { Debug1("RVAL-VAROBJ %s\n",yytext); switch(ACTION) { case control: InstallControlRValue(CURRENTITEM,yytext); return RVALUE; case groups: HandleGroupRValue(yytext); return RVALUE; default: yyerror("Misplaced assignment"); } } YY_BREAK case 37: YY_RULE_SETUP #line 494 "cflex.l" { Debug1("BRACELIST-VAROBJ %s\n",yytext); if (ACTION == acls && strlen(CURRENTOBJECT) > 0) /* Irregular acl syntax */ { HandleBraceObjectClassifier(yytext); } else { HandleBraceObjectID(yytext); } return VAROBJ; } YY_BREAK case 38: YY_RULE_SETUP #line 508 "cflex.l" { Debug1("\nCFSERVD-VAROBJ %s\n",yytext); HandleServerRule(yytext); return ACCESSOBJ; } YY_BREAK case 39: YY_RULE_SETUP #line 515 "cflex.l" { printf("Stray character (%s)",yytext); return yytext[0]; } YY_BREAK case 40: YY_RULE_SETUP #line 520 "cflex.l" ECHO; YY_BREAK #line 4339 "lex.yy.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(INCONTROL): case YY_STATE_EOF(BRACELIST): case YY_STATE_EOF(INASSIGN): case YY_STATE_EOF(CFSERVD): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( yywrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart(yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1983 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { register int yy_is_jam; register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 1983 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 1982); return yy_is_jam ? 0 : yy_current_state; } static void yyunput (int c, register char * yy_bp ) { register char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up yytext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart(yyin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( yywrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve yytext */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void yyrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ yyensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = yy_create_buffer(yyin,YY_BUF_SIZE ); } yy_init_buffer(YY_CURRENT_BUFFER,input_file ); yy_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * yypop_buffer_state(); * yypush_buffer_state(new_buffer); */ yyensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; yy_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void yy_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with yy_create_buffer() * */ void yy_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yyfree((void *) b->yy_ch_buf ); yyfree((void *) b ); } #ifndef __cplusplus extern int isatty (int ); #endif /* __cplusplus */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a yyrestart() or at EOF. */ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; yy_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then yy_init_buffer was _probably_ * called from yyrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void yy_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) yy_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; yyensure_buffer_stack(); /* This block is copied from yy_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from yy_switch_to_buffer. */ yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void yypop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { yy_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void yyensure_buffer_stack (void) { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to yylex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * yy_scan_bytes() instead. */ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) { return yy_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to yylex() will * scan from a @e copy of @a bytes. * @param bytes the byte buffer to scan * @param len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) yyalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ yytext[yyleng] = (yy_hold_char); \ (yy_c_buf_p) = yytext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ yyleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int yyget_lineno (void) { return yylineno; } /** Get the input stream. * */ FILE *yyget_in (void) { return yyin; } /** Get the output stream. * */ FILE *yyget_out (void) { return yyout; } /** Get the length of the current token. * */ int yyget_leng (void) { return yyleng; } /** Get the current token. * */ char *yyget_text (void) { return yytext; } /** Set the current line number. * @param line_number * */ void yyset_lineno (int line_number ) { yylineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * * @see yy_switch_to_buffer */ void yyset_in (FILE * in_str ) { yyin = in_str ; } void yyset_out (FILE * out_str ) { yyout = out_str ; } int yyget_debug (void) { return yy_flex_debug; } void yyset_debug (int bdebug ) { yy_flex_debug = bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from yylex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT yyin = stdin; yyout = stdout; #else yyin = (FILE *) 0; yyout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * yylex_init() */ return 0; } /* yylex_destroy is for both reentrant and non-reentrant scanners. */ int yylex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ yy_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; yypop_buffer_state(); } /* Destroy the stack itself. */ yyfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * yylex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *yyalloc (yy_size_t size ) { return (void *) malloc( size ); } void *yyrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void yyfree (void * ptr ) { free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 520 "cflex.l" /* EOF */ cfengine-2.2.10/src/cf.extern.h0000644000175000001440000003373111010517553013130 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ /*******************************************************************/ /* */ /* extern HEADER for cfengine */ /* */ /*******************************************************************/ #include "../pub/getopt.h" #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) extern pthread_mutex_t MUTEX_SYSCALL; extern pthread_mutex_t MUTEX_LOCK; extern pthread_attr_t PTHREADDEFAULTS; extern pthread_mutex_t MUTEX_COUNT; extern pthread_mutex_t MUTEX_HOSTNAME; # endif extern pid_t ALARM_PID; extern short INSTALLALL; extern short ALL_SINGLECOPY; extern int PASS; extern RSA *PRIVKEY, *PUBKEY; extern char BINDINTERFACE[CF_BUFSIZE]; extern struct sock ECGSOCKS[ATTR]; extern char *TCPNAMES[CF_NETATTR]; extern char **METHODARGV; extern int GOTMETHODARGS; extern struct Item *QUERYVARS; extern struct Item *METHODRETURNVARS; extern struct Item *METHODRETURNCLASSES; extern struct Audit *AUDITPTR; extern struct Audit *VAUDIT; extern int PR_KEPT; extern int PR_REPAIRED; extern int PR_NOTKEPT; extern char METHODFILENAME[CF_BUFSIZE]; extern char *VMETHODPROTO[]; extern int METHODARGC; extern char METHODREPLYTO[CF_BUFSIZE]; extern char METHODFOR[CF_BUFSIZE]; extern char METHODFORCE[CF_BUFSIZE]; extern char CONTEXTID[32]; extern char METHODNAME[CF_BUFSIZE]; extern char METHODMD5[CF_BUFSIZE]; extern char PADCHAR; extern struct cfagent_connection *CONN; extern int AUTHENTICATED; extern struct Item *IPADDRESSES; extern char PIDFILE[CF_BUFSIZE]; extern char STR_CFENGINEPORT[16]; extern unsigned short SHORT_CFENGINEPORT; extern char CFLOCK[CF_BUFSIZE]; extern char SAVELOCK[CF_BUFSIZE]; extern char CFLOG[CF_BUFSIZE]; extern char CFLAST[CF_BUFSIZE]; extern char LOCKDB[CF_BUFSIZE]; extern char EDITBUFF[CF_BUFSIZE]; extern char *tzname[2]; extern int CFSIGNATURE; extern char CFDES1[8]; extern char CFDES2[8]; extern char CFDES3[8]; extern char CFPUBKEYFILE[CF_BUFSIZE]; extern char CFPRIVKEYFILE[CF_BUFSIZE]; extern char CFWORKDIR[CF_BUFSIZE]; extern char AVDB[CF_MAXVARSIZE]; extern dev_t ROOTDEVICE; extern char *VPRECONFIG; extern char *VRCFILE; extern char *VARCH; extern char *VARCH2; extern char VYEAR[]; extern char VDAY[]; extern char VMONTH[]; extern char VHR[]; extern char VMINUTE[]; extern char VSEC[]; extern char *ACTIONTEXT[]; extern char *ACTIONID[]; extern char *BUILTINS[]; extern char *CLASSTEXT[]; extern char *CLASSATTRIBUTES[CF_CLASSATTR][CF_ATTRDIM]; extern char *FILEACTIONTEXT[]; extern char *COMMATTRIBUTES[]; extern char VINPUTFILE[]; extern char *VCANONICALFILE; extern char VCURRENTFILE[]; extern char VLOGFILE[]; extern char *CHDIR; extern char *VSETUIDLOG; extern FILE *VLOGFP; extern DB *AUDITDBP; extern short AUDIT; extern char VEDITABORT[]; extern char LISTSEPARATOR; extern char REPOSCHAR; extern char DISCOMP; extern char USESHELL; extern char PREVIEW; extern char PURGE; extern char CHECKSUM; extern char COMPRESS; extern int CHECKSUMUPDATES; extern int DISABLESIZE; extern char VLOGDIR[]; extern char VLOCKDIR[]; extern struct tm TM1; extern struct tm TM2; extern int ERRORCOUNT; extern int NUMBEROFEDITS; extern time_t CFSTARTTIME; extern time_t CFINITSTARTTIME; extern int CF_TIMEOUT; extern struct utsname VSYSNAME; extern int LINENUMBER; extern mode_t DEFAULTMODE; extern mode_t DEFAULTSYSTEMMODE; extern int HAVEUID; extern char *FINDERTYPE; extern char *VUIDNAME; extern char *VGIDNAME; extern char CFSERVER[]; extern char *PROTOCOL[]; extern char VIPADDRESS[]; extern char VPREFIX[]; extern int VRECURSE; extern int VAGE; extern int RPCTIMEOUT; extern char MOUNTMODE; extern char DELETEDIR; extern char DELETEFSTAB; extern char FORCE; extern char FORCEIPV4; extern char FORCELINK; extern char FORCEDIRS; extern char STEALTH; extern char PRESERVETIMES; extern char TRUSTKEY; extern char FORK; extern short FULLENCRYPT; extern short SKIPIDENTIFY; extern short COMPATIBILITY_MODE; extern short LINKSILENT; extern short UPDATEONLY; extern char LINKTYPE; extern char AGETYPE; extern char COPYTYPE; extern char DEFAULTCOPYTYPE; extern char LINKDIRS; extern char LOGP; extern char INFORMP; extern char AUDITP; extern char *FILTERNAME; extern char *STRATEGYNAME; extern char *CURRENTOBJECT; extern char *CURRENTITEM; extern char *GROUPBUFF; extern char *ACTIONBUFF; extern char *CLASSBUFF; extern char ALLCLASSBUFFER[4*CF_BUFSIZE]; extern char CHROOT[CF_BUFSIZE]; extern char ELSECLASSBUFFER[CF_BUFSIZE]; extern char FAILOVERBUFFER[CF_BUFSIZE]; extern char *LINKFROM; extern char *LINKTO; extern char *ERROR; extern char *MOUNTFROM; extern char *MOUNTONTO; extern char *MOUNTOPTS; extern char *DESTINATION; extern char *IMAGEACTION; extern char *EXPR; extern char *CURRENTAUTHPATH; extern char *RESTART; extern char *FILTERDATA; extern char *STRATEGYDATA; extern char *PKGVER; extern short PROSIGNAL; extern char PROACTION; extern char PROCOMP; extern char IMGCOMP; extern int IMGSIZE; extern char *CHECKSUMDB; extern char *COMPRESSCOMMAND; extern char *HASH[CF_HASHTABLESIZE]; extern char VBUFF[CF_BUFSIZE]; extern char OUTPUT[CF_BUFSIZE*2]; extern char VFACULTY[CF_MAXVARSIZE]; extern char VDOMAIN[CF_MAXVARSIZE]; extern char VSYSADM[CF_MAXVARSIZE]; extern char VNETMASK[CF_MAXVARSIZE]; extern char VBROADCAST[CF_MAXVARSIZE]; extern char VMAILSERVER[CF_BUFSIZE]; extern struct Item *VTIMEZONE; extern struct Item *VDEFAULTROUTE; extern char VNFSTYPE[CF_MAXVARSIZE]; extern char *VREPOSITORY; extern char *LOCALREPOS; extern char VIFNAME[16]; extern char VIFNAMEOVERRIDE[16]; extern enum classes VSYSTEMHARDCLASS; extern char VFQNAME[]; extern char VUQNAME[]; extern char LOGFILE[]; extern char *CMPSENSETEXT[]; extern char *CMPSENSEOPERAND[]; extern char NOABSPATH; extern char CHKROOT; extern struct Item *VEXCLUDECACHE; extern struct Item *VSINGLECOPY; extern struct Item *VAUTODEFINE; extern struct Item *VEXCLUDECOPY; extern struct Item *VEXCLUDELINK; extern struct Item *VCOPYLINKS; extern struct Item *VLINKCOPIES; extern struct Item *VEXCLUDEPARSE; extern struct Item *VCPLNPARSE; extern struct Item *VINCLUDEPARSE; extern struct Item *VIGNOREPARSE; extern struct Item *VACLBUILD; extern struct Item *VFILTERBUILD; extern struct Item *VSTRATEGYBUILD; extern struct Item *VMOUNTLIST; extern struct Item *VHEAP; /* Points to the base of the attribute heap */ extern struct Item *VNEGHEAP; extern struct Item *ABORTHEAP; /* For packages: */ extern struct Package *VPKG; extern struct Package *VPKGTOP; /* HvB : Bas van der Vlies */ extern struct Mountables *VMOUNTABLES; /* Points to the list of mountables */ extern struct Mountables *VMOUNTABLESTOP; extern struct cfObject *VOBJTOP; extern struct cfObject *VOBJ; extern char *PARSEMETHODRETURNCLASSES; extern struct Item *METHODARGS; extern flag CF_MOUNT_RO; /* mount directory readonly */ extern struct Item *VALERTS; extern struct Item *VMOUNTED; extern struct Tidy *VTIDY; /* Points to the list of tidy specs */ extern struct Disk *VREQUIRED; /* List of required file systems */ extern struct Disk *VREQUIREDTOP; extern struct ShellComm *VSCRIPT; /* List of scripts to execute */ extern struct ShellComm *VSCRIPTTOP; extern struct ShellComm *VSCLI; extern struct ShellComm *VSCLITOP; extern struct Interface *VIFLIST; extern struct Interface *VIFLISTTOP; extern struct Mounted *MOUNTED; /* Files systems already mounted */ extern struct Item VDEFAULTBINSERVER; extern struct Item *VBINSERVERS; extern struct Link *VLINK; extern struct File *VFILE; extern struct Item *VHOMESERVERS; extern struct Item *VSETUIDLIST; extern struct Disable *VDISABLELIST; extern struct Disable *VDISABLETOP; extern struct File *VMAKEPATH; extern struct File *VMAKEPATHTOP; extern struct Link *VCHLINK; extern struct Item *VIGNORE; extern struct Item *VHOMEPATLIST; extern struct Item *EXTENSIONLIST; extern struct Item *SUSPICIOUSLIST; extern struct Item *SCHEDULE; extern struct Item *SPOOLDIRLIST; extern struct Item *NONATTACKERLIST; extern struct Item *MULTICONNLIST; extern struct Item *TRUSTKEYLIST; extern struct Item *DHCPLIST; extern struct Item *ALLOWUSERLIST; extern struct Item *SKIPVERIFY; extern struct Item *ATTACKERLIST; extern struct Item *MOUNTOPTLIST; extern struct Item *VRESOLVE; extern struct MiscMount *VMISCMOUNT; extern struct MiscMount *VMISCMOUNTTOP; extern struct Item *VIMPORT; extern struct Item *VACTIONSEQ; extern struct Item *VACCESSLIST; extern struct Item *VADDCLASSES; extern struct Item *VALLADDCLASSES; extern struct Item *VJUSTACTIONS; extern struct Item *VAVOIDACTIONS; extern struct Edit *VEDITLIST; extern struct Edit *VEDITLISTTOP; extern struct Filter *VFILTERLIST; extern struct Filter *VFILTERLISTTOP; extern struct Strategy *VSTRATEGYLIST; extern struct Strategy *VSTRATEGYLISTTOP; extern struct CFACL *VACLLIST; extern struct CFACL *VACLLISTTOP; extern struct UnMount *VUNMOUNT; extern struct UnMount *VUNMOUNTTOP; extern struct Item *VCLASSDEFINE; extern struct Image *VIMAGE; extern struct Image *VIMAGETOP; extern struct Method *VMETHODS; extern struct Method *VMETHODSTOP; extern struct Process *VPROCLIST; extern struct Process *VPROCTOP; extern struct Item *VSERVERLIST; extern struct Item *VRPCPEERLIST; extern struct Item *VREDEFINES; extern struct Item *VREPOSLIST; extern struct Auth *VADMIT; extern struct Auth *VDENY; extern struct Auth *VADMITTOP; extern struct Auth *VDENYTOP; /* Associated variables which simplify logic */ extern struct Link *VLINKTOP; extern struct Link *VCHLINKTOP; extern struct Tidy *VTIDYTOP; extern struct File *VFILETOP; extern char *COPYRIGHT; extern short DEBUG; extern short D1; extern short D2; extern short D3; extern short D4; extern short PARSING; extern short SHOWDB; extern short ISCFENGINE; extern short LASTSEEN; extern short VERBOSE; extern short EXCLAIM; extern short INFORM; extern short CHECK; extern int PIFELAPSED; extern int PEXPIREAFTER; extern short LOGGING; extern short INFORM_save; extern short LOGGING_save; extern short CFPARANOID; extern short SHOWACTIONS; extern short LOGTIDYHOMEFILES; extern char TIDYDIRS; extern short TRAVLINKS; extern short DEADLINKS; extern short PTRAVLINKS; extern short DONTDO; extern short IFCONF; extern short PARSEONLY; extern short GOTMOUNTINFO; extern short NOMOUNTS; extern short NOMODULES; extern short NOPROCS; extern short NOMETHODS; extern short NOFILECHECK; extern short NOTIDY; extern short NOSCRIPTS; extern short PRSYSADM; extern short PRSCHEDULE; extern short MOUNTCHECK; extern short NOEDITS; extern short KILLOLDLINKS; extern short IGNORELOCK; extern short NOPRECONFIG; extern short WARNINGS; extern short NONALPHAFILES; extern short MINUSF; extern short NOLINKS; extern short ENFORCELINKS; extern short NOCOPY; extern short FORCENETCOPY; extern short SILENT; extern short EDITVERBOSE; extern char IMAGEBACKUP; extern short ROTATE; extern int TIDYSIZE; extern short USEENVIRON; extern short PROMATCHES; extern short EDABORTMODE; extern short NOPROCS; extern short UNDERSCORE_CLASSES; extern short NOHARDCLASSES; extern short NOSPLAY; extern short DONESPLAY; extern char XDEV; extern char RXDIRS; extern char TYPECHECK; extern char SCAN; extern enum actions ACTION; extern enum vnames CONTROLVAR; extern mode_t PLUSMASK; extern mode_t MINUSMASK; extern u_long PLUSFLAG; extern u_long MINUSFLAG; extern flag ACTION_IS_LINK; extern flag ACTION_IS_LINKCHILDREN; extern flag MOUNT_ONTO; extern flag MOUNT_FROM; extern flag HAVE_RESTART; extern flag ACTIONPENDING; extern flag HOMECOPY; extern char ENCRYPT; extern char VERIFY; extern char COMPATIBILITY; extern char *VPSCOMM[]; extern char *VPSOPTS[]; extern char *VMOUNTCOMM[]; extern char *VMOUNTOPTS[]; extern char *VIFDEV[]; extern char *VETCSHELLS[]; extern char *VRESOLVCONF[]; extern char *VHOSTEQUIV[]; extern char *VFSTAB[]; extern char *VMAILDIR[]; extern char *VNETSTAT[]; extern char *VROUTE[]; extern char *VROUTEADDFMT[]; extern char *VROUTEDELFMT[]; extern char *VFILECOMM[]; extern char *ACTIONSEQTEXT[]; extern char *VEDITNAMES[]; extern char *VFILTERNAMES[]; extern char *VUNMOUNTCOMM[]; extern char *VRESOURCES[]; extern char *PKGMGRTEXT[]; extern char *PKGACTIONTEXT[]; extern int VTIMEOUT; extern mode_t UMASK; extern char *SIGNALS[]; extern char *tzname[2]; /* see man ctime */ extern int SENSIBLEFILECOUNT; extern int SENSIBLEFSSIZE; extern int EDITFILESIZE; extern int EDITBINFILESIZE; extern int VIFELAPSED; extern int VEXPIREAFTER; extern int VDEFAULTIFELAPSED; extern int VDEFAULTEXPIREAFTER; extern int AUTOCREATED; extern enum fileactions FILEACTION; extern enum cmpsense CMPSENSE; extern enum pkgmgrs PKGMGR; extern enum pkgmgrs DEFAULTPKGMGR; extern enum pkgactions PKGACTION; extern unsigned short PORTNUMBER; extern int CURRENTLINENUMBER; extern struct Item *CURRENTLINEPTR; extern int EDITGROUPLEVEL; extern int SEARCHREPLACELEVEL; extern int FOREACHLEVEL; extern char COMMENTSTART[], COMMENTEND[]; extern char *OBS[CF_OBSERVABLES][2]; extern char *CF_SCLICODES[CF_MAX_SCLICODES][2]; /* GNU REGEXP */ extern struct re_pattern_buffer *SEARCHPATTBUFF; extern struct re_pattern_buffer *PATTBUFFER; extern char *CF_DIGEST_TYPES[4][2]; extern int CF_DIGEST_SIZES[4]; cfengine-2.2.10/src/modes.c0000644000175000001440000001515410362013221012325 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /***************************************************************/ /* Modestring toolkit */ /***************************************************************/ void ParseModeString(char *modestring,mode_t *plusmask,mode_t *minusmask) { char *sp; int affected = 0, value = 0, gotaction; char action = '='; enum modestate state = unknown; enum modesort found_sort = unknown; /* Already found "sort" of mode */ enum modesort sort = unknown; /* Sort of started but not yet finished mode */ if (modestring == NULL) { return; } Debug1("ParseModeString(%s)\n",modestring); gotaction = false; *plusmask = *minusmask = 0; for (sp = modestring; true ; sp++) { switch (*sp) { case 'a': CheckModeState(who,state,symbolic,sort,*sp); affected |= 07777; sort = symbolic; break; case 'u': CheckModeState(who,state,symbolic,sort,*sp); affected |= 04700; sort = symbolic; break; case 'g': CheckModeState(who,state,symbolic,sort,*sp); affected |= 02070; sort = symbolic; break; case 'o': CheckModeState(who,state,symbolic,sort,*sp); affected |= 00007; sort = symbolic; break; case '+': case '-': case '=': if (gotaction) { yyerror("Too many +-= in mode string"); } CheckModeState(who,state,symbolic,sort,*sp); action = *sp; state = which; gotaction = true; sort = unknown; break; case 'r': CheckModeState(which,state,symbolic,sort,*sp); value |= 0444 & affected; sort = symbolic; break; case 'w': CheckModeState(which,state,symbolic,sort,*sp); value |= 0222 & affected; sort = symbolic; break; case 'x': CheckModeState(which,state,symbolic,sort,*sp); value |= 0111 & affected; sort = symbolic; break; case 's': CheckModeState(which,state,symbolic,sort,*sp); value |= 06000 & affected; sort = symbolic; break; case 't': CheckModeState(which,state,symbolic,sort,*sp); value |= 01000; sort = symbolic; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': CheckModeState(which,state,numeric,sort,*sp); sort = numeric; gotaction = true; state = which; affected = 07777; /* TODO: Hard-coded; see below */ sscanf(sp,"%o",&value); if (value > 07777) /* TODO: Hardcoded ! Is this correct for all sorts of Unix ? What about NT ? Any (POSIX)-constants ?? */ { yyerror("Mode-Value too big !\n"); } while (isdigit((int)*sp) && (*sp != '\0')) { sp++; } sp--; break; case ',': SetMask(action,value,affected,plusmask,minusmask); if (found_sort != unknown && found_sort != sort) { Warning("Symbolic and numeric form for modes mixed"); } found_sort = sort; sort = unknown; action = '='; affected = 0; value = 0; gotaction = false; state = who; break; case '\0': if (state == who || value == 0) { if (strcmp(modestring,"0000") != 0 && strcmp(modestring,"000") != 0) { Warning("mode string is incomplete"); } } SetMask(action,value,affected,plusmask,minusmask); if (found_sort != unknown && found_sort != sort) { Warning("Symbolic and numeric form for modes mixed"); } Debug1("[PLUS=%o][MINUS=%o]\n",*plusmask,*minusmask); return; default: snprintf(OUTPUT,CF_BUFSIZE,"Invalid mode string (%s)",modestring); yyerror (OUTPUT); break; } } } /*********************************************************/ void CheckModeState(enum modestate stateA,enum modestate stateB,enum modesort sortA,enum modesort sortB,char ch) { if ((stateA != wild) && (stateB != wild) && (stateA != stateB)) { sprintf(VBUFF,"Mode string constant (%c) used out of context",ch); yyerror(VBUFF); } if ((sortA != unknown) && (sortB != unknown) && (sortA != sortB)) { yyerror("Symbolic and numeric filemodes mixed within expression"); } } /*********************************************************/ void SetMask(char action,int value,int affected,mode_t *p,mode_t *m) { Debug1("SetMask(%c%o,%o)\n",action,value,affected); switch(action) { case '+': *p |= value; *m |= 0; return; case '-': *p |= 0; *m |= value; return; case '=': *p |= value; *m |= ((~value) & 07777 & affected); return; default: sprintf(VBUFF,"Mode directive %c is unknown",action); yyerror(VBUFF); return; } } cfengine-2.2.10/src/mount.c0000644000175000001440000000663510202123552012366 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ /* Mount support toolkit */ /*********************************************************************/ int MountPathDefined() { if (VMOUNTLIST == NULL) { CfLog(cfinform,"Program does not define mountpattern\n",""); return false; } return true; } /*********************************************************************/ int MatchAFileSystem(char *server,char *lastlink) { struct Item *mp; char *sp; char host[CF_MAXVARSIZE]; for (mp = VMOUNTED; mp != NULL; mp=mp->next) { sscanf (mp->name,"%[^:]",host); if (! IsItemIn(VBINSERVERS,host)) { continue; } if (strcmp(host,VDEFAULTBINSERVER.name) == 0) { continue; /* Can't link machine to itself! */ } for (sp = mp->name+strlen(mp->name); *(sp-1) != '/'; sp--) { } if (IsHomeDir(sp)) { continue; } if (strcmp(sp,lastlink) == 0) { strcpy(server,mp->name+strlen(host)+1); return(true); } } return(false); } /*********************************************************************/ int IsMountedFileSystem (struct stat *childstat,char *dir,int rlevel) /* Is FS NFS mounted ? */ { struct stat parentstat; struct Mountables *mp; char host[CF_MAXVARSIZE]; for (mp = VMOUNTABLES; mp !=NULL; mp=mp->next) { if (strstr(mp->filesystem,dir)) { sscanf(mp->filesystem,"%[^:]",host); Debug("Looking at filesystem %s on %s\n",mp->filesystem,host); if (strncmp(host,VFQNAME,strlen(host)) == 0) { Verbose("Filesystem %s belongs to this host\n",dir); return false; } } } strcpy(VBUFF,dir); if (VBUFF[strlen(VBUFF)-1] == '/') { strcat(VBUFF,".."); } else { strcat(VBUFF,"/.."); } if (stat(VBUFF,&parentstat) == -1) { Debug2("File %s couldn't stat its parent directory! Assuming permission\n",dir); Debug2("is denied because the file system is mounted from another host.\n"); return(true); } if (rlevel == 0) /* If this is the root of a search, don't stop before we started ! */ { Debug("NotMountedFileSystem\n"); return false; } if (childstat->st_dev != parentstat.st_dev) { Debug2("[%s is on a different file system, not descending]\n",dir); return (true); } Debug("NotMountedFileSystem\n"); return(false); } cfengine-2.2.10/src/df.c0000644000175000001440000001133511065763341011624 00000000000000/* Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Disk usage module, Demosthenes Skipitaris */ /* */ /*******************************************************************/ #include "../pub/getopt.h" #include "cf.defs.h" #include "cf.extern.h" #ifdef HAVE_SYS_STATFS_H #include #endif #ifdef HAVE_SYS_VFS_H #include #endif #ifdef HAVE_SYS_STATVFS_H #include #endif /************************************************************************/ int GetDiskUsage (char *file,enum cfsizes type) { #if defined SOLARIS || defined OSF || defined UNIXWARE || (defined(__NetBSD__) && __NetBSD_Version__ >= 200040000) struct statvfs buf; #elif defined ULTRIX struct fs_data buf; #else struct statfs buf; #endif u_long blocksize = 1024, total = 0, used = 0, avail = 0; int capacity = 0; memset(&buf,0,sizeof(buf)); #if defined ULTRIX if (getmnt (NULL, &buf, sizeof (struct fs_data), STAT_ONE, file) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't get filesystem info for %s\n",file); CfLog(cferror,OUTPUT,""); return CF_INFINITY; } #elif defined SOLARIS || defined OSF || defined UNIXWARE || (defined(__NetBSD__) && __NetBSD_Version__ >= 200040000) if (statvfs (file, &buf) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't get filesystem info for %s\n",file); CfLog(cferror,OUTPUT,""); return CF_INFINITY; } #elif defined IRIX || defined SCO || defined CFCRAY || (defined(__NetBSD__) && __NetBSD_Version__ >= 200040000) if (statfs (file, &buf, sizeof (struct statfs), 0) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't get filesystem info for %s\n",file); CfLog(cferror,OUTPUT,""); return CF_INFINITY; } #else if (statfs (file, &buf) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't get filesystem info for %s\n",file); CfLog(cferror,OUTPUT,""); return CF_INFINITY; } #endif #if defined ULTRIX total = buf.fd_btot; used = buf.fd_btot - buf.fd_bfree; avail = buf.fd_bfreen; #endif #if defined SOLARIS total = buf.f_blocks * (buf.f_frsize / blocksize); used = (buf.f_blocks - buf.f_bfree) * (buf.f_frsize / blocksize); avail = buf.f_bavail * (buf.f_frsize / blocksize); #endif #if defined NETBSD || defined FREEBSD || defined OPENBSD || defined SUNOS || defined HPuUX || defined DARWIN total = buf.f_blocks; used = buf.f_blocks - buf.f_bfree; avail = buf.f_bavail; #endif #if defined OSF total = (buf.f_blocks * buf.f_frsize) / blocksize; used = ((buf.f_blocks - buf.f_bfree)* (buf.f_frsize) / blocksize); avail = (buf.f_bavail * buf.f_frsize) / blocksize; #endif #if defined AIX || defined SCO || defined CFCRAY total = buf.f_blocks * ((float)buf.f_bsize / blocksize); used = (buf.f_blocks - buf.f_bfree) * ((float)buf.f_bsize / blocksize); avail = buf.f_bfree * ((float)buf.f_bsize / blocksize); #endif #if defined LINUX total = buf.f_blocks * ((float)buf.f_bsize / blocksize); used = (buf.f_blocks - buf.f_bfree) * ((float)buf.f_bsize / blocksize); avail = buf.f_bavail * ((float)buf.f_bsize / blocksize); #endif #if defined IRIX /* Float fix by arjen@sara.nl */ total = buf.f_blocks * ((float)buf.f_bsize / blocksize); used = (buf.f_blocks - buf.f_bfree) * ((float)buf.f_bsize / blocksize); avail = buf.f_bfree * ((float)buf.f_bsize/blocksize); #endif capacity = (double) (avail) / (double) (avail + used) * 100; Debug2("GetDiskUsage(%s) = %d/%d\n",file,avail,capacity); /* Free kilobytes */ if (type == cfabs) { return avail; } else { return capacity; } } cfengine-2.2.10/src/wrapper.c0000644000175000001440000002355311114312753012710 00000000000000/* Copyright (C) 1995-2000 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: wrapper.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*******************************************************************/ /* These functions are wrappers for the real functions so that we can abstract the task of parsing general wildcard paths like /a*b/bla?/xyz from a single function ExpandWildCardsAndDo() */ /*******************************************************************/ void TidyWrapper(char *startpath,void *vp) { struct Tidy *tp; struct stat sb; tp = (struct Tidy *) vp; Debug2("TidyWrapper(%s)\n",startpath); if (tp->done == 'y') { return; } tp->done = 'y'; if (!GetLock(ASUniqueName("tidy"),CanonifyName(startpath),tp->ifelapsed,tp->expireafter,VUQNAME,CFSTARTTIME)) { return; } if (stat(startpath,&sb) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Tidy directory %s cannot be accessed",startpath); CfLog(cfinform,OUTPUT,"stat"); ReleaseCurrentLock(); return; } RegisterRecursionRootDevice(sb.st_dev); RecursiveTidySpecialArea(startpath,tp,tp->maxrecurse,&sb); tp->done = 'y'; ReleaseCurrentLock(); } /*******************************************************************/ void RecHomeTidyWrapper(char *startpath,void *vp) { struct stat sb; struct Tidy *tp = (struct Tidy *) vp; Verbose("Tidying Home partition %s...\n",startpath); if (tp != NULL) { if (!GetLock(ASUniqueName("tidy"),CanonifyName(startpath),tp->ifelapsed,tp->expireafter,VUQNAME,CFSTARTTIME)) { return; } } else { if (!GetLock(ASUniqueName("tidy"),CanonifyName(startpath),VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME)) { return; } } if (stat(startpath,&sb) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Tidy directory %s cannot be accessed",startpath); CfLog(cfinform,OUTPUT,"stat"); ReleaseCurrentLock(); return; } RegisterRecursionRootDevice(sb.st_dev); RecursiveHomeTidy(startpath,1,&sb); ReleaseCurrentLock(); } /*******************************************************************/ void CheckFileWrapper(char *startpath,void *vp) { struct stat statbuf; mode_t filemode; char *lastnode, lock[CF_MAXVARSIZE]; int fd; struct File *ptr; ptr = (struct File *)vp; if (ptr->uid != NULL) { snprintf(lock,CF_MAXVARSIZE-1,"%s_%o_%o_%d",startpath,ptr->plus,ptr->minus,ptr->uid->uid); } else { snprintf(lock,CF_MAXVARSIZE-1,"%s_%o_%o",startpath,ptr->plus,ptr->minus); } if (!GetLock(ASUniqueName("files"),CanonifyName(lock),ptr->ifelapsed,ptr->expireafter,VUQNAME,CFSTARTTIME)) { return; } if ((strlen(startpath) == 0) || (startpath == NULL)) { return; } if (ptr->action == touch && IsWildCard(ptr->path)) { printf("%s: Can't touch a wildcard! (%s)\n",VPREFIX,ptr->path); return; } for (lastnode = startpath+strlen(startpath)-1; *lastnode != '/'; lastnode--) { } lastnode++; if (ptr->inclusions != NULL && !IsWildItemIn(ptr->inclusions,lastnode)) { Debug2("cfengine: skipping non-included pattern %s\n",lastnode); if (stat(startpath,&statbuf) != -1) { if (!S_ISDIR(statbuf.st_mode)) { return; /* assure that we recurse into directories */ } } } if (IsWildItemIn(ptr->exclusions,lastnode)) { Debug2("Skipping excluded pattern file %s\n",lastnode); ReleaseCurrentLock(); return; } Debug("Checking wrapped file object %s\n",ptr->path); if (stat(startpath,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot access file/directory %s\n",ptr->path); CfLog(cfinform,OUTPUT,"stat"); if (TouchDirectory(ptr)) /* files ending in /. */ { MakeDirectoriesFor(startpath,'n'); ptr->action = fixall; *(startpath+strlen(ptr->path)-2) = '\0'; /* trunc /. */ CheckExistingFile("*",startpath,&statbuf,ptr); ReleaseCurrentLock(); return; } if (ptr->plus == 0 && ptr->minus == 0) { filemode = 0600; } else { filemode = DEFAULTMODE; /* Decide the mode for filecreation */ filemode |= ptr->plus; filemode &= ~(ptr->minus); } switch (ptr->action) { case create: case touch: if (! DONTDO) { MakeDirectoriesFor(startpath,'n'); if ((fd = creat(ptr->path,filemode)) == -1) { perror("creat"); AddMultipleClasses(ptr->elsedef); return; } else { AddMultipleClasses(ptr->defines); close(fd); } CheckExistingFile("*",startpath,&statbuf,ptr); } snprintf(OUTPUT,CF_BUFSIZE*2,"Creating file %s, mode = %o\n",ptr->path,filemode); CfLog(cfinform,OUTPUT,""); break; case alert: case linkchildren: case warnall: case warnplain: case warndirs: case fixplain: case fixdirs: case fixall: snprintf(OUTPUT,CF_BUFSIZE*2,"File/Dir %s did not exist and was marked (%s)\n",ptr->path,FILEACTIONTEXT[ptr->action]); CfLog(cfinform,OUTPUT,""); break; case compress: break; default: FatalError("cfengine: Internal sofware error: Checkfiles(), bad action\n"); } } else { struct Link empty; empty.inclusions = ptr->inclusions; empty.exclusions = ptr->exclusions; empty.defines = NULL; empty.elsedef = NULL; empty.nofile = false; if (ptr->action == create) { struct File tmp; memcpy(&tmp,ptr,sizeof(struct File)); tmp.action = fixall; if (tmp.plus == 0 && tmp.minus == 0) { tmp.plus = 0600; } CheckExistingFile("*",startpath,&statbuf,&tmp); ReleaseCurrentLock(); return; } if (ptr->action == linkchildren) { LinkChildren(ptr->path,'s',&statbuf,ptr->uid->uid,ptr->gid->gid,&empty); ReleaseCurrentLock(); return; } if (S_ISDIR(statbuf.st_mode) && (ptr->recurse != 0)) { if (IgnoreFile(startpath,ReadLastNode(startpath),ptr->ignores)) { Verbose("%s: (Skipping ignored directory %s)\n",VPREFIX,startpath); return; } CheckExistingFile("*",startpath,&statbuf,ptr); RegisterRecursionRootDevice(statbuf.st_dev); RecursiveCheck(startpath,ptr->recurse,0,ptr,&statbuf); } else { if (lstat(startpath,&statbuf) == -1) { CfLog(cferror,"Unable to stat already statted object!","lstat"); return; } CheckExistingFile("*",startpath,&statbuf,ptr); } } ReleaseCurrentLock(); } /*******************************************************************/ void DirectoriesWrapper(char *dir,void *vp) { struct stat statbuf; char directory[CF_EXPANDSIZE]; struct File *ptr; int succeeded = false; int ok = false; memset(directory,0,CF_BUFSIZE); ExpandVarstring(dir,directory,""); ptr = (struct File *)vp; if (stat(directory,&statbuf) == 0) { if (S_ISDIR(statbuf.st_mode)) { Verbose("Directory %s okay\n",directory); ok = true; } else { snprintf(OUTPUT,CF_BUFSIZE,"A non-directory object prevents directory %s from being created\n",directory); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_FAIL); succeeded = false; AddMultipleClasses(ptr->elsedef); return; } } if (!ok) { ExpandVarstring(dir,directory,""); AddSlash(directory); strcat(directory,"."); MakeDirectoriesFor(directory,'n'); if (stat(directory,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot stat %s after creating it",directory); CfLog(cfinform,OUTPUT,"stat"); } else { succeeded = true; } } if (!GetLock(ASUniqueName("directories"),CanonifyName(directory),ptr->ifelapsed,ptr->expireafter,VUQNAME,CFSTARTTIME)) { return; } CheckExistingFile("*",dir,&statbuf,ptr); if (ptr != NULL) { if (succeeded) { AddMultipleClasses(ptr->defines); } else { AddMultipleClasses(ptr->elsedef); } } ReleaseCurrentLock(); } /*******************************************************************/ int TouchDirectory(struct File *ptr) /* True if file path in /. */ { char *sp; if (ptr->action == touch||ptr->action == create) { sp = ptr->path+strlen(ptr->path)-2; if (strcmp(sp,"/.") == 0) { return(true); } else { return false; } } else { return false; } } cfengine-2.2.10/src/cfparse.c0000644000175000001440000014241111170173310012642 00000000000000/* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton implementation for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.3" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Using locations. */ #define YYLSP_NEEDED 0 /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { LVALUE = 258, ID = 259, VAROBJ = 260, LBRACK = 261, RBRACK = 262, CONTROL = 263, GROUPS = 264, ARROW = 265, EQUALS = 266, EDITFILES = 267, QSTRING = 268, RVALUE = 269, BCLASS = 270, LBRACE = 271, RBRACE = 272, PARSECLASS = 273, LARROW = 274, OPTION = 275, FUNCTION = 276, ACL = 277, ADMIT = 278, DENY = 279, FILTERS = 280, STRATEGIES = 281, ACTIONTYPE = 282, ACCESSOBJ = 283 }; #endif /* Tokens. */ #define LVALUE 258 #define ID 259 #define VAROBJ 260 #define LBRACK 261 #define RBRACK 262 #define CONTROL 263 #define GROUPS 264 #define ARROW 265 #define EQUALS 266 #define EDITFILES 267 #define QSTRING 268 #define RVALUE 269 #define BCLASS 270 #define LBRACE 271 #define RBRACE 272 #define PARSECLASS 273 #define LARROW 274 #define OPTION 275 #define FUNCTION 276 #define ACL 277 #define ADMIT 278 #define DENY 279 #define FILTERS 280 #define STRATEGIES 281 #define ACTIONTYPE 282 #define ACCESSOBJ 283 /* Copy the first part of user declarations. */ #line 1 "cfparse.y" /* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* PARSER for cfengine */ /* */ /*******************************************************************/ #include #include "cf.defs.h" #include "cf.extern.h" extern char *yytext; /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ /* Line 216 of yacc.c. */ #line 203 "y.tab.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int i) #else static int YYID (i) int i; #endif { return i; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined _STDLIB_H \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef _STDLIB_H # define _STDLIB_H 1 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss; YYSTYPE yyvs; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 40 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 92 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 29 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 21 /* YYNRULES -- Number of rules. */ #define YYNRULES 79 /* YYNRULES -- Number of states. */ #define YYNSTATES 92 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 283 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint8 yyprhs[] = { 0, 0, 3, 4, 6, 8, 11, 14, 16, 19, 21, 24, 26, 28, 31, 34, 36, 39, 41, 44, 46, 49, 51, 54, 56, 58, 61, 63, 66, 70, 72, 75, 77, 80, 82, 85, 89, 91, 94, 96, 99, 103, 107, 111, 113, 115, 118, 121, 123, 126, 128, 131, 133, 136, 138, 141, 146, 150, 155, 159, 161, 164, 166, 169, 172, 174, 176, 178, 181, 184, 188, 190, 193, 198, 203, 205, 208, 211, 214, 216 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int8 yyrhs[] = { 30, 0, -1, -1, 31, -1, 32, -1, 31, 32, -1, 8, 33, -1, 8, -1, 9, 33, -1, 9, -1, 27, 35, -1, 27, -1, 12, -1, 12, 45, -1, 22, 45, -1, 22, -1, 25, 45, -1, 25, -1, 26, 45, -1, 26, -1, 23, 36, -1, 23, -1, 24, 36, -1, 24, -1, 34, -1, 18, 34, -1, 18, -1, 33, 18, -1, 33, 18, 34, -1, 37, -1, 34, 37, -1, 40, -1, 18, 40, -1, 18, -1, 35, 18, -1, 35, 18, 40, -1, 41, -1, 18, 41, -1, 18, -1, 36, 18, -1, 36, 18, 41, -1, 3, 11, 38, -1, 6, 39, 7, -1, 14, -1, 21, -1, 39, 21, -1, 39, 14, -1, 42, -1, 40, 42, -1, 43, -1, 41, 43, -1, 21, -1, 21, 44, -1, 5, -1, 5, 44, -1, 5, 10, 5, 44, -1, 5, 10, 5, -1, 5, 19, 5, 44, -1, 5, 19, 5, -1, 13, -1, 13, 44, -1, 28, -1, 28, 44, -1, 44, 20, -1, 20, -1, 46, -1, 18, -1, 18, 46, -1, 45, 18, -1, 45, 18, 46, -1, 47, -1, 46, 47, -1, 16, 5, 48, 17, -1, 16, 4, 48, 17, -1, 49, -1, 48, 49, -1, 15, 13, -1, 4, 13, -1, 4, -1, 5, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint8 yyrline[] = { 0, 51, 51, 52, 54, 55, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 82, 83, 85, 86, 87, 88, 89, 91, 92, 93, 94, 95, 97, 99, 101, 102, 103, 104, 106, 107, 109, 110, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 123, 124, 126, 127, 129, 130, 131, 132, 133, 135, 136, 138, 139, 141, 142, 144, 145, 146, 147 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "LVALUE", "ID", "VAROBJ", "LBRACK", "RBRACK", "CONTROL", "GROUPS", "ARROW", "EQUALS", "EDITFILES", "QSTRING", "RVALUE", "BCLASS", "LBRACE", "RBRACE", "PARSECLASS", "LARROW", "OPTION", "FUNCTION", "ACL", "ADMIT", "DENY", "FILTERS", "STRATEGIES", "ACTIONTYPE", "ACCESSOBJ", "$accept", "specification", "statements", "statement", "controllist", "declarations", "classlist", "classaccesslist", "declaration", "bracketlist", "rvalues", "entries", "accessentries", "entry", "accessentry", "options", "objects", "objectbrackets", "objectbracket", "objlist", "obj", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 29, 30, 30, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 37, 38, 39, 39, 39, 39, 40, 40, 41, 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 44, 44, 45, 45, 45, 45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 49, 49 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 0, 1, 1, 2, 2, 1, 2, 1, 2, 1, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 3, 1, 2, 1, 2, 1, 2, 3, 1, 2, 1, 2, 3, 3, 3, 1, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 4, 3, 4, 3, 1, 2, 1, 2, 2, 1, 1, 1, 2, 2, 3, 1, 2, 4, 4, 1, 2, 2, 2, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint8 yydefact[] = { 2, 7, 9, 12, 15, 21, 23, 17, 19, 11, 0, 3, 4, 0, 26, 6, 24, 29, 8, 0, 66, 13, 65, 70, 14, 38, 61, 20, 36, 49, 22, 16, 18, 53, 59, 33, 51, 10, 31, 47, 1, 5, 0, 25, 27, 30, 0, 0, 67, 68, 71, 37, 64, 62, 39, 50, 0, 0, 54, 60, 32, 52, 34, 48, 0, 41, 28, 78, 79, 0, 0, 74, 0, 69, 63, 40, 56, 58, 35, 43, 44, 0, 77, 76, 73, 75, 72, 55, 57, 42, 46, 45 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int8 yydefgoto[] = { -1, 10, 11, 12, 15, 16, 37, 27, 17, 65, 81, 38, 28, 39, 29, 53, 21, 22, 23, 70, 71 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -34 static const yytype_int8 yypact[] = { 8, 5, 5, -3, -3, 43, 43, -3, -3, 37, 19, 8, -34, 29, 40, 31, 40, -34, 31, 58, 59, 50, 59, -34, 50, 46, 60, 64, 46, -34, 64, 50, 50, 2, 60, 23, 60, 65, 23, -34, -34, -34, 72, 40, 40, -34, 55, 55, 59, 59, -34, 46, -34, 66, 46, -34, 79, 80, 66, 66, 23, 66, 23, -34, 51, -34, 40, 74, -34, 75, 49, -34, 52, 59, -34, 46, 60, 60, 23, -34, -34, 4, -34, -34, -34, -34, -34, 66, 66, -34, -34, -34 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int8 yypgoto[] = { -34, -34, -34, 78, 88, -7, -34, 85, -14, -34, -34, -21, -16, -33, -27, -30, 69, -10, -22, 45, 9 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const yytype_uint8 yytable[] = { 50, 55, 45, 58, 59, 63, 61, 43, 13, 51, 48, 89, 56, 19, 60, 20, 1, 2, 90, 40, 3, 57, 52, 14, 55, 91, 50, 63, 33, 45, 4, 5, 6, 7, 8, 9, 34, 66, 75, 73, 42, 78, 33, 13, 36, 63, 87, 88, 55, 44, 34, 50, 45, 67, 68, 35, 67, 68, 36, 67, 68, 25, 46, 47, 69, 79, 84, 69, 49, 86, 69, 26, 80, 24, 26, 19, 31, 32, 64, 85, 52, 85, 54, 62, 76, 77, 74, 82, 83, 41, 18, 30, 72 }; static const yytype_uint8 yycheck[] = { 22, 28, 16, 33, 34, 38, 36, 14, 3, 25, 20, 7, 10, 16, 35, 18, 8, 9, 14, 0, 12, 19, 20, 18, 51, 21, 48, 60, 5, 43, 22, 23, 24, 25, 26, 27, 13, 44, 54, 49, 11, 62, 5, 3, 21, 78, 76, 77, 75, 18, 13, 73, 66, 4, 5, 18, 4, 5, 21, 4, 5, 18, 4, 5, 15, 14, 17, 15, 18, 17, 15, 28, 21, 4, 28, 16, 7, 8, 6, 70, 20, 72, 18, 18, 5, 5, 20, 13, 13, 11, 2, 6, 47 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 8, 9, 12, 22, 23, 24, 25, 26, 27, 30, 31, 32, 3, 18, 33, 34, 37, 33, 16, 18, 45, 46, 47, 45, 18, 28, 36, 41, 43, 36, 45, 45, 5, 13, 18, 21, 35, 40, 42, 0, 32, 11, 34, 18, 37, 4, 5, 46, 18, 47, 41, 20, 44, 18, 43, 10, 19, 44, 44, 40, 44, 18, 42, 6, 38, 34, 4, 5, 15, 48, 49, 48, 46, 20, 41, 5, 5, 40, 14, 21, 39, 13, 13, 17, 49, 17, 44, 44, 7, 14, 21 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) #else static void yy_stack_print (bottom, top) yytype_int16 *bottom; yytype_int16 *top; #endif { YYFPRINTF (stderr, "Stack now"); for (; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { fprintf (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); fprintf (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into YYRESULT an error message about the unexpected token YYCHAR while in state YYSTATE. Return the number of bytes copied, including the terminating null byte. If YYRESULT is null, do not copy anything; just return the number of bytes that would be copied. As a special case, return 0 if an ordinary "syntax error" message will do. Return YYSIZE_MAXIMUM if overflow occurs during size calculation. */ static YYSIZE_T yysyntax_error (char *yyresult, int yystate, int yychar) { int yyn = yypact[yystate]; if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) return 0; else { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; # if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); # endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= (yysize1 < yysize); yysize = yysize1; if (yysize_overflow) return YYSIZE_MAXIMUM; if (yyresult) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yyresult; int yyi = 0; while ((*yyp = *yyf) != '\0') { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } } return yysize; } } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The look-ahead symbol. */ int yychar; /* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { int yystate; int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss = yyssa; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; YYSTYPE *yyvsp; #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a look-ahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a look-ahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } if (yyn == YYFINAL) YYACCEPT; /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: #line 51 "cfparse.y" { yyerror("Warning: invalid statement"); } break; /* Line 1267 of yacc.c. */ #line 1497 "y.tab.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if ! YYERROR_VERBOSE yyerror (YY_("syntax error")); #else { YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) { YYSIZE_T yyalloc = 2 * yysize; if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) yyalloc = YYSTACK_ALLOC_MAXIMUM; if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); yymsg = (char *) YYSTACK_ALLOC (yyalloc); if (yymsg) yymsg_alloc = yyalloc; else { yymsg = yymsgbuf; yymsg_alloc = sizeof yymsgbuf; } } if (0 < yysize && yysize <= yymsg_alloc) { (void) yysyntax_error (yymsg, yystate, yychar); yyerror (yymsg); } else { yyerror (YY_("syntax error")); if (yysize != 0) goto yyexhaustedlab; } } #endif } if (yyerrstatus == 3) { /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (/*CONSTCOND*/ 0) goto yyerrorlab; /* Do not reclaim the symbols of the rule which action triggered this YYERROR. */ YYPOPSTACK (yylen); yylen = 0; YY_STACK_PRINT (yyss, yyssp); yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK (1); yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEOF && yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); /* Do not reclaim the symbols of the rule which action triggered this YYABORT or YYACCEPT. */ YYPOPSTACK (yylen); YY_STACK_PRINT (yyss, yyssp); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK (1); } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif #if YYERROR_VERBOSE if (yymsg != yymsgbuf) YYSTACK_FREE (yymsg); #endif /* Make sure YYID is used. */ return YYID (yyresult); } #line 149 "cfparse.y" /*****************************************************************/ void yyerror(s) char *s; { fprintf (stderr, "cf:%s:%s:%d: %s \n",VPREFIX,VCURRENTFILE,LINENUMBER,s); ERRORCOUNT++; if (ERRORCOUNT > 10) { FatalError("Too many errors"); } } /*****************************************************************/ /* EOF */ cfengine-2.2.10/src/prototypes.h0000644000175000001440000012275711055247565013507 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ /*******************************************************************/ /* */ /* cfengine function prototypes */ /* */ /* contributed by Stuart Sharpe, September 2000 */ /* */ /*******************************************************************/ /* pub/full-write.c */ int cf_full_write (int desc, char *ptr, size_t len); /* checksum_db.c */ int ReadChecksum(DB *dbp,char type,char *name,unsigned char digest[EVP_MAX_MD_SIZE+1], unsigned char *attr); int WriteChecksum(DB *dbp,char type,char *name,unsigned char digest[EVP_MAX_MD_SIZE+1], unsigned char *attr); void DeleteChecksum(DB *dbp,char type,char *name); DBT *NewChecksumKey(char type,char *name); void DeleteChecksumKey(DBT *key); DBT *NewChecksumValue(unsigned char digest[EVP_MAX_MD_SIZE+1],unsigned char attr[EVP_MAX_MD_SIZE+1]); void DeleteChecksumValue(DBT *value); /* 2Dlist.c */ void Set2DList (struct TwoDimList *list); char *Get2DListEnt (struct TwoDimList *list); void Build2DListFromVarstring (struct TwoDimList **TwoDimlist,char *varstring,char sep,short tied); int IncrementTwoDimList (struct TwoDimList *from); int TieIncrementTwoDimList (struct TwoDimList *from); struct TwoDimList *list;void AppendTwoDimItem (struct TwoDimList **liststart,struct Item *itemlist); void Delete2DList (struct TwoDimList *item); int EndOfTwoDimList (struct TwoDimList *list); /* acl.c */ void aclsortperror (int error); #if defined SOLARIS && defined HAVE_SYS_ACL_H struct acl; enum cffstype StringToFstype (char *string); struct CFACL *GetACL (char *acl_alias); int ParseSolarisMode (char* mode, mode_t oldmode); int BuildAclEntry (struct stat *sb, char *acltype, char *name, struct acl *newaclbufp); #endif void InstallACL (char *alias, char *classes); void AddACE (char *acl, char *string, char *classes); int CheckACLs (char *filename, enum fileactions action, struct Item *acl_aliases); enum cffstype StringToFstype (char *string); struct CFACL *GetACL (char *acl_alias); int CheckPosixACE (struct CFACE *aces, char method, char *filename, enum fileactions action); /* cfd.c Function prototypes for cfd.c are in cfd.c itself, since they are not called from elsewhere. */ /* cfagent.c Function prototypes for cfengine.c are in cfengine.c itself, since they are not called from elsewhere. */ /* cflex.l */ int yylex (void); /* cfparse.y */ void yyerror (char *s); int yyparse (void); /* cfrun.c Function prototypes for cfrun.c are in cfrun.c itself, since they are not called from elsewhere. */ /* checksums.c */ int CompareCheckSums (char *file1, char *file2, struct Image *ip, struct stat *sstat, struct stat *dstat); int CompareBinarySums (char *file1, char *file2, struct Image *ip, struct stat *sstat, struct stat *dstat); char ChecksumType(char *typestr); char *ChecksumName(char type); int ChecksumSize(char type); /* functions.c */ void BuildClassEnvironment (void); char *EvaluateFunction (char *function, char *value); enum builtin FunctionStringToCode (char *str); int IsBuiltinFunction (char *function); int CheckForModule (char *actiontxt, char *args); void HandleStatInfo (enum builtin fn,char *args,char *value); void HandleCompareStat (enum builtin fn,char *args,char *value); void GetRandom (char* args,char *value); void HandleFunctionExec (char* args,char *value,int useshell); void HandleStatInfo (enum builtin fn,char* args,char *value); void HandleCompareStat (enum builtin fn,char* args,char *value); void HandleReturnsZero (char* args,char *value,int useshell); void HandleIPRange (char* args,char *value); void HandleHostRange (char* args,char *value); void HandleIsDefined (char* args,char *value); void HandleStrCmp (char* args,char *value); void HandleGreaterThan (char* args,char *value,char plusminus); void HandleRegCmp (char* args,char *value); void HandleClassRegex(char *args,char *value); void HandleShowState (char* args,char *value); void HandleReadFile (char *args,char *value); void HandleReadArray (char *args,char *value); void HandlePrintFile (char *args,char *value); void HandleReadList (char *args,char *value); void HandleReadTCP (char *args,char *value); void HandleReadTable (char *args,char *value); void HandleReturnValues (char *args,char *value); void HandleReturnClasses (char *args,char *value); void HandleSyslogFn (char *args,char *value); void HandleSelectPLeader (char *args,char *value); void HandleSelectPGroup (char *args,char *value); void HandleUserExists (char *args,char *value); void HandleGroupExists (char *args,char *value); void HandleSetState (char *args,char *value); void HandleUnsetState (char *args,char *value); void HandlePrepModule (char *args,char *value); void HandleAssociation (char *args,char *value); int FunctionArgs (char *args,char argv[CF_MAXFARGS][CF_EXPANDSIZE],int number); int FileFormat (char *args,char argv[CF_MAXFARGS][CF_EXPANDSIZE],int number,char sep); int IsSocketType (char *s); int IsTCPType (char *s); int IsProcessType (char *s); void HandleFriendStatus (char *args,char *value); /* granules.c */ char *ConvTimeKey (char *str); char *GenTimeKey (time_t now); /* chflags.c */ void ParseFlagString (char *flagstring, u_long *plusmask, u_long *minusmask); /* client.c */ int OpenServerConnection (struct Image *ip); void CloseServerConnection (void); int cf_rstat (char *file, struct stat *buf, struct Image *ip, char *stattype); CFDIR *cf_ropendir (char *dirname, struct Image *ip); void FlushClientCache (struct Image *ip); int CompareMD5Net (char *file1, char *file2, struct Image *ip); int CopyRegNet (char *source, char *new, struct Image *ip, off_t size); int GetCachedStatData (char *file, struct stat *statbuf, struct Image *ip, char *stattype); void CacheData (struct cfstat *data, struct Image *ip); void FlushToEnd (int sd, int toget); int cfprintf(char *out, int len2, char *in1, char *in2, char *in3); struct cfagent_connection *NewAgentConn (void); void DeleteAgentConn (struct cfagent_connection *ap); int RemoteConnect (char *host,char forceipv4,short oldport,char *newport); /* comparray.c */ int FixCompressedArrayValue (int i, char *value, struct CompressedArray **start); void DeleteCompressedArray (struct CompressedArray *start); int CompressedArrayElementExists (struct CompressedArray *start, int key); char *CompressedArrayValue (struct CompressedArray *start, int key); /* copy.c */ void CheckForHoles (struct stat *sstat, struct Image *ip); int CopyRegDisk (char *source, char *new, struct Image *ip); int EmbeddedWrite (char *new,int dd,char *buf,struct Image *ip,int towrite,int *last_write_made_hole,int n_read); /* dce_acl.c */ #ifndef HAVE_DCE_DACLIF_H int CheckDFSACE(struct CFACE *aces, char method, char *filename, enum fileactions action); #endif /* df.c */ int GetDiskUsage (char *file, enum cfsizes type); /* do.c */ void DoMethods (void); void GetHomeInfo (void); void GetMountInfo (void); void MakePaths (void); void MakeChildLinks (void); void MakeLinks (void); void MailCheck (void); void ExpiredUserCheck (char *spooldir, int always); void MountFileSystems (void); void CheckRequired (void); int ScanDiskArrivals (char *name, struct stat *sb, int rlevel); void TidyFiles (void); void TidyHome (void); void TidyHomeDir (struct TidyPattern *ptr, char *subdir); void Scripts (void); void GetSetuidLog (void); void CheckFiles (void); void SaveSetuidLog (void); void DisableFiles (void); void MountHomeBinServers (void); void MountMisc (void); void Unmount (void); void EditFiles (void); void CheckResolv (void); void MakeImages (void); void ConfigureInterfaces (void); void CheckTimeZone (void); void CheckProcesses (void); void CheckPackages (void); int RequiredFileSystemOkay (char *name); void InstallMountedItem (char *host, char *mountdir); void InstallMountableItem (char *path, char *mnt_opts, flag readonly); void AddToFstab (char *host, char *mountpt, char *rmountpt, char *mode, char *options, int ismounted); int CheckFreeSpace (char *file, struct Disk *ptr); void CheckHome (struct File *ptr); void EditItemsInResolvConf (struct Item *from, struct Item **list); int TZCheck (char *tzsys, char *tzlist); void ExpandWildCardsAndDo (char *wildpath, char *buffer, void (*function)(char *path, void *ptr), void *argptr); int TouchDirectory (struct File *ptr); void RecFileCheck (char *startpath, void *vp); int MatchStringInFstab (char *str); int ScanFileSystemArrivals (char *name,int rlevel,struct stat *sb, DB *dbp); void RecordFileSystemArrivals (DB *dbp, time_t mtime); /* edittools.c */ int DoRecursiveEditFiles (char *name, int level, struct Edit *ptr,struct stat *sb); void DoEditHomeFiles (struct Edit *ptr); void WrapDoEditFile (struct Edit *ptr, char *filename); void DoEditFile (struct Edit *ptr, char *filename); int IncrementEditPointer (char *str, struct Item *liststart); int ResetEditSearch (char *str, struct Item *list); int ReplaceEditLineWith (char *string); int ExpandAllVariables (struct Item *list); int RunEditScript (char *script, char *fname, struct Item **filestart, struct Edit *ptr); void DoFixEndOfLine (struct Item *list, char *type); void HandleAutomountResources (struct Item **filestart, char *opts); void CheckEditSwitches (char *filename, struct Edit *ptr); void AddEditfileClasses (struct Edit *list, int editsdone); struct Edlist *ThrowAbort (struct Edlist *from); struct Edlist *SkipToEndGroup (struct Edlist *ep, char *filename); int BinaryEditFile (struct Edit *ptr, char *filename); int LoadBinaryFile (char *source, off_t size, void *memseg); int SaveBinaryFile (char *file, off_t size, void *memseg, char *repository); void WarnIfContainsRegex (void *memseg, off_t size, char *data, char *filename); void WarnIfContainsFilePattern (void *memseg, off_t size, char *data, char *filename); int BinaryReplaceRegex (void *memseg, off_t size, char *search, char *replace, char *filename); /* crypto.c */ void RandomSeed (void); void LoadSecretKeys (void); void MD5Random (unsigned char digest[EVP_MAX_MD_SIZE+1]); int EncryptString (char *in, char *out, unsigned char *key, int len); int DecryptString (char *in, char *out, unsigned char *key, int len); RSA *HavePublicKey (char *ipaddress); void SavePublicKey (char *ipaddress, RSA *key); void DeletePublicKey (char *ipaddress); void GenerateRandomSessionKey (void); char *KeyPrint(RSA *key); /* errors.c */ void FatalError (char *s); void Warning (char *s); void ResetLine (char *s); /* eval.c */ int CfShow(void); int ShowClass(char *c1,char *c2); int CountParentheses(char *str); int NestedParentheses(char *str); int Day2Number (char *s); int Month2Number (char *s); void AddInstallable (char *classlist); void AddMultipleClasses (char *classlist); void AddTimeClass (char *str); void AddClassToHeap (char *class); void DeleteClassFromHeap (char *class); int IsHardClass (char *sp); int IsSpecialClass (char *class); int IsExcluded (char *exception); int IsDefinedClass (char *class); int IsInstallable (char *class); void AddPrefixedMultipleClasses (char *prefix,char *class); void NegateCompoundClass (char *class, struct Item **heap); int EvaluateORString (char *class, struct Item *list,int fromIsInstallable); int EvaluateANDString (char *class, struct Item *list,int fromIsInstallable); int GetORAtom (char *start, char *buffer); int GetANDAtom (char *start, char *buffer); int CountEvalAtoms (char *class); enum actions ActionStringToCode (char *str); int IsBracketed (char *s); void DeleteClassesFromContext (char *s); void CheckCommonErrors(char *s); /* filedir.c */ int IsHomeDir (char *name); int EmptyDir (char *path); int RecursiveCheck (char *name, int recurse, int rlevel, struct File *ptr,struct stat *sb); #ifdef DARWIN int CheckFinderType (char *file, enum fileactions action, char *cf_findertype, struct stat *statbuf); #endif void CheckExistingFile (char *cf_findertype,char *file, struct stat *dstat, struct File *ptr); void CheckCopiedFile (char *cf_findertype,char *file,struct stat *dstat, struct stat *sstat, struct Image *ptr); int CheckOwner (char *file, struct File *ptr, struct stat *statbuf); int CheckHomeSubDir (char *testpath, char *tidypath, int recurse); int FileIsNewer (char *file1, char *file2); int IgnoreFile (char *pathto, char *name, struct Item *ignores); void CompressFile (char *file); void LogChecksumChange(char *file); /* filenames.c */ int IsIn(char c,char *s); int IsAbsoluteFileName (char *f); void CreateEmptyFile (char *f); int RootDirLength (char *f); void AddSlash (char *str); void DeleteSlash (char *str); void DeleteNewline (char *str); char *LastFileSeparator (char *str); int ChopLastNode (char *str); char *CanonifyName (char *str); char *Space2Score (char *str); char *ASUniqueName (char *str); char *ReadLastNode (char *str); int MakeDirectoriesFor (char *file, char force); int BufferOverflow (char *str1, char *str2); int ExpandOverflow (char *str1, char *str2); void Chop (char *str); int CompressPath (char *dest, char *src); char ToLower (char ch); char ToUpper (char ch); char *ToUpperStr (char *str); char *ToLowerStr (char *str); /* filters.c */ void InstallFilter (char *filter); void CheckFilters (void); void InstallFilterTest (char *alias, char *type, char *data); enum filternames FilterActionsToCode (char *filtertype); int FilterExists (char *name); int ProcessFilter (char *proc, struct Item *filterlist,char **names,int *start,int *stop); void SplitLine (char *proc, char **names,int *start,int *stop,char **line); int FileObjectFilter (char *file, struct stat *statptr, struct Item *filterlist, enum actions context); time_t Date2Number (char *string, time_t now); void Size2Number (char *buffer); int FilterTypeMatch (struct stat *ptr,char *match); int FilterOwnerMatch (struct stat *lstatptr,char *crit); int FilterGroupMatch (struct stat *lstatptr,char *crit); int FilterModeMatch (struct stat *lstatptr,char *crit); int FilterTimeMatch (time_t stattime,char *from,char *to); int FilterNameRegexMatch (char *file,char *crit); int FilterExecRegexMatch (char *file,char *crit); int FilterExecMatch (char *file,char *crit); int FilterIsSymLinkTo (char *file,char *crit); void DoFilter (struct Item **attr,char **crit,struct stat *lstatptr,char *filename); void GetProcessColumns (char *proc,char **names,int *start,int *stop); int FilterProcMatch (char *name1,char *name2,char *expr,char **names,char **line); int FilterProcSTimeMatch (char *name1,char *name2,char *expr1,char *expr2,char **names,char **line); int FilterProcTTimeMatch (char *name1,char *name2,char *expr1,char *expr2,char **names,char **line); void DoProc (struct Item **attr,char **crit,char **names,char **line); /* * HvB: Bas van der Vlies */ void ParseTTime (char *line,char *time_str); /* ifconf.c */ void IfConf (char *vifdev, char *address,char *vnetmask, char *vbroadcast); int GetIfStatus (int sk, char *vifdev, char *address, char *vnetmask, char *vbroadcast); void SetIfStatus (int sk, char *vifdev, char *address, char *vnetmask, char *vbroadcast); void GetBroadcastAddr (char *ipaddr, char *vifdev, char *vnetmask, char *vbroadcast); void SetDefaultRoute (void); /* image.c */ void GetRemoteMethods (void); void RecursiveImage (struct Image *ip, char *from, char *to, int maxrecurse); void CheckHomeImages (struct Image *ip); void CheckImage (char *source, char *destination, struct Image *ip); void PurgeFiles (struct Item *filelist, char *directory, struct Item *exclusions); void ImageCopy (char *sourcefile, char *destfile, struct stat sourcestatbuf, struct Image *ip); int cfstat (char *file, struct stat *buf, struct Image *ip); int cflstat (char *file, struct stat *buf, struct Image *ip); int cfreadlink (char *sourcefile, char *linkbuf, int buffsize, struct Image *ip); CFDIR *cfopendir (char *name, struct Image *ip); struct cfdirent *cfreaddir (CFDIR *cfdirh, struct Image *ip); void cfclosedir (CFDIR *dirh); int CopyReg (char *source, char *dest, struct stat sstat, struct stat dstat, struct Image *ip); void RegisterHardLink (int i, char *value, struct Image *ip); /* init.c */ void CheckWorkDirectories (void); void SetSignals (void); void ActAsDaemon (int preserve); int IsInterfaceAddress (char *s); /* install.c */ void InstallControlRValue (char *lvalue,char *varvalue); void HandleEdit (char *file, char *edit, char *string); void HandleOptionalFileAttribute (char *item); void HandleOptionalMountablesAttribute (char *item); void HandleOptionalImageAttribute (char *item); void HandleOptionalRequired (char *item); void HandleOptionalInterface (char *item); void HandleOptionalUnMountAttribute (char *item); void HandleOptionalMiscMountsAttribute (char *item); void HandleOptionalTidyAttribute (char *item); void HandleOptionalDirAttribute (char *item); void HandleOptionalDisableAttribute (char *item); void HandleOptionalLinkAttribute (char *item); void HandleOptionalProcessAttribute (char *item); void HandleOptionalScriptAttribute (char *item); void HandleOptionalAlertsAttribute (char *item); void HandleOptionalPackagesAttribute (char *item); void HandleOptionalMethodsAttribute (char *item); void HandleChDir (char *value); void HandleChRoot (char *value); void HandleFileItem (char *item); void InstallObject (char *name); void InstallBroadcastItem (char *item); void InstallDefaultRouteItem (char *item); void InstallGroupRValue (char *rval, enum itemtypes type); void HandleHomePattern (char *pattern); void AppendNameServer (char *item); void AppendImport (char *item); void InstallHomeserverItem (char *item); void InstallBinserverItem (char *item); void InstallMailserverPath (char *path); void InstallLinkItem (char *from, char *to); void InstallLinkChildrenItem (char *from, char *to); void InstallRequiredPath (char *path, int freespace); void AppendMountable (char *path); void AppendUmount (char *path, char deldir, char delfstab, char force); void AppendMiscMount (char *from, char *onto, char * mode,char *opts); void AppendIgnore (char *path); void InstallPending (enum actions action); int EditFileExists (char *file); int GetExecOutput (char *command, char *buffer,int useshell); void InstallEditFile (char *file, char *edit, char *data); void AddEditAction (char *file, char *edit, char *data); enum editnames EditActionsToCode (char *edit); void AppendInterface (char *ifname, char *ip, char *netmask, char *broadcast); void AppendScript (char *item, int timeout, char useshell, char *uidname, char *gidname); void AppendSCLI(char *item, int timeout, char useshell, char *uidname, char *gidname); void AppendDisable (char *path, char *type, short int rotate, char comp, int size); void InstallTidyItem (char *path, char *wild, int rec, short int age, char travlinks, int tidysize, char type, char ldirs, char tidydirs, char *classes); void InstallMakePath (char *path, mode_t plus, mode_t minus, char *uidnames, char *gidnames); void HandleTravLinks (char *value); void HandleTidySize (char *value); void HandleUmask (char *value); void HandleDisableSize (char *value); void HandleCopySize (char *value); void HandleRequiredSize (char *value); void HandleTidyType (char *value); void HandleTidyLinkDirs (char *value); void HandleTidyRmdirs (char *value); void HandleCopyBackup (char *value); void HandleTimeOut (char *value); void HandleUseShell (char *value); void HandleFork (char *value); void HandleChecksum (char *value); void HandleTimeStamps (char *value); int GetFileAction (char *action); void InstallFileListItem (char *path, mode_t plus, mode_t minus, enum fileactions action, char *uidnames, char *gidnames, int recurse, char travlinks, char chksum); void InstallProcessItem (char *expr, char *restart, short int matches, char comp, short int signal, char action, char *classes, char useshell, char *uidname, char *gidname); void InstallImageItem (char *cf_findertype, char *path, mode_t plus, mode_t minus, char *destination, char *action, char *uidnames, char *gidnames, int size, char comp, int rec, char type, char lntype, char *server); void InstallMethod (char *function, char *file); void InstallAuthItem (char *path, char *attribute, struct Auth **list, struct Auth **listtop, char *classes); void InstallPackagesItem (char *name, char *ver, enum cmpsense sense, enum pkgmgrs mgr, enum pkgactions action); int GetCmpSense (char *sense); int GetPkgMgr (char *mgr); int GetPkgAction (char *pkgaction); int GetCommAttribute (char *s); void HandleRecurse (char *value); void HandleCopyType (char *value); void HandleDisableFileType (char *value); void HandleDisableRotate (char *value); void HandleAge (char *days); void HandleProcessMatches (char *value); void HandleProcessSignal (char *value); void HandleNetmask (char *value); void HandleIPAddress (char *value); void HandleBroadcast (char *value); void AppendToActionSequence (char *action); void AppendToAccessList (char *user); void HandleLinkAction (char *value); void HandleDeadLinks (char *value); void HandleLinkType (char *value); void HandleServer (char *value); void HandleDefine (char *value); void HandleElseDefine (char *value); void HandleFailover (char *value); struct UidList *MakeUidList (char *uidnames); struct GidList *MakeGidList (char *gidnames); void InstallTidyPath (char *path, char *wild, int rec, short int age, char travlinks, int tidysize, char type, char ldirs,char tidydirs, char *classes); void AddTidyItem (char *path, char *wild, int rec, short int age, char travlinks, int tidysize, char type, char ldirs, short int tidydirs, char *classes); int TidyPathExists (char *path); void AddSimpleUidItem (struct UidList **uidlist, int uid, char *uidname); void AddSimpleGidItem (struct GidList **gidlist, int gid, char *gidname); void InstallAuthPath (char *path, char *hostname, char *classes, struct Auth **list, struct Auth **listtop); void AddAuthHostItem (char *path, char *attribute, char *classes, struct Auth **list); int AuthPathExists (char *path, struct Auth *list); int HandleAdmitAttribute (struct Auth *ptr, char *attribute); void PrependTidy (struct TidyPattern **list, char *wild, int rec, short int age, char travlinks, int tidysize, char type, char ldirs,char tidydirs, char *classes); void HandleShortSwitch (char *name,char *value,short *flag); void HandleCharSwitch (char *name,char *value,char *flag); void HandleIntSwitch (char *name,char *value,int *flag,int min, int max); void PrependAuditFile(char *file); void VersionAuditFile(void); /* ip.c */ char *sockaddr_ntop (struct sockaddr *sa); void *sockaddr_pton (int af,void *src); void CfenginePort (void); void StrCfenginePort (void); int IsIPV4Address (char *name); int IsIPV6Address (char *name); char *Hostname2IPString (char *name); char *IPString2Hostname (char *name); char *IPString2UQHostname (char *name); /* instrument.c */ void RecordPerformance(char *name, time_t t, double value); void RecordClassUsage(void); void LastSeen (char *host,enum roles role); void CheckFriendConnections(int hours); void CheckFriendReliability(void); DBT *NewDBKey(char *name); void DeleteDBKey(DBT *key); DBT *NewDBValue(void *ptr,int size); void DeleteDBValue(DBT *value); int ReadDB(DB *dbp,char *name,void *ptr,int size); int WriteDB(DB *dbp,char *name,void *ptr,int size); void DeleteDB(DB *dbp,char *name); double GAverage(double anew,double aold,double trust); /* item-ext.c */ int OrderedListsMatch (struct Item *list1, struct Item *list2); int RegexOK (char *string); int IsWildItemIn (struct Item *list, char *item); void InsertItemAfter (struct Item **filestart, struct Item *ptr, char *string); void InsertFileAfter (struct Item **filestart, struct Item *ptr, char *string); struct Item *LocateNextItemContaining (struct Item *list,char *string); struct Item *LocateNextItemMatching (struct Item *list,char *string); struct Item *LocateNextItemStarting (struct Item *list,char *string); struct Item *LocateItemMatchingRegExp (struct Item *list,char *string); struct Item *LocateItemContainingRegExp (struct Item *list,char *string); int DeleteToRegExp (struct Item **filestart, char *string); int DeleteItemGeneral (struct Item **filestart, char *string, enum matchtypes type); int DeleteItemLiteral (struct Item **filestart, char *string); int DeleteItemStarting (struct Item **list,char *string); int DeleteItemNotStarting (struct Item **list,char *string); int DeleteItemMatching (struct Item **list,char *string); int DeleteItemNotMatching (struct Item **list,char *string); int DeleteItemContaining (struct Item **list,char *string); int DeleteItemNotContaining (struct Item **list,char *string); int DeleteLinesWithFileItems (struct Item **list,char *string,enum editnames code); int AppendLinesFromFile (struct Item **filestart,char *filename); int CommentItemStarting (struct Item **list, char *string, char *comm, char *end); int CommentItemContaining (struct Item **list, char *string, char *comm, char *end); int CommentItemMatching (struct Item **list, char *string, char *comm, char *end); int UnCommentItemMatching (struct Item **list, char *string, char *comm, char *end); int UnCommentItemContaining (struct Item **list, char *string, char *comm, char *end); int CommentToRegExp (struct Item **filestart, char *string, char *comm, char *end); int UnCommentToRegExp(struct Item **filestart,char *string,char *comm,char *end); int DeleteSeveralLines (struct Item **filestart, char *string); struct Item *GotoLastItem (struct Item *list); int LineMatches (char *line, char *regexp); int GlobalReplace (struct Item **liststart, char *search, char *replace); int SingleReplace (struct Item **liststart, char *search, char *replace); int CommentSeveralLines (struct Item **filestart, char *string, char *comm, char *end); int UnCommentSeveralLines (struct Item **filestart, char *string, char *comm, char *end); int ItemMatchesRegEx (char *item, char *regex); void ReplaceWithFieldMatch (struct Item **filestart, char *field, char *replace, char split, char *filename); void AppendToLine (struct Item *current, char *text, char *filename); int CfRegcomp (regex_t *preg, const char *regex, int cflags); /* item-file.c */ int LoadItemList (struct Item **liststart, char *file); int SaveItemList (struct Item *liststart, char *file, char *repository); int CompareToFile (struct Item *liststart, char *file); /* item.c */ struct Item *String2List(char *string); int ListLen (struct Item *list); int ByteSizeList (struct Item *list); void AppendItems (struct Item **liststart, char *itemstring, char *classes); int IsItemIn (struct Item *list, char *item); int IsClassedItemIn (struct Item *list, char *item); int IsFuzzyItemIn (struct Item *list, char *item); int GetItemListCounter (struct Item *list, char *item); struct Item *ConcatLists (struct Item *list1, struct Item *list2); void CopyList (struct Item **dest,struct Item *source); int FuzzySetMatch (char *s1, char *s2); int FuzzyMatchParse (char *item); int FuzzyHostMatch (char *arg0, char *arg1,char *basename); int FuzzyHostParse (char *arg1,char *arg2); void PrependItem (struct Item **liststart, char *itemstring, char *classes); void AppendItem (struct Item **liststart, char *itemstring, char *classes); void InstallItem (struct Item **liststart, char *itemstring, char *classes, int ifelapsed, int expireafter); void DeleteItemList (struct Item *item); void DeleteItem (struct Item **liststart, struct Item *item); void DebugListItemList (struct Item *liststart); int ItemListsEqual (struct Item *list1, struct Item *list2); struct Item *SplitStringAsItemList (char *string, char sep); struct Item *ListFromArgs (char *string); void IncrementItemListCounter (struct Item *ptr, char *string); void SetItemListCounter (struct Item *ptr, char *string,int value); struct Item *SortItemListNames(struct Item *list); struct Item *SortItemListCounters(struct Item *list); /* link.c */ struct Link; int LinkChildFiles (char *from, char *to, struct Link *ptr); void LinkChildren (char *path, char type, struct stat *rootstat, uid_t uid, gid_t gid,struct Link *ptr); int RecursiveLink (struct Link *lp, char *from, char *to, int maxrecurse); int LinkFiles (char *from, char *to,struct Link *ptr); int RelativeLink (char *from, char *to,struct Link *ptr); int AbsoluteLink (char *from, char *to,struct Link *ptr); int DoLink (char *from, char *to, char *defines); void KillOldLink (char *name, char *defines); int HardLinkFiles (char *from, char *to,struct Link *ptr); void DoHardLink (char *from, char *to, char *defines); int ExpandLinks (char *dest, char *from, int level); char *AbsLinkPath (char *from, char *relto); /* locks.c */ void WritePID(char *file); void PreLockState (void); void SaveExecLock (void); void RestoreExecLock (void); void InitializeLocks (void); void CloseLocks (void); void HandleSignal (int signum); int GetLock (char *operator, char *operand, int ifelapsed, int expireafter, char *host, time_t now); void ReleaseCurrentLock (void); int CountActiveLocks (void); time_t GetLastLock (void); time_t CheckOldLock (void); void SetLock (void); void LockLog (int pid, char *str, char *operator, char *operand); int PutLock (char *name); int DeleteLock (char *name); time_t GetLockTime (char *name); pid_t GetLockPid (char *name); void ExtractOpLock(char *op); /* log.c */ void AuditLog(char doaudit,struct Audit *ap,int lineno,char *str,char status); void CfLog (enum cfoutputlevel level, char *string, char *errstr); void ResetOutputRoute (char log, char inform); void ShowAction (void); void CfOpenLog (void); void CfCheckAudit(void); void CloseAuditLog(void); void AuditStatusMessage(char status); /* macro.c */ void SetContext (char *id); int ScopeIsMethod (void); void InitHashTable (char **table); void BlankHashTable (char *scope); void PrintHashTable (char **table); int Hash (char *name); int ElfHash (char *name); void AddMacroValue (char *scope, char *name, char *value); char *GetMacroValue (char *scope,char *name); void RecordMacroId (char *name); int CompareMacro (char *name, char *macro); void DeleteMacros (char *scope); void DeleteMacro (char *scope,char *name); struct cfObject *ObjectContext (char *scope); void DispatchMethodReply (void); void EncapsulateReply (char *name); /* HvB */ int OptionIs (char *scope, char *name, short on); /* methods.c */ void CheckForMethod (void); void CheckMethodReply (void); void DispatchNewMethod (struct Method *ptr); struct Item *GetPendingMethods (int state); int ChildLoadMethodPackage (char *name, char *md5); int ParentLoadReplyPackage (char *name); char *GetMethodFilename (struct Method *ptr); void EvaluatePendingMethod (char *name); void DeleteMethodList (struct Method *ptr); void EncapsulateMethod (struct Method *ptr,char *name); enum methproto ConvertMethodProto (char *name); struct Method *IsDefinedMethod (char *name,char *digeststr); int CountAttachments (char *name); void SplitMethodName (char *name,char *client,char *server,char *methodname,char *digeststr,char *extra); int CheckForMethodPackage (char *name); /* misc.c */ int VM_version (void); int linux_fedora_version (void); int linux_redhat_version (void); int linux_mandrake_version (void); int linux_suse_version (void); int linux_slackware_version (char *filename); int debian_version (void); int lsb_version (void); int Xen_domain(void); char * UnQuote (char *name); int DirPush (char *name,struct stat *sb); void DirPop (int goback,char *name,struct stat *sb); void CheckLinkSecurity (struct stat *sb, char *name); void GetNameInfo (void); void GetEnvironment(void); void AddNetworkClass (char *netmask); void TruncateFile (char *name); int FileSecure (char *name); int ChecksumChanged (char *filename, unsigned char digest[EVP_MAX_MD_SIZE+1], int warnlevel, int refresh, char type); char *ChecksumPrint (char type,unsigned char digest[EVP_MAX_MD_SIZE+1]); void ChecksumFile (char *filename,unsigned char digest[EVP_MAX_MD_SIZE+1],char type); void ChecksumList (struct Item *list,unsigned char digest[EVP_MAX_MD_SIZE+1],char type); int ChecksumsMatch (unsigned char digest1[EVP_MAX_MD_SIZE+1],unsigned char digest2[EVP_MAX_MD_SIZE+1],char type); void ChecksumPurge (void); void ChecksumString (char *buffer,int len,unsigned char digest[EVP_MAX_MD_SIZE+1],char type); int IgnoredOrExcluded (enum actions action, char *file, struct Item *inclusions, struct Item *exclusions); void Banner (char *string); void SetDomainName (char *sp); void GetInterfaceInfo (void); void DeleteInterfaceInfo (char *regex); void GetV6InterfaceInfo (void); void DebugBinOut (char *string, int len); int ShellCommandReturnsZero (char *comm, int useshell); void SetClassesOnScript (char *comm, char *classes, char *elseclasses, int useshell); void IDClasses (void); void AddListSeparator(char *s); void ChopListSeparator(char *s); void SetReferenceTime(int setclasses); void SetStartTime(int setclasses); /* modes.c */ void ParseModeString (char *modestring, mode_t *plusmask, mode_t *minusmask); void CheckModeState (enum modestate stateA, enum modestate stateB,enum modesort modeA, enum modesort modeB, char ch); void SetMask (char action, int value, int affected, mode_t *p, mode_t *m); /* mount.c */ int MountPathDefined (void); int MatchAFileSystem (char *server, char *lastlink); int IsMountedFileSystem (struct stat *childstat, char *dir, int rlevel); /* net.c */ int SendTransaction (int sd, char *buffer,int len, char status); int ReceiveTransaction (int sd, char *buffer,int *more); int RecvSocketStream (int sd, char *buffer, int toget, int nothing); int SendSocketStream (int sd, char *buffer, int toget, int flags); /* strategies.c */ void InstallStrategy (char *value, char *classes); void AddClassToStrategy (char *alias,char *class,char *value); void SetStrategies (void); void GetNonMarkov (void); /* parse.c */ int ParseInputFile (char *file,int audit); void ParseFile (char *f,char *env,int audit); void ParseStdin (void); void NewParser (void); int RemoveEscapeSequences (char *from,char *to); void DeleteParser (void); void SetAction (enum actions action); void HandleLValue (char *id); void HandleBraceObjectClassifier (char *id); void HandleBraceObjectID (char *id); void HandleClass (char *id); void HandleServerRule (char *obj); void HandleGroupRValue (char *item); void HandleFunctionObject (char *fn); void HandleQuotedString (char *qstring); void HandleVarObject (char *path); void HandleVarpath (char *varpath); void HandleOption (char *option); int CompoundId (char *id); void InitializeAction (void); void SetMountPath (char *value); void SetRepository (char *value); char *FindInputFile (char *result, char *filename); /* patches.c */ int IntMin (int a,int b); char *StrStr (char *s1,char *s2); int StrnCmp (char *s1,char *s2,size_t n); #ifndef HAVE_GETNETGRENT int setnetgrent (const char *netgroup); int getnetgrent (char **host, char **user, char **domain); void endnetgrent (void); #endif #ifndef HAVE_UNAME int uname (struct utsname *name); #endif #ifndef HAVE_STRSTR char *strstr (char *s1,char *s2); #endif #ifndef HAVE_STRDUP char *strdup (char *str); #endif #ifndef HAVE_STRRCHR char *strrchr (char *str,char ch); #endif #ifndef HAVE_STRERROR char *strerror (int err); #endif #ifndef HAVE_STRSEP char *strsep(char **stringp, const char *delim); #endif #ifndef HAVE_PUTENV int putenv (char *s); #endif #ifndef HAVE_SETEUID int seteuid (uid_t euid); #endif #ifndef HAVE_SETEUID int setegid (gid_t egid); #endif int IsPrivileged (void); /* alerts.c */ void DoAlerts (void); /* package.c */ int PackageCheck (struct Package *ptr,char *package, enum pkgmgrs pkgmgr, char *version, enum cmpsense cmp); int PackageList (struct Package *ptr,char *package, enum pkgmgrs pkgmgr, char *version, enum cmpsense cmp, struct Item **pkglist); int UpgradePackage (struct Package *ptr,char *package, enum pkgmgrs pkgmgr, char *version, enum cmpsense cmp); int InstallPackage (struct Package *ptr,enum pkgmgrs pkgmgr, struct Item **pkglist); int RemovePackage (struct Package *ptr,enum pkgmgrs pkgmgr, struct Item **pkglist); void ProcessPendingPackages (struct Package *ptr,enum pkgmgrs pkgmgr, enum pkgactions action, struct Item **pkglist); /* popen.c */ FILE *cfpopensetuid (char *command, char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv); FILE *cfpopen (char *command, char *type); FILE *cfpopen_sh (char *command, char *type); FILE *cfpopen_shsetuid (char *command, char *type, uid_t uid, gid_t gid, char *chdirv, char *chrootv); int cfpwait (pid_t pid); int cfpclose (FILE *pp); int cfpclose_def (FILE *pp, char *defines, char *elsedef); int CfSetUid(uid_t uid,gid_t gid); int SplitCommand (char *comm, char (*arg)[CF_BUFSIZE]); /* process.c */ int LoadProcessTable (struct Item **procdata, char *psopts); void DoProcessCheck (struct Process *pp, struct Item *procdata); int FindMatches (struct Process *pp, struct Item *procdata, struct Item **killlist); void DoSignals (struct Process *pp,struct Item *list); /* proto.c */ int IdentifyForVerification (int sd,char *localip, int family); int KeyAuthentication (struct Image *ip); int BadProtoReply (char *buf); int OKProtoReply (char *buf); int FailedProtoReply (char *buf); void CheckRemoteVersion(void); /* read.c */ int ReadLine (char *buff, int size, FILE *fp); /* report.c */ void ListDefinedVariables (void); void ListDefinedClasses (void); void ListDefinedMethods (char *classes); void ListDefinedAlerts (char *classes); void ListDefinedStrategies (char *classes); void ListDefinedInterfaces (char *classes); void ListDefinedHomePatterns (char *classes); void ListDefinedBinservers (char *classes); void ListDefinedLinks (char *classes); void ListDefinedLinkchs (char *classes); void ListDefinedResolvers (char *classes); void ListDefinedScripts (char *classes); void ListDefinedSCLI (char *classes); void ListDefinedImages (char *classes); void ListDefinedTidy (char *classes); void ListDefinedMountables (char *classes); void ListMiscMounts (char *classes); void ListDefinedRequired (char *classes); void ListDefinedHomeservers (char *classes); void ListDefinedDisable (char *classes); void ListDefinedMakePaths (char *classes); void ListDefinedImports (void); void ListDefinedIgnore (char *classes); void ListDefinedPackages (char *classes); void ListFiles (char *classes); void ListActionSequence (void); void ListUnmounts (char *classes); void ListProcesses (char *classes); void ListACLs (void); void ListFileEdits (char *classes); void ListFilters (char *classes); void InterfacePromise(struct Interface *ifp); void LinkPromise(struct Link *ptr, char *type); void PromiseItem(struct Item *ptr); void PromiseMethod(struct Method *ptr); void PromiseShellCommand(struct ShellComm *ptr); void PromiseFileCopy(struct Image *ptr); void PromiseTidy(struct Tidy *ptr,char *classes); void PromiseMountable(struct Mountables *ptr); void PromiseMiscMount(struct MiscMount *ptr); void DiskPromises(struct Disk *ptr); void PromiseDisable(struct Disable *ptr); void PromiseDirectories(struct File *ptr); void PromiseFiles(struct File *ptr); void PromiseUnmount(struct UnMount *ptr); void PromiseFileEdits(struct Edit *ptr,char *classes); void PromiseProcess(struct Process *ptr); void PromisePackages(struct Package *ptr); /* repository.c */ int Repository (char *file, char *repository); /* rotate.c */ void RotateFiles (char *name, int number); /* scli.c */ void SCLIScript(void); /* sensible.c */ int SensibleFile (char *nodename, char *path, struct Image *ip); void RegisterRecursionRootDevice (dev_t device); int DeviceChanged (dev_t thisdevice); /* state.c */ void AddPersistentClass (char *name,unsigned int ttl_minutes, enum statepolicy policy); void DeletePersistentClass (char *name); void PersistentClassesToHeap (void); void DePort (char *tcpbuffer); /* tidy.c */ int RecursiveHomeTidy (char *name, int level,struct stat *sb); int TidyHomeFile (char *path, char *name,struct stat *statbuf, int level); int RecursiveTidySpecialArea (char *name, struct Tidy *tp, int maxrecurse, struct stat *sb); void TidyParticularFile (char *path, char *name, struct Tidy *tp, struct stat *statbuf, int is_dir, int level,int usepath); void DoTidyFile (char *path, char *name, struct TidyPattern *tlp, struct stat *statbuf, short int logging_this, int isdir,int usepath); void DeleteTidyList (struct TidyPattern *list); /* timeout.c */ void SetTimeOut (int timeout); void TimeOut (void); void DeleteTimeOut (void); /* varstring.c */ void GetSepElement(char *from,char *to,int index,char sep); int IsListVar(char *name,char sep); int VarListLen(char *name, char sep); int TrueVar (char *var); int CheckVarID (char *var); int IsVarString (char *str); int ExpandVarstring (char *string,char buffer[CF_EXPANDSIZE], char *bserver); char *ExtractInnerVarString (char *string, char *substr); char *ExtractOuterVarString (char *string, char *substr); int ExpandVarbinserv (char *string, char *buffer, char *bserver); enum vnames ScanVariable (char *name); struct Item *SplitVarstring (char *varstring); struct Item *SplitString (char *varstring,char sep); /* wildcard.c */ int IsWildCard (char *str); int WildMatch (char *wildptr,char *cmpptr); char *AfterSubString (char *big, char *small, int status, char lastwild); /* wrapper.c */ void TidyWrapper (char *startpath, void *vp); void RecHomeTidyWrapper (char *startpath, void *vp); void CheckFileWrapper (char *startpath, void *vp); void DirectoriesWrapper (char *dir, void *vp); #ifdef HPuUX int Error; #endif cfengine-2.2.10/src/install.c0000644000175000001440000046536711022762501012711 00000000000000/* cfengine for GNU Copyright (C) 1995- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Routines which install actions parsed by the parser */ /* */ /* Derived from parse.c (Parse object) */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*******************************************************************/ void InstallControlRValue(char *lvalue,char *varvalue) { int number = -1; char buffer[CF_MAXVARSIZE], command[CF_MAXVARSIZE], *sp; char value[CF_EXPANDSIZE]; ExpandVarstring(varvalue,value,NULL); if (ScanVariable(lvalue) == cfautodef) { AppendItems(&VAUTODEFINE,value,CLASSBUFF); return; } if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing %s=%s, no match (%s)\n",lvalue,varvalue,CLASSBUFF); return; } if (strcmp(varvalue,CF_NOCLASS) == 0) { Debug1("Not installing %s, evaluated to false\n",varvalue); return; } /* begin version compat */ if (strncmp(value,"exec ",5) == 0) { for (sp = value+4; *sp == ' '; sp++) { } if (*sp == '/') { strncpy(command,sp,CF_MAXVARSIZE); GetExecOutput(command,value,false); Chop(value); value[CF_MAXVARSIZE-1] = '\0'; /* Truncate to CF_MAXVARSIZE */ } else { Warning("Exec string in control did not specify an absolute path"); } } /* end version 1 compat */ /* Actionsequence needs to be dynamical here, so make exception - should be IsInstallable?? */ if ((ScanVariable(lvalue) != cfactseq) && !IsDefinedClass(CLASSBUFF)) { Debug("Class %s not defined, not defining\n",CLASSBUFF); return; } else { Debug1("Assign variable [%s=%s] when %s)\n",lvalue,value,CLASSBUFF); } switch (ScanVariable(lvalue)) { case cfsite: case cffaculty: if (!IsDefinedClass(CLASSBUFF)) { break; } if (VFACULTY[0] != '\0') { yyerror("Multiple declaration of variable faculty / site"); FatalError("Redefinition of basic system variable"); } strcpy(VFACULTY,value); break; case cfdomain: if (!IsDefinedClass(CLASSBUFF)) { break; } if (strlen(value) > 0) { strcpy(VDOMAIN,value); DeleteClassFromHeap("undefined_domain"); } else { yyerror("domain is empty"); } if (!StrStr(VSYSNAME.nodename,VDOMAIN)) { snprintf(VFQNAME,CF_BUFSIZE,"%s.%s",VSYSNAME.nodename,ToLowerStr(VDOMAIN)); strcpy(VUQNAME,VSYSNAME.nodename); } else { int n = 0; strcpy(VFQNAME,VSYSNAME.nodename); while(VSYSNAME.nodename[n++] != '.') { } strncpy(VUQNAME,VSYSNAME.nodename,n-1); } if (! NOHARDCLASSES) { char *ptr; if (strlen(VFQNAME) > CF_MAXVARSIZE-1) { FatalError("The fully qualified name is longer than CF_MAXVARSIZE!!"); } strcpy(buffer,VFQNAME); AddClassToHeap(CanonifyName(buffer)); /* Add some domain hierarchy classes */ for (ptr=VFQNAME; *ptr != '\0'; ptr++) { if (*ptr == '.') { if (*(ptr+1) != '\0') { Debug("Defining domain #%s#\n",(ptr+1)); AddClassToHeap(CanonifyName(ptr+1)); } else { Debug("Domain rejected\n"); } } } } break; case cfsysadm: /* Can be redefined */ if (!IsDefinedClass(CLASSBUFF)) { break; } strcpy(VSYSADM,value); break; case cfnetmask: if (!IsDefinedClass(CLASSBUFF)) { break; } if (VNETMASK[0] != '\0') { yyerror("Multiple declaration of variable netmask"); FatalError("Redefinition of basic system variable"); } strcpy(VNETMASK,value); AddNetworkClass(VNETMASK); break; case cfmountpat: SetMountPath(value); break; case cfrepos: SetRepository(value); break; case cfhomepat: Debug1("Installing %s as home pattern\n",value); AppendItem(&VHOMEPATLIST,value,CLASSBUFF); break; case cfextension: AppendItems(&EXTENSIONLIST,value,CLASSBUFF); break; case cfsuspicious: AppendItems(&SUSPICIOUSLIST,value,CLASSBUFF); break; case cfschedule: AppendItems(&SCHEDULE,value,CLASSBUFF); break; case cfspooldirs: AppendItem(&SPOOLDIRLIST,value,CLASSBUFF); break; case cfmethodpeers: AppendItems(&VRPCPEERLIST,value,CLASSBUFF); break; case cfnonattackers: AppendItems(&NONATTACKERLIST,value,CLASSBUFF); break; case cfmulticonn: AppendItems(&MULTICONNLIST,value,CLASSBUFF); break; case cftrustkeys: AppendItems(&TRUSTKEYLIST,value,CLASSBUFF); break; case cfabortclasses: AppendItem(&ABORTHEAP,value,CLASSBUFF); break; case cfignoreinterfaceregex: DeleteInterfaceInfo(value); break; case cfdynamic: AppendItems(&DHCPLIST,value,CLASSBUFF); break; case cfallowusers: AppendItems(&ALLOWUSERLIST,value,CLASSBUFF); break; case cfskipverify: AppendItems(&SKIPVERIFY,value,CLASSBUFF); break; case cfredef: AppendItems(&VREDEFINES,value,CLASSBUFF); break; case cfattackers: AppendItems(&ATTACKERLIST,value,CLASSBUFF); break; case cftimezone: if (!IsDefinedClass(CLASSBUFF)) { break; } AppendItem(&VTIMEZONE,value,NULL); break; case cfssize: sscanf(value,"%d",&number); if (number >= 0) { SENSIBLEFSSIZE = number; } else { yyerror("Silly value for sensiblesize (must be positive integer)"); } break; case cfscount: sscanf(value,"%d",&number); if (number > 0) { SENSIBLEFILECOUNT = number; } else { yyerror("Silly value for sensiblecount (must be positive integer)"); } break; case cfeditsize: sscanf(value,"%d",&number); if (number >= 0) { EDITFILESIZE = number; } else { yyerror("Silly value for editfilesize (must be positive integer)"); } break; case cfbineditsize: sscanf(value,"%d",&number); if (number >= 0) { EDITBINFILESIZE = number; } else { yyerror("Silly value for editbinaryfilesize (must be positive integer)"); } break; case cfifelapsed: sscanf(value,"%d",&number); if (number >= 0) { VDEFAULTIFELAPSED = VIFELAPSED = number; } else { yyerror("Silly value for IfElapsed"); } break; case cfexpireafter: sscanf(value,"%d",&number); if (number > 0) { VDEFAULTEXPIREAFTER = VEXPIREAFTER = number; } else { yyerror("Silly value for ExpireAfter"); } break; case cfactseq: AppendToActionSequence(value); break; case cfaccess: AppendToAccessList(value); break; case cfnfstype: strcpy(VNFSTYPE,value); break; case cfmethodname: if (strcmp(METHODNAME,"cf-nomethod") != 0) { yyerror("Redefinition of method name"); } strncpy(METHODNAME,value,CF_BUFSIZE-1); SetContext("private-method"); break; case cfarglist: AppendItem(&METHODARGS,value,CLASSBUFF); break; case cfaddclass: AddMultipleClasses(value); break; case cfinstallclass: AddInstallable(value); break; case cfexcludecp: PrependItem(&VEXCLUDECOPY,value,CLASSBUFF); break; case cfsinglecp: PrependItem(&VSINGLECOPY,value,CLASSBUFF); if ((strcmp(value,"on")==0) || (strcmp(value,"true")==0) || (strcmp(value,"*")==0)) { ALL_SINGLECOPY = true; } break; break; case cfexcludeln: PrependItem(&VEXCLUDELINK,value,CLASSBUFF); break; case cfcplinks: PrependItem(&VCOPYLINKS,value,CLASSBUFF); break; case cflncopies: PrependItem(&VLINKCOPIES,value,CLASSBUFF); break; case cfrepchar: if (strlen(value) > 1) { yyerror("reposchar can only be a single letter"); break; } if (value[0] == '/') { yyerror("illegal value for reposchar"); break; } REPOSCHAR = value[0]; break; case cflistsep: if (strlen(value) > 1) { yyerror("listseparator can only be a single letter"); break; } if (value[0] == '/') { yyerror("illegal value for listseparator"); break; } LISTSEPARATOR = value[0]; break; case cfunderscore: if (strcmp(value,"on") == 0) { char rename[CF_MAXVARSIZE]; UNDERSCORE_CLASSES=true; Verbose("Resetting classes using underscores...\n"); while(DeleteItemContaining(&VHEAP,CLASSTEXT[VSYSTEMHARDCLASS])) { } sprintf(rename,"_%s",CLASSTEXT[VSYSTEMHARDCLASS]); AddClassToHeap(rename); break; } if (strcmp(value,"off") == 0) { UNDERSCORE_CLASSES=false; break; } yyerror("illegal value for underscoreclasses"); break; case cfifname: if (strlen(value)>15) { yyerror("Silly interface name, (should be something link eth0)"); } strncpy(VIFNAMEOVERRIDE,value,15); VIFDEV[VSYSTEMHARDCLASS] = VIFNAMEOVERRIDE; /* override */ Debug("Overriding interface with %s\n",VIFDEV[VSYSTEMHARDCLASS]); break; case cfdefcopy: if (strcmp(value,"ctime") == 0) { DEFAULTCOPYTYPE = 't'; return; } else if (strcmp(value,"mtime") == 0) { DEFAULTCOPYTYPE = 'm'; return; } else if (strcmp(value,"checksum")==0 || strcmp(value,"sum") == 0) { DEFAULTCOPYTYPE = 'c'; return; } else if (strcmp(value,"byte")==0 || strcmp(value,"binary") == 0) { DEFAULTCOPYTYPE = 'b'; return; } yyerror("Illegal default copy type"); break; case cfdefpkgmgr: DEFAULTPKGMGR = GetPkgMgr(value); break; default: AddMacroValue(CONTEXTID,lvalue,value); break; } } /*******************************************************************/ void HandleEdit(char *file,char *edit,char *string) /* child routines in edittools.c */ { if (! IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing Edit no match\n"); return; } if (string == NULL) { Debug1("Handling Edit of %s, action [%s] with no data if (%s)\n",file,edit,CLASSBUFF); } else { Debug1("Handling Edit of %s, action [%s] with data <%s> if (%s)\n",file,edit,string,CLASSBUFF); } if (EditFileExists(file)) { AddEditAction(file,edit,string); } else { InstallEditFile(file,edit,string); } } /********************************************************************/ void HandleOptionalFileAttribute(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("File attribute with no value"); } Debug1("HandleOptionalFileAttribute(%s)\n",value); switch(GetCommAttribute(item)) { case cfrecurse: HandleRecurse(value); break; case cfmode: ParseModeString(value,&PLUSMASK,&MINUSMASK); break; case cfflags: ParseFlagString(value,&PLUSFLAG,&MINUSFLAG); break; case cfowner: if (strlen(value) < CF_BUFSIZE) { strcpy(VUIDNAME,value); } else { yyerror("Too many owners"); } break; case cfgroup: if (strlen(value) < CF_BUFSIZE) { strcpy(VGIDNAME,value); } else { yyerror("Too many groups"); } break; case cfaction: FILEACTION = (enum fileactions) GetFileAction(value); break; case cflinks: HandleTravLinks(value); break; case cfexclude: DeleteSlash(value); PrependItem(&VEXCLUDEPARSE,value,CF_ANYCLASS); break; case cfinclude: DeleteSlash(value); PrependItem(&VINCLUDEPARSE,value,CF_ANYCLASS); break; case cfignore: PrependItem(&VIGNOREPARSE,value,CF_ANYCLASS); break; case cfacl: PrependItem(&VACLBUILD,value,CF_ANYCLASS); break; case cffilter: PrependItem(&VFILTERBUILD,value,CF_ANYCLASS); break; case cfdefine: HandleDefine(value); break; case cfelsedef: HandleElseDefine(value); break; case cfsetlog: HandleCharSwitch("log",value,&LOGP); break; case cfsetinform: HandleCharSwitch("inform",value,&INFORMP); break; case cfsetaudit: HandleCharSwitch("audit",value,&AUDITP); break; case cfchksum: HandleChecksum(value); break; case cfxdev: HandleCharSwitch("xdev",value,&XDEV); break; case cfrxdirs: HandleCharSwitch("rxdirs",value,&RXDIRS); break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; default: yyerror("Illegal file attribute"); } } /*******************************************************************/ void HandleOptionalImageAttribute(char *item) { char value[CF_EXPANDSIZE],ebuff[CF_EXPANDSIZE]; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%[^\n]",value); if (value[0] == '\0') { yyerror("Copy attribute with no value"); } Debug1("HandleOptionalImageAttribute(%s)\n",value); switch(GetCommAttribute(item)) { #ifdef DARWIN case cffindertype: if (strlen(value) == 4) { strncpy(FINDERTYPE,value,CF_BUFSIZE); } else { yyerror("Attribute findertype must be exactly 4 characters"); } break; #endif case cfmode: ParseModeString(value,&PLUSMASK,&MINUSMASK); break; case cfflags: ParseFlagString(value,&PLUSFLAG,&MINUSFLAG); break; case cfowner: strcpy(VUIDNAME,value); break; case cfgroup: strcpy(VGIDNAME,value); break; case cfdest: strcpy(DESTINATION,value); break; case cfaction: strcpy(IMAGEACTION,value); break; case cfcompat: HandleCharSwitch("oldserver",value,&COMPATIBILITY); break; case cfcheckroot: HandleCharSwitch("checkroot",value,&CHKROOT); break; case cfforce: HandleCharSwitch("force",value,&FORCE); break; case cfforcedirs: HandleCharSwitch("forcedirs",value,&FORCEDIRS); break; case cfforceipv4: HandleCharSwitch("forceipv4",value,&FORCEIPV4); break; case cfbackup: HandleCharSwitch("backup",value,&IMAGEBACKUP); break; case cfrecurse: HandleRecurse(value); break; case cftype: HandleCopyType(value); break; case cfexclude: PrependItem(&VEXCLUDEPARSE,value,CF_ANYCLASS); break; case cfsymlink: PrependItem(&VCPLNPARSE,value,CF_ANYCLASS); break; case cfinclude: PrependItem(&VINCLUDEPARSE,value,CF_ANYCLASS); break; case cfignore: PrependItem(&VIGNOREPARSE,value,CF_ANYCLASS); break; case cflntype: HandleLinkType(value); break; case cfserver: HandleServer(value); break; case cfencryp: HandleCharSwitch("encrypt",value,&ENCRYPT); break; case cfverify: HandleCharSwitch("verify",value,&VERIFY); break; case cfdefine: HandleDefine(value); break; case cfelsedef: HandleElseDefine(value); break; case cffailover: HandleFailover(value); break; case cfsize: HandleCopySize(value); break; case cfacl: PrependItem(&VACLBUILD,value,CF_ANYCLASS); break; case cfpurge: HandleCharSwitch("purge",value,&PURGE); break; case cfsetlog: HandleCharSwitch("log",value,&LOGP); break; case cfsetinform: HandleCharSwitch("inform",value,&INFORMP); break; case cfsetaudit: HandleCharSwitch("audit",value,&AUDITP); break; case cfstealth: HandleCharSwitch("stealth",value,&STEALTH); break; case cftypecheck: HandleCharSwitch("typecheck",value,&TYPECHECK); break; case cfrepository: strncpy(LOCALREPOS,value,CF_BUFSIZE-CF_BUFFERMARGIN); break; case cffilter: PrependItem(&VFILTERBUILD,value,CF_ANYCLASS); break; case cftrustkey: HandleCharSwitch("trustkey",value,&TRUSTKEY); break; case cftimestamps: HandleTimeStamps(value); break; case cfxdev: HandleCharSwitch("xdev",value,&XDEV); break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; default: yyerror("Illegal copy attribute"); } } /******************************************************************/ void HandleOptionalRequired(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Required/disk attribute with no value"); } Debug1("HandleOptionalRequiredAttribute(%s)\n",value); switch(GetCommAttribute(ebuff)) { case cffree: HandleRequiredSize(value); break; case cfscan: HandleCharSwitch("scanarrivals",value,&SCAN); break; case cfdefine: HandleDefine(value); break; case cfelsedef: HandleElseDefine(value); break; case cfsetlog: HandleCharSwitch("log",value,&LOGP); break; case cfsetinform: HandleCharSwitch("inform",value,&INFORMP); break; case cfsetaudit: HandleCharSwitch("audit",value,&AUDITP); break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; /* HvB: Bas van der Vlies */ case cfforce: HandleCharSwitch("force",value,&FORCE); break; default: yyerror("Illegal disk/required attribute"); } } /******************************************************************/ void HandleOptionalInterface(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("intefaces attribute with no value"); } Debug1("HandleOptionalInterfaceAttribute(value=%s)\n",value); switch(GetCommAttribute(item)) { case cfsetnetmask: HandleNetmask(value); break; case cfsetbroadcast: HandleBroadcast(value); break; case cfsetipaddress: HandleIPAddress(value); break; default: yyerror("Illegal interfaces attribute"); } } /***********************************************************************/ void HandleOptionalMountablesAttribute(char *item) /* HvB: Bas van der Vlies */ { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("mount attribute with no value"); } Debug1("HandleOptionalMountItem(%s)\n",value); switch(GetCommAttribute(item)) { case cfmountoptions: strcpy(MOUNTOPTS, value); break; case cfreadonly: if ((strcmp(value,"on")==0) || (strcmp(value,"true")==0)) { CF_MOUNT_RO=true; } break; default: yyerror("Illegal mount option" "(mountoptions/readonly)"); } } /******************************************************************/ void HandleOptionalUnMountAttribute(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Unmount attribute with no value"); } Debug1("HandleOptionalUnMountsItem(%s)\n",value); switch(GetCommAttribute(item)) { case cfdeldir: if (strcmp(value,"true") == 0 || strcmp(value,"yes") == 0) { DELETEDIR = 'y'; break; } if (strcmp(value,"false") == 0 || strcmp(value,"no") == 0) { DELETEDIR = 'n'; break; } break; case cfdelfstab: if (strcmp(value,"true") == 0 || strcmp(value,"yes") == 0) { DELETEFSTAB = 'y'; break; } if (strcmp(value,"false") == 0 || strcmp(value,"no") == 0) { DELETEFSTAB = 'n'; break; } break; case cfforce: if (strcmp(value,"true") == 0 || strcmp(value,"yes") == 0) { FORCE = 'y'; break; } if (strcmp(value,"false") == 0 || strcmp(value,"no") == 0) { FORCE = 'n'; break; } break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; default: yyerror("Illegal unmount option (deletedir/deletefstab/force)"); } } /******************************************************************/ void HandleOptionalMiscMountsAttribute(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Miscmounts attribute with no value"); } Debug1("HandleOptionalMiscMOuntsItem(%s)\n",value); switch(GetCommAttribute(item)) { case cfmode: { struct Item *op; struct Item *next; if (MOUNTOPTLIST) {/* just in case */ DeleteItemList(MOUNTOPTLIST); } MOUNTOPTLIST = SplitStringAsItemList(value,','); for (op = MOUNTOPTLIST; op != NULL; op = next) { next = op->next; /* in case op is deleted */ Debug1("miscmounts option: %s\n", op->name); if (strcmp(op->name,"rw") == 0) { MOUNTMODE='w'; DeleteItem(&MOUNTOPTLIST,op); } else if (strcmp(op->name,"ro") == 0) { MOUNTMODE='o'; DeleteItem(&MOUNTOPTLIST,op); } /* validate other mount options here */ } } break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; default: yyerror("Illegal miscmounts attribute (rw/ro)"); } } /******************************************************************/ void HandleOptionalTidyAttribute(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Tidy attribute with no value"); } Debug1("HandleOptionalTidyAttribute(%s)\n",value); switch(GetCommAttribute(item)) { case cfrecurse: HandleRecurse(value); break; case cfexclude: PrependItem(&VEXCLUDEPARSE,value,CF_ANYCLASS); break; case cfignore: PrependItem(&VIGNOREPARSE,value,CF_ANYCLASS); break; case cfinclude: case cfpattern: strcpy(CURRENTITEM,value); if (*value == '/') { yyerror("search pattern begins with / must be a relative name"); } break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; case cfage: HandleAge(value); break; case cflinks: HandleTravLinks(value); break; case cfsize: HandleTidySize(value); break; case cftype: HandleTidyType(value); break; case cfdirlinks: HandleTidyLinkDirs(value); break; case cfrmdirs: HandleTidyRmdirs(value); break; case cfdefine: HandleDefine(value); break; case cfelsedef: HandleElseDefine(value); break; case cfsetlog: HandleCharSwitch("log",value,&LOGP); break; case cfsetinform: HandleCharSwitch("inform",value,&INFORMP); break; case cfsetaudit: HandleCharSwitch("audit",value,&AUDITP); break; case cfcompress: HandleCharSwitch("compress",value,&COMPRESS); break; case cffilter: PrependItem(&VFILTERBUILD,value,CF_ANYCLASS); break; case cfxdev: HandleCharSwitch("xdev",value,&XDEV); break; default: yyerror("Illegal tidy attribute"); } } /******************************************************************/ void HandleOptionalDirAttribute(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(item,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Directory attribute with no value"); } Debug1("HandleOptionalDirAttribute(%s)\n",value); switch(GetCommAttribute(item)) { case cfmode: ParseModeString(value,&PLUSMASK,&MINUSMASK); break; case cfflags: ParseFlagString(value,&PLUSFLAG,&MINUSFLAG); break; case cfowner: strcpy(VUIDNAME,value); break; case cfgroup: strcpy(VGIDNAME,value); break; case cfdefine: HandleDefine(value); break; case cfelsedef: HandleElseDefine(value); break; case cfsetlog: HandleCharSwitch("log",value,&LOGP); break; case cfsetinform: HandleCharSwitch("inform",value,&INFORMP); break; case cfsetaudit: HandleCharSwitch("audit",value,&AUDITP); break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; case cfrxdirs: HandleCharSwitch("rxdirs",value,&RXDIRS); break; default: yyerror("Illegal directory attribute"); } } /*******************************************************************/ void HandleOptionalDisableAttribute(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Disable attribute with no value"); } Debug1("HandleOptionalDisableAttribute(%s)\n",value); switch(GetCommAttribute(item)) { case cfaction: if (strcmp(value,"warn") == 0) { PROACTION = 'w'; } else if (strcmp(value,"delete") == 0) { PROACTION = 'd'; } else { yyerror("Unknown action for disable"); } break; case cftype: HandleDisableFileType(value); break; case cfrotate: HandleDisableRotate(value); break; case cfsize: HandleDisableSize(value); break; case cfdefine: HandleDefine(value); break; case cfelsedef: HandleElseDefine(value); break; case cfsetlog: HandleCharSwitch("log",value,&LOGP); break; case cfsetinform: HandleCharSwitch("inform",value,&INFORMP); break; case cfsetaudit: HandleCharSwitch("audit",value,&AUDITP); break; case cfrepository: strncpy(LOCALREPOS,value,CF_BUFSIZE-CF_BUFFERMARGIN); break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; case cfdest: strncpy(DESTINATION,value,CF_BUFSIZE-1); break; default: yyerror("Illegal disable attribute"); } } /*******************************************************************/ void HandleOptionalLinkAttribute(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Link attribute with no value"); } Debug1("HandleOptionalLinkAttribute(%s)\n",value); switch(GetCommAttribute(item)) { case cfaction: HandleLinkAction(value); break; case cftype: HandleLinkType(value); break; case cfexclude: PrependItem(&VEXCLUDEPARSE,value,CF_ANYCLASS); break; case cfinclude: PrependItem(&VINCLUDEPARSE,value,CF_ANYCLASS); break; case cffilter: PrependItem(&VFILTERBUILD,value,CF_ANYCLASS); break; case cfignore: PrependItem(&VIGNOREPARSE,value,CF_ANYCLASS); break; case cfcopy: PrependItem(&VCPLNPARSE,value,CF_ANYCLASS); break; case cfrecurse: HandleRecurse(value); break; case cfcptype: HandleCopyType(value); break; case cfnofile: HandleDeadLinks(value); break; case cfdefine: HandleDefine(value); break; case cfelsedef: HandleElseDefine(value); break; case cfsetlog: HandleCharSwitch("log",value,&LOGP); break; case cfsetinform: HandleCharSwitch("inform",value,&INFORMP); break; case cfsetaudit: HandleCharSwitch("audit",value,&AUDITP); break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; default: yyerror("Illegal link attribute"); } } /*******************************************************************/ void HandleOptionalProcessAttribute(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Process attribute with no value"); } Debug1("HandleOptionalProcessAttribute(%s)\n",value); switch(GetCommAttribute(item)) { case cfaction: if (strcmp(value,"signal") == 0 || strcmp(value,"do") == 0) { PROACTION = 's'; } else if (strcmp(value,"bymatch") == 0) { PROACTION = 'm'; } else if (strcmp(value,"warn") == 0) { PROACTION = 'w'; ACTIONPENDING = true; } else { yyerror("Unknown action for processes"); } break; case cfmatches: HandleProcessMatches(value); ACTIONPENDING = true; break; case cfsignal: HandleProcessSignal(value); ACTIONPENDING = true; break; case cfdefine: HandleDefine(value); break; case cfelsedef: HandleElseDefine(value); break; case cfuseshell:HandleUseShell(value); break; case cfsetlog: HandleCharSwitch("log",value,&LOGP); break; case cfsetinform: HandleCharSwitch("inform",value,&INFORMP); break; case cfsetaudit: HandleCharSwitch("audit",value,&AUDITP); break; case cfexclude: PrependItem(&VEXCLUDEPARSE,value,CF_ANYCLASS); break; case cfinclude: PrependItem(&VINCLUDEPARSE,value,CF_ANYCLASS); break; case cffilter: PrependItem(&VFILTERBUILD,value,CF_ANYCLASS); break; case cfowner: strcpy(VUIDNAME,value); break; case cfgroup: strcpy(VGIDNAME,value); break; case cfchdir: HandleChDir(value); break; case cfchroot: HandleChRoot(value); break; case cfumask: HandleUmask(value); break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; default: yyerror("Illegal process attribute"); } } /*******************************************************************/ void HandleOptionalPackagesAttribute(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Packages attribute with no value"); } Debug1("HandleOptionalPackagesAttribute(%s)\n",value); switch(GetCommAttribute(item)) { case cfversion: strcpy(PKGVER,value); break; case cfcmp: CMPSENSE = (enum cmpsense) GetCmpSense(value); break; case cfpkgmgr: PKGMGR = (enum pkgmgrs) GetPkgMgr(value); break; case cfdefine: HandleDefine(value); break; case cfelsedef: HandleElseDefine(value); break; case cfsetlog: HandleCharSwitch("log",value,&LOGP); break; case cfsetinform: HandleCharSwitch("inform",value,&INFORMP); break; case cfsetaudit: HandleCharSwitch("audit",value,&AUDITP); break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; case cfaction: PKGACTION = (enum pkgactions) GetPkgAction(value); break; default: yyerror("Illegal packages attribute"); } } /*******************************************************************/ void HandleOptionalMethodsAttribute(char *item) { char value[CF_BUFSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Methods attribute with no value"); } switch(GetCommAttribute(item)) { case cfserver: HandleServer(value); break; case cfaction: strncpy(ACTIONBUFF,value,CF_BUFSIZE-1); break; case cfretvars: strncpy(METHODFILENAME,value,CF_BUFSIZE-1); break; case cfretclasses: if (strlen(PARSEMETHODRETURNCLASSES) > 0) { yyerror("Redefinition of method return_classes"); } else { strncpy(PARSEMETHODRETURNCLASSES,value,CF_BUFSIZE-1); } break; case cfforcereplyto: strncpy(METHODFORCE,value,CF_BUFSIZE-1); break; case cfsendclasses: if (strlen(METHODREPLYTO) > 0) { yyerror("Redefinition of method send_classes"); } else { strncpy(METHODREPLYTO,value,CF_MAXVARSIZE-1); } break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; case cfowner: strncpy(VUIDNAME,value,CF_BUFSIZE-1); break; case cfgroup: strncpy(VGIDNAME,value,CF_BUFSIZE-1); break; case cfchdir: HandleChDir(value); break; case cfchroot: HandleChRoot(value); break; default: yyerror("Illegal methods attribute"); } ACTIONPENDING = true; } /*******************************************************************/ void HandleOptionalScriptAttribute(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Shellcommand attribute with no value"); } Debug1("HandleOptionalScriptAttribute(%s)\n",value); switch(GetCommAttribute(item)) { case cftimeout: HandleTimeOut(value); break; case cfuseshell: HandleUseShell(value); break; case cfsetlog: HandleCharSwitch("log",value,&LOGP); break; case cfsetinform: HandleCharSwitch("inform",value,&INFORMP); break; case cfsetaudit: HandleCharSwitch("audit",value,&AUDITP); break; case cfowner: strcpy(VUIDNAME,value); break; case cfgroup: strcpy(VGIDNAME,value); break; case cfdefine: HandleDefine(value); break; case cfelsedef: HandleElseDefine(value); break; case cfumask: HandleUmask(value); break; case cffork: HandleCharSwitch("background",value,&FORK); break; case cfchdir: HandleChDir(value); break; case cfchroot: HandleChRoot(value); break; case cfpreview: HandleCharSwitch("preview",value,&PREVIEW); break; case cfnoabspath: HandleCharSwitch("noabspath",value,&NOABSPATH); break; case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; default: yyerror("Illegal shellcommand attribute"); } } /*******************************************************************/ void HandleOptionalAlertsAttribute(char *item) { char value[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; value[0] = '\0'; ExpandVarstring(item,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { yyerror("Alerts attribute with no value"); } Debug1("HandleOptionalAlertsAttribute(%s)\n",value); switch(GetCommAttribute(item)) { case cfifelap: HandleIntSwitch("ifelapsed",value,&PIFELAPSED,0,999999); break; case cfexpaft: HandleIntSwitch("expireafter",value,&PEXPIREAFTER,0,999999); break; case cfsetaudit: HandleCharSwitch("audit",value,&AUDITP); break; default: yyerror("Illegal alerts attribute"); } } /*******************************************************************/ void HandleChDir(char *value) { if (!IsAbsoluteFileName(value)) { yyerror("chdir is not an absolute directory name"); } strcpy(CHDIR,value); } /*******************************************************************/ void HandleChRoot(char *value) { if (!IsAbsoluteFileName(value)) { yyerror("chdir is not an absolute directory name"); } strcpy(CHROOT,value); } /*******************************************************************/ void HandleFileItem(char *item) { if (strcmp(item,"home") == 0) { ACTIONPENDING=true; strcpy(CURRENTOBJECT,"home"); return; } snprintf(OUTPUT,100,"Unknown attribute %s",item); yyerror(OUTPUT); } /*******************************************************************/ void InstallBroadcastItem(char *item) { Debug1("Install broadcast mode (%s)\n",item); if ( ! IsInstallable(CLASSBUFF)) { Debug1("Not installing %s, no match\n",item); return; } if (VBROADCAST[0] != '\0') { yyerror("Multiple declaration of variable broadcast"); FatalError("Redefinition of basic system variable"); } if (strcmp("ones",item) == 0) { strcpy(VBROADCAST,"one"); return; } if (strcmp("zeroes",item) == 0) { strcpy(VBROADCAST,"zero"); return; } if (strcmp("zeros",item) == 0) { strcpy(VBROADCAST,"zero"); return; } yyerror ("Unknown broadcast mode (should be ones, zeros or zeroes)"); FatalError("Unknown broadcast mode"); } /*******************************************************************/ void InstallDefaultRouteItem(char *item) { struct hostent *hp; struct in_addr inaddr; char ebuff[CF_EXPANDSIZE]; Debug1("Install defaultroute mode (%s)\n",item); if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing %s, no match\n",item); return; } if (VDEFAULTROUTE != NULL) { yyerror("Multiple declaration of variable defaultroute"); FatalError("Redefinition of basic system variable"); } ExpandVarstring(item,ebuff,NULL); if (inet_addr(ebuff) == -1) { if ((hp = gethostbyname(ebuff)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Bad address/host (%s) in default route\n",ebuff); CfLog(cferror,OUTPUT,"gethostbyname"); yyerror ("Bad specification of default packet route: hostname or decimal IP address"); } else { memcpy(&inaddr,hp->h_addr, hp->h_length); PrependItem(&VDEFAULTROUTE,inet_ntoa(inaddr),CLASSBUFF); } } else { PrependItem(&VDEFAULTROUTE,ebuff,CLASSBUFF); } } /*******************************************************************/ void InstallGroupRValue(char *item,enum itemtypes type) { char *machine, *user, *domain; char ebuff[CF_EXPANDSIZE]; if (!IsDefinedClass(CLASSBUFF)) { Debug("Not defining class (%s) - no match of container class (%s)\n",item,CLASSBUFF); return; } if (*item == '\'' || *item == '"' || *item == '`') { ExpandVarstring(item+1,ebuff,NULL); } else { ExpandVarstring(item,ebuff,NULL); } Debug1("HandleGroupRVal(%s) group (%s), type=%d with fqname=%s,uqname=%s\n",ebuff,GROUPBUFF,type,VFQNAME,VUQNAME); switch (type) { case simple: if (strcmp(ebuff,VUQNAME) == 0) { AddClassToHeap(GROUPBUFF); break; } if (strcmp(ebuff,VFQNAME) == 0) { AddClassToHeap(GROUPBUFF); break; } if (IsDefinedClass(ebuff)) { AddClassToHeap(GROUPBUFF); break; } Debug("[No match of class %s]\n\n",ebuff); break; case netgroup: setnetgrent(ebuff); while (getnetgrent(&machine,&user,&domain)) { if (strcmp(machine,VUQNAME) == 0) { Debug1("Matched %s in netgroup %s\n",machine,ebuff); AddClassToHeap(GROUPBUFF); break; } if (strcmp(machine,VFQNAME) == 0) { Debug1("Matched %s in netgroup %s\n",machine,ebuff); AddClassToHeap(GROUPBUFF); break; } } endnetgrent(); break; case groupdeletion: setnetgrent(ebuff); while (getnetgrent(&machine,&user,&domain)) { if (strcmp(machine,VUQNAME) == 0) { Debug1("Matched delete item %s in netgroup %s\n",machine,ebuff); DeleteItemLiteral(&VHEAP,GROUPBUFF); break; } if (strcmp(machine,VFQNAME) == 0) { Debug1("Matched delete item %s in netgroup %s\n",machine,ebuff); DeleteItemLiteral(&VHEAP,GROUPBUFF); break; } } endnetgrent(); break; case classscript: if (ebuff[0] != '/') { yyerror("Quoted scripts must begin with / for absolute path"); break; } SetClassesOnScript(ebuff,GROUPBUFF,NULL,false); break; case deletion: if (IsDefinedClass(ebuff)) { DeleteItemLiteral(&VHEAP,GROUPBUFF); } break; default: yyerror("Software error"); FatalError("Unknown item type"); } } /*******************************************************************/ void HandleHomePattern(char *pattern) { char ebuff[CF_EXPANDSIZE]; ExpandVarstring(pattern,ebuff,""); AppendItem(&VHOMEPATLIST,ebuff,CLASSBUFF); } /*******************************************************************/ void AppendNameServer(char *item) { char ebuff[CF_EXPANDSIZE]; struct Item *list = NULL, *ip; Debug1("Installing item (%s) in the nameserver list\n",item); if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing %s, no match\n",item); return; } ExpandVarstring(item,ebuff,""); list = SplitStringAsItemList(ebuff,LISTSEPARATOR); for (ip = list; ip != NULL; ip=ip->next) { PrependItem(&VRESOLVE,ip->name,CLASSBUFF); } } /*******************************************************************/ void AppendImport(char *item) { char ebuff[CF_EXPANDSIZE]; if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing %s, no match\n",item); return; } if (strcmp(item,VCURRENTFILE) == 0) { yyerror("A file cannot import itself"); FatalError("Infinite self-reference in class inheritance"); } Debug1("\n\n [Installing item (%s) in the import list]\n\n",item); ExpandVarstring(item,ebuff,""); InstallItem(&VIMPORT,ebuff,CLASSBUFF,0,0); } /*******************************************************************/ void InstallHomeserverItem(char *item) { char ebuff[CF_EXPANDSIZE]; if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing %s, no match\n",item); return; } ExpandVarstring(item,ebuff,""); AppendItem(&VHOMESERVERS,ebuff,CLASSBUFF); } /*******************************************************************/ void InstallBinserverItem(char *item) { char ebuff[CF_EXPANDSIZE]; if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing %s, no match\n",item); return; } ExpandVarstring(item,ebuff,""); AppendItem(&VBINSERVERS,ebuff,CLASSBUFF); } /*******************************************************************/ void InstallMailserverPath(char *path) { if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing %s, no match\n",path); return; } if (VMAILSERVER[0] != '\0') { FatalError("Redefinition of mailserver"); } strcpy(VMAILSERVER,path); Debug1("Installing mailserver (%s) for group (%s)",path,GROUPBUFF); } /*******************************************************************/ void InstallLinkItem(char *from,char *to) { struct Link *ptr; char buffer[CF_EXPANDSIZE], buffer2[CF_EXPANDSIZE]; char ebuff[CF_EXPANDSIZE]; Debug1("Storing Link: (From)%s->(To)%s\n",from,to); if (!IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing link no match\n"); return; } ExpandVarstring(from,ebuff,""); if (strlen(ebuff) > 1) { DeleteSlash(ebuff); } ExpandVarstring(to,buffer,""); if (strlen(buffer) > 1) { DeleteSlash(buffer); } ExpandVarstring(ALLCLASSBUFFER,buffer2,""); if ((ptr = (struct Link *)malloc(sizeof(struct Link))) == NULL) { FatalError("Memory Allocation failed for InstallListItem() #1"); } if ((ptr->from = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallListItem() #2"); } if ((ptr->to = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed for InstallListItem() #3"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallListItem() #4"); } if ((ptr->defines = strdup(buffer2)) == NULL) { FatalError("Memory Allocation failed for InstallListItem() #4a"); } ExpandVarstring(ELSECLASSBUFFER,buffer,""); if ((ptr->elsedef = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed xxx"); } AddInstallable(ptr->defines); AddInstallable(ptr->elsedef); if (VLINKTOP == NULL) /* First element in the list */ { VLINK = ptr; } else { VLINKTOP->next = ptr; } if (strlen(ptr->from) > 1) { DeleteSlash(ptr->from); } if (strlen(ptr->to) > 1) { DeleteSlash(ptr->to); } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->force = FORCELINK; ptr->silent = LINKSILENT; ptr->type = LINKTYPE; ptr->copytype = COPYTYPE; ptr->next = NULL; ptr->copy = VCPLNPARSE; ptr->exclusions = VEXCLUDEPARSE; ptr->inclusions = VINCLUDEPARSE; ptr->ignores = VIGNOREPARSE; ptr->filters = VFILTERBUILD; ptr->recurse = VRECURSE; ptr->nofile = DEADLINKS; ptr->log = LOGP; ptr->inform = INFORMP; ptr->logaudit = AUDITP; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); VLINKTOP = ptr; if (ptr->recurse != 0) { yyerror("Recursion can only be used with +> multiple links"); } InitializeAction(); } /*******************************************************************/ void InstallLinkChildrenItem (char *from,char *to) { struct Link *ptr; char *sp, buffer[CF_EXPANDSIZE],ebuff[CF_EXPANDSIZE]; struct TwoDimList *tp = NULL; Debug1("Storing Linkchildren item: %s -> %s\n",from,to); if (!IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing linkchildren no match\n"); return; } ExpandVarstring(from,ebuff,""); ExpandVarstring(ALLCLASSBUFFER,buffer,""); Build2DListFromVarstring(&tp,to,LISTSEPARATOR,false); Set2DList(tp); for (sp = Get2DListEnt(tp); sp != NULL; sp = Get2DListEnt(tp)) { if ((ptr = (struct Link *)malloc(sizeof(struct Link))) == NULL) { FatalError("Memory Allocation failed for InstallListChildrenItem() #1"); } if ((ptr->from = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallLinkchildrenItem() #2"); } if ((ptr->to = strdup(sp)) == NULL) { FatalError("Memory Allocation failed for InstallLinkChildrenItem() #3"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallLinkChildrenItem() #3"); } if ((ptr->defines = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed for InstallListItem() #4a"); } ExpandVarstring(ELSECLASSBUFFER,buffer,""); if ((ptr->elsedef = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed for Installrequied() #2"); } AddInstallable(ptr->defines); AddInstallable(ptr->elsedef); if (VCHLINKTOP == NULL) /* First element in the list */ { VCHLINK = ptr; } else { VCHLINKTOP->next = ptr; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->force = FORCELINK; ptr->silent = LINKSILENT; ptr->type = LINKTYPE; ptr->next = NULL; ptr->copy = VCPLNPARSE; ptr->nofile = DEADLINKS; ptr->exclusions = VEXCLUDEPARSE; ptr->inclusions = VINCLUDEPARSE; ptr->ignores = VIGNOREPARSE; ptr->copytype = COPYTYPE; ptr->filters = VFILTERBUILD; ptr->recurse = VRECURSE; ptr->log = LOGP; ptr->inform = INFORMP; ptr->logaudit = AUDITP; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); VCHLINKTOP = ptr; if (ptr->recurse != 0 && strcmp(ptr->to,"linkchildren") == 0) { yyerror("Sorry don't know how to recurse with linkchildren keyword"); } } Delete2DList(tp); InitializeAction(); } /*******************************************************************/ void InstallRequiredPath(char *path,int freespace) { struct Disk *ptr; char buffer[CF_EXPANDSIZE],ebuff[CF_EXPANDSIZE],*sp; struct TwoDimList *tp = NULL; Build2DListFromVarstring(&tp,path,LISTSEPARATOR,false); Set2DList(tp); for (sp = Get2DListEnt(tp); sp != NULL; sp = Get2DListEnt(tp)) { Debug1("Installing item (%s) in the required list\n",sp); if (!IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing %s, no match\n",sp); return; } ExpandVarstring(sp,ebuff,""); if ((ptr = (struct Disk *)malloc(sizeof(struct Disk))) == NULL) { FatalError("Memory Allocation failed for InstallRequired() #1"); } if ((ptr->name = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallRequired() #2"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallRequired() #2"); } ExpandVarstring(ALLCLASSBUFFER,buffer,""); if ((ptr->define = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed for Installrequied() #2"); } ExpandVarstring(ELSECLASSBUFFER,buffer,""); if ((ptr->elsedef = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed for Installrequied() #2"); } if (VREQUIRED == NULL) /* First element in the list */ { VREQUIRED = ptr; } else { VREQUIREDTOP->next = ptr; } AddInstallable(ptr->define); AddInstallable(ptr->elsedef); if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->freespace = freespace; ptr->next = NULL; ptr->log = LOGP; ptr->inform = INFORMP; ptr->logaudit = AUDITP; ptr->done = 'n'; ptr->scanarrivals = SCAN; ptr->scope = strdup(CONTEXTID); /* HvB : Bas van der Vlies */ ptr->force = FORCE; VREQUIREDTOP = ptr; } Delete2DList(tp); InitializeAction(); } /*******************************************************************/ void InstallMountableItem(char *path,char *mnt_opts,flag readonly) { struct Mountables *ptr; char ebuff[CF_EXPANDSIZE]; Debug1("Adding mountable %s to list\n",path); if (!IsDefinedClass(CLASSBUFF)) { return; } ExpandVarstring(path,ebuff,""); Debug1("Adding mountable %s to list\n",ebuff); /* * Check if mount entry already exists */ if (VMOUNTABLES != NULL) { for (ptr = VMOUNTABLES; ptr != NULL; ptr = ptr->next) { if ( strcmp(ptr->filesystem, VBUFF) == 0 ) { snprintf(OUTPUT,CF_BUFSIZE*2,"Only one definition per mount allowed: %s\n",ptr->filesystem); yyerror(OUTPUT); return; } } } if ((ptr = (struct Mountables *)malloc(sizeof(struct Mountables))) == NULL) { FatalError("Memory Allocation failed for InstallMountableItem() #1"); } if ((ptr->filesystem = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallMountableItem() #2"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallMountableItem() #3"); } if ( mnt_opts[0] != '\0' ) { if ( (ptr->mountopts = strdup(mnt_opts)) == NULL ) { FatalError("Memory Allocation failed for InstallMountableItem() #4"); } } else { ptr->mountopts = NULL; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->readonly = readonly; ptr->next = NULL; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); if (VMOUNTABLESTOP == NULL) /* First element in the list */ { VMOUNTABLES = ptr; } else { VMOUNTABLESTOP->next = ptr; } VMOUNTABLESTOP = ptr; } /*******************************************************************/ void AppendUmount(char *path,char deldir,char delfstab,char force) { struct UnMount *ptr; char ebuff[CF_EXPANDSIZE]; if (!IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing %s, no match\n",path); return; } ExpandVarstring(path,ebuff,""); if ((ptr = (struct UnMount *)malloc(sizeof(struct UnMount))) == NULL) { FatalError("Memory Allocation failed for AppendUmount() #1"); } if ((ptr->name = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for AppendUmount() #2"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for AppendUmount() #5"); } if (VUNMOUNTTOP == NULL) /* First element in the list */ { VUNMOUNT = ptr; } else { VUNMOUNTTOP->next = ptr; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->next = NULL; ptr->deletedir = deldir; /* t/f - true false */ ptr->deletefstab = delfstab; ptr->force = force; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); VUNMOUNTTOP = ptr; } /*******************************************************************/ void AppendMiscMount(char *from,char *onto,char *mode, char *opts) { struct MiscMount *ptr; char ebuff[CF_EXPANDSIZE]; Debug1("Adding misc mountable %s %s (%s) to list\n",from,onto,opts); if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing %s, no match\n",from); return; } if ((ptr = (struct MiscMount *)malloc(sizeof(struct MiscMount))) == NULL) { FatalError("Memory Allocation failed for AppendMiscMount #1"); } ExpandVarstring(from,ebuff,""); if ((ptr->from = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for AppendMiscMount() #2"); } ExpandVarstring(onto,ebuff,""); if ((ptr->onto = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for AppendMiscMount() #3"); } if ((ptr->options = strdup(opts)) == NULL) { FatalError("Memory Allocation failed for AppendMiscMount() #4"); } if ((ptr->mode = strdup(mode)) == NULL) { FatalError("Memory Allocation failed for AppendMiscMount() #4a"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for AppendMiscMount() #5"); } if (VMISCMOUNTTOP == NULL) /* First element in the list */ { VMISCMOUNT = ptr; } else { VMISCMOUNTTOP->next = ptr; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->next = NULL; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); VMISCMOUNTTOP = ptr; } /*******************************************************************/ void AppendIgnore(char *path) { struct TwoDimList *tp = NULL; char *sp; Debug1("Installing item (%s) in the ignore list\n",path); if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing %s, no match\n",path); return; } Build2DListFromVarstring(&tp,path,LISTSEPARATOR,false); Set2DList(tp); for (sp = Get2DListEnt(tp); sp != NULL; sp = Get2DListEnt(tp)) { InstallItem(&VIGNORE,sp,CLASSBUFF,0,0); } Delete2DList(tp); } /*******************************************************************/ void InstallPending(enum actions action) { if (ACTIONPENDING) { Debug1("\n [BEGIN InstallPending %s\n",ACTIONTEXT[action]); } else { Debug1(" (No actions pending in %s)\n",ACTIONTEXT[action]); return; } switch (action) { case filters: InstallFilterTest(FILTERNAME,CURRENTITEM,FILTERDATA); CURRENTITEM[0] = '\0'; FILTERDATA[0] = '\0'; break; case strategies: AddClassToStrategy(STRATEGYNAME,CURRENTITEM,STRATEGYDATA); break; case resolve: AppendNameServer(CURRENTOBJECT); break; case files: InstallFileListItem(CURRENTOBJECT,PLUSMASK,MINUSMASK,FILEACTION,VUIDNAME, VGIDNAME,VRECURSE,(char)PTRAVLINKS,CHECKSUM); break; case processes: InstallProcessItem(EXPR,RESTART,PROMATCHES,PROCOMP, PROSIGNAL,PROACTION,CLASSBUFF,USESHELL,VUIDNAME,VGIDNAME); break; case image: InstallImageItem(FINDERTYPE,CURRENTOBJECT,PLUSMASK,MINUSMASK,DESTINATION, IMAGEACTION,VUIDNAME,VGIDNAME,IMGSIZE,IMGCOMP, VRECURSE,COPYTYPE,LINKTYPE,CFSERVER); break; case ignore: AppendIgnore(CURRENTOBJECT); break; case tidy: if (VAGE >= 99999) { yyerror("Must specify an age for tidy actions"); return; } InstallTidyItem(CURRENTOBJECT,CURRENTITEM,VRECURSE,VAGE,(char)PTRAVLINKS, TIDYSIZE,AGETYPE,LINKDIRS,TIDYDIRS,CLASSBUFF); break; case makepath: InstallMakePath(CURRENTOBJECT,PLUSMASK,MINUSMASK,VUIDNAME,VGIDNAME); break; case methods: InstallMethod(CURRENTOBJECT,ACTIONBUFF); break; case rename_disable: case disable: AppendDisable(CURRENTOBJECT,CURRENTITEM,ROTATE,DISCOMP,DISABLESIZE); break; case shellcommands: AppendScript(CURRENTOBJECT,VTIMEOUT,USESHELL,VUIDNAME,VGIDNAME); InitializeAction(); break; case scli: AppendSCLI(CURRENTOBJECT,VTIMEOUT,USESHELL,VUIDNAME,VGIDNAME); InitializeAction(); break; case alerts: if (strcmp(CLASSBUFF,"any") == 0) { yyerror("Alerts cannot be in class any - probably a mistake"); } else { Debug("Install %s if %s\n",CURRENTOBJECT,CLASSBUFF); InstallItem(&VALERTS,CURRENTOBJECT,CLASSBUFF,0,0); } InitializeAction(); break; case interfaces: AppendInterface(VIFNAME,LINKTO,DESTINATION,CURRENTOBJECT); break; case disks: case required: InstallRequiredPath(CURRENTOBJECT,IMGSIZE); break; /* HvB: Bas van der Vlies */ case mountables: InstallMountableItem(CURRENTOBJECT,MOUNTOPTS,CF_MOUNT_RO); break; case misc_mounts: if ((strlen(MOUNTFROM) != 0) && (strlen(MOUNTONTO) != 0)) { struct Item *op; /* Reconcat list */ for (op = MOUNTOPTLIST; op != NULL; op = op->next) { if (BufferOverflow(MOUNTOPTS,op->name)) { printf(" culprit: InstallPending, skipping miscmount %s %s\n", MOUNTFROM, MOUNTONTO); return; } strcat(MOUNTOPTS,op->name); strcat(MOUNTOPTS,","); } MOUNTOPTS[strlen(MOUNTOPTS)-1] = '\0'; switch (MOUNTMODE) { case 'o': AppendMiscMount(MOUNTFROM,MOUNTONTO,"ro",MOUNTOPTS); break; case 'w': AppendMiscMount(MOUNTFROM,MOUNTONTO,"rw",MOUNTOPTS); break; default: printf("Install pending, miscmount, shouldn't happen\n"); MOUNTOPTS[0] = '\0'; /* no mount mode set! */ } } InitializeAction(); break; case unmounta: AppendUmount(CURRENTOBJECT,DELETEDIR,DELETEFSTAB,FORCE); break; case links: if (LINKTO[0] == '\0') { return; } if (ACTION_IS_LINKCHILDREN) { InstallLinkChildrenItem(LINKFROM,LINKTO); ACTION_IS_LINKCHILDREN = false; } else if (ACTION_IS_LINK) { InstallLinkItem(LINKFROM,LINKTO); ACTION_IS_LINK = false; } else { return; /* Don't have whole command */ } break; case packages: InstallPackagesItem(CURRENTOBJECT,PKGVER,CMPSENSE,PKGMGR,PKGACTION); break; } Debug1(" END InstallPending]\n\n"); } /*******************************************************************/ /* Level 3 */ /*******************************************************************/ void HandleCharSwitch(char *name,char *value,char *pflag) { Debug1("HandleCharSwitch(%s=%s)\n",name,value); if ((strcmp(value,"true") == 0) || (strcmp(value,"on") == 0)) { *pflag = 'y'; return; } if ((strcmp(value,"false") == 0) || (strcmp(value,"off") == 0)) { *pflag = 'n'; return; } if ((strcmp(value,"timestamp") == 0)) { *pflag = 's'; return; } if (ACTION == image) { printf("Switch %s=(true/false/timestamp)|(on/off)",name); yyerror("Illegal switch value"); } else { printf("Switch %s=(true/false)|(on/off)",name); yyerror("Illegal switch value"); } } /*******************************************************************/ void HandleIntSwitch(char *name,char *value,int *pflag,int min,int max) { int numvalue = -17267592; /* silly number, never happens */ Debug1("HandleIntSwitch(%s=%s,%d,%d)\n",name,value,min,max); sscanf(value,"%d",&numvalue); if (numvalue == -17267592) { snprintf(OUTPUT,CF_BUFSIZE,"Integer expected as argument to %s",name); yyerror(OUTPUT); return; } if ((numvalue <= max) && (numvalue >= min)) { *pflag = numvalue; return; } else { snprintf(OUTPUT,CF_BUFSIZE,"Integer %s out of range (%d <= %s <= %d)",name,min,name,max); yyerror(OUTPUT); } } /*******************************************************************/ int EditFileExists(char *file) { struct Edit *ptr; char ebuff[CF_EXPANDSIZE]; ExpandVarstring(file,ebuff,""); for (ptr = VEDITLIST; ptr != NULL; ptr=ptr->next) { if (strcmp(ptr->fname,ebuff) == 0) { return true; } } return false; } /********************************************************************/ int GetExecOutput(char *command,char *buffer,int useshell) /* Buffer initially contains whole exec string */ { int offset = 0; char line[CF_BUFSIZE], *sp; FILE *pp; Debug1("GetExecOutput(%s,%s)\n",command,buffer); if (useshell) { pp = cfpopen_sh(command,"r"); } else { pp = cfpopen(command,"r"); } if (pp == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open pipe to command %s\n",command); CfLog(cfinform,OUTPUT,"pipe"); return false; } memset(buffer,0,CF_BUFSIZE); while (!feof(pp)) { if (ferror(pp)) /* abortable */ { fflush(pp); break; } ReadLine(line,CF_BUFSIZE,pp); if (ferror(pp)) /* abortable */ { fflush(pp); break; } for (sp = line; *sp != '\0'; sp++) { if (*sp == '\n') { *sp = ' '; } } if (strlen(line)+offset > CF_BUFSIZE-10) { snprintf(OUTPUT,CF_BUFSIZE*2,"Buffer exceeded %d bytes in exec %s\n",CF_MAXVARSIZE,command); CfLog(cferror,OUTPUT,""); break; } snprintf(buffer+offset,CF_BUFSIZE,"%s ",line); offset += strlen(line)+1; } if (offset > 0) { Chop(buffer); } Debug("GetExecOutput got: [%s]\n",buffer); cfpclose(pp); return true; } /********************************************************************/ void InstallEditFile(char *file,char *edit,char *data) { struct Edit *ptr; char ebuff[CF_EXPANDSIZE]; if (data == NULL) { Debug1("InstallEditFile(%s,%s,-) with classes %s\n",file,edit,CLASSBUFF); } else { Debug1("InstallEditFile(%s,%s,%s) with classes %s\n",file,edit,data,CLASSBUFF); } if (!IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing Edit no match\n"); return; } ExpandVarstring(file,ebuff,""); if ((ptr = (struct Edit *)malloc(sizeof(struct Edit))) == NULL) { FatalError("Memory Allocation failed for InstallEditFile() #1"); } if ((ptr->fname = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallEditFile() #2"); } if (VEDITLISTTOP == NULL) /* First element in the list */ { VEDITLIST = ptr; } else { VEDITLISTTOP->next = ptr; } if (strncmp(ebuff,"home",4) == 0 && strlen(ebuff) < 6) { yyerror("Can't edit home directories: missing a filename after home"); } if (strlen(LOCALREPOS) > 0) { ExpandVarstring(LOCALREPOS,ebuff,""); ptr->repository = strdup(ebuff); } else { ptr->repository = NULL; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->logaudit = AUDITP; ptr->lineno = LINENUMBER; /* This might not be true if several stanzas */ ptr->done = 'n'; ptr->split = CF_UNUSED_CHAR; ptr->scope = strdup(CONTEXTID); ptr->recurse = 0; ptr->useshell = 'y'; ptr->binary = 'n'; ptr->next = NULL; ptr->actions = NULL; ptr->filters = NULL; ptr->ignores = NULL; ptr->umask = UMASK; ptr->exclusions = NULL; ptr->inclusions = NULL; ptr->warn = 'n'; VEDITLISTTOP = ptr; AddEditAction(file,edit,data); } /********************************************************************/ void AddEditAction(char *file,char *edit,char *data) { struct Edit *ptr; struct Edlist *top,*new, *ep; struct TwoDimList *tp = NULL; char varbuff[CF_EXPANDSIZE]; mode_t saved_umask; char *sp; if (data == NULL) { Debug2("AddEditAction(%s,%s,-)\n",file,edit); } else { Debug2("AddEditAction(%s,%s,%s)\n",file,edit,data); } if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing Edit no match\n"); return; } for (ptr = VEDITLIST; ptr != NULL; ptr=ptr->next) { ExpandVarstring(file,varbuff,""); if (strcmp(ptr->fname,varbuff) == 0) { /* 2D list wrapper start - variable is data */ if (EditActionsToCode(edit) == EditSplit) { if (data != NULL) { ptr->split = *(data); Verbose("Found new editfiles list separator \"%c\"",ptr->split); return; } else { yyerror("Bad list separator for editfiles entry"); return; } } Build2DListFromVarstring(&tp,data,ptr->split,false); Set2DList(tp); for (sp = Get2DListEnt(tp); sp != NULL; sp = Get2DListEnt(tp)) { if ((new = (struct Edlist *)malloc(sizeof(struct Edlist))) == NULL) { FatalError("Memory Allocation failed for AddEditAction() #1"); } if (ptr->actions == NULL) { ptr->actions = new; } else { for (top = ptr->actions; top->next != NULL; top=top->next) { } top->next = new; } if ((new->code = EditActionsToCode(edit)) == NoEdit) { snprintf(OUTPUT,CF_BUFSIZE,"Unknown edit action \"%s\"",edit); yyerror(OUTPUT); } if (data == NULL) { new->data = NULL; } else { if ((new->data = strdup(sp)) == NULL) { FatalError("Memory Allocation failed for AddEditAction() #1"); } } new->next = NULL; if ((new->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallEditFile() #3"); } switch(new->code) { case EditUmask: saved_umask = UMASK; HandleUmask(sp); ptr->umask = UMASK; UMASK = saved_umask; break; case WarnIfFileMissing: ptr->warn = 'y'; break; case EditIgnore: PrependItem(&(ptr->ignores),sp,CF_ANYCLASS); break; case EditExclude: PrependItem(&(ptr->exclusions),sp,CF_ANYCLASS); break; case EditInclude: PrependItem(&(ptr->inclusions),sp,CF_ANYCLASS); break; case EditRecurse: if (strcmp(data,"inf") == 0) { ptr->recurse = CF_INF_RECURSE; } else { ptr->recurse = atoi(data); if (ptr->recurse < 0) { yyerror("Illegal recursion value"); } } break; case Append: if (EDITGROUPLEVEL == 0) { yyerror("Append used outside of Group - non-convergent"); } break; case EditMode: if (strcmp(data,"Binary") == 0) { ptr->binary = 'y'; } break; case BeginGroupIfNoMatch: case BeginGroupIfMatch: case BeginGroupIfNoLineMatching: case BeginGroupIfLineMatching: case BeginGroupIfNoLineContaining: case BeginGroupIfLineContaining: case BeginGroupIfNoSuchLine: case BeginGroupIfDefined: case BeginGroupIfNotDefined: case BeginGroupIfFileIsNewer: case BeginGroupIfFileExists: if (IsListVar(data,ptr->split)) { yyerror("List variables are not currently supported in BeginGroup*"); } EDITGROUPLEVEL++; break; case EndGroup: EDITGROUPLEVEL--; if (EDITGROUPLEVEL < 0) { yyerror("EndGroup without Begin"); } break; case ReplaceAll: if (SEARCHREPLACELEVEL > 0) { yyerror("ReplaceAll without With before or at line"); } if (IsListVar(data,ptr->split)) { yyerror("List variables are not currently supported in ReplaceAll/With"); } SEARCHREPLACELEVEL++; break; case ReplaceFirst: if (SEARCHREPLACELEVEL > 0) { yyerror("ReplaceFirst without With before or at line"); } SEARCHREPLACELEVEL++; break; case With: if (IsListVar(data,ptr->split)) { yyerror("List variables are not currently supported in ReplaceAll/With"); } SEARCHREPLACELEVEL--; break; case ForEachLineIn: if (FOREACHLEVEL > 0) { yyerror("Nested ForEach loops not allowed"); } FOREACHLEVEL++; break; case EndLoop: FOREACHLEVEL--; if (FOREACHLEVEL < 0) { yyerror("EndLoop without ForEachLineIn"); } break; case DefineInGroup: if (EDITGROUPLEVEL <= 0) { yyerror("DefineInGroup outside a group"); } AddInstallable(new->data); break; case SetLine: if (FOREACHLEVEL > 0) { yyerror("SetLine inside ForEachLineIn loop"); } break; case FixEndOfLine: if (strlen(sp) > CF_EXTRASPC - 1) { yyerror("End of line type is too long!"); printf(" (max %d characters allowed)\n",CF_EXTRASPC); } break; case ReplaceLinesMatchingField: if (atoi(sp) == 0) { yyerror("Argument must be an integer, greater than zero"); } break; case EditFilter: PrependItem(&(ptr->filters),data,NULL); break; case ElseDefineClasses: case DefineClasses: if (EDITGROUPLEVEL > 0 || FOREACHLEVEL > 0) { yyerror("Class definitions inside conditionals or loops are not allowed. Did you mean DefineInGroup?"); } AddInstallable(new->data); break; case EditRepos: ptr->repository = strdup(sp); break; } /* 2d wrapper end */ } Delete2DList(tp); return; } } printf("cfengine: software error - no file matched installing %s edit\n",file); } /********************************************************************/ enum editnames EditActionsToCode(char *edit) { int i; Debug2("EditActionsToCode(%s)\n",edit); for (i = 0; VEDITNAMES[i] != '\0'; i++) { if (strcmp(VEDITNAMES[i],edit) == 0) { return (enum editnames) i; } } return (NoEdit); } /********************************************************************/ void PrependAuditFile(char *file) { struct stat statbuf;; if ((AUDITPTR = (struct Audit *)malloc(sizeof(struct Audit))) == NULL) { CfLog(cferror,"","malloc audit"); FatalError(""); } if (stat(file,&statbuf) == -1) { /* shouldn't happen */ return; } ChecksumFile(file,AUDITPTR->digest,'m'); AUDITPTR->next = VAUDIT; AUDITPTR->filename = strdup(file); AUDITPTR->date = strdup(ctime(&statbuf.st_mtime)); Chop(AUDITPTR->date); AUDITPTR->version = NULL; VAUDIT = AUDITPTR; } /********************************************************************/ void VersionAuditFile() { char *sp; if (sp = GetMacroValue(CONTEXTID,"cfinputs_version")) { AUDITPTR->version = strdup(sp); } else { Verbose("Cfengine input file had no explicit version string\n"); } } /********************************************************************/ void AppendInterface(char *ifname,char *address,char *netmask,char *broadcast) { struct Interface *ifp; Debug1("Installing item (%s:%s:%s) in the interfaces list\n",ifname,netmask,broadcast); if (!IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing %s, no match\n",ifname); return; } if (strlen(netmask) < 7) { yyerror("illegal or missing netmask"); InitializeAction(); return; } if (strlen(broadcast) < 3) { yyerror("illegal or missing broadcast address"); InitializeAction(); return; } if ((ifp = (struct Interface *)malloc(sizeof(struct Interface))) == NULL) { FatalError("Memory Allocation failed for AppendInterface() #1"); } if ((ifp->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for Appendinterface() #2"); } if ((ifp->ifdev = strdup(ifname)) == NULL) { FatalError("Memory Allocation failed for AppendInterface() #3"); } if ((ifp->netmask = strdup(netmask)) == NULL) { FatalError("Memory Allocation failed for AppendInterface() #3"); } if ((ifp->broadcast = strdup(broadcast)) == NULL) { FatalError("Memory Allocation failed for AppendInterface() #3"); } if ((ifp->ipaddress = strdup(address)) == NULL) { FatalError("Memory Allocation failed for AppendInterface() #3"); } if (VIFLISTTOP == NULL) /* First element in the list */ { VIFLIST = ifp; } else { VIFLISTTOP->next = ifp; } ifp->audit = AUDITPTR; ifp->lineno = LINENUMBER; ifp->next = NULL; ifp->done = 'n'; ifp->scope = strdup(CONTEXTID); VIFLISTTOP = ifp; InitializeAction(); } /*******************************************************************/ void AppendScript(char *item,int timeout,char useshell,char *uidname,char *gidname) { struct TwoDimList *tp = NULL; struct ShellComm *ptr; struct passwd *pw; struct group *gw; char *sp, ebuff[CF_EXPANDSIZE]; int uid = CF_NOUSER; int gid = CF_NOUSER; Debug1("Installing shellcommand (%s) in the script list\n",item); if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing (%s), no class match (%s)\n",item,CLASSBUFF); InitializeAction(); return; } Build2DListFromVarstring(&tp,item,LISTSEPARATOR,false); /* Must be at least one space between each var */ Set2DList(tp); for (sp = Get2DListEnt(tp); sp != NULL; sp = Get2DListEnt(tp)) { if ((ptr = (struct ShellComm *)malloc(sizeof(struct ShellComm))) == NULL) { FatalError("Memory Allocation failed for AppendScript() #1"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for Appendscript() #2"); } if (*sp != '/' && NOABSPATH != 'y') { yyerror("scripts or commands must have absolute path names"); printf ("cfengine: concerns: %s\n",sp); free(ptr->classes); return; } if ((ptr->name = strdup(sp)) == NULL) { FatalError("Memory Allocation failed for Appendscript() #3"); } ExpandVarstring(CHROOT,ebuff,""); if ((ptr->chroot = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for Appendscipt() #4b"); } ExpandVarstring(CHDIR,ebuff,""); if ((ptr->chdir = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for Appendscript() #4c"); } if (VSCRIPTTOP == NULL) /* First element in the list */ { VSCRIPT = ptr; } else { VSCRIPTTOP->next = ptr; } if (*uidname == '*') { ptr->uid = CF_SAME_OWNER; } else if (isdigit((int)*uidname)) { sscanf(uidname,"%d",&uid); if (uid == CF_NOUSER) { yyerror("Unknown or silly user id"); return; } else { ptr->uid = uid; } } else if ((pw = getpwnam(uidname)) == NULL) { yyerror("Unknown or silly user id"); return; } else { ptr->uid = pw->pw_uid; } if (*gidname == '*') { ptr->gid = CF_SAME_GROUP; } else if (isdigit((int)*gidname)) { sscanf(gidname,"%d",&gid); if (gid == CF_NOUSER) { yyerror("Unknown or silly group id"); continue; } else { ptr->gid = gid; } } else if ((gw = getgrnam(gidname)) == NULL) { yyerror("Unknown or silly group id"); continue; } else { ptr->gid = gw->gr_gid; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->log = LOGP; ptr->inform = INFORMP; ptr->logaudit = AUDITP; ptr->timeout = timeout; ptr->useshell = useshell; ptr->umask = UMASK; ptr->fork = FORK; ptr->preview = PREVIEW; ptr->noabspath = NOABSPATH; ptr->next = NULL; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); ExpandVarstring(ALLCLASSBUFFER,ebuff,""); if ((ptr->defines = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for AppendShellcommand() #3"); } ExpandVarstring(ELSECLASSBUFFER,ebuff,""); if ((ptr->elsedef = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for AppendShellcommand() #4"); } AddInstallable(ptr->defines); AddInstallable(ptr->elsedef); VSCRIPTTOP = ptr; } Delete2DList(tp); } /*******************************************************************/ void AppendSCLI(char *item,int timeout,char useshell,char *uidname,char *gidname) { struct TwoDimList *tp = NULL; struct ShellComm *ptr; struct passwd *pw; struct group *gw; char *sp, ebuff[CF_EXPANDSIZE]; int uid = CF_NOUSER; int gid = CF_NOUSER; Debug1("Installing SCLI (SNMP) command (%s) in the list\n",item); if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing (%s), no class match (%s)\n",item,CLASSBUFF); InitializeAction(); return; } Build2DListFromVarstring(&tp,item,LISTSEPARATOR,false); Set2DList(tp); for (sp = Get2DListEnt(tp); sp != NULL; sp = Get2DListEnt(tp)) { if ((ptr = (struct ShellComm *)malloc(sizeof(struct ShellComm))) == NULL) { FatalError("Memory Allocation failed for AppendScli() #1"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for Appendscli() #2"); } if ((ptr->name = strdup(sp)) == NULL) { FatalError("Memory Allocation failed for Appendscli() #3"); } ExpandVarstring(CHROOT,ebuff,""); if ((ptr->chroot = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for Appendscli() #4b"); } ExpandVarstring(CHDIR,ebuff,""); if ((ptr->chdir = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for Appendscli() #4c"); } if (VSCLITOP == NULL) /* First element in the list */ { VSCLI = ptr; } else { VSCLITOP->next = ptr; } if (*uidname == '*') { ptr->uid = CF_SAME_OWNER; } else if (isdigit((int)*uidname)) { sscanf(uidname,"%d",&uid); if (uid == CF_NOUSER) { yyerror("Unknown or silly user id"); return; } else { ptr->uid = uid; } } else if ((pw = getpwnam(uidname)) == NULL) { yyerror("Unknown or silly user id"); return; } else { ptr->uid = pw->pw_uid; } if (*gidname == '*') { ptr->gid = CF_SAME_GROUP; } else if (isdigit((int)*gidname)) { sscanf(gidname,"%d",&gid); if (gid == CF_NOUSER) { yyerror("Unknown or silly group id"); continue; } else { ptr->gid = gid; } } else if ((gw = getgrnam(gidname)) == NULL) { yyerror("Unknown or silly group id"); continue; } else { ptr->gid = gw->gr_gid; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->log = LOGP; ptr->inform = INFORMP; ptr->logaudit = AUDITP; ptr->timeout = timeout; ptr->useshell = useshell; ptr->umask = UMASK; ptr->fork = FORK; ptr->preview = PREVIEW; ptr->noabspath = NOABSPATH; ptr->next = NULL; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); ExpandVarstring(ALLCLASSBUFFER,ebuff,""); if ((ptr->defines = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for AppendSCLI() #3"); } ExpandVarstring(ELSECLASSBUFFER,ebuff,""); if ((ptr->elsedef = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for AppendSCLI() #3"); } AddInstallable(ptr->defines); AddInstallable(ptr->elsedef); VSCLITOP = ptr; } Delete2DList(tp); } /********************************************************************/ void AppendDisable(char *path,char *type,short rotate,char comp,int size) { char *sp; struct Disable *ptr; struct TwoDimList *tp = NULL; char ebuff[CF_EXPANDSIZE]; Debug1("Installing item (%s) in the disable list\n",path); if (!IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing %s, no match\n",path); return; } Build2DListFromVarstring(&tp,path,LISTSEPARATOR,false); Set2DList(tp); for (sp = Get2DListEnt(tp); sp != NULL; sp = Get2DListEnt(tp)) { if (strlen(type) > 0 && strcmp(type,"plain") != 0 && strcmp(type,"file") !=0 && strcmp(type,"link") !=0 && strcmp(type,"links") !=0 ) { yyerror("Invalid file type in Disable"); } if ((ptr = (struct Disable *)malloc(sizeof(struct Disable))) == NULL) { FatalError("Memory Allocation failed for AppendDisable() #1"); } if ((ptr->name = strdup(sp)) == NULL) { FatalError("Memory Allocation failed for AppendDisable() #2"); } ExpandVarstring(ALLCLASSBUFFER,ebuff,""); if ((ptr->defines = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for AppendDisable() #3"); } ExpandVarstring(ELSECLASSBUFFER,ebuff,""); if ((ptr->elsedef = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for AppendDisable() #3"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for AppendDisable() #4"); } if (strlen(type) == 0) { sprintf(ebuff,"all"); } else { sprintf(ebuff,"%s",type); } if ((ptr->type = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for AppendDisable() #4"); } ExpandVarstring(DESTINATION,ebuff,""); if ((ptr->destination = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for AppendDisable() #3"); } if (VDISABLETOP == NULL) /* First element in the list */ { VDISABLELIST = ptr; } else { VDISABLETOP->next = ptr; } if (strlen(LOCALREPOS) > 0) { ExpandVarstring(LOCALREPOS,ebuff,""); ptr->repository = strdup(ebuff); } else { ptr->repository = NULL; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->rotate = rotate; ptr->comp = comp; ptr->size = size; ptr->next = NULL; ptr->log = LOGP; ptr->inform = INFORMP; ptr->logaudit = AUDITP; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); ptr->action = PROACTION; VDISABLETOP = ptr; InitializeAction(); AddInstallable(ptr->defines); AddInstallable(ptr->elsedef); } Delete2DList(tp); } /*******************************************************************/ void InstallMethod(char *function,char *file) { char *sp,*vp,work[CF_EXPANDSIZE],name[CF_BUFSIZE]; struct Method *ptr; struct Item *bare_send_args = NULL, *sip; uid_t uid = CF_NOUSER; gid_t gid = CF_NOUSER; struct passwd *pw; struct group *gw; struct TwoDimList *tp = NULL; Debug1("Install item (%s=%s) in the methods list iff %s?\n",function,file,CLASSBUFF); if (strlen(file) == 0) { snprintf(OUTPUT,CF_BUFSIZE,"Missing action file from declaration of method %s",function); yyerror(OUTPUT); return; } memset(name,0,CF_BUFSIZE); if (!strstr(function,"(")) { yyerror("Missing parenthesis or extra space"); InitializeAction(); return; } /* First look at bare args to cache an arg fingerprint */ strcpy(work,function); if (work[strlen(work)-1] != ')') { yyerror("Illegal use of space or nested parentheses"); } work [strlen(work)-1] = '\0'; /*chop last ) */ sscanf(function,"%[^(]",name); if (strlen(name) == 0) { yyerror("Empty method"); return; } for (sp = work; sp != NULL; sp++) /* Pick out the args*/ { if (*sp == '(') { break; } } sp++; if (strlen(sp) == 0) { yyerror("Missing argument (void?) to method"); } /* Now expand variables */ /* ExpandVarstring(function,work,""); */ strcpy(work,function); Build2DListFromVarstring(&tp,work,LISTSEPARATOR,true); /* step in time for lists here */ Set2DList(tp); for (vp = Get2DListEnt(tp); vp != NULL; vp = Get2DListEnt(tp)) { Debug1("Installing item (%s=%s) in the methods list iff %s\n",function,file,CLASSBUFF); if ((ptr = (struct Method *)malloc(sizeof(struct Method))) == NULL) { FatalError("Memory Allocation failed for InstallMethod() #1"); } if (VMETHODSTOP == NULL) { VMETHODS = ptr; } else { VMETHODSTOP->next = ptr; } if (vp[strlen(vp)-1] != ')') { yyerror("Illegal use of space or nested parentheses"); } vp [strlen(vp)-1] = '\0'; /*chop last ) */ sscanf(work,"%[^(]",name); if (strlen(name) == 0) { yyerror("Empty method"); return; } for (sp = vp; sp != NULL; sp++) /* Pick out the args*/ { if (*sp == '(') { break; } } sp++; if (strlen(sp) == 0) { yyerror("Missing argument (void?) to method"); } Debug("Found args [%s]\n\n",sp); ptr->send_args = ListFromArgs(sp); ptr->send_classes = SplitStringAsItemList(METHODREPLYTO,','); METHODREPLYTO[0] = '\0'; if ((ptr->name = strdup(name)) == NULL) { FatalError("Memory Allocation failed for InstallMethod() #2"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallMethod() #3"); } if (strlen(file) == 0) { yyerror("Missing filename in method"); return; } if (strcmp(file,"dispatch") == 0) { ptr->invitation = 'y'; } else { ptr->invitation = 'n'; } if (file[0] == '/' || file[0] == '.') { snprintf(OUTPUT,CF_BUFSIZE,"Method name (%s) was absolute. Must be in trusted Modules directory (no path prefix)",file); yyerror(OUTPUT); return; } ptr->file = strdup(file); if (strlen(CFSERVER) > 0) { ptr->servers = SplitStringAsItemList(CFSERVER,','); } else { ptr->servers = SplitStringAsItemList("localhost",','); } bare_send_args = ListFromArgs(sp); /* Append server to make this unique */ for (sip = ptr->servers; sip != NULL; sip = sip->next) { PrependItem(&bare_send_args,sip->name,NULL); } ChecksumList(bare_send_args,ptr->digest,'m'); DeleteItemList(bare_send_args); ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->bundle = NULL; ptr->return_vars = SplitStringAsItemList(METHODFILENAME,','); ptr->return_classes = SplitStringAsItemList(PARSEMETHODRETURNCLASSES,','); ptr->scope = strdup(CONTEXTID); ptr->useshell = USESHELL; ptr->log = LOGP; ptr->inform = INFORMP; ptr->logaudit = AUDITP; if (*VUIDNAME == '*') { ptr->uid = CF_SAME_OWNER; } else if (isdigit((int)*VUIDNAME)) { sscanf(VUIDNAME,"%d",&uid); if (uid == CF_NOUSER) { yyerror("Unknown or silly user id"); return; } else { ptr->uid = uid; } } else if ((pw = getpwnam(VUIDNAME)) == NULL) { yyerror("Unknown or silly user id"); return; } else { ptr->uid = pw->pw_uid; } if (*VGIDNAME == '*') { ptr->gid = CF_SAME_GROUP; } else if (isdigit((int)*VGIDNAME)) { sscanf(VGIDNAME,"%d",&gid); if (gid == CF_NOUSER) { yyerror("Unknown or silly group id"); return; } else { ptr->gid = gid; } } else if ((gw = getgrnam(VGIDNAME)) == NULL) { yyerror("Unknown or silly group id"); return; } else { ptr->gid = gw->gr_gid; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ExpandVarstring(CHROOT,work,""); if ((ptr->chroot = strdup(work)) == NULL) { FatalError("Memory Allocation failed for InstallProcItem() #4b"); } ExpandVarstring(CHDIR,work,""); if ((ptr->chdir = strdup(work)) == NULL) { FatalError("Memory Allocation failed for InstallProcItem() #4c"); } ExpandVarstring(METHODFORCE,work,""); if ((ptr->forcereplyto = strdup(work)) == NULL) { FatalError("Memory Allocation failed for InstallProcItem() #4c"); } ptr->next = NULL; VMETHODSTOP = ptr; } InitializeAction(); } /*******************************************************************/ void InstallTidyItem(char *path,char *wild,int rec,short age,char travlinks,int tidysize,char type,char ldirs,char tidydirs,char *classes) { struct TwoDimList *tp = NULL; char *sp; if (strcmp(path,"/") != 0) { DeleteSlash(path); } Build2DListFromVarstring(&tp,path,LISTSEPARATOR,false); Set2DList(tp); for (sp = Get2DListEnt(tp); sp != NULL; sp = Get2DListEnt(tp)) { if (TidyPathExists(sp)) { AddTidyItem(sp,wild,rec,age,travlinks,tidysize,type,ldirs,tidydirs,classes); } else { InstallTidyPath(sp,wild,rec,age,travlinks,tidysize,type,ldirs,tidydirs,classes); } } Delete2DList(tp); InitializeAction(); } /*******************************************************************/ void InstallMakePath(char *path,mode_t plus,mode_t minus,char *uidnames,char *gidnames) { struct File *ptr; char buffer[CF_EXPANDSIZE],ebuff[CF_MAXVARSIZE]; struct Item *list = NULL, *ip; struct TwoDimList *tp = NULL; char *sp; int lastnode = false; Debug1("InstallMakePath (%s) (+%o)(-%o)(%s)(%s)\n",path,plus,minus,uidnames,gidnames); if (!IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing directory item, no match\n"); return; } Build2DListFromVarstring(&tp,path,LISTSEPARATOR,false); Set2DList(tp); for (sp = Get2DListEnt(tp); sp != NULL; sp = Get2DListEnt(tp)) { if (strcmp(uidnames,"LastNode") == 0) { strncpy(ebuff,ReadLastNode(sp),CF_MAXVARSIZE-1); Verbose("File owner will be set to directory last node (%s)\n",ebuff); } else { strncpy(ebuff,uidnames,CF_MAXVARSIZE-1); } if ((ptr = (struct File *)malloc(sizeof(struct File))) == NULL) { FatalError("Memory Allocation failed for InstallMakepath() #1"); } if ((ptr->path = strdup(sp)) == NULL) { FatalError("Memory Allocation failed for InstallMakepath() #2"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallMakepath() #3"); } ExpandVarstring(ALLCLASSBUFFER,buffer,""); if ((ptr->defines = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed for InstallMakepath() #3a"); } ExpandVarstring(ELSECLASSBUFFER,buffer,""); if ((ptr->elsedef = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed for InstallMakepath() #3a"); } AddInstallable(ptr->defines); AddInstallable(ptr->elsedef); if (VMAKEPATHTOP == NULL) /* First element in the list */ { VMAKEPATH = ptr; } else { VMAKEPATHTOP->next = ptr; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->plus = plus; ptr->minus = minus; ptr->recurse = 0; ptr->action = fixdirs; ptr->uid = MakeUidList(ebuff); ptr->gid = MakeGidList(gidnames); ptr->inclusions = NULL; ptr->exclusions = NULL; ptr->acl_aliases= VACLBUILD; ptr->log = LOGP; ptr->filters = NULL; ptr->inform = INFORMP; ptr->logaudit = AUDITP; ptr->plus_flags = PLUSFLAG; ptr->minus_flags = MINUSFLAG; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); ptr->next = NULL; VMAKEPATHTOP = ptr; } InitializeAction(); } /*******************************************************************/ void HandleTravLinks(char *value) { if (ACTION == tidy && strncmp(CURRENTOBJECT,"home",4) == 0) { yyerror("Can't use links= option with special variable home in tidy"); yyerror("Use command line options instead.\n"); } if (PTRAVLINKS != '?') { Warning("redefinition of links= option"); } if ((strcmp(value,"stop") == 0) || (strcmp(value,"false") == 0)) { PTRAVLINKS = (short) 'F'; return; } if ((strcmp(value,"traverse") == 0) || (strcmp(value,"follow") == 0) || (strcmp(value,"true") == 0)) { PTRAVLINKS = (short) 'T'; return; } if ((strcmp(value,"tidy"))==0) { PTRAVLINKS = (short) 'K'; return; } yyerror("Illegal links= specifier"); } /*******************************************************************/ void HandleTidySize(char *value) { int num = -1; char *sp, units = 'k'; for (sp = value; *sp != '\0'; sp++) { *sp = ToLower(*sp); } if (strcmp(value,"empty") == 0) { TIDYSIZE = CF_EMPTYFILE; } else { sscanf(value,"%d%c",&num,&units); if (num <= 0) { if (*value == '>') { sscanf(value+1,"%d%c",&num,&units); if (num <= 0) { yyerror("size value must be a decimal number with units m/b/k"); } } else { yyerror("size value must be a decimal number with units m/b/k"); } } switch (units) { case 'b': TIDYSIZE = num; break; case 'm': TIDYSIZE = num * 1024 * 1024; break; default: TIDYSIZE = num * 1024; } } } /*******************************************************************/ void HandleUmask(char *value) { int num = -1; Debug("HandleUmask(%s)",value); sscanf(value,"%o",&num); if (num < 0) { yyerror("umask value must be an octal number >= zero"); } UMASK = (mode_t) num; } /*******************************************************************/ void HandleDisableSize(char *value) { int i = -1; char *sp, units = 'b'; for (sp = value; *sp != '\0'; sp++) { *sp = ToLower(*sp); } switch (*value) { case '>': DISCOMP = '>'; value++; break; case '<': DISCOMP = '<'; value++; break; default : DISCOMP = '='; } sscanf(value,"%d%c",&i,&units); if (i < 1) { yyerror("disable size attribute with silly value (must be > 0)"); } switch (units) { case 'k': DISABLESIZE = i * 1024; break; case 'm': DISABLESIZE = i * 1024 * 1024; break; default: DISABLESIZE = i; } } /*******************************************************************/ void HandleCopySize(char *value) { int i = -1; char *sp, units = 'b'; for (sp = value; *sp != '\0'; sp++) { *sp = ToLower(*sp); } switch (*value) { case '>': IMGCOMP = '>'; value++; break; case '<': IMGCOMP = '<'; value++; break; default : IMGCOMP = '='; } sscanf(value,"%d%c",&i,&units); if (i < 0) { yyerror("copy size attribute with silly value (must be a non-negative number)"); } switch (units) { case 'k': IMGSIZE = i * 1024; break; case 'm': IMGSIZE = i * 1024 * 1024; break; default: IMGSIZE = i; } } /*******************************************************************/ void HandleRequiredSize(char *value) { int i = -1; char *sp, units = 'b'; for (sp = value; *sp != '\0'; sp++) { *sp = ToLower(*sp); } switch (*value) { case '>': IMGCOMP = '>'; value++; break; case '<': IMGCOMP = '<'; value++; break; default : IMGCOMP = '='; } sscanf(value,"%d%c",&i,&units); if (i < 1) { yyerror("disk/required size attribute with silly value (must be > 0)"); } switch (units) { case 'b': IMGSIZE = i / 1024; break; case 'm': IMGSIZE = i * 1024; break; case '%': IMGSIZE = -i; /* -ve number signals percentage */ break; default: IMGSIZE = i; } } /*******************************************************************/ void HandleTidyType(char *value) { if (strcmp(value,"a")== 0 || strcmp(value,"atime") == 0) { AGETYPE = 'a'; return; } if (strcmp(value,"m")== 0 || strcmp(value,"mtime") == 0) { AGETYPE = 'm'; return; } if (strcmp(value,"c")== 0 || strcmp(value,"ctime") == 0) { AGETYPE = 'c'; return; } yyerror("Illegal age search type, must be atime/ctime/mtime"); } /*******************************************************************/ void HandleTidyLinkDirs(char *value) { if (strcmp(value,"keep")== 0) { LINKDIRS = 'k'; return; } if ((strcmp(value,"tidy")== 0) || (strcmp(value,"delete") == 0)) { LINKDIRS = 'y'; return; } yyerror("Illegal linkdirs value, must be keep/delete/tidy"); } /*******************************************************************/ void HandleTidyRmdirs(char *value) { if ((strcmp(value,"true") == 0)||(strcmp(value,"all") == 0)) { TIDYDIRS = 'y'; return; } if ((strcmp(value,"false") == 0)||(strcmp(value,"none") == 0)) { TIDYDIRS = 'n'; return; } if (strcmp(value,"sub") == 0) { TIDYDIRS = 's'; return; } yyerror("Illegal rmdirs value, must be true/false/sub"); } /*******************************************************************/ void HandleTimeOut(char *value) { int num = -1; sscanf(value,"%d",&num); if (num <= 0) { yyerror("timeout value must be a decimal number > 0"); } VTIMEOUT = num; } /*******************************************************************/ void HandleUseShell(char *value) { if (strcmp(value,"true") == 0) { USESHELL = 'y'; return; } if (strcmp(value,"false") == 0) { USESHELL = 'n'; return; } if (strcmp(value,"dumb") == 0) { USESHELL = 'd'; return; } yyerror("Illegal attribute for useshell= "); } /*******************************************************************/ void HandleChecksum(char *value) { CHECKSUM = ChecksumType(ToLowerStr(value)); } /*******************************************************************/ void HandleTimeStamps(char *value) { if (strcmp(value,"preserve") == 0 || strcmp(value,"keep") == 0) { PRESERVETIMES = 'y'; return; } PRESERVETIMES = 'n'; } /*******************************************************************/ int GetFileAction(char *action) { int i; for (i = 0; FILEACTIONTEXT[i] != '\0'; i++) { if (strcmp(action,FILEACTIONTEXT[i]) == 0) { return i; } } yyerror("Unknown action type"); return (int) warnall; } /*******************************************************************/ void InstallFileListItem(char *path,mode_t plus,mode_t minus,enum fileactions action,char *uidnames,char *gidnames,int recurse,char travlinks,char chksum) { struct File *ptr; char *spl,ebuff[CF_EXPANDSIZE]; struct TwoDimList *tp = NULL; Debug1("InstallFileaction (%s) (+%o)(-%o) (%s) (%d) (%c)\n",path,plus,minus,FILEACTIONTEXT[action],action,travlinks); if (!IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing file item, no match\n"); return; } Build2DListFromVarstring(&tp,path,LISTSEPARATOR,false); Set2DList(tp); for (spl = Get2DListEnt(tp); spl != NULL; spl = Get2DListEnt(tp)) { if ((ptr = (struct File *)malloc(sizeof(struct File))) == NULL) { FatalError("Memory Allocation failed for InstallFileListItem() #1"); } if ((ptr->path = strdup(spl)) == NULL) { FatalError("Memory Allocation failed for InstallFileListItem() #2"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallFileListItem() #3"); } ExpandVarstring(ALLCLASSBUFFER,ebuff,""); if ((ptr->defines = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallFileListItem() #3"); } ExpandVarstring(ELSECLASSBUFFER,ebuff,""); if ((ptr->elsedef = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallFileListItem() #3"); } AddInstallable(ptr->defines); AddInstallable(ptr->elsedef); if (VFILETOP == NULL) /* First element in the list */ { VFILE = ptr; } else { VFILETOP->next = ptr; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->action = action; ptr->plus = plus; ptr->minus = minus; ptr->recurse = recurse; ptr->uid = MakeUidList(uidnames); ptr->gid = MakeGidList(gidnames); ptr->exclusions = VEXCLUDEPARSE; ptr->inclusions = VINCLUDEPARSE; ptr->filters = NULL; ptr->ignores = VIGNOREPARSE; ptr->travlinks = travlinks; ptr->acl_aliases = VACLBUILD; ptr->filters = VFILTERBUILD; ptr->next = NULL; ptr->log = LOGP; ptr->xdev = XDEV; ptr->rxdirs = RXDIRS; ptr->inform = INFORMP; ptr->logaudit = AUDITP; ptr->checksum = chksum; ptr->plus_flags = PLUSFLAG; ptr->minus_flags = MINUSFLAG; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); VFILETOP = ptr; Debug1("Installed file object %s\n",spl); } Delete2DList(tp); InitializeAction(); } /*******************************************************************/ void InstallProcessItem(char *expr,char *restart,short matches,char comp,short signal,char action,char *classes,char useshell,char *uidname,char *gidname) { struct Process *ptr; char ebuff[CF_EXPANDSIZE]; uid_t uid; gid_t gid; struct passwd *pw; struct group *gw; Debug1("InstallProcessItem(%s,%s,%d,%d,%c)\n",expr,restart,matches,signal,action); if ( ! IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing process item, no match\n"); return; } if ((ptr = (struct Process *)malloc(sizeof(struct Process))) == NULL) { FatalError("Memory Allocation failed for InstallProcItem() #1"); } ExpandVarstring(expr,ebuff,""); if ((ptr->expr = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallProcItem() #2"); } ExpandVarstring(restart,ebuff,""); if (strcmp(ebuff,"SetOptionString") == 0) { if ((strlen(ebuff) > 0) && ebuff[0] != '/') { snprintf(OUTPUT,CF_BUFSIZE,"Restart command (%s) does not have an absolute pathname",ebuff); yyerror(OUTPUT); } } if ((ptr->restart = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallProcItem() #3"); } ExpandVarstring(ALLCLASSBUFFER,ebuff,""); if ((ptr->defines = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallProcItem() #4"); } ExpandVarstring(ELSECLASSBUFFER,ebuff,""); if ((ptr->elsedef = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallProcItem() #4a"); } ExpandVarstring(CHROOT,ebuff,""); if ((ptr->chroot = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallProcItem() #4b"); } ExpandVarstring(CHDIR,ebuff,""); if ((ptr->chdir = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallProcItem() #4c"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallProcItem() #5"); } if (VPROCTOP == NULL) /* First element in the list */ { VPROCLIST = ptr; } else { VPROCTOP->next = ptr; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->matches = matches; ptr->comp = comp; ptr->signal = signal; ptr->action = action; ptr->umask = UMASK; ptr->useshell = useshell; ptr->next = NULL; ptr->log = LOGP; ptr->inform = INFORMP; ptr->logaudit = AUDITP; ptr->exclusions = VEXCLUDEPARSE; ptr->inclusions = VINCLUDEPARSE; ptr->filters = ptr->filters = VFILTERBUILD; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); if (*uidname == '*') { ptr->uid = -1; } else if (isdigit((int)*uidname)) { sscanf(uidname,"%d",&uid); if (uid == CF_NOUSER) { yyerror("Unknown or silly restart user id"); return; } else { ptr->uid = uid; } } else if ((pw = getpwnam(uidname)) == NULL) { yyerror("Unknown or silly restart user id"); return; } else { ptr->uid = pw->pw_uid; } if (*gidname == '*') { ptr->gid = -1; } else if (isdigit((int)*gidname)) { sscanf(gidname,"%d",&gid); if (gid == CF_NOUSER) { yyerror("Unknown or silly restart group id"); return; } else { ptr->gid = gid; } } else if ((gw = getgrnam(gidname)) == NULL) { yyerror("Unknown or silly restart group id"); return; } else { ptr->gid = gw->gr_gid; } VPROCTOP = ptr; InitializeAction(); AddInstallable(ptr->defines); AddInstallable(ptr->elsedef); } /*******************************************************************/ void InstallPackagesItem(char *name,char *ver,enum cmpsense sense,enum pkgmgrs mgr,enum pkgactions action) { struct Package *ptr; char buffer[CF_EXPANDSIZE]; if ( ! IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing packages item, no match\n"); return; } /* If the package manager is set to pkgmgr_none, then an invalid * manager was specified, so we don't need to do anything */ if ( PKGMGR == pkgmgr_none ) { InitializeAction(); Debug1("Package manager set to none. Not installing package item\n"); return; } Debug1("InstallPackagesItem(%s,%s,%s,%s,%s)\n", name,ver,CMPSENSETEXT[sense],PKGMGRTEXT[mgr],PKGACTIONTEXT[action]); if ((ptr = (struct Package *)malloc(sizeof(struct Package))) == NULL) { FatalError("Memory Allocation failed for InstallPackageItem() #1"); } if ((ptr->name = strdup(name)) == NULL) { FatalError("Memory Allocation failed for InstallPackageItem() #2"); } if ((ptr->ver = strdup(ver)) == NULL) { FatalError("Memory Allocation failed for InstallPackageItem() #3"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallPackageItem() #4"); } ExpandVarstring(ALLCLASSBUFFER,buffer,""); if ((ptr->defines = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed for InstallPackageItem() #4a"); } ExpandVarstring(ELSECLASSBUFFER,buffer,""); if ((ptr->elsedef = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed for InstallPackageItem() #4b"); } AddInstallable(ptr->defines); AddInstallable(ptr->elsedef); if (VPKGTOP == NULL) /* First element in the list */ { VPKG = ptr; } else { VPKGTOP->next = ptr; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->log = LOGP; ptr->inform = INFORMP; ptr->logaudit = AUDITP; ptr->cmp = sense; ptr->pkgmgr = mgr; ptr->action = action; ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); ptr->next = NULL; VPKGTOP = ptr; InitializeAction(); } /*******************************************************************/ int GetCmpSense(char *sense) { int i; for (i = 0; CMPSENSETEXT[i] != '\0'; i++) { if (strcmp(sense,CMPSENSETEXT[i]) == 0) { return i; } } yyerror("Unknown comparison sense"); return (int) cmpsense_eq; } /*******************************************************************/ int GetPkgMgr(char *pkgmgr) { int i; for (i = 0; PKGMGRTEXT[i] != '\0'; i++) { if (strcmp(pkgmgr,PKGMGRTEXT[i]) == 0) { return i; } } yyerror("Unknown package manager"); return (int) pkgmgr_none; } /*******************************************************************/ int GetPkgAction(char *pkgaction) { int i; for (i = 0; PKGACTIONTEXT[i] != '\0'; i++) { if (strcmp(pkgaction,PKGACTIONTEXT[i]) == 0) { return i; } } yyerror("Unknown package action"); return (int) pkgaction_none; } /*******************************************************************/ void InstallImageItem(char *cf_findertype,char *path,mode_t plus,mode_t minus,char *destination,char *action,char *uidnames,char *gidnames,int size,char comp,int rec,char type,char lntype,char *server) { struct Image *ptr; char *spl; char buf1[CF_EXPANDSIZE], buf2[CF_EXPANDSIZE], buf3[CF_EXPANDSIZE], buf4[CF_EXPANDSIZE]; struct TwoDimList *tp = NULL; struct Item *expserver = NULL, *ep; if (!IsInstallable(CLASSBUFF)) { Debug1("Not installing copy item, no match (%s,%s)\n",path,CLASSBUFF); InitializeAction(); return; } buf2[0] = '\0'; Debug1("InstallImageItem (%s) (+%o)(-%o) (%s), server=%s\n",path,plus,minus,destination,server); if (strlen(action) == 0) /* default action */ { strcat(action,"fix"); } if (!(strcmp(action,"silent") == 0 || strcmp(action,"warn") == 0 || strcmp(action,"fix") == 0)) { sprintf(VBUFF,"Illegal action in image/copy item: %s",action); yyerror(VBUFF); return; } ExpandVarstring(path,buf1,""); ExpandVarstring(server,buf3,""); if (strlen(buf1) > 1) { DeleteSlash(buf1); } expserver = SplitStringAsItemList(buf3,LISTSEPARATOR); Build2DListFromVarstring(&tp,path,LISTSEPARATOR,false); /* Must split on space in comm string */ Set2DList(tp); for (spl = Get2DListEnt(tp); spl != NULL; spl = Get2DListEnt(tp)) { for (ep = expserver; ep != NULL; ep=ep->next) { Debug("\nBegin pass with server = %s\n",ep->name); if ((ptr = (struct Image *)malloc(sizeof(struct Image))) == NULL) { FatalError("Memory Allocation failed for InstallImageItem() #1"); } if ((ptr->classes = strdup(CLASSBUFF)) == NULL) { FatalError("Memory Allocation failed for InstallImageItem() #3"); } if (!FORCENETCOPY && ((strcmp(ep->name,VFQNAME) == 0) || (strcmp(ep->name,VUQNAME) == 0) || (strcmp(ep->name,VSYSNAME.nodename) == 0))) { Debug("Swapping %s for localhost\n",server); free(ep->name); ep->name = strdup("localhost"); } if (strlen(ep->name) > MAXHOSTNAMELEN) { snprintf(OUTPUT,CF_BUFSIZE,"Server name (%s) is too long",ep->name); yyerror(OUTPUT); DeleteItemList(expserver); return; } if (!IsItemIn(VSERVERLIST,ep->name)) /* cache list of servers */ { AppendItem(&VSERVERLIST,ep->name,NULL); } Debug("Transformed server %s into %s\n",server,ep->name); if ((ptr->server = strdup(ep->name)) == NULL) { FatalError("Memory Allocation failed for InstallImageItem() #5"); } if ((ptr->action = strdup(action)) == NULL) { FatalError("Memory Allocation failed for InstallImageItem() #6"); } ExpandVarstring(ALLCLASSBUFFER,buf4,""); if ((ptr->defines = strdup(buf4)) == NULL) { FatalError("Memory Allocation failed for InstallImageItem() #7"); } ExpandVarstring(ELSECLASSBUFFER,buf4,""); if ((ptr->elsedef = strdup(buf4)) == NULL) { FatalError("Memory Allocation failed for InstallImageItem() #7"); } ExpandVarstring(FAILOVERBUFFER,buf4,""); if ((ptr->failover = strdup(buf4)) == NULL) { FatalError("Memory Allocation failed for InstallImageItem() #8"); } if (strlen(destination) == 0) { strcpy(buf2,spl); } else { ExpandVarstring(destination,buf2,""); } if (IsDefinedClass(CLASSBUFF)) { if ((strcmp(spl,buf2) == 0) && (strcmp(ep->name,"localhost") == 0)) { yyerror("Image loop: file/dir copies to itself or missing destination file"); continue; } } if (strlen(buf2) > 1) { DeleteSlash(buf2); } if (!IsAbsoluteFileName(buf2)) { if (strncmp(buf2,"home",4) == 0) { if (strlen(buf2) > 4 && buf2[4] != '/') { yyerror("illegal use of home or not absolute pathname"); return; } } else if (*buf2 == '$') { /* unexpanded variable */ } else { snprintf(OUTPUT,CF_BUFSIZE,"Image %s needs an absolute pathname",buf2); yyerror(OUTPUT); return; } } if ((ptr->destination = strdup(buf2)) == NULL) { FatalError("Memory Allocation failed for InstallImageItem() #4"); } if ((ptr->path = strdup(spl)) == NULL) { FatalError("Memory Allocation failed for InstallImageItem() #2"); } if (VIMAGETOP == NULL) { VIMAGE = ptr; } else { VIMAGETOP->next = ptr; } if ((ptr->cf_findertype = strdup(cf_findertype)) == NULL) { FatalError("Memory Allocation failed for cf_findertype ptr in InstallImageItem()"); } ptr->plus = plus; ptr->minus = minus; ptr->uid = MakeUidList(uidnames); ptr->gid = MakeGidList(gidnames); ptr->force = FORCE; ptr->next = NULL; ptr->backup = IMAGEBACKUP; ptr->done = 'n'; ptr->audit = AUDITPTR; ptr->lineno = LINENUMBER; ptr->scope = strdup(CONTEXTID); if (strlen(LOCALREPOS) > 0) { ExpandVarstring(LOCALREPOS,buf2,""); ptr->repository = strdup(buf2); } else { ptr->repository = NULL; } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->recurse = rec; ptr->type = type; ptr->stealth = STEALTH; ptr->checkroot = CHKROOT; ptr->preservetimes = PRESERVETIMES; ptr->encrypt = ENCRYPT; ptr->verify = VERIFY; ptr->size = size; ptr->comp = comp; ptr->linktype = lntype; ptr->symlink = VCPLNPARSE; ptr->exclusions = VEXCLUDEPARSE; ptr->inclusions = VINCLUDEPARSE; ptr->filters = VFILTERBUILD; ptr->ignores = VIGNOREPARSE; ptr->cache = NULL; ptr->purge = PURGE; if (PURGE == 'y') { ptr->forcedirs = 'y'; ptr->typecheck = 'n'; } else { ptr->forcedirs = FORCEDIRS; ptr->typecheck = TYPECHECK; } if (ptr->purge == 'y' && strstr(ep->name,"localhost") != 0) { Verbose("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); Verbose("!! Purge detected in local (non-cfservd) file copy to file %s\n",ptr->destination); Verbose("!! Do not risk purge if source %s is NFS mounted (see manual)\n",ptr->path); Verbose("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); } ptr->log = LOGP; ptr->inform = INFORMP; ptr->logaudit = AUDITP; ptr->plus_flags = PLUSFLAG; ptr->minus_flags = MINUSFLAG; ptr->trustkey = TRUSTKEY; ptr->compat = COMPATIBILITY; ptr->forceipv4 = FORCEIPV4; ptr->xdev = XDEV; if (ptr->compat == 'y' && ptr->encrypt == 'y') { yyerror("You cannot mix version1 compatibility with encrypted transfers"); return; } ptr->acl_aliases = VACLBUILD; ptr->inode_cache = NULL; VIMAGETOP = ptr; AddInstallable(ptr->defines); AddInstallable(ptr->elsedef); } } DeleteItemList(expserver); Delete2DList(tp); InitializeAction(); } /*******************************************************************/ void InstallAuthItem(char *path,char *attribute,struct Auth **list,struct Auth **listtop,char *classes) /* This is the top level interface for installing access rules for the server. Picks out the structures by name. */ { struct TwoDimList *tp = NULL; char attribexp[CF_EXPANDSIZE]; char *sp1; struct Item *vlist = NULL,*ip; Debug1("InstallAuthItem(%s,%s)\n",path,attribute); vlist = SplitStringAsItemList(attribute,LISTSEPARATOR); Build2DListFromVarstring(&tp,path,LISTSEPARATOR,false); Set2DList(tp); for (sp1 = Get2DListEnt(tp); sp1 != NULL; sp1 = Get2DListEnt(tp)) { for (ip = vlist; ip != NULL; ip = ip->next) { ExpandVarstring(ip->name,attribexp,""); Debug1("InstallAuthItem(%s=%s,%s)\n",path,sp1,attribexp); if (AuthPathExists(sp1,*list)) { AddAuthHostItem(sp1,attribexp,classes,list); } else { InstallAuthPath(sp1,attribexp,classes,list,listtop); } } } Delete2DList(tp); DeleteItemList(vlist); } /*******************************************************************/ int GetCommAttribute(char *s) { int i; char comm[CF_MAXVARSIZE]; for (i = 0; s[i] != '\0'; i++) { s[i] = ToLower(s[i]); } comm[0]='\0'; sscanf(s,"%[^=]",comm); Debug1("GetCommAttribute(%s)\n",comm); for (i = 0; COMMATTRIBUTES[i] != NULL; i++) { if (strncmp(COMMATTRIBUTES[i],comm,strlen(comm)) == 0) { Debug1("GetCommAttribute - got: %s\n",COMMATTRIBUTES[i]); return i; } } return cfbad; } /*******************************************************************/ void HandleRecurse(char *value) { int n = -1; if (strcmp(value,"inf") == 0) { VRECURSE = CF_INF_RECURSE; } else { /* Bas if (strncmp(CURRENTOBJECT,"home",4) == 0) { Bas yyerror("Recursion is always infinite for home"); return; } */ sscanf(value,"%d",&n); if (n == -1) { yyerror("Illegal recursion specifier"); } else { VRECURSE = n; } } } /*******************************************************************/ void HandleCopyType(char *value) { if (strcmp(value,"ctime") == 0) { Debug1("Set copy by ctime\n"); COPYTYPE = 't'; return; } else if (strcmp(value,"mtime") == 0) { Debug1("Set copy by mtime\n"); COPYTYPE = 'm'; return; } else if (strcmp(value,"checksum")==0 || strcmp(value,"sum") == 0) { Debug1("Set copy by md5 checksum\n"); COPYTYPE = 'c'; return; } else if (strcmp(value,"byte")==0 || strcmp(value,"binary") == 0) { Debug1("Set copy by byte comaprison\n"); COPYTYPE = 'b'; return; } else if (strcmp(value,"any")==0 || strcmp(value,"binary") == 0) { Debug1("Set copy by any comaprison\n"); COPYTYPE = 'a'; return; } yyerror("Illegal copy type"); } /*******************************************************************/ void HandleDisableFileType(char *value) { if (strlen(CURRENTITEM) != 0) { Warning("Redefinition of filetype in disable"); } if (strcmp(value,"link") == 0 || strcmp(value,"links") == 0) { strcpy(CURRENTITEM,"link"); } else if (strcmp(value,"plain") == 0 || strcmp(value,"file") == 0) { strcpy(CURRENTITEM,"file"); } else { yyerror("Disable filetype unknown"); } } /*******************************************************************/ void HandleDisableRotate(char *value) { int num = 0; if (strcmp(value,"empty") == 0 || strcmp(value,"truncate") == 0) { ROTATE = CF_TRUNCATE; } else { sscanf(value,"%d",&num); if (num == 0) { yyerror("disable/rotate value must be a decimal number greater than zero or keyword empty"); } if (! SILENT && num > 99) { Warning("rotate value looks silly"); } ROTATE = (short) num; } } /*******************************************************************/ void HandleAge(char *days) { sscanf(days,"%d",&VAGE); Debug1("HandleAge(%d)\n",VAGE); } /*******************************************************************/ void HandleProcessMatches(char *value) { int i = -1; switch (*value) { case '>': PROCOMP = '>'; value++; break; case '<': PROCOMP = '<'; value++; break; default : PROCOMP = '='; } sscanf(value,"%d",&i); if (i < 0) { yyerror("matches attribute with silly value (must be >= 0)"); } PROMATCHES = (short) i; ACTIONPENDING = true; } /*******************************************************************/ void HandleProcessSignal(char *value) { int i; char *sp; for (i = 1; i < highest_signal; i++) { for (sp = value; *sp != '\0'; sp++) { *sp = ToUpper(*sp); } if (strcmp(SIGNALS[i],"no signal") == 0) { continue; } if (strcmp(SIGNALS[i]+3,value) == 0) /* 3 to cut off "sig" */ { PROSIGNAL = (short) i; return; } } i = 0; sscanf(value,"%d",&i); if (i < 1 && i >= highest_signal) { yyerror("Unknown signal in attribute - try using a number"); } ACTIONPENDING = true; PROSIGNAL = (short) i; } /*******************************************************************/ void HandleNetmask(char *value) { if (strlen(DESTINATION) == 0) { strcpy(DESTINATION,value); } else { yyerror("redefinition of netmask"); } } /*******************************************************************/ void HandleIPAddress(char *value) { if (strlen(LINKTO) == 0) { strcpy(LINKTO,value); } else { yyerror("redefinition of ip address"); } } /*******************************************************************/ void HandleBroadcast(char *value) { if (strlen(CURRENTOBJECT) != 0) { yyerror("redefinition of broadcast address"); printf("Previous val = %s\n",CURRENTOBJECT); } if (strcmp("ones",value) == 0) { strcpy(CURRENTOBJECT,"one"); return; } if (strcmp("zeroes",value) == 0) { strcpy(CURRENTOBJECT,"zero"); return; } if (strcmp("zeros",value) == 0) { strcpy(CURRENTOBJECT,"zero"); return; } yyerror("Illegal broadcast specifier (ones/zeros)"); } /*******************************************************************/ void AppendToActionSequence (char *action) { int j = 0; char *sp,cbuff[CF_BUFSIZE],actiontxt[CF_BUFSIZE]; Debug1("Installing item (%s) in the action sequence list\n",action); AppendItem(&VACTIONSEQ,action,CLASSBUFF); if (strstr(action,"module")) { USEENVIRON=true; } cbuff[0]='\0'; actiontxt[0]='\0'; sp = action; while (*sp != '\0') { ++j; sscanf(sp,"%[^. ]",cbuff); while ((*sp != '\0') && (*sp !='.')) { sp++; } if (*sp == '.') { sp++; } if (IsHardClass(cbuff)) { char *tmp = malloc(strlen(action)+30); sprintf(tmp,"Error in action sequence: %s\n",action); yyerror(tmp); free(tmp); yyerror("You cannot add a reserved class!"); return; } if (j == 1) { strcpy(actiontxt,cbuff); continue; } else if (!IsSpecialClass(cbuff)) { AddInstallable(cbuff); } } } /*******************************************************************/ void AppendToAccessList (char *user) { char id[CF_MAXVARSIZE]; struct passwd *pw; Debug1("Adding to access list for %s\n",user); if (isalpha((int)user[0])) { if ((pw = getpwnam(user)) == NULL) { yyerror("No such user in password database"); return; } sprintf(id,"%d",pw->pw_uid); AppendItem(&VACCESSLIST,id,NULL); } else { AppendItem(&VACCESSLIST,user,NULL); } } /*******************************************************************/ void HandleLinkAction(char *value) { if (strcmp(value,"silent") == 0) { LINKSILENT = true; return; } yyerror("Invalid link action"); } /*******************************************************************/ void HandleDeadLinks(char *value) { if (strcmp(value,"kill") == 0) { DEADLINKS = true; return; } if (strcmp(value,"force") == 0) { FORCELINK = 'y'; return; } yyerror("Invalid deadlink option"); } /*******************************************************************/ void HandleLinkType(char *value) { if (strcmp(value,"hard") == 0) { if (ACTION_IS_LINKCHILDREN) { yyerror("hard links inappropriate for multiple linkage"); } if (ACTION == image) { yyerror("hard links inappropriate for copy operation"); } LINKTYPE = 'h'; return; } if (strcmp(value,"symbolic") == 0 || strcmp(value,"sym") == 0) { LINKTYPE = 's'; return; } if (strcmp(value,"abs") == 0 || strcmp(value,"absolute") == 0) { LINKTYPE = 'a'; return; } if (strcmp(value,"rel") == 0 || strcmp(value,"relative") == 0) { LINKTYPE = 'r'; return; } if (strcmp(value,"none") == 0 || strcmp(value,"copy") == 0) { LINKTYPE = 'n'; return; } snprintf(OUTPUT,CF_BUFSIZE*2,"Invalid link type %s\n",value); yyerror(OUTPUT); } /*******************************************************************/ void HandleServer(char *value) { Debug("Server in copy set to : %s\n",value); strcpy(CFSERVER,value); } /*******************************************************************/ void HandleDefine(char *value) { char *sp; Debug("Define response classes: %s\n",value); if (strlen(value) > CF_BUFSIZE) { yyerror("class list too long - can't handle it!"); } /*if (!IsInstallable(value)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Undeclared installable define=%s (see AddInstallable)",value); yyerror(OUTPUT); } */ strcpy(ALLCLASSBUFFER,value); for (sp = value; *sp != '\0'; sp++) { if (*sp == ':' || *sp == ',' || *sp == '.') { continue; } if (! isalnum((int)*sp) && *sp != '_') { snprintf(OUTPUT,CF_BUFSIZE*2,"Illegal class list in define=%s\n",value); yyerror(OUTPUT); } } } /*******************************************************************/ void HandleElseDefine(char *value) { char *sp; Debug("Define elsedefault classes: %s\n",value); if (strlen(value) > CF_BUFSIZE) { yyerror("class list too long - can't handle it!"); } strcpy(ELSECLASSBUFFER,value); for (sp = value; *sp != '\0'; sp++) { if (*sp == ':' || *sp == ',' || *sp == '.') { continue; } if (! isalnum((int)*sp) && *sp != '_') { snprintf(OUTPUT,CF_BUFSIZE*2,"Illegal class list in elsedefine=%s\n",value); yyerror(OUTPUT); } } } /*******************************************************************/ void HandleFailover(char *value) { char *sp; Debug("Define failover classes: %s\n",value); if (strlen(value) > CF_BUFSIZE) { yyerror("class list too long - can't handle it!"); } strcpy(FAILOVERBUFFER,value); for (sp = value; *sp != '\0'; sp++) { if (*sp == ':' || *sp == ',' || *sp == '.') { continue; } if (! isalnum((int)*sp) && *sp != '_') { snprintf(OUTPUT,CF_BUFSIZE*2,"Illegal class list in failover=%s\n",value); yyerror(OUTPUT); } } } /*******************************************************************/ /* Level 4 */ /*******************************************************************/ struct UidList *MakeUidList(char *uidnames) { struct UidList *uidlist; struct Item *ip, *tmplist; char uidbuff[CF_BUFSIZE]; char *sp; int offset; struct passwd *pw; char *machine, *user, *domain, buffer[CF_EXPANDSIZE], *usercopy=NULL; int uid; int tmp = -1; uidlist = NULL; buffer[0] = '\0'; ExpandVarstring(uidnames,buffer,""); for (sp = buffer; *sp != '\0'; sp+=strlen(uidbuff)) { if (*sp == ',') { sp++; } if (sscanf(sp,"%[^,]",uidbuff)) { if (uidbuff[0] == '+') /* NIS group - have to do this in a roundabout */ { /* way because calling getpwnam spoils getnetgrent */ offset = 1; if (uidbuff[1] == '@') { offset++; } setnetgrent(uidbuff+offset); tmplist = NULL; while (getnetgrent(&machine,&user,&domain)) { if (user != NULL) { AppendItem(&tmplist,user,NULL); } } endnetgrent(); for (ip = tmplist; ip != NULL; ip=ip->next) { if ((pw = getpwnam(ip->name)) == NULL) { if (!PARSING) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unknown user [%s]\n",ip->name); CfLog(cferror,OUTPUT,""); } uid = CF_UNKNOWN_OWNER; /* signal user not found */ usercopy = ip->name; } else { uid = pw->pw_uid; } AddSimpleUidItem(&uidlist,uid,usercopy); } DeleteItemList(tmplist); continue; } if (isdigit((int)uidbuff[0])) { sscanf(uidbuff,"%d",&tmp); uid = (uid_t)tmp; } else { if (strcmp(uidbuff,"*") == 0) { uid = CF_SAME_OWNER; /* signals wildcard */ } else if ((pw = getpwnam(uidbuff)) == NULL) { if (!PARSING) { snprintf(OUTPUT,CF_BUFSIZE,"Unknown user %s\n",uidbuff); CfLog(cferror,OUTPUT,""); } uid = CF_UNKNOWN_OWNER; /* signal user not found */ usercopy = uidbuff; } else { uid = pw->pw_uid; } } AddSimpleUidItem(&uidlist,uid,usercopy); } } if (uidlist == NULL) { AddSimpleUidItem(&uidlist,CF_SAME_OWNER,(char *) NULL); } return (uidlist); } /*********************************************************************/ struct GidList *MakeGidList(char *gidnames) { struct GidList *gidlist; char gidbuff[CF_BUFSIZE],buffer[CF_EXPANDSIZE]; char *sp, *groupcopy=NULL; struct group *gr; int gid; int tmp = -1; gidlist = NULL; buffer[0] = '\0'; ExpandVarstring(gidnames,buffer,""); for (sp = buffer; *sp != '\0'; sp+=strlen(gidbuff)) { if (*sp == ',') { sp++; } if (sscanf(sp,"%[^,]",gidbuff)) { if (isdigit((int)gidbuff[0])) { sscanf(gidbuff,"%d",&tmp); gid = (gid_t)tmp; } else { if (strcmp(gidbuff,"*") == 0) { gid = CF_SAME_GROUP; /* signals wildcard */ } else if ((gr = getgrnam(gidbuff)) == NULL) { if (!PARSING) { snprintf(OUTPUT,CF_BUFSIZE,"Unknown group %s\n",gidbuff); CfLog(cferror,OUTPUT,""); } gid = CF_UNKNOWN_GROUP; groupcopy = gidbuff; } else { gid = gr->gr_gid; } } AddSimpleGidItem(&gidlist,gid,groupcopy); } } if (gidlist == NULL) { AddSimpleGidItem(&gidlist,CF_SAME_GROUP,NULL); } return(gidlist); } /*******************************************************************/ void InstallTidyPath(char *path,char *wild,int rec,short age,char travlinks,int tidysize,char type,char ldirs,char tidydirs,char *classes) { struct Tidy *ptr; char *sp,ebuff[CF_EXPANDSIZE]; int no_of_links = 0; if (!IsInstallable(classes)) { InitializeAction(); Debug1("Not installing tidy path, no match\n"); return; } VBUFF[0]='\0'; /* Expand any variables */ ExpandVarstring(path,ebuff,""); if (strlen(ebuff) != 1) { DeleteSlash(ebuff); } if ((ptr = (struct Tidy *)malloc(sizeof(struct Tidy))) == NULL) { FatalError("Memory Allocation failed for InstallTidyItem() #1"); } if ((ptr->path = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallTidyItem() #3"); } if (VTIDYTOP == NULL) /* First element in the list */ { VTIDY = ptr; } else { VTIDYTOP->next = ptr; } if (rec != CF_INF_RECURSE && strncmp("home/",ptr->path,5) == 0) /* Is this a subdir of home wildcard? */ { for (sp = ptr->path; *sp != '\0'; sp++) /* Need to make recursion relative to start */ { /* of the search, not relative to home */ if (*sp == '/') { no_of_links++; } } } if (PIFELAPSED != -1) { ptr->ifelapsed = PIFELAPSED; } else { ptr->ifelapsed = VIFELAPSED; } if (PEXPIREAFTER != -1) { ptr->expireafter = PEXPIREAFTER; } else { ptr->expireafter = VEXPIREAFTER; } ptr->done = 'n'; ptr->scope = strdup(CONTEXTID); ptr->tidylist = NULL; ptr->maxrecurse = rec + no_of_links; ptr->next = NULL; ptr->xdev = XDEV; ptr->exclusions = VEXCLUDEPARSE; ptr->ignores = VIGNOREPARSE; VEXCLUDEPARSE = NULL; VIGNOREPARSE = NULL; VTIDYTOP = ptr; AddTidyItem(path,wild,rec+no_of_links,age,travlinks,tidysize,type,ldirs,tidydirs,classes); } /*********************************************************************/ void AddTidyItem(char *path,char *wild,int rec,short age,char travlinks,int tidysize,char type,char ldirs,short tidydirs,char *classes) { char varbuff[CF_EXPANDSIZE]; struct Tidy *ptr; struct Item *ip; Debug1("AddTidyItem(%s,pat=%s,size=%d)\n",path,wild,tidysize); if (!IsInstallable(CLASSBUFF)) { InitializeAction(); Debug1("Not installing TidyItem no match\n"); return; } for (ptr = VTIDY; ptr != NULL; ptr=ptr->next) { ExpandVarstring(path,varbuff,""); if (strcmp(ptr->path,varbuff) == 0) { PrependTidy(&(ptr->tidylist),wild,rec,age,travlinks,tidysize,type,ldirs,tidydirs,classes); for (ip = VEXCLUDEPARSE; ip != NULL; ip=ip->next) { AppendItem(&(ptr->exclusions),ip->name,ip->classes); } for (ip = VIGNOREPARSE; ip != NULL; ip=ip->next) { AppendItem(&(ptr->ignores),ip->name,ip->classes); } DeleteItemList(VEXCLUDEPARSE); DeleteItemList(VIGNOREPARSE); /* Must have the maximum recursion level here */ if (rec == CF_INF_RECURSE || ((ptr->maxrecurse < rec) && (ptr->maxrecurse != CF_INF_RECURSE))) { ptr->maxrecurse = rec; } return; } } } /*********************************************************************/ int TidyPathExists(char *path) { struct Tidy *tp; char ebuff[CF_EXPANDSIZE]; ExpandVarstring(path,ebuff,""); for (tp = VTIDY; tp != NULL; tp=tp->next) { if (strcmp(tp->path,ebuff) == 0) { Debug1("TidyPathExists(%s)\n",ebuff); return true; } } return false; } /*******************************************************************/ /* Level 5 */ /*******************************************************************/ void AddSimpleUidItem(struct UidList **uidlist,int uid,char *uidname) { struct UidList *ulp, *u; char *copyuser; if ((ulp = (struct UidList *)malloc(sizeof(struct UidList))) == NULL) { FatalError("cfengine: malloc() failed #1 in AddSimpleUidItem()"); } ulp->uid = uid; if (uid == CF_UNKNOWN_OWNER) /* unknown user */ { if ((copyuser = strdup(uidname)) == NULL) { FatalError("cfengine: malloc() failed #2 in AddSimpleUidItem()"); } ulp->uidname = copyuser; } else { ulp->uidname = NULL; } ulp->next = NULL; if (*uidlist == NULL) { *uidlist = ulp; } else { for (u = *uidlist; u->next != NULL; u = u->next) { } u->next = ulp; } } /*******************************************************************/ void AddSimpleGidItem(struct GidList **gidlist,int gid,char *gidname) { struct GidList *glp,*g; char *copygroup; if ((glp = (struct GidList *)malloc(sizeof(struct GidList))) == NULL) { FatalError("cfengine: malloc() failed #1 in AddSimpleGidItem()"); } glp->gid = gid; if (gid == CF_UNKNOWN_GROUP) /* unknown group */ { if ((copygroup = strdup(gidname)) == NULL) { FatalError("cfengine: malloc() failed #2 in AddSimpleGidItem()"); } glp->gidname = copygroup; } else { glp->gidname = NULL; } glp->next = NULL; if (*gidlist == NULL) { *gidlist = glp; } else { for (g = *gidlist; g->next != NULL; g = g->next) { } g->next = glp; } } /***********************************************************************/ void InstallAuthPath(char *path,char *hostname,char *classes,struct Auth **list,struct Auth **listtop) { struct Auth *ptr; char ebuff[CF_EXPANDSIZE]; if (!IsDefinedClass(classes)) { Debug1("Not installing Auth path, no match\n"); InitializeAction(); return; } Debug1("InstallAuthPath(%s,%s) for %s\n",path,hostname,classes); ExpandVarstring(path,ebuff,""); if (strlen(ebuff) != 1) { DeleteSlash(ebuff); } if ((ptr = (struct Auth *)malloc(sizeof(struct Auth))) == NULL) { FatalError("Memory Allocation failed for InstallAuthPath() #1"); } if ((ptr->path = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallAuthPath() #3"); } if (*listtop == NULL) /* First element in the list */ { *list = ptr; } else { (*listtop)->next = ptr; } ptr->accesslist = NULL; ptr->maproot = NULL; ptr->encrypt = false; ptr->next = NULL; *listtop = ptr; AddAuthHostItem(ptr->path,hostname,classes,list); } /***********************************************************************/ void AddAuthHostItem(char *path,char *attribute,char *classes,struct Auth **list) { char varbuff[CF_EXPANDSIZE]; struct Auth *ptr; struct Item *ip, *split = NULL; Debug1("AddAuthHostItem(%s,%s)\n",path,attribute); if (!IsDefinedClass(CLASSBUFF)) { Debug1("Not installing AuthItem no match\n"); return; } split = SplitStringAsItemList(attribute,LISTSEPARATOR); for (ptr = *list; ptr != NULL; ptr=ptr->next) { ExpandVarstring(path,varbuff,""); if (strcmp(ptr->path,varbuff) == 0) { for (ip = split; ip != NULL; ip=ip->next) { if (!HandleAdmitAttribute(ptr,ip->name)) { PrependItem(&(ptr->accesslist),ip->name,classes); } } DeleteItemList(split); return; } } DeleteItemList(split); } /*********************************************************************/ int AuthPathExists(char *path,struct Auth *list) { struct Auth *ap; char ebuff[CF_EXPANDSIZE]; Debug1("AuthPathExists(%s)\n",path); ExpandVarstring(path,ebuff,""); if (ebuff[0] != '/') { yyerror("Missing absolute path to a directory"); FatalError("Cannot continue"); } for (ap = list; ap != NULL; ap=ap->next) { if (strcmp(ap->path,ebuff) == 0) { return true; } } return false; } /*********************************************************************/ int HandleAdmitAttribute(struct Auth *ptr,char *attribute) { char value[CF_MAXVARSIZE],buffer[CF_EXPANDSIZE],host[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE],*sp; value[0] = '\0'; ExpandVarstring(attribute,ebuff,NULL); sscanf(ebuff,"%*[^=]=%s",value); if (value[0] == '\0') { return false; } Debug1("HandleAdmitFileAttribute(%s)\n",value); switch(GetCommAttribute(attribute)) { case cfencryp: Debug("\nENCRYPTION tag %s\n",value); if ((strcmp(value,"on")==0) || (strcmp(value,"true")==0)) { ptr->encrypt = true; return true; } break; case cfroot: Debug("\nROOTMAP tag %s\n",value); ExpandVarstring(value,buffer,""); for (sp = buffer; *sp != '\0'; sp+=strlen(host)) { if (*sp == ',') { sp++; } host[0] = '\0'; if (sscanf(sp,"%[^,\n]",host)) { char copyhost[CF_BUFSIZE]; strncpy(copyhost,host,CF_BUFSIZE-1); if (!strstr(copyhost,".")) { if (strlen(copyhost)+strlen(VDOMAIN) < CF_MAXVARSIZE-2) { strcat(copyhost,"."); strcat(copyhost,VDOMAIN); } else { yyerror("Server name too long"); } } if (!IsItemIn(ptr->maproot,copyhost)) { PrependItem(&(ptr->maproot),copyhost,NULL); } else { Debug("Not installing %s in rootmap\n",host); } } } return true; break; } yyerror("Illegal admit/deny attribute"); return false; } /*********************************************************************/ void PrependTidy(struct TidyPattern **list,char *wild,int rec,short age,char travlinks,int tidysize,char type,char ldirs,char tidydirs,char *classes) { struct TidyPattern *tp; char *spe = NULL,*sp, buffer[CF_EXPANDSIZE]; if ((tp = (struct TidyPattern *)malloc(sizeof(struct TidyPattern))) == NULL) { perror("Can't allocate memory in PrependTidy()"); FatalError(""); } if ((sp = strdup(wild)) == NULL) { FatalError("Memory Allocation failed for PrependTidy() #2"); } ExpandVarstring(ALLCLASSBUFFER,buffer,""); if ((tp->defines = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed for PrependTidy() #2a"); } ExpandVarstring(ELSECLASSBUFFER,buffer,""); if ((tp->elsedef = strdup(buffer)) == NULL) { FatalError("Memory Allocation failed for PrependTidy() #2a"); } AddInstallable(tp->defines); AddInstallable(tp->elsedef); if ((classes!= NULL) && (spe = malloc(strlen(classes)+2)) == NULL) { perror("Can't allocate memory in PrependItem()"); FatalError(""); } if (travlinks == '?') { travlinks = 'F'; /* False is default */ } tp->audit = AUDITPTR; tp->lineno = LINENUMBER; tp->size = tidysize; tp->recurse = rec; tp->age = age; tp->searchtype = type; tp->travlinks = travlinks; tp->filters = VFILTERBUILD; tp->pattern = sp; tp->next = *list; tp->dirlinks = ldirs; tp->log = LOGP; tp->inform = INFORMP; tp->logaudit = AUDITP; tp->compress = COMPRESS; tp->rmdirs = tidydirs; tp->tidied = false; *list = tp; if (classes != NULL) { strcpy(spe,classes); tp->classes = spe; } else { tp->classes = NULL; } } /* EOF */ cfengine-2.2.10/src/strategies.c0000644000175000001440000001116010661520372013375 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /**************************************************************************/ /* */ /* File: strategies.c */ /* */ /**************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*****************************************************************************/ void InstallStrategy(char *alias,char *classes) { struct Strategy *ptr; char ebuff[CF_EXPANDSIZE]; Debug1("InstallStrategy(%s,%s)\n",alias,classes); if (! IsInstallable(classes)) { Debug1("Not installing Strategy no match\n"); return; } ExpandVarstring(alias,ebuff,""); if ((ptr = (struct Strategy *)malloc(sizeof(struct Strategy))) == NULL) { FatalError("Memory Allocation failed for InstallStrategy() #1"); } if ((ptr->name = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed in InstallStrategy"); } ExpandVarstring(classes,ebuff,""); if ((ptr->classes = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed in InstallStrategy"); } if (VSTRATEGYLISTTOP == NULL) /* First element in the list */ { VSTRATEGYLIST = ptr; } else { VSTRATEGYLISTTOP->next = ptr; } ptr->next = NULL; ptr->type = 'r'; ptr->done = 'n'; ptr->strategies = NULL; VSTRATEGYLISTTOP = ptr; } /*****************************************************************************/ void AddClassToStrategy(char *alias,char *class,char *value) { struct Strategy *sp; char buf[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; int val = -1; if (class[strlen(class)-1] != ':') { yyerror("Strategic class definition doesn't end in colon"); return; } memset(buf,0,CF_MAXVARSIZE); sscanf(class,"%[^:]",&buf); ExpandVarstring(value,ebuff,""); Debug("AddClassToStrategy(%s,%s,%s)\n",alias,class,ebuff); sscanf(ebuff,"%d",&val); if (val <= 0) { yyerror("strategy distribution weight must be an integer"); return; } for (sp = VSTRATEGYLIST; sp != NULL; sp=sp->next) { if (strcmp(alias,sp->name) == 0) { if (!IsItemIn(sp->strategies,buf)) { AppendItem(&(sp->strategies),buf,ebuff); AddInstallable(buf); } } } } /*****************************************************************************/ void SetStrategies() { struct Strategy *ptr; struct Item *ip; int total,count; double prob,cum,fluct; for (ptr = VSTRATEGYLIST; ptr != NULL; ptr=ptr->next) { if (ptr->done == 'y') { continue; } else { ptr->done = 'y'; } Verbose("\n Evaluating strategy %s (type=%c)\n",ptr->name,ptr->type); if (ptr->strategies) { total = 0; for (ip = ptr->strategies; ip !=NULL; ip=ip->next) { total += atoi(ip->classes); } /* Get random number 0-1 */ fluct = drand48(); count = 0; cum = 0.0; for (ip = ptr->strategies; ip != NULL; ip=ip->next) { prob = ((double)atoi(ip->classes))/((double)total); cum += prob; Debug("%s : %f cum %f\n",ip->name,prob,cum); Verbose(" Class %d: %f-%f\n",count,cum-prob,cum); if ((fluct < cum) || ip->next == NULL) { Verbose(" - Choosing %s (%f)\n",ip->name,fluct); AddClassToHeap(ip->name); break; } count++; } } } } /*****************************************************************************/ /* END */ cfengine-2.2.10/src/cf.defs.h0000644000175000001440000014026111120234302012527 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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, 675 Mass Ave, Cambridge, MA 02139, USA. */ /*******************************************************************/ /* */ /* HEADER for cfengine */ /* */ /*******************************************************************/ /* Hard link this file between cf2/cf3 for consistent update */ #include "conf.h" #include #include #ifndef _GETOPT_H #include "../pub/getopt.h" #endif #ifdef HAVE_STDLIB_H #include #endif #include #include #include #include #ifdef HAVE_UNAME #include #else #define _SYS_NMLN 257 struct utsname { char sysname[_SYS_NMLN]; char nodename[_SYS_NMLN]; char release[_SYS_NMLN]; char version[_SYS_NMLN]; char machine[_SYS_NMLN]; }; #endif #include #include #ifdef HAVE_SYS_SYSTEMINFO_H # include #endif #ifdef HAVE_SYS_PARAM_H # include #endif #ifdef HAVE_SYS_MOUNT_H #include #endif #ifdef HAVE_SYS_WAIT_H # include #endif #ifndef WEXITSTATUS # define WEXITSTATUS(s) ((unsigned)(s) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(s) (((s) & 255) == 0) #endif #ifndef WIFSIGNALED # define WIFSIGNALED(s) ((s) & 0) /* Can't use for BSD */ #endif #ifndef WTERMSIG #define WTERMSIG(s) ((s) & 0) #endif #include #include #include #include #include #include #include #ifdef HAVE_DIRENT_H # include #else # define dirent direct # if HAVE_SYS_NDIR_H # include # endif # if HAVE_SYS_DIR_H # include # endif # if HAVE_NDIR_H # include # endif #endif #include #include extern int errno; /* Do this for ease of configuration from the Makefile */ #ifdef HPuUX #define HPUX #endif #ifdef SunOS #define SUN4 #endif /* end of patch */ #ifdef AIX #ifndef ps2 #include #endif #endif #ifdef SOLARIS #include #undef nfstype #endif #ifndef HAVE_BCOPY #define bcopy(fr,to,n) memcpy(to,fr,n) /* Eliminate ucblib */ #define bcmp(s1, s2, n) memcmp ((s1), (s2), (n)) #define bzero(s, n) memset ((s), 0, (n)) #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef DARWIN #include #include #endif #ifdef HAVE_SYS_MALLOC_H #ifdef DARWIN #include #include #endif #else #ifdef HAVE_MALLOC_H #ifndef OPENBSD #ifdef __FreeBSD__ #include #else #include #endif #endif #endif #endif #include #ifdef HAVE_VFS_H # include #endif #ifdef HPUX # include #endif #ifdef HAVE_UTIME_H # include /* use utime not utimes for portability */ #elif TIME_WITH_SYS_TIME # include # include #elif HAVE_SYS_TIME_H # include #elif ! defined(AOS) # include #endif #ifdef HAVE_TIME_H # include #endif #ifdef HAVE_SYS_TIME_H # include #endif #include #include #ifdef HAVE_SYS_SOCKIO_H # include #endif #include #include #include #include #ifndef AOS # include #endif #include #if !defined LINUX && !defined NT #include #undef sgi #include #endif #ifdef LINUX #ifdef __GLIBC__ # include # include #else # include # include #endif #endif #ifdef HAVE_PCRE # include #elif HAVE_RXPOSIX_H # include #elif HAVE_REGEX_H # include #else # include "../pub/gnuregex.h" #endif #ifndef HAVE_SNPRINTF #include "../pub/snprintf.h" #endif #ifndef CLOCK_REALTIME #define CLOCK_REALTIME 1 #endif #ifndef HAVE_CLOCKID_T typedef int clockid_t; #endif #ifdef HAVE_PTHREAD_H # define __USE_GNU 1 # include # ifndef _SC_THREAD_STACK_MIN # define _SC_THREAD_STACK_MIN PTHREAD_STACK_MIN # endif #endif #ifdef HAVE_SCHED_H # include #endif #ifdef WITH_SELINUX # include #endif /*******************************************************************/ /* Various defines */ /*******************************************************************/ #define true 1 #define false 0 #define CF_BUFSIZE 4096 #define CF_BILLION 1000000000L #define CF_EXPANDSIZE (2*CF_BUFSIZE) #define CF_ALLCLASSSIZE (4*CF_BUFSIZE) #define CF_BUFFERMARGIN 32 #define CF_BLOWFISHSIZE 16 #define CF_SMALLBUF 128 #define CF_MAXVARSIZE 1024 #define CF_NONCELEN (CF_BUFSIZE/16) #define CF_MAXLINKSIZE 256 #define CF_MAXLINKLEVEL 4 #define CF_MAXFARGS 8 #define CF_MAX_IP_LEN 64 /* numerical ip length */ #define CF_PROCCOLS 16 #define CF_HASHTABLESIZE 4969 /* prime number */ #define CF_MACROALPHABET 61 /* a-z, A-Z plus a bit */ #define CF_MAXSHELLARGS 64 #define CF_MAX_SCLICODES 16 #define CF_SAMEMODE 0 #define CF_SAME_OWNER ((uid_t)-1) #define CF_UNKNOWN_OWNER ((uid_t)-2) #define CF_SAME_GROUP ((gid_t)-1) #define CF_UNKNOWN_GROUP ((gid_t)-2) #define CF_NOSIZE -1 #define CF_EXTRASPC 8 /* pads items during AppendItem for eol handling in editfiles */ #define CF_INFINITY ((int)999999999) #define CF_TICKS_PER_DAY 86400 /* 60 * 60 *24 */ #define CF_TICKS_PER_HOUR 3600 /* 60 * 60 */ #define CF_HALF_HOUR 1800 /* 60 * 30 */ #define CF_NOT_CONNECTED -1 #define CF_COULD_NOT_CONNECT -2 #define CF_RECURSION_LIMIT 100 #define CF_MONDAY_MORNING 342000 #define CF_NOVAL -0.7259285297502359 #define CF_UNUSED_CHAR (char)127 #define CF_MAXDIGESTNAMELEN 7 #define CF_CHKSUMKEYOFFSET CF_MAXDIGESTNAMELEN+1 #define CF_IFREQ 2048 /* Reportedly the largest size that does not segfault 32/64 bit*/ #define CF_ADDRSIZE 128 #define CF_METHODEXEC 0 #define CF_METHODREPLY 1 #define CF_EXEC_IFELAPSED 5 #define CF_EXEC_EXPIREAFTER 10 /* Need this to to avoid conflict with solaris 2.6 and db.h */ #ifdef SOLARIS # ifndef u_int32_t # define u_int32_t uint32_t # define u_int16_t uint16_t # define u_int8_t uint8_t # endif #endif #include /*******************************************************************/ /* Class array limits */ /* This is the only place you ever need to edit anything */ /*******************************************************************/ #define CF_CLASSATTR 36 /* increase this for each new class added */ /* It defines the array size for class data */ #define CF_ATTRDIM 3 /* Only used in CLASSATTRUBUTES[][] defn */ /* end class array limits */ /*******************************************************************/ #define CF_CLASSUSAGE "cf_classes.db" #define CF_PERFORMANCE "performance.db" #define CF_CHKDB "checksum_digests.db" #define CF_AVDB_FILE "cf_observations.db" #define CF_OLDAVDB_FILE "cf_learning.db" #define CF_STATEDB_FILE "cf_state.db" #define CF_OLDLASTDB_FILE "cf_lastseen.db" #define CF_LASTDB_FILE "cf_LastSeen.db" #define CF_AUDITDB_FILE "cf_Audit.db" #define CF_STATELOG_FILE "state_log" #define CF_ENVNEW_FILE "env_data.new" #define CF_ENV_FILE "env_data" #define CF_TCPDUMP_COMM "/usr/sbin/tcpdump -t -n -v" #define CF_SCLI_COMM "/usr/local/bin/scli" #define CF_INPUTSVAR "CFINPUTS" /* default name for file path var */ #define CF_ALLCLASSESVAR "CFALLCLASSES" /* default name for CFALLCLASSES env */ #define CF_INF_RECURSE -99 /* code used to signify inf in recursion */ #define CF_TRUNCATE -1 #define CF_EMPTYFILE -2 #define CF_USELOGFILE true /* synonyms for tidy.c */ #define CF_NOLOGFILE false #define CF_SAVED ".cfsaved" #define CF_EDITED ".cfedited" #define CF_NEW ".cfnew" #define CFD_TERMINATOR "---cfXen/gine/cfXen/gine---" #define CFD_TRUE "CFD_TRUE" #define CFD_FALSE "CFD_FALSE" #define CF_ANYCLASS "any" #define CF_NOCLASS "XX_CF_opposite_any_XX" #define CF_NOUSER -99 #define CF_RSA_PROTO_OFFSET 24 #define CF_PROTO_OFFSET 16 #define CF_INBAND_OFFSET 8 #define CF_SMALL_OFFSET 2 /* digest sizes */ #define CF_MD5_LEN 16 #define CF_SHA_LEN 20 #define CF_SHA1_LEN 20 #define CF_BEST_LEN 0 #define CF_SHA224_LEN 28 #define CF_SHA256_LEN 32 #define CF_SHA384_LEN 48 #define CF_SHA512_LEN 64 #define CF_DONE 't' #define CF_MORE 'm' #ifndef ERESTARTSYS # define ERESTARTSYS EINTR #endif #define CF_FAILEDSTR "BAD: Unspecified server refusal (see verbose server output)" #define CF_CHANGEDSTR1 "BAD: File changed " /* Split this so it cannot be recognized */ #define CF_CHANGEDSTR2 "while copying" #define CF_START_DOMAIN "undefined.domain" #define CFLOGSIZE 1048576 /* Size of lock-log before rotation */ /* Output control defines */ #define Verbose if (VERBOSE || DEBUG || D2) printf #define EditVerbose if (EDITVERBOSE || DEBUG || D2) printf #define Debug4 if (D4) printf #define Debug3 if (D3 || DEBUG || D2) printf #define Debug2 if (DEBUG || D2) printf #define Debug1 if (DEBUG || D1) printf #define Debug if (DEBUG || D1 || D2) printf #define DebugVoid if (false) printf #define Silent if (! SILENT || VERBOSE || DEBUG || D2) printf #define DaemonOnly if (ISCFENGINE) yyerror("This belongs in cfservd.conf") #define CfengineOnly if (! ISCFENGINE) yyerror("This belongs in cfagent.conf") /* GNU REGEX */ #define BYTEWIDTH 8 /*****************************************************************************/ /* Auditing key */ #define CF_NOP 'n' #define CF_CHG 'c' #define CF_WARN 'w' /* something wrong but nothing done */ #define CF_FAIL 'f' #define CF_DENIED 'd' #define CF_TIMEX 't' #define CF_INTERPT 'i' #define CF_REGULAR 'r' #define CF_REPORT 'R' #define CF_UNKNOWN 'u' /*****************************************************************************/ #define CFGRACEPERIOD 4.0 /* training period in units of counters (weeks,iterations)*/ #define cf_noise_threshold 6 /* number that does not warrent large anomaly status */ #define big_number 100000 #define CF_PERSISTENCE 15 #define LDT_BUFSIZE 10 #define CF_GRAINS 64 #define ATTR 11 #define CF_NETATTR 7 /* icmp udp dns tcpsyn tcpfin tcpack */ #define PH_LIMIT 10 #define CF_WEEK (7.0*24.0*3600.0) #define CF_HOUR 3600 #define CF_RELIABLE_CLASSES 7*24 /* CF_WEEK/CF_HOUR */ #define CF_MEASURE_INTERVAL (5.0*60.0) #define CF_OBSERVABLES 91 struct QPoint { double q; double expect; double var; }; struct Event { time_t t; struct QPoint Q; }; struct Averages { struct QPoint Q[CF_OBSERVABLES]; }; struct OldAverages /* For conversion to new db */ { double expect_number_of_users; double expect_rootprocs; double expect_otherprocs; double expect_diskfree; double expect_loadavg; double expect_incoming[ATTR]; double expect_outgoing[ATTR]; double expect_pH[PH_LIMIT]; double var_number_of_users; double var_rootprocs; double var_otherprocs; double var_diskfree; double var_loadavg; double var_incoming[ATTR]; double var_outgoing[ATTR]; double var_pH[PH_LIMIT]; double expect_netin[CF_NETATTR]; double expect_netout[CF_NETATTR]; double var_netin[CF_NETATTR]; double var_netout[CF_NETATTR]; }; /******************************************************************/ struct LockData { pid_t pid; time_t time; }; /*****************************************************************************/ #define CF_AUDIT_COMMENT 128 #define CF_AUDIT_VERSION 64 #define CF_AUDIT_DATE 32 struct AuditLog /* key includes operation and date */ { char operator[CF_AUDIT_COMMENT]; char comment[CF_AUDIT_COMMENT]; char filename[CF_AUDIT_COMMENT]; char bundle[CF_AUDIT_VERSION]; /* not used in cf2 */ char version[CF_AUDIT_VERSION]; char date[CF_AUDIT_DATE]; short lineno; char status; }; /*******************************************************************/ /* Copy file defines */ /*******************************************************************/ /* Based heavily on cp.c in GNU-fileutils */ #ifndef DEV_BSIZE #ifdef BSIZE #define DEV_BSIZE BSIZE #else /* !BSIZE */ #define DEV_BSIZE 4096 #endif /* !BSIZE */ #endif /* !DEV_BSIZE */ /* Extract or fake data from a `struct stat'. ST_BLKSIZE: Optimal I/O blocksize for the file, in bytes. ST_NBLOCKS: Number of 512-byte blocks in the file (including indirect blocks). */ #define SMALL_BLOCK_BUF_SIZE 512 #ifndef HAVE_ST_BLOCKS # define ST_BLKSIZE(statbuf) DEV_BSIZE # if defined(_POSIX_SOURCE) || !defined(BSIZE) /* fileblocks.c uses BSIZE. */ # define ST_NBLOCKS(statbuf) (((statbuf).st_size + 512 - 1) / 512) # else /* !_POSIX_SOURCE && BSIZE */ # define ST_NBLOCKS(statbuf) (st_blocks ((statbuf).st_size)) # endif /* !_POSIX_SOURCE && BSIZE */ #else /* HAVE_ST_BLOCKS */ /* Some systems, like Sequents, return st_blksize of 0 on pipes. */ # define ST_BLKSIZE(statbuf) ((statbuf).st_blksize > 0 \ ? (statbuf).st_blksize : DEV_BSIZE) # if defined(hpux) || defined(__hpux__) || defined(__hpux) /* HP-UX counts st_blocks in 1024-byte units. This loses when mixing HP-UX and BSD filesystems with NFS. */ # define ST_NBLOCKS(statbuf) ((statbuf).st_blocks * 2) # else /* !hpux */ # if defined(_AIX) && defined(_I386) /* AIX PS/2 counts st_blocks in 4K units. */ # define ST_NBLOCKS(statbuf) ((statbuf).st_blocks * 8) # else /* not AIX PS/2 */ # define ST_NBLOCKS(statbuf) ((statbuf).st_blocks) # endif /* not AIX PS/2 */ # endif /* !hpux */ #endif /* HAVE_ST_BLOCKS */ #ifndef SEEK_CUR #define SEEK_CUR 1 #endif /*******************************************************************/ /* Client server defines */ /*******************************************************************/ #define CFENGINE_SERVICE "cfengine" enum PROTOS { cfd_exec, cfd_auth, cfd_get, cfd_opendir, cfd_synch, cfd_classes, cfd_md5, cfd_smd5, cfd_cauth, cfd_sauth, cfd_ssynch, cfd_sget, cfd_version, cfd_sopendir, cfd_bad }; #define CF_WORDSIZE 8 /* Number of bytes in a word */ /*******************************************************************/ enum cf_filetype { cf_reg, cf_link, cf_dir, cf_fifo, cf_block, cf_char, cf_sock }; /*******************************************************************/ enum roles { cf_connect, cf_accept }; /*******************************************************************/ struct cfstat { char *cf_filename; /* What file are we statting? */ char *cf_server; /* Which server did this come from? */ enum cf_filetype cf_type; /* enum filetype */ mode_t cf_lmode; /* Mode of link, if link */ mode_t cf_mode; /* Mode of remote file, not link */ uid_t cf_uid; /* User ID of the file's owner */ gid_t cf_gid; /* Group ID of the file's group */ off_t cf_size; /* File size in bytes */ time_t cf_atime; /* Time of last access */ time_t cf_mtime; /* Time of last data modification */ time_t cf_ctime; /* Time of last file status change */ char cf_makeholes; /* what we need to know from blksize and blks */ char *cf_readlink; /* link value or NULL */ int cf_failed; /* stat returned -1 */ int cf_nlink; /* Number of hard links */ int cf_ino; /* inode number on server */ dev_t cf_dev; /* device number */ struct cfstat *next; }; /*******************************************************************/ struct cfdir { DIR *cf_dirh; struct Item *cf_list; struct Item *cf_listpos; /* current pos */ }; typedef struct cfdir CFDIR; /*******************************************************************/ struct cfdirent { struct dirent *cf_dirp; char d_name[CF_BUFSIZE]; /* This is bigger than POSIX */ }; /*******************************************************************/ enum cfsizes { cfabs, cfpercent }; /*******************************************************************/ enum statepolicy { cfreset, /* Policy when trying to add already defined persistent states */ cfpreserve }; /*******************************************************************/ enum builtin { nofn, fn_randomint, fn_newerthan, fn_accessedbefore, fn_changedbefore, fn_fileexists, fn_isdir, fn_islink, fn_isplain, fn_execresult, fn_execshellresult, fn_returnszero, fn_returnszeroshell, fn_iprange, fn_hostrange, fn_isdefined, fn_strcmp, fn_regcmp, fn_classregex, fn_showstate, fn_friendstat, fn_readfile, fn_returnvars, fn_returnclasses, fn_syslog, fn_setstate, fn_unsetstate, fn_module, fn_adj, fn_readarray, fn_readtable, fn_readlist, fn_selectpl, fn_selectpn, fn_selectpna, fn_greaterthan, fn_lessthan, fn_readtcp, fn_printfile, fn_userexists, fn_groupexists }; /*******************************************************************/ enum actions { none, control, alerts, groups, image, resolve, processes, files, tidy, homeservers, binservers, mailserver, required, disks, mountables, links, import, shellcommands, disable, rename_disable, makepath, ignore, broadcast, defaultroute, misc_mounts, editfiles, unmounta, admit, deny, acls, interfaces, filters, strategies, packages, methods, scli }; /*******************************************************************/ enum classes { empty, soft, sun4, ultrx, hp, aix, linuxx, solaris, osf, digital, sun3, irix4, irix, irix64, freebsd, solarisx86, bsd4_3, newsos, netbsd, aos, bsd_i, nextstep, crayos, GnU, cfnt, unix_sv, openbsd, cfsco, darwin, ux4800, qnx, dragonfly, unused1, unused2, unused3 }; /*******************************************************************/ enum fileactions { warnall, warnplain, warndirs, fixall, fixplain, fixdirs, touch, linkchildren, create, compress, alert }; /*******************************************************************/ enum commattr /* See COMMATTRIBUTES[] in globals.c for matching entry */ { cffindertype, cfrecurse, cfmode, cfowner, cfgroup, cfage, cfaction, cfpattern, cflinks, cftype, cfdest, cfforce, cfforcedirs, cfforceipv4, cfforcereplyto, cfbackup, cfrotate, cfsize, cfmatches, cfsignal, cfexclude, cfcopy, cfsymlink, cfcptype, cflntype, cfinclude, cfdirlinks, cfrmdirs, cfserver, cfdefine, cfelsedef, cffailover, cftimeout, cffree, cfnofile, cfacl, cfpurge, cfuseshell, cfsetlog, cfsetinform, cfsetipaddress, cfsetnetmask, cfsetbroadcast, cfignore, cfdeldir, cfdelfstab, cfstealth, cfchksum, cfflags, cfencryp, cfverify, cfroot, cftypecheck, cfumask, cfcompress, cffilter, cffork, cfchdir, cfchroot, cfpreview, cfrepository, cftimestamps, cftrustkey, cfcompat, cfmountoptions, cfreadonly, cfversion, cfcmp, cfpkgmgr, cfxdev, cfrxdirs, cfretvars, cfretclasses, cfsendclasses, cfifelap, cfexpaft, cfscan, cfnoabspath, cfcheckroot, cfsetaudit, cfbad /* HvB must be as last */ }; /*******************************************************************/ enum itemtypes { simple, netgroup, classscript, deletion, groupdeletion }; /*********************************************************************/ enum vnames { cfversionvar, cffaculty, cfsite, cfhost, cffqhost, cfipaddr, cfbinserver, cfsysadm, cfdomain, cftimezone, cfnetmask, cfnfstype, cfssize, cfscount, cfeditsize, cfbineditsize, cfactseq, cfmountpat, cfhomepat, cfaddclass, cfinstallclass, cfschedule, cfaccess, cfclass, cfarch, cfarch2, cfdate, cfyear, cfmonth, cfday, cfhr, cfmin, cfallclass, cfexcludecp, cfsinglecp, cfautodef, cfexcludeln, cfcplinks, cflncopies, cfrepos, cfspc, cftab, cflf, cfcr, cfn, cfdblquote, cfcolon, cfquote, cfdollar, cfrepchar, cflistsep, cfunderscore, cfifname, cfexpireafter, cfifelapsed, cfextension, cfsuspicious, cfspooldirs, cfnonattackers, cfattackers, cfmulticonn, cfarglist, cfmethodname, cfmethodpeers, cftrustkeys, cfdynamic, cfallowusers, cfskipverify, cfdefcopy, cfredef, cfdefpkgmgr, cfabortclasses, cfignoreinterfaceregex, nonexistentvar }; /*******************************************************************/ enum methproto { cfmeth_name, cfmeth_file, cfmeth_time, cfmeth_replyto, cfmeth_sendclass, cfmeth_attacharg, cfmeth_isreply, badmeths }; /*******************************************************************/ enum resc { rmountcom, runmountcom, rethernet, rmountopts, runused, rfstab, rmaildir, rnetstat, rpscomm, rpsopts }; /*******************************************************************/ enum aseq { mkpaths, lnks, chkmail, requir, diskreq, tidyf, shellcom, chkfiles, disabl, renam, mountresc, edfil, mountall, umnt, resolv, imag, netconfig, tzone, mountinfo, procs, pkgs, meths, non, plugin }; /*******************************************************************/ enum editnames { NoEdit, DeleteLinesStarting, DeleteLinesNotStarting, DeleteLinesContaining, DeleteLinesNotContaining, DeleteLinesMatching, DeleteLinesNotMatching, DeleteLinesStartingFileItems, DeleteLinesContainingFileItems, DeleteLinesMatchingFileItems, DeleteLinesNotStartingFileItems, DeleteLinesNotContainingFileItems, DeleteLinesNotMatchingFileItems, AppendIfNoSuchLine, PrependIfNoSuchLine, WarnIfNoSuchLine, WarnIfLineMatching, WarnIfNoLineMatching, WarnIfLineStarting, WarnIfLineContaining, WarnIfNoLineStarting, WarnIfNoLineContaining, HashCommentLinesContaining, HashCommentLinesStarting, HashCommentLinesMatching, SlashCommentLinesContaining, SlashCommentLinesStarting, SlashCommentLinesMatching, PercentCommentLinesContaining, PercentCommentLinesStarting, PercentCommentLinesMatching, ResetSearch, SetSearchRegExp, LocateLineMatching, InsertLine, AppendIfNoSuchLinesFromFile, IncrementPointer, ReplaceLineWith, ExpandVariables, DeleteToLineMatching, HashCommentToLineMatching, PercentCommentToLineMatching, SetScript, RunScript, RunScriptIfNoLineMatching, RunScriptIfLineMatching, AppendIfNoLineMatching, PrependIfNoLineMatching, DeleteNLines, EmptyEntireFilePlease, GotoLastLine, BreakIfLineMatches, BeginGroupIfNoMatch, BeginGroupIfMatch, BeginGroupIfNoLineMatching, BeginGroupIfNoSuchLine, BeginGroupIfLineMatching, EndGroup, Append, Prepend, SetCommentStart, SetCommentEnd, CommentLinesMatching, CommentLinesStarting, CommentToLineMatching, UnCommentToLineMatching, CommentNLines, UnCommentNLines, ReplaceAll, ReplaceFirst, With, SetLine, FixEndOfLine, AbortAtLineMatching, UnsetAbort, AutoMountDirectResources, UnCommentLinesContaining, UnCommentLinesMatching, InsertFile, CommentLinesContaining, BeginGroupIfFileIsNewer, BeginGroupIfFileExists, BeginGroupIfNoLineContaining, BeginGroupIfLineContaining, BeginGroupIfDefined, BeginGroupIfNotDefined, AutoCreate, WarnIfFileMissing, ForEachLineIn, EndLoop, ReplaceLinesMatchingField, SplitOn, AppendToLineIfNotContains, DeleteLinesAfterThisMatching, DefineClasses, ElseDefineClasses, CatchAbort, EditBackup, EditLog, EditInform, EditRecurse, EditMode, WarnIfContainsString, WarnIfContainsFile, EditIgnore, EditExclude, EditInclude, EditRepos, EditUmask, EditUseShell, EditFilter, DefineInGroup, EditIfElapsed, EditExpireAfter, EditSplit, LogAudit, }; enum RegExpTypes { posix, gnu, bsd }; /*******************************************************************/ enum SignalNames { cfnosignal, cfhup, cfint, cfquit, cfill, cftrap, cfiot, cfemt, cffpr, cfkill, cfbus, cfsegv, cfsys, cfpipe, cfalrm, cfterm }; #define highest_signal 64 /*******************************************************************/ enum cfoutputlevel { cfsilent, cfinform, cfverbose, cfeditverbose, cferror, cflogonly, cfloginform }; /*******************************************************************/ enum modestate { wild, who, which }; enum modesort { unknown, numeric, symbolic }; /*******************************************************************/ enum cmpsense /* For package version comparison */ { cmpsense_eq, cmpsense_gt, cmpsense_lt, cmpsense_ge, cmpsense_le, cmpsense_ne, cmpsense_none }; /*******************************************************************/ enum pkgmgrs /* Available package managers to query in packages: */ { pkgmgr_rpm, pkgmgr_dpkg, pkgmgr_sun, pkgmgr_aix, pkgmgr_portage, pkgmgr_freebsd, pkgmgr_none }; /*******************************************************************/ enum pkgactions /* What to do with a package if it is found/not found */ { pkgaction_install, pkgaction_remove, pkgaction_upgrade, pkgaction_fix, pkgaction_none }; /*******************************************************************/ typedef char flag; enum socks { netbiosns, netbiosdgm, netbiosssn, irc, cfengine, nfsd, smtp, www, ftp, ssh, wwws }; enum iptypes { icmp, udp, dns, tcpsyn, tcpack, tcpfin, tcpmisc }; enum observables { ob_users, ob_rootprocs, ob_otherprocs, ob_diskfree, ob_loadavg, ob_netbiosns_in, ob_netbiosns_out, ob_netbiosdgm_in, ob_netbiosdgm_out, ob_netbiosssn_in, ob_netbiosssn_out, ob_irc_in, ob_irc_out, ob_cfengine_in, ob_cfengine_out, ob_nfsd_in, ob_nfsd_out, ob_smtp_in, ob_smtp_out, ob_www_in, ob_www_out, ob_ftp_in, ob_ftp_out, ob_ssh_in, ob_ssh_out, ob_wwws_in, ob_wwws_out, ob_icmp_in, ob_icmp_out, ob_udp_in, ob_udp_out, ob_dns_in, ob_dns_out, ob_tcpsyn_in, ob_tcpsyn_out, ob_tcpack_in, ob_tcpack_out, ob_tcpfin_in, ob_tcpfin_out, ob_tcpmisc_in, ob_tcpmisc_out, ob_webaccess, ob_weberrors, ob_syslog, ob_messages, ob_temp0, ob_temp1, ob_temp2, ob_temp3, ob_cpuall, ob_cpu0, ob_cpu1, ob_cpu2, ob_cpu3, ob_spare }; struct sock { char *portnr; char *name; enum observables in; enum observables out; }; /*******************************************************************/ struct cfagent_connection { int sd; int trust; /* true if key being accepted on trust */ int authenticated; int protoversion; int family; /* AF_INET or AF_INET6 */ char localip[CF_MAX_IP_LEN]; char remoteip[CF_MAX_IP_LEN]; unsigned char *session_key; short error; }; /*******************************************************************/ struct cfObject { char *scope; /* Name of object (scope) */ void *hashtable[CF_HASHTABLESIZE]; /* Variable heap */ char type[CF_HASHTABLESIZE]; /* scalar or itlist? */ char *classlist; /* Private classes -- ? */ struct Item *actionsequence; struct cfObject *next; }; /* $(globalvar) $(obj.name) */ /*******************************************************************/ struct CompressedArray { int key; char *value; struct CompressedArray *next; }; /*******************************************************************/ struct Audit { char *version; char *filename; char *date; unsigned char digest[EVP_MAX_MD_SIZE+1]; struct Audit *next; }; /*******************************************************************/ /* Action /promise types */ /*******************************************************************/ struct Interface { char done; char *scope; char *ifdev; char *ipaddress; char *netmask; char *broadcast; char *classes; int lineno; struct Audit *audit; struct Interface *next; }; /*******************************************************************/ struct Method { char done; char *scope; char *chdir; char *chroot; uid_t uid; gid_t gid; char useshell; struct Item *send_args; struct Item *send_classes; struct Item *servers; struct Item *return_vars; struct Item *return_classes; char *file; char *name; unsigned char digest[EVP_MAX_MD_SIZE+1]; char *classes; char *bundle; char *forcereplyto; char invitation; int ifelapsed; int expireafter; char log; char inform; char logaudit; int lineno; struct Audit *audit; struct Method *next; }; /*******************************************************************/ struct Item { char done; char *name; char *classes; int counter; int ifelapsed; int expireafter; struct Item *next; struct Audit *audit; char logaudit; int lineno; char *scope; }; /*******************************************************************/ struct TwoDimList { short is2d; /* true if list > 1 */ short rounds; short tied; /* do variables march together or in rounds ? */ char sep; /* list separator */ struct Item *ilist; /* Each node contains a list */ struct Item *current; /* A static working pointer */ struct TwoDimList *next; }; /*******************************************************************/ struct Process { char done; char *scope; char *expr; /* search regex */ char *restart; /* shell comm to be done after */ char *chdir; char *chroot; uid_t uid; gid_t gid; mode_t umask; short matches; char comp; char *defines; char *elsedef; short signal; char action; char *classes; char useshell; char log; char inform; char logaudit; struct Item *exclusions; struct Item *inclusions; struct Item *filters; int ifelapsed; int expireafter; int lineno; struct Audit *audit; struct Process *next; }; /*******************************************************************/ struct Mountables { char done; char *scope; char readonly; /* y/n - true false */ char *filesystem; char *mountopts; char *classes; struct Audit *audit; int lineno; struct Mountables *next; }; /*******************************************************************/ struct Tidy { int maxrecurse; /* sets maxval */ char done; /* Too intensive in Tidy Pattern */ char *scope; char *path; char xdev; int ifelapsed; int expireafter; struct Item *exclusions; struct Item *ignores; struct TidyPattern *tidylist; struct Tidy *next; }; /**** SUB CLASS *********************************************/ struct TidyPattern { int recurse; short age; int size; /* in bytes */ char *pattern; /* synonym for pattern */ struct Item *filters; char *classes; char *defines; struct Audit *audit; int lineno; char tidied; char *elsedef; char compress; char travlinks; char dirlinks; /* k=keep, t=tidy */ char rmdirs; /* t=true, f=false, s=sub-only */ char searchtype; /* a, m, c time */ char log; char inform; char logaudit; struct TidyPattern *next; }; /*******************************************************************/ struct Mounted { char *scope; char *name; char *on; char *options; char *type; struct Audit *audit; int lineno; }; /*******************************************************************/ struct MiscMount { char done; char *scope; char *from; char *onto; char *mode; char *options; char *classes; int ifelapsed; int expireafter; struct Audit *audit; int lineno; struct MiscMount *next; }; /*******************************************************************/ struct UnMount { char done; char *scope; char *name; char *classes; char deletedir; /* y/n - true false */ char deletefstab; char force; int ifelapsed; int expireafter; struct Audit *audit; int lineno; struct UnMount *next; }; /*******************************************************************/ struct File { char done; char *scope; char *path; char *defines; char *elsedef; enum fileactions action; mode_t plus; mode_t minus; int recurse; char travlinks; struct Item *exclusions; struct Item *inclusions; struct Item *filters; struct Item *ignores; char *classes; struct UidList *uid; struct GidList *gid; struct Item *acl_aliases; char log; char compress; char inform; char logaudit; char xdev; char rxdirs; int ifelapsed; int expireafter; struct Audit *audit; int lineno; char checksum; /* m=md5, n=none, b = crosscheck etc (see CF_DIGEST_TYPES) */ u_long plus_flags; /* for *BSD chflags */ u_long minus_flags; /* for *BSD chflags */ struct File *next; }; /*******************************************************************/ struct Disk { char done; char *scope; char *name; char *classes; char *define; char *elsedef; char force; /* HvB: Bas van der Vlies */ int freespace; int ifelapsed; int expireafter; char log; char inform; char logaudit; char scanarrivals; struct Audit *audit; int lineno; struct Disk *next; }; /*******************************************************************/ struct Disable { char done; char *scope; char *name; char *destination; char *classes; char *type; char *repository; short rotate; int size; char comp; char action; /* d=delete,w=warn */ char *defines; char *elsedef; struct Item *filters; struct Disable *next; char log; char inform; char logaudit; int ifelapsed; int expireafter; struct Audit *audit; int lineno; }; /*******************************************************************/ struct Image { char done; char *scope; char *classes; char *defines; char *elsedef; char *failover; char xdev; int recurse; int ifelapsed; int expireafter; struct Audit *audit; int lineno; struct Item *exclusions; struct Item *inclusions; struct Item *filters; struct Item *ignores; char log; char inform; char logaudit; u_long plus_flags; /* for *BSD chflags */ u_long minus_flags; /* for *BSD chflags */ mode_t plus; mode_t minus; struct UidList *uid; struct GidList *gid; char *cf_findertype; /* Type info for finder */ char *path; char *destination; char *server; char *repository; char *action; /* fix / warn /silent */ char force; /* true false */ char forcedirs; char forceipv4; char type; /* checksum, ctime, binary */ char linktype; /* if file is linked instead of copied */ char stealth; /* preserve times on source files */ char preservetimes; /* preserve times in copy */ char checkroot; /* check perms on root directory */ char backup; int makeholes; off_t size; char comp; char purge; struct Item *symlink; struct cfstat *cache; /* stat cache */ struct CompressedArray *inode_cache; /* inode cache */ int addrfamily; struct Image *next; struct Item *acl_aliases; char typecheck; char trustkey; char encrypt; char verify; char compat; }; /*******************************************************************/ struct UidList { uid_t uid; char *uidname; /* when uid is -2 */ struct UidList *next; }; /*******************************************************************/ struct GidList { gid_t gid; char *gidname; /* when gid is -2 */ struct GidList *next; }; /*******************************************************************/ enum cffstype { posixfs, solarisfs, dfsfs, afsfs, hpuxfs, ntfs, badfs }; /*******************************************************************/ enum matchtypes { literalStart, literalComplete, literalSomewhere, regexComplete, NOTliteralStart, NOTliteralComplete, NOTliteralSomewhere, NOTregexComplete }; /*******************************************************************/ struct CFACL { char * acl_alias; enum cffstype type; char method; /* a = append, o = overwrite */ char nt_acltype; struct CFACE *aces; struct CFACL *next; }; /*******************************************************************/ struct CFACE { #ifdef NT char *access; /* allowed / denied */ long int NTMode; /* NT's access mask */ #endif char *mode; /* permission flags*/ char *name; /* id name */ char *acltype; /* user / group / other */ char *classes; struct CFACE *next; }; /*******************************************************************/ struct Link { char done; char *scope; char *from; char *to; char *classes; char *defines; char *elsedef; char force; short nofile; short silent; char type; char copytype; int recurse; int ifelapsed; int expireafter; struct Item *exclusions; struct Item *inclusions; struct Item *ignores; struct Item *filters; struct Item *copy; struct Link *next; char log; char inform; char logaudit; struct Audit *audit; int lineno; }; /*******************************************************************/ struct Edit { char done; /* Have this here, too dangerous in Edlist */ char warn; char *scope; char *fname; char *defines; char *elsedef; mode_t umask; char useshell; char split; char *repository; int recurse; char binary; /* y/n */ int ifelapsed; int expireafter; char logaudit; struct Audit *audit; int lineno; struct Item *ignores; struct Item *exclusions; struct Item *inclusions; struct Item *filters; struct Edlist *actions; struct Edit *next; }; /**** SUB-CLASS ********************************************/ struct Edlist { enum editnames code; char *data; struct Edlist *next; char *classes; }; /*******************************************************************/ enum filternames { filterresult, filterowner, filtergroup, filtermode, filtertype, filterfromctime, filtertoctime, filterfrommtime, filtertomtime, filterfromatime, filtertoatime, filterfromsize, filtertosize, filterexecregex, filternameregex, filterdefclasses, filterelsedef, filterexec, filtersymlinkto, filterpid, filterppid, filterpgid, filterrsize, filtersize, filterstatus, filtercmd, filterfromttime, filtertottime, filterfromstime, filtertostime, filtertty, filterpriority, filterthreads, NoFilter }; struct Filter { char *alias; char *defines; char *elsedef; char *classes; char context; /* f=file, p=process */ char *criteria[NoFilter]; /* array of strings */ struct Filter *next; }; /*******************************************************************/ struct ShellComm { char done; char *scope; char *name; char *classes; char *chdir; char *chroot; int timeout; mode_t umask; uid_t uid; gid_t gid; char useshell; struct ShellComm *next; char log; char inform; char logaudit; char fork; char *defines; char *elsedef; char preview; char noabspath; struct Audit *audit; int lineno; int ifelapsed; int expireafter; }; enum cfscli_codes { cfscli_arb, cfscli_ok, cfscli_return, cfscli_error, cfscli_noconnect, cfscli_noxml, cfscli_syntaxerr, cfscli_syntaxerr_args, cfscli_syntaxerr_regex, cfscli_syntaxerr_num, cfscli_syntaxerr_val, cfscli_syntaxerr_token, cfscli_syntaxerr_badcom, cfscli_snmp_return, cfscli_snmp_lookup, cfscli_null }; /*******************************************************************/ struct Auth { char *path; struct Item *accesslist; struct Item *maproot; /* which hosts should have root read access */ int encrypt; /* which files HAVE to be transmitted securely */ struct Auth *next; }; /*******************************************************************/ struct Strategy { char done; char *name; char *classes; char type; /* default r=random */ struct Item *strategies; struct Strategy *next; }; /*******************************************************************/ struct Package /* For packages: */ { char done; char *scope; char *name; char *classes; char log; char inform; char logaudit; char *defines; char *elsedef; char *ver; enum cmpsense cmp; enum pkgmgrs pkgmgr; enum pkgactions action; struct Package *next; struct Audit *audit; int lineno; int ifelapsed; int expireafter; }; /*******************************************************************/ /* Checksum database structures */ /*******************************************************************/ struct Checksum_Value { unsigned char mess_digest[EVP_MAX_MD_SIZE+1]; /* Content digest */ unsigned char attr_digest[EVP_MAX_MD_SIZE+1]; /* Attribute digest */ }; /*******************************************************************/ /* Ultrix/BSD don't have all these from sys/stat.h */ /*******************************************************************/ # ifndef S_IFBLK # define S_IFBLK 0060000 # endif # ifndef S_IFCHR # define S_IFCHR 0020000 # endif # ifndef S_IFDIR # define S_IFDIR 0040000 # endif # ifndef S_IFIFO # define S_IFIFO 0010000 # endif # ifndef S_IFREG # define S_IFREG 0100000 # endif # ifndef S_IFLNK # define S_IFLNK 0120000 # endif # ifndef S_IFSOCK # define S_IFSOCK 0140000 # endif # ifndef S_IFMT # define S_IFMT 00170000 # endif #ifndef S_ISREG # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif #ifndef S_ISDIR # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) #endif #ifndef S_ISLNK # define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) #endif #ifndef S_ISFIFO # define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) #endif #ifndef S_ISCHR # define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) #endif #ifndef S_ISBLK # define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) #endif #ifndef S_ISSOCK # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) #endif #ifndef S_IRUSR #define S_IRWXU 00700 #define S_IRUSR 00400 #define S_IWUSR 00200 #define S_IXUSR 00100 #define S_IRWXG 00070 #define S_IRGRP 00040 #define S_IWGRP 00020 #define S_IXGRP 00010 #define S_IRWXO 00007 #define S_IROTH 00004 #define S_IWOTH 00002 #define S_IXOTH 00001 #endif /********************************************************************/ /* *BSD chflags stuff - Andreas.Klussmann@infosys.heitec.net */ /********************************************************************/ # if !defined UF_NODUMP # define UF_NODUMP 0 # endif # if !defined UF_IMMUTABLE # define UF_IMMUTABLE 0 # endif # if !defined UF_APPEND # define UF_APPEND 0 # endif # if !defined UF_OPAQUE # define UF_OPAQUE 0 # endif # if !defined UF_NOUNLINK # define UF_NOUNLINK 0 # endif # if !defined SF_ARCHIVED # define SF_ARCHIVED 0 # endif # if !defined SF_IMMUTABLE # define SF_IMMUTABLE 0 # endif # if !defined SF_APPEND # define SF_APPEND 0 # endif # if !defined SF_NOUNLINK # define SF_NOUNLINK 0 # endif # define CHFLAGS_MASK ( UF_NODUMP | UF_IMMUTABLE | UF_APPEND | UF_OPAQUE | UF_NOUNLINK | SF_ARCHIVED | SF_IMMUTABLE | SF_APPEND | SF_NOUNLINK ) /* For cygwin32 */ #if !defined O_BINARY # define O_BINARY 0 #endif /*******************************************************************/ /* File path manipulation primitives */ /*******************************************************************/ /* Defined maximum length of a filename. */ #ifdef NT # define MAX_FILENAME 227 #else # define MAX_FILENAME 254 #endif /* File node separator (cygwin can use \ or / but prefer \ for communicating * with native windows commands). */ #ifdef NT # define IsFileSep(c) ((c) == '\\' || (c) == '/') # define FILE_SEPARATOR '\\' # define FILE_SEPARATOR_STR "\\" #else # define IsFileSep(c) ((c) == '/') # define FILE_SEPARATOR '/' # define FILE_SEPARATOR_STR "/" #endif /********************************************************************/ /* All prototypes */ /********************************************************************/ #include "prototypes.h" cfengine-2.2.10/src/timeout.c0000644000175000001440000000202110766756766012735 00000000000000/*****************************************************************************/ /* */ /* File: timeout.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*************************************************************************/ void SetTimeOut(int timeout) { ALARM_PID = -1; signal(SIGALRM,(void *)TimeOut); alarm(timeout); } /*************************************************************************/ void TimeOut() { alarm(0); if (ALARM_PID != -1) { Verbose("%s: Time out of process %d\n",VPREFIX,ALARM_PID); kill(ALARM_PID,cfterm); kill(ALARM_PID,cfkill); } else { Verbose("%s: Time out\n",VPREFIX); } } /*************************************************************************/ void DeleteTimeOut() { } cfengine-2.2.10/src/init.c0000644000175000001440000002166711023443413012174 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: init.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include "../pub/global.h" /*********************************************************************/ void CheckWorkDirectories() { struct stat statbuf; int result; char *sp; Debug("CheckWorkDirectories()\n"); if (uname(&VSYSNAME) == -1) { perror("uname "); FatalError("Uname couldn't get kernel name info!!\n"); } snprintf(LOGFILE,CF_BUFSIZE,"%s/cfagent.%s.log",VLOGDIR,VSYSNAME.nodename); VSETUIDLOG = strdup(LOGFILE); if (!IsPrivileged()) { Verbose("\n(Non privileged user...)\n\n"); if ((sp = getenv("HOME")) == NULL) { FatalError("You do not have a HOME variable pointing to your home directory"); } snprintf(VLOGDIR,CF_BUFSIZE,"%s/.cfagent",sp); snprintf(VLOCKDIR,CF_BUFSIZE,"%s/.cfagent",sp); snprintf(VBUFF,CF_BUFSIZE,"%s/.cfagent/test",sp); MakeDirectoriesFor(VBUFF,'y'); snprintf(VBUFF,CF_BUFSIZE,"%s/.cfagent/state/test",sp); MakeDirectoriesFor(VBUFF,'n'); snprintf(CFPRIVKEYFILE,CF_BUFSIZE,"%s/.cfagent/ppkeys/localhost.priv",sp); snprintf(CFPUBKEYFILE,CF_BUFSIZE,"%s/.cfagent/ppkeys/localhost.pub",sp); } else { snprintf(VBUFF,CF_BUFSIZE,"%s/test",VLOCKDIR); snprintf(VBUFF,CF_BUFSIZE,"%s/test",VLOGDIR); MakeDirectoriesFor(VBUFF,'n'); snprintf(VBUFF,CF_BUFSIZE,"%s/state/test",VLOGDIR); MakeDirectoriesFor(VBUFF,'n'); snprintf(CFPRIVKEYFILE,CF_BUFSIZE,"%s/ppkeys/localhost.priv",CFWORKDIR); snprintf(CFPUBKEYFILE,CF_BUFSIZE,"%s/ppkeys/localhost.pub",CFWORKDIR); } Verbose("Checking integrity of the state database\n"); snprintf(VBUFF,CF_BUFSIZE,"%s/state",VLOCKDIR); if (stat(VBUFF,&statbuf) == -1) { snprintf(VBUFF,CF_BUFSIZE,"%s/state",VLOCKDIR); MakeDirectoriesFor(VBUFF,'n'); if (chown(VBUFF,getuid(),getgid()) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to set owner on %s to %d.%d",VBUFF,getuid(),getgid()); CfLog(cferror,OUTPUT,"chown"); } chmod(VBUFF,(mode_t)0755); } else { if (statbuf.st_mode & 022) { snprintf(OUTPUT,CF_BUFSIZE*2,"UNTRUSTED: State directory %s (mode %o) was not private!\n",VLOCKDIR,statbuf.st_mode & 0777); CfLog(cferror,OUTPUT,""); } } Verbose("Checking integrity of the module directory\n"); snprintf(VBUFF,CF_BUFSIZE,"%s/modules",VLOCKDIR); if (stat(VBUFF,&statbuf) == -1) { snprintf(VBUFF,CF_BUFSIZE,"%s/modules/test",VLOCKDIR); MakeDirectoriesFor(VBUFF,'n'); snprintf(VBUFF,CF_BUFSIZE,"%s/modules",VLOCKDIR); if (chown(VBUFF,getuid(),getgid()) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to set owner on %s to %d.%d",VBUFF,getuid(),getgid()); CfLog(cferror,OUTPUT,"chown"); } chmod(VBUFF,(mode_t)0700); } else { if (statbuf.st_mode & 022) { snprintf(OUTPUT,CF_BUFSIZE*2,"UNTRUSTED: Module directory %s (mode %o) was not private!\n",VLOCKDIR,statbuf.st_mode & 0777); CfLog(cferror,OUTPUT,""); } } Verbose("Checking integrity of the input data for RPC\n"); snprintf(VBUFF,CF_BUFSIZE,"%s/rpc_in",VLOCKDIR); if (stat(VBUFF,&statbuf) == -1) { snprintf(VBUFF,CF_BUFSIZE,"%s/rpc_in/test",VLOCKDIR); MakeDirectoriesFor(VBUFF,'n'); snprintf(VBUFF,CF_BUFSIZE,"%s/rpc_in",VLOCKDIR); if (chown(VBUFF,getuid(),getgid()) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to set owner on %s to %d.%d",VBUFF,getuid(),getgid()); CfLog(cferror,OUTPUT,"chown"); } chmod(VBUFF,(mode_t)0700); } else { if (statbuf.st_mode & 077) { snprintf(OUTPUT,CF_BUFSIZE*2,"UNTRUSTED: RPC input directory %s was not private! (%o)\n",VBUFF,statbuf.st_mode & 0777); FatalError(OUTPUT); } } Verbose("Checking integrity of the output data for RPC\n"); snprintf(VBUFF,CF_BUFSIZE,"%s/rpc_out",VLOCKDIR); if (stat(VBUFF,&statbuf) == -1) { snprintf(VBUFF,CF_BUFSIZE,"%s/rpc_out/test",VLOCKDIR); MakeDirectoriesFor(VBUFF,'n'); snprintf(VBUFF,CF_BUFSIZE,"%s/rpc_out",VLOCKDIR); if (chown(VBUFF,getuid(),getgid()) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to set owner on %s to %d.%d",VBUFF,getuid(),getgid()); CfLog(cferror,OUTPUT,"chown"); } chmod(VBUFF,(mode_t)0700); } else { if (statbuf.st_mode & 077) { snprintf(OUTPUT,CF_BUFSIZE*2,"UNTRUSTED: RPC output directory %s was not private! (%o)\n",VBUFF,statbuf.st_mode & 0777); FatalError(OUTPUT); } } Verbose("Checking integrity of the PKI directory\n"); snprintf(VBUFF,CF_BUFSIZE,"%s/ppkeys",VLOCKDIR); if (stat(VBUFF,&statbuf) == -1) { snprintf(VBUFF,CF_BUFSIZE,"%s/ppkeys/test",VLOCKDIR); MakeDirectoriesFor(VBUFF,'n'); snprintf(VBUFF,CF_BUFSIZE,"%s/ppkeys",VLOCKDIR); chmod(VBUFF,(mode_t)0700); /* Keys must be immutable to others */ } else { if (statbuf.st_mode & 077) { snprintf(OUTPUT,CF_BUFSIZE*2,"UNTRUSTED: Private key directory %s/ppkeys (mode %o) was not private!\n",VLOCKDIR,statbuf.st_mode & 0777); FatalError(OUTPUT); } } Verbose("Making sure that locks are private...\n"); if (chown(VLOCKDIR,getuid(),getgid()) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to set owner on %s to %d.%d",VLOCKDIR,getuid(),getgid()); CfLog(cferror,OUTPUT,"chown"); } /* Locks must be immutable to others */ if (stat(VLOCKDIR,&statbuf) != -1) { /* change permissions go-w */ chmod(VLOCKDIR,(mode_t)(statbuf.st_mode & ~022)); } } /**********************************************************************/ void ActAsDaemon(int preserve) { int fd, maxfd; #ifdef HAVE_SETSID setsid(); #endif closelog(); fflush(NULL); fd = open("/dev/null", O_RDWR, 0); if (fd != -1) { dup2(fd,STDIN_FILENO); dup2(fd,STDOUT_FILENO); dup2(fd,STDERR_FILENO); if (fd > STDERR_FILENO) close(fd); } chdir("/"); #ifdef HAVE_SYSCONF maxfd = sysconf(_SC_OPEN_MAX); #else # ifdef _POXIX_OPEN_MAX maxfd = _POSIX_OPEN_MAX; # else maxfd = 1024; # endif #endif for (fd=STDERR_FILENO+1; fd < maxfd; ++fd) { if (fd != preserve) close(fd); } } /*******************************************************************/ int IsIPV6Address(char *name) { char *sp; int count,max = 0; Debug("IsIPV6Address(%s)\n",name); if (name == NULL) { return false; } count = 0; for (sp = name; *sp != '\0'; sp++) { if (isalnum((int)*sp)) { count++; } else if ((*sp != ':') && (*sp != '.')) { return false; } if (*sp == 'r') { return false; } if (count > max) { max = count; } else { count = 0; } } if (max <= 2) { Debug("Looks more like a MAC address"); return false; } if (strstr(name,":") == NULL) { return false; } if (StrStr(name,"scope")) { return false; } return true; } /*******************************************************************/ int IsIPV4Address(char *name) { char *sp; int count = 0; Debug("IsIPV4Address(%s)\n",name); if (name == NULL) { return false; } for (sp = name; *sp != '\0'; sp++) { if (!isdigit((int)*sp) && (*sp != '.')) { return false; } if (*sp == '.') { count++; } } if (count != 3) { return false; } return true; } /*******************************************************************/ int IsInterfaceAddress(char *adr) /* Does this address belong to a local interface */ { struct Item *ip; for (ip = IPADDRESSES; ip != NULL; ip=ip->next) { if (StrnCmp(adr,ip->name,strlen(adr)) == 0) { Debug("Identifying (%s) as one of my interfaces\n",adr); return true; } } Debug("(%s) is not one of my interfaces\n",adr); return false; } cfengine-2.2.10/src/popen_def.c0000644000175000001440000000662311023536224013166 00000000000000 /* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: popen_def.c */ /* */ /* Created: Fri Jul 20 15:13:38 2001 */ /* */ /* Author: > */ /* */ /* Revision: $Id$ */ /* */ /* Description: */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" extern pid_t *CHILD; extern int MAXFD; /* Max number of simultaneous pipes */ /******************************************************************************/ int cfpclose_def(FILE *pp,char *defines,char *elsedef) { int fd, status, wait_result; pid_t pid; Debug("cfpclose_def(pp)\n"); if (CHILD == NULL) /* popen hasn't been called */ { return -1; } fd = fileno(pp); if ((pid = CHILD[fd]) == 0) { return -1; } CHILD[fd] = 0; if (fclose(pp) == EOF) { return -1; } Debug("cfpopen_def - Waiting for process %d\n",pid); #ifdef HAVE_WAITPID while(waitpid(pid,&status,0) < 0) { if (errno != EINTR) { Verbose("Waitpid failed - %d\n",errno); return -1; } } if (status == 0) { AddMultipleClasses(defines); } else { AddMultipleClasses(elsedef); Debug("Child returned status %d\n",status); } return status; #else while ((wait_result = wait(&status)) != pid) { if (wait_result <= 0) { snprintf(OUTPUT,CF_BUFSIZE,"Wait for child failed\n"); CfLog(cfinform,OUTPUT,"wait"); return -1; } } if (WIFSIGNALED(status)) { return -1; } if (! WIFEXITED(status)) { return -1; } if (WEXITSTATUS(status) == 0) { AddMultipleClasses(defines); } else { AddMultipleClasses(elsedef); } return (WEXITSTATUS(status)); #endif } cfengine-2.2.10/src/cflex.l0000644000175000001440000004273311170173265012350 00000000000000%{ /* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* LEXER for cfengine */ /* */ /* */ /*******************************************************************/ #include "cfparse.h" #include "cf.defs.h" #include "cf.extern.h" /* Note the %o %a declarations to allow more internal workspace */ %} %option noyywrap %s INCONTROL BRACELIST INASSIGN CFSERVD %o 60000 %a 40000 %p 20000 %n 2000 actiont copy:|resolve:|files:|tidy:|homeservers:|binservers:|mailserver:|disks:|mountables:|links:|shellcommands:|disable:|directories:|ignore:|interfaces:|defaultroute:|miscmounts:|unmount:|processes:|required:|broadcast:|alerts:|packages:|methods:|rename:|scli: space [ \t\xa\xd]+ comment #.* linedir #line[ \t]+[0-9]+.* qstring \"((\\\")|[^"])*\"|\'((\\\')|[^'])*\'|`[^`]*` function [!a-zA-Z0-9_]+\({qstring}*[^)]*\) item [+]?[-.,!@a-zA-Z0-9_\200-\377]+ id [a-zA-Z0-9_\200-\377]+ lvalue [a-zA-Z0-9_\200-\377]+ classt [.|&!,;a-zA-Z0-9_()\200-\377]+:: option [a-z0-9]+=[^ \t\n]+ varobj [^ \t\n\xa\xd]+ newline ([\n]|[\xd][\xa]) lbrack \( rbrack \) lbrace \{ rbrace \} equals = forcearrow ->! lforcearrow \+>! arrow -> larrow \+> %% admit: { DaemonOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN CFSERVD; SetAction(admit); return ADMIT; } grant: { DaemonOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN CFSERVD; SetAction(admit); return ADMIT; } deny: { DaemonOnly; InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN CFSERVD; SetAction(deny); return DENY; } control: { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INCONTROL; SetAction(control); return CONTROL; } strategies: { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(strategies); return STRATEGIES; } groups: { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INCONTROL; SetAction(groups); return GROUPS; } classes: { /* Synonym for groups */ Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INCONTROL; SetAction(groups); return GROUPS; } acl: { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(acls); return ACL; } filters: { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(filters); return FILTERS; } {actiont} { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INITIAL; SetAction(ActionStringToCode(yytext)); return ACTIONTYPE; } import: { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INITIAL; SetAction(ActionStringToCode(yytext)); return ACTIONTYPE; } editfiles: { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(editfiles); return EDITFILES; } {newline} { LINENUMBER++; } {space} { } {linedir} { ResetLine((char *)yytext+6); } {comment} { } {lforcearrow} { Debug1("LFARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINKCHILDREN = true; FORCELINK='y'; return LARROW; } {forcearrow} { Debug1("FARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINK = true; FORCELINK='y'; return ARROW; } {arrow} { Debug1("ARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINK = true; FORCELINK='n'; return ARROW; } {larrow} { Debug1("LARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINKCHILDREN = true; FORCELINK='n'; return LARROW; } {equals} { Debug1("EQUALS %s\n",yytext); return EQUALS; } {classt} { Debug1("\nNEW CLASS PREDICATE:: %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ yytext[strlen((char *)yytext)-2] = '\0'; HandleClass(yytext); return PARSECLASS; } {lvalue} { Debug1("LVALUE %s\n",yytext); HandleLValue(yytext); return LVALUE; } {id}: { Debug1("BRACELIST-CLASSIFIER %s\n",yytext); HandleBraceObjectClassifier(yytext); return BCLASS; } {id} { Debug1("BRACELIST-ID %s\n",yytext); if (ACTION == editfiles) /* Syntax different for editfiles :( */ { HandleBraceObjectClassifier(yytext); } else { HandleBraceObjectID(yytext); } return ID; } {lbrack} { Debug1("LEFTBRACK\n"); BEGIN INASSIGN; return LBRACK; } {lbrace} { bzero(FILTERNAME,CF_BUFSIZE); /* Reset */ bzero(STRATEGYNAME,CF_BUFSIZE); /* Reset */ Debug1("LBRACE\n"); return LBRACE; } {rbrack} { Debug1("RIGHTBRACK\n\n"); /* If this is a method, load the received arguments as soon as possible */ if (!GOTMETHODARGS && (METHODARGS != NULL)) { Verbose("This looks like a private method, adding parameters.\n"); CheckForMethod(); GOTMETHODARGS = true; } BEGIN INCONTROL; return RBRACK; } {rbrace} { Debug1("RBRACE\n"); if (EDITGROUPLEVEL != 0) { yyerror("Editfiles Begin/End mismatch before or at line"); } if (SEARCHREPLACELEVEL != 0) { yyerror("ReplaceAll/With mismatch before or at line"); } if (FOREACHLEVEL != 0) { yyerror("ForEachLineIn/EndLoop mismatch before or at line"); } InstallPending(ACTION); InitializeAction(); return RBRACE; } {qstring} { char *sp = NULL; int less = 0; Debug1("RVAL-QSTRING %s\n",yytext); if ((sp = malloc(strlen(yytext)+1)) == NULL) { FatalError("Malloc failure in parsing"); } if((less = RemoveEscapeSequences(yytext,sp)) > 0) { Debug1("QSTRING-LESS %d\n",less); yyless(less); } switch (ACTION) { case control: InstallControlRValue(CURRENTITEM,sp); free(sp); return RVALUE; case groups: HandleGroupRValue(sp); free(sp); return RVALUE; } } {qstring} { char *sp = NULL; int less = 0; Debug1("QSTRING %s\n",yytext); if ((sp = malloc(strlen(yytext)+1)) == NULL) { FatalError("Malloc failure in parsing"); } if ((less = RemoveEscapeSequences(yytext,sp)) > 0) { Debug1("QSTRING-LESS %d\n",less); yyless(less); } HandleQuotedString(sp); free(sp); return QSTRING; } {function} { Debug1("RVAL-FUNCTION %s\n",yytext); HandleFunctionObject(yytext); return FUNCTION; } {function} { Debug1("FUNCTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ if (ACTION == alerts) { ACTIONPENDING = true; } HandleFunctionObject(yytext); return FUNCTION; } {option} { Debug1("\nOPTION %s\n",yytext); HandleOption(yytext); return OPTION; } {varobj} { Debug1("VAROBJ %s\n",yytext); if ((ACTION_IS_LINK || ACTION_IS_LINKCHILDREN) && (strlen(LINKTO)==0)) { Debug("Pending link destination...\n"); } else { /* Check anomalour process syntax */ if (ACTION == processes && (strcmp(ToLowerStr(yytext),"restart") == 0 || HAVE_RESTART || strcmp(ToLowerStr(yytext),"setoptionstring") == 0)) { } else if (ACTIONPENDING) { InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ } } IsVarString(yytext); /* Syntax check */ HandleVarObject(yytext); return VAROBJ; } {varobj} { Debug1("RVAL-VAROBJ %s\n",yytext); switch(ACTION) { case control: InstallControlRValue(CURRENTITEM,yytext); return RVALUE; case groups: HandleGroupRValue(yytext); return RVALUE; default: yyerror("Misplaced assignment"); } } {varobj} { Debug1("BRACELIST-VAROBJ %s\n",yytext); if (ACTION == acls && strlen(CURRENTOBJECT) > 0) /* Irregular acl syntax */ { HandleBraceObjectClassifier(yytext); } else { HandleBraceObjectID(yytext); } return VAROBJ; } {varobj} { Debug1("\nCFSERVD-VAROBJ %s\n",yytext); HandleServerRule(yytext); return ACCESSOBJ; } . { printf("Stray character (%s)",yytext); return yytext[0]; } %% /* EOF */ cfengine-2.2.10/src/rotate.c0000644000175000001440000000766110202123552012522 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*********************************************************************/ /* */ /* TOOLKITS: "rotate" library */ /* */ /*********************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include "../pub/global.h" /*********************************************************************/ void RotateFiles(char *name,int number) /* Rotates file extensions like in free bsd, messages, syslog */ /* etc. Note that this doesn't check for failure, since the */ /* aim is to disable the files anyway */ { int i, fd; struct Image dummy; struct stat statbuf; char filename[CF_BUFSIZE]; if (stat(name,&statbuf) == -1) { Verbose("No access to file %s\n",name); return; } for (i = number-1; i > 0; i--) { if (BufferOverflow(name,"1")) { CfLog(cferror,"Culprit: RotateFiles in Disable:\n",""); return; } snprintf(filename,CF_BUFSIZE,"%s.%d",name,i); snprintf(VBUFF,CF_BUFSIZE,"%s.%d",name, i+1); if (rename(filename,VBUFF) == -1) { Debug("Rename failed in RotateFiles %s -> %s\n",name,filename); } snprintf(filename,CF_BUFSIZE,"%s.%d.gz",name,i); snprintf(VBUFF,CF_BUFSIZE,"%s.%d.gz",name, i+1); if (rename(filename,VBUFF) == -1) { Debug("Rename failed in RotateFiles %s -> %s\n",name,filename); } snprintf(filename,CF_BUFSIZE,"%s.%d.Z",name,i); snprintf(VBUFF,CF_BUFSIZE,"%s.%d.Z",name, i+1); if (rename(filename,VBUFF) == -1) { Debug("Rename failed in RotateFiles %s -> %s\n",name,filename); } snprintf(filename,CF_BUFSIZE,"%s.%d.bz",name,i); snprintf(VBUFF,CF_BUFSIZE,"%s.%d.bz",name, i+1); if (rename(filename,VBUFF) == -1) { Debug("Rename failed in RotateFiles %s -> %s\n",name,filename); } snprintf(filename,CF_BUFSIZE,"%s.%d.bz2",name,i); snprintf(VBUFF,CF_BUFSIZE,"%s.%d.bz2",name, i+1); if (rename(filename,VBUFF) == -1) { Debug("Rename failed in RotateFiles %s -> %s\n",name,filename); } } snprintf(VBUFF,CF_BUFSIZE,"%s.1",name); dummy.server = "localhost"; dummy.inode_cache = NULL; dummy.cache = NULL; dummy.stealth = 'n'; dummy.encrypt = 'n'; dummy.preservetimes = 'n'; if (CopyRegDisk(name,VBUFF,&dummy) == -1) { Debug2("cfengine: copy failed in RotateFiles %s -> %s\n",name,VBUFF); } chmod(VBUFF,statbuf.st_mode); chown(VBUFF,statbuf.st_uid,statbuf.st_gid); chmod(name,0600); /* File must be writable to empty ..*/ if ((fd = creat(name,statbuf.st_mode)) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Failed to create new %s in disable(rotate)\n",name); CfLog(cferror,OUTPUT,"creat"); } else { chown(name,statbuf.st_uid,statbuf.st_gid); /* NT doesn't have fchown */ fchmod(fd,statbuf.st_mode); close(fd); } } cfengine-2.2.10/src/nameinfo.c0000644000175000001440000006545211141260464013031 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*********************************************************************/ /* */ /* TOOLKITS: "object" library */ /* */ /*********************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include "../pub/global.h" #ifdef IRIX #include #endif #ifdef _AIX #include #endif #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN # ifdef _SIZEOF_ADDR_IFREQ # define SIZEOF_IFREQ(x) _SIZEOF_ADDR_IFREQ(x) # else # define SIZEOF_IFREQ(x) \ ((x).ifr_addr.sa_len > sizeof(struct sockaddr) ? \ (sizeof(struct ifreq) - sizeof(struct sockaddr) + \ (x).ifr_addr.sa_len) : sizeof(struct ifreq)) # endif #else # define SIZEOF_IFREQ(x) sizeof(struct ifreq) #endif /*******************************************************************/ void GetNameInfo() { int i,found = false; char *sp,*sp2; time_t tloc; struct hostent *hp; struct sockaddr_in cin; #ifdef AIX char real_version[_SYS_NMLN]; #endif #ifdef IRIX char real_version[256]; /* see */ #endif #ifdef HAVE_SYSINFO long sz; #endif Debug("GetNameInfo()\n"); VFQNAME[0] = VUQNAME[0] = '\0'; if (uname(&VSYSNAME) == -1) { perror("uname "); FatalError("Uname couldn't get kernel name info!!\n"); } #ifdef AIX snprintf(real_version,_SYS_NMLN,"%.80s.%.80s", VSYSNAME.version, VSYSNAME.release); strncpy(VSYSNAME.release, real_version, _SYS_NMLN); #elif defined IRIX /* This gets us something like `6.5.19m' rather than just `6.5'. */ syssgi (SGI_RELEASE_NAME, 256, real_version); #endif for (sp = VSYSNAME.sysname; *sp != '\0'; sp++) { *sp = ToLower(*sp); } for (sp = VSYSNAME.machine; *sp != '\0'; sp++) { *sp = ToLower(*sp); } #ifdef _AIX switch (_system_configuration.architecture) { case POWER_RS: strncpy(VSYSNAME.machine, "power", _SYS_NMLN); break; case POWER_PC: strncpy(VSYSNAME.machine, "powerpc", _SYS_NMLN); break; case IA64: strncpy(VSYSNAME.machine, "ia64", _SYS_NMLN); break; } #endif for (i = 0; CLASSATTRIBUTES[i][0] != '\0'; i++) { if (WildMatch(CLASSATTRIBUTES[i][0],ToLowerStr(VSYSNAME.sysname))) { if (WildMatch(CLASSATTRIBUTES[i][1],VSYSNAME.machine)) { if (WildMatch(CLASSATTRIBUTES[i][2],VSYSNAME.release)) { if (UNDERSCORE_CLASSES) { snprintf(VBUFF,CF_BUFSIZE,"_%s",CLASSTEXT[i]); AddClassToHeap(VBUFF); } else { AddClassToHeap(CLASSTEXT[i]); } found = true; VSYSTEMHARDCLASS = (enum classes) i; break; } } else { Debug2("Cfengine: I recognize %s but not %s\n",VSYSNAME.sysname,VSYSNAME.machine); continue; } } } if ((sp = malloc(strlen(VSYSNAME.nodename)+1)) == NULL) { FatalError("malloc failure in initialize()"); } strcpy(sp,VSYSNAME.nodename); SetDomainName(sp); strncpy(VUQNAME,sp,MAXHOSTNAMELEN); /* Default assume non-qualified kernel name, correct below */ for (sp2=sp; *sp2 != '\0'; sp2++) /* Truncate fully qualified name */ { if (*sp2 == '.') { *sp2 = '\0'; Debug("Truncating fully qualified hostname %s to %s\n",VSYSNAME.nodename,sp); strncpy(VUQNAME,sp,MAXHOSTNAMELEN); break; } } VDEFAULTBINSERVER.name = sp; AddClassToHeap(CanonifyName(sp)); free(sp); /* Release the ressource */ if ((tloc = time((time_t *)NULL)) == -1) { printf("Couldn't read system clock\n"); } if (VERBOSE || DEBUG || D2 || D3) { if (UNDERSCORE_CLASSES) { snprintf(VBUFF,CF_BUFSIZE,"_%s",CLASSTEXT[i]); } else { snprintf(VBUFF,CF_BUFSIZE,"%s",CLASSTEXT[i]); } if (ISCFENGINE) { printf ("GNU Configuration Engine - \n%s\n%s\n\n",VERSION,COPYRIGHT); } else { printf ("GNU Cfengine server daemon - \n%s\n%s\n\n",VERSION,COPYRIGHT); } printf ("------------------------------------------------------------------------\n\n"); printf ("Host name is: %s\n",VSYSNAME.nodename); printf ("Operating System Type is %s\n",VSYSNAME.sysname); printf ("Operating System Release is %s\n",VSYSNAME.release); printf ("Architecture = %s\n\n\n",VSYSNAME.machine); printf ("Using internal soft-class %s for host %s\n\n",VBUFF,CLASSTEXT[VSYSTEMHARDCLASS]); printf ("The time is now %s\n\n",ctime(&tloc)); printf ("------------------------------------------------------------------------\n\n"); } sprintf(VBUFF,"%d_bit",sizeof(long)*8); AddClassToHeap(VBUFF); Verbose("Additional hard class defined as: %s\n",CanonifyName(VBUFF)); snprintf(VBUFF,CF_BUFSIZE,"%s_%s",VSYSNAME.sysname,VSYSNAME.release); AddClassToHeap(CanonifyName(VBUFF)); #ifdef IRIX /* Get something like `irix64_6_5_19m' defined as well as `irix64_6_5'. Just copying the latter into VSYSNAME.release wouldn't be backwards-compatible. */ snprintf(VBUFF,CF_BUFSIZE,"%s_%s",VSYSNAME.sysname,real_version); AddClassToHeap(CanonifyName(VBUFF)); #endif AddClassToHeap(CanonifyName(VSYSNAME.machine)); Verbose("Additional hard class defined as: %s\n",CanonifyName(VBUFF)); snprintf(VBUFF,CF_BUFSIZE,"%s_%s",VSYSNAME.sysname,VSYSNAME.machine); AddClassToHeap(CanonifyName(VBUFF)); Verbose("Additional hard class defined as: %s\n",CanonifyName(VBUFF)); snprintf(VBUFF,CF_BUFSIZE,"%s_%s_%s",VSYSNAME.sysname,VSYSNAME.machine,VSYSNAME.release); AddClassToHeap(CanonifyName(VBUFF)); Verbose("Additional hard class defined as: %s\n",CanonifyName(VBUFF)); #ifdef HAVE_SYSINFO #ifdef SI_ARCHITECTURE sz = sysinfo(SI_ARCHITECTURE,VBUFF,CF_BUFSIZE); if (sz == -1) { Verbose("cfengine internal: sysinfo returned -1\n"); } else { AddClassToHeap(CanonifyName(VBUFF)); Verbose("Additional hard class defined as: %s\n",VBUFF); } #endif #ifdef SI_PLATFORM sz = sysinfo(SI_PLATFORM,VBUFF,CF_BUFSIZE); if (sz == -1) { Verbose("cfengine internal: sysinfo returned -1\n"); } else { AddClassToHeap(CanonifyName(VBUFF)); Verbose("Additional hard class defined as: %s\n",VBUFF); } #endif #endif snprintf(VBUFF,CF_BUFSIZE,"%s_%s_%s_%s",VSYSNAME.sysname,VSYSNAME.machine,VSYSNAME.release,VSYSNAME.version); if (strlen(VBUFF) < CF_MAXVARSIZE-2) { VARCH = strdup(CanonifyName(VBUFF)); } else { Verbose("cfengine internal: $(arch) overflows CF_MAXVARSIZE! Truncating\n"); VARCH = strdup(CanonifyName(VSYSNAME.sysname)); } snprintf(VBUFF,CF_BUFSIZE,"%s_%s",VSYSNAME.sysname,VSYSNAME.machine); VARCH2 = strdup(CanonifyName(VBUFF)); AddClassToHeap(VARCH); Verbose("Additional hard class defined as: %s\n",VARCH); if (! found) { CfLog(cferror,"Cfengine: I don't understand what architecture this is!",""); } strcpy(VBUFF,"compiled_on_"); strcat(VBUFF,CanonifyName(AUTOCONF_SYSNAME)); AddClassToHeap(CanonifyName(VBUFF)); Verbose("\nGNU autoconf class from compile time: %s\n\n",VBUFF); /* Get IP address from nameserver */ if ((hp = gethostbyname(VSYSNAME.nodename)) == NULL) { return; } else { memset(&cin,0,sizeof(cin)); cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; Verbose("Address given by nameserver: %s\n",inet_ntoa(cin.sin_addr)); strcpy(VIPADDRESS,inet_ntoa(cin.sin_addr)); for (i=0; hp->h_aliases[i]!= NULL; i++) { Debug("Adding alias %s..\n",hp->h_aliases[i]); AddClassToHeap(CanonifyName(hp->h_aliases[i])); } } } /*********************************************************************/ void GetInterfaceInfo(void) { int fd,len,i,j,first_address; struct ifreq ifbuf[CF_IFREQ],ifr, *ifp; struct ifconf list; struct sockaddr_in *sin; struct hostent *hp; char *sp; char ip[CF_MAXVARSIZE]; char name[CF_BUFSIZE]; char last_name[CF_BUFSIZE]; Debug("GetInterfaceInfo()\n"); last_name[0] = '\0'; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { CfLog(cferror,"Couldn't open socket","socket"); exit(1); } list.ifc_len = sizeof(ifbuf); list.ifc_req = ifbuf; #ifdef SIOCGIFCONF if (ioctl(fd, SIOCGIFCONF, &list) == -1 || (list.ifc_len < (sizeof(struct ifreq)))) #else if (ioctl(fd, OSIOCGIFCONF, &list) == -1 || (list.ifc_len < (sizeof(struct ifreq)))) #endif { CfLog(cferror,"Couldn't get interfaces - old kernel? Try setting CF_IFREQ to 1024","ioctl"); exit(1); } for (j = 0,len = 0,ifp = list.ifc_req; len < list.ifc_len; len+=SIZEOF_IFREQ(*ifp),j++,ifp=(struct ifreq *)((char *)ifp+SIZEOF_IFREQ(*ifp))) { if (ifp->ifr_addr.sa_family == 0) { continue; } Verbose("Interface %d: %s\n", j+1, ifp->ifr_name); /* Chun Tian (binghe) : use a last_name to detect whether current address is a interface's first address: if current ifr_name = last_name, it's not the first address of current interface. */ if (strncmp(last_name,ifp->ifr_name,sizeof(ifp->ifr_name)) == 0) { first_address = false; } else { first_address = true; } strncpy(last_name,ifp->ifr_name,sizeof(ifp->ifr_name)); if (UNDERSCORE_CLASSES) { snprintf(VBUFF, CF_BUFSIZE, "_net_iface_%s", CanonifyName(ifp->ifr_name)); } else { snprintf(VBUFF, CF_BUFSIZE, "net_iface_%s", CanonifyName(ifp->ifr_name)); } AddClassToHeap(VBUFF); if (ifp->ifr_addr.sa_family == AF_INET) { strncpy(ifr.ifr_name,ifp->ifr_name,sizeof(ifp->ifr_name)); if (ioctl(fd,SIOCGIFFLAGS,&ifr) == -1) { CfLog(cferror,"No such network device","ioctl"); close(fd); return; } /* Used to check if interface was "up" if ((ifr.ifr_flags & IFF_UP) && !(ifr.ifr_flags & IFF_LOOPBACK)) Now check whether it is configured ... */ if ((ifr.ifr_flags & IFF_BROADCAST) && !(ifr.ifr_flags & IFF_LOOPBACK)) { sin=(struct sockaddr_in *)&ifp->ifr_addr; if ((hp = gethostbyaddr((char *)&(sin->sin_addr.s_addr),sizeof(sin->sin_addr.s_addr),AF_INET)) == NULL) { Debug("Host information for %s not found\n", inet_ntoa(sin->sin_addr)); } else { if (hp->h_name != NULL) { Debug("Adding hostip %s..\n",inet_ntoa(sin->sin_addr)); AddClassToHeap(CanonifyName(inet_ntoa(sin->sin_addr))); Debug("Adding hostname %s..\n",hp->h_name); AddClassToHeap(CanonifyName(hp->h_name)); if (hp->h_aliases != NULL) { for (i=0; hp->h_aliases[i] != NULL; i++) { Debug("Adding alias %s..\n",hp->h_aliases[i]); AddClassToHeap(CanonifyName(hp->h_aliases[i])); } } } } /* Old style compat */ strcpy(ip,inet_ntoa(sin->sin_addr)); AppendItem(&IPADDRESSES,ip,""); for (sp = ip+strlen(ip)-1; *sp != '.'; sp--) { } *sp = '\0'; AddClassToHeap(CanonifyName(ip)); /* New style classes */ strcpy(ip,"ipv4_"); strcat(ip,inet_ntoa(sin->sin_addr)); AddClassToHeap(CanonifyName(ip)); for (sp = ip+strlen(ip)-1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; AddClassToHeap(CanonifyName(ip)); } } /* Matching variables */ if (first_address) { strcpy(ip,inet_ntoa(sin->sin_addr)); snprintf(name,CF_MAXVARSIZE-1,"ipv4[%s]",CanonifyName(ifp->ifr_name)); AddMacroValue(CONTEXTID,name,ip); i = 3; for (sp = ip+strlen(ip)-1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; snprintf(name,CF_MAXVARSIZE-1,"ipv4_%d[%s]",i--,CanonifyName(ifp->ifr_name)); AddMacroValue(CONTEXTID,name,ip); } } } } } } close(fd); } /*********************************************************************/ void DeleteInterfaceInfo(char *regexp) { int fd,len,i,j,ret; struct ifreq ifbuf[CF_IFREQ],ifr, *ifp; struct ifconf list; struct sockaddr_in *sin; struct hostent *hp; char *sp; char ip[CF_MAXVARSIZE]; char name[CF_BUFSIZE]; regex_t rx; regmatch_t pmatch; Verbose("IgnoreInterfaceRegex %s\n\n",regexp); if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { CfLog(cferror,"Couldn't open socket","socket"); exit(1); } if ((ret = regcomp(&rx,regexp,REG_EXTENDED)) != 0) { regerror(ret,&rx,name,1023); snprintf(OUTPUT,CF_BUFSIZE,"Regular expression error %d for %s: %s\n",ret,regexp,name); yyerror(OUTPUT); return; } list.ifc_len = sizeof(ifbuf); list.ifc_req = ifbuf; #ifdef SIOCGIFCONF if (ioctl(fd, SIOCGIFCONF, &list) == -1 || (list.ifc_len < (sizeof(struct ifreq)))) #else if (ioctl(fd, OSIOCGIFCONF, &list) == -1 || (list.ifc_len < (sizeof(struct ifreq)))) #endif { CfLog(cferror,"Couldn't get interfaces - old kernel? Try setting CF_IFREQ to 1024","ioctl"); exit(1); } for (j = 0,len = 0,ifp = list.ifc_req; len < list.ifc_len; len+=SIZEOF_IFREQ(*ifp),j++,ifp=(struct ifreq *)((char *)ifp+SIZEOF_IFREQ(*ifp))) { if (ifp->ifr_addr.sa_family == 0) { continue; } if (regexec(&rx,ifp->ifr_name,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ifp->ifr_name))) { Verbose("Deleting interface info for %s\n",ifp->ifr_name); } else { continue; } } Debug("Interface %d: %s\n", j+1, ifp->ifr_name); if (UNDERSCORE_CLASSES) { snprintf(VBUFF, CF_BUFSIZE, "_net_iface_%s", CanonifyName(ifp->ifr_name)); } else { snprintf(VBUFF, CF_BUFSIZE, "net_iface_%s", CanonifyName(ifp->ifr_name)); } DeleteClassFromHeap(VBUFF); if (ifp->ifr_addr.sa_family == AF_INET) { strncpy(ifr.ifr_name,ifp->ifr_name,sizeof(ifp->ifr_name)); if (ioctl(fd,SIOCGIFFLAGS,&ifr) == -1) { CfLog(cferror,"No such network device","ioctl"); close(fd); return; } /* Used to check if interface was "up" if ((ifr.ifr_flags & IFF_UP) && !(ifr.ifr_flags & IFF_LOOPBACK)) Now check whether it is configured ... */ if ((ifr.ifr_flags & IFF_BROADCAST) && !(ifr.ifr_flags & IFF_LOOPBACK)) { sin=(struct sockaddr_in *)&ifp->ifr_addr; if ((hp = gethostbyaddr((char *)&(sin->sin_addr.s_addr),sizeof(sin->sin_addr.s_addr),AF_INET)) == NULL) { Debug("Host information for %s not found\n", inet_ntoa(sin->sin_addr)); } else { if (hp->h_name != NULL) { Debug("Deleting hostip %s..\n",inet_ntoa(sin->sin_addr)); DeleteClassFromHeap(CanonifyName(inet_ntoa(sin->sin_addr))); Debug("Deleting hostname %s..\n",hp->h_name); DeleteClassFromHeap(CanonifyName(hp->h_name)); if (hp->h_aliases != NULL) { for (i=0; hp->h_aliases[i] != NULL; i++) { Debug("Deleting alias %s..\n",hp->h_aliases[i]); DeleteClassFromHeap(CanonifyName(hp->h_aliases[i])); } } } } /* Old style compat */ strcpy(ip,inet_ntoa(sin->sin_addr)); DeleteItemLiteral(&IPADDRESSES,ip); for (sp = ip+strlen(ip)-1; *sp != '.'; sp--) { } *sp = '\0'; DeleteClassFromHeap(CanonifyName(ip)); /* New style classes */ strcpy(ip,"ipv4_"); strcat(ip,inet_ntoa(sin->sin_addr)); DeleteClassFromHeap(CanonifyName(ip)); for (sp = ip+strlen(ip)-1; (sp > ip); sp--) { if (*sp == '.') { *sp = '\0'; DeleteClassFromHeap(CanonifyName(ip)); } } } } } close(fd); } /*********************************************************************/ void GetV6InterfaceInfo(void) { FILE *pp; char buffer[CF_BUFSIZE]; /* Whatever the manuals might say, you cannot get IPV6 interface configuration from the ioctls. This seems to be implemented in a non standard way across OSes BSDi has done getifaddrs(), solaris 8 has a new ioctl, Stevens book shows the suggestion which has not been implemented... */ Verbose("Trying to locate my IPv6 address\n"); switch (VSYSTEMHARDCLASS) { case cfnt: /* NT cannot do this */ return; case irix: case irix4: case irix64: if ((pp = cfpopen("/usr/etc/ifconfig -a","r")) == NULL) { Verbose("Could not find interface info\n"); return; } break; case hp: if ((pp = cfpopen("/usr/sbin/ifconfig -a","r")) == NULL) { Verbose("Could not find interface info\n"); return; } break; case aix: if ((pp = cfpopen("/etc/ifconfig -a","r")) == NULL) { Verbose("Could not find interface info\n"); return; } break; default: if ((pp = cfpopen("/sbin/ifconfig -a","r")) == NULL) { Verbose("Could not find interface info\n"); return; } } /* Don't know the output format of ifconfig on all these .. hope for the best*/ while (!feof(pp)) { fgets(buffer,CF_BUFSIZE-1,pp); if (ferror(pp)) /* abortable */ { break; } if (StrStr(buffer,"inet6")) { struct Item *ip,*list = NULL; char *sp; list = SplitStringAsItemList(buffer,' '); for (ip = list; ip != NULL; ip=ip->next) { for (sp = ip->name; *sp != '\0'; sp++) { if (*sp == '/') /* Remove CIDR mask */ { *sp = '\0'; } } if (IsIPV6Address(ip->name) && (strcmp(ip->name,"::1") != 0)) { Verbose("Found IPv6 address %s\n",ip->name); AppendItem(&IPADDRESSES,ip->name,""); AddClassToHeap(CanonifyName(ip->name)); } } DeleteItemList(list); } } cfpclose(pp); } /*********************************************************************/ void AddNetworkClass(char *netmask) /* Function contrib David Brownlee */ { struct in_addr ip,nm; char *sp,nmbuf[CF_MAXVARSIZE],ipbuf[CF_MAXVARSIZE]; /* * Has to differentiate between cases such as: * 192.168.101.1/24 -> 192.168.101 and * 192.168.101.1/26 -> 192.168.101.0 * We still have the, um... 'interesting' Class C default Network Class * set by GetNameInfo() */ /* This is also a convenient method to ensure valid dotted quad */ if ((nm.s_addr = inet_addr(netmask)) != -1 && (ip.s_addr = inet_addr(VIPADDRESS)) != -1) { ip.s_addr &= nm.s_addr; /* Will not work with IPv6 */ strcpy(ipbuf,inet_ntoa(ip)); strcpy(nmbuf,inet_ntoa(nm)); while( (sp = strrchr(nmbuf,'.')) && strcmp(sp,".0") == 0 ) { *sp = 0; *strrchr(ipbuf,'.') = 0; } AddClassToHeap(CanonifyName(ipbuf)); } } /*********************************************************************/ void SetDomainName(char *hostname) { char fqn[CF_MAXVARSIZE]; char *ptr; char buffer[CF_BUFSIZE]; strcpy(VFQNAME,hostname); /* By default VFQNAME = hostname (nodename) */ if (strstr(VFQNAME,".") == 0) { /* The nodename is not full qualified - try to find the FQDN hostname */ if (gethostname(fqn, sizeof(fqn)) != -1) { struct hostent *hp; if (hp = gethostbyname(fqn)) { if (strstr(hp->h_name,".")) { /* We find a FQDN hostname So we change the VFQNAME variable */ strncpy(VFQNAME,hp->h_name,CF_MAXVARSIZE); VFQNAME[CF_MAXVARSIZE-1]= '\0'; } } } } strcpy(buffer,VFQNAME); AddClassToHeap(CanonifyName(buffer)); AddClassToHeap(CanonifyName(ToLowerStr(buffer))); if (strstr(VFQNAME,".")) { /* If VFQNAME is full qualified we can create VDOMAIN variable */ ptr = strchr(VFQNAME, '.'); strcpy(VDOMAIN, ++ptr); DeleteClassFromHeap("undefined_domain"); } if (strstr(VFQNAME,".") == 0 && (strcmp(VDOMAIN,CF_START_DOMAIN) != 0)) { strcat(VFQNAME,"."); strcat(VFQNAME,VDOMAIN); } if (strstr(VFQNAME,".")) { /* Add some domain hierarchy classes */ for (ptr=VFQNAME; *ptr != '\0'; ptr++) { if (*ptr == '.') { if (*(ptr+1) != '\0') { Debug("Defining domain #%s#\n",(ptr+1)); AddClassToHeap(CanonifyName(ptr+1)); } else { Debug("Domain rejected\n"); } } } } AddClassToHeap(CanonifyName(VDOMAIN)); } /*******************************************************************/ void SetReferenceTime(int setclasses) { time_t tloc; char vbuff[CF_BUFSIZE]; if ((tloc = time((time_t *)NULL)) == -1) { CfLog(cferror,"Couldn't read system clock\n",""); } CFSTARTTIME = tloc; snprintf(vbuff,CF_BUFSIZE,"%s",ctime(&tloc)); Verbose("Reference time set to %s\n",ctime(&tloc)); if (setclasses) { AddTimeClass(vbuff); } } /*******************************************************************/ void SetStartTime(int setclasses) { time_t tloc; if ((tloc = time((time_t *)NULL)) == -1) { CfLog(cferror,"Couldn't read system clock\n",""); } CFINITSTARTTIME = tloc; Debug("Job start time set to %s\n",ctime(&tloc)); } /*******************************************************************/ void BuildClassEnvironment() { struct Item *ip; int size = 0; char file[CF_BUFSIZE], *sp; FILE *fp; DB *dbp; DB_ENV *dbenv = NULL; Debug("(BuildClassEnvironment)\n"); snprintf(ALLCLASSBUFFER,CF_BUFSIZE,"%s=",CF_ALLCLASSESVAR); if (!IsPrivileged()) { Verbose("\n(Non privileged user...)\n\n"); if ((sp = getenv("HOME")) == NULL) { FatalError("You do not have a HOME variable pointing to your home directory"); } snprintf(file,CF_BUFSIZE,"%s/.cfagent/allclasses",sp); } else { snprintf(file,CF_BUFSIZE,"%s/state/allclasses",WORKDIR); } if ((fp = fopen(file,"w")) == NULL) { CfLog(cfinform,"Could not open allclasses cache file",""); return; } for (ip = VHEAP; ip != NULL; ip=ip->next) { if (IsDefinedClass(ip->name)) { if ((size += strlen(ip->name)) > CF_ALLCLASSSIZE - CF_BUFFERMARGIN) { Verbose("Class buffer overflowed, dumping class environment for modules\n"); Verbose("This would probably crash the exec interface on most machines\n"); } else { size++; /* Allow for : separator */ strcat(ALLCLASSBUFFER,ip->name); strcat(ALLCLASSBUFFER,":"); } fprintf(fp,"%s\n",ip->name); } } for (ip = VALLADDCLASSES; ip != NULL; ip=ip->next) { if (IsDefinedClass(ip->name)) { if ((size += strlen(ip->name)) > 4*CF_BUFSIZE - CF_BUFFERMARGIN) { Verbose("Class buffer overflowed, dumping class environment for modules\n"); Verbose("This would probably crash the exec interface on most machines\n"); } else { size++; /* Allow for : separator */ strcat(ALLCLASSBUFFER,ip->name); strcat(ALLCLASSBUFFER,":"); } fprintf(fp,"%s\n",ip->name); } } Debug2("---\nENVIRONMENT: %s\n---\n",ALLCLASSBUFFER); if (USEENVIRON) { if (putenv(ALLCLASSBUFFER) == -1) { perror("putenv"); } } fclose(fp); } /*******************************************************************/ void GetEnvironment() { char env[CF_BUFSIZE],class[CF_BUFSIZE],name[CF_MAXVARSIZE],value[CF_MAXVARSIZE]; FILE *fp; struct stat statbuf; time_t now = time(NULL); Verbose("Looking for environment from cfenvd...\n"); snprintf(env,CF_BUFSIZE,"%s/state/%s",CFWORKDIR,CF_ENV_FILE); if (stat(env,&statbuf) == -1) { Verbose("\nUnable to detect environment from cfenvd\n\n"); return; } if (statbuf.st_mtime < (now - 60*60)) { Verbose("Environment data are too old - discarding\n"); unlink(env); return; } if (!GetMacroValue(CONTEXTID,"env_time")) { snprintf(value,CF_MAXVARSIZE-1,"%s",ctime(&statbuf.st_mtime)); Chop(value); AddMacroValue(CONTEXTID,"env_time",value); } else { CfLog(cferror,"Reserved variable $(env_time) in use",""); } Verbose("Loading environment...\n"); if ((fp = fopen(env,"r")) == NULL) { Verbose("\nUnable to detect environment from cfenvd\n\n"); return; } while (!feof(fp)) { class[0] = '\0'; name[0] = '\0'; value[0] = '\0'; fgets(class,CF_BUFSIZE-1,fp); if (feof(fp)) { break; } if (strstr(class,"=")) { sscanf(class,"%255[^=]=%255[^\n]",name,value); if (!GetMacroValue(CONTEXTID,name)) { AddMacroValue(CONTEXTID,name,value); } } else { AddClassToHeap(class); } } fclose(fp); Verbose("Environment data loaded\n\n"); if (IsDefinedClass("nt")) { AddClassToHeap("windows"); } if (VERBOSE) { AddClassToHeap("verbose_mode"); } if (INFORM) { AddClassToHeap("inform_mode"); } if (DEBUG) { AddClassToHeap("debug_mode"); } } cfengine-2.2.10/src/cflex.l.in0000644000175000001440000004272711120756555012764 00000000000000%{ /* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* LEXER for cfengine */ /* */ /* */ /*******************************************************************/ #include "cfparse.h" #include "cf.defs.h" #include "cf.extern.h" /* Note the %o %a declarations to allow more internal workspace */ %} @NOWRAP@ %s INCONTROL BRACELIST INASSIGN CFSERVD %o 60000 %a 40000 %p 20000 %n 2000 actiont copy:|resolve:|files:|tidy:|homeservers:|binservers:|mailserver:|disks:|mountables:|links:|shellcommands:|disable:|directories:|ignore:|interfaces:|defaultroute:|miscmounts:|unmount:|processes:|required:|broadcast:|alerts:|packages:|methods:|rename:|scli: space [ \t\xa\xd]+ comment #.* linedir #line[ \t]+[0-9]+.* qstring \"((\\\")|[^"])*\"|\'((\\\')|[^'])*\'|`[^`]*` function [!a-zA-Z0-9_]+\({qstring}*[^)]*\) item [+]?[-.,!@a-zA-Z0-9_@EIGHTBIT@]+ id [a-zA-Z0-9_@EIGHTBIT@]+ lvalue [a-zA-Z0-9_@EIGHTBIT@]+ classt [.|&!,;a-zA-Z0-9_()@EIGHTBIT@]+:: option [a-z0-9]+=[^ \t\n]+ varobj [^ \t\n\xa\xd]+ newline ([\n]|[\xd][\xa]) lbrack \( rbrack \) lbrace \{ rbrace \} equals = forcearrow ->! lforcearrow \+>! arrow -> larrow \+> %% admit: { DaemonOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN CFSERVD; SetAction(admit); return ADMIT; } grant: { DaemonOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN CFSERVD; SetAction(admit); return ADMIT; } deny: { DaemonOnly; InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN CFSERVD; SetAction(deny); return DENY; } control: { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INCONTROL; SetAction(control); return CONTROL; } strategies: { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(strategies); return STRATEGIES; } groups: { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INCONTROL; SetAction(groups); return GROUPS; } classes: { /* Synonym for groups */ Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INCONTROL; SetAction(groups); return GROUPS; } acl: { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(acls); return ACL; } filters: { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(filters); return FILTERS; } {actiont} { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INITIAL; SetAction(ActionStringToCode(yytext)); return ACTIONTYPE; } import: { Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN INITIAL; SetAction(ActionStringToCode(yytext)); return ACTIONTYPE; } editfiles: { CfengineOnly; Debug1("NEW ACTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ BEGIN BRACELIST; SetAction(editfiles); return EDITFILES; } {newline} { LINENUMBER++; } {space} { } {linedir} { ResetLine((char *)yytext+6); } {comment} { } {lforcearrow} { Debug1("LFARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINKCHILDREN = true; FORCELINK='y'; return LARROW; } {forcearrow} { Debug1("FARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINK = true; FORCELINK='y'; return ARROW; } {arrow} { Debug1("ARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINK = true; FORCELINK='n'; return ARROW; } {larrow} { Debug1("LARROW %s\n",yytext); strcpy(LINKFROM,CURRENTOBJECT); ACTION_IS_LINKCHILDREN = true; FORCELINK='n'; return LARROW; } {equals} { Debug1("EQUALS %s\n",yytext); return EQUALS; } {classt} { Debug1("\nNEW CLASS PREDICATE:: %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ yytext[strlen((char *)yytext)-2] = '\0'; HandleClass(yytext); return PARSECLASS; } {lvalue} { Debug1("LVALUE %s\n",yytext); HandleLValue(yytext); return LVALUE; } {id}: { Debug1("BRACELIST-CLASSIFIER %s\n",yytext); HandleBraceObjectClassifier(yytext); return BCLASS; } {id} { Debug1("BRACELIST-ID %s\n",yytext); if (ACTION == editfiles) /* Syntax different for editfiles :( */ { HandleBraceObjectClassifier(yytext); } else { HandleBraceObjectID(yytext); } return ID; } {lbrack} { Debug1("LEFTBRACK\n"); BEGIN INASSIGN; return LBRACK; } {lbrace} { bzero(FILTERNAME,CF_BUFSIZE); /* Reset */ bzero(STRATEGYNAME,CF_BUFSIZE); /* Reset */ Debug1("LBRACE\n"); return LBRACE; } {rbrack} { Debug1("RIGHTBRACK\n\n"); /* If this is a method, load the received arguments as soon as possible */ if (!GOTMETHODARGS && (METHODARGS != NULL)) { Verbose("This looks like a private method, adding parameters.\n"); CheckForMethod(); GOTMETHODARGS = true; } BEGIN INCONTROL; return RBRACK; } {rbrace} { Debug1("RBRACE\n"); if (EDITGROUPLEVEL != 0) { yyerror("Editfiles Begin/End mismatch before or at line"); } if (SEARCHREPLACELEVEL != 0) { yyerror("ReplaceAll/With mismatch before or at line"); } if (FOREACHLEVEL != 0) { yyerror("ForEachLineIn/EndLoop mismatch before or at line"); } InstallPending(ACTION); InitializeAction(); return RBRACE; } {qstring} { char *sp = NULL; int less = 0; Debug1("RVAL-QSTRING %s\n",yytext); if ((sp = malloc(strlen(yytext)+1)) == NULL) { FatalError("Malloc failure in parsing"); } if((less = RemoveEscapeSequences(yytext,sp)) > 0) { Debug1("QSTRING-LESS %d\n",less); yyless(less); } switch (ACTION) { case control: InstallControlRValue(CURRENTITEM,sp); free(sp); return RVALUE; case groups: HandleGroupRValue(sp); free(sp); return RVALUE; } } {qstring} { char *sp = NULL; int less = 0; Debug1("QSTRING %s\n",yytext); if ((sp = malloc(strlen(yytext)+1)) == NULL) { FatalError("Malloc failure in parsing"); } if ((less = RemoveEscapeSequences(yytext,sp)) > 0) { Debug1("QSTRING-LESS %d\n",less); yyless(less); } HandleQuotedString(sp); free(sp); return QSTRING; } {function} { Debug1("RVAL-FUNCTION %s\n",yytext); HandleFunctionObject(yytext); return FUNCTION; } {function} { Debug1("FUNCTION %s\n",yytext); InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ if (ACTION == alerts) { ACTIONPENDING = true; } HandleFunctionObject(yytext); return FUNCTION; } {option} { Debug1("\nOPTION %s\n",yytext); HandleOption(yytext); return OPTION; } {varobj} { Debug1("VAROBJ %s\n",yytext); if ((ACTION_IS_LINK || ACTION_IS_LINKCHILDREN) && (strlen(LINKTO)==0)) { Debug("Pending link destination...\n"); } else { /* Check anomalour process syntax */ if (ACTION == processes && (strcmp(ToLowerStr(yytext),"restart") == 0 || HAVE_RESTART || strcmp(ToLowerStr(yytext),"setoptionstring") == 0)) { } else if (ACTIONPENDING) { InstallPending(ACTION); /* Flush any existing actions */ InitializeAction(); /* Clear data for files/dirs */ } } IsVarString(yytext); /* Syntax check */ HandleVarObject(yytext); return VAROBJ; } {varobj} { Debug1("RVAL-VAROBJ %s\n",yytext); switch(ACTION) { case control: InstallControlRValue(CURRENTITEM,yytext); return RVALUE; case groups: HandleGroupRValue(yytext); return RVALUE; default: yyerror("Misplaced assignment"); } } {varobj} { Debug1("BRACELIST-VAROBJ %s\n",yytext); if (ACTION == acls && strlen(CURRENTOBJECT) > 0) /* Irregular acl syntax */ { HandleBraceObjectClassifier(yytext); } else { HandleBraceObjectID(yytext); } return VAROBJ; } {varobj} { Debug1("\nCFSERVD-VAROBJ %s\n",yytext); HandleServerRule(yytext); return ACCESSOBJ; } . { printf("Stray character (%s)",yytext); return yytext[0]; } %% /* EOF */ cfengine-2.2.10/src/state.c0000644000175000001440000001671311023012130012331 00000000000000 /* cfengine for GNU Copyright (C) 2003- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: state.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include struct CfState { unsigned int expires; enum statepolicy policy; }; /*****************************************************************************/ void AddPersistentClass(char *name,unsigned int ttl_minutes,enum statepolicy policy) { int errno; DBT key,value; DB *dbp; struct CfState state; time_t now = time(NULL); char filename[CF_BUFSIZE]; snprintf(filename,CF_BUFSIZE,"%s/state/%s",VLOCKDIR,CF_STATEDB_FILE); if ((errno = db_create(&dbp,NULL,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open average database %s\n",filename); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,filename,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,filename,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open average database %s\n",filename); CfLog(cferror,OUTPUT,"db_open"); return; } chmod(filename,0644); memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); key.data = name; key.size = strlen(name)+1; if ((errno = dbp->get(dbp,NULL,&key,&value,0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp,errno,NULL); dbp->close(dbp,0); return; } } if (value.data != NULL) { memcpy((void *)&state,value.data,sizeof(state)); if (state.policy == cfpreserve) { if (now < state.expires) { Verbose("Persisent state %s is already in a preserved state -- %d minutes to go\n",name,(state.expires-now)/60); dbp->close(dbp,0); return; } } } else { Verbose("New state %s but empty\n",key.data); } memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); key.data = name; key.size = strlen(name)+1; state.expires = now + ttl_minutes * 60; state.policy = policy; value.data = &state; value.size = sizeof(state); if ((errno = dbp->put(dbp,NULL,&key,&value,0)) != 0) { CfLog(cferror,"put failed","db->put"); } Verbose("(Re)Set persistent state %s for %d minutes\n",name,ttl_minutes); dbp->close(dbp,0); } /*****************************************************************************/ void DeletePersistentClass(char *name) { int errno; DBT key,value; DB *dbp; char filename[CF_BUFSIZE]; snprintf(filename,CF_BUFSIZE,"%s/state/%s",VLOCKDIR,CF_STATEDB_FILE); if ((errno = db_create(&dbp,NULL,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open average database %s\n",filename); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,filename,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,filename,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open average database %s\n",filename); CfLog(cferror,OUTPUT,"db_open"); return; } chmod(filename,0644); memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); key.data = name; key.size = strlen(name)+1; if ((errno = dbp->del(dbp,NULL,&key,0)) != 0) { CfLog(cferror,"","db_store"); } Debug("Deleted persistent state %s if found\n",name); dbp->close(dbp,0); } /*****************************************************************************/ void PersistentClassesToHeap() { DBT key,value; DB *dbp; DBC *dbcp; DB_ENV *dbenv = NULL; int ret; time_t now = time(NULL); struct CfState q; char filename[CF_BUFSIZE]; Banner("Loading persistent classes"); snprintf(filename,CF_BUFSIZE,"%s/state/%s",VLOCKDIR,CF_STATEDB_FILE); if ((errno = db_create(&dbp,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open checksum database %s\n",filename); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,filename,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,filename,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open persistent state database %s\n",filename); CfLog(cferror,OUTPUT,"db_open"); dbp->close(dbp,0); return; } /* Acquire a cursor for the database. */ if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { CfLog(cferror,"Error reading from persistent state database",""); dbp->err(dbp, ret, "DB->cursor"); return; } /* Initialize the key/data return pair. */ memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); /* Walk through the database and print out the key/data pairs. */ while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { memcpy((void *)&q,value.data,sizeof(struct CfState)); Debug(" - Found key %s...\n",key.data); if (now > q.expires) { Verbose(" Persistent class %s expired\n",key.data); if ((errno = dbp->del(dbp,NULL,&key,0)) != 0) { CfLog(cferror,"","db_store"); } } else { Verbose(" Persistent class %s for %d more minutes\n",key.data,(q.expires-now)/60); Verbose(" Adding persistent class %s to heap\n",key.data); AddMultipleClasses(key.data); } } dbcp->c_close(dbcp); dbp->close(dbp,0); Banner("Loaded persistent memory"); } /*****************************************************************************/ void DePort(char *address) { char *sp,*chop,*fc = NULL,*fd = NULL,*ld = NULL; int i = 0,ccount = 0, dcount = 0; /* Start looking for ethernet/ipv6 addresses */ for (sp = address; *sp != '\0'; sp++) { if (*sp == ':') { if (!fc) { fc = sp; } ccount++; } if (*sp == '.') { if (!fd) { fd = sp; } ld = sp; dcount++; } } if (!fd) { /* This does not look like an IP address+port, maybe ethernet */ return; } if (dcount == 4) { chop = ld; } else if (dcount > 1 && fc != NULL) { chop = fc; } else if (ccount > 1 && fd != NULL) { chop = fd; } else { /* Don't recognize address */ return; } if (chop < address+strlen(address)) { *chop = '\0'; } Verbose("Deport => %s\n",address); return; } cfengine-2.2.10/src/parse.c0000644000175000001440000007630010707625056012352 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Parse Zone for cfengine */ /* */ /* This is wide screen entertainment. Resize */ /* your window before viewing! */ /* */ /* The routines here are called by the lexer and the yacc parser */ /* */ /*******************************************************************/ #define INET #include #include "cf.defs.h" #include "cf.extern.h" extern FILE *yyin; /*******************************************************************/ int ParseInputFile(char *file,int audit) { char filename[CF_BUFSIZE], *sp; struct Item *ptr; struct stat s; struct Item *done = NULL; Debug("Parse(%s)\n",file); NewParser(); PARSING = true; if (strcmp(file,"-") == 0) { Debug("(BEGIN PARSING STDIN)\n"); ParseStdin(); } else { sp = FindInputFile(filename,file); Debug("(BEGIN PARSING %s)\n",filename); Verbose("Looking for an input file %s\n",filename); if (stat(filename,&s) == -1) { Verbose("(No file %s)\n",filename); Debug("(END OF PARSING %s)\n",filename); Verbose("Finished with %s\n",filename); PARSING = false; DeleteParser(); return false; } ParseFile(filename,sp,audit); } for (ptr = VIMPORT; ptr != NULL; ptr=ptr->next) { if (IsExcluded(ptr->classes)) { continue; } Debug("(BEGIN PARSING %s)\n",ptr->name); Verbose("Looking for an input file %s\n",ptr->name); sp = FindInputFile(filename,ptr->name); if (!IsItemIn(done,filename)) { ParseFile(filename,sp,audit); PrependItem(&done,filename,NULL); } } DeleteItemList(done); PARSING = false; DeleteParser(); Debug("(END OF PARSING %s)\n",file); Verbose("Finished with %s\n\n",file); if (strcmp(file,"update.conf") == 0) { GetRemoteMethods(); } return true; } /*******************************************************************/ void NewParser() { Debug("New Parser Object::"); FINDERTYPE = (char *) malloc(CF_BUFSIZE); strncpy(FINDERTYPE, "*", CF_BUFSIZE); /* "*" = no findertype set */ VUIDNAME = (char *) malloc(CF_BUFSIZE); VGIDNAME = (char *) malloc(CF_BUFSIZE); FILTERNAME = (char *) malloc(CF_BUFSIZE); STRATEGYNAME = (char *) malloc(CF_BUFSIZE); CURRENTITEM = (char *) malloc(CF_BUFSIZE); GROUPBUFF = (char *) malloc(CF_BUFSIZE); ACTIONBUFF = (char *) malloc(CF_BUFSIZE); CURRENTOBJECT = (char *) malloc(CF_BUFSIZE); CURRENTAUTHPATH = (char *) malloc(CF_BUFSIZE); CLASSBUFF = (char *) malloc(CF_BUFSIZE); LINKFROM = (char *) malloc(CF_BUFSIZE); LINKTO = (char *) malloc(CF_BUFSIZE); ERROR = (char *) malloc(CF_BUFSIZE); EXPR = (char *) malloc(CF_BUFSIZE); MOUNTFROM = (char *) malloc(CF_BUFSIZE); MOUNTONTO = (char *) malloc(CF_BUFSIZE); *MOUNTFROM = '\0'; *MOUNTONTO = '\0'; MOUNTOPTS = (char *) malloc(CF_BUFSIZE); PKGVER = (char *) malloc(CF_BUFSIZE); PKGVER[0] = '\0'; DESTINATION = (char *) malloc(CF_BUFSIZE); IMAGEACTION = (char *) malloc(CF_BUFSIZE); PARSEMETHODRETURNCLASSES = (char *) malloc(CF_BUFSIZE); CHDIR = (char *) malloc(CF_BUFSIZE); RESTART = (char *) malloc(CF_BUFSIZE); LOCALREPOS = (char *) malloc(CF_BUFSIZE); FILTERDATA = (char *) malloc(CF_BUFSIZE); STRATEGYDATA = (char *) malloc(CF_BUFSIZE); memset(CLASSBUFF,0,CF_BUFSIZE); } /*******************************************************************/ void DeleteParser() { Debug("Delete Parser Object::"); free(PARSEMETHODRETURNCLASSES); free(FINDERTYPE); free(VUIDNAME); free(VGIDNAME); free(FILTERNAME); free(STRATEGYNAME); free(CURRENTITEM); free(GROUPBUFF); free(ACTIONBUFF); free(CURRENTOBJECT); free(CURRENTAUTHPATH); free(CLASSBUFF); free(LINKFROM); free(LINKTO); free(ERROR); free(EXPR); free(RESTART); free(MOUNTFROM); free(MOUNTONTO); free(MOUNTOPTS); free(DESTINATION); free(IMAGEACTION); free(PKGVER); free(CHDIR); free(LOCALREPOS); free(FILTERDATA); free(STRATEGYDATA); } /*******************************************************************/ int RemoveEscapeSequences(char *from,char *to) { char *sp,*cp; char start = *from; int len = strlen(from); if (len == 0) { return 0; } for (sp=from+1,cp=to; (sp-from) < len; sp++,cp++) { if ((*sp == start)) { *(cp) = '\0'; if (*(sp+1) != '\0') { return (2+(sp - from)); } return 0; } if (*sp == '\n') { LINENUMBER++; } if (*sp == '\\') { switch (*(sp+1)) { case '\n': LINENUMBER++; sp+=2; break; case '\\': case '\"': case '\'': sp++; break; } } *cp = *sp; } yyerror("Runaway string"); *(cp) = '\0'; return 0; } /*******************************************************************/ void SetAction (enum actions action) { InstallPending(ACTION); /* Flush any existing actions */ SetStrategies(); Debug1("\n\n==============================BEGIN NEW ACTION %s=============\n\n",ACTIONTEXT[action]); ACTION = action; strcpy(ACTIONBUFF,ACTIONTEXT[action]); switch (ACTION) { case interfaces: case files: case makepath: case tidy: case disable: case rename_disable: case filters: case strategies: case image: case links: case required: case disks: case shellcommands: case scli: case alerts: case unmounta: case admit: case deny: case methods: case processes: InitializeAction(); } Debug1("\nResetting CLASS to ANY\n\n"); strcpy(CLASSBUFF,CF_ANYCLASS); /* default class */ } /*******************************************************************/ void HandleLValue(char *id) /* Record name of a variable assignment */ { Debug1("HandleLVALUE(%s) in action %s\n",id,ACTIONTEXT[ACTION]); switch(ACTION) /* Check for IP names in cfd */ { case control: if ((CONTROLVAR = ScanVariable(id)) != nonexistentvar) { strcpy(CURRENTITEM,id); return; } else { if (IsDefinedClass(CLASSBUFF)) { RecordMacroId(id); } return; } break; case groups: { int count = 1; char *cid = id; while (*cid != '\0') { if (*cid++ == '.') { count++; } } if (strcmp(id,CF_ANYCLASS) == 0) { yyerror("Reserved class "); } if (count > 1) /* compound class */ { yyerror("Group with compound identifier"); FatalError("Dots [.] not allowed in group identifiers"); } if (IsHardClass(id)) { yyerror("Reserved class name (choose a different name)"); } strcpy(GROUPBUFF,id); } break; } } /*******************************************************************/ void HandleBraceObjectID(char *id) /* Record identifier for braced object */ { Debug1("HandleBraceObjectID(%s) in action %s\n",id,ACTIONTEXT[ACTION]); switch (ACTION) { case acls: strcpy(CURRENTOBJECT,id); InstallACL(id,CLASSBUFF); break; case strategies: if (strlen(STRATEGYNAME) == 0) { strcpy(STRATEGYNAME,id); InstallStrategy(id,CLASSBUFF); } else { yyerror("Multiple identifiers or forgotten quotes in strategy"); } break; case editfiles: if (strlen(CURRENTOBJECT) == 0) { strcpy(CURRENTOBJECT,id); EDITGROUPLEVEL = 0; FOREACHLEVEL = 0; SEARCHREPLACELEVEL = 0; } else { yyerror("Multiple filenames in editfiles"); } break; case filters: if (strlen(FILTERNAME)==0) { strcpy(FILTERNAME,id); InstallFilter(id); } else { yyerror("Multiple identifiers in filter"); } break; } } /*******************************************************************/ void HandleBraceObjectClassifier(char *id) /* Record LHS item in braced object */ { Debug1("HandleClassifier(%s) in action %s\n",id,ACTIONTEXT[ACTION]); switch (ACTION) { case acls: AddACE(CURRENTOBJECT,id,CLASSBUFF); break; case filters: case strategies: strcpy(CURRENTITEM,id); break; case editfiles: if (strcmp(id,"EndGroup") == 0 || strcmp(id,"GotoLastLine") == 0 || strcmp(id,"AutoCreate") == 0 || strcmp(id,"WarnIfFileMissing") == 0 || strcmp(id,"EndLoop") == 0 || strcmp(id,"CatchAbort") == 0 || strcmp(id,"ExpandVariables") == 0 || strcmp(id,"EmptyEntireFilePlease") == 0) { HandleEdit(CURRENTOBJECT,id,NULL); } strcpy(CURRENTITEM,id); break; } } /*******************************************************************/ void HandleClass (char *id) { int members; char *sp; Debug("HandleClass(%s)\n",id); for (sp = id; *sp != '\0'; sp++) { switch (*sp) { case '-': case '*': snprintf(OUTPUT,CF_BUFSIZE,"Illegal character (%c) in class %s",*sp,id); yyerror(OUTPUT); } } InstallPending(ACTION); if ((members = CompoundId(id)) > 1) /* Parse compound id */ { Debug1("Compound class = (%s) with %d members\n",id,members); } else { Debug1("Simple class = (%s)\n",id); } strcpy(CLASSBUFF,id); } /*******************************************************************/ void HandleQuotedString(char *qstring) { Debug1("HandleQuotedString %s\n",qstring); switch (ACTION) { case editfiles: HandleEdit(CURRENTOBJECT,CURRENTITEM,qstring); break; case filters: strcpy(FILTERDATA,qstring); ACTIONPENDING = true; InstallPending(ACTION); break; case strategies: strcpy(STRATEGYDATA,qstring); ACTIONPENDING = true; InstallPending(ACTION); break; case processes: /* Handle anomalous syntax of restart/setoptonstring */ if (strcmp(CURRENTOBJECT,"SetOptionString") == 0) { if (HAVE_RESTART) { yyerror("Processes syntax error"); } strcpy(RESTART,qstring); ACTIONPENDING = true; InstallPending(ACTION); return; } if (strlen(RESTART) > 0 || (!HAVE_RESTART && strlen(EXPR) > 0)) /* Any string must be new rule */ { if (!ACTIONPENDING) { yyerror("Insufficient or incomplete processes statement"); } InstallPending(ACTION); InitializeAction(); } if (EXPR[0] == '\0') { if (HAVE_RESTART) { yyerror("Missing process search expression"); } Debug1("Installing expression %s\n",qstring); strcpy(EXPR,qstring); HAVE_RESTART = false; } else if (HAVE_RESTART) { Debug1("Installing restart expression\n"); strncpy(RESTART,qstring,CF_BUFSIZE-1); ACTIONPENDING = true; } break; case interfaces: strncpy(VIFNAME,qstring,15); break; default: InstallPending(ACTION); strncpy(CURRENTOBJECT,qstring,CF_BUFSIZE-1); ACTIONPENDING = true; return; } } /*******************************************************************/ void HandleGroupRValue(char *rval) /* Assignment in groups/classes */ { Debug1("\nHandleGroupRvalue(%s)\n",rval); if (ACTION == control) { if (CountParentheses(rval) > 0) { yyerror("Variables in function with $() rather than ${} - bug workaround"); } if (NestedParentheses(rval) > 1) { yyerror("Variables in function with $() rather than ${} - bug workaround"); } } if (strcmp(rval,"+") == 0 || strcmp(rval,"-") == 0) { yyerror("+/- not bound to identifier"); } if (rval[0] == '+') /* Lookup in NIS */ { rval++; if (rval[0] == '@') /* Irrelevant */ { rval++; } Debug1("Netgroup rval, lookup NIS group (%s)\n",rval); InstallGroupRValue(rval,netgroup); } else if ((rval[0] == '-') && (ACTION != processes)) { rval++; if (rval[0] == '@') /* Irrelevant */ { rval++; InstallGroupRValue(rval,groupdeletion); } else { InstallGroupRValue(rval,deletion); } } else if (rval[0] == '\"' || rval[0] == '\'' || rval[0] == '`') { *(rval+strlen(rval)-1) = '\0'; InstallGroupRValue(rval,classscript); } else if (rval[0] == '/') { InstallGroupRValue(rval,classscript); } else { InstallGroupRValue(rval,simple); } } /***************************************************************************/ void HandleFunctionObject(char *fn) /* Function in main body */ { char local[CF_BUFSIZE]; Debug("HandleFunctionObject(%s)\n",fn); if (ACTION == methods) { strncpy(CURRENTOBJECT,fn,CF_BUFSIZE-1); ACTIONPENDING = true; return; } if ((ACTION != alerts) && (!IsDefinedClass(CLASSBUFF))) { Debug("Function object class was beyond current environment (%s)\n",CLASSBUFF); return; } if (IsBuiltinFunction(fn)) { local[0] = '\0'; strcpy(local,EvaluateFunction(fn,local)); switch (ACTION) { case groups: InstallGroupRValue(local,simple); break; case control: if (strncmp("CF_ASSOCIATIVE_ARRAY",local,strlen("CF_ASSOCIATIVE_ARRAY")) == 0) { break; } InstallControlRValue(CURRENTITEM,local); break; case alerts: if (strcmp(local,"noinstall") != 0) { Debug("Recognized function %s\n",fn); strncpy(CURRENTOBJECT,fn,CF_BUFSIZE-1); ACTIONPENDING = true; } else { Debug("Not recognized %s\n",fn); } break; default: snprintf(OUTPUT,CF_BUFSIZE,"Function call %s out of place",fn); yyerror(OUTPUT); } } } /***************************************************************************/ void HandleVarObject(char *object) { Debug1("Handling Object = (%s)\n",object); strncpy(CURRENTOBJECT,object,CF_BUFSIZE-1); /* Yes this must be here */ if (object[strlen(object)-1] == ':') { yyerror("There seems to be an action or class syntax error"); } ACTIONPENDING = true; /* we're parsing an action */ if (ACTION_IS_LINK || ACTION_IS_LINKCHILDREN) /* to-link (after ->) */ { strncpy(LINKTO,CURRENTOBJECT,CF_BUFSIZE-1); return; } switch (ACTION) { case control: switch (CONTROLVAR) { case cfmountpat: SetMountPath(object); break; case cfrepos: SetRepository(object); break; case cfrepchar: if (strlen(object) > 1) { yyerror("reposchar can only be a single letter"); } if (object[0] == '/') { yyerror("illegal value for reposchar"); } REPOSCHAR = object[0]; break; case cflistsep: if (strlen(object) > 1) { yyerror("listseparator can only be a single letter"); } if (object[0] == '/') { yyerror("illegal value for listseparator"); } LISTSEPARATOR = object[0]; break; case cfhomepat: yyerror("Path relative to mountpath required"); FatalError("Absolute path was specified\n"); break; case nonexistentvar: if (IsDefinedClass(CLASSBUFF)) { AddMacroValue(CONTEXTID,CURRENTITEM,object); } break; } break; case import: AppendImport(object); /* Recursion */ break; case links: /* from link (see cf.l) */ break; case filters: if (strlen(FILTERNAME) == 0) { yyerror("empty or broken filter"); } else { strncpy(CURRENTITEM,object,CF_BUFSIZE-1); ACTIONPENDING = true; } break; case disks: case required: strncpy(CURRENTOBJECT,object,CF_BUFSIZE-1); break; case shellcommands: case scli: break; /* HvB : Bas van der Vlies */ case mountables: break; case defaultroute:InstallDefaultRouteItem(object); break; case resolve: break; case broadcast: InstallBroadcastItem(object); break; case mailserver: InstallMailserverPath(object); break; case tidy: strncpy(CURRENTITEM,object,CF_BUFSIZE-1); break; case rename_disable: case disable: strncpy(CURRENTOBJECT,object,CF_BUFSIZE-1); ACTIONPENDING = true; break; case makepath: strncpy(CURRENTOBJECT,object,CF_BUFSIZE-1); break; case ignore: strncpy(CURRENTOBJECT,object,CF_BUFSIZE-1); break; case misc_mounts: if (! MOUNT_FROM) { MOUNT_FROM = true; strncpy(MOUNTFROM,CURRENTOBJECT,CF_BUFSIZE-1); } else { if (MOUNT_ONTO) { yyerror ("Path not expected"); FatalError("miscmounts: syntax error"); } MOUNT_ONTO = true; strncpy(MOUNTONTO,CURRENTOBJECT,CF_BUFSIZE-1); } break; case unmounta: strncpy(CURRENTOBJECT,object,CF_BUFSIZE-1); break; case image: case files: break; case editfiles: /* file recorded in CURRENTOBJECT */ strncpy(CURRENTOBJECT,object,CF_BUFSIZE-1); break; case processes: if (strcmp(ToLowerStr(object),"restart") == 0) { if (HAVE_RESTART) { yyerror("Repeated Restart option in processes"); } HAVE_RESTART = true; Debug1("Found restart directive\n"); } else if (strcmp(ToLowerStr(object),"setoptionstring") == 0) { InstallPending(ACTION); InitializeAction(); Debug1("\nFound SetOptionString\n"); strcpy(CURRENTOBJECT,"SetOptionString"); strcpy(EXPR,"SetOptionString"); } else if (HAVE_RESTART) { Debug1("Installing restart expression\n"); strncpy(RESTART,object,CF_BUFSIZE-1); ACTIONPENDING = true; } else { Debug1("Dropped %s :(\n",object); } break; case binservers: InstallBinserverItem(object); break; case homeservers: InstallHomeserverItem(object); break; case packages: break; case methods: if (strlen(object) > CF_BUFSIZE-1) { yyerror("Method argument string is too long"); } break; default: yyerror("Unknown command or name out of context"); } } /*******************************************************************/ void HandleServerRule(char *object) { char buffer[CF_EXPANDSIZE]; ExpandVarstring(object,buffer,""); Debug("HandleServerRule(%s=%s)\n",object,buffer); if (*buffer == '/') { Debug("\n\nNew admit/deny object=%s\n",buffer); strcpy(CURRENTAUTHPATH,object); } else { switch(ACTION) /* Check for IP names in cfservd */ { case admit: FuzzyMatchParse(buffer); InstallAuthItem(CURRENTAUTHPATH,object,&VADMIT,&VADMITTOP,CLASSBUFF); break; case deny: FuzzyMatchParse(buffer); InstallAuthItem(CURRENTAUTHPATH,object,&VDENY,&VDENYTOP,CLASSBUFF); break; } } } /*******************************************************************/ void HandleOption(char *option) { Debug("HandleOption(%s)\n",option); switch (ACTION) { case files: HandleOptionalFileAttribute(option); break; case image: HandleOptionalImageAttribute(option); break; case tidy: HandleOptionalTidyAttribute(option); break; case makepath: HandleOptionalDirAttribute(option); break; case disable: case rename_disable: HandleOptionalDisableAttribute(option); break; case links: HandleOptionalLinkAttribute(option); break; case processes: HandleOptionalProcessAttribute(option); break; case misc_mounts: HandleOptionalMiscMountsAttribute(option); break; case mountables: HandleOptionalMountablesAttribute(option); break; case unmounta: HandleOptionalUnMountAttribute(option); break; case shellcommands: case scli: HandleOptionalScriptAttribute(option); break; case alerts: HandleOptionalAlertsAttribute(option); break; case disks: case required: HandleOptionalRequired(option); break; case interfaces: HandleOptionalInterface(option); if (strlen(VIFNAME) && strlen(CURRENTOBJECT) && strlen(DESTINATION)) { ACTIONPENDING = true; } break; case admit: InstallAuthItem(CURRENTAUTHPATH,option,&VADMIT,&VADMITTOP,CLASSBUFF); break; case deny: InstallAuthItem(CURRENTAUTHPATH,option,&VDENY,&VDENYTOP,CLASSBUFF); break; case import: /* Need option for private modules... */ break; case packages: HandleOptionalPackagesAttribute(option); break; case methods: HandleOptionalMethodsAttribute(option); break; default: yyerror("Options cannot be used in this context:"); } } /*******************************************************************/ /* Level 2 */ /*******************************************************************/ void ParseFile(char *filename,char *env,int audit) { FILE *save_yyin = yyin; signal(SIGALRM,(void *)TimeOut); alarm(RPCTIMEOUT); if (!FileSecure(filename)) { FatalError("Security exception"); } if ((yyin = fopen(filename,"r")) == NULL) /* Open root file */ { printf("%s: Can't open file %s\n",VPREFIX,filename); if (env == NULL) { printf("%s: (%s is set to )\n",VPREFIX,CF_INPUTSVAR); } else { printf("%s: (%s is set to %s)\n",VPREFIX,CF_INPUTSVAR,env); } exit (1); } strcpy(VCURRENTFILE,filename); Debug("\n##########################################################################\n"); Debug("# BEGIN PARSING %s\n",VCURRENTFILE); Debug("##########################################################################\n\n"); LINENUMBER = 1; if (audit) { PrependAuditFile(filename); } while (!feof(yyin)) { yyparse(); if (ferror(yyin)) /* abortable */ { printf("%s: Error reading %s\n",VPREFIX,VCURRENTFILE); perror("cfengine"); exit(1); } } if (audit) { VersionAuditFile(); } fclose (yyin); yyin = save_yyin; alarm(0); signal(SIGALRM,SIG_DFL); InstallPending(ACTION); } /*******************************************************************/ void ParseStdin() { yyin = stdin; Debug("\n##########################################################################\n"); Debug("# BEGIN PARSING stdin\n"); Debug("##########################################################################\n\n"); LINENUMBER=1; while (!feof(yyin)) { yyparse(); if (ferror(yyin)) /* abortable */ { printf("%s: Error reading %s\n",VPREFIX,VCURRENTFILE); perror("cfengine"); exit(1); } } InstallPending(ACTION); } /*******************************************************************/ int CompoundId(char *id) /* check for dots in the name */ { int count = 1; char *cid = id; for (cid = id; *cid != '\0'; cid++) { if (*cid == '.' || *cid == '|') { count++; } } return(count); } /*******************************************************************/ void RecordMacroId(char *name) { Debug("RecordMacroId(%s)\n",name); strcpy(CURRENTITEM,name); if (strcmp(name,"this") == 0) { yyerror("$(this) is a reserved variable"); } } /*******************************************************************/ /* Level 2 */ /*******************************************************************/ char *FindInputFile(char *result,char *filename) { char *sp; result[0] = '\0'; if (MINUSF && (*filename == '.' || *filename == '/')) { Verbose("Manually overidden relative path (%s)\n",filename); strncpy(result,filename,CF_BUFSIZE-1); return result; } if ((sp=getenv(CF_INPUTSVAR)) != NULL) { if (!IsAbsoluteFileName(filename)) /* Don't prepend to absolute names */ { strcpy(result,sp); if (! IsAbsoluteFileName(result)) { Verbose("CFINPUTS was not an absolute path, overriding with %s\n",CFWORKDIR); snprintf(result,CF_BUFSIZE,"%s/inputs",CFWORKDIR); } AddSlash(result); } } else { if (!IsAbsoluteFileName(filename)) /* Don't prepend to absolute names */ { strcpy(result,CFWORKDIR); AddSlash(result); strcat(result,"inputs/"); } } strcat(result,filename); return result; } /*******************************************************************/ /* Toolkits Misc */ /*******************************************************************/ void InitializeAction() /* Set defaults */ { Debug1("InitializeAction()\n"); ACTIONPENDING = false; PLUSMASK = (mode_t)0; MINUSMASK = (mode_t)0; PLUSFLAG = (u_long)0; MINUSFLAG = (u_long)0; VRECURSE = 0; HAVE_RESTART = false; VAGE = 99999; strncpy(FINDERTYPE,"*",CF_BUFSIZE); strcpy(VUIDNAME,"*"); strcpy(VGIDNAME,"*"); HAVE_RESTART = 0; FILEACTION=warnall; PIFELAPSED=-1; PEXPIREAFTER=-1; *CURRENTAUTHPATH = '\0'; *CURRENTOBJECT = '\0'; *CURRENTITEM = '\0'; *DESTINATION = '\0'; *IMAGEACTION = '\0'; *LOCALREPOS = '\0'; *EXPR = '\0'; *RESTART = '\0'; *FILTERDATA = '\0'; *STRATEGYDATA = '\0'; *CHDIR ='\0'; METHODFILENAME[0] = '\0'; PARSEMETHODRETURNCLASSES[0] = '\0'; METHODFORCE[0] = '\0'; CHROOT[0] = '\0'; strcpy(VIFNAME,""); PTRAVLINKS = (short) '?'; IMAGEBACKUP = 'y'; ENCRYPT = 'n'; VERIFY = 'n'; ROTATE=0; TIDYSIZE=0; PROMATCHES=-1; PROCOMP = '!'; PROACTION = 'd'; PROSIGNAL=0; COMPRESS='n'; AGETYPE='a'; COPYTYPE = DEFAULTCOPYTYPE; /* 't' */ LINKDIRS = 'k'; USESHELL = 'y'; LOGP = 'd'; INFORMP = 'd'; PURGE = 'n'; TRUSTKEY = 'n'; NOABSPATH = 'n'; CHKROOT = 'n'; SCAN = 'n'; CHECKSUM = 'n'; TIDYDIRS = 'n'; VEXCLUDEPARSE = NULL; VINCLUDEPARSE = NULL; VIGNOREPARSE = NULL; VACLBUILD = NULL; VFILTERBUILD = NULL; VSTRATEGYBUILD = NULL; VCPLNPARSE = NULL; VTIMEOUT=0; PKGMGR = DEFAULTPKGMGR; /* pkgmgr_none */ PKGACTION = pkgaction_none; CMPSENSE = cmpsense_eq; PKGVER[0] = '\0'; STRATEGYNAME[0] = '\0'; FILTERNAME[0] = '\0'; memset(ALLCLASSBUFFER,0,CF_BUFSIZE); memset(ELSECLASSBUFFER,0,CF_BUFSIZE); strcpy(CFSERVER,"localhost"); IMGCOMP = DISCOMP='>'; IMGSIZE = DISABLESIZE=CF_NOSIZE; DELETEDIR = 'y'; /* t=true */ DELETEFSTAB = 'y'; FORCE = 'n'; FORCEDIRS = 'n'; STEALTH = 'n'; XDEV = 'n'; PRESERVETIMES = 'n'; TYPECHECK = 'y'; UMASK = 077; /* Default umask for scripts/files */ FORK = 'n'; PREVIEW = 'n'; COMPATIBILITY = 'n'; if (MOUNT_FROM && MOUNT_ONTO) { Debug("Resetting miscmount data\n"); MOUNT_FROM = false; MOUNT_ONTO = false; MOUNTMODE='w'; *MOUNTFROM = '\0'; *MOUNTONTO = '\0'; } /* * HvB: Bas van der Vlies */ CF_MOUNT_RO=false; MOUNTOPTS[0]='\0'; /* Make sure we don't clean the buffer in the middle of a link! */ if ( ! ACTION_IS_LINK && ! ACTION_IS_LINKCHILDREN) { memset(LINKFROM,0,CF_BUFSIZE); memset(LINKTO,0,CF_BUFSIZE); /* ALSO RESTART */ LINKSILENT = false; LINKTYPE = 's'; FORCELINK = 'n'; DEADLINKS = false; } } /*********************************************************************/ void SetMountPath (char *value) { char buff[CF_EXPANDSIZE]; ExpandVarstring(value,buff,""); Debug("Appending [%s] to mountlist\n",buff); AppendItem(&VMOUNTLIST,buff,CLASSBUFF); } /*********************************************************************/ void SetRepository (char *value) { char ebuff[CF_EXPANDSIZE]; if (*value != '/') { yyerror("File repository must be an absolute directory name"); } if (strlen(VREPOSITORY) != 0) { yyerror("Redefinition of system variable repository"); } ExpandVarstring(value,ebuff,""); VREPOSITORY = strdup(ebuff); } /* EOF */ cfengine-2.2.10/src/misc.c0000644000175000001440000010270711144464130012162 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 PARTICULARmandar 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 */ /*********************************************************************/ /* */ /* TOOLKITS: "object" library */ /* */ /*********************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include "../pub/global.h" #include /*********************************************************************/ /* TOOLKIT : files/directories */ /*********************************************************************/ int DirPush(char *name,struct stat *sb) /* Enter dir and check for race exploits */ { if (chdir(name) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Could not change to directory %s, mode %o in tidy",name,sb->st_mode & 07777); CfLog(cfinform,OUTPUT,"chdir"); return false; } else { Debug("Changed directory to %s\n",name); } CheckLinkSecurity(sb,name); return true; } /**********************************************************************/ void DirPop(int goback,char * name,struct stat *sb) /* Exit dir and check for race exploits */ { if (goback && TRAVLINKS) { if (chdir(name) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Error in backing out of recursive descent securely to %s",name); CfLog(cferror,OUTPUT,"chdir"); HandleSignal(SIGTERM); } CheckLinkSecurity(sb,name); } else if (goback) { if (chdir("..") == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Error in backing out of recursive descent securely to %s",name); CfLog(cferror,OUTPUT,"chdir"); HandleSignal(SIGTERM); } } } /**********************************************************************/ void CheckLinkSecurity(struct stat *sb,char *name) { struct stat security; Debug("Checking the inode and device to make sure we are where we think we are...\n"); if (stat(".",&security) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Could not stat directory %s after entering!",name); CfLog(cferror,OUTPUT,"stat"); return; } if ((sb->st_dev != security.st_dev) || (sb->st_ino != security.st_ino)) { snprintf(OUTPUT,CF_BUFSIZE,"SERIOUS SECURITY ALERT: path race exploited in recursion to/from %s. Not safe for agent to continue - aborting",name); CfLog(cferror,OUTPUT,""); HandleSignal(SIGTERM); /* Exits */ } } /**********************************************************************/ void TruncateFile(char *name) { struct stat statbuf; int fd; if (stat(name,&statbuf) == -1) { Debug2("cfengine: didn't find %s to truncate\n",name); return; } else { if ((fd = creat(name,000)) == -1) /* dummy mode ignored */ { snprintf(OUTPUT,CF_BUFSIZE*2,"creat(%s) failed\n",name); CfLog(cferror,OUTPUT,"creat"); } else { close(fd); } } } /*************************************************************************/ int FileSecure (char *name) { struct stat statbuf; if (PARSEONLY || !CFPARANOID) { return true; } if (stat(name,&statbuf) == -1) { return false; } if (statbuf.st_uid != getuid()) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is not owned by uid %d (security exception)",name,getuid()); CfLog(cferror,OUTPUT,""); } /* Is the file writable by ANYONE except the owner ? */ if (statbuf.st_mode & (S_IWGRP | S_IWOTH)) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s (owner %d) is writable by others (security exception)",name,getuid()); CfLog(cferror,OUTPUT,""); return false; } return true; } /*************************************************************************/ int IgnoredOrExcluded(enum actions action,char *file,struct Item *inclusions,struct Item *exclusions) { char *lastnode; Debug("IgnoredOrExcluded(%s)\n",file); if (strstr(file,"/")) { for (lastnode = file+strlen(file); *lastnode != '/'; lastnode--) { } lastnode++; } else { lastnode = file; } if ((inclusions != NULL) && !IsWildItemIn(inclusions,lastnode)) { Debug("cfengine: skipping non-included pattern %s\n",file); return true; } switch(action) { case image: if (IsWildItemIn(VEXCLUDECOPY,lastnode) || IsWildItemIn(exclusions,lastnode)) { Debug("Skipping excluded pattern %s\n",file); return true; } break; case links: if (IsWildItemIn(VEXCLUDELINK,lastnode) || IsWildItemIn(exclusions,lastnode)) { Debug("Skipping excluded pattern %s\n",file); return true; } break; default: if (IsWildItemIn(exclusions,lastnode)) { Debug("Skipping excluded pattern %s\n",file); return true; } } return false; } /*********************************************************************/ void Banner(char *string) { Verbose("---------------------------------------------------------------------\n"); Verbose("%s\n",string); Verbose("---------------------------------------------------------------------\n\n"); } /*******************************************************************/ int ShellCommandReturnsZero(char *comm,int useshell) { int status, i, argc = 0; pid_t pid; char arg[CF_MAXSHELLARGS][CF_BUFSIZE]; char **argv; if (!useshell) { /* Build argument array */ for (i = 0; i < CF_MAXSHELLARGS; i++) { memset (arg[i],0,CF_BUFSIZE); } argc = SplitCommand(comm,arg); if (argc == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Too many arguments in %s\n",comm); CfLog(cferror,OUTPUT,""); return false; } } if ((pid = fork()) < 0) { FatalError("Failed to fork new process"); } else if (pid == 0) /* child */ { ALARM_PID = -1; if (useshell) { if (execl("/bin/sh","sh","-c",comm,NULL) == -1) { yyerror("script failed"); perror("execl"); exit(1); } } else { argv = (char **) malloc((argc+1)*sizeof(char *)); if (argv == NULL) { FatalError("Out of memory"); } for (i = 0; i < argc; i++) { argv[i] = arg[i]; } argv[i] = (char *) NULL; if (execv(arg[0],argv) == -1) { yyerror("script failed"); perror("execvp"); exit(1); } free((char *)argv); } } else /* parent */ { pid_t wait_result; while ((wait_result = wait(&status)) != pid) { if (wait_result <= 0) { snprintf(OUTPUT,CF_BUFSIZE,"Wait for child failed\n"); CfLog(cfinform,OUTPUT,"wait"); return false; } } if (WIFSIGNALED(status)) { Debug("Script %s returned: %d\n",comm,WTERMSIG(status)); return false; } if (! WIFEXITED(status)) { return false; } if (WEXITSTATUS(status) == 0) { Debug("Shell command returned 0\n"); return true; } else { Debug("Shell command was non-zero: %d\n",WEXITSTATUS(status)); return false; } } return false; } /*********************************************************************/ void SetClassesOnScript(char *execstr,char *classes,char *elseclasses,int useshell) { FILE *pp; int print; char line[CF_BUFSIZE],*sp; switch (useshell) { case 'y': pp = cfpopen_sh(execstr,"r"); break; default: pp = cfpopen(execstr,"r"); break; } if (pp == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open pipe to command %s\n",execstr); CfLog(cferror,OUTPUT,"popen"); return; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); break; } ReadLine(line,CF_BUFSIZE,pp); if (strstr(line,"cfengine-die")) { break; } if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); break; } /* * Dumb script - echo non-empty lines to standard output. */ print = false; for (sp = line; *sp != '\0'; sp++) { if (! isspace((int)*sp)) { print = true; break; } } if (print) { Verbose("%s:%s: %s\n",VPREFIX,execstr,line); } } cfpclose_def(pp,classes,elseclasses); } /*********************************************************************/ char *UnQuote(char *s) { if (s[strlen(s)-1] == '\"') { s[strlen(s)-1] = '\0'; } if (s[0] == '\"') { return s+1; } else { return s; } } /*********************************************************************/ void AddListSeparator(char *s) { if (s[strlen(s)-1] != LISTSEPARATOR) { s[strlen(s)+1] = '\0'; s[strlen(s)] = LISTSEPARATOR; } } /*********************************************************************/ void ChopListSeparator(char *s) { if (s[strlen(s)-1] == LISTSEPARATOR) { s[strlen(s)-1] = '\0'; } } /*******************************************************************/ void IDClasses() { struct stat statbuf; char *sp; int i = 0; AddClassToHeap("any"); /* This is a reserved word / wildcard */ snprintf(VBUFF,CF_BUFSIZE,"cfengine_%s",CanonifyName(VERSION)); AddClassToHeap(VBUFF); for (sp = VBUFF+strlen(VBUFF); i < 2; sp--) { if (*sp == '_') { i++; *sp = '\0'; AddClassToHeap(VBUFF); } } #ifdef LINUX /* {Mandrake,Fedora} has a symlink at /etc/redhat-release pointing to * /etc/{mandrake,fedora}-release, so we else-if around that */ if (stat("/etc/mandrake-release",&statbuf) != -1) { Verbose("This appears to be a mandrake system.\n"); AddClassToHeap("Mandrake"); linux_mandrake_version(); } else if (stat("/etc/fedora-release",&statbuf) != -1) { Verbose("This appears to be a fedora system.\n"); AddClassToHeap("redhat"); AddClassToHeap("fedora"); linux_fedora_version(); } else if (stat("/etc/redhat-release",&statbuf) != -1) { Verbose("This appears to be a redhat system.\n"); AddClassToHeap("redhat"); linux_redhat_version(); } if (stat("/etc/generic-release",&statbuf) != -1) { Verbose("\nThis appears to be a sun cobalt system.\n"); AddClassToHeap("SunCobalt"); } if (stat("/etc/SuSE-release",&statbuf) != -1) { Verbose("\nThis appears to be a SuSE system.\n"); AddClassToHeap("SuSE"); linux_suse_version(); } #define SLACKWARE_ANCIENT_VERSION_FILENAME "/etc/slackware-release" #define SLACKWARE_VERSION_FILENAME "/etc/slackware-version" if (stat(SLACKWARE_VERSION_FILENAME,&statbuf) != -1) { Verbose("\nThis appears to be a slackware system.\n"); AddClassToHeap("slackware"); linux_slackware_version(SLACKWARE_VERSION_FILENAME); } else if (stat(SLACKWARE_ANCIENT_VERSION_FILENAME,&statbuf) != -1) { Verbose("\nThis appears to be an ancient slackware system.\n"); AddClassToHeap("slackware"); linux_slackware_version(SLACKWARE_ANCIENT_VERSION_FILENAME); } if (stat("/etc/generic-release",&statbuf) != -1) { Verbose("\nThis appears to be a sun cobalt system.\n"); AddClassToHeap("SunCobalt"); } if (stat("/etc/debian_version",&statbuf) != -1) { Verbose("\nThis appears to be a debian system.\n"); AddClassToHeap("debian"); debian_version(); } if (stat("/etc/UnitedLinux-release",&statbuf) != -1) { Verbose("\nThis appears to be a UnitedLinux system.\n"); AddClassToHeap("UnitedLinux"); } if (stat("/etc/gentoo-release",&statbuf) != -1) { Verbose("\nThis appears to be a gentoo system.\n"); AddClassToHeap("gentoo"); } lsb_version(); #endif if (stat("/proc/vmware/version",&statbuf) != -1 || stat("/etc/vmware-release",&statbuf) != -1) { Verbose("\nThis appears to be a VMware Server ESX system.\n"); AddClassToHeap("VMware"); VM_version(); } else if (stat("/etc/vmware",&statbuf) != -1) { if (S_ISDIR(statbuf.st_mode)) { Verbose("\nThis appears to be a VMware xSX system.\n"); AddClassToHeap("VMware"); VM_version(); } } if (stat("/proc/xen/capabilities",&statbuf) != -1) { Verbose("\nThis appears to be a xen pv system.\n"); AddClassToHeap("xen"); Xen_domain(); } #ifdef XEN_CPUID_SUPPORT else if (Xen_hv_check()) { Verbose("\nThis appears to be a xen hv system.\n"); AddClassToHeap("xen"); AddClassToHeap("xen_domu_hv"); } #endif } /*********************************************************************************/ int linux_fedora_version(void) { #define FEDORA_ID "Fedora" #define RELEASE_FLAG "release " /* We are looking for one of the following strings... * * Fedora Core release 1 (Yarrow) * Fedora release 7 (Zodfoobar) */ #define FEDORA_REL_FILENAME "/etc/fedora-release" FILE *fp; /* The full string read in from fedora-release */ char relstring[CF_MAXVARSIZE]; char classbuf[CF_MAXVARSIZE]; /* Fedora */ char *vendor=""; /* Where the numerical release will be found */ char *release=NULL; int major = -1; char strmajor[CF_MAXVARSIZE]; /* Grab the first line from the file and then close it. */ if ((fp = fopen(FEDORA_REL_FILENAME,"r")) == NULL) { return 1; } fgets(relstring, sizeof(relstring), fp); fclose(fp); Verbose("Looking for fedora core linux info...\n"); /* First, try to grok the vendor */ if(!strncmp(relstring, FEDORA_ID, strlen(FEDORA_ID))) { vendor = "fedora"; } else { Verbose("Could not identify OS distro from %s\n", FEDORA_REL_FILENAME); return 2; } /* Now, grok the release. We assume that all the strings will * have the word 'release' before the numerical release. */ release = strstr(relstring, RELEASE_FLAG); if(release == NULL) { Verbose("Could not find a numeric OS release in %s\n", FEDORA_REL_FILENAME); return 2; } else { release += strlen(RELEASE_FLAG); if (sscanf(release, "%d", &major) == 1) { sprintf(strmajor, "%d", major); } } if (major != -1 && (strcmp(vendor,"") != 0)) { classbuf[0] = '\0'; strcat(classbuf, vendor); AddClassToHeap(classbuf); strcat(classbuf, "_"); strcat(classbuf, strmajor); AddClassToHeap(classbuf); } return 0; } /*********************************************************************************/ int linux_redhat_version(void) { #define REDHAT_ID "Red Hat Linux" #define REDHAT_AS_ID "Red Hat Enterprise Linux AS" #define REDHAT_AS21_ID "Red Hat Linux Advanced Server" #define REDHAT_ES_ID "Red Hat Enterprise Linux ES" #define REDHAT_WS_ID "Red Hat Enterprise Linux WS" #define REDHAT_C_ID "Red Hat Enterprise Linux Client" #define REDHAT_S_ID "Red Hat Enterprise Linux Server" #define MANDRAKE_ID "Linux Mandrake" #define MANDRAKE_10_1_ID "Mandrakelinux" #define WHITEBOX_ID "White Box Enterprise Linux" #define CENTOS_ID "CentOS" #define SCIENTIFIC_SL_ID "Scientific Linux SL" #define SCIENTIFIC_CERN_ID "Scientific Linux CERN" #define RELEASE_FLAG "release " /* We are looking for one of the following strings... * * Red Hat Linux release 6.2 (Zoot) * Red Hat Linux Advanced Server release 2.1AS (Pensacola) * Red Hat Enterprise Linux AS release 3 (Taroon) * Red Hat Enterprise Linux WS release 3 (Taroon) * Red Hat Enterprise Linux Client release 5 (Tikanga) * Red Hat Enterprise Linux Server release 5 (Tikanga) * Linux Mandrake release 7.1 (helium) * Red Hat Enterprise Linux ES release 2.1 (Panama) * White Box Enterprise linux release 3.0 (Liberation) * Scientific Linux SL Release 4.0 (Beryllium) * CentOS release 4.0 (Final) */ #define RH_REL_FILENAME "/etc/redhat-release" FILE *fp; /* The full string read in from redhat-release */ char relstring[CF_MAXVARSIZE]; char classbuf[CF_MAXVARSIZE]; /* Red Hat, Mandrake */ char *vendor=""; /* as (Advanced Server, Enterprise) */ char *edition=""; /* Where the numerical release will be found */ char *release=NULL; int i; int major = -1; char strmajor[CF_MAXVARSIZE]; int minor = -1; char strminor[CF_MAXVARSIZE]; /* Grab the first line from the file and then close it. */ if ((fp = fopen(RH_REL_FILENAME,"r")) == NULL) { return 1; } fgets(relstring, sizeof(relstring), fp); fclose(fp); Verbose("Looking for redhat linux info in \"%s\"\n",relstring); /* First, try to grok the vendor and the edition (if any) */ if(!strncmp(relstring, REDHAT_ES_ID, strlen(REDHAT_ES_ID))) { vendor = "redhat"; edition = "es"; } else if(!strncmp(relstring, REDHAT_WS_ID, strlen(REDHAT_WS_ID))) { vendor = "redhat"; edition = "ws"; } else if(!strncmp(relstring, REDHAT_WS_ID, strlen(REDHAT_WS_ID))) { vendor = "redhat"; edition = "ws"; } else if(!strncmp(relstring, REDHAT_AS_ID, strlen(REDHAT_AS_ID)) || !strncmp(relstring, REDHAT_AS21_ID, strlen(REDHAT_AS21_ID))) { vendor = "redhat"; edition = "as"; } else if(!strncmp(relstring, REDHAT_S_ID, strlen(REDHAT_S_ID))) { vendor = "redhat"; edition = "s"; } else if(!strncmp(relstring, REDHAT_C_ID, strlen(REDHAT_C_ID))) { vendor = "redhat"; edition = "c"; } else if(!strncmp(relstring, REDHAT_ID, strlen(REDHAT_ID))) { vendor = "redhat"; } else if(!strncmp(relstring, MANDRAKE_ID, strlen(MANDRAKE_ID))) { vendor = "mandrake"; } else if(!strncmp(relstring, MANDRAKE_10_1_ID, strlen(MANDRAKE_10_1_ID))) { vendor = "mandrake"; } else if(!strncmp(relstring, WHITEBOX_ID, strlen(WHITEBOX_ID))) { vendor = "whitebox"; } else if(!strncmp(relstring, SCIENTIFIC_SL_ID, strlen(SCIENTIFIC_SL_ID))) { vendor = "scientific"; edition = "sl"; } else if(!strncmp(relstring, SCIENTIFIC_CERN_ID, strlen(SCIENTIFIC_CERN_ID))) { vendor = "scientific"; edition = "cern"; } else if(!strncmp(relstring, CENTOS_ID, strlen(CENTOS_ID))) { vendor = "centos"; } else { Verbose("Could not identify OS distro from %s\n", RH_REL_FILENAME); return 2; } /* Now, grok the release. For AS, we neglect the AS at the end of the * numerical release because we already figured out that it *is* AS * from the infomation above. We assume that all the strings will * have the word 'release' before the numerical release. */ /* Convert relstring to lowercase so that vendors like Scientific Linux don't fall through the cracks. */ for (i = 0; i < strlen(relstring); i++) { relstring[i] = tolower(relstring[i]); } release = strstr(relstring, RELEASE_FLAG); if(release == NULL) { Verbose("Could not find a numeric OS release in %s\n", RH_REL_FILENAME); return 2; } else { release += strlen(RELEASE_FLAG); if (sscanf(release, "%d.%d", &major, &minor) == 2) { sprintf(strmajor, "%d", major); sprintf(strminor, "%d", minor); } /* red hat 9 is *not* red hat 9.0. * and same thing with RHEL AS 3 */ else if (sscanf(release, "%d", &major) == 1) { sprintf(strmajor, "%d", major); minor = -2; } } if (major != -1 && minor != -1 && (strcmp(vendor,"") != 0)) { classbuf[0] = '\0'; strcat(classbuf, vendor); AddClassToHeap(classbuf); strcat(classbuf, "_"); if (strcmp(edition,"") != 0) { strcat(classbuf, edition); AddClassToHeap(classbuf); strcat(classbuf, "_"); } strcat(classbuf, strmajor); AddClassToHeap(classbuf); if (minor != -2) { strcat(classbuf, "_"); strcat(classbuf, strminor); AddClassToHeap(classbuf); } } return 0; } /******************************************************************/ int linux_suse_version(void) { #define SUSE_REL_FILENAME "/etc/SuSE-release" /* Check if it's a SuSE Enterprise version (all in lowercase) */ #define SUSE_SLES8_ID "suse sles-8" #define SUSE_SLES_ID "suse linux enterprise server" #define SUSE_RELEASE_FLAG "linux " /* The full string read in from SuSE-release */ char relstring[CF_MAXVARSIZE]; char classbuf[CF_MAXVARSIZE]; char vbuf[CF_BUFSIZE]; /* Where the numerical release will be found */ char *release=NULL; int i,version; int major = -1; char strmajor[CF_MAXVARSIZE]; int minor = -1; char strminor[CF_MAXVARSIZE]; FILE *fp; /* Grab the first line from the file and then close it. */ if ((fp = fopen(SUSE_REL_FILENAME,"r")) == NULL) { return 1; } fgets(relstring, sizeof(relstring), fp); Chop(relstring); fclose(fp); /* Check if it's a SuSE Enterprise version */ Verbose("Looking for SuSE enterprise info in \"%s\"\n",relstring); /* Convert relstring to lowercase to handle rename of SuSE to * SUSE with SUSE 10.0. */ for (i = 0; i < strlen(relstring); i++) { relstring[i] = tolower(relstring[i]); } /* Check if it's a SuSE Enterprise version (all in lowercase) */ if (!strncmp(relstring, SUSE_SLES8_ID, strlen(SUSE_SLES8_ID))) { classbuf[0] = '\0'; strcat(classbuf, "SLES8"); AddClassToHeap(classbuf); } else { for (version = 9; version < 13; version++) { snprintf(vbuf,CF_BUFSIZE,"%s %d ",SUSE_SLES_ID,version); Debug("Checking for suse [%s]\n",vbuf); if (!strncmp(relstring, vbuf, strlen(vbuf))) { snprintf(classbuf,CF_MAXVARSIZE,"SLES%d",version); AddClassToHeap(classbuf); } } } /* Determine release version. We assume that the version follows * the string "SuSE Linux" or "SUSE LINUX". */ release = strstr(relstring, SUSE_RELEASE_FLAG); if (release == NULL) { Verbose("Could not find a numeric OS release in %s\n",SUSE_REL_FILENAME); return 2; } else { release += strlen(SUSE_RELEASE_FLAG); sscanf(release, "%d.%d", &major, &minor); sprintf(strmajor, "%d", major); sprintf(strminor, "%d", minor); } if(major != -1 && minor != -1) { classbuf[0] = '\0'; strcat(classbuf, "SuSE"); AddClassToHeap(classbuf); strcat(classbuf, "_"); strcat(classbuf, strmajor); AddClassToHeap(classbuf); strcat(classbuf, "_"); strcat(classbuf, strminor); AddClassToHeap(classbuf); } return 0; } int linux_slackware_version(char *filename) { int major = -1; int minor = -1; int release = -1; char classname[CF_MAXVARSIZE] = ""; FILE *fp; if ((fp = fopen(filename,"r")) == NULL) { return 1; } Verbose("Looking for Slackware version...\n"); switch (fscanf(fp, "Slackware %d.%d.%d", &major, &minor, &release)) { case 3: Verbose("This appears to be a Slackware %u.%u.%u system.", major, minor, release); snprintf(classname, CF_MAXVARSIZE, "slackware_%u_%u_%u", major, minor, release); AddClassToHeap(classname); /* Fall-through */ case 2: Verbose("This appears to be a Slackware %u.%u system.", major, minor); snprintf(classname, CF_MAXVARSIZE, "slackware_%u_%u", major, minor); AddClassToHeap(classname); /* Fall-through */ case 1: Verbose("This appears to be a Slackware %u system.", major); snprintf(classname, CF_MAXVARSIZE, "slackware_%u", major); AddClassToHeap(classname); break; case 0: Verbose("No Slackware version number found.\n"); fclose(fp); return 2; } fclose(fp); return 0; } /******************************************************************/ int debian_version(void) /* Andrew Stribblehill */ { #define DEBIAN_VERSION_FILENAME "/etc/debian_version" int major = -1; int release = -1; char classname[CF_MAXVARSIZE] = ""; FILE *fp; if ((fp = fopen(DEBIAN_VERSION_FILENAME,"r")) == NULL) { return 1; } Verbose("Looking for Debian version...\n"); switch (fscanf(fp, "%d.%d", &major, &release)) { case 2: Verbose("This appears to be a Debian %u.%u system.", major, release); snprintf(classname, CF_MAXVARSIZE, "debian_%u_%u", major, release); AddClassToHeap(classname); /* Fall-through */ case 1: Verbose("This appears to be a Debian %u system.", major); snprintf(classname, CF_MAXVARSIZE, "debian_%u", major); AddClassToHeap(classname); break; case 0: Verbose("No Debian version number found.\n"); fclose(fp); return 2; } fclose(fp); return 0; } /******************************************************************/ int linux_mandrake_version(void) { /* We are looking for one of the following strings... */ #define MANDRAKE_ID "Linux Mandrake" #define MANDRAKE_REV_ID "Mandrake Linux" #define MANDRAKE_10_1_ID "Mandrakelinux" #define RELEASE_FLAG "release " #define MANDRAKE_REL_FILENAME "/etc/mandrake-release" FILE *fp; /* The full string read in from mandrake-release */ char relstring[CF_MAXVARSIZE]; char classbuf[CF_MAXVARSIZE]; /* I've never seen Mandrake-Move or the other 'editions', so I'm not going to try and support them here. Contributions welcome. */ /* Where the numerical release will be found */ char *release=NULL; char *vendor=NULL; int major = -1; char strmajor[CF_MAXVARSIZE]; int minor = -1; char strminor[CF_MAXVARSIZE]; /* Grab the first line from the file and then close it. */ if ((fp = fopen(MANDRAKE_REL_FILENAME,"r")) == NULL) { return 1; } fgets(relstring, sizeof(relstring), fp); fclose(fp); Verbose("Looking for Mandrake linux info in \"%s\"\n",relstring); /* Older Mandrakes had the 'Mandrake Linux' string in reverse order */ if(!strncmp(relstring, MANDRAKE_ID, strlen(MANDRAKE_ID))) { vendor = "mandrake"; } else if(!strncmp(relstring, MANDRAKE_REV_ID, strlen(MANDRAKE_REV_ID))) { vendor = "mandrake"; } else if(!strncmp(relstring, MANDRAKE_10_1_ID, strlen(MANDRAKE_10_1_ID))) { vendor = "mandrake"; } else { Verbose("Could not identify OS distro from %s\n", MANDRAKE_REL_FILENAME); return 2; } /* Now, grok the release. We assume that all the strings will * have the word 'release' before the numerical release. */ release = strstr(relstring, RELEASE_FLAG); if(release == NULL) { Verbose("Could not find a numeric OS release in %s\n", MANDRAKE_REL_FILENAME); return 2; } else { release += strlen(RELEASE_FLAG); if (sscanf(release, "%d.%d", &major, &minor) == 2) { sprintf(strmajor, "%d", major); sprintf(strminor, "%d", minor); } else { Verbose("Could not break down release version numbers in %s\n", MANDRAKE_REL_FILENAME); } } if (major != -1 && minor != -1 && strcmp(vendor, "")) { classbuf[0] = '\0'; strcat(classbuf, vendor); AddClassToHeap(classbuf); strcat(classbuf, "_"); strcat(classbuf, strmajor); AddClassToHeap(classbuf); if (minor != -2) { strcat(classbuf, "_"); strcat(classbuf, strminor); AddClassToHeap(classbuf); } } return 0; } /******************************************************************/ static void * lsb_release(const char *command, const char *key) { char * info = NULL; FILE * fp; snprintf(VBUFF, CF_BUFSIZE, "%s %s", command, key); if ((fp = cfpopen(VBUFF, "r")) == NULL) { return NULL; } if (ReadLine(VBUFF, CF_BUFSIZE, fp)) { char * buffer = VBUFF; strsep(&buffer, ":"); while((*buffer != '\0') && isspace(*buffer)) { buffer++; } info = buffer; while((*buffer != '\0') && !isspace(*buffer)) { *buffer = tolower(*buffer++); } *buffer = '\0'; info = strdup(info); } cfpclose(fp); return info; } /******************************************************************/ int lsb_version(void) { #define LSB_RELEASE_COMMAND "lsb_release" char classname[CF_MAXVARSIZE]; char *distrib = NULL; char *release = NULL; char *codename = NULL; int major = 0; int minor = 0; char *path, *dir, *rest; struct stat statbuf; path = rest = strdup(getenv("PATH")); if (strlen(path) == 0) { return 1; } for (; dir = strsep(&rest, ":") ;) { snprintf(VBUFF, CF_BUFSIZE, "%s/" LSB_RELEASE_COMMAND, dir); if (stat(VBUFF,&statbuf) != -1) { free(path); path = strdup(VBUFF); Verbose("\nThis appears to be a LSB compliant system.\n"); AddClassToHeap("lsb_compliant"); break; } } if (!dir) { free(path); return 1; } if ((distrib = lsb_release(path, "--id")) != NULL) { snprintf(classname, CF_MAXVARSIZE, "%s", distrib); AddClassToHeap(classname); if ((codename = lsb_release(path, "--codename")) != NULL) { snprintf(classname, CF_MAXVARSIZE, "%s_%s", distrib, codename); AddClassToHeap(classname); } if ((release = lsb_release(path, "--release")) != NULL) { switch (sscanf(release, "%d.%d\n", &major, &minor)) { case 2: snprintf(classname, CF_MAXVARSIZE, "%s_%u_%u", distrib, major, minor); AddClassToHeap(classname); case 1: snprintf(classname, CF_MAXVARSIZE, "%s_%u", distrib, major); AddClassToHeap(classname); } } free(path); return 0; } else { free(path); return 2; } } /******************************************************************/ int VM_version(void) { FILE *fp; char *sp,buffer[CF_BUFSIZE],classbuf[CF_BUFSIZE],version[CF_BUFSIZE]; struct stat statbuf; int major,minor,bug; int len = 0; int sufficient = 0; /* VMware Server ESX >= 3 has version info in /proc */ if ((fp = fopen("/proc/vmware/version","r")) != NULL) { ReadLine(buffer,CF_BUFSIZE,fp); Chop(buffer); if (sscanf(buffer,"VMware ESX Server %d.%d.%d",&major,&minor,&bug) > 0) { snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %d",major); AddClassToHeap(CanonifyName(classbuf)); snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %d.%d",major,minor); AddClassToHeap(CanonifyName(classbuf)); snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %d.%d.%d",major,minor,bug); AddClassToHeap(CanonifyName(classbuf)); sufficient = 1; } else if (sscanf(buffer,"VMware ESX Server %s",version) > 0) { snprintf(classbuf,CF_BUFSIZE,"VMware ESX Server %s",version); AddClassToHeap(CanonifyName(classbuf)); sufficient = 1; } fclose(fp); } /* Fall back to checking for other files */ if (sufficient < 1 && ((fp = fopen("/etc/vmware-release","r")) != NULL) || (fp = fopen("/etc/issue","r")) != NULL) { ReadLine(buffer,CF_BUFSIZE,fp); Chop(buffer); AddClassToHeap(CanonifyName(buffer)); /* Strip off the release code name e.g. "(Dali)" */ if ((sp = strchr(buffer,'(')) != NULL) { *sp = 0; Chop(buffer); AddClassToHeap(CanonifyName(buffer)); } sufficient = 1; fclose(fp); } return sufficient < 1 ? 1 : 0; } /******************************************************************/ int Xen_domain(void) { FILE *fp; char buffer[CF_BUFSIZE]; int sufficient = 0; /* xen host will have "control_d" in /proc/xen/capabilities, xen guest will not */ if ((fp = fopen("/proc/xen/capabilities","r")) != NULL) { while (!feof(fp)) { ReadLine(buffer,CF_BUFSIZE,fp); if (strstr(buffer,"control_d")) { AddClassToHeap("xen_dom0"); sufficient = 1; } } if (sufficient < 1) { AddClassToHeap("xen_domu_pv"); sufficient = 1; } } return sufficient < 1 ? 1 : 0; } #ifdef XEN_CPUID_SUPPORT /* borrowed from Xen source/tools/libxc/xc_cpuid_x86.c */ void Xen_cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { asm ( /* %ebx register need to be saved before usage and restored thereafter * for PIC-compliant code on i386 */ #ifdef __i386__ "push %%ebx; cpuid; mov %%ebx,%1; pop %%ebx" #else "push %%rbx; cpuid; mov %%ebx,%1; pop %%rbx" #endif : "=a" (*eax), "=r" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (idx), "2" (0) ); } int Xen_hv_check(void) { uint32_t eax, ebx, ecx, edx; char signature[13]; Xen_cpuid(0x40000000, &eax, &ebx, &ecx, &edx); *(uint32_t *)(signature + 0) = ebx; *(uint32_t *)(signature + 4) = ecx; *(uint32_t *)(signature + 8) = edx; signature[12] = '\0'; if ( strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002) ) return 0; Xen_cpuid(0x40000001, &eax, &ebx, &ecx, &edx); return 1; } #endif cfengine-2.2.10/src/proto.c0000644000175000001440000003356210761474333012406 00000000000000/* Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* File Image copying */ /* */ /* client part for remote copying */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ int BadProtoReply(char *buf) { Debug("Protoreply: (%s)\n",buf); return (strncmp(buf,"BAD:",4) == 0); } /*********************************************************************/ int OKProtoReply(char *buf) { return(strncmp(buf,"OK:",3) == 0); } /*********************************************************************/ int FailedProtoReply(char *buf) { return(strncmp(buf,CF_FAILEDSTR,strlen(CF_FAILEDSTR)) == 0); } /*********************************************************************/ int IdentifyForVerification(int sd,char *localip,int family) { char sendbuff[CF_BUFSIZE],dnsname[CF_BUFSIZE]; struct in_addr *iaddr; struct hostent *hp; int len,err; struct passwd *user_ptr; char *uname; #if defined(HAVE_GETADDRINFO) char myaddr[256]; /* Compilation trick for systems that don't know ipv6 */ #else struct sockaddr_in myaddr; #endif memset(sendbuff,0,CF_BUFSIZE); memset(dnsname,0,CF_BUFSIZE); if (!SKIPIDENTIFY && (strcmp(VDOMAIN,CF_START_DOMAIN) == 0)) { CfLog(cferror,"Undefined domain name",""); return false; } if (!SKIPIDENTIFY) { /* First we need to find out the IP address and DNS name of the socket we are sending from. This is not necessarily the same as VFQNAME if the machine has a different uname from its IP name (!) This can happen on stupidly set up machines or on hosts with multiple interfaces, with different names on each interface ... */ switch (family) { case AF_INET: len = sizeof(struct sockaddr_in); break; #if defined(HAVE_GETADDRINFO) case AF_INET6: len = sizeof(struct sockaddr_in6); break; #endif default: CfLog(cferror,"Software error in IdentifyForVerification",""); } if (getsockname(sd,(struct sockaddr *)&myaddr,&len) == -1) { CfLog(cferror,"Couldn't get socket address\n","getsockname"); return false; } snprintf(localip,CF_MAX_IP_LEN-1,"%s",sockaddr_ntop((struct sockaddr *)&myaddr)); Debug("Identifying this agent as %s i.e. %s, with signature %d\n",localip,VFQNAME,CFSIGNATURE); #if defined(HAVE_GETADDRINFO) if ((err=getnameinfo((struct sockaddr *)&myaddr,len,dnsname,CF_MAXVARSIZE,NULL,0,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't look up address v6 for %s: %s\n",dnsname,gai_strerror(err)); CfLog(cferror,OUTPUT,""); return false; } #else iaddr = &(myaddr.sin_addr); hp = gethostbyaddr((void *)iaddr,sizeof(myaddr.sin_addr),family); if ((hp == NULL) || (hp->h_name == NULL)) { CfLog(cferror,"Couldn't lookup IP address\n","gethostbyaddr"); return false; } strncpy(dnsname,hp->h_name,CF_MAXVARSIZE); if ((strstr(hp->h_name,".") == 0) && (strlen(VDOMAIN) > 0)) { strcat(dnsname,"."); strcat(dnsname,VDOMAIN); } #endif } else { strcpy(localip,VIPADDRESS); if (strlen(VFQNAME) > 0) { Verbose("SkipIdent was requested, so we are trusting and annoucning the identity as (%s) for this host\n",VFQNAME); strcat(dnsname,VFQNAME); } else { strcat(dnsname,"skipident"); } } user_ptr = getpwuid(getuid()); uname = user_ptr ? user_ptr->pw_name : "UNKNOWN"; /* Some resolvers will not return FQNAME and missing PTR will give numerical result */ if ((strlen(VDOMAIN) > 0) && !IsIPV6Address(dnsname) && !strchr(dnsname,'.')) { Debug("Appending domain %s to %s\n",VDOMAIN,dnsname); strcat(dnsname,"."); strncat(dnsname,VDOMAIN,CF_MAXVARSIZE/2); } if (strncmp(dnsname,localip,strlen(localip)) == 0) { /* Seems to be a bug in some resolvers that adds garbage, when it just returns the input */ strcpy(dnsname,localip); } if (strlen(dnsname) == 0) { strcpy(dnsname,localip); } snprintf(sendbuff,CF_BUFSIZE-1,"CAUTH %s %s %s %d",localip,dnsname,uname,CFSIGNATURE); Debug("SENT:::%s\n",sendbuff); SendTransaction(sd,sendbuff,0,CF_DONE); return true; } /*********************************************************************/ int KeyAuthentication(struct Image *ip) { char sendbuffer[CF_EXPANDSIZE],in[CF_BUFSIZE],*out,*decrypted_cchall; BIGNUM *nonce_challenge, *bn = NULL; unsigned long err; unsigned char digest[EVP_MAX_MD_SIZE]; int encrypted_len,nonce_len = 0,len; char cant_trust_server, keyname[CF_BUFSIZE]; RSA *server_pubkey = NULL; if (COMPATIBILITY_MODE) { return true; } if (PUBKEY == NULL || PRIVKEY == NULL) { CfLog(cferror,"No public/private key pair found\n",""); return false; } /* Generate a random challenge to authenticate the server */ nonce_challenge = BN_new(); BN_rand(nonce_challenge,CF_NONCELEN,0,0); nonce_len = BN_bn2mpi(nonce_challenge,in); ChecksumString(in,nonce_len,digest,'m'); /* We assume that the server bound to the remote socket is the official one i.e. = root's */ if (OptionIs(CONTEXTID,"HostnameKeys",true)) { snprintf(keyname,CF_BUFSIZE,"root-%s",ip->server); Debug("KeyAuthentication(with hostname key %s)\n",keyname); } else { snprintf(keyname,CF_BUFSIZE,"root-%s",CONN->remoteip); Debug("KeyAuthentication(with IP keyname %s)\n",keyname); } if (server_pubkey = HavePublicKey(keyname)) { cant_trust_server = 'y'; /* encrypted_len = BN_num_bytes(server_pubkey->n);*/ encrypted_len = RSA_size(server_pubkey); } else { cant_trust_server = 'n'; /* have to trust server, since we can't verify id */ encrypted_len = nonce_len; } snprintf(sendbuffer,CF_BUFSIZE,"SAUTH %c %d %d",cant_trust_server,encrypted_len,nonce_len); if ((out = malloc(encrypted_len)) == NULL) { FatalError("memory failure"); } if (server_pubkey != NULL) { if (RSA_public_encrypt(nonce_len,in,out,server_pubkey,RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Public encryption failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); free(out); return false; } memcpy(sendbuffer+CF_RSA_PROTO_OFFSET,out,encrypted_len); } else { memcpy(sendbuffer+CF_RSA_PROTO_OFFSET,in,nonce_len); } /* proposition C1 - Send challenge / nonce */ SendTransaction(CONN->sd,sendbuffer,CF_RSA_PROTO_OFFSET+encrypted_len,CF_DONE); BN_free(bn); BN_free(nonce_challenge); free(out); if (DEBUG||D2) { RSA_print_fp(stdout,PUBKEY,0); } /*Send the public key - we don't know if server has it */ /* proposition C2 */ memset(sendbuffer,0,CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->n,sendbuffer); SendTransaction(CONN->sd,sendbuffer,len,CF_DONE); /* No need to encrypt the public key ... */ /* proposition C3 */ memset(sendbuffer,0,CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->e,sendbuffer); SendTransaction(CONN->sd,sendbuffer,len,CF_DONE); /* check reply about public key - server can break connection here */ /* proposition S1 */ memset(in,0,CF_BUFSIZE); if (ReceiveTransaction(CONN->sd,in,NULL) == -1) { CfLog(cferror,"Protocol transaction broken off",NULL); return false; } if (BadProtoReply(in)) { CfLog(cferror,in,""); return false; } /* Get challenge response - should be md5 of challenge */ /* proposition S2 */ memset(in,0,CF_BUFSIZE); if (ReceiveTransaction(CONN->sd,in,NULL) == -1) { CfLog(cferror,"Protocol transaction broken off",NULL); return false; } if (!ChecksumsMatch(digest,in,'m')) { snprintf(OUTPUT,CF_BUFSIZE,"Challenge response from server %s/%s was incorrect!",ip->server,CONN->remoteip); CfLog(cferror,OUTPUT,""); return false; } else { char server[CF_EXPANDSIZE]; ExpandVarstring(ip->server,server,NULL); if (cant_trust_server == 'y') /* challenge reply was correct */ { Verbose("\n...............................................................\n"); snprintf(OUTPUT,CF_BUFSIZE,"Strong authentication of server=%s connection confirmed\n",server); CfLog(cfverbose,OUTPUT,""); } else { if (ip->trustkey == 'y') { snprintf(OUTPUT,CF_BUFSIZE,"Trusting server identity and willing to accept key from %s=%s",server,CONN->remoteip); CfLog(cferror,OUTPUT,""); } else { snprintf(OUTPUT,CF_BUFSIZE,"Not authorized to trust the server=%s's public key (trustkey=false)\n",server); CfLog(cferror,OUTPUT,""); return false; } } } /* Receive counter challenge from server */ Debug("Receive counter challenge from server\n"); /* proposition S3 */ memset(in,0,CF_BUFSIZE); encrypted_len = ReceiveTransaction(CONN->sd,in,NULL); if (encrypted_len < 0) { CfLog(cferror,"Protocol transaction sent illegal cipher length",NULL); return false; } if ((decrypted_cchall = malloc(encrypted_len)) == NULL) { FatalError("memory failure"); } if (RSA_private_decrypt(encrypted_len,in,decrypted_cchall,PRIVKEY,RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Private decrypt failed = %s, abandoning\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); return false; } /* proposition C4 */ ChecksumString(decrypted_cchall,nonce_len,digest,'m'); Debug("Replying to counter challenge with md5\n"); SendTransaction(CONN->sd,digest,16,CF_DONE); free(decrypted_cchall); /* If we don't have the server's public key, it will be sent */ if (server_pubkey == NULL) { RSA *newkey = RSA_new(); Debug("Collecting public key from server!\n"); /* proposition S4 - conditional */ if ((len = ReceiveTransaction(CONN->sd,in,NULL)) <= 0) { CfLog(cferror,"Protocol error in RSA authentation from IP %s\n",ip->server); return false; } if ((newkey->n = BN_mpi2bn(in,len,NULL)) == NULL) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Private decrypt failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); RSA_free(newkey); return false; } /* proposition S5 - conditional */ if ((len=ReceiveTransaction(CONN->sd,in,NULL)) == 0) { CfLog(cfinform,"Protocol error in RSA authentation from IP %s\n",ip->server); RSA_free(newkey); return false; } if ((newkey->e = BN_mpi2bn(in,len,NULL)) == NULL) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Private decrypt failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); RSA_free(newkey); return false; } SavePublicKey(keyname,newkey); server_pubkey = RSAPublicKey_dup(newkey); RSA_free(newkey); } /* proposition C5 */ GenerateRandomSessionKey(); DebugBinOut(CONN->session_key,CF_BLOWFISHSIZE); if (CONN->session_key == NULL) { CfLog(cferror,"A random session key could not be established",""); return false; } else { Debug("Generated session key\n"); DebugBinOut(CONN->session_key,CF_BLOWFISHSIZE); } /* blowfishmpisize = BN_bn2mpi((BIGNUM *)CONN->session_key,in); */ DebugBinOut(CONN->session_key,CF_BLOWFISHSIZE); encrypted_len = RSA_size(server_pubkey); Debug("Encrypt %d to %d\n",CF_BLOWFISHSIZE,encrypted_len); if ((out = malloc(encrypted_len)) == NULL) { FatalError("memory failure"); } if (RSA_public_encrypt(CF_BLOWFISHSIZE,CONN->session_key,out,server_pubkey,RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); snprintf(OUTPUT,CF_BUFSIZE,"Public encryption failed = %s\n",ERR_reason_error_string(err)); CfLog(cferror,OUTPUT,""); free(out); return false; } Debug("Encryption succeeded\n"); SendTransaction(CONN->sd,out,encrypted_len,CF_DONE); DebugBinOut(out,encrypted_len); if (server_pubkey != NULL) { RSA_free(server_pubkey); } free(out); return true; } /*********************************************************************/ void CheckRemoteVersion() { char sendbuffer[CF_BUFSIZE]; char recvbuffer[CF_BUFSIZE]; int tosend; Debug("CheckRemoteVersion\n"); snprintf(sendbuffer,CF_BUFSIZE,"VERSION"); tosend = strlen(sendbuffer); if (SendTransaction(CONN->sd,sendbuffer,tosend,CF_DONE) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Transmission failed while checking version"); CfLog(cfinform,OUTPUT,"send"); return; } if (ReceiveTransaction(CONN->sd,recvbuffer,NULL) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Reply failed while checking version"); CfLog(cfinform,OUTPUT,"send"); CONN->protoversion = 0; return; } if (BadProtoReply(recvbuffer)) { CONN->protoversion = 0; return; } else { CONN->protoversion = 1; return; } } cfengine-2.2.10/src/repository.c0000644000175000001440000000744710550144564013461 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*********************************************************************/ /* */ /* Repository handler */ /* */ /*********************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include "../pub/global.h" /*********************************************************************/ int Repository(char *file,char *repository) /* Returns true if the file was backup up and false if not */ { char buffer[CF_BUFSIZE]; char localrepository[CF_BUFSIZE]; char node[CF_BUFSIZE]; struct stat sstat, dstat; char *sp; struct Image dummy; short imagecopy; if (repository == NULL) { strncpy(localrepository,VREPOSITORY,CF_BUFSIZE); } else { if (strcmp(repository,"none") == 0 || strcmp(repository,"off") == 0) { return false; } strncpy(localrepository,repository,CF_BUFSIZE); } if (IMAGEBACKUP == 'n') { return true; } if (IsItemIn(VREPOSLIST,file)) { snprintf(OUTPUT,CF_BUFSIZE,"The file %s has already been moved to the repository once.",file); CfLog(cfinform,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE,"Multiple update will cause loss of backup. Use backup=false in copy to override."); CfLog(cfinform,OUTPUT,""); return true; } PrependItem(&VREPOSLIST,file,NULL); if ((strlen(localrepository) == 0) || HOMECOPY) { return false; } Debug2("Repository(%s)\n",file); strcpy (node,file); buffer[0] = '\0'; for (sp = node; *sp != '\0'; sp++) { if (*sp == '/') { *sp = REPOSCHAR; } } strncpy(buffer,localrepository,CF_BUFSIZE-2); AddSlash(buffer); if (BufferOverflow(buffer,node)) { Debug("culprit: Repository()\n"); return false; } strcat(buffer,node); if (!MakeDirectoriesFor(buffer,'y')) { snprintf(OUTPUT,CF_BUFSIZE,"Repository (%s),testfile (%s)",localrepository,buffer); } if (stat(file,&sstat) == -1) { Debug2("Repository file %s not there\n",file); return true; } stat(buffer,&dstat); imagecopy = IMAGEBACKUP; /* without this there would be loop between this */ IMAGEBACKUP = 'n'; /* and Repository */ dummy.server = "localhost"; dummy.inode_cache = NULL; dummy.cache = NULL; dummy.stealth = 'n'; dummy.encrypt = 'n'; dummy.preservetimes = 'n'; dummy.repository = NULL; CheckForHoles(&sstat,&dummy); if (CopyReg(file,buffer,sstat,dstat,&dummy)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Moved %s to repository location %s\n",file,buffer); CfLog(cfinform,OUTPUT,""); IMAGEBACKUP = imagecopy; return true; } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Failed to move %s to repository location %s\n",file,buffer); CfLog(cfinform,OUTPUT,""); IMAGEBACKUP = imagecopy; return false; } } cfengine-2.2.10/src/expand-editfiles.c0000644000175000001440000001411210542766346014463 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /*****************************************************************************/ /* */ /* File: expand-editfiles.c */ /* */ /*****************************************************************************/ int DoRecursiveEditFiles(char *name,int level,struct Edit *ptr,struct stat *sb) { DIR *dirh; struct dirent *dirp; char pcwd[CF_BUFSIZE]; struct stat statbuf; int goback; if (level == -1) { return false; } Debug("RecursiveEditFiles(%s)\n",name); if (!DirPush(name,sb)) { return false; } if ((dirh = opendir(".")) == NULL) { return true; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,name,NULL)) { continue; } if (IgnoreFile(name,dirp->d_name,ptr->ignores)) { continue; } strcpy(pcwd,name); /* Assemble pathname */ AddSlash(pcwd); if (BufferOverflow(pcwd,dirp->d_name)) { return true; } strcat(pcwd,dirp->d_name); if (!FileObjectFilter(pcwd,&statbuf,ptr->filters,editfiles)) { Verbose("Skipping filtered file %s\n",pcwd); continue; } if (TRAVLINKS) { if (lstat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",pcwd); CfLog(cferror,OUTPUT,"stat"); continue; } if (S_ISLNK(statbuf.st_mode) && (statbuf.st_mode != getuid())) { snprintf(OUTPUT,CF_BUFSIZE,"File %s is an untrusted link. cfagent will not follow it with a destructive operation (tidy)",pcwd); continue; } if (stat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"RecursiveCheck was working on %s when this happened:\n",pcwd); CfLog(cferror,OUTPUT,"stat"); continue; } } else { if (lstat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"RecursiveCheck was working in %s when this happened:\n",pcwd); CfLog(cferror,OUTPUT,"lstat"); continue; } } if (S_ISDIR(statbuf.st_mode)) { if (IsMountedFileSystem(&statbuf,pcwd,level)) { continue; } else { if ((ptr->recurse > 1) || (ptr->recurse == CF_INF_RECURSE)) { goback = DoRecursiveEditFiles(pcwd,level-1,ptr,&statbuf); DirPop(goback,name,sb); } else { WrapDoEditFile(ptr,pcwd); } } } else { WrapDoEditFile(ptr,pcwd); } } closedir(dirh); return true; } /********************************************************************/ void DoEditHomeFiles(struct Edit *ptr) { DIR *dirh, *dirh2; struct dirent *dirp, *dirp2; char *sp,homedir[CF_BUFSIZE],dest[CF_BUFSIZE]; struct passwd *pw; struct stat statbuf; struct Item *ip; uid_t uid; if (!MountPathDefined()) { CfLog(cfinform,"Mountpattern is undefined\n",""); return; } for (ip = VMOUNTLIST; ip != NULL; ip=ip->next) { if (IsExcluded(ip->classes)) { continue; } if ((dirh = opendir(ip->name)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",ip->name); CfLog(cferror,OUTPUT,"opendir"); return; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,ip->name,NULL)) { continue; } strcpy(homedir,ip->name); AddSlash(homedir); strcat(homedir,dirp->d_name); if (! IsHomeDir(homedir)) { continue; } if ((dirh2 = opendir(homedir)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory%s\n",homedir); CfLog(cferror,OUTPUT,"opendir"); return; } for (dirp2 = readdir(dirh2); dirp2 != NULL; dirp2 = readdir(dirh2)) { if (!SensibleFile(dirp2->d_name,homedir,NULL)) { continue; } strcpy(dest,homedir); AddSlash(dest); strcat(dest,dirp2->d_name); AddSlash(dest); sp = ptr->fname + strlen("home/"); strcat(dest,sp); if (stat(dest,&statbuf)) { EditVerbose("File %s doesn't exist for editing, skipping\n",dest); continue; } if ((pw = getpwnam(dirp2->d_name)) == NULL) { Debug2("cfengine: directory corresponds to no user %s - ignoring\n",dirp2->d_name); continue; } else { Debug2("(Setting user id to %s)\n",dirp2->d_name); } uid = statbuf.st_uid; WrapDoEditFile(ptr,dest); chown(dest,uid,CF_SAME_OWNER); } closedir(dirh2); } closedir(dirh); } } cfengine-2.2.10/src/cfagent.c0000644000175000001440000013603611140113300012622 00000000000000/* Copyright (C) 1994- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Cfengine : a site configuration langugae */ /* */ /* Module: (main) cfengine.c */ /* */ /* Mark Burgess 1994/96 */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*******************************************************************/ /* Functions internal to cfengine.c */ /*******************************************************************/ int main (int argc,char *argv[]); void Initialize (int argc, char **argv); void PreNetConfig (void); void ReadRCFile (void); void EchoValues (void); void CheckSystemVariables (void); void SetReferenceTime (int setclasses); void SetStartTime (int setclasses); void DoTree (int passes, char *info); enum aseq EvaluateAction (char *action, struct Item **classlist, int pass); void CheckOpts (int argc, char **argv); int GetResource (char *var); void Syntax (void); void EmptyActionSequence (void); void GetEnvironment (void); int NothingLeftToDo (void); void SummarizeObjects (void); void SetContext (char *id); void DeleteCaches (void); void QueryCheck(void); /*******************************************************************/ /* Command line options */ /*******************************************************************/ /* GNU STUFF FOR LATER #include "getopt.h" */ struct option OPTIONS[49] = { { "auto",no_argument,0,'A'}, { "sysadm",no_argument,0,'a' }, { "update-only",no_argument,0,'B'}, { "force-net-copy",no_argument,0,'b'}, { "no-check-mounts",no_argument,0,'C' }, { "no-check-files",no_argument,0,'c' }, { "define",required_argument,0,'D' }, { "debug",optional_argument,0,'d' }, { "enforce-links",no_argument,0,'E'}, { "no-edits",no_argument,0,'e'}, { "file",required_argument,0,'f' }, { "check-contradictions",no_argument,0,'g'}, { "help",no_argument,0,'h' }, { "no-hard-classes",no_argument,0,'H'}, { "inform",no_argument,0,'I'}, { "no-ifconfig",no_argument,0,'i' }, { "just",required_argument,0,'j'}, { "no-lock",no_argument,0,'K'}, { "no-copy",no_argument,0,'k'}, { "delete-stale-links",no_argument,0,'L' }, { "traverse-links",no_argument,0,'l' }, { "no-modules",no_argument,0,'M'}, { "negate",required_argument,0,'N' }, { "no-mount",no_argument,0,'m' }, { "undefine",required_argument,0,'N' }, { "just-print",no_argument,0,'n'}, { "recon",no_argument,0,'n' }, { "dry-run",no_argument,0,'n'}, { "avoid",required_argument,0,'o'}, { "no-processes",no_argument,0,'P'}, { "parse-only",no_argument,0,'p' }, { "query",required_argument,0,'Q'}, { "no-splay",no_argument,0,'q'}, { "silent",no_argument,0,'S' }, { "no-commands",no_argument,0,'s' }, { "no-tidy",no_argument,0,'t' }, { "underscore-classes",no_argument,0,'U'}, { "use-env",no_argument,0,'u'}, { "version",no_argument,0,'V' }, { "verbose",no_argument,0,'v' }, { "csdb",no_argument,0,'W'}, { "no-warn",no_argument,0,'w' }, { "quiet",no_argument,0,'w' }, { "no-preconf",no_argument,0,'x' }, { "no-links",no_argument,0,'X'}, { "secure-input",no_argument,0,'Y'}, { "method",required_argument,0,'Z' }, { "zone-info",no_argument,0,'z'}, { NULL,0,0,0 } }; /*******************************************************************/ /* Level 0 : Main */ /*******************************************************************/ int main(int argc,char *argv[]) { struct Item *ip; SetContext("global"); SetSignals(); signal (SIGTERM,HandleSignal); /* Signal Handler */ signal (SIGHUP,HandleSignal); signal (SIGINT,HandleSignal); signal (SIGPIPE,HandleSignal); signal (SIGUSR1,HandleSignal); signal (SIGUSR2,HandleSignal); Initialize(argc,argv); SetReferenceTime(true); SetStartTime(false); if (! NOHARDCLASSES) { GetNameInfo(); GetInterfaceInfo(); GetV6InterfaceInfo(); GetEnvironment(); } PreNetConfig(); ReadRCFile(); /* Should come before parsing so that it can be overridden */ if (IsPrivileged() && !MINUSF && !PRSCHEDULE) { SetContext("update"); if (ParseInputFile("update.conf",true)) { CheckSystemVariables(); if (!PARSEONLY && (QUERYVARS == NULL)) { DoTree(2,"Update"); DoAlerts(); EmptyActionSequence(); DeleteClassesFromContext("update"); DeleteCaches(); } VIMPORT = NULL; } else { Verbose("Skipping update.conf (-F=%d)\n",MINUSF); } if (ERRORCOUNT > 0) { exit(1); } } if (UPDATEONLY) { return 0; } SetContext("main"); if (!PARSEONLY) { PersistentClassesToHeap(); GetEnvironment(); } ParseInputFile(VINPUTFILE,true); CheckFilters(); EchoValues(); /* CheckForMethod(); Move to InitializeAction */ if (PRSYSADM) /* -a option */ { printf("%s\n",VSYSADM); exit (0); } if (PRSCHEDULE) { for (ip = SCHEDULE; ip != NULL; ip=ip->next) { printf("[%s]\n",ip->name); } printf("\n"); exit(0); } if (ERRORCOUNT > 0) { exit(1); } if (PARSEONLY) /* Establish lock for root */ { exit(0); } CfOpenLog(); CheckSystemVariables(); CfCheckAudit(); SetReferenceTime(false); /* Reset */ QueryCheck(); DoTree(3,"Main Tree"); DoAlerts(); CheckMethodReply(); if (OptionIs(CONTEXTID,"ChecksumPurge", true)) { ChecksumPurge(); } RecordClassUsage(); SummarizeObjects(); CloseAuditLog(); closelog(); return 0; } /*******************************************************************/ /* Level 1 */ /*******************************************************************/ void Initialize(int argc,char *argv[]) { char *sp, **cfargv; int i, j, cfargc, seed; struct stat statbuf; unsigned char s[16]; char ebuff[CF_EXPANDSIZE]; strcpy(VDOMAIN,CF_START_DOMAIN); PreLockState(); ISCFENGINE = true; VFACULTY[0] = '\0'; VSYSADM[0] = '\0'; VNETMASK[0]= '\0'; VBROADCAST[0] = '\0'; VMAILSERVER[0] = '\0'; ALLCLASSBUFFER[0] = '\0'; VREPOSITORY = strdup("\0"); strcpy(METHODNAME,"cf-nomethod"); METHODREPLYTO[0] = '\0'; METHODFOR[0] = '\0'; #ifndef HAVE_REGCOMP re_syntax_options |= RE_INTERVALS; #endif strcpy(VINPUTFILE,"cfagent.conf"); strcpy(VNFSTYPE,"nfs"); IDClasses(); /* Note we need to fix the options since the argv mechanism doesn't */ /* work when the shell #!/bla/cfengine -v -f notation is used. */ /* Everything ends up inside a single argument! Here's the fix */ cfargc = 1; /* Pass 1: Find how many arguments there are. */ for (i = 1, j = 1; i < argc; i++) { sp = argv[i]; while (*sp != '\0') { while (*sp == ' ' && *sp != '\0') /* Skip to arg */ { sp++; } cfargc++; while (*sp != ' ' && *sp != '\0') /* Skip to white space */ { sp++; } } } /* Allocate memory for cfargv. */ cfargv = (char **) malloc(sizeof(char *) * (cfargc + 1)); if (!cfargv) { FatalError("cfagent: Out of memory parsing arguments\n"); } /* Pass 2: Parse the arguments. */ cfargv[0] = "cfagent"; for (i = 1, j = 1; i < argc; i++) { sp = argv[i]; while (*sp != '\0') { while (*sp == ' ' && *sp != '\0') /* Skip to arg */ { if (*sp == ' ') { *sp = '\0'; /* Break argv string */ } sp++; } cfargv[j++] = sp; while (*sp != ' ' && *sp != '\0') /* Skip to white space */ { sp++; } } } cfargv[j] = NULL; VDEFAULTBINSERVER.name = ""; VEXPIREAFTER = VDEFAULTEXPIREAFTER; VIFELAPSED = VDEFAULTIFELAPSED; TRAVLINKS = false; /* XXX Initialize workdir for non privileged users */ strcpy(CFWORKDIR,WORKDIR); #ifndef NT if (getuid() > 0) { char *homedir; if ((homedir = getenv("HOME")) != NULL) { strcpy(CFWORKDIR,homedir); strcat(CFWORKDIR,"/.cfagent"); } } #endif sprintf(ebuff,"%s/state/cf_procs",CFWORKDIR); if (stat(ebuff,&statbuf) == -1) { CreateEmptyFile(ebuff); } sprintf(ebuff,"%s/state/cf_rootprocs",CFWORKDIR); if (stat(ebuff,&statbuf) == -1) { CreateEmptyFile(ebuff); } sprintf(ebuff,"%s/state/cf_otherprocs",CFWORKDIR); if (stat(ebuff,&statbuf) == -1) { CreateEmptyFile(ebuff); } strcpy(VLOGDIR,CFWORKDIR); strcpy(VLOCKDIR,VLOGDIR); /* Same since 2.0.a8 */ OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); CheckWorkDirectories(); RandomSeed(); RAND_bytes(s,16); s[15] = '\0'; seed = ElfHash(s); srand48((long)seed); CheckOpts(cfargc,cfargv); free(cfargv); AddInstallable("no_default_route"); CfenginePort(); StrCfenginePort(); } /*******************************************************************/ void PreNetConfig() /* Execute a shell script */ { struct stat buf; char comm[CF_BUFSIZE],ebuff[CF_EXPANDSIZE]; char *sp; FILE *pp; if (NOPRECONFIG) { CfLog(cfverbose,"Ignoring the cf.preconf file: option set",""); return; } strcpy(VPREFIX,"cfengine:"); strcat(VPREFIX,VUQNAME); if ((sp=getenv(CF_INPUTSVAR)) != NULL) { snprintf(comm,CF_BUFSIZE,"%s/%s",sp,VPRECONFIG); if (stat(comm,&buf) == -1) { CfLog(cfverbose,"No preconfiguration file",""); return; } snprintf(comm,CF_BUFSIZE,"%s/%s %s 2>&1",sp,VPRECONFIG,CLASSTEXT[VSYSTEMHARDCLASS]); } else { snprintf(comm,CF_BUFSIZE,"%s/%s",CFWORKDIR,VPRECONFIG); if (stat(comm,&buf) == -1) { CfLog(cfverbose,"No preconfiguration file\n",""); return; } snprintf(comm,CF_BUFSIZE,"%s/%s %s",CFWORKDIR,VPRECONFIG,CLASSTEXT[VSYSTEMHARDCLASS]); } if (S_ISDIR(buf.st_mode) || S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error: %s was not a regular file\n",VPRECONFIG); CfLog(cferror,OUTPUT,""); FatalError("Aborting."); } Verbose("\n\nExecuting Net Preconfiguration script...%s\n\n",VPRECONFIG); if ((pp = cfpopen(comm,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Failed to open pipe to %s\n",comm); CfLog(cferror,OUTPUT,""); return; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { CfLog(cferror,"Error running preconfig\n","ferror"); break; } ReadLine(ebuff,CF_BUFSIZE,pp); if (feof(pp)) { break; } if (strstr(ebuff,"cfengine-preconf-abort")) { exit(2); } if (ferror(pp)) /* abortable */ { CfLog(cferror,"Error running preconfig\n","ferror"); break; } CfLog(cfinform,ebuff,""); } cfpclose(pp); } /*******************************************************************/ void DeleteCaches() { /* DeleteItemList(VEXCLUDECACHE); ?? */ } /*******************************************************************/ void ReadRCFile() { char filename[CF_BUFSIZE], buffer[CF_BUFSIZE], *mp; char class[CF_MAXVARSIZE], variable[CF_MAXVARSIZE], value[CF_MAXVARSIZE]; int c; FILE *fp; filename[0] = buffer[0] = class[0] = variable[0] = value[0] = '\0'; LINENUMBER = 0; snprintf(filename,CF_BUFSIZE,"%s/inputs/%s",CFWORKDIR,VRCFILE); if ((fp = fopen(filename,"r")) == NULL) /* Open root file */ { return; } while (!feof(fp)) { ReadLine(buffer,CF_BUFSIZE,fp); LINENUMBER++; class[0]='\0'; variable[0]='\0'; value[0]='\0'; if (strlen(buffer) == 0 || buffer[0] == '#') { continue; } if (strstr(buffer,":") == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Malformed line (missing :) in resource file %s - skipping\n",VRCFILE); CfLog(cferror,OUTPUT,""); continue; } sscanf(buffer,"%[^.].%[^:]:%[^\n]",class,variable,value); if (class[0] == '\0' || variable[0] == '\0' || value[0] == '\0') { snprintf(OUTPUT,CF_BUFSIZE*2,"%s:%s - Bad resource\n",VRCFILE,buffer); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"class=%s,variable=%s,value=%s\n",class,variable,value); CfLog(cferror,OUTPUT,""); FatalError("Bad resource"); } if (strcmp(CLASSTEXT[VSYSTEMHARDCLASS],class) != 0) { continue; /* No point if not equal*/ } if ((mp = strdup(value)) == NULL) { perror("malloc"); FatalError("malloc in ReadRCFile"); } snprintf(OUTPUT,CF_BUFSIZE*2,"Redefining resource %s as %s (%s)\n",variable,value,class); CfLog(cfverbose,OUTPUT,""); c = VSYSTEMHARDCLASS; switch (GetResource(variable)) { case rmountcom: VMOUNTCOMM[c] = mp; break; case runmountcom: VUNMOUNTCOMM[c] = mp; break; case rethernet: VIFDEV[c] = mp; break; case rmountopts: VMOUNTOPTS[c] = mp; break; case rfstab: VFSTAB[c] = mp; break; case rmaildir: VMAILDIR[c] = mp; break; case rnetstat: VNETSTAT[c] = mp; break; case rpscomm: VPSCOMM[c] = mp; break; case rpsopts: VPSOPTS[c] = mp; break; default: snprintf(OUTPUT,CF_BUFSIZE,"Bad resource %s in %s\n",variable,VRCFILE); FatalError(OUTPUT); break; } } fclose(fp); } /*******************************************************************/ void EmptyActionSequence() { DeleteItemList(VACTIONSEQ); VACTIONSEQ = NULL; } /*******************************************************************/ void EchoValues() { struct Item *ip,*p2; char ebuff[CF_EXPANDSIZE]; ebuff[0] = '\0'; if (GetMacroValue(CONTEXTID,"OutputPrefix")) { ExpandVarstring("$(OutputPrefix)",ebuff,NULL); } if (strlen(ebuff) != 0) { strncpy(VPREFIX,ebuff,40); /* No more than 40 char prefix (!) */ } else { strcpy(VPREFIX,"cfengine:"); strcat(VPREFIX,VUQNAME); } p2 = SortItemListNames(VHEAP); VHEAP = p2; if (VERBOSE || DEBUG || D2 || D3) { struct Item *ip; ListDefinedClasses(); printf("\nGlobal expiry time for locks: %d minutes\n",VEXPIREAFTER); printf("\nGlobal anti-spam elapse time: %d minutes\n\n",VIFELAPSED); printf("Extensions which should not be directories = ( "); for (ip = EXTENSIONLIST; ip != NULL; ip=ip->next) { printf("%s ",ip->name); } printf(")\n"); printf("Suspicious filenames to be warned about = ( "); for (ip = SUSPICIOUSLIST; ip != NULL; ip=ip->next) { printf("%s ",ip->name); } printf(")\n"); } if (DEBUG || D2 || D3) { printf("\nFully qualified hostname is: %s\n",VFQNAME); printf("Unqualified hostname is: %s\n",VUQNAME); printf("\nSystem administrator mail address is: %s\n",VSYSADM); printf("Sensible size = %d\n",SENSIBLEFSSIZE); printf("Sensible count = %d\n",SENSIBLEFILECOUNT); printf("Edit File (Max) Size = %d\n\n",EDITFILESIZE); printf("Edit Binary File (Max) Size = %d\n\n",EDITBINFILESIZE); printf("------------------------------------------------------------\n"); ListDefinedInterfaces(NULL); printf("------------------------------------------------------------\n"); ListDefinedBinservers(NULL); printf("------------------------------------------------------------\n"); ListDefinedHomeservers(NULL); printf("------------------------------------------------------------\n"); ListDefinedHomePatterns(NULL); printf("------------------------------------------------------------\n"); ListActionSequence(); printf("\nWill need to copy from the following trusted sources = ( "); for (ip = VSERVERLIST; ip !=NULL; ip=ip->next) { printf("%s ",ip->name); } printf(")\n"); printf("\nUsing mailserver %s\n",VMAILSERVER); printf("\nLocal mountpoints: "); for (ip = VMOUNTLIST; ip != NULL; ip=ip->next) { printf ("%s ",ip->name); } printf("\n"); if (VDEFAULTROUTE != NULL) { if (IsDefinedClass(VDEFAULTROUTE->classes)) { printf("\nDefault route for packets %s\n\n",VDEFAULTROUTE->name); } } printf("\nFile repository = %s\n\n",VREPOSITORY); printf("\nNet interface name = %s\n",VIFDEV[VSYSTEMHARDCLASS]); printf("------------------------------------------------------------\n"); ListDefinedImports(); printf("------------------------------------------------------------\n"); ListDefinedVariables(); printf("------------------------------------------------------------\n"); ListDefinedStrategies(NULL); printf("------------------------------------------------------------\n"); ListACLs(); printf("------------------------------------------------------------\n"); ListFilters(NULL); printf("------------------------------------------------------------\n"); ListDefinedIgnore(NULL); printf("------------------------------------------------------------\n"); printf("------------------------------------------------------------\n"); ListDefinedAlerts(NULL); printf("------------------------------------------------------------\n"); ListDefinedDisable(NULL); printf("------------------------------------------------------------\n"); ListFiles(NULL); ListDefinedMakePaths(NULL); printf("------------------------------------------------------------\n"); ListFileEdits(NULL); printf("------------------------------------------------------------\n"); ListDefinedImages(NULL); printf("------------------------------------------------------------\n"); ListDefinedLinks(NULL); printf("------------------------------------------------------------\n"); ListDefinedLinkchs(NULL); printf("------------------------------------------------------------\n"); ListDefinedMethods(NULL); printf("------------------------------------------------------------\n"); ListDefinedMountables(NULL); printf("------------------------------------------------------------\n"); ListMiscMounts(NULL); printf("------------------------------------------------------------\n"); ListUnmounts(NULL); printf("------------------------------------------------------------\n"); ListDefinedPackages(NULL); printf("------------------------------------------------------------\n"); ListProcesses(NULL); printf("------------------------------------------------------------\n"); ListDefinedRequired(NULL); printf("------------------------------------------------------------\n"); ListDefinedResolvers(NULL); printf("------------------------------------------------------------\n"); ListDefinedSCLI(NULL); printf("------------------------------------------------------------\n"); ListDefinedScripts(NULL); printf("------------------------------------------------------------\n"); ListDefinedTidy(NULL); printf("------------------------------------------------------------\n"); if (IGNORELOCK) { printf("\nIgnoring locks...\n"); } } } /*******************************************************************/ void CheckSystemVariables() { char id[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; int time, hash, activecfs, locks; Debug2("\n\n"); if (VACTIONSEQ == NULL) { Warning("actionsequence is empty "); Warning("perhaps cfagent.conf/update.conf have not yet been set up?"); } ACTION = none; sprintf(id,"%d",geteuid()); /* get effective user id */ ebuff[0] = '\0'; if (!StrStr(VSYSNAME.nodename,VDOMAIN)) { snprintf(VFQNAME,CF_BUFSIZE,"%s.%s",VSYSNAME.nodename,ToLowerStr(VDOMAIN)); strcpy(VUQNAME,VSYSNAME.nodename); } else { int n = 0; strcpy(VFQNAME,VSYSNAME.nodename); while(VSYSNAME.nodename[n++] != '.') { } strncpy(VUQNAME,VSYSNAME.nodename,n-1); } Verbose("Accepted domain name: %s\n\n",VDOMAIN); if (VACCESSLIST != NULL && !IsItemIn(VACCESSLIST,id)) { FatalError("Access denied - user not listed in access list"); } Debug2("cfagent -d : Debugging output enabled.\n"); EDITVERBOSE = false; if (DONTDO && (VERBOSE || DEBUG || D2)) { printf("cfagent -n: Running in ``All talk and no action'' mode\n"); } if (TRAVLINKS && (VERBOSE || DEBUG || D2)) { printf("cfagent -l : will traverse symbolic links\n"); printf(" WARNING: This is inherently insecure, if there are untrusted users!\n"); } if ( ! IFCONF && (VERBOSE || DEBUG || D2)) { printf("cfagent -i : suppressing interface configuration\n"); } if ( NOFILECHECK && (VERBOSE || DEBUG || D2)) { printf("cfagent -c : suppressing file checks\n"); } if ( NOSCRIPTS && (VERBOSE || DEBUG || D2)) { printf("cfagent -s : suppressing script execution\n"); } if ( NOTIDY && (VERBOSE || DEBUG || D2)) { printf("cfagent -t : suppressing tidy function\n"); } if ( NOMOUNTS && (VERBOSE || DEBUG || D2)) { printf("cfagent -m : suppressing mount operations\n"); } if ( MOUNTCHECK && (VERBOSE || DEBUG || D2)) { printf("cfagent -C : check mount points\n"); } if (ERRORCOUNT > 0) { FatalError("Execution terminated after parsing due to errors in program"); } VCANONICALFILE = strdup(CanonifyName(VINPUTFILE)); if (GetMacroValue(CONTEXTID,"LockDirectory")) { Verbose("\n[LockDirectory is no longer used - same as LogDirectory]\n\n"); } if (GetMacroValue(CONTEXTID,"LogDirectory")) { Verbose("\n[LogDirectory is no longer runtime configurable: use configure --with-workdir=CFWORKDIR ]\n\n"); } Verbose("LogDirectory = %s\n",VLOGDIR); LoadSecretKeys(); if (GetMacroValue(CONTEXTID,"childlibpath")) { snprintf(OUTPUT,CF_BUFSIZE,"LD_LIBRARY_PATH=%s",GetMacroValue(CONTEXTID,"childlibpath")); if (putenv(strdup(OUTPUT)) == 0) { Verbose("Setting %s\n",OUTPUT); } else { Verbose("Failed to set %s\n",GetMacroValue(CONTEXTID,"childlibpath")); } } if (GetMacroValue(CONTEXTID,"BindToInterface")) { ExpandVarstring("$(BindToInterface)",ebuff,NULL); strncpy(BINDINTERFACE,ebuff,CF_BUFSIZE-1); Debug("$(BindToInterface) Expanded to %s\n",BINDINTERFACE); } if (GetMacroValue(CONTEXTID,"MaxCfengines")) { activecfs = atoi(GetMacroValue(CONTEXTID,"MaxCfengines")); locks = CountActiveLocks(); if (locks >= activecfs) { snprintf(OUTPUT,CF_BUFSIZE*2,"Too many cfagents running (%d/%d)\n",locks,activecfs); CfLog(cferror,OUTPUT,""); closelog(); exit(1); } } if (OptionIs(CONTEXTID,"SkipIdentify",true)) { SKIPIDENTIFY = true; } if (OptionIs(CONTEXTID,"Verbose",true)) { VERBOSE = true; } if (OptionIs(CONTEXTID,"LastSeen",false)) { LASTSEEN = false; } if (OptionIs(CONTEXTID,"FullEncryption",true)) { FULLENCRYPT = true; } if (OptionIs(CONTEXTID,"Inform",true)) { INFORM = true; } if (OptionIs(CONTEXTID,"Exclamation",false)) { EXCLAIM = false; } if (OptionIs(CONTEXTID,"Auditing",true)) { AUDIT = true; } INFORM_save = INFORM; if (OptionIs(CONTEXTID,"Syslog",true)) { LOGGING = true; } LOGGING_save = LOGGING; if (OptionIs(CONTEXTID,"DryRun",true)) { DONTDO = true; AddClassToHeap("opt_dry_run"); } if (GetMacroValue(CONTEXTID,"BinaryPaddingChar")) { strcpy(ebuff,GetMacroValue(CONTEXTID,"BinaryPaddingChar")); if (ebuff[0] == '\\') { switch (ebuff[1]) { case '0': PADCHAR = '\0'; break; case '\n': PADCHAR = '\n'; break; case '\\': PADCHAR = '\\'; } } else { PADCHAR = ebuff[0]; } } if (OptionIs(CONTEXTID,"Warnings",true)) { WARNINGS = true; } if (OptionIs(CONTEXTID,"NonAlphaNumFiles",true)) { NONALPHAFILES = true; } if (OptionIs(CONTEXTID,"SecureInput",true)) { CFPARANOID = true; } if (OptionIs(CONTEXTID,"ShowActions",true)) { SHOWACTIONS = true; } if (GetMacroValue(CONTEXTID,"Umask")) { mode_t val; val = (mode_t)atoi(GetMacroValue(CONTEXTID,"Umask")); if (umask(val) == (mode_t)-1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't set umask to %o\n",val); CfLog(cferror,OUTPUT,"umask"); } } if (GetMacroValue(CONTEXTID,"DefaultCopyType")) { if (strcmp(GetMacroValue(CONTEXTID,"DefaultCopyType"),"mtime") == 0) { DEFAULTCOPYTYPE = 'm'; } if (strcmp(GetMacroValue(CONTEXTID,"DefaultCopyType"),"checksum") == 0) { DEFAULTCOPYTYPE = 'c'; } if (strcmp(GetMacroValue(CONTEXTID,"DefaultCopyType"),"binary") == 0) { DEFAULTCOPYTYPE = 'b'; } if (strcmp(GetMacroValue(CONTEXTID,"DefaultCopyType"),"ctime") == 0) { DEFAULTCOPYTYPE = 't'; } } if (GetMacroValue(CONTEXTID,"ChecksumDatabase")) { FatalError("ChecksumDatabase variable is deprecated - comment it out"); } else { snprintf(ebuff,CF_BUFSIZE,"%s/%s",CFWORKDIR,CF_CHKDB); CHECKSUMDB = strdup(ebuff); } if (SHOWDB) { printf("%s\n",CHECKSUMDB); exit(0); } Verbose("Checksum database is %s\n",CHECKSUMDB); if (GetMacroValue(CONTEXTID,"CompressCommand")) { ExpandVarstring("$(CompressCommand)",ebuff,NULL); COMPRESSCOMMAND = strdup(ebuff); if (*COMPRESSCOMMAND != '/') { FatalError("$(CompressCommand) does not expand to an absolute filename\n"); } } if (OptionIs(CONTEXTID,"ChecksumUpdates",true)) { CHECKSUMUPDATES = true; } if (GetMacroValue(CONTEXTID,"TimeOut")) { time = atoi(GetMacroValue(CONTEXTID,"TimeOut")); if (time < 3 || time > 60) { CfLog(cfinform,"TimeOut not between 3 and 60 seconds, ignoring.\n",""); } else { CF_TIMEOUT = time; } } /* Make sure we have a healthy binserver list so binserver expansion works, even if binserver not defined */ if (VBINSERVERS == NULL) { PrependItem(&VBINSERVERS,VUQNAME,NULL); } if (VBINSERVERS->name != NULL) { VDEFAULTBINSERVER = *VBINSERVERS; Verbose("Default binary server seems to be %s\n",VDEFAULTBINSERVER.name); } AppendItem(&VBINSERVERS,VUQNAME,NULL); /* Done binserver massage */ if (NOSPLAY) { return; } time = 0; snprintf(ebuff,CF_BUFSIZE,"%s+%s+%d",VFQNAME,VIPADDRESS,getuid()); hash = Hash(ebuff); if (!NOSPLAY) { if (GetMacroValue(CONTEXTID,"SplayTime")) { time = atoi(GetMacroValue(CONTEXTID,"SplayTime")); if (time < 0) { CfLog(cfinform,"SplayTime with negative value, ignoring.\n",""); return; } if (!DONESPLAY) { if (!PARSEONLY) { DONESPLAY = true; Verbose("Sleeping for SplayTime %d seconds\n\n",(int)(time*60*hash/CF_HASHTABLESIZE)); sleep((int)(time*60*hash/CF_HASHTABLESIZE)); } } else { Verbose("Time splayed once already - not repeating\n"); } } } if (OptionIs(CONTEXTID,"LogTidyHomeFiles",false)) { LOGTIDYHOMEFILES = false; } } /*******************************************************************/ void QueryCheck() { char src[CF_MAXVARSIZE],ebuff[CF_EXPANDSIZE]; struct Item *ip; if (QUERYVARS == NULL) { return; } for (ip = QUERYVARS; ip != NULL; ip=ip->next) { snprintf(src,CF_MAXVARSIZE,"$(%s)",ip->name); ExpandVarstring(src,ebuff,""); printf("%s=%s\n",ip->name,ebuff); } exit(0); } /*******************************************************************/ void DoTree(int passes,char *info) { struct Item *action; Debug("DoTree(%d,%s)\n",passes,info); for (PASS = 1; PASS <= passes; PASS++) { for (action = VACTIONSEQ; action !=NULL; action=action->next) { SetStartTime(false); if (VJUSTACTIONS && (!IsItemIn(VJUSTACTIONS, action->name))) { continue; } if (VAVOIDACTIONS && IsItemIn(VAVOIDACTIONS, action->name)) { continue; } if (IsExcluded(action->classes)) { continue; } if ((PASS > 1) && NothingLeftToDo()) { break; } Verbose("\n*********************************************************************\n"); Verbose(" %s Sched: %s pass %d @ %s",info,action->name,PASS,ctime(&CFINITSTARTTIME)); Verbose("*********************************************************************\n\n"); switch (EvaluateAction(action->name,&VADDCLASSES,PASS)) { case mountinfo: if (PASS == 1) { GetHomeInfo(); GetMountInfo(); } break; case mkpaths: if (!NOFILECHECK) { GetSetuidLog(); MakePaths(); SaveSetuidLog(); } break; case lnks: MakeChildLinks(); MakeLinks(); break; case chkmail: MailCheck(); break; case mountall: if (!NOMOUNTS && PASS == 1) { MountFileSystems(); } break; case requir: case diskreq: CheckRequired(); break; case tidyf: if (!NOTIDY) { TidyFiles(); } break; case shellcom: if (!NOSCRIPTS) { Scripts(); SCLIScript(); } break; case chkfiles: if (!NOFILECHECK) { GetSetuidLog(); CheckFiles(); SaveSetuidLog(); } break; case disabl: case renam: DisableFiles(); break; case mountresc: if (!NOMOUNTS) { if (!GetLock("Mountres",CanonifyName(VFSTAB[VSYSTEMHARDCLASS]),0,VEXPIREAFTER,VUQNAME,0)) { exit(0); /* Note IFELAPSED must be zero to avoid conflict with mountresc */ } MountHomeBinServers(); MountMisc(); ReleaseCurrentLock(); } break; case umnt: Unmount(); break; case edfil: if (!NOEDITS) { EditFiles(); } break; case resolv: if (PASS > 1) { continue; } if (!GetLock(ASUniqueName("resolve"),"",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME)) { continue; } CheckResolv(); ReleaseCurrentLock(); break; case imag: if (!NOCOPY) { GetSetuidLog(); MakeImages(); SaveSetuidLog(); } break; case netconfig: if (IFCONF) { ConfigureInterfaces(); } break; case tzone: CheckTimeZone(); break; case procs: if (!NOPROCS) { CheckProcesses(); } break; case meths: if (!NOMETHODS) { DoMethods(); } break; case pkgs: CheckPackages(); break; case plugin: break; default: snprintf(OUTPUT,CF_BUFSIZE*2,"Undefined action %s in sequence\n",action->name); FatalError(OUTPUT); break; } DeleteItemList(VADDCLASSES); VADDCLASSES = NULL; } } } /*******************************************************************/ int NothingLeftToDo() /* Check the *probable* source for additional action */ { struct ShellComm *vscript; struct Link *vlink; struct File *vfile; struct Disable *vdisablelist; struct File *vmakepath; struct Link *vchlink; struct UnMount *vunmount; struct Edit *veditlist; struct Process *vproclist; struct Tidy *vtidy; struct Package *vpkg; struct Image *vcopy; if (IsWildItemIn(VACTIONSEQ,"process*")) { for (vproclist = VPROCLIST; vproclist != NULL; vproclist=vproclist->next) { if ((vproclist->done == 'n') && IsDefinedClass(vproclist->classes)) { Verbose("Checking for potential rule:: Proc <%s> / %s\n",vproclist->expr,vproclist->classes); return false; } } } if (IsWildItemIn(VACTIONSEQ,"shellcomman*")) { for (vscript = VSCRIPT; vscript != NULL; vscript=vscript->next) { if ((vscript->done == 'n') && IsDefinedClass(vscript->classes)) { Verbose("Checking for potential rule:: Shell <%s> / %s\n",vscript->name,vscript->classes); return false; } } } if (IsWildItemIn(VACTIONSEQ,"cop*")) { for (vcopy = VIMAGE; vcopy != NULL; vcopy=vcopy->next) { if ((vcopy->done == 'n') && IsDefinedClass(vcopy->classes)) { Verbose("Checking for potential rule:: Copy <%s> / %s\n",vcopy->path,vcopy->classes); return false; } } } if (IsWildItemIn(VACTIONSEQ,"file*")) { for (vfile = VFILE; vfile != NULL; vfile=vfile->next) { if ((vfile->done == 'n') && IsDefinedClass(vfile->classes)) { Verbose("Checking for potential rule:: File <%s>/ %s\n",vfile->path,vfile->classes); return false; } } } if (IsWildItemIn(VACTIONSEQ,"tid*")) { for (vtidy = VTIDY; vtidy != NULL; vtidy=vtidy->next) { if (vtidy->done == 'n') { struct TidyPattern *tp; int active = 0; for (tp = vtidy->tidylist; tp != NULL; tp=tp->next) { if (IsDefinedClass(tp->classes)) { active=1; break; } } if (active) { Verbose("Checking for potential rule:: Tidy <%s>\n",vtidy->path); return false; } } } } if (IsWildItemIn(VACTIONSEQ,"editfile*")) { for (veditlist = VEDITLIST; veditlist != NULL; veditlist=veditlist->next) { struct Edlist *ep; int something_to_do = false; for (ep = veditlist->actions; ep != NULL; ep=ep->next) { if (IsDefinedClass(ep->classes)) { something_to_do = true; if (ep->data) { Verbose("Defined Edit %s / %s\n",ep->data,ep->classes); } else { Verbose("Defined Edit nodata / %s\n",ep->classes); } break; } } if (veditlist->done == 'n' && something_to_do) { Verbose("Checking for potential rule:: Edit <%s>\n",veditlist->fname); return false; } } } if (IsWildItemIn(VACTIONSEQ,"process*")) { for (vdisablelist = VDISABLELIST; vdisablelist != NULL; vdisablelist=vdisablelist->next) { if (vdisablelist->done == 'n' && IsDefinedClass(vdisablelist->classes)) { Verbose("Checking for potential rule:: Disable <%s> / %s\n",vdisablelist->name,vdisablelist->classes); return false; } } } if (IsWildItemIn(VACTIONSEQ,"director*")) { for (vmakepath = VMAKEPATH; vmakepath != NULL; vmakepath=vmakepath->next) { if (vmakepath->done == 'n' && IsDefinedClass(vmakepath->classes)) { Verbose("Checking for potential rule:: makePath <%s>\n",vmakepath->path); return false; } } } if (IsWildItemIn(VACTIONSEQ,"link*")) { for (vlink = VLINK; vlink != NULL; vlink=vlink->next) { if (vlink->done == 'n' && IsDefinedClass(vlink->classes)) { Verbose("Checking for potential rule:: Link <%s>\n",vlink->from); return false; } } for (vchlink = VCHLINK; vchlink != NULL; vchlink=vchlink->next) { if (vchlink->done == 'n' && IsDefinedClass(vchlink->classes)) { Verbose("Checking for potential rule:: CLink <%s>\n",vchlink->from); return false; } } } if (IsWildItemIn(VACTIONSEQ,"unmoun*")) { for (vunmount = VUNMOUNT; vunmount != NULL; vunmount=vunmount->next) { if (vunmount->done == 'n' && IsDefinedClass(vunmount->classes)) { Verbose("Checking for potential rule:: Umount <%s>\n",vunmount->name); return false; } } } if (IsWildItemIn(VACTIONSEQ,"packag*")) { for (vpkg = VPKG; vpkg != NULL; vpkg=vpkg->next) { if (vpkg->done == 'n' && IsDefinedClass(vpkg->classes)) { Verbose("Checking for potential rule:: Packages <%s>\n",vpkg->name); return false; } } } return true; } /*******************************************************************/ enum aseq EvaluateAction(char *action,struct Item **classlist,int pass) { int i,j = 0; char *sp,cbuff[CF_BUFSIZE],actiontxt[CF_BUFSIZE],mod[CF_BUFSIZE],args[CF_BUFSIZE]; struct Item *ip; cbuff[0]='\0'; actiontxt[0]='\0'; mod[0] = args[0] = '\0'; sscanf(action,"%s %[^\n]",mod,args); sp = mod; while (*sp != '\0') { ++j; sscanf(sp,"%[^.]",cbuff); while ((*sp != '\0') && (*sp !='.')) { sp++; } if (*sp == '.') { sp++; } if (IsHardClass(cbuff)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error in action sequence: %s\n",action); CfLog(cferror,OUTPUT,""); FatalError("You cannot add a reserved class!"); } if (j == 1) { VIFELAPSED = VDEFAULTIFELAPSED; VEXPIREAFTER = VDEFAULTEXPIREAFTER; strcpy(actiontxt,cbuff); continue; } else { if ((strncmp(actiontxt,"module:",7) != 0) && ! IsSpecialClass(cbuff)) { AppendItem(classlist,cbuff,NULL); } } } BuildClassEnvironment(); if ((VERBOSE || DEBUG || D2) && *classlist != NULL) { printf("\n New temporary class additions\n"); printf(" --------( Pass %d )-------\n",pass); for (ip = *classlist; ip != NULL; ip=ip->next) { printf(" %s\n",ip->name); } } ACTION = none; for (i = 0; ACTIONSEQTEXT[i] != NULL; i++) { if (strcmp(ACTIONSEQTEXT[i],actiontxt) == 0) { Debug("Actionsequence item %s\n",actiontxt); ACTION = i; return (enum aseq) i; } } Debug("Checking if entry is a module\n"); if (strncmp(actiontxt,"module:",7) == 0) { if (pass == 1) { CheckForModule(actiontxt,args); } return plugin; } Verbose("No action matched %s\n",actiontxt); return(non); } /*******************************************************************/ void SummarizeObjects() { struct cfObject *op; Verbose("\n\n++++++++++++++++++++++++++++++++++++++++\n"); Verbose("Summary of objects involved\n"); Verbose("++++++++++++++++++++++++++++++++++++++++\n\n"); for (op = VOBJ; op != NULL; op=op->next) { Verbose(" %s\n",op->scope); } } /*******************************************************************/ /* Level 2 */ /*******************************************************************/ void CheckOpts(int argc,char **argv) { extern char *optarg; struct Item *actionList; int optindex = 0; int c; while ((c=getopt_long(argc,argv,"WbBzMgAbKqkhYHd:vlniIf:pPmcCtsSaeEVD:N:LwxXuUj:o:Z:Q:",OPTIONS,&optindex)) != EOF) { switch ((char) c) { case 'E': printf("%s: the enforce-links option can only be used in interactive mode.\n",VPREFIX); printf("%s: Do you really want to blindly enforce ALL links? (y/n)\n",VPREFIX); if (getchar() != 'y') { printf("cfagent: aborting\n"); closelog(); exit(1); } ENFORCELINKS = true; break; case 'B': UPDATEONLY = true; break; case 'f': strncpy(VINPUTFILE,optarg, CF_BUFSIZE-1); VINPUTFILE[CF_BUFSIZE-1] = '\0'; MINUSF = true; break; case 'g': CHECK = true; break; case 'd': AddClassToHeap("opt_debug"); switch ((optarg==NULL) ? '3' : *optarg) { case '1': D1 = true; break; case '2': D2 = true; break; case '3': D3 = true; VERBOSE = true; break; case '4': D4 = true; break; default: DEBUG = true; break; } break; case 'M': NOMODULES = true; break; case 'K': IGNORELOCK = true; break; case 'A': IGNORELOCK = true; break; case 'D': AddMultipleClasses(optarg); break; case 'N': NegateCompoundClass(optarg,&VNEGHEAP); break; case 'b': FORCENETCOPY = true; break; case 'e': NOEDITS = true; break; case 'i': IFCONF = false; break; case 'I': INFORM = true; break; case 'v': VERBOSE = true; break; case 'l': FatalError("Option -l is deprecated -- too dangerous"); break; case 'n': DONTDO = true; IGNORELOCK = true; AddClassToHeap("opt_dry_run"); break; case 'p': PARSEONLY = true; IGNORELOCK = true; break; case 'm': NOMOUNTS = true; break; case 'c': NOFILECHECK = true; break; case 'C': MOUNTCHECK = true; break; case 't': NOTIDY = true; break; case 's': NOSCRIPTS = true; break; case 'a': PRSYSADM = true; IGNORELOCK = true; PARSEONLY = true; break; case 'z': PRSCHEDULE = true; IGNORELOCK = true; PARSEONLY = true; break; case 'Z': strncpy(METHODMD5,optarg,CF_BUFSIZE-1); Debug("Got method call reference %s\n",METHODMD5); break; case 'L': KILLOLDLINKS = true; break; case 'V': printf("GNU cfengine %s\n%s\n",VERSION,COPYRIGHT); printf("This program is covered by the GNU Public License and may be\n"); printf("copied free of charge. No warranty is implied.\n\n"); exit(0); case 'h': Syntax(); exit(0); case 'x': NOPRECONFIG = true; break; case 'w': WARNINGS = false; break; case 'X': NOLINKS = true; break; case 'k': NOCOPY = true; break; case 'S': SILENT = true; break; case 'u': USEENVIRON = true; break; case 'U': UNDERSCORE_CLASSES = true; break; case 'H': NOHARDCLASSES = true; break; case 'P': NOPROCS = true; break; case 'q': NOSPLAY = true; break; case 'W': SHOWDB = true; break; case 'Y': CFPARANOID = true; break; case 'j': actionList = SplitStringAsItemList(optarg, ','); VJUSTACTIONS = ConcatLists(actionList, VJUSTACTIONS); break; case 'o': actionList = SplitStringAsItemList(optarg, ','); VAVOIDACTIONS = ConcatLists(actionList, VAVOIDACTIONS); break; case 'Q': if (optarg == NULL || strlen(optarg) == 0) { exit(1); } IGNORELOCK = true; NOSPLAY = true; QUERYVARS = SplitStringAsItemList(optarg,','); break; default: Syntax(); exit(1); } } } /*******************************************************************/ int GetResource(char *var) { int i; for (i = 0; VRESOURCES[i] != '\0'; i++) { if (strcmp(VRESOURCES[i],var)==0) { return i; } } snprintf (OUTPUT,CF_BUFSIZE,"Unknown resource %s in %s",var,VRCFILE); FatalError(OUTPUT); return 0; } /*******************************************************************/ void Syntax() { int i; printf("GNU cfengine: A system configuration engine (cfagent)\n%s\n%s\n",VERSION,COPYRIGHT); printf("\n"); printf("Options:\n\n"); for (i=0; OPTIONS[i].name != NULL; i++) { printf("--%-20s (-%c)\n",OPTIONS[i].name,(char)OPTIONS[i].val); } printf("\nDebug levels: 1=parsing, 2=running, 3=summary, 4=expression eval\n"); printf("\nBug reports to bug-cfengine@cfengine.org\n"); printf("General help to help-cfengine@cfengine.org\n"); printf("Info & fixes at http://www.cfengine.org\n"); } /* EOF */ cfengine-2.2.10/src/checksum_db.c0000644000175000001440000002701710675756477013530 00000000000000 /* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: checksum_db.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /* Alter this code at your peril. Berkeley DB is *very* sensitive to errors. */ /***************************************************************/ int ChecksumChanged(char *filename,unsigned char digest[EVP_MAX_MD_SIZE+1],int warnlevel,int refresh,char type) /* Returns false if filename never seen before, and adds a checksum to the database. Returns true if checksums do not match and also updates database to the new value */ { struct stat stat1, stat2; int i,needupdate = false, size = 21; unsigned char dbdigest[EVP_MAX_MD_SIZE+1],dbattr[EVP_MAX_MD_SIZE+1]; unsigned char current_digest[EVP_MAX_MD_SIZE+1],attr_digest[EVP_MAX_MD_SIZE+1]; DBT *key,*value; DB *dbp; DB_ENV *dbenv = NULL; FILE *fp; Debug("ChecksumChanged: key %s (type=%c) with data %s\n",filename,type,ChecksumPrint(type,digest)); size = ChecksumSize(type); memset(current_digest,0,EVP_MAX_MD_SIZE+1); memset(attr_digest,0,EVP_MAX_MD_SIZE+1); ChecksumFile(filename,current_digest,type); if (CHECKSUMDB == NULL) { if (ISCFENGINE) { FatalError("Checksum database is undefined (shouldn't happen - misc.c)"); } else { Debug("Direct comparison (no db)\n"); for (i = 0; i < size; i++) { if (digest[i] != current_digest[i]) { return true; } } return false; } } if (refresh) /* this section should not be used anymore */ { /* Check whether database is current wrt local file - simple cheap test */ if (stat(filename,&stat1) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't stat %s\n",filename); CfLog(cferror,OUTPUT,"stat"); return false; } if (stat(CHECKSUMDB,&stat2) != -1) { if (stat1.st_mtime > stat2.st_mtime) { Debug("Checksum database is older than %s...refresh needed\n",filename); needupdate = true; } else { Debug("Checksum up to date..\n"); } } else { needupdate = true; } } if ((errno = db_create(&dbp,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open checksum database %s\n",CHECKSUMDB); CfLog(cferror,OUTPUT,"db_open"); return false; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,CHECKSUMDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,CHECKSUMDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open checksum database %s\n",CHECKSUMDB); CfLog(cferror,OUTPUT,"db_open"); dbp->close(dbp,0); return false; } if (needupdate) /* This section should not be needed any more */ { DeleteChecksum(dbp,type,filename); WriteChecksum(dbp,type,filename,current_digest,attr_digest); } if (ReadChecksum(dbp,type,filename,dbdigest,dbattr)) { /* Ignoring attr for now - future development */ for (i = 0; i < size; i++) { if (current_digest[i] != dbdigest[i]) { Debug("Found checksum for %s in database but it didn't match\n",filename); if (EXCLAIM) { CfLog(warnlevel,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",""); } snprintf(OUTPUT,CF_BUFSIZE*2,"SECURITY ALERT: Checksum (%s) for %s changed!",ChecksumName(type),filename); CfLog(warnlevel,OUTPUT,""); if (EXCLAIM) { CfLog(warnlevel,"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",""); } if (CHECKSUMUPDATES) { Verbose("Updating checksum for %s to %s\n",filename,ChecksumPrint(type,current_digest)); DeleteChecksum(dbp,type,filename); WriteChecksum(dbp,type,filename,current_digest,attr_digest); } dbp->close(dbp,0); return true; /* Checksum updated but was changed */ } } Debug("Found checksum for %s in database and it matched\n",filename); dbp->close(dbp,0); return false; } else { /* Key was not found, so install it */ if (ISCFENGINE) { snprintf(OUTPUT,CF_BUFSIZE,"File %s was not in %s database - new file found",filename,ChecksumName(type)); CfLog(cfsilent,OUTPUT,""); } Debug("Storing checksum for %s in database %s\n",filename,ChecksumPrint(type,current_digest)); WriteChecksum(dbp,type,filename,current_digest,attr_digest); dbp->close(dbp,0); if (ISCFENGINE) { return false; /* No need to warn when first installed */ } else { return true; } } } /***************************************************************/ void ChecksumPurge() /* Go through the database and purge records about non-existent files */ { DBT key,value; DB *dbp; DBC *dbcp; DB_ENV *dbenv = NULL; int ret; struct stat statbuf; if ((errno = db_create(&dbp,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open checksum database %s\n",CHECKSUMDB); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,CHECKSUMDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,CHECKSUMDB,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open checksum database %s\n",CHECKSUMDB); CfLog(cferror,OUTPUT,"db_open"); dbp->close(dbp,0); return; } /* Acquire a cursor for the database. */ if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { CfLog(cferror,"Error reading from checksum database",""); dbp->err(dbp, ret, "DB->cursor"); return; } /* Walk through the database and print out the key/data pairs. */ memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { char *obj = (char *)key.data + CF_CHKSUMKEYOFFSET; if (stat(obj,&statbuf) == -1) { Verbose("Purging file %s from checksum db - no longer exists\n",obj); snprintf(OUTPUT,CF_BUFSIZE*2,"SECURITY INFO: %s checksum for %s purged - file no longer exists!",key.data,obj); CfLog(cferror,OUTPUT,""); if ((errno = dbp->del(dbp,NULL,&key,0)) != 0) { CfLog(cferror,"","db_store"); } } memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); } dbcp->c_close(dbcp); dbp->close(dbp,0); } /*****************************************************************************/ int ReadChecksum(DB *dbp,char type,char *name,unsigned char digest[EVP_MAX_MD_SIZE+1], unsigned char *attr) { DBT *key,value; struct Checksum_Value chk_val; key = NewChecksumKey(type,name); memset(&value,0,sizeof(value)); if ((errno = dbp->get(dbp,NULL,key,&value,0)) == 0) { memset(digest,0,EVP_MAX_MD_SIZE+1); memset(&chk_val,0,sizeof(chk_val)); memcpy(&chk_val,value.data,sizeof(chk_val)); memcpy(digest,chk_val.mess_digest,EVP_MAX_MD_SIZE+1); Debug("READ %c %s %s\n",type,name,ChecksumPrint(type,digest)); DeleteChecksumKey(key); return true; } else { Debug("Checksum read failed: %s",db_strerror(errno)); DeleteChecksumKey(key); return false; } } /*****************************************************************************/ int WriteChecksum(DB *dbp,char type,char *name,unsigned char digest[EVP_MAX_MD_SIZE+1], unsigned char *attr) { DBT *key,*value; key = NewChecksumKey(type,name); value = NewChecksumValue(digest,attr); Debug("DATA = %s\n",ChecksumPrint(type,value->data)); if ((errno = dbp->put(dbp,NULL,key,value,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Checksum write failed: %s",db_strerror(errno)); CfLog(cferror,OUTPUT,"db->put"); DeleteChecksumKey(key); DeleteChecksumValue(value); return false; } else { DeleteChecksumKey(key); DeleteChecksumValue(value); return true; } } /*****************************************************************************/ void DeleteChecksum(DB *dbp,char type,char *name) { DBT *key; key = NewChecksumKey(type,name); if ((errno = dbp->del(dbp,NULL,key,0)) != 0) { CfLog(cferror,"","db_store"); } DeleteChecksumKey(key); Debug("DELETED %s\n",name); } /*****************************************************************************/ /* level 1 */ /*****************************************************************************/ DBT *NewChecksumKey(char type,char *name) { char *chk_key; DBT *key; if ((chk_key = malloc(strlen(name)+CF_MAXDIGESTNAMELEN+2)) == NULL) { FatalError("NewChecksumKey malloc error"); } if ((key = (DBT *)malloc(sizeof(DBT))) == NULL) { FatalError("DBT malloc error"); } memset(key,0,sizeof(DBT)); memset(chk_key,0,strlen(name)+CF_MAXDIGESTNAMELEN+2); strcpy(chk_key,ChecksumName(type)); /* safe */ /* Berkeley DB needs this packed */ strncpy(chk_key+CF_CHKSUMKEYOFFSET,name,strlen(name)); Debug("KEY => %s,%s\n",chk_key,chk_key+CF_CHKSUMKEYOFFSET); key->data = chk_key; key->size = strlen(name)+CF_MAXDIGESTNAMELEN+2; return key; } /*****************************************************************************/ void DeleteChecksumKey(DBT *key) { free((char *)key->data); free((char *)key); } /*****************************************************************************/ DBT *NewChecksumValue(unsigned char digest[EVP_MAX_MD_SIZE+1],unsigned char attr[EVP_MAX_MD_SIZE+1]) { struct Checksum_Value *chk_val; DBT *value; char *x; if ((chk_val = (struct Checksum_Value *)malloc(sizeof(struct Checksum_Value))) == NULL) { FatalError("NewChecksumKey malloc error"); } if ((value = (DBT *) malloc(sizeof(DBT))) == NULL) { FatalError("DBT Value malloc error"); } memset(value,0,sizeof(DBT)); memset(chk_val,0,sizeof(struct Checksum_Value)); memcpy(chk_val->mess_digest,digest,EVP_MAX_MD_SIZE+1); memcpy(chk_val->attr_digest,attr,EVP_MAX_MD_SIZE+1); value->data = (void *) chk_val; value->size = sizeof(*chk_val); return value; } /*****************************************************************************/ void DeleteChecksumValue(DBT *value) { struct Checksum_Value *chk_val; chk_val = (struct Checksum_Value *) value->data; free((char *)chk_val); free((char *)value); } cfengine-2.2.10/src/Makefile.in0000644000175000001440000031375611170173245013143 00000000000000# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ sbin_PROGRAMS = cfagent$(EXEEXT) cfservd$(EXEEXT) cfrun$(EXEEXT) \ cfkey$(EXEEXT) cfenvd$(EXEEXT) cfenvgraph$(EXEEXT) \ cfexecd$(EXEEXT) cfshow$(EXEEXT) cfetool$(EXEEXT) \ cfetoolgraph$(EXEEXT) subdir = src DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(srcdir)/cflex.l.in $(srcdir)/conf.h.in \ cflex.c cfparse.c cfparse.h ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = conf.h CONFIG_CLEAN_FILES = cflex.l am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sbindir)" libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libcfengine_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libcfengine_la_OBJECTS = libcfengine_la-init.lo \ libcfengine_la-modules.lo libcfengine_la-alerts.lo \ libcfengine_la-report.lo libcfengine_la-client.lo \ libcfengine_la-ip.lo libcfengine_la-ipname.lo \ libcfengine_la-instrument.lo libcfengine_la-process.lo \ libcfengine_la-timeout.lo libcfengine_la-ifconf.lo \ libcfengine_la-image.lo libcfengine_la-item.lo \ libcfengine_la-item-ext.lo libcfengine_la-item-file.lo \ libcfengine_la-2Dlist.lo libcfengine_la-globals.lo \ libcfengine_la-classes.lo libcfengine_la-misc.lo \ libcfengine_la-parse.lo libcfengine_la-functions.lo \ libcfengine_la-edittools.lo libcfengine_la-patches.lo \ libcfengine_la-install.lo libcfengine_la-link.lo \ libcfengine_la-tidy.lo libcfengine_la-filedir.lo \ libcfengine_la-eval.lo libcfengine_la-modes.lo \ libcfengine_la-sockaddr.lo libcfengine_la-chflags.lo \ libcfengine_la-locks.lo libcfengine_la-mount.lo \ libcfengine_la-macro.lo libcfengine_la-filenames.lo \ libcfengine_la-varstring.lo libcfengine_la-wildcard.lo \ libcfengine_la-cfparse.lo libcfengine_la-comparray.lo \ libcfengine_la-read.lo libcfengine_la-checksums.lo \ libcfengine_la-proto.lo libcfengine_la-filters.lo \ libcfengine_la-copy.lo libcfengine_la-repository.lo \ libcfengine_la-rotate.lo libcfengine_la-errors.lo \ libcfengine_la-cflex.lo libcfengine_la-net.lo \ libcfengine_la-df.lo libcfengine_la-log.lo \ libcfengine_la-crypto.lo libcfengine_la-popen.lo \ libcfengine_la-popen_def.lo libcfengine_la-sensible.lo \ libcfengine_la-acl.lo libcfengine_la-dce_acl.lo \ libcfengine_la-nameinfo.lo libcfengine_la-strategies.lo \ libcfengine_la-granules.lo libcfengine_la-methods.lo \ libcfengine_la-dtypes.lo libcfengine_la-state.lo \ libcfengine_la-checksum_db.lo libcfengine_la-expand-files.lo \ libcfengine_la-expand-tidy.lo libcfengine_la-expand-image.lo \ libcfengine_la-expand-editfiles.lo libcfengine_la-package.lo \ libcfengine_la-scli.lo libcfengine_la_OBJECTS = $(am_libcfengine_la_OBJECTS) libcfengine_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libcfengine_la_CFLAGS) \ $(CFLAGS) $(libcfengine_la_LDFLAGS) $(LDFLAGS) -o $@ sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(sbin_PROGRAMS) am_cfagent_OBJECTS = cfagent.$(OBJEXT) wrapper.$(OBJEXT) do.$(OBJEXT) cfagent_OBJECTS = $(am_cfagent_OBJECTS) cfagent_LDADD = $(LDADD) cfagent_DEPENDENCIES = libcfengine.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_cfenvd_OBJECTS = cfenvd.$(OBJEXT) env_monitor.$(OBJEXT) cfenvd_OBJECTS = $(am_cfenvd_OBJECTS) cfenvd_LDADD = $(LDADD) cfenvd_DEPENDENCIES = libcfengine.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_cfenvgraph_OBJECTS = cfenvgraph.$(OBJEXT) cfenvgraph_OBJECTS = $(am_cfenvgraph_OBJECTS) cfenvgraph_LDADD = $(LDADD) cfenvgraph_DEPENDENCIES = libcfengine.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_cfetool_OBJECTS = cfetool.$(OBJEXT) cfetool_OBJECTS = $(am_cfetool_OBJECTS) cfetool_LDADD = $(LDADD) cfetool_DEPENDENCIES = libcfengine.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_cfetoolgraph_OBJECTS = cfetoolgraph.$(OBJEXT) cfetoolgraph_OBJECTS = $(am_cfetoolgraph_OBJECTS) cfetoolgraph_LDADD = $(LDADD) cfetoolgraph_DEPENDENCIES = libcfengine.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_cfexecd_OBJECTS = cfexecd.$(OBJEXT) cfexecd_OBJECTS = $(am_cfexecd_OBJECTS) cfexecd_LDADD = $(LDADD) cfexecd_DEPENDENCIES = libcfengine.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_cfkey_OBJECTS = cfkey.$(OBJEXT) cfkey_OBJECTS = $(am_cfkey_OBJECTS) cfkey_LDADD = $(LDADD) cfkey_DEPENDENCIES = libcfengine.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_cfrun_OBJECTS = cfrun.$(OBJEXT) cfrun_OBJECTS = $(am_cfrun_OBJECTS) cfrun_LDADD = $(LDADD) cfrun_DEPENDENCIES = libcfengine.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_cfservd_OBJECTS = cfservd.$(OBJEXT) cfservd_OBJECTS = $(am_cfservd_OBJECTS) cfservd_LDADD = $(LDADD) cfservd_DEPENDENCIES = libcfengine.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_cfshow_OBJECTS = cfshow.$(OBJEXT) cfshow_OBJECTS = $(am_cfshow_OBJECTS) cfshow_LDADD = $(LDADD) cfshow_DEPENDENCIES = libcfengine.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS) LTLEXCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(LEX) $(LFLAGS) $(AM_LFLAGS) YLWRAP = $(top_srcdir)/ylwrap YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS) LTYACCCOMPILE = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=compile $(YACC) $(YFLAGS) $(AM_YFLAGS) SOURCES = $(libcfengine_la_SOURCES) $(cfagent_SOURCES) \ $(cfenvd_SOURCES) $(cfenvgraph_SOURCES) $(cfetool_SOURCES) \ $(cfetoolgraph_SOURCES) $(cfexecd_SOURCES) $(cfkey_SOURCES) \ $(cfrun_SOURCES) $(cfservd_SOURCES) $(cfshow_SOURCES) DIST_SOURCES = $(libcfengine_la_SOURCES) $(cfagent_SOURCES) \ $(cfenvd_SOURCES) $(cfenvgraph_SOURCES) $(cfetool_SOURCES) \ $(cfetoolgraph_SOURCES) $(cfexecd_SOURCES) $(cfkey_SOURCES) \ $(cfrun_SOURCES) $(cfservd_SOURCES) $(cfshow_SOURCES) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BERKELEY_DB_CFLAGS = @BERKELEY_DB_CFLAGS@ BERKELEY_DB_LDFLAGS = @BERKELEY_DB_LDFLAGS@ BERKELEY_DB_LIB = @BERKELEY_DB_LIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EIGHTBIT = @EIGHTBIT@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCC_CFLAG = @GCC_CFLAG@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SELINUX = @LIB_SELINUX@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ NOWRAP = @NOWRAP@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_LIB_CPPFLAGS = @OPENSSL_LIB_CPPFLAGS@ OPENSSL_LIB_LDFLAGS = @OPENSSL_LIB_LDFLAGS@ OPENSSL_LIB_LIB = @OPENSSL_LIB_LIB@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PS2PDF = @PS2PDF@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TEXI2DVI = @TEXI2DVI@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(GCC_CFLAG) @CFLAGS@ AM_YFLAGS = -d LDADD = libcfengine.la $(BERKELEY_DB_LDFLAGSD) $(BERKELEY_DB_LIB) $(OPENSSL_LIB_LDFLAGS) $(OPENSSL_LIB_LIB) INCLUDES = $(BERKELEY_DB_CFLAGS) $(OPENSSL_LIB_CPPFLAGS) AM_LDFLAGS = $(BERKELEY_DB_LDFLAGS) $(OPENSSL_LIB_LDFLAGS) @LDFLAGS@ # # Fix this generically # lib_LTLIBRARIES = libcfengine.la libcfengine_la_LDFLAGS = -version-info 1:0:0 -no-undefined libcfengine_la_LIBADD = $(BERKELEY_DB_LDFLAGSD) $(BERKELEY_DB_LIB) $(OPENSSL_LIB_LDFLAGS) $(OPENSSL_LIB_LIB) libcfengine_la_CFLAGS = $(AM_CFLAGS) # Separate out a library libcfengine_la_SOURCES = \ init.c \ modules.c \ alerts.c \ report.c \ client.c \ ip.c \ ipname.c \ instrument.c \ process.c \ timeout.c \ ifconf.c \ image.c \ item.c \ item-ext.c \ item-file.c \ 2Dlist.c \ globals.c \ classes.c \ misc.c \ parse.c \ functions.c \ edittools.c \ patches.c \ install.c \ link.c \ tidy.c \ filedir.c \ eval.c \ modes.c \ sockaddr.c \ chflags.c \ locks.c \ mount.c \ macro.c \ filenames.c \ varstring.c \ wildcard.c \ cfparse.y \ comparray.c \ read.c \ checksums.c \ proto.c \ filters.c \ copy.c \ repository.c \ rotate.c \ errors.c \ cflex.l \ net.c \ df.c \ log.c \ crypto.c \ popen.c \ popen_def.c \ sensible.c \ acl.c \ dce_acl.c \ nameinfo.c \ strategies.c \ granules.c \ methods.c \ dtypes.c \ state.c \ checksum_db.c \ expand-files.c \ expand-tidy.c \ expand-image.c \ expand-editfiles.c \ package.c \ scli.c #libcfengine_la_LIBADD = -L../pub -lcfpub cfshow_SOURCES = \ cfshow.c cfagent_SOURCES = \ cfagent.c \ wrapper.c \ do.c cfservd_SOURCES = \ cfservd.c cfexecd_SOURCES = \ cfexecd.c #cfexecd_LDADD = $(LEXLIB) $(BERKELEY_DB_LIB) $(OPENSSL_LIB_LIB) cfrun_SOURCES = \ cfrun.c cfkey_SOURCES = \ cfkey.c cfenvd_SOURCES = \ cfenvd.c \ env_monitor.c cfenvgraph_SOURCES = \ cfenvgraph.c cfetool_SOURCES = \ cfetool.c cfetoolgraph_SOURCES = \ cfetoolgraph.c # # Pickup header files here so Automake knows about them # noinst_HEADERS = \ cfservd.h \ cfparse.h \ cf.defs.h \ cf.extern.h \ prototypes.h \ cfetooldefs.h # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = cflex.c cfparse.c cfparse.h # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = cflex.c cfparse.c cfparse.h # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in conf.h.in stamp-h.in all: conf.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .l .lo .o .obj .y $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu src/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh conf.h: stamp-h1 @if test ! -f $@; then \ rm -f stamp-h1; \ $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ else :; fi stamp-h1: $(srcdir)/conf.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status src/conf.h $(srcdir)/conf.h.in: $(am__configure_deps) $(top_srcdir)/acconfig.h cd $(top_srcdir) && $(AUTOHEADER) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f conf.h stamp-h1 cflex.l: $(top_builddir)/config.status $(srcdir)/cflex.l.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ if test -f $$p; then \ f=$(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ else :; fi; \ done uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ p=$(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ test "$$dir" != "$$p" || dir=.; \ echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done cfparse.h: cfparse.c @if test ! -f $@; then \ rm -f cfparse.c; \ $(MAKE) $(AM_MAKEFLAGS) cfparse.c; \ else :; fi libcfengine.la: $(libcfengine_la_OBJECTS) $(libcfengine_la_DEPENDENCIES) $(libcfengine_la_LINK) -rpath $(libdir) $(libcfengine_la_OBJECTS) $(libcfengine_la_LIBADD) $(LIBS) install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)" @list='$(sbin_PROGRAMS)'; for p in $$list; do \ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ if test -f $$p \ || test -f $$p1 \ ; then \ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \ else :; fi; \ done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; for p in $$list; do \ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \ rm -f "$(DESTDIR)$(sbindir)/$$f"; \ done clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done cfagent$(EXEEXT): $(cfagent_OBJECTS) $(cfagent_DEPENDENCIES) @rm -f cfagent$(EXEEXT) $(LINK) $(cfagent_OBJECTS) $(cfagent_LDADD) $(LIBS) cfenvd$(EXEEXT): $(cfenvd_OBJECTS) $(cfenvd_DEPENDENCIES) @rm -f cfenvd$(EXEEXT) $(LINK) $(cfenvd_OBJECTS) $(cfenvd_LDADD) $(LIBS) cfenvgraph$(EXEEXT): $(cfenvgraph_OBJECTS) $(cfenvgraph_DEPENDENCIES) @rm -f cfenvgraph$(EXEEXT) $(LINK) $(cfenvgraph_OBJECTS) $(cfenvgraph_LDADD) $(LIBS) cfetool$(EXEEXT): $(cfetool_OBJECTS) $(cfetool_DEPENDENCIES) @rm -f cfetool$(EXEEXT) $(LINK) $(cfetool_OBJECTS) $(cfetool_LDADD) $(LIBS) cfetoolgraph$(EXEEXT): $(cfetoolgraph_OBJECTS) $(cfetoolgraph_DEPENDENCIES) @rm -f cfetoolgraph$(EXEEXT) $(LINK) $(cfetoolgraph_OBJECTS) $(cfetoolgraph_LDADD) $(LIBS) cfexecd$(EXEEXT): $(cfexecd_OBJECTS) $(cfexecd_DEPENDENCIES) @rm -f cfexecd$(EXEEXT) $(LINK) $(cfexecd_OBJECTS) $(cfexecd_LDADD) $(LIBS) cfkey$(EXEEXT): $(cfkey_OBJECTS) $(cfkey_DEPENDENCIES) @rm -f cfkey$(EXEEXT) $(LINK) $(cfkey_OBJECTS) $(cfkey_LDADD) $(LIBS) cfrun$(EXEEXT): $(cfrun_OBJECTS) $(cfrun_DEPENDENCIES) @rm -f cfrun$(EXEEXT) $(LINK) $(cfrun_OBJECTS) $(cfrun_LDADD) $(LIBS) cfservd$(EXEEXT): $(cfservd_OBJECTS) $(cfservd_DEPENDENCIES) @rm -f cfservd$(EXEEXT) $(LINK) $(cfservd_OBJECTS) $(cfservd_LDADD) $(LIBS) cfshow$(EXEEXT): $(cfshow_OBJECTS) $(cfshow_DEPENDENCIES) @rm -f cfshow$(EXEEXT) $(LINK) $(cfshow_OBJECTS) $(cfshow_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfagent.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfenvd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfenvgraph.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfetool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfetoolgraph.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfexecd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfkey.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfrun.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfservd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfshow.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/do.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env_monitor.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-2Dlist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-acl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-alerts.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-cflex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-cfparse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-checksum_db.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-checksums.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-chflags.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-classes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-client.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-comparray.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-copy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-crypto.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-dce_acl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-df.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-dtypes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-edittools.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-errors.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-eval.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-expand-editfiles.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-expand-files.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-expand-image.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-expand-tidy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-filedir.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-filenames.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-filters.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-functions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-globals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-granules.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-ifconf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-image.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-init.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-install.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-instrument.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-ip.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-ipname.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-item-ext.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-item-file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-item.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-link.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-locks.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-macro.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-methods.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-misc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-modes.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-modules.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-mount.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-nameinfo.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-net.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-package.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-parse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-patches.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-popen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-popen_def.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-process.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-proto.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-read.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-report.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-repository.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-rotate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-scli.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-sensible.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-sockaddr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-state.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-strategies.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-tidy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-timeout.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-varstring.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcfengine_la-wildcard.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wrapper.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< libcfengine_la-init.lo: init.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-init.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-init.Tpo -c -o libcfengine_la-init.lo `test -f 'init.c' || echo '$(srcdir)/'`init.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-init.Tpo $(DEPDIR)/libcfengine_la-init.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='init.c' object='libcfengine_la-init.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-init.lo `test -f 'init.c' || echo '$(srcdir)/'`init.c libcfengine_la-modules.lo: modules.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-modules.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-modules.Tpo -c -o libcfengine_la-modules.lo `test -f 'modules.c' || echo '$(srcdir)/'`modules.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-modules.Tpo $(DEPDIR)/libcfengine_la-modules.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='modules.c' object='libcfengine_la-modules.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-modules.lo `test -f 'modules.c' || echo '$(srcdir)/'`modules.c libcfengine_la-alerts.lo: alerts.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-alerts.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-alerts.Tpo -c -o libcfengine_la-alerts.lo `test -f 'alerts.c' || echo '$(srcdir)/'`alerts.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-alerts.Tpo $(DEPDIR)/libcfengine_la-alerts.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='alerts.c' object='libcfengine_la-alerts.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-alerts.lo `test -f 'alerts.c' || echo '$(srcdir)/'`alerts.c libcfengine_la-report.lo: report.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-report.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-report.Tpo -c -o libcfengine_la-report.lo `test -f 'report.c' || echo '$(srcdir)/'`report.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-report.Tpo $(DEPDIR)/libcfengine_la-report.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='report.c' object='libcfengine_la-report.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-report.lo `test -f 'report.c' || echo '$(srcdir)/'`report.c libcfengine_la-client.lo: client.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-client.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-client.Tpo -c -o libcfengine_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-client.Tpo $(DEPDIR)/libcfengine_la-client.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='client.c' object='libcfengine_la-client.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-client.lo `test -f 'client.c' || echo '$(srcdir)/'`client.c libcfengine_la-ip.lo: ip.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-ip.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-ip.Tpo -c -o libcfengine_la-ip.lo `test -f 'ip.c' || echo '$(srcdir)/'`ip.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-ip.Tpo $(DEPDIR)/libcfengine_la-ip.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ip.c' object='libcfengine_la-ip.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-ip.lo `test -f 'ip.c' || echo '$(srcdir)/'`ip.c libcfengine_la-ipname.lo: ipname.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-ipname.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-ipname.Tpo -c -o libcfengine_la-ipname.lo `test -f 'ipname.c' || echo '$(srcdir)/'`ipname.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-ipname.Tpo $(DEPDIR)/libcfengine_la-ipname.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ipname.c' object='libcfengine_la-ipname.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-ipname.lo `test -f 'ipname.c' || echo '$(srcdir)/'`ipname.c libcfengine_la-instrument.lo: instrument.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-instrument.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-instrument.Tpo -c -o libcfengine_la-instrument.lo `test -f 'instrument.c' || echo '$(srcdir)/'`instrument.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-instrument.Tpo $(DEPDIR)/libcfengine_la-instrument.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='instrument.c' object='libcfengine_la-instrument.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-instrument.lo `test -f 'instrument.c' || echo '$(srcdir)/'`instrument.c libcfengine_la-process.lo: process.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-process.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-process.Tpo -c -o libcfengine_la-process.lo `test -f 'process.c' || echo '$(srcdir)/'`process.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-process.Tpo $(DEPDIR)/libcfengine_la-process.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='process.c' object='libcfengine_la-process.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-process.lo `test -f 'process.c' || echo '$(srcdir)/'`process.c libcfengine_la-timeout.lo: timeout.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-timeout.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-timeout.Tpo -c -o libcfengine_la-timeout.lo `test -f 'timeout.c' || echo '$(srcdir)/'`timeout.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-timeout.Tpo $(DEPDIR)/libcfengine_la-timeout.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='timeout.c' object='libcfengine_la-timeout.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-timeout.lo `test -f 'timeout.c' || echo '$(srcdir)/'`timeout.c libcfengine_la-ifconf.lo: ifconf.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-ifconf.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-ifconf.Tpo -c -o libcfengine_la-ifconf.lo `test -f 'ifconf.c' || echo '$(srcdir)/'`ifconf.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-ifconf.Tpo $(DEPDIR)/libcfengine_la-ifconf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ifconf.c' object='libcfengine_la-ifconf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-ifconf.lo `test -f 'ifconf.c' || echo '$(srcdir)/'`ifconf.c libcfengine_la-image.lo: image.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-image.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-image.Tpo -c -o libcfengine_la-image.lo `test -f 'image.c' || echo '$(srcdir)/'`image.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-image.Tpo $(DEPDIR)/libcfengine_la-image.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='image.c' object='libcfengine_la-image.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-image.lo `test -f 'image.c' || echo '$(srcdir)/'`image.c libcfengine_la-item.lo: item.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-item.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-item.Tpo -c -o libcfengine_la-item.lo `test -f 'item.c' || echo '$(srcdir)/'`item.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-item.Tpo $(DEPDIR)/libcfengine_la-item.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='item.c' object='libcfengine_la-item.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-item.lo `test -f 'item.c' || echo '$(srcdir)/'`item.c libcfengine_la-item-ext.lo: item-ext.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-item-ext.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-item-ext.Tpo -c -o libcfengine_la-item-ext.lo `test -f 'item-ext.c' || echo '$(srcdir)/'`item-ext.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-item-ext.Tpo $(DEPDIR)/libcfengine_la-item-ext.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='item-ext.c' object='libcfengine_la-item-ext.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-item-ext.lo `test -f 'item-ext.c' || echo '$(srcdir)/'`item-ext.c libcfengine_la-item-file.lo: item-file.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-item-file.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-item-file.Tpo -c -o libcfengine_la-item-file.lo `test -f 'item-file.c' || echo '$(srcdir)/'`item-file.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-item-file.Tpo $(DEPDIR)/libcfengine_la-item-file.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='item-file.c' object='libcfengine_la-item-file.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-item-file.lo `test -f 'item-file.c' || echo '$(srcdir)/'`item-file.c libcfengine_la-2Dlist.lo: 2Dlist.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-2Dlist.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-2Dlist.Tpo -c -o libcfengine_la-2Dlist.lo `test -f '2Dlist.c' || echo '$(srcdir)/'`2Dlist.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-2Dlist.Tpo $(DEPDIR)/libcfengine_la-2Dlist.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='2Dlist.c' object='libcfengine_la-2Dlist.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-2Dlist.lo `test -f '2Dlist.c' || echo '$(srcdir)/'`2Dlist.c libcfengine_la-globals.lo: globals.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-globals.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-globals.Tpo -c -o libcfengine_la-globals.lo `test -f 'globals.c' || echo '$(srcdir)/'`globals.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-globals.Tpo $(DEPDIR)/libcfengine_la-globals.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='globals.c' object='libcfengine_la-globals.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-globals.lo `test -f 'globals.c' || echo '$(srcdir)/'`globals.c libcfengine_la-classes.lo: classes.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-classes.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-classes.Tpo -c -o libcfengine_la-classes.lo `test -f 'classes.c' || echo '$(srcdir)/'`classes.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-classes.Tpo $(DEPDIR)/libcfengine_la-classes.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='classes.c' object='libcfengine_la-classes.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-classes.lo `test -f 'classes.c' || echo '$(srcdir)/'`classes.c libcfengine_la-misc.lo: misc.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-misc.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-misc.Tpo -c -o libcfengine_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-misc.Tpo $(DEPDIR)/libcfengine_la-misc.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='misc.c' object='libcfengine_la-misc.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c libcfengine_la-parse.lo: parse.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-parse.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-parse.Tpo -c -o libcfengine_la-parse.lo `test -f 'parse.c' || echo '$(srcdir)/'`parse.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-parse.Tpo $(DEPDIR)/libcfengine_la-parse.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='parse.c' object='libcfengine_la-parse.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-parse.lo `test -f 'parse.c' || echo '$(srcdir)/'`parse.c libcfengine_la-functions.lo: functions.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-functions.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-functions.Tpo -c -o libcfengine_la-functions.lo `test -f 'functions.c' || echo '$(srcdir)/'`functions.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-functions.Tpo $(DEPDIR)/libcfengine_la-functions.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='functions.c' object='libcfengine_la-functions.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-functions.lo `test -f 'functions.c' || echo '$(srcdir)/'`functions.c libcfengine_la-edittools.lo: edittools.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-edittools.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-edittools.Tpo -c -o libcfengine_la-edittools.lo `test -f 'edittools.c' || echo '$(srcdir)/'`edittools.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-edittools.Tpo $(DEPDIR)/libcfengine_la-edittools.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='edittools.c' object='libcfengine_la-edittools.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-edittools.lo `test -f 'edittools.c' || echo '$(srcdir)/'`edittools.c libcfengine_la-patches.lo: patches.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-patches.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-patches.Tpo -c -o libcfengine_la-patches.lo `test -f 'patches.c' || echo '$(srcdir)/'`patches.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-patches.Tpo $(DEPDIR)/libcfengine_la-patches.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='patches.c' object='libcfengine_la-patches.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-patches.lo `test -f 'patches.c' || echo '$(srcdir)/'`patches.c libcfengine_la-install.lo: install.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-install.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-install.Tpo -c -o libcfengine_la-install.lo `test -f 'install.c' || echo '$(srcdir)/'`install.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-install.Tpo $(DEPDIR)/libcfengine_la-install.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='install.c' object='libcfengine_la-install.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-install.lo `test -f 'install.c' || echo '$(srcdir)/'`install.c libcfengine_la-link.lo: link.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-link.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-link.Tpo -c -o libcfengine_la-link.lo `test -f 'link.c' || echo '$(srcdir)/'`link.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-link.Tpo $(DEPDIR)/libcfengine_la-link.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='link.c' object='libcfengine_la-link.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-link.lo `test -f 'link.c' || echo '$(srcdir)/'`link.c libcfengine_la-tidy.lo: tidy.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-tidy.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-tidy.Tpo -c -o libcfengine_la-tidy.lo `test -f 'tidy.c' || echo '$(srcdir)/'`tidy.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-tidy.Tpo $(DEPDIR)/libcfengine_la-tidy.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='tidy.c' object='libcfengine_la-tidy.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-tidy.lo `test -f 'tidy.c' || echo '$(srcdir)/'`tidy.c libcfengine_la-filedir.lo: filedir.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-filedir.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-filedir.Tpo -c -o libcfengine_la-filedir.lo `test -f 'filedir.c' || echo '$(srcdir)/'`filedir.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-filedir.Tpo $(DEPDIR)/libcfengine_la-filedir.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='filedir.c' object='libcfengine_la-filedir.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-filedir.lo `test -f 'filedir.c' || echo '$(srcdir)/'`filedir.c libcfengine_la-eval.lo: eval.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-eval.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-eval.Tpo -c -o libcfengine_la-eval.lo `test -f 'eval.c' || echo '$(srcdir)/'`eval.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-eval.Tpo $(DEPDIR)/libcfengine_la-eval.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='eval.c' object='libcfengine_la-eval.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-eval.lo `test -f 'eval.c' || echo '$(srcdir)/'`eval.c libcfengine_la-modes.lo: modes.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-modes.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-modes.Tpo -c -o libcfengine_la-modes.lo `test -f 'modes.c' || echo '$(srcdir)/'`modes.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-modes.Tpo $(DEPDIR)/libcfengine_la-modes.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='modes.c' object='libcfengine_la-modes.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-modes.lo `test -f 'modes.c' || echo '$(srcdir)/'`modes.c libcfengine_la-sockaddr.lo: sockaddr.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-sockaddr.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-sockaddr.Tpo -c -o libcfengine_la-sockaddr.lo `test -f 'sockaddr.c' || echo '$(srcdir)/'`sockaddr.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-sockaddr.Tpo $(DEPDIR)/libcfengine_la-sockaddr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sockaddr.c' object='libcfengine_la-sockaddr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-sockaddr.lo `test -f 'sockaddr.c' || echo '$(srcdir)/'`sockaddr.c libcfengine_la-chflags.lo: chflags.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-chflags.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-chflags.Tpo -c -o libcfengine_la-chflags.lo `test -f 'chflags.c' || echo '$(srcdir)/'`chflags.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-chflags.Tpo $(DEPDIR)/libcfengine_la-chflags.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='chflags.c' object='libcfengine_la-chflags.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-chflags.lo `test -f 'chflags.c' || echo '$(srcdir)/'`chflags.c libcfengine_la-locks.lo: locks.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-locks.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-locks.Tpo -c -o libcfengine_la-locks.lo `test -f 'locks.c' || echo '$(srcdir)/'`locks.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-locks.Tpo $(DEPDIR)/libcfengine_la-locks.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='locks.c' object='libcfengine_la-locks.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-locks.lo `test -f 'locks.c' || echo '$(srcdir)/'`locks.c libcfengine_la-mount.lo: mount.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-mount.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-mount.Tpo -c -o libcfengine_la-mount.lo `test -f 'mount.c' || echo '$(srcdir)/'`mount.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-mount.Tpo $(DEPDIR)/libcfengine_la-mount.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mount.c' object='libcfengine_la-mount.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-mount.lo `test -f 'mount.c' || echo '$(srcdir)/'`mount.c libcfengine_la-macro.lo: macro.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-macro.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-macro.Tpo -c -o libcfengine_la-macro.lo `test -f 'macro.c' || echo '$(srcdir)/'`macro.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-macro.Tpo $(DEPDIR)/libcfengine_la-macro.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='macro.c' object='libcfengine_la-macro.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-macro.lo `test -f 'macro.c' || echo '$(srcdir)/'`macro.c libcfengine_la-filenames.lo: filenames.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-filenames.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-filenames.Tpo -c -o libcfengine_la-filenames.lo `test -f 'filenames.c' || echo '$(srcdir)/'`filenames.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-filenames.Tpo $(DEPDIR)/libcfengine_la-filenames.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='filenames.c' object='libcfengine_la-filenames.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-filenames.lo `test -f 'filenames.c' || echo '$(srcdir)/'`filenames.c libcfengine_la-varstring.lo: varstring.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-varstring.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-varstring.Tpo -c -o libcfengine_la-varstring.lo `test -f 'varstring.c' || echo '$(srcdir)/'`varstring.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-varstring.Tpo $(DEPDIR)/libcfengine_la-varstring.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='varstring.c' object='libcfengine_la-varstring.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-varstring.lo `test -f 'varstring.c' || echo '$(srcdir)/'`varstring.c libcfengine_la-wildcard.lo: wildcard.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-wildcard.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-wildcard.Tpo -c -o libcfengine_la-wildcard.lo `test -f 'wildcard.c' || echo '$(srcdir)/'`wildcard.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-wildcard.Tpo $(DEPDIR)/libcfengine_la-wildcard.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='wildcard.c' object='libcfengine_la-wildcard.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-wildcard.lo `test -f 'wildcard.c' || echo '$(srcdir)/'`wildcard.c libcfengine_la-cfparse.lo: cfparse.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-cfparse.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-cfparse.Tpo -c -o libcfengine_la-cfparse.lo `test -f 'cfparse.c' || echo '$(srcdir)/'`cfparse.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-cfparse.Tpo $(DEPDIR)/libcfengine_la-cfparse.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cfparse.c' object='libcfengine_la-cfparse.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-cfparse.lo `test -f 'cfparse.c' || echo '$(srcdir)/'`cfparse.c libcfengine_la-comparray.lo: comparray.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-comparray.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-comparray.Tpo -c -o libcfengine_la-comparray.lo `test -f 'comparray.c' || echo '$(srcdir)/'`comparray.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-comparray.Tpo $(DEPDIR)/libcfengine_la-comparray.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='comparray.c' object='libcfengine_la-comparray.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-comparray.lo `test -f 'comparray.c' || echo '$(srcdir)/'`comparray.c libcfengine_la-read.lo: read.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-read.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-read.Tpo -c -o libcfengine_la-read.lo `test -f 'read.c' || echo '$(srcdir)/'`read.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-read.Tpo $(DEPDIR)/libcfengine_la-read.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='read.c' object='libcfengine_la-read.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-read.lo `test -f 'read.c' || echo '$(srcdir)/'`read.c libcfengine_la-checksums.lo: checksums.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-checksums.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-checksums.Tpo -c -o libcfengine_la-checksums.lo `test -f 'checksums.c' || echo '$(srcdir)/'`checksums.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-checksums.Tpo $(DEPDIR)/libcfengine_la-checksums.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='checksums.c' object='libcfengine_la-checksums.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-checksums.lo `test -f 'checksums.c' || echo '$(srcdir)/'`checksums.c libcfengine_la-proto.lo: proto.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-proto.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-proto.Tpo -c -o libcfengine_la-proto.lo `test -f 'proto.c' || echo '$(srcdir)/'`proto.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-proto.Tpo $(DEPDIR)/libcfengine_la-proto.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='proto.c' object='libcfengine_la-proto.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-proto.lo `test -f 'proto.c' || echo '$(srcdir)/'`proto.c libcfengine_la-filters.lo: filters.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-filters.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-filters.Tpo -c -o libcfengine_la-filters.lo `test -f 'filters.c' || echo '$(srcdir)/'`filters.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-filters.Tpo $(DEPDIR)/libcfengine_la-filters.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='filters.c' object='libcfengine_la-filters.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-filters.lo `test -f 'filters.c' || echo '$(srcdir)/'`filters.c libcfengine_la-copy.lo: copy.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-copy.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-copy.Tpo -c -o libcfengine_la-copy.lo `test -f 'copy.c' || echo '$(srcdir)/'`copy.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-copy.Tpo $(DEPDIR)/libcfengine_la-copy.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='copy.c' object='libcfengine_la-copy.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-copy.lo `test -f 'copy.c' || echo '$(srcdir)/'`copy.c libcfengine_la-repository.lo: repository.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-repository.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-repository.Tpo -c -o libcfengine_la-repository.lo `test -f 'repository.c' || echo '$(srcdir)/'`repository.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-repository.Tpo $(DEPDIR)/libcfengine_la-repository.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='repository.c' object='libcfengine_la-repository.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-repository.lo `test -f 'repository.c' || echo '$(srcdir)/'`repository.c libcfengine_la-rotate.lo: rotate.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-rotate.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-rotate.Tpo -c -o libcfengine_la-rotate.lo `test -f 'rotate.c' || echo '$(srcdir)/'`rotate.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-rotate.Tpo $(DEPDIR)/libcfengine_la-rotate.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='rotate.c' object='libcfengine_la-rotate.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-rotate.lo `test -f 'rotate.c' || echo '$(srcdir)/'`rotate.c libcfengine_la-errors.lo: errors.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-errors.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-errors.Tpo -c -o libcfengine_la-errors.lo `test -f 'errors.c' || echo '$(srcdir)/'`errors.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-errors.Tpo $(DEPDIR)/libcfengine_la-errors.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='errors.c' object='libcfengine_la-errors.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-errors.lo `test -f 'errors.c' || echo '$(srcdir)/'`errors.c libcfengine_la-cflex.lo: cflex.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-cflex.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-cflex.Tpo -c -o libcfengine_la-cflex.lo `test -f 'cflex.c' || echo '$(srcdir)/'`cflex.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-cflex.Tpo $(DEPDIR)/libcfengine_la-cflex.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='cflex.c' object='libcfengine_la-cflex.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-cflex.lo `test -f 'cflex.c' || echo '$(srcdir)/'`cflex.c libcfengine_la-net.lo: net.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-net.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-net.Tpo -c -o libcfengine_la-net.lo `test -f 'net.c' || echo '$(srcdir)/'`net.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-net.Tpo $(DEPDIR)/libcfengine_la-net.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='net.c' object='libcfengine_la-net.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-net.lo `test -f 'net.c' || echo '$(srcdir)/'`net.c libcfengine_la-df.lo: df.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-df.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-df.Tpo -c -o libcfengine_la-df.lo `test -f 'df.c' || echo '$(srcdir)/'`df.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-df.Tpo $(DEPDIR)/libcfengine_la-df.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='df.c' object='libcfengine_la-df.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-df.lo `test -f 'df.c' || echo '$(srcdir)/'`df.c libcfengine_la-log.lo: log.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-log.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-log.Tpo -c -o libcfengine_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-log.Tpo $(DEPDIR)/libcfengine_la-log.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='log.c' object='libcfengine_la-log.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-log.lo `test -f 'log.c' || echo '$(srcdir)/'`log.c libcfengine_la-crypto.lo: crypto.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-crypto.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-crypto.Tpo -c -o libcfengine_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-crypto.Tpo $(DEPDIR)/libcfengine_la-crypto.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto.c' object='libcfengine_la-crypto.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-crypto.lo `test -f 'crypto.c' || echo '$(srcdir)/'`crypto.c libcfengine_la-popen.lo: popen.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-popen.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-popen.Tpo -c -o libcfengine_la-popen.lo `test -f 'popen.c' || echo '$(srcdir)/'`popen.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-popen.Tpo $(DEPDIR)/libcfengine_la-popen.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='popen.c' object='libcfengine_la-popen.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-popen.lo `test -f 'popen.c' || echo '$(srcdir)/'`popen.c libcfengine_la-popen_def.lo: popen_def.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-popen_def.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-popen_def.Tpo -c -o libcfengine_la-popen_def.lo `test -f 'popen_def.c' || echo '$(srcdir)/'`popen_def.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-popen_def.Tpo $(DEPDIR)/libcfengine_la-popen_def.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='popen_def.c' object='libcfengine_la-popen_def.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-popen_def.lo `test -f 'popen_def.c' || echo '$(srcdir)/'`popen_def.c libcfengine_la-sensible.lo: sensible.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-sensible.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-sensible.Tpo -c -o libcfengine_la-sensible.lo `test -f 'sensible.c' || echo '$(srcdir)/'`sensible.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-sensible.Tpo $(DEPDIR)/libcfengine_la-sensible.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sensible.c' object='libcfengine_la-sensible.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-sensible.lo `test -f 'sensible.c' || echo '$(srcdir)/'`sensible.c libcfengine_la-acl.lo: acl.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-acl.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-acl.Tpo -c -o libcfengine_la-acl.lo `test -f 'acl.c' || echo '$(srcdir)/'`acl.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-acl.Tpo $(DEPDIR)/libcfengine_la-acl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='acl.c' object='libcfengine_la-acl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-acl.lo `test -f 'acl.c' || echo '$(srcdir)/'`acl.c libcfengine_la-dce_acl.lo: dce_acl.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-dce_acl.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-dce_acl.Tpo -c -o libcfengine_la-dce_acl.lo `test -f 'dce_acl.c' || echo '$(srcdir)/'`dce_acl.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-dce_acl.Tpo $(DEPDIR)/libcfengine_la-dce_acl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dce_acl.c' object='libcfengine_la-dce_acl.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-dce_acl.lo `test -f 'dce_acl.c' || echo '$(srcdir)/'`dce_acl.c libcfengine_la-nameinfo.lo: nameinfo.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-nameinfo.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-nameinfo.Tpo -c -o libcfengine_la-nameinfo.lo `test -f 'nameinfo.c' || echo '$(srcdir)/'`nameinfo.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-nameinfo.Tpo $(DEPDIR)/libcfengine_la-nameinfo.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nameinfo.c' object='libcfengine_la-nameinfo.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-nameinfo.lo `test -f 'nameinfo.c' || echo '$(srcdir)/'`nameinfo.c libcfengine_la-strategies.lo: strategies.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-strategies.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-strategies.Tpo -c -o libcfengine_la-strategies.lo `test -f 'strategies.c' || echo '$(srcdir)/'`strategies.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-strategies.Tpo $(DEPDIR)/libcfengine_la-strategies.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='strategies.c' object='libcfengine_la-strategies.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-strategies.lo `test -f 'strategies.c' || echo '$(srcdir)/'`strategies.c libcfengine_la-granules.lo: granules.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-granules.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-granules.Tpo -c -o libcfengine_la-granules.lo `test -f 'granules.c' || echo '$(srcdir)/'`granules.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-granules.Tpo $(DEPDIR)/libcfengine_la-granules.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='granules.c' object='libcfengine_la-granules.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-granules.lo `test -f 'granules.c' || echo '$(srcdir)/'`granules.c libcfengine_la-methods.lo: methods.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-methods.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-methods.Tpo -c -o libcfengine_la-methods.lo `test -f 'methods.c' || echo '$(srcdir)/'`methods.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-methods.Tpo $(DEPDIR)/libcfengine_la-methods.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='methods.c' object='libcfengine_la-methods.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-methods.lo `test -f 'methods.c' || echo '$(srcdir)/'`methods.c libcfengine_la-dtypes.lo: dtypes.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-dtypes.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-dtypes.Tpo -c -o libcfengine_la-dtypes.lo `test -f 'dtypes.c' || echo '$(srcdir)/'`dtypes.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-dtypes.Tpo $(DEPDIR)/libcfengine_la-dtypes.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dtypes.c' object='libcfengine_la-dtypes.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-dtypes.lo `test -f 'dtypes.c' || echo '$(srcdir)/'`dtypes.c libcfengine_la-state.lo: state.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-state.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-state.Tpo -c -o libcfengine_la-state.lo `test -f 'state.c' || echo '$(srcdir)/'`state.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-state.Tpo $(DEPDIR)/libcfengine_la-state.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='state.c' object='libcfengine_la-state.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-state.lo `test -f 'state.c' || echo '$(srcdir)/'`state.c libcfengine_la-checksum_db.lo: checksum_db.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-checksum_db.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-checksum_db.Tpo -c -o libcfengine_la-checksum_db.lo `test -f 'checksum_db.c' || echo '$(srcdir)/'`checksum_db.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-checksum_db.Tpo $(DEPDIR)/libcfengine_la-checksum_db.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='checksum_db.c' object='libcfengine_la-checksum_db.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-checksum_db.lo `test -f 'checksum_db.c' || echo '$(srcdir)/'`checksum_db.c libcfengine_la-expand-files.lo: expand-files.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-expand-files.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-expand-files.Tpo -c -o libcfengine_la-expand-files.lo `test -f 'expand-files.c' || echo '$(srcdir)/'`expand-files.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-expand-files.Tpo $(DEPDIR)/libcfengine_la-expand-files.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='expand-files.c' object='libcfengine_la-expand-files.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-expand-files.lo `test -f 'expand-files.c' || echo '$(srcdir)/'`expand-files.c libcfengine_la-expand-tidy.lo: expand-tidy.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-expand-tidy.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-expand-tidy.Tpo -c -o libcfengine_la-expand-tidy.lo `test -f 'expand-tidy.c' || echo '$(srcdir)/'`expand-tidy.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-expand-tidy.Tpo $(DEPDIR)/libcfengine_la-expand-tidy.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='expand-tidy.c' object='libcfengine_la-expand-tidy.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-expand-tidy.lo `test -f 'expand-tidy.c' || echo '$(srcdir)/'`expand-tidy.c libcfengine_la-expand-image.lo: expand-image.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-expand-image.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-expand-image.Tpo -c -o libcfengine_la-expand-image.lo `test -f 'expand-image.c' || echo '$(srcdir)/'`expand-image.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-expand-image.Tpo $(DEPDIR)/libcfengine_la-expand-image.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='expand-image.c' object='libcfengine_la-expand-image.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-expand-image.lo `test -f 'expand-image.c' || echo '$(srcdir)/'`expand-image.c libcfengine_la-expand-editfiles.lo: expand-editfiles.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-expand-editfiles.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-expand-editfiles.Tpo -c -o libcfengine_la-expand-editfiles.lo `test -f 'expand-editfiles.c' || echo '$(srcdir)/'`expand-editfiles.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-expand-editfiles.Tpo $(DEPDIR)/libcfengine_la-expand-editfiles.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='expand-editfiles.c' object='libcfengine_la-expand-editfiles.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-expand-editfiles.lo `test -f 'expand-editfiles.c' || echo '$(srcdir)/'`expand-editfiles.c libcfengine_la-package.lo: package.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-package.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-package.Tpo -c -o libcfengine_la-package.lo `test -f 'package.c' || echo '$(srcdir)/'`package.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-package.Tpo $(DEPDIR)/libcfengine_la-package.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='package.c' object='libcfengine_la-package.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-package.lo `test -f 'package.c' || echo '$(srcdir)/'`package.c libcfengine_la-scli.lo: scli.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -MT libcfengine_la-scli.lo -MD -MP -MF $(DEPDIR)/libcfengine_la-scli.Tpo -c -o libcfengine_la-scli.lo `test -f 'scli.c' || echo '$(srcdir)/'`scli.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libcfengine_la-scli.Tpo $(DEPDIR)/libcfengine_la-scli.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='scli.c' object='libcfengine_la-scli.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcfengine_la_CFLAGS) $(CFLAGS) -c -o libcfengine_la-scli.lo `test -f 'scli.c' || echo '$(srcdir)/'`scli.c .l.c: $(am__skiplex) $(SHELL) $(YLWRAP) $< $(LEX_OUTPUT_ROOT).c $@ -- $(LEXCOMPILE) .y.c: $(am__skipyacc) $(SHELL) $(YLWRAP) $< y.tab.c $@ y.tab.h $*.h y.output $*.output -- $(YACCCOMPILE) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: $(HEADERS) $(SOURCES) conf.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ list='$(SOURCES) $(HEADERS) conf.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: $(HEADERS) $(SOURCES) conf.h.in $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ list='$(SOURCES) $(HEADERS) conf.h.in $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS) conf.h installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(sbindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -rm -f cflex.c -rm -f cfparse.c -rm -f cfparse.h -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags dvi: dvi-am dvi-am: html: html-am info: info-am info-am: install-data-am: install-dvi: install-dvi-am install-exec-am: install-libLTLIBRARIES install-sbinPROGRAMS install-html: install-html-am install-info: install-info-am install-man: install-pdf: install-pdf-am install-ps: install-ps-am installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-libLTLIBRARIES uninstall-sbinPROGRAMS .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool clean-sbinPROGRAMS ctags \ distclean distclean-compile distclean-generic distclean-hdr \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-libLTLIBRARIES install-man install-pdf \ install-pdf-am install-ps install-ps-am install-sbinPROGRAMS \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags uninstall uninstall-am \ uninstall-libLTLIBRARIES uninstall-sbinPROGRAMS # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-2.2.10/src/instrument.c0000644000175000001440000006030311152045230013425 00000000000000 /* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: instrument.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include # if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) pthread_mutex_t MUTEX_GETADDR = PTHREAD_MUTEX_INITIALIZER; # endif /* Alter this code at your peril. Berkeley DB is very sensitive to errors. */ /***************************************************************/ void RecordPerformance(char *eventname,time_t t,double value) { DB *dbp; DB_ENV *dbenv = NULL; char name[CF_BUFSIZE]; struct Event e,newe; double lastseen,delta2; int lsea = CF_WEEK; time_t now = time(NULL); Debug("PerformanceEvent(%s,%.1f s)\n",eventname,value); snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_PERFORMANCE); if ((errno = db_create(&dbp,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open performance database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open performance database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } if (ReadDB(dbp,eventname,&e,sizeof(e))) { lastseen = now - e.t; newe.t = t; newe.Q.q = value; newe.Q.expect = GAverage(value,e.Q.expect,0.3); delta2 = (value - e.Q.expect)*(value - e.Q.expect); newe.Q.var = GAverage(delta2,e.Q.var,0.3); /* Have to kickstart variance computation, assume 1% to start */ if (newe.Q.var <= 0.0009) { newe.Q.var = newe.Q.expect / 100.0; } } else { lastseen = 0.0; newe.t = t; newe.Q.q = value; newe.Q.expect = value; newe.Q.var = 0.001; } if (lastseen > (double)lsea) { Verbose("Performance record %s expired\n",eventname); DeleteDB(dbp,eventname); } else { Verbose("Performance(%s): time=%.4f secs, av=%.4f +/- %.4f\n",eventname,value,newe.Q.expect,sqrt(newe.Q.var)); WriteDB(dbp,eventname,&newe,sizeof(newe)); } dbp->close(dbp,0); } /***************************************************************/ void RecordClassUsage() { DB *dbp; DB_ENV *dbenv = NULL; DBC *dbcp; DBT key,stored; char name[CF_BUFSIZE]; struct Event e,entry,newe; double lsea = CF_WEEK * 52; /* expire after a year */ time_t now = time(NULL); struct Item *ip,*list = NULL; double lastseen,delta2; double vtrue = 1.0; /* end with a rough probability */ Debug("RecordClassUsage\n"); for (ip = VHEAP; ip != NULL; ip=ip->next) { if (!IsItemIn(list,ip->name)) { PrependItem(&list,ip->name,NULL); } } for (ip = VALLADDCLASSES; ip != NULL; ip=ip->next) { if (!IsItemIn(list,ip->name)) { PrependItem(&list,ip->name,NULL); } } snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_CLASSUSAGE); if ((errno = db_create(&dbp,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open performance database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open performance database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } /* First record the classes that are in use */ for (ip = list; ip != NULL; ip=ip->next) { if (ReadDB(dbp,ip->name,&e,sizeof(e))) { lastseen = now - e.t; newe.t = now; newe.Q.q = vtrue; newe.Q.expect = GAverage(vtrue,e.Q.expect,0.5); delta2 = (vtrue - e.Q.expect)*(vtrue - e.Q.expect); newe.Q.var = GAverage(delta2,e.Q.var,0.5); } else { lastseen = 0.0; newe.t = now; newe.Q.q = 0.5*vtrue; newe.Q.expect = 0.5*vtrue; /* With no data it's 50/50 what we can say */ newe.Q.var = 0.000; } if (lastseen > lsea) { Verbose("Class usage record %s expired\n",ip->name); DeleteDB(dbp,ip->name); } else { Debug("Upgrading %s %f\n",ip->name,newe.Q.expect); WriteDB(dbp,ip->name,&newe,sizeof(newe)); } } /* Then update with zero the ones we know about that are not active */ /* Acquire a cursor for the database. */ if ((errno = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { Debug("Error reading from class database: "); dbp->err(dbp, errno, "DB->cursor"); return; } /* Initialize the key/data return pair. */ memset(&key, 0, sizeof(key)); memset(&stored, 0, sizeof(stored)); memset(&entry, 0, sizeof(entry)); while (dbcp->c_get(dbcp, &key, &stored, DB_NEXT) == 0) { double measure,av,var; time_t then; char tbuf[CF_BUFSIZE],eventname[CF_BUFSIZE]; strcpy(eventname,(char *)key.data); if (stored.data != NULL) { memcpy(&entry,stored.data,sizeof(entry)); then = entry.t; measure = entry.Q.q; av = entry.Q.expect; var = entry.Q.var; lastseen = now - then; snprintf(tbuf,CF_BUFSIZE-1,"%s",ctime(&then)); tbuf[strlen(tbuf)-9] = '\0'; /* Chop off second and year */ if (lastseen > lsea) { Verbose("Class usage record %s expired\n",eventname); DeleteDB(dbp,eventname); } else if (!IsItemIn(list,eventname)) { newe.t = then; newe.Q.q = 0; newe.Q.expect = GAverage(0.0,av,0.5); delta2 = av*av; newe.Q.var = GAverage(delta2,var,0.5); Debug("Downgrading class %s from %lf to %lf\n",eventname,entry.Q.expect,newe.Q.expect); WriteDB(dbp,eventname,&newe,sizeof(newe)); } } } dbp->close(dbp,0); } /***************************************************************/ void LastSeen(char *hostname,enum roles role) { DB *dbp,*dbpent; DB_ENV *dbenv = NULL, *dbenv2 = NULL; char name[CF_BUFSIZE],databuf[CF_BUFSIZE]; time_t now = time(NULL); struct QPoint q,newq; double lastseen,delta2; int lsea = -1; if (strlen(hostname) == 0) { snprintf(OUTPUT,CF_BUFSIZE,"LastSeen registry for empty hostname with role %d",role); CfLog(cflogonly,OUTPUT,""); return; } Debug("LastSeen(%s) reg\n",hostname); /* Tidy old versions - temporary */ snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_OLDLASTDB_FILE); unlink(name); if ((errno = db_create(&dbp,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't init last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } /* Now open special file for peer entropy record - INRIA intermittency */ snprintf(name,CF_BUFSIZE-1,"%s/%s.%s",CFWORKDIR,CF_LASTDB_FILE,hostname); if ((errno = db_create(&dbpent,dbenv2,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't init last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbpent->open)(dbpent,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbpent->open)(dbpent,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef HAVE_PTHREAD_H if (pthread_mutex_lock(&MUTEX_GETADDR) != 0) { CfLog(cferror,"pthread_mutex_lock failed","unlock"); exit(1); } #endif switch (role) { case cf_accept: snprintf(databuf,CF_BUFSIZE-1,"-%s",Hostname2IPString(hostname)); break; case cf_connect: snprintf(databuf,CF_BUFSIZE-1,"+%s",Hostname2IPString(hostname)); break; } #ifdef HAVE_PTHREAD_H if (pthread_mutex_unlock(&MUTEX_GETADDR) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","unlock"); exit(1); } #endif if (GetMacroValue(CONTEXTID,"LastSeenExpireAfter")) { lsea = atoi(GetMacroValue(CONTEXTID,"LastSeenExpireAfter")); lsea *= CF_TICKS_PER_DAY; } if (lsea < 0) { lsea = CF_WEEK; } if (ReadDB(dbp,databuf,&q,sizeof(q))) { lastseen = (double)now - q.q; newq.q = (double)now; /* Last seen is now-then */ newq.expect = GAverage(lastseen,q.expect,0.3); delta2 = (lastseen - q.expect)*(lastseen - q.expect); newq.var = GAverage(delta2,q.var,0.3); } else { lastseen = 0.0; newq.q = (double)now; newq.expect = 0.0; newq.var = 0.0; } #ifdef HAVE_PTHREAD_H if (pthread_mutex_lock(&MUTEX_GETADDR) != 0) { CfLog(cferror,"pthread_mutex_lock failed","unlock"); exit(1); } #endif if (lastseen > (double)lsea) { Verbose("Last seen %s expired\n",databuf); DeleteDB(dbp,databuf); } else { WriteDB(dbp,databuf,&newq,sizeof(newq)); WriteDB(dbpent,GenTimeKey(now),&newq,sizeof(newq)); } #ifdef HAVE_PTHREAD_H if (pthread_mutex_unlock(&MUTEX_GETADDR) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","unlock"); exit(1); } #endif dbp->close(dbp,0); dbpent->close(dbpent,0); } /***************************************************************/ void CheckFriendConnections(int hours) /* Go through the database of recent connections and check for Long Time No See ...*/ { DBT key,value; DB *dbp; DBC *dbcp; DB_ENV *dbenv = NULL; int ret, secs = CF_TICKS_PER_HOUR*hours, criterion, overdue, regex=false; time_t now = time(NULL),lsea = -1, tthen, then = 0; char name[CF_BUFSIZE],hostname[CF_BUFSIZE],datebuf[CF_MAXVARSIZE]; char addr[CF_BUFSIZE],type[CF_BUFSIZE], *regexp; struct QPoint entry; double average = 0.0, var = 0.0, ticksperminute = 60.0; double ticksperhour = (double)CF_TICKS_PER_HOUR,ticksperday = (double)CF_TICKS_PER_DAY; regex_t rx,rxcache; regmatch_t pmatch; if (regexp = GetMacroValue(CONTEXTID,"IgnoreFriendRegex")) { Verbose("IgnoreFriendRegex %s\n\n",regexp); if ((ret = regcomp(&rx,regexp,REG_EXTENDED)) != 0) { regerror(ret,&rx,name,1023); snprintf(OUTPUT,CF_BUFSIZE,"Regular expression error %d for %s: %s\n",ret,regexp,name); CfLog(cfinform,OUTPUT,""); regex = false; } else { regex = true; } } Verbose("CheckFriendConnections(%d)\n",hours); snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); if ((errno = db_create(&dbp,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } /* Acquire a cursor for the database. */ if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { CfLog(cferror,"Error reading from last-seen database",""); dbp->err(dbp, ret, "DB->cursor"); return; } /* Walk through the database and print out the key/data pairs. */ memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { memset(&entry, 0, sizeof(entry)); strcpy(hostname,(char *)key.data); if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); then = (time_t)entry.q; average = (double)entry.expect; var = (double)entry.var; } else { continue; } /* Got data, now get expiry criterion */ if (secs == 0) { /* Twice the average delta is significant */ criterion = (now - then > (int)(average+2.0*sqrt(var)+0.5)); overdue = now - then - (int)(average); } else { criterion = (now - then > secs); overdue = (now - then - secs); } if (GetMacroValue(CONTEXTID,"LastSeenExpireAfter")) { lsea = atoi(GetMacroValue(CONTEXTID,"LastSeenExpireAfter")); lsea *= CF_TICKS_PER_DAY; } if (lsea < 0) { lsea = (time_t)CF_WEEK/7; } if (regex) { if (regexec(&rx,IPString2Hostname(hostname+1),1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(hostname+1))) { Verbose("Not judging friend %s\n",hostname); criterion = false; lsea = CF_INFINITY; } } } tthen = (time_t)then; snprintf(datebuf,CF_BUFSIZE-1,"%s",ctime(&tthen)); datebuf[strlen(datebuf)-9] = '\0'; /* Chop off second and year */ snprintf(addr,15,"%s",hostname+1); switch(*hostname) { case '+': snprintf(type,CF_BUFSIZE,"last responded to hails"); break; case'-': snprintf(type,CF_BUFSIZE,"last hailed us"); break; } snprintf(OUTPUT,CF_BUFSIZE,"Host %s i.e. %s %s @ [%s] (overdue by %d mins)", IPString2Hostname(hostname+1), addr, type, datebuf, overdue/(int)ticksperminute); if (criterion) { CfLog(cferror,OUTPUT,""); } else { CfLog(cfverbose,OUTPUT,""); } snprintf(OUTPUT,CF_BUFSIZE,"i.e. (%.2f) hrs ago, Av %.2f +/- %.2f hrs\n", ((double)(now-then))/ticksperhour, average/ticksperhour, sqrt(var)/ticksperhour); if (criterion) { CfLog(cferror,OUTPUT,""); } else { CfLog(cfverbose,OUTPUT,""); } if ((now-then) > lsea) { snprintf(OUTPUT,CF_BUFSIZE,"Giving up on host %s -- too long since last seen",IPString2Hostname(hostname+1)); CfLog(cferror,OUTPUT,""); DeleteDB(dbp,hostname); } memset(&value,0,sizeof(value)); memset(&key,0,sizeof(key)); } dbcp->c_close(dbcp); dbp->close(dbp,0); } /***************************************************************/ void CheckFriendReliability() { DBT key,value; DB *dbp,*dbpent; DBC *dbcp; DB_ENV *dbenv = NULL, *dbenv2 = NULL; int i,ret; double n[CF_RELIABLE_CLASSES],n_av[CF_RELIABLE_CLASSES],total; double p[CF_RELIABLE_CLASSES],p_av[CF_RELIABLE_CLASSES]; char name[CF_BUFSIZE],hostname[CF_BUFSIZE],timekey[CF_MAXVARSIZE]; struct QPoint entry; struct Item *ip, *hostlist = NULL; double entropy,average,var,sum,sum_av,expect,actual; time_t now = time(NULL), then, lastseen = CF_WEEK; Verbose("CheckFriendReliability()\n"); snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); average = (double) CF_HOUR; /* It will take a week for a host to be deemed reliable */ var = 0; if ((errno = db_create(&dbp,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { CfLog(cferror,"Error reading from last-seen database",""); dbp->err(dbp, ret, "DB->cursor"); return; } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { strcpy(hostname,IPString2Hostname((char *)key.data+1)); if (!IsItemIn(hostlist,hostname)) { /* Check hostname not recorded twice with +/- */ AppendItem(&hostlist,hostname,NULL); Verbose(" Measuring reliability of %s\n",hostname); } } dbcp->c_close(dbcp); dbp->close(dbp,0); /* Now go through each host and recompute entropy */ for (ip = hostlist; ip != NULL; ip=ip->next) { snprintf(name,CF_BUFSIZE-1,"%s/%s.%s",CFWORKDIR,CF_LASTDB_FILE,ip->name); if ((errno = db_create(&dbpent,dbenv2,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't init reliability profile database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbpent->open)(dbpent,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbpent->open)(dbpent,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open last-seen database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); continue; } for (i = 0; i < CF_RELIABLE_CLASSES; i++) { n[i] = n_av[i] = 0.0; } total = 0.0; for (now = CF_MONDAY_MORNING; now < CF_MONDAY_MORNING+CF_WEEK; now += CF_MEASURE_INTERVAL) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); strcpy(timekey,GenTimeKey(now)); key.data = timekey; key.size = strlen(timekey)+1; if ((errno = dbp->get(dbp,NULL,&key,&value,0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp,errno,NULL); exit(1); } } if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); then = (time_t)entry.q; lastseen = now - then; if (lastseen < 0) { lastseen = 0; /* Never seen before, so pretend */ } average = (double)entry.expect; var = (double)entry.var; Debug("%s => then = %ld, lastseen = %ld, average=%.2f\n",hostname,then,lastseen,average); } else { /* If we have no data, it means no contact for whatever reason. It could be unable to respond unwilling to respond, policy etc. Assume for argument that we expect regular responses ... */ lastseen += CF_MEASURE_INTERVAL; /* infer based on no data */ } for (i = 0; i < CF_RELIABLE_CLASSES; i++) { if (lastseen >= i*CF_HOUR && lastseen < (i+1)*CF_HOUR) { n[i]++; } if (average >= (double)(i*CF_HOUR) && average < (double)((i+1)*CF_HOUR)) { n_av[i]++; } } total++; } sum = sum_av = 0.0; for (i = 0; i < CF_RELIABLE_CLASSES; i++) { p[i] = n[i]/total; p_av[i] = n_av[i]/total; sum += p[i]; sum_av += p_av[i]; } Debug("Reliabilities sum to %.2f av %.2f\n\n",sum,sum_av); sum = sum_av = 0.0; for (i = 0; i < CF_RELIABLE_CLASSES; i++) { if (p[i] == 0.0) { continue; } sum -= p[i] * log(p[i]); } for (i = 0; i < CF_RELIABLE_CLASSES; i++) { if (p_av[i] == 0.0) { continue; } sum_av -= p_av[i] * log(p_av[i]); } actual = sum/log((double)CF_RELIABLE_CLASSES)*100.0; expect = sum_av/log((double)CF_RELIABLE_CLASSES)*100.0; Verbose("Scaled entropy for %s = %.1f %%\n",ip->name,actual); Verbose("Expected entropy for %s = %.1f %%\n\n",ip->name,expect); if (actual > expect) { snprintf(OUTPUT,CF_BUFSIZE,"The reliability of %s has decreased!\n",ip->name); CfLog(cfinform,OUTPUT,""); } if (actual > 50.0) { snprintf(OUTPUT,CF_BUFSIZE,"FriendStatus reports the intermittency of %s above 50%% (scaled entropy units)\n",ip->name); CfLog(cferror,OUTPUT,""); } if (expect > actual) { snprintf(OUTPUT,CF_BUFSIZE,"The reliability of %s seems to be improving!\n",ip->name); CfLog(cfinform,OUTPUT,""); } dbpent->close(dbpent,0); } DeleteItemList(hostlist); } /*****************************************************************************/ /* level 1 */ /*****************************************************************************/ int ReadDB(DB *dbp,char *name,void *ptr,int size) { DBT *key,value; key = NewDBKey(name); memset(&value,0,sizeof(DBT)); if ((errno = dbp->get(dbp,NULL,key,&value,0)) == 0) { memset(ptr,0,size); memcpy(ptr,value.data,size); Debug("READ %s\n",name); DeleteDBKey(key); return true; } else { Debug("Database read failed: %s",db_strerror(errno)); return false; } } /*****************************************************************************/ int WriteDB(DB *dbp,char *name,void *ptr,int size) { DBT *key,*value; key = NewDBKey(name); value = NewDBValue(ptr,size); if ((errno = dbp->put(dbp,NULL,key,value,0)) != 0) { Debug("Database write failed: %s",db_strerror(errno)); DeleteDBKey(key); DeleteDBValue(value); return false; } else { Debug("WriteDB => %s\n",name); DeleteDBKey(key); DeleteDBValue(value); return true; } } /*****************************************************************************/ void DeleteDB(DB *dbp,char *name) { DBT *key; key = NewDBKey(name); if ((errno = dbp->del(dbp,NULL,key,0)) != 0) { Debug("Database deletion failed: %s",db_strerror(errno)); } DeleteDBKey(key); Debug("DELETED DB %s\n",name); } /*****************************************************************************/ /* Level 2 */ /*****************************************************************************/ DBT *NewDBKey(char *name) { char *dbkey; DBT *key; if ((dbkey = malloc(strlen(name)+1)) == NULL) { FatalError("NewChecksumKey malloc error"); } if ((key = (DBT *)malloc(sizeof(DBT))) == NULL) { FatalError("DBT malloc error"); } memset(key,0,sizeof(DBT)); memset(dbkey,0,strlen(name)+1); strncpy(dbkey,name,strlen(name)); key->data = (void *)dbkey; key->size = strlen(name)+1; return key; } /*****************************************************************************/ void DeleteDBKey(DBT *key) { free((char *)key->data); free((char *)key); } /*****************************************************************************/ DBT *NewDBValue(void *ptr,int size) { void *val; DBT *value; if ((val = (void *)malloc(size)) == NULL) { FatalError("NewDBKey malloc error"); } if ((value = (DBT *) malloc(sizeof(DBT))) == NULL) { FatalError("DBT Value malloc error"); } memset(value,0,sizeof(DBT)); memset(val,0,size); memcpy(val,ptr,size); value->data = val; value->size = size; return value; } /*****************************************************************************/ void DeleteDBValue(DBT *value) { free((char *)value->data); free((char *)value); } /*****************************************************************************/ /* Toolkit */ /*****************************************************************************/ double GAverage(double anew,double aold,double p) /* return convex mixture - p is the trust in the new value */ { return (p*anew + (1-p)*aold); } cfengine-2.2.10/src/cfparse.h0000644000175000001440000000600111170173310012641 00000000000000/* A Bison parser, made by GNU Bison 2.3. */ /* Skeleton interface for Bison's Yacc-like parsers in C Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 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, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { LVALUE = 258, ID = 259, VAROBJ = 260, LBRACK = 261, RBRACK = 262, CONTROL = 263, GROUPS = 264, ARROW = 265, EQUALS = 266, EDITFILES = 267, QSTRING = 268, RVALUE = 269, BCLASS = 270, LBRACE = 271, RBRACE = 272, PARSECLASS = 273, LARROW = 274, OPTION = 275, FUNCTION = 276, ACL = 277, ADMIT = 278, DENY = 279, FILTERS = 280, STRATEGIES = 281, ACTIONTYPE = 282, ACCESSOBJ = 283 }; #endif /* Tokens. */ #define LVALUE 258 #define ID 259 #define VAROBJ 260 #define LBRACK 261 #define RBRACK 262 #define CONTROL 263 #define GROUPS 264 #define ARROW 265 #define EQUALS 266 #define EDITFILES 267 #define QSTRING 268 #define RVALUE 269 #define BCLASS 270 #define LBRACE 271 #define RBRACE 272 #define PARSECLASS 273 #define LARROW 274 #define OPTION 275 #define FUNCTION 276 #define ACL 277 #define ADMIT 278 #define DENY 279 #define FILTERS 280 #define STRATEGIES 281 #define ACTIONTYPE 282 #define ACCESSOBJ 283 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef int YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif extern YYSTYPE yylval; cfengine-2.2.10/src/item-ext.c0000644000175000001440000013315410765042604012771 00000000000000/* cfengine for GNU Copyright (C) 1995,1999 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*********************************************************************/ /* */ /* TOOLKIT: the "item extension" object library for cfengine */ /* */ /*********************************************************************/ /* The functions in this file are mostly used by "editfiles" commands; * DoEditFile() may need to reset more globals before returning for * them to always work as expected. */ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************************************/ struct Item *ListFromArgs(char *string) /* Splits a string with quoted components etc */ { struct Item *ip = NULL; int inquotes_level = 0,i = 0,argc=0; int inquote_level = 0; int paren_level = 0; char *sp,lastch = '\0'; char item[CF_BUFSIZE]; memset(item,0,CF_BUFSIZE); for (sp = string; *sp != '\0'; sp++) { switch (*sp) { case '\"': if (lastch == '\\') /* Escaped quote */ { if (inquotes_level == 0) { yyerror("Quoting error - escaped quote outside string"); FatalError("Unrecoverable"); } i--; } else { inquotes_level = 1 - inquotes_level; /* toggle */ continue; } break; case '\'': if (lastch == '\\') /* Escaped quote */ { if (inquotes_level == 0) { yyerror("Quoting error - escaped quote outside string"); FatalError("Unrecoverable"); } i--; } else { inquote_level = 1 - inquote_level; /* toggle */ continue; } break; case '(': if (inquotes_level == 0) { paren_level++; } break; case ')': if (inquotes_level == 0) { paren_level--; } break; case ',': if ((inquotes_level == 0) && (paren_level == 0)) { item[i] = '\0'; i = 0; AppendItem(&ip,item,""); Debug("ListArg[%d]=(%s)\n",argc++,item); memset(item,0,CF_BUFSIZE); continue; } } item[i++] = *sp; lastch = *sp; } item[i] = '\0'; AppendItem(&ip,item,""); Debug("ListArg[%d]=(%s)\n",argc,item); return ip; } /*********************************************************************/ int OrderedListsMatch(struct Item *list1,struct Item *list2) { struct Item *ip1,*ip2; for (ip1 = list1,ip2 = list2; (ip1!=NULL)&&(ip2!=NULL); ip1=ip1->next,ip2=ip2->next) { if (strcmp(ip1->name,ip2->name) != 0) { Debug("OrderedListMatch failed on (%s,%s)\n",ip1->name,ip2->name); return false; } } if (ip1 != ip2) { return false; } return true; } /*********************************************************************/ int IsClassedItemIn(struct Item *list,char *item) { struct Item *ptr; if ((item == NULL) || (strlen(item) == 0)) { return true; } for (ptr = list; ptr != NULL; ptr=ptr->next) { if (strcmp(ptr->name,item) == 0) { if (IsExcluded(ptr->classes)) { continue; } return(true); } } return(false); } /*********************************************************************/ int IsWildItemIn(struct Item *list,char *wildcard) /* Checks whether item matches a list of wildcards */ { struct Item *ptr; for (ptr = list; ptr != NULL; ptr=ptr->next) { if (IsExcluded(ptr->classes)) { continue; } if (WildMatch(wildcard,ptr->name) || WildMatch(ptr->name,wildcard)) { Debug("IsWildItem(%s,%s)\n",wildcard,ptr->name); return(true); } } return(false); } /*********************************************************************/ void InsertItemAfter (struct Item **filestart,struct Item *ptr,char *string) { struct Item *ip; char *sp; EditVerbose("Inserting %s \n",string); if ((ip = (struct Item *)malloc(sizeof(struct Item))) == NULL) { CfLog(cferror,"","Can't allocate memory in InsertItemAfter()"); FatalError(""); } if ((sp = malloc(strlen(string)+1)) == NULL) { CfLog(cferror,"","Can't allocate memory in InsertItemAfter()"); FatalError(""); } if (CURRENTLINEPTR == NULL) /* File is empty */ { if (*filestart == NULL) { *filestart = ip; ip->next = NULL; } else { ip->next = (*filestart)->next; (*filestart)->next = ip; } strcpy(sp,string); ip->name = sp; ip->classes = NULL; CURRENTLINEPTR = ip; CURRENTLINENUMBER = 1; } else { ip->next = CURRENTLINEPTR->next; CURRENTLINENUMBER++; CURRENTLINEPTR->next = ip; CURRENTLINEPTR = ip; strcpy(sp,string); ip->name = sp; ip->classes = NULL; } NUMBEROFEDITS++; return; } /*********************************************************************/ struct Item *LocateNextItemContaining(struct Item *list,char *string) { struct Item *ip; for (ip = list; ip != NULL; ip=ip->next) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { EditVerbose("Aborting search, regex %s matches line\n",VEDITABORT); return NULL; } if (strstr(ip->name,string)) { return ip; } } return NULL; } /*********************************************************************/ int RegexOK(char *string) { regex_t rx; if (CfRegcomp(&rx,string, REG_EXTENDED) != 0) { return false; } regfree(&rx); return true; } /*********************************************************************/ struct Item *LocateNextItemMatching(struct Item *list,char *string) { struct Item *ip; regex_t rx,rxcache; regmatch_t pmatch; if (CfRegcomp(&rxcache,string, REG_EXTENDED) != 0) { return NULL; } for (ip = list; ip != NULL; ip=ip->next) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); regfree(&rx); return NULL; } memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,ip->name,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name))) { regfree(&rx); return ip; } } } /* regfree(&rx); */ return NULL; } /*********************************************************************/ struct Item *LocateNextItemStarting(struct Item *list,char *string) { struct Item *ip; for (ip = list; (ip != NULL); ip=ip->next) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); return NULL; } if (strncmp(ip->name,string,strlen(string)) == 0) { return ip; } } return NULL; } /*********************************************************************/ struct Item *LocateItemMatchingRegExp(struct Item *list,char *string) { struct Item *ip; regex_t rx,rxcache; regmatch_t pmatch; int line = CURRENTLINENUMBER; if (list != NULL) { Debug("LocateItemMatchingRexExp(%s,%s)\n",list->name,string); } if (CfRegcomp(&rxcache,string, REG_EXTENDED) != 0) { return NULL; } for (ip = list; (ip != NULL); ip=ip->next, line++) { if (ip->name == NULL) { continue; } memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); regfree(&rx); return NULL; } if (regexec(&rx,ip->name,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name))) { EditVerbose("Edit: Search ended at line %d\n",line); EditVerbose("Edit: (Found %s)\n",ip->name); CURRENTLINENUMBER = line; CURRENTLINEPTR = ip; regfree(&rx); return ip; } } } EditVerbose("Edit: Search for %s failed. Current line still %d\n",string,CURRENTLINENUMBER); /* regfree(&rx); */ return NULL; } /*********************************************************************/ struct Item *LocateItemContainingRegExp(struct Item *list,char *string) { struct Item *ip; regex_t rx,rxcache; regmatch_t pmatch; int line = 1; if (CfRegcomp(&rxcache,string, REG_EXTENDED) != 0) { return NULL; } for (ip = list; (ip != NULL); ip=ip->next) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); regfree(&rx); return NULL; } memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,ip->name,1,&pmatch,0) == 0) { EditVerbose("Search ended at line %d\n",line); CURRENTLINENUMBER = line; CURRENTLINEPTR = ip; regfree(&rx); return ip; } } EditVerbose("Search for %s failed. Current line still %d\n",string,CURRENTLINENUMBER); /* regfree(&rx);*/ return NULL; } /********************************************************************/ int DeleteToRegExp(struct Item **filestart,char *string) /* Delete up to but not including a line matching the regex */ { struct Item *ip, *ip_prev, *ip_end = NULL; int linefound = false; regex_t rx,rxcache; regmatch_t pmatch; Debug2("DeleteToRegExp(list,%s)\n",string); if (CURRENTLINEPTR == NULL) /* Shouldn't happen */ { CfLog(cferror,"File line-pointer undefined during editfile action\n",""); return true; } if (CfRegcomp(&rxcache,string, REG_EXTENDED) != 0) { return false; } for (ip = CURRENTLINEPTR; (ip != NULL); ip=ip->next) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); regfree(&rx); return false; } memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,ip->name,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name))) { linefound = true; ip_end = ip; break; } } } if (! linefound) { return false; } for (ip_prev = *filestart; ip_prev != CURRENTLINEPTR && ip_prev->next != CURRENTLINEPTR; ip_prev=ip_prev->next) { } for (ip = CURRENTLINEPTR; ip != NULL; ip = CURRENTLINEPTR) { if (ip->name == NULL) { continue; } if (ip == ip_end) { EditVerbose("Edit: terminating line: %s (Done)\n",ip->name); return true; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); regfree(&rx); return false; } EditVerbose("Edit: delete line %s\n",ip->name); NUMBEROFEDITS++; CURRENTLINEPTR = ip->next; if (ip == *filestart) { *filestart = ip->next; } else { ip_prev->next = ip->next; } free (ip->name); free ((char *)ip); } /* regfree(&rx); */ return true; } /*********************************************************************/ /* DeleteItem* function notes: * -They all take an item list and an item specification ("string" argument.) * -Some of them treat the item spec as a literal string, while others * treat it as a regular expression. * -They all delete the first item meeting their criteria, as below. * function deletes item * ------------------------------------------------------------------------ * DeleteItemStarting start is literally equal to string item spec * DeleteItemLiteral literally equal to string item spec * DeleteItemMatching fully matched by regex item spec * DeleteItemContaining containing string item spec */ /*********************************************************************/ int DeleteItemGeneral(struct Item **list,char *string,enum matchtypes type) { struct Item *ip,*last = NULL; int match = 0, matchlen = 0; regex_t rx,rxcache; regmatch_t pmatch; if (list == NULL) { return false; } switch (type) { case literalStart: matchlen = strlen(string); break; case regexComplete: case NOTregexComplete: if (CfRegcomp(&rxcache,string, REG_EXTENDED) != 0) { return false; } break; } for (ip = *list; ip != NULL; ip=ip->next) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); return false; } switch(type) { case NOTliteralStart: match = (strncmp(ip->name, string, matchlen) != 0); break; case literalStart: match = (strncmp(ip->name, string, matchlen) == 0); break; case NOTliteralComplete: match = (strcmp(ip->name, string) != 0); break; case literalComplete: match = (strcmp(ip->name, string) == 0); break; case NOTliteralSomewhere: match = (strstr(ip->name, string) == NULL); break; case literalSomewhere: match = (strstr(ip->name, string) != NULL); break; case NOTregexComplete: case regexComplete: /* To fix a bug on some implementations where rx gets emptied */ memcpy(&rx,&rxcache,sizeof(rx)); match = (regexec(&rx,ip->name,1,&pmatch,0) == 0) && (pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name)); if (type == NOTregexComplete) { match = !match; } break; } if (match) { if (type == regexComplete || type == NOTregexComplete) { regfree(&rx); } EditVerbose("Deleted item %s\n",ip->name); if (ip == *list) { free((*list)->name); if (ip->classes != NULL) { free(ip->classes); } *list = ip->next; free((char *)ip); NUMBEROFEDITS++; return true; } else { if (ip != NULL) { if (last != NULL) { last->next = ip->next; } free(ip->name); if (ip->classes != NULL) { free(ip->classes); } free((char *)ip); } NUMBEROFEDITS++; return true; } } last = ip; } return false; } /*********************************************************************/ int DeleteItemStarting(struct Item **list,char *string) /* delete 1st item starting with string */ { return DeleteItemGeneral(list,string,literalStart); } /*********************************************************************/ int DeleteItemNotStarting(struct Item **list,char *string) /* delete 1st item starting with string */ { return DeleteItemGeneral(list,string,NOTliteralStart); } /*********************************************************************/ int DeleteItemLiteral(struct Item **list,char *string) /* delete 1st item which is string */ { return DeleteItemGeneral(list,string,literalComplete); } /*********************************************************************/ int DeleteItemMatching(struct Item **list,char *string) /* delete 1st item fully matching regex */ { return DeleteItemGeneral(list,string,regexComplete); } /*********************************************************************/ int DeleteItemNotMatching(struct Item **list,char *string) /* delete 1st item fully matching regex */ { return DeleteItemGeneral(list,string,NOTregexComplete); } /*********************************************************************/ int DeleteItemContaining(struct Item **list,char *string) /* delete first item containing string */ { return DeleteItemGeneral(list,string,literalSomewhere); } /*********************************************************************/ int DeleteItemNotContaining(struct Item **list,char *string) /* delete first item containing string */ { return DeleteItemGeneral(list,string,NOTliteralSomewhere); } /*********************************************************************/ int CommentItemStarting(struct Item **list,char *string,char *comm,char *end) { struct Item *ip; char buff[CF_BUFSIZE]; for (ip = *list; ip != NULL; ip=ip->next) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); return false; } if (strncmp(ip->name,string,strlen(string)) == 0) { if (strlen(ip->name)+strlen(comm)+strlen(end)+2 > CF_BUFSIZE) { CfLog(cferror,"Bufsize overflow while commenting line - abort\n",""); return false; } if (strncmp(ip->name,comm,strlen(comm))== 0) { continue; } EditVerbose("Commenting %s%s%s\n",comm,ip->name,end); snprintf(buff,CF_BUFSIZE,"%s%s%s",comm,ip->name,end); free(ip->name); if ((ip->name = malloc(strlen(buff)+1)) == NULL) { CfLog(cferror,"malloc in CommentItemStarting\n",""); FatalError(""); } strcpy(ip->name,buff); NUMBEROFEDITS++; return true; } } return false; } /*********************************************************************/ int CommentItemContaining(struct Item **list,char *string,char *comm,char *end) { struct Item *ip; char buff[CF_BUFSIZE]; for (ip = *list; ip != NULL; ip=ip->next) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); return false; } if (strstr(ip->name,string)) { if (strlen(ip->name)+strlen(comm)+strlen(end)+2 > CF_BUFSIZE) { CfLog(cferror,"Bufsize overflow while commenting line - abort\n",""); return false; } if (strncmp(ip->name,comm,strlen(comm))== 0) { continue; } EditVerbose("Commenting %s%s%s\n",comm,ip->name,end); snprintf(buff,CF_BUFSIZE,"%s%s%s",comm,ip->name,end); free(ip->name); if ((ip->name = malloc(strlen(buff)+1)) == NULL) { CfLog(cferror,"malloc in CommentItemContaining\n",""); FatalError(""); } strcpy(ip->name,buff); NUMBEROFEDITS++; return true; } } return false; } /*********************************************************************/ int CommentItemMatching(struct Item **list,char *string,char *comm,char *end) { struct Item *ip; char buff[CF_BUFSIZE]; regex_t rx,rxcache; regmatch_t pmatch; if (CfRegcomp(&rxcache,string, REG_EXTENDED) != 0) { return false; } for (ip = *list; ip != NULL; ip=ip->next) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); regfree(&rx); return false; } memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,ip->name,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name))) { if (strlen(ip->name)+strlen(comm)+strlen(end)+2 > CF_BUFSIZE) { CfLog(cferror,"Bufsize overflow while commenting line - abort\n",""); regfree(&rx); return false; } if (strncmp(ip->name,comm,strlen(comm)) == 0) /* Already commented */ { continue; } EditVerbose("Commenting %s%s%s\n",comm,ip->name,end); snprintf(buff,CF_BUFSIZE,"%s%s%s",comm,ip->name,end); free(ip->name); if ((ip->name = malloc(strlen(buff)+1)) == NULL) { CfLog(cferror,"malloc in CommentItemContaining\n ",""); FatalError(""); } strcpy(ip->name,buff); NUMBEROFEDITS++; regfree(&rx); return true; } } } /* regfree(&rx); */ return false; } /********************************************************************/ int UnCommentItemMatching(struct Item **list,char *string,char *comm,char *end) { struct Item *ip; char *sp, *sp1, *sp2, *spc; regex_t rx,rxcache; regmatch_t pmatch; Debug("UnCommentItemMatching %s/%s\n",string,comm); if (CfRegcomp(&rxcache,string, REG_EXTENDED) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Failed to compile expression %s",string); CfLog(cferror,OUTPUT,""); return false; } for (ip = *list; ip != NULL; ip=ip->next) { if (ip->name == NULL) { continue; } memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ Debug("Compare %s/%s\n",string,ip->name); if (regexec(&rx,ip->name,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name))) { Debug("Compare %s/%s - ok FOUND\n",string,ip->name); if (strlen(ip->name)+strlen(comm)+strlen(end)+2 > CF_BUFSIZE) { CfLog(cferror,"Bufsize overflow while commenting line - abort\n",""); regfree(&rx); return false; } if (strstr(ip->name,comm) == NULL) { CURRENTLINEPTR = ip->next; continue; } EditVerbose("Uncomment line %s\n",ip->name); CURRENTLINEPTR = ip->next; if ((sp = malloc(strlen(ip->name)+2)) == NULL) { CfLog(cferror,"No Memory in UnCommentNLines\n","malloc"); regfree(&rx); return false; } spc = sp; for (sp1 = ip->name; isspace((int)*sp1); sp1++) { *spc++ = *sp1; } *spc = '\0'; sp2 = ip->name+strlen(ip->name); if ((strlen(end) != 0) && (strstr(ip->name,end) != NULL)) { for (sp2 = ip->name+strlen(ip->name); strncmp(sp2,end,strlen(end)) != 0; sp2--) { } *sp2 = '\0'; } strcat(sp,sp1+strlen(comm)); if (sp2 != ip->name+strlen(ip->name)) { strcat(sp,sp2+strlen(end)); } if (strcmp(sp,ip->name) != 0) { NUMBEROFEDITS++; } free(ip->name); ip->name = sp; regfree(&rx); return true; } } } /* regfree(&rx); */ return false; } /********************************************************************/ int UnCommentItemContaining(struct Item **list,char *string,char *comm,char *end) { struct Item *ip; char *sp, *sp1, *sp2, *spc; for (ip = *list; ip != NULL; ip=ip->next) { if (ip->name == NULL) { continue; } if (strstr(ip->name,string)) { if (strstr(ip->name,comm) == NULL) { CURRENTLINEPTR = ip->next; continue; } EditVerbose("Uncomment line %s\n",ip->name); CURRENTLINEPTR = ip->next; if ((sp = malloc(strlen(ip->name)+2)) == NULL) { CfLog(cferror,"No memory in UnCommentNLines\n","malloc"); return false; } spc = sp; for (sp1 = ip->name; isspace((int)*sp1); sp1++) { *spc++ = *sp1; } *spc = '\0'; sp2 = ip->name+strlen(ip->name); if ((strlen(end) != 0) && (strstr(ip->name,end) != NULL)) { for (sp2 = ip->name+strlen(ip->name); strncmp(sp2,end,strlen(end)) != 0; sp2--) { } *sp2 = '\0'; } strcat(sp,sp1+strlen(comm)); if (sp2 != ip->name+strlen(ip->name)) { strcat(sp,sp2+strlen(end)); } if (strcmp(sp,ip->name) != 0) { NUMBEROFEDITS++; } free(ip->name); ip->name = sp; return true; } } return false; } /********************************************************************/ int CommentToRegExp(struct Item **filestart,char *string,char *comm,char *end) /* Comment up to and including a line matching the regex */ { struct Item *ip, *ip_end = NULL; int linefound = false, done; char *sp; regex_t rx,rxcache; regmatch_t pmatch; Debug2("CommentToRegExp(list,%s %s)\n",comm,string); if (CURRENTLINEPTR == NULL) /* Shouldn't happen */ { CfLog(cferror,"File line-pointer undefined during editfile action\n",""); return true; } if (CfRegcomp(&rxcache,string, REG_EXTENDED) != 0) { return false; } for (ip = CURRENTLINEPTR; (ip != NULL); ip=ip->next) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); regfree(&rx); return false; } memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,ip->name,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name))) { linefound = true; ip_end = ip; break; } } } if (! linefound) { return false; } done = false; for (ip = CURRENTLINEPTR; ip != NULL; ip = CURRENTLINEPTR) { if (ip == ip_end) { EditVerbose("Terminating line: %s (Done)\n",ip->name); done = true; } EditVerbose("Comment line %s%s%s\n",comm,ip->name, end); NUMBEROFEDITS++; CURRENTLINEPTR = ip->next; if ((sp = malloc(strlen(ip->name)+strlen(comm)+strlen(end)+2)) == NULL) { CfLog(cferror,"No memory in CommentToRegExp\n","malloc"); regfree(&rx); return false; } strcpy (sp,comm); strcat (sp,ip->name); strcat (sp,end); free (ip->name); ip->name = sp; if (done) { break; } } /* regfree(&rx); */ return true; } /********************************************************************/ int UnCommentToRegExp(struct Item **filestart,char *string,char *comm,char *end) /* Comment up to and including a line matching the regex */ { struct Item *ip, *ip_end = NULL; int linefound = false, done; char *sp, *sp2; regex_t rx,rxcache; regmatch_t pmatch; Debug2("CommentToRegExp(list,%s %s)\n",comm,string); if (CURRENTLINEPTR == NULL) /* Shouldn't happen */ { CfLog(cferror,"File line-pointer undefined during editfile action\n",""); return true; } if (CfRegcomp(&rxcache,string, REG_EXTENDED) != 0) { return false; } for (ip = CURRENTLINEPTR; (ip != NULL); ip=ip->next) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); regfree(&rx); return false; } memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,ip->name,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(ip->name))) { linefound = true; ip_end = ip; break; } } } if (!linefound) { return false; } for (ip = CURRENTLINEPTR; ip != NULL; ip = CURRENTLINEPTR) { if (ip == ip_end) { EditVerbose("Terminating line: %s (Done)\n",ip->name); done = true; } if (strncmp(ip->name,comm,strlen(comm)) != 0) { CURRENTLINEPTR = ip->next; continue; } EditVerbose("Uncomment line %s\n",ip->name); CURRENTLINEPTR = ip->next; if ((sp = malloc(strlen(ip->name))) == NULL) { CfLog(cferror,"No Memory in UnCommentToRegexp\n","malloc"); regfree(&rx); return false; } strcpy(sp,ip->name+strlen(comm)); if ((strlen(end) != 0) && (strstr(sp,end) != NULL)) { for (sp2 = sp+strlen(sp); strncmp(sp2,end,strlen(end)) != 0; sp2--) { } *sp2 = '\0'; } if (strcmp(sp,ip->name) != 0) { NUMBEROFEDITS++; } free(ip->name); ip->name = sp; } /* regfree(&rx); */ return true; } /********************************************************************/ int DeleteSeveralLines (struct Item **filestart,char *string) /* Deletes up to N lines from current position */ { struct Item *ip, *ip_prev; int ctr, N = -99, done = false; Debug2("DeleteNLines(list,%s)\n",string); sscanf(string,"%d", &N); if (N < 1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Illegal number value in DeleteNLines: %s\n",string); CfLog(cferror,OUTPUT,""); return false; } if (CURRENTLINEPTR == NULL) /* Shouldn't happen */ { CfLog(cferror,"File line-pointer undefined during editfile action\n",""); return true; } for (ip_prev = *filestart; ip_prev && ip_prev->next != CURRENTLINEPTR; ip_prev=ip_prev->next) { } ctr = 1; for (ip = CURRENTLINEPTR; ip != NULL; ip = CURRENTLINEPTR) { if (ip->name == NULL) { continue; } if (EDABORTMODE && ItemMatchesRegEx(ip->name,VEDITABORT)) { Verbose("Aborting search, regex %s matches line\n",VEDITABORT); return false; } if (ctr == N) { EditVerbose("Terminating line: %s (Done)\n",ip->name); done = true; } EditVerbose("Delete line %s\n",ip->name); NUMBEROFEDITS++; CURRENTLINEPTR = ip->next; if (ip_prev == NULL) { *filestart = ip->next; } else { ip_prev->next = ip->next; } free (ip->name); free ((char *)ip); ctr++; if (done) { break; } } if (ctr-1 < N) { snprintf(OUTPUT,CF_BUFSIZE*2,"DeleteNLines deleted only %d lines (not %d)\n",ctr-1,N); CfLog(cfsilent,OUTPUT,""); } return true; } /********************************************************************/ struct Item *GotoLastItem (struct Item *list) { struct Item *ip; CURRENTLINENUMBER=1; CURRENTLINEPTR=list; for (ip = list; ip != NULL && ip->next != NULL; ip=ip->next) { CURRENTLINENUMBER++; } CURRENTLINEPTR = ip; return ip; } /********************************************************************/ int LineMatches (char *line,char *regexp) { regex_t rx,rxcache; regmatch_t pmatch; if (CfRegcomp(&rxcache,regexp, REG_EXTENDED) != 0) { return false; } memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,line,1,&pmatch,0) == 0) { /* Exact match of whole line */ if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(line))) { regfree(&rx); return true; } } regfree(&rx); return false; } /********************************************************************/ int GlobalReplace(struct Item **liststart,char *search,char *replace) { int i; char *sp, *start = NULL; struct Item *ip; struct Item *oldCurrentLinePtr; regex_t rx,rxcache; regmatch_t match,matchcheck; EditVerbose("Checking for global replace/%s/%s\n",search,replace); if (CfRegcomp(&rxcache,search,REG_EXTENDED) != 0) { return false; } for (ip = *liststart; ip != NULL; ip=ip->next) { if (ip->name == NULL) { continue; } memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,ip->name,1,&match,0) == 0) { start = ip->name + match.rm_so; } else { continue; } memset(VBUFF,0,CF_BUFSIZE); i = 0; for (sp = ip->name; *sp != '\0'; sp++) { if (sp != start) { VBUFF[i] = *sp; } else { sp += match.rm_eo - match.rm_so - 1; VBUFF[i] = '\0'; strcat(VBUFF,replace); i += strlen(replace)-1; memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,sp,1,&match,0) == 0) { start = sp + match.rm_so; } else { start = 0; } } i++; } Debug("Replace:\n (%s)\nwith (%s)\n",ip->name,VBUFF); if (regexec(&rx,VBUFF,1,&matchcheck,0) == 0) { if ((matchcheck.rm_so == 0) && (matchcheck.rm_eo == strlen(VBUFF))) { Verbose("Edit operation replaces [%s] with whole line [%s], so it appears convergent.\n",search,replace); } else { if (EDITGROUPLEVEL <= 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING: Non-convergent edit operation ReplaceAll [%s] With [%s]",search,replace); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"Line begins [%.40s]",ip->name); CfLog(cferror,OUTPUT,""); CfLog(cferror,"Replacement matches search string and will thus replace every time - edit was not done",""); return false; } else { /* This needs to be a smarter check - to see if the group fixes the problem or not*/ snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING: Possible non-convergent edit operation ReplaceAll [%s] With [%s]",search,replace); CfLog(cfinform,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"Line begins [%.40s]",ip->name); CfLog(cfinform,OUTPUT,""); CfLog(cfinform,"Replacement, although predicated, could match search string and might thus replace every time - edit was not done",""); } } } CURRENTLINEPTR = ip; InsertItemAfter(liststart,ip,VBUFF); oldCurrentLinePtr = CURRENTLINEPTR; /* set by Insert */ DeleteItem(liststart,ip); ip = oldCurrentLinePtr; } regfree(&rxcache); return true; } /********************************************************************/ /* part of ReplaceFirst regexp With string */ /* written by steve rader */ /********************************************************************/ int SingleReplace(liststart,search,replace) struct Item **liststart; char *search, *replace; { int i; char *sp, *start = NULL; struct Item *ip; struct Item *oldCurrentLinePtr; regex_t rx,rxcache; regmatch_t match; EditVerbose("SRDEBUG Checking for SingleReplace s/%s/%s/\n",search,replace); if (CfRegcomp(&rxcache,search,REG_EXTENDED) != 0) { EditVerbose("SRDEBUG SingleReplace ab-ended: could not compile regex! (this should not happen?)\n"); return false; } i = 0; for (ip = *liststart; ip != NULL; ip=ip->next) { i++; if (ip->name == NULL) { continue; } bcopy(&rxcache,&rx,sizeof(rx)); /* workaround for regexec()s that empty rx */ if (regexec(&rx,ip->name,1,&match,0) == 0) { start = ip->name + match.rm_so; EditVerbose("Doing SingleReplace of \"%s\" with \"%s\" on line %d\n",start,replace,i); bzero(VBUFF,CF_BUFSIZE); strcpy(VBUFF,ip->name); VBUFF[match.rm_so] = '\0'; /* ...head of string */ strcat(VBUFF,replace); /* ...replacement string */ sp = ip->name; sp += match.rm_eo; strcat(VBUFF,sp); /* ...tail of string */ Debug("SRDEBUG old line num %d is: \"%s\"\n",i,ip->name); Debug("SRDEBUG new line num %d is: \"%s\"\n",i,VBUFF); CURRENTLINEPTR = ip; InsertItemAfter(liststart,ip,VBUFF); oldCurrentLinePtr = CURRENTLINEPTR; DeleteItem(liststart,ip); ip = oldCurrentLinePtr; } } regfree(&rxcache); return true; } /********************************************************************/ int CommentSeveralLines(struct Item **filestart,char *string,char *comm,char *end) /* Comments up to N lines from current position */ { struct Item *ip; int ctr, N = -99, done = false; char *sp; Debug2("CommentNLines(list,%s)\n",string); sscanf(string,"%d", &N); if (N < 1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Illegal number value in CommentNLines: %s\n",string); CfLog(cferror,OUTPUT,""); return false; } if (CURRENTLINEPTR == NULL) /* Shouldn't happen */ { snprintf(OUTPUT,CF_BUFSIZE*2,"File line-pointer undefined during editfile action\n"); CfLog(cferror,OUTPUT,""); return true; } ctr = 1; for (ip = CURRENTLINEPTR; ip != NULL; ip = CURRENTLINEPTR) { if (ip->name == NULL) { continue; } if (ctr > N) { break; } if (ctr == N) { EditVerbose("Terminating line: %s (Done)\n",ip->name); done = true; } for (sp = ip->name; isspace((int)*sp); sp++) { } if (strncmp(sp,comm,strlen(comm)) == 0) { CURRENTLINEPTR = ip->next; ctr++; continue; } EditVerbose("Comment line %s\n",ip->name); NUMBEROFEDITS++; CURRENTLINEPTR = ip->next; if ((sp = malloc(strlen(ip->name)+strlen(comm)+strlen(end)+2)) == NULL) { CfLog(cferror,"No memory in CommentNLines\n","malloc"); return false; } strcpy (sp,comm); strcat (sp,ip->name); strcat (sp,end); free (ip->name); ip->name = sp; ctr++; if (done) { break; } } if (ctr-1 < N) { snprintf(OUTPUT,CF_BUFSIZE*2,"CommentNLines commented only %d lines (not %d)\n",ctr-1,N); CfLog(cfinform,OUTPUT,""); } return true; } /********************************************************************/ int UnCommentSeveralLines (struct Item **filestart,char *string,char *comm,char *end) /* Comments up to N lines from current position */ { struct Item *ip; int ctr, N = -99, done = false; char *sp, *sp1, *sp2, *spc; Debug2("UnCommentNLines(list,%s)\n",string); sscanf(string,"%d", &N); if (N < 1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Illegal number value in CommentNLines: %s\n",string); CfLog(cferror,OUTPUT,""); return false; } if (CURRENTLINEPTR == NULL) /* Shouldn't happen */ { snprintf(OUTPUT,CF_BUFSIZE*2,"File line-pointer undefined during editfile action\n"); CfLog(cferror,OUTPUT,""); return true; } ctr = 1; for (ip = CURRENTLINEPTR; ip != NULL; ip = CURRENTLINEPTR) { if (ip->name == NULL) { continue; } if (ctr > N) { break; } if (ctr == N) { EditVerbose("Terminating line: %s (Done)\n",ip->name); done = true; } if (strstr(ip->name,comm) == NULL) { CURRENTLINEPTR = ip->next; ctr++; continue; } EditVerbose("Uncomment line %s\n",ip->name); CURRENTLINEPTR = ip->next; if ((sp = malloc(strlen(ip->name)+2)) == NULL) { CfLog(cferror,"No memory in UnCommentNLines\n","malloc"); return false; } spc = sp; for (sp1 = ip->name; isspace((int)*sp1); sp1++) { *spc++ = *sp1; } *spc = '\0'; sp2 = ip->name+strlen(ip->name); if ((strlen(end) != 0) && (strstr(ip->name,end) != NULL)) { for (sp2 = ip->name+strlen(ip->name); strncmp(sp2,end,strlen(end)) != 0; sp2--) { } *sp2 = '\0'; } strcat(sp,sp1+strlen(comm)); if (sp2 != ip->name+strlen(ip->name)) { strcat(sp,sp2+strlen(end)); } ctr++; if (strcmp(sp,ip->name) != 0) { NUMBEROFEDITS++; } free(ip->name); ip->name = sp; if (done) { break; } } if (ctr-1 < N) { snprintf(OUTPUT,CF_BUFSIZE*2,"CommentNLines commented only %d lines (not %d)\n",ctr-1,N); CfLog(cfinform,OUTPUT,""); } return true; } /********************************************************************/ int ItemMatchesRegEx(char *item,char *regex) { regex_t rx,rxcache; regmatch_t pmatch; Debug("ItemMatchesRegEx(%s %s)\n",item,regex); if (CfRegcomp(&rxcache,regex, REG_EXTENDED) != 0) { return true; } memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,item,1,&pmatch,0) == 0) { if ((pmatch.rm_so == 0) && (pmatch.rm_eo == strlen(item))) { regfree(&rx); return true; } } regfree(&rx); return false; } /********************************************************************/ void ReplaceWithFieldMatch(struct Item **filestart,char *field,char *replace,char split,char *filename) { struct Item *ip; char match[CF_BUFSIZE], linefield[CF_BUFSIZE], *sp, *sps, *spe; int matching_field = 0, fcount, i, linenum, count = 0; Debug("ReplaceWithFieldMatch(%s,%s,%c)\n",field,replace,split); if ((replace == NULL) || (strlen(replace) == 0)) { EditVerbose("Ignoring empty line which doing ReplaceLinesMatchingField\n"); return; } matching_field = atoi(field); memset(match,0,CF_BUFSIZE); fcount = 1; sps = spe = NULL; for (sp = replace; *sp != '\0'; sp++) { if (*sp == split) { if (fcount == matching_field) { spe = sp; break; } fcount++; } if ((fcount == matching_field) && (sps == NULL)) { sps = sp; } } if (fcount < matching_field) { CfLog(cfsilent,"File formats did not completely match in ReplaceLinesMatchingField\n",""); snprintf(OUTPUT,CF_BUFSIZE*2,"while editing %s\n",filename); CfLog(cfsilent,OUTPUT,""); return; } if (spe == NULL) { spe = sp; } for (i = 0, sp = sps; sp != spe; i++, sp++) { match[i] = *sp; } Debug2("Edit: Replacing lines matching field %d == \"%s\"\n",matching_field,match); linenum = 1; for (ip = *filestart; ip != NULL; ip=ip->next, linenum++) { memset(linefield,0,CF_BUFSIZE); fcount = 1; sps = spe = NULL; if (ip->name == NULL) { continue; } for (sp = ip->name; *sp != '\0'; sp++) { if (*sp == split) { if (fcount == matching_field) { spe = sp; break; } fcount++; } if ((fcount == matching_field) && (sps == NULL)) { sps = sp; } } if (spe == NULL) { spe = sp; } if (sps == NULL) { sps = sp; } for (i = 0, sp = sps; sp != spe; i++, sp++) { linefield[i] = *sp; } if (strcmp(linefield,match) == 0) { EditVerbose("Replacing line %d (key %s)\n",linenum,match); count++; if (strcmp(replace,ip->name) == 0) { continue; } if (count > 1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Several lines in %s matched key %s\n",filename,match); CfLog(cfsilent,OUTPUT,""); } NUMBEROFEDITS++; free(ip->name); ip->name = (char *) malloc(strlen(replace)+1); strcpy(ip->name,replace); EditVerbose("Edit: With (%s)\n",replace); } } } /********************************************************************/ void AppendToLine(struct Item *current,char *text,char *filename) { char *new; int wasblank = false; if (current == NULL) { FatalError("Software error -- attempt to append to a non-existent line (shouldn't happen)"); } if (current->name != NULL) { wasblank = false; if (strstr(current->name,text)) { return; } } EditVerbose("Appending %s to line %-60s...\n",text,current->name); new = malloc(strlen(current->name)+strlen(text)+1); strcpy(new,current->name); strcat(new,text); NUMBEROFEDITS++; if (!wasblank) { free(current->name); } current->name = new; } /**************************************************************/ int CfRegcomp(regex_t *preg,const char *regex,int cflags) { int code; char buf[CF_BUFSIZE]; if (regex == NULL || *regex == '\0') { return -1; } code = regcomp(preg,regex,cflags); if (code != 0) { snprintf(buf,CF_BUFSIZE,"Regular expression error %d for %s\n", code, regex); CfLog(cferror,buf,""); regerror(code,preg,buf,CF_BUFSIZE); CfLog(cferror,buf,""); return -1; } return 0; } /* EOF */ cfengine-2.2.10/src/cfparse.y0000644000175000001440000001200410202123441012655 00000000000000%{ /* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* PARSER for cfengine */ /* */ /*******************************************************************/ #include #include "cf.defs.h" #include "cf.extern.h" extern char *yytext; %} %token LVALUE ID VAROBJ LBRACK RBRACK CONTROL GROUPS %token ARROW EQUALS EDITFILES QSTRING RVALUE BCLASS %token LBRACE RBRACE PARSECLASS LARROW OPTION FUNCTION %token ACL ADMIT DENY FILTERS STRATEGIES ACTIONTYPE ACCESSOBJ %% specification: { yyerror("Warning: invalid statement"); } | statements; statements: statement | statements statement; statement: CONTROL controllist | CONTROL | GROUPS controllist | GROUPS | ACTIONTYPE classlist | ACTIONTYPE | EDITFILES | EDITFILES objects | ACL objects | ACL | FILTERS objects | FILTERS | STRATEGIES objects | STRATEGIES | ADMIT classaccesslist | ADMIT | DENY classaccesslist | DENY; controllist: declarations | PARSECLASS declarations | PARSECLASS | controllist PARSECLASS | controllist PARSECLASS declarations; declarations: declaration | declarations declaration; classlist: entries | PARSECLASS entries | PARSECLASS | classlist PARSECLASS | classlist PARSECLASS entries; classaccesslist: accessentries | PARSECLASS accessentries | PARSECLASS | classaccesslist PARSECLASS | classaccesslist PARSECLASS accessentries; declaration: LVALUE EQUALS bracketlist; bracketlist: LBRACK rvalues RBRACK; rvalues: RVALUE | FUNCTION | rvalues FUNCTION | rvalues RVALUE; entries: entry | entries entry; accessentries: accessentry | accessentries accessentry; entry: FUNCTION | FUNCTION options | VAROBJ | VAROBJ options | VAROBJ ARROW VAROBJ options | VAROBJ ARROW VAROBJ | VAROBJ LARROW VAROBJ options | VAROBJ LARROW VAROBJ | QSTRING | QSTRING options; accessentry: ACCESSOBJ | ACCESSOBJ options; options: options OPTION | OPTION; objects: objectbrackets | PARSECLASS | PARSECLASS objectbrackets | objects PARSECLASS | objects PARSECLASS objectbrackets; objectbrackets: objectbracket | objectbrackets objectbracket; objectbracket: LBRACE VAROBJ objlist RBRACE | LBRACE ID objlist RBRACE; objlist: obj | objlist obj; obj: BCLASS QSTRING | ID QSTRING | ID | VAROBJ; %% /*****************************************************************/ void yyerror(s) char *s; { fprintf (stderr, "cf:%s:%s:%d: %s \n",VPREFIX,VCURRENTFILE,LINENUMBER,s); ERRORCOUNT++; if (ERRORCOUNT > 10) { FatalError("Too many errors"); } } /*****************************************************************/ /* EOF */ cfengine-2.2.10/src/wildcard.c0000644000175000001440000002123511004100144012777 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /*************************************************************************/ /* WILDCARD TOOLKIT : Level 0 */ /*************************************************************************/ #define nomatch 0 #define match 1 #define maxlen 20 #define startofstrings 10 #define middleofstrings 11 #define endofstrings 12 #define Wild(c) ((c == '*' || c == '?') ? true : false) #include /*************************************************************************/ int IsWildCard (char *str) { return (strchr(str,'?') || strchr(str,'*')); } /*************************************************************************/ int WildMatch (char *wildptr,char *cmpptr) { char buffer[CF_BUFSIZE]; int i, status = startofstrings; char lastwild = '\0'; Debug("WildMatch(%s,%s)\n",wildptr,cmpptr); if (strstr(wildptr,"*") == NULL && strstr(wildptr,"?") == NULL) { return (! strcmp(wildptr,cmpptr)); } while (true) { while (*wildptr == '?') /* 1 */ { wildptr++; cmpptr++; if ((*cmpptr == '\0') && (*wildptr != '\0')) /* 2 */ { return(nomatch); } lastwild = '?'; status = middleofstrings; } if (*wildptr == '\0' && *cmpptr == '\0') /* 3 */ { return(match); } else if (*wildptr == '\0') /* 4 */ { return(nomatch); } if (*wildptr == '*') /* 5 */ { while (*wildptr == '*') /* 6 */ { wildptr++; } if (*wildptr == '\0') /* 7 */ { if (*cmpptr == '\0') /* 8 */ { return(nomatch); } else { return(match); } } cmpptr++; /* 9 */ status = middleofstrings; lastwild = '*'; } for (i = 0; !(Wild(*wildptr) || *wildptr == '\0'); i++) /* 10 */ { buffer[i] = *wildptr++; if (*wildptr == '\0') /* 11 */ { status = endofstrings; } } buffer[i] = '\0'; if ((cmpptr = AfterSubString(cmpptr,buffer,status,lastwild)) == NULL) { return(nomatch); /* 12 */ } status = middleofstrings; } } /******************************************************************/ /* Wildcard Toolkit : Level 1 */ /******************************************************************/ char *AfterSubString(char *big,char *small,int status,char lastwild) /* If the last wildcard was a ? then this just tries to */ /* match the substrings from the present position, otherwise */ /* looks for next occurrance of small within big and returns */ /* a pointer to the next character in big after small or */ /* NULL if there is no string found to match */ /* If end of strings is signalled, make sure that the string */ /* is tied to the end of big. This makes sure that there is */ /* correct alignment with end of string marker. */ { char *bigptr; if (strlen(small) > strlen(big)) /* 13 */ { return(NULL); } if (lastwild == '?') /* 14 */ { if (strncmp(big,small,strlen(small)) == 0) { return(big+strlen(small)); } else { return(NULL); } } if (status == endofstrings) /* 15 */ { big = big + strlen(big) - strlen(small); } for (bigptr = big; *bigptr != '\0'; ++bigptr) /* 16 */ { if (strncmp(bigptr,small,strlen(small)) == 0) { return(bigptr+strlen(small)); } if (status == startofstrings) /* 17 */ { return(NULL); } } return(NULL); /* 18 */ } /****************************************************************** Comments : 1. ? Matches a single character. Skip over with pointers. 2. Check that the compare string hasn't run out too soon. 3. If the wild-match is complete return MATCH! 4. other wise check that the wild card string hasn't run out too soon. 5. * Matches any string. 6. Skip over any *'s in the wildcard string and leave pointer on the first character after. 7. If the last character in the wildstring is *, match any remaining characters... 8. ...except no string at all. e.g. xyz* doesn't match xyz 9. Advancing this pointer by one, prevents * from matching the null string even when the pointers haven't reached the end of the string (so that the match is not complete). This works because it screws up the pattern match in the routine `AfterSubString()' by removing the first character from a string which might otherwise match. e.g. it stops *.c from matching .c because the strings which get passed to AfterSubString are `.c' (from *.c) and `c' (from .c). 10.Isolate the next string sandwhiched between wild-cards or string delimiters. Copy to buffer. 11.Make a note if we hit the end of wildstring in the process. i.e. is this the end of the strings we're matching? 12.The call to this routine checks whether a match is allowed between the isolated string and the comparison string. If a match is allowed it updates the pointers so that they point to the next characters after the match. Otherwise it returns NULL. AfterSubString() 13. You can't find a string larger than big inside big! (This could occur because of points 15. and 9.) 14. If the last wildcard was just to match a single character then the string match must be anchored to the current pointer locations. 15. If this is the end of the strings to be matched, then make sure the match also correctly identifies which pattern matches the END of the string. e.g. to avoid confusion over *.abc in .abc.abc.abc 16. If the last wildcard was a * or none, then use a forward floating comparision which can skip over anyjunk characters looking for the next occurrance of the string. 17. If this is the first two characters in the string and there is no match, give up. This anchors the floating match to the start to avoid a*b matching xaxb by skipping over the first x! 18. If there is no match yet, there's no chance! Test Data ---------- Wild String Valid Match No Match ------------ ----------- ---------- abcd abcd *mmm* abcmmmabc abcmmm mmm *j jjjj jjjjx *.c a.c .c .c.c *y ayyyyyyy ya y ?a aa aaa ba ab ???a aaaa ab xyza xyzaa ??? xyz ab abcd * anything *.* anything.anything a* abc a bad ?mmm? ammmb abcmmmd mmm a*b axyzb xyz abbb axab *******************************************************************/ /* EOF */ cfengine-2.2.10/src/methods.c0000644000175000001440000014304211167066575012707 00000000000000/* Copyright (C) 1995-2000 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: methods.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*******************************************************************/ void CheckForMethod() { struct Item *ip; int i = 0; if (strcmp(METHODNAME,"cf-nomethod") == 0) { return; } if (! MINUSF) { FatalError("Input files claim to be a module but this is a parent process\n"); } Verbose("\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n+\n"); Verbose("+ This is a private method: %s\n",METHODNAME); if (METHODARGS == NULL) { FatalError("This module was declared a method but no MethodParameters declaration was given"); } else { Verbose("+\n+ Method argument prototype = ("); i = 1; for (ip = METHODARGS; ip != NULL; ip=ip->next) { i++; } METHODARGV = (char **) malloc(sizeof(char *) * i); i = 0; for (ip = METHODARGS; ip != NULL; ip=ip->next) { /* Fill this temporarily with the formal parameters */ METHODARGV[i++] = ip->name; Verbose("%s ",ip->name); } METHODARGC = i; Verbose(")\n+\n"); } Verbose("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n"); Verbose("Looking for a data package for this method (%s)\n",METHODMD5); if (!ChildLoadMethodPackage(METHODNAME,METHODMD5)) { snprintf(OUTPUT,CF_BUFSIZE,"No valid incoming request to execute method (%s)\n",METHODNAME); CfLog(cfinform,OUTPUT,""); exit(0); } Debug("Method package looks ok -- proceeding\n"); } /*******************************************************************/ void CheckMethodReply() { if (ScopeIsMethod()) { if (strlen(METHODREPLYTO) > 0) { Banner("Method reply message"); DispatchMethodReply(); } } } /*****************************************************************************/ void DispatchNewMethod(struct Method *ptr) { struct Item *ip; char label[CF_BUFSIZE]; char serverip[CF_SMALLBUF],clientip[CF_SMALLBUF]; serverip[0] = clientip[0] = '\0'; for (ip = ptr->servers; ip != NULL; ip=ip->next) { if (strcmp(ip->name,"none") == 0) { Verbose("Method with no server is a no-op\n"); continue; } if ((strcmp(ip->name,"localhost") == 0) || (strcmp(ip->name,"::1") == 0) || (strcmp(ip->name,"127.0.0.1") == 0)) { Verbose("\nDispatch method localhost:%s to %s/rpc_in\n",ptr->name,VLOCKDIR); ptr->invitation = 'y'; snprintf(label,CF_BUFSIZE-1,"%s/rpc_in/localhost+localhost+%s+%s",VLOCKDIR,ptr->name,ChecksumPrint('m',ptr->digest)); EncapsulateMethod(ptr,label); } else { strncpy(serverip,Hostname2IPString(ip->name),63); if (strlen(ptr->forcereplyto) > 0) { strncpy(clientip,ptr->forcereplyto,63); } else { strncpy(clientip,Hostname2IPString(VFQNAME),63); } if (strcmp(clientip,serverip) == 0) { Debug("Invitation to accept remote method on this host %s\n",ip->name); Debug("(Note that this is not a method to be executed as server localhost)\n"); continue; } Verbose("Posting to server (%s) from our calling id %s\n",serverip,VFQNAME); snprintf(label,CF_BUFSIZE-1,"%s/rpc_out/%s+%s+%s+%s",VLOCKDIR,clientip,serverip,ptr->name,ChecksumPrint('m',ptr->digest)); EncapsulateMethod(ptr,label); Debug("\nDispatched method %s to %s/rpc_out\n",label,VLOCKDIR); } } } /*****************************************************************************/ struct Item *GetPendingMethods(int state) { char filename[CF_MAXVARSIZE],path[CF_BUFSIZE],name[CF_BUFSIZE]; char client[CF_BUFSIZE],server[CF_BUFSIZE],extra[CF_BUFSIZE],digeststring[CF_BUFSIZE]; DIR *dirh; struct dirent *dirp; struct Method *mp; struct Item *list = NULL, *ip; struct stat statbuf; int belongs_here, correct_server,I_am_server; Debug("GetPendingMethods(%d) in (%s/rpc_in)\n",state,VLOCKDIR); Debug("Processing applications...\n"); snprintf(filename,CF_MAXVARSIZE-1,"%s/rpc_in",VLOCKDIR); if ((dirh = opendir(filename)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",filename); CfLog(cfverbose,OUTPUT,"opendir"); return NULL; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,filename,NULL)) { continue; } snprintf(path,CF_BUFSIZE-1,"%s/%s",filename,dirp->d_name); if (stat(path,&statbuf) == -1) { continue; } if (statbuf.st_mtime < CFSTARTTIME - (VEXPIREAFTER * 60)) { Verbose("Purging expired incoming method %s (expireafter=%d)\n",path,VEXPIREAFTER); unlink(path); continue; } SplitMethodName(dirp->d_name,client,server,name,digeststring,extra); if (strlen(name) == 0) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to extract method name from package (%s)",dirp->d_name); CfLog(cfinform,OUTPUT,""); continue; } belongs_here = false; for (ip = IPADDRESSES; ip != NULL; ip = ip->next) { if (strcmp(server,ip->name) == 0 || strcmp(client,ip->name) == 0) { belongs_here = true; } } if (strcmp(server,"localhost") == 0) { belongs_here = true; } if (!belongs_here) { Debug("Purging stray community file that does not belong here: %s\n",dirp->d_name); unlink(path); continue; } if (strlen(extra) != 0) { if (state == CF_METHODREPLY) { Debug("Found an attachment (%s) in reply to %s\n",extra,name); } else { Debug("Found an attachment (%s) to incoming method %s\n",extra,name); } continue; } if ((state == CF_METHODREPLY) && (strstr(name,":Reply") == 0)) { Debug("Ignoring bundle (%s->%s) from waiting function call\n",dirp->d_name,name); continue; } if ((state == CF_METHODEXEC) && (strstr(name,":Reply"))) { Debug("Ignoring bundle (%s) from waiting reply\n",name); continue; } if (state == CF_METHODEXEC) { Debug("Looking at method (%s) from (%s) intended for exec on (%s) with arghash %s\n",name,client,server,digeststring); } else { Debug("Looking for reply to (%s) from (%s) to (%s) with arghash %s\n",name,client,server,digeststring); } ip = SplitStringAsItemList(name,':'); I_am_server = (IsItemIn(IPADDRESSES,server) || strstr(server,"localhost")); if (mp = IsDefinedMethod(ip->name,digeststring)) { correct_server = (IsItemIn(mp->servers,"localhost")|| IsItemIn(mp->servers,IPString2Hostname(server)) || IsItemIn(mp->servers,IPString2UQHostname(server)) || IsItemIn(mp->servers,server)); switch(state) { case CF_METHODREPLY: /* if receiving reply then we are the client */ if (correct_server && IsDefinedClass(mp->classes)) { Verbose("Found an approval to issue reply from a locally executed method (%s) to client %s from server %s\n",name,client,server); } else { Debug("No local recipient for this reply (%s) if (%s)\n",dirp->d_name,mp->classes); DeleteItemList(ip); unlink(path); continue; } break; case CF_METHODEXEC: /* if we are the server, the registered server (mp->server) should match the arrived request (server) AND it should match our identity */ if (correct_server && I_am_server && IsDefinedClass(mp->classes)) { Verbose("Found a local approval to execute this method (%s) on behalf of sender %s if (%s)\n",name,IPString2Hostname(client),mp->classes); } else { Debug("No local approval for executing received request (%s) if (%s)\n",dirp->d_name,mp->classes); DeleteItemList(ip); continue; } } AppendItem(&list,dirp->d_name,""); mp->bundle = strdup(dirp->d_name); DeleteItemList(ip); } else { Debug("No such method pending (%s) in this context for host %s=%s=%s in\n",dirp->d_name,server,IPString2Hostname(server),VIPADDRESS); DeleteItemList(ip); } } closedir(dirh); if (list == NULL) { return NULL; } return list; } /*****************************************************************************/ void EvaluatePendingMethod(char *methodname) /* Actually execute any method that is our responsibilty */ { struct Method *ptr; char line[CF_BUFSIZE]; char options[CF_BUFSIZE]; char client[CF_BUFSIZE],server[CF_BUFSIZE],name[CF_BUFSIZE],digeststring[CF_BUFSIZE],extra[CF_BUFSIZE]; char *sp; char execstr[CF_BUFSIZE]; int print; FILE *pp; SplitMethodName(methodname,client,server,name,digeststring,extra); /* Could check client for access granted? */ if (strcmp(server,"localhost") == 0 || strcmp(IPString2Hostname(server),VFQNAME) == 0) { Debug("EvaluatePendingMethod(%s)\n",name); } else { Debug("Nothing to do for %s\n",methodname); return; } options[0] = '\0'; if (INFORM) { strcat(options,"-I "); } if (IGNORELOCK) { strcat(options,"-K "); } if (VERBOSE) { strcat(options,"-v "); } if (DEBUG || D2) { strcat(options,"-d2 "); } ptr = IsDefinedMethod(name,digeststring); strcat(options,"-Z "); strcat(options,digeststring); strcat(options," "); snprintf(execstr,CF_BUFSIZE-1,"%s/bin/cfagent -f %s %s",CFWORKDIR,GetMethodFilename(ptr),options); Verbose("Trying %s\n",execstr); if (IsExcluded(ptr->classes)) { Verbose("(Excluded on classes (%s))\n",ptr->classes); return; } ResetOutputRoute(ptr->log,ptr->inform); if (!GetLock(ASUniqueName("method-exec"),CanonifyName(methodname),ptr->ifelapsed,ptr->expireafter,VUQNAME,CFSTARTTIME)) { return; } snprintf(OUTPUT,CF_BUFSIZE*2,"Executing method %s...(uid=%d,gid=%d)\n",execstr,ptr->uid,ptr->gid); CfLog(cfverbose,OUTPUT,""); if (DONTDO) { printf("%s: execute method %s\n",VPREFIX,ptr->name); } else { switch (ptr->useshell) { case 'y': pp = cfpopen_shsetuid(execstr,"r",ptr->uid,ptr->gid,ptr->chdir,ptr->chroot); break; default: pp = cfpopensetuid(execstr,"r",ptr->uid,ptr->gid,ptr->chdir,ptr->chroot); break; } if (pp == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open pipe to command %s\n",execstr); CfLog(cferror,OUTPUT,"popen"); ResetOutputRoute('d','d'); ReleaseCurrentLock(); return; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); break; } ReadLine(line,CF_BUFSIZE,pp); if (strstr(line,"cfengine-die")) { break; } if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); break; } print = false; for (sp = line; *sp != '\0'; sp++) { if (! isspace((int)*sp)) { print = true; break; } } if (print) { printf("%s:%s: %s\n",VPREFIX,ptr->name,line); } } cfpclose(pp); } snprintf(OUTPUT,CF_BUFSIZE*2,"Finished local method %s processing\n",execstr); CfLog(cfverbose,OUTPUT,""); ResetOutputRoute('d','d'); ReleaseCurrentLock(); return; } /*****************************************************************************/ /* Level 2 */ /*****************************************************************************/ int ParentLoadReplyPackage(char *methodname) { char client[CF_MAXVARSIZE],server[CF_BUFSIZE],name[CF_BUFSIZE],buf[CF_BUFSIZE]; char line[CF_BUFSIZE],type[CF_SMALLBUF],arg[CF_BUFSIZE], **methodargv = NULL; char basepackage[CF_BUFSIZE],digeststring[CF_BUFSIZE],extra[CF_MAXVARSIZE]; char *sp; struct Item *ip; struct Method *mp; int isreply = false, argnum = 0, i, methodargc = 0; FILE *fp,*fin; Debug("\nParentLoadReplyPackage(%s)\n\nLook for method replies in %s/rpc_in\n",methodname,VLOCKDIR); SplitMethodName(methodname,client,server,name,digeststring,extra); for (sp = name; *sp != '\0'; sp++) { if (*sp == ':') /* Strip off :Reply */ { *sp = '\0'; break; } } if ((mp = IsDefinedMethod(name,digeststring)) == NULL) { return false; } i = 1; for (ip = mp->return_vars; ip != NULL; ip=ip->next) { i++; } methodargv = (char **) malloc(i*sizeof(char *)); i = 0; for (ip = mp->return_vars; ip != NULL; ip=ip->next) { /* Fill this temporarily with the formal parameters */ methodargv[i++] = ip->name; } methodargc = i; snprintf(basepackage,CF_BUFSIZE-1,"%s/rpc_in/%s",VLOCKDIR,methodname); argnum = CountAttachments(basepackage); if (argnum != methodargc) { Verbose("Number of return arguments (%d) does not match template (%d)\n",argnum,methodargc); Verbose("Discarding method %s\n",name); free((char *)methodargv); return false; } snprintf(buf,CF_BUFSIZE,"rpc_in_%s_%s_%s",name,server,digeststring); Debug("Checking the neuronic deadtime to see if we just did a version of this: class %s\n",buf); if (IsDefinedClass(CanonifyName(buf))) { free((char *)methodargv); return false; } else { Verbose("No further replies can be accepted yet (tot %d mins)\n",mp->ifelapsed); AddPersistentClass(CanonifyName(buf),mp->ifelapsed,cfpreserve); } argnum = 0; Verbose("Opening bundle %s\n",methodname); if ((fp = fopen(basepackage,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open a parameter bundle (%s) for method %s for parent reply",basepackage,name); CfLog(cfinform,OUTPUT,"fopen"); free((char *)methodargv); return false; } while (!feof(fp)) { memset(line,0,CF_BUFSIZE); fgets(line,CF_BUFSIZE,fp); type[0] = '\0'; arg[0] = '\0'; sscanf(line,"%63s %s",type,arg); Debug("\nReading line: %s",line); switch (ConvertMethodProto(type)) { case cfmeth_name: Debug("Handling name %s=%s\n",arg,name); if (strncmp(arg,name,strlen(name)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Method name %s did not match package name %s",name,arg); CfLog(cfinform,OUTPUT,""); fclose(fp); free((char *)methodargv); return false; } break; case cfmeth_isreply: Debug("Method identifies itself as a reply\n"); isreply = true; break; case cfmeth_sendclass: Debug("Method is sending us as classlist: %s\n",arg); if (IsItemIn(mp->return_classes,arg)) { char classname[CF_MAXVARSIZE]; if (ListLen(mp->servers) > 1) { struct Item *ip; int i = 1; for (ip = mp->servers; ip != NULL; ip=ip->next) { if ((strcmp(ip->name,IPString2Hostname(server)) == 0) || (strcmp(ip->name,IPString2UQHostname(server)) == 0) || (strcmp(ip->name,server) == 0) ) { snprintf(classname,CF_MAXVARSIZE-1,"%s_%d",name,i); Verbose("Setting method class %s\n",classname); AddPrefixedMultipleClasses(classname,arg); break; } i++; } } else { snprintf(classname,CF_MAXVARSIZE-1,"%s",name); Verbose("Setting method classes %s\n",classname); AddPrefixedMultipleClasses(classname,arg); } } else { Verbose("Method returned a class (%s) that was not in the return_classes access list\n",arg); } break; case cfmeth_attacharg: Debug("Method has attached an argument\n",arg); if (methodargv[argnum][0] == '/') { int val; struct stat statbuf; FILE *fin,*fout; Debug("Method's reply is supposed to be a file %s\n",methodargv[argnum]); if (stat (arg,&statbuf) == -1) { Verbose("Unable to stat file %s\n",arg); return false; } val = statbuf.st_size; Debug("Install file in %s at %s\n",arg,methodargv[argnum]); if ((fin = fopen(arg,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"could not open argument bundle %s\n",arg); CfLog(cferror,OUTPUT,"fopen"); free((char *)methodargv); return false; } if ((fout = fopen(methodargv[argnum],"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not write to local parameter file %s\n",methodargv[argnum]); CfLog(cferror,OUTPUT,"fopen"); free((char *)methodargv); fclose(fin); return false; } if (val > CF_BUFSIZE) { int count = 0; while(!feof(fin)) { fputc(fgetc(fin),fout); count++; if (count == val) { break; } Debug("Wrote #\n"); } } else { memset(buf,0,CF_BUFSIZE); fread(buf,val,1,fin); fwrite(buf,val,1,fout); Debug("Wrote #\n"); } fclose(fin); fclose(fout); } else { char argbuf[CF_BUFSIZE],newname[CF_MAXVARSIZE]; memset(argbuf,0,CF_BUFSIZE); Debug("Method reply is meant to be a variable\n"); Debug("Read arg from file %s in parent load\n",arg); if ((fin = fopen(arg,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Missing module argument package (%s)\n",arg); FatalError(OUTPUT); } fread(argbuf,CF_BUFSIZE-1,1,fin); Debug("ARG read as: %40.40s\n",argbuf); fclose(fin); if (IsItemIn(mp->return_vars,methodargv[argnum])) { Debug("ARG passes the return ACL: %s\n",methodargv[argnum]); if (ListLen(mp->servers) > 1) { struct Item *ip; int i = 1; Debug("Multi-server reply from [%s]\n",server); for (ip = mp->servers; ip != NULL; ip=ip->next) { if ((strcmp(ip->name,IPString2Hostname(server)) == 0) || (strcmp(ip->name,IPString2UQHostname(server)) == 0) || (strcmp(ip->name,server) == 0) ) { snprintf(newname,CF_MAXVARSIZE-1,"%s_%d.%s",name,i,methodargv[argnum]); Verbose("Setting variable %s to %s\n",newname,argbuf); AddMacroValue(CONTEXTID,newname,argbuf); break; } i++; } } else { Debug("Single server reply\n"); snprintf(newname,CF_MAXVARSIZE-1,"%s.%s",name,methodargv[argnum]); Verbose("Setting variable %s to %s\n",newname,argbuf); AddMacroValue(CONTEXTID,newname,argbuf); } } else { Verbose("Method returned a variable (%s) that was not in the return_vars access list\n",argbuf); } } Debug("Unlink %s\n",arg); unlink(arg); argnum++; break; case cfmeth_time: break; default: Debug("Protocol error (%s) in package received for method %s\n",type,basepackage); break; } } fclose(fp); free((char *)methodargv); unlink(basepackage); /* Now remove the invitation */ if (!isreply) { Verbose("Reply package was not marked as a reply\n"); ReleaseCurrentLock(); return false; } return true; } /*****************************************************************************/ int ChildLoadMethodPackage(char *name,char *digeststring) { char line[CF_BUFSIZE],type[CF_SMALLBUF],arg[CF_BUFSIZE]; char basepackage[CF_BUFSIZE],cffilename[CF_BUFSIZE],buf[CF_BUFSIZE],ebuff[CF_EXPANDSIZE]; char clientip[CF_BUFSIZE],ipaddress[CF_BUFSIZE]; struct stat statbuf; FILE *fp,*fin,*fout; int argnum = 0; Verbose("Child is looking for its bundle: %s\n",name); METHODFILENAME[0] = '\0'; if (!CheckForMethodPackage(name)) { Verbose("Could not find anything looking like a current invitation\n"); return false; } if (strcmp(METHODREPLYTO,"localhost") != 0) { strncpy(clientip,Hostname2IPString(METHODREPLYTO),63); strncpy(ipaddress,Hostname2IPString(METHODFOR),63); } else { strncpy(clientip,"localhost",63); strncpy(ipaddress,"localhost",63); } snprintf(basepackage,CF_BUFSIZE-1,"%s/rpc_in/%s+%s+%s+%s",VLOCKDIR,clientip,ipaddress,METHODNAME,METHODMD5); argnum = CountAttachments(basepackage); if (argnum != METHODARGC) { Verbose("Number of return arguments (%d) does not match template (%d)\n",argnum,METHODARGC); Verbose("Discarding method %s\n",name); return false; } argnum = 0; if ((fp = fopen(basepackage,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open a parameter bundle (%s) for method %s for child loading",basepackage,name); CfLog(cfinform,OUTPUT,"fopen"); return false; } while (!feof(fp)) { memset(line,0,CF_BUFSIZE); fgets(line,CF_BUFSIZE,fp); type[0] = '\0'; arg[0] = '\0'; sscanf(line,"%63s %s",type,arg); switch (ConvertMethodProto(type)) { case cfmeth_name: if (strcmp(arg,name) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Method name %s did not match package name %s",name,arg); CfLog(cfinform,OUTPUT,""); fclose(fp); return false; } break; case cfmeth_file: if (GetMacroValue(CONTEXTID,"moduledirectory")) { ExpandVarstring("$(moduledirectory)",ebuff,NULL); } else { snprintf(ebuff,CF_BUFSIZE,"%s/modules",VLOCKDIR); } snprintf(cffilename,CF_BUFSIZE-1,"%s/%s",ebuff,arg); if (lstat(cffilename,&statbuf) != -1) { if (S_ISLNK(statbuf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE,"SECURITY ALERT. Method (%s) executable is a symbolic link",name); CfLog(cferror,OUTPUT,""); fclose(fp); continue; } } if (stat(cffilename,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Method name %s did not find executable name %s",name,cffilename); CfLog(cfinform,OUTPUT,"stat"); fclose(fp); continue; } strncpy(METHODFILENAME,cffilename,CF_MAXVARSIZE); break; case cfmeth_replyto: Debug("Found reply to host: %s\n",arg); strncpy(METHODREPLYTO,arg,CF_MAXVARSIZE-1); break; case cfmeth_sendclass: Verbose("Defining transmitted class: %s\n",arg); if (!IsHardClass(arg)) { AddMultipleClasses(arg); } else { snprintf(OUTPUT,CF_BUFSIZE,"Cannot redefine a hard class in a method (%s)",arg); CfLog(cfinform,OUTPUT,""); } break; case cfmeth_attacharg: Debug("Handling expected local argument (%s)\n",METHODARGV[argnum]); if (METHODARGV[argnum][0] == '/') { int val; struct stat statbuf; if (stat (arg,&statbuf) == -1) { Verbose("Unable to stat file %s\n",arg); return false; } val = statbuf.st_size; Debug("Install file in %s at %s\n",arg,METHODARGV[argnum]); if ((fin = fopen(arg,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"could not open argument bundle %s\n",arg); CfLog(cferror,OUTPUT,"fopen"); return false; } if ((fout = fopen(METHODARGV[argnum],"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not write to local parameter file %s\n",METHODARGV[argnum]); CfLog(cferror,OUTPUT,"fopen"); fclose(fin); return false; } if (val > CF_BUFSIZE) { int count = 0; while(!feof(fin)) { fputc(fgetc(fin),fout); count++; if (count == val) { break; } Debug("Wrote #\n"); } } else { memset(buf,0,CF_BUFSIZE); fread(buf,val,1,fin); fwrite(buf,val,1,fout); Debug("Wrote #\n"); } fclose(fin); fclose(fout); } else { char argbuf[CF_BUFSIZE]; memset(argbuf,0,CF_BUFSIZE); Debug("Read arg from file %s\n",arg); if ((fin = fopen(arg,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Missing module argument package (%s)\n",arg); FatalError(OUTPUT); } fread(argbuf,CF_BUFSIZE-1,1,fin); fclose(fin); if (strcmp(METHODARGV[argnum],"void") != 0) { Verbose("Setting transmitted variable %s = ( %s )\n",METHODARGV[argnum],argbuf); AddMacroValue(CONTEXTID,METHODARGV[argnum],argbuf); } else { Verbose("Method had no arguments (void)\n"); } } Debug("Removing arg %s\n",arg); unlink(arg); argnum++; break; default: break; } } fclose(fp); if (strlen(METHODFILENAME) == 0) { snprintf(OUTPUT,CF_BUFSIZE,"Method (%s) package had no filename to execute",name); CfLog(cfinform,OUTPUT,""); return false; } if (strlen(METHODREPLYTO) == 0) { snprintf(OUTPUT,CF_BUFSIZE,"Method (%s) package had no replyto address",name); CfLog(cfinform,OUTPUT,""); return false; } Debug("Done loading %s\n",basepackage); unlink(basepackage); /* Now remove the invitation */ return true; } /*****************************************************************************/ void DispatchMethodReply() { char label[CF_BUFSIZE]; char ipaddress[CF_SMALLBUF],clientip[CF_SMALLBUF]; Verbose("DispatchMethodReply()\n\n"); if (strcmp(METHODREPLYTO,"localhost") == 0 || strcmp(METHODREPLYTO,"::1") == 0 || strcmp(METHODREPLYTO,"127.0.0.1") == 0) { snprintf(label,CF_BUFSIZE-1,"%s/rpc_in/localhost+localhost+%s:Reply+%s",VLOCKDIR,METHODNAME,METHODMD5); EncapsulateReply(label); } else { strncpy(clientip,Hostname2IPString(METHODREPLYTO),63); strncpy(ipaddress,Hostname2IPString(VFQNAME),63); Verbose("\nDispatch method %s:%s to %s/rpc_out\n",METHODREPLYTO,METHODNAME,VLOCKDIR); snprintf(label,CF_BUFSIZE-1,"%s/rpc_out/%s+%s+%s:Reply+%s",VLOCKDIR,clientip,ipaddress,METHODNAME,METHODMD5); EncapsulateReply(label); } } /*****************************************************************************/ char *GetMethodFilename(struct Method *ptr) { char line[CF_BUFSIZE],type[CF_SMALLBUF],arg[CF_BUFSIZE]; char basepackage[CF_BUFSIZE],cffilename[CF_BUFSIZE],ebuff[CF_EXPANDSIZE]; static char returnfile[CF_BUFSIZE]; FILE *fp; struct stat statbuf; int numargs = 0, argnum = 0; numargs = ListLen(ptr->send_args); snprintf(basepackage,CF_BUFSIZE-1,"%s/rpc_in/%s",VLOCKDIR,ptr->bundle); if ((fp = fopen(basepackage,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open a parameter bundle (%s) for method %s to get filenames",ptr->bundle,ptr->name); CfLog(cfinform,OUTPUT,"fopen"); return returnfile; } argnum = 0; while (!feof(fp)) { memset(line,0,CF_BUFSIZE); fgets(line,CF_BUFSIZE,fp); type[0] = '\0'; arg[0] = '\0'; sscanf(line,"%63s %s",type,arg); switch (ConvertMethodProto(type)) { case cfmeth_name: if (strcmp(arg,ptr->name) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Method name %s did not match package name %s",ptr->name,arg); CfLog(cfinform,OUTPUT,""); fclose(fp); return returnfile; } break; case cfmeth_file: memset(ebuff,0,CF_BUFSIZE); if (GetMacroValue(CONTEXTID,"moduledirectory")) { ExpandVarstring("$(moduledirectory)",ebuff,NULL); } else { snprintf(ebuff,CF_BUFSIZE,"%s/modules",VLOCKDIR); } snprintf(cffilename,CF_BUFSIZE-1,"%s/%s",ebuff,arg); if (lstat(cffilename,&statbuf) != -1) { if (S_ISLNK(statbuf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE,"SECURITY ALERT. Method (%s) source is a symbolic link",ptr->name); CfLog(cferror,OUTPUT,""); fclose(fp); return returnfile; } } if (stat(cffilename,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Method name %s did not find package name %s",ptr->name,cffilename); CfLog(cfinform,OUTPUT,"stat"); fclose(fp); return returnfile; } strncpy(returnfile,cffilename,CF_MAXVARSIZE); break; case cfmeth_attacharg: argnum++; break; default: break; } } fclose(fp); if (numargs != argnum) { Verbose("Method (%s) arguments did not agree with the agreed template in the config file (%d/%d)\n",ptr->name,argnum,numargs); return returnfile; } return returnfile; } /******************************************************************************/ /* Level 3 */ /******************************************************************************/ enum methproto ConvertMethodProto(char *name) { int i; for (i = 0; VMETHODPROTO[i] != NULL; i++) { if (strcmp(name,VMETHODPROTO[i]) == 0) { break; } } return (enum methproto) i; } /*****************************************************************************/ int CheckForMethodPackage(char *methodname) { DIR *dirh; struct Method *mp = NULL; struct dirent *dirp; struct Item *methodID = NULL; char dirname[CF_MAXVARSIZE],path[CF_BUFSIZE]; char name[CF_BUFSIZE],client[CF_BUFSIZE],server[CF_BUFSIZE],digeststring[CF_BUFSIZE],extra[256]; struct stat statbuf; int gotmethod = false; snprintf(dirname,CF_MAXVARSIZE-1,"%s/rpc_in",VLOCKDIR); if ((dirh = opendir(dirname)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",dirname); CfLog(cfverbose,OUTPUT,"opendir"); return false; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,dirname,NULL)) { continue; } snprintf(path,CF_BUFSIZE-1,"%s/%s",dirname,dirp->d_name); if (stat(path,&statbuf) == -1) { continue; } Debug("Examining child's incoming (%s)\n",dirp->d_name); SplitMethodName(dirp->d_name,client,server,name,digeststring,extra); Debug("This request came from %s - our reply should be sent there!\n",client); strcpy(METHODREPLYTO,client); Debug("This request referred to us as %s - a plausible identity\n",client); strcpy(METHODFOR,server); if (strcmp(methodname,name) == 0) { gotmethod = true; break; } if (mp = IsDefinedMethod(name,digeststring)) { if (statbuf.st_mtime < (CFSTARTTIME - (mp->expireafter * 60))) { Debug("Purging expired method %s\n",path); unlink(path); continue; } } else { if (statbuf.st_mtime < (CFSTARTTIME - 2*3600)) /* Default 2 hr expiry */ { Debug("Purging expired method %s\n",path); unlink(path); continue; } } DeleteItemList(methodID); } closedir(dirh); if (gotmethod) { return true; } else { return false; } } /*****************************************************************************/ struct Method *IsDefinedMethod(char *name,char *digeststring) { struct Method *mp; for (mp = VMETHODS; mp != NULL; mp=mp->next) { Debug("Check for potentially defined method (%s=%s)(%s)\n",name,mp->name,digeststring); if (strncmp(mp->name,name,strlen(mp->name)) == 0) { Debug(" Comparing digests: %s=%s\n",digeststring,ChecksumPrint('m',mp->digest)); if (strcmp(digeststring,ChecksumPrint('m',mp->digest)) == 0) { Verbose("Method %s is defined\n",name); return mp; } else { Debug("Method %s instance found, but arguments did not match\n",name); } } } Debug("Method %s not defined\n",name); return NULL; } /*****************************************************************************/ int CountAttachments(char *basepackage) { FILE *fp; int argnum = 0; char line[CF_BUFSIZE],type[CF_BUFSIZE],arg[CF_BUFSIZE]; Debug("CountAttachments(%s)\n",basepackage); if ((fp = fopen(basepackage,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open a parameter bundle (%s) while counting attachments\n",basepackage); CfLog(cfinform,OUTPUT,"fopen"); return 0; } while (!feof(fp)) { memset(line,0,CF_BUFSIZE); fgets(line,CF_BUFSIZE,fp); type[0] = '\0'; arg[0] = '\0'; sscanf(line,"%63s %s",type,arg); switch (ConvertMethodProto(type)) { case cfmeth_attacharg: argnum++; break; } } fclose(fp); return argnum; } /******************************************************************************/ /* Tool level */ /******************************************************************************/ void EncapsulateMethod(struct Method *ptr,char *name) { struct Item *ip; char expbuf[CF_EXPANDSIZE],filename[CF_BUFSIZE]; int i = 0; FILE *fp; if (strstr(name,":Reply")) /* TODO - check if remote spoofing this could be dangerous*/ { snprintf(OUTPUT,CF_BUFSIZE,"Method name (%s) should not contain a reply signal",name); CfLog(cferror,OUTPUT,""); } if ((fp = fopen(name,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not dispatch method to %s\n",name); CfLog(cferror,OUTPUT,"fopen"); return; } Debug("EncapsulatingMethod(%s)\n",name); fprintf(fp,"%s %s\n",VMETHODPROTO[cfmeth_name],ptr->name); fprintf(fp,"%s %s\n",VMETHODPROTO[cfmeth_file],ptr->file); fprintf(fp,"%s %lu\n",VMETHODPROTO[cfmeth_time],(unsigned long)CFSTARTTIME); if (ptr->servers == NULL || ptr->servers->name == NULL) { fprintf(fp,"%s localhost\n",VMETHODPROTO[cfmeth_replyto]); } else if (strcmp(ptr->servers->name,"localhost") == 0) { fprintf(fp,"%s localhost\n",VMETHODPROTO[cfmeth_replyto]); } else { /* Send FQNAME or VIPADDRESS or IPv6? This is difficult. Best to send IP to avoid lookups, and hosts might have a fixed name but variable IP ... get it from interface? unfortunately can't do this for IPv6 yet -- leave that for another day.*/ if (strlen(ptr->forcereplyto) > 0) { fprintf(fp,"%s %s\n",VMETHODPROTO[cfmeth_replyto],ptr->forcereplyto); } else { fprintf(fp,"%s %s\n",VMETHODPROTO[cfmeth_replyto],VIPADDRESS); } } for (ip = ptr->send_classes; ip != NULL; ip=ip->next) { /* If classX is defined locally, activate class method_classX in method */ if (IsDefinedClass(ip->name)) { fprintf(fp,"%s %s\n",VMETHODPROTO[cfmeth_sendclass],ip->name); } } for (ip = ptr->send_args; ip != NULL; ip=ip->next) { i++; if (strstr(name,"rpc_out")) /* Remote copy needs to be transferred to incoming for later .. */ { char correction[CF_BUFSIZE]; snprintf(correction,CF_BUFSIZE-1,"%s/rpc_in/%s",VLOCKDIR,name+strlen(VLOCKDIR)+2+strlen("rpc_out")); fprintf(fp,"%s %s+%d\n",VMETHODPROTO[cfmeth_attacharg],correction,i); } else { fprintf(fp,"%s %s+%d\n",VMETHODPROTO[cfmeth_attacharg],name,i); } } fclose(fp); Debug("Packaging done\n"); /* Now open a new file for each argument - this provides more policy control and security for remote access, since file sizes can be limited and there is less chance of buffer overflows */ i = 0; for (ip = ptr->send_args; ip != NULL; ip=ip->next) { i++; snprintf(filename,CF_BUFSIZE-1,"%s+%d",name,i); Debug("Create arg_file %s\n",filename); if (IsBuiltinFunction(ip->name)) { char name[CF_BUFSIZE],args[CF_BUFSIZE],value[CF_BUFSIZE],sourcefile[CF_BUFSIZE]; char *sp,maxbytes[CF_BUFSIZE],*nf,*nm; int count = 0,val = 0; FILE *fin,*fout; /*Expand var 2dim*/ Debug("Evaluating readfile inclusion...\n"); sscanf(ip->name,"%255[^(](%255[^)])",name,args); ExpandVarstring(name,expbuf,NULL); switch (FunctionStringToCode(expbuf)) { case fn_readfile: sourcefile[0] = '\0'; maxbytes[0] = '\0'; for (sp = args; *sp != '\0'; sp++) { if (*sp == ',') { count++; } } if (count != 1) { yyerror("ReadFile(filename,maxbytes): argument error"); return; } sscanf(args,"%[^,],%[^)]",sourcefile,maxbytes); Debug("ReadFile [%s] < [%s]\n",sourcefile,maxbytes); if (sourcefile[0]=='\0' || maxbytes[0] == '\0') { yyerror("Argument error in class-function"); return; } nf = UnQuote(sourcefile); nm = UnQuote(maxbytes); val = atoi(nm); if ((fin = fopen(nf,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"could not open ReadFile(%s)\n",nf); CfLog(cferror,OUTPUT,"fopen"); return; } Debug("Writing file to %s\n",filename); if ((fout = fopen(filename,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open argument attachment %s\n",filename); CfLog(cferror,OUTPUT,"fopen"); fclose(fin); return; } if (val > CF_BUFSIZE) { int count = 0; while(!feof(fin)) { fputc(fgetc(fin),fout); count++; if (count == val) { break; } Debug("Wrote #\n"); } } else { memset(value,0,CF_BUFSIZE); fread(value,val,1,fin); fwrite(value,val,1,fout); Debug("Wrote #\n"); } fclose(fin); fclose(fout); Debug("Done with file dispatch\n"); break; default: snprintf(OUTPUT,CF_BUFSIZE,"Invalid function (%s) used in function argument processing",expbuf); CfLog(cferror,OUTPUT,""); } } else { if ((fp = fopen(filename,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could dispatch method to %s\n",name); CfLog(cferror,OUTPUT,"fopen"); return; } ExpandVarstring(ip->name,expbuf,NULL); fwrite(expbuf,strlen(expbuf),1,fp); fclose(fp); } } } /******************************************************************************/ void EncapsulateReply(char *name) { FILE *fp; struct Item *ip; char expbuf[CF_EXPANDSIZE],filename[CF_BUFSIZE]; int i = 0; if ((fp = fopen(name,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could dispatch method to %s\n",name); CfLog(cferror,OUTPUT,"fopen"); return; } Debug("EncapsulatingReply(%s)\n",name); fprintf(fp,"%s %s\n",VMETHODPROTO[cfmeth_name],METHODNAME); fprintf(fp,"%s %lu\n",VMETHODPROTO[cfmeth_time],(unsigned long)CFSTARTTIME); fprintf(fp,"%s true\n",VMETHODPROTO[cfmeth_isreply]); Verbose("Checking whether to define any classes ...\n"); for (ip = METHODRETURNCLASSES; ip != NULL; ip=ip->next) { /* If classX is defined locally, activate class method_classX in method */ Debug("Is class %s defined in method?\n",ip->name); if (IsDefinedClass(ip->name)) { Verbose("Packaging return class %s\n",ip->name); fprintf(fp,"%s %s\n",VMETHODPROTO[cfmeth_sendclass],ip->name); } else { Verbose("Not defining return class %s\n",ip->name); } } DeleteItemList(ip); for (ip = METHODRETURNVARS; ip != NULL; ip=ip->next) { i++; ExpandVarstring(ip->name,expbuf,NULL); if (strstr(name,"rpc_out")) /* Remote copy needs to be transferred to incoming for later .. */ { char correction[CF_BUFSIZE]; snprintf(correction,CF_BUFSIZE-1,"%s/rpc_in/%s",VLOCKDIR,name+strlen(VLOCKDIR)+2+strlen("rpc_out")); fprintf(fp,"%s %s+%d\n",VMETHODPROTO[cfmeth_attacharg],correction,i); } else { fprintf(fp,"%s %s+%d\n",VMETHODPROTO[cfmeth_attacharg],name,i); } } DeleteItemList(ip); fclose(fp); Debug("Packaging done\n"); /* Now open a new file for each argument - this provides more policy control and security for remote access, since file sizes can be limited and there is less chance of buffer overflows */ i = 0; for (ip = METHODRETURNVARS; ip != NULL; ip=ip->next) { i++; snprintf(filename,CF_BUFSIZE-1,"%s+%d",name,i); Debug("Create arg_file %s\n",filename); if (IsBuiltinFunction(ip->name)) { char name[CF_BUFSIZE],args[CF_BUFSIZE],value[CF_BUFSIZE],sourcefile[CF_BUFSIZE]; char *sp,maxbytes[CF_BUFSIZE],*nf,*nm; int count = 0,val = 0; FILE *fin,*fout; Debug("Evaluating readfile inclusion...\n"); sscanf(ip->name,"%255[^(](%255[^)])",name,args); ExpandVarstring(name,expbuf,NULL); switch (FunctionStringToCode(expbuf)) { case fn_readfile: sourcefile[0] = '\0'; maxbytes[0] = '\0'; for (sp = args; *sp != '\0'; sp++) { if (*sp == ',') { count++; } } if (count != 1) { yyerror("ReadFile(filename,maxbytes): argument error"); return; } sscanf(args,"%[^,],%[^)]",sourcefile,maxbytes); Debug("ReadFile [%s] < [%s]\n",sourcefile,maxbytes); if (sourcefile[0]=='\0' || maxbytes[0] == '\0') { yyerror("Argument error in class-function"); return; } nf = UnQuote(sourcefile); nm = UnQuote(maxbytes); val = atoi(nm); if ((fin = fopen(nf,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"could not open ReadFile(%s)\n",nf); CfLog(cferror,OUTPUT,"fopen"); return; } if ((fout = fopen(filename,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could not open argument attachment %s\n",filename); CfLog(cferror,OUTPUT,"fopen"); fclose(fin); return; } if (val > CF_BUFSIZE) { int count = 0; while(!feof(fin)) { fputc(fgetc(fin),fout); count++; if (count == val) { break; } } } else { memset(value,0,CF_BUFSIZE); fread(value,val,1,fin); fwrite(value,val,1,fout); } fclose(fin); fclose(fout); break; default: snprintf(OUTPUT,CF_BUFSIZE,"Invalid function (%s) used in function argument processing",expbuf); CfLog(cferror,OUTPUT,""); } } else { if ((fp = fopen(filename,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Could dispatch method to %s\n",name); CfLog(cferror,OUTPUT,"fopen"); return; } ExpandVarstring(ip->name,expbuf,NULL); fwrite(expbuf,strlen(expbuf),1,fp); fclose(fp); } } DeleteItemList(ip); } /******************************************************************************/ void SplitMethodName(char *name,char *client,char *server,char *methodname,char *digeststring,char *extra) { Debug("SplitMethodName(%s)\n",name); methodname[0] = '\0'; client[0] = '\0'; server[0] = '\0'; digeststring[0] = '\0'; extra[0] = '\0'; sscanf(name,"%1024[^+]+%1024[^+]+%1024[^+]+%[^+]+%64s",client,server,methodname,digeststring,extra); Debug("Method client -> %s\n",client); Debug("Method server -> %s\n",server); Debug("Method name -> %s\n",methodname); Debug("Method digeststring -> %s\n",digeststring); Debug("Method extra -> %s\n",extra); } cfengine-2.2.10/src/cfexecd.c0000644000175000001440000006233211055247117012634 00000000000000/* Copyright (C) 1995- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Cfexecd : local scheduling daemon */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #ifdef NT # include #endif /*******************************************************************/ /* GLOBAL VARIABLES */ /*******************************************************************/ struct option CFDOPTIONS[] = { { "help",no_argument,0,'h' }, { "debug",optional_argument,0,'d' }, { "verbose",no_argument,0,'v' }, { "no-splay",no_argument,0,'q' }, { "no-fork",no_argument,0,'F' }, { "once",no_argument,0,'1'}, { "foreground",no_argument,0,'g'}, { "parse-only",no_argument,0,'p'}, { "ld-library-path",required_argument,0,'L'}, { NULL,0,0,0 } }; int NO_FORK = false; int ONCE = false; int MAXLINES = -1; char MAILTO[CF_BUFSIZE]; char MAILFROM[CF_BUFSIZE]; const int INF_LINES = -2; /*******************************************************************/ /* Functions internal to cfservd.c */ /*******************************************************************/ void CheckOptsAndInit (int argc,char **argv); void StartServer (int argc, char **argv); void Syntax (void); void *ExitCleanly (void); void *LocalExec (void *scheduled_run); void MailResult (char *filename, char *to); int ScheduleRun (void); void AddClassToHeap (char *class); void DeleteClassFromHeap (char *class); int Dialogue (int sd,char *class); int OpeningCeremony(int sd); void GetCfStuff (void); void Banner (char * s); int CompareResult (char *filename, char *prev_file); int FileChecksum (char *filename, unsigned char *digest, char type); /*******************************************************************/ /* Level 0 : Main */ /*******************************************************************/ int main (int argc,char **argv) { CheckOptsAndInit(argc,argv); StartServer(argc,argv); if (!ONCE) { RestoreExecLock(); ReleaseCurrentLock(); closelog(); } return 0; } /********************************************************************/ /* Level 1 */ /********************************************************************/ void CheckOptsAndInit(int argc,char **argv) { extern char *optarg; int optindex = 0; char ld_library_path[CF_BUFSIZE]; int c,seed; unsigned char s[16]; ld_library_path[0] = '\0'; Banner("Check options"); NOSPLAY = false; sprintf(VPREFIX, "cfexecd"); openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,LOG_DAEMON); while ((c=getopt_long(argc,argv,"L:d:vhpqFV1g",CFDOPTIONS,&optindex)) != EOF) { switch ((char) c) { case 'd': switch ((optarg==NULL)?3:*optarg) { case '1': D1 = true; break; case '2': D2 = true; break; default: DEBUG = true; break; } NO_FORK = true; VERBOSE = true; printf("cfexecd Debug mode: running in foreground\n"); break; case 'v': VERBOSE = true; break; case 'V': printf("GNU %s-%s daemon\n%s\n",PACKAGE,VERSION,COPYRIGHT); printf("This program is covered by the GNU Public License and may be\n"); printf("copied free of charge. No warrenty is implied.\n\n"); exit(0); break; case 'q': NOSPLAY = true; break; case 'p': PARSEONLY = true; break; case 'g': NO_FORK = true; break; case 'L': snprintf(ld_library_path,CF_BUFSIZE-1,"LD_LIBRARY_PATH=%s",optarg); if (putenv(strdup(ld_library_path)) != 0) { } break; case 'F': case '1': ONCE = true; NO_FORK = true; break; case 'h': Syntax(); exit(1); break; /* never reached.... */ default: Syntax(); exit(1); } } LOGGING = true; /* Do output to syslog */ /* XXX Initialize workdir for non privileged users */ strcpy(CFWORKDIR,WORKDIR); #ifndef NT if (getuid() > 0) { char *homedir; if ((homedir = getenv("HOME")) != NULL) { strcpy(CFWORKDIR,homedir); strcat(CFWORKDIR,"/.cfagent"); } } #endif snprintf(VBUFF,CF_BUFSIZE,"%s/inputs/update.conf",CFWORKDIR); MakeDirectoriesFor(VBUFF,'y'); snprintf(VBUFF,CF_BUFSIZE,"%s/bin/cfagent -D from_cfexecd",CFWORKDIR); MakeDirectoriesFor(VBUFF,'y'); snprintf(VBUFF,CF_BUFSIZE,"%s/outputs/spooled_reports",CFWORKDIR); MakeDirectoriesFor(VBUFF,'y'); snprintf(VBUFF,CF_BUFSIZE,"%s/inputs",CFWORKDIR); chmod(VBUFF,0700); snprintf(VBUFF,CF_BUFSIZE,"%s/outputs",CFWORKDIR); chmod(VBUFF,0700); strncpy(VLOCKDIR,CFWORKDIR,CF_BUFSIZE-1); strncpy(VLOGDIR,CFWORKDIR,CF_BUFSIZE-1); VCANONICALFILE = strdup(CanonifyName(VINPUTFILE)); GetCfStuff(); MAILTO[0] = '\0'; MAILFROM[0] = '\0'; VIPADDRESS[0] = '\0'; VMAILSERVER[0] = '\0'; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); CheckWorkDirectories(); RandomSeed(); RAND_bytes(s,16); s[15] = '\0'; seed = ElfHash(s); srand48((long)seed); } /*******************************************************************/ void StartServer(int argc,char **argv) { int pid,time_to_run = false; time_t now = time(NULL); #ifdef HAVE_PTHREAD_H pthread_t tid = 1; #else int tid = -1 #endif Banner("Starting server"); if ((!NO_FORK) && (fork() != 0)) { snprintf(OUTPUT,CF_BUFSIZE*2,"cfexecd starting %.24s\n",ctime(&now)); CfLog(cfinform,OUTPUT,""); exit(0); } if (!ONCE) { if (!GetLock("cfexecd","execd",0,0,VUQNAME,now)) { snprintf(OUTPUT,CF_BUFSIZE*2,"cfexecd: Couldn't get a lock -- exists or too soon: IfElapsed %d, ExpireAfter %d\n",0,0); CfLog(cfverbose,OUTPUT,""); return; } SaveExecLock(); } if (!NO_FORK) { ActAsDaemon(0); } WritePID("cfexecd.pid"); signal(SIGINT,(void *)ExitCleanly); signal(SIGTERM,(void *)ExitCleanly); signal(SIGHUP,SIG_IGN); signal(SIGPIPE,SIG_IGN); signal(SIGUSR1,HandleSignal); signal(SIGUSR2,HandleSignal); umask(077); if (ONCE) { GetCfStuff(); LocalExec((void *)0); } else { char **nargv; int i; /* * Append --once option to our arguments for spawned monitor process. */ nargv = malloc(sizeof(char *) * (argc+2)); for (i = 0; i < argc; i++) { nargv[i] = argv[i]; } nargv[i++] = strdup("--once"); nargv[i++] = NULL; GetCfStuff(); while (true) { time_to_run = ScheduleRun(); if (time_to_run) { if (!GetLock("cfd","exec",CF_EXEC_IFELAPSED,CF_EXEC_EXPIREAFTER,VUQNAME,time(NULL))) { snprintf(OUTPUT,CF_BUFSIZE*2,"cfexecd: Couldn't get exec lock -- exists or too soon: IfElapsed %d, ExpireAfter %d\n",CF_EXEC_IFELAPSED,CF_EXEC_EXPIREAFTER); CfLog(cfverbose,OUTPUT,""); continue; } GetCfStuff(); #ifdef NT /* * Spawn a separate process - spawn will work if the cfexecd binary * has changed (where cygwin's fork() would fail). */ Debug("Spawning %s\n", nargv[0]); pid = _spawnvp((int)_P_NOWAIT,nargv[0],nargv); if (pid < 1) { CfLog(cfinform,"Can't spawn run","spawnvp"); } #endif #ifndef NT #if (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) pthread_attr_init(&PTHREADDEFAULTS); pthread_attr_setdetachstate(&PTHREADDEFAULTS,PTHREAD_CREATE_DETACHED); #ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE pthread_attr_setstacksize(&PTHREADDEFAULTS,(size_t)2048*1024); #endif if (pthread_create(&tid,&PTHREADDEFAULTS,LocalExec,(void *)1) != 0) { CfLog(cfinform,"Can't create thread!","pthread_create"); LocalExec((void *)1); } pthread_attr_destroy(&PTHREADDEFAULTS); #else LocalExec((void *)1); #endif #endif ReleaseCurrentLock(); } } } } /*********************************************************************/ /* Level 2 */ /*********************************************************************/ void Syntax() { int i; printf("GNU cfengine daemon: scheduler\n%s-%s\n%s\n",PACKAGE,VERSION,COPYRIGHT); printf("\n"); printf("Options:\n\n"); for (i=0; CFDOPTIONS[i].name != NULL; i++) { printf("--%-20s (-%c)\n",CFDOPTIONS[i].name,(char)CFDOPTIONS[i].val); } printf("\nBug reports to bug-cfengine@cfengine.org\n"); printf("General help to help-cfengine@cfengine.org\n"); printf("Info & fixes at http://www.cfengine.org\n"); } /*******************************************************************/ void GetCfStuff() { FILE *pp; char cfcom[CF_BUFSIZE]; static char line[CF_BUFSIZE]; /* Do not init variables here, in case we can use previous values. */ snprintf(cfcom,CF_BUFSIZE-1,"%s/bin/cfagent -Q smtpserver,sysadm,fqhost,host,domain,ipaddress,EmailMaxLines,EmailFrom,EmailTo -D from_cfexecd",CFWORKDIR); if ((pp=cfpopen(cfcom,"r")) == NULL) { CfLog(cfinform,"Couldn't start cfengine!","cfpopen"); line[0] = '\0'; return; } while (!feof(pp)) { char name[CF_BUFSIZE],content[CF_BUFSIZE]; line[0] = '\0'; fgets(line,CF_BUFSIZE,pp); Chop(line); sscanf(line,"%[^=]=%[^\n]",name,content); if (strcmp(name,"sysadm") == 0) { strncpy(MAILTO,content,CF_MAXVARSIZE-1); Debug("%s\n",line); continue; } if (strcmp(name,"smtpserver") == 0) { Debug("%s/%s\n",name,content); strncpy(VMAILSERVER,content,CF_MAXVARSIZE-1); continue; } if (strcmp(name,"fqhost") == 0) { Debug("%s/%s\n",name,content); strncpy(VFQNAME,content,CF_MAXVARSIZE-1); continue; } if (strcmp(name,"host") == 0) { Debug("%s/%s\n",name,content); strncpy(VUQNAME,content,CF_MAXVARSIZE-1); continue; } if (strcmp(name,"domain") == 0) { Debug("%s/%s\n",name,content); strncpy(VDOMAIN,content,CF_MAXVARSIZE-1); continue; } if (strcmp(name,"ipaddress") == 0) { Debug("%s/%s\n",name,content); strncpy(VIPADDRESS,content,17); continue; } if (strcmp(name,"EmailMaxLines") == 0) { Debug("%s/%s\n",name,content); MAXLINES = 100; if (strcmp(content,"inf") == 0) { MAXLINES = -2; Debug("EmailMaxLines set to infinity\n"); } else { sscanf(content,"%d",&MAXLINES); } continue; } if (strcmp(name,"EmailFrom") == 0) { Debug("%s/%s\n",name,content); if (strstr(content,"$") == NULL && strlen(content) > 0) { strncpy(MAILFROM,content,CF_MAXVARSIZE-1); continue; } } if (strcmp(name,"EmailTo") == 0) { Debug("%s/%s\n",name,content); if (strstr(content,"$") == NULL && strlen(content) > 0) { strncpy(MAILTO,content,CF_MAXVARSIZE-1); continue; } } } cfpclose(pp); Debug("Got(to:%s,serv:%s,fqhost:%s,host:%s,domain:%s,ip:%s,max:%d,from:%s)\n",MAILTO,VMAILSERVER,VFQNAME,VUQNAME,VDOMAIN,VIPADDRESS,MAXLINES,MAILFROM); /* Now get schedule */ snprintf(cfcom,CF_BUFSIZE-1,"%s/bin/cfagent -z -D from_cfexecd",CFWORKDIR); if ((pp=cfpopen(cfcom,"r")) == NULL) { CfLog(cfinform,"Couldn't start cfengine!","cfpopen"); line[0] = '\0'; return; } DeleteItemList(SCHEDULE); SCHEDULE = NULL; while (!feof(pp)) { line[0] = '\0'; VBUFF[0] = '\0'; fgets(line,CF_BUFSIZE,pp); sscanf(line,"[%[^]]",VBUFF); if (strlen(VBUFF)==0) { continue; } if (!IsItemIn(SCHEDULE,VBUFF)) { AppendItem(&SCHEDULE,VBUFF,NULL); } } cfpclose(pp); if (SCHEDULE == NULL) { Verbose("No schedule defined in cfagent.conf, defaulting to Min00_05\n"); AppendItem(&SCHEDULE,"Min00_05",NULL); } } /*********************************************************************/ int ScheduleRun() { time_t now; char timekey[64]; struct Item *ip; Verbose("Sleeping...\n"); sleep(60); /* 1 Minute resolution is enough */ now = time(NULL); snprintf(timekey,63,"%s",ctime(&now)); AddTimeClass(timekey); for (ip = SCHEDULE; ip != NULL; ip = ip->next) { Verbose("Checking schedule %s...\n",ip->name); if (IsDefinedClass(ip->name)) { Verbose("Waking up the agent at %s ~ %s \n",timekey,ip->name); DeleteItemList(VHEAP); VHEAP = NULL; return true; } } DeleteItemList(VHEAP); VHEAP = NULL; return false; } /*********************************************************************/ /* Level 3 */ /*********************************************************************/ void *ExitCleanly() { ReleaseCurrentLock(); closelog(); unlink(PIDFILE); exit(0); } /**************************************************************/ static char *timestamp(time_t stamp, char *buf, size_t len) { struct tm *ltime; ltime = localtime(&stamp); snprintf(buf, len, "%04d-%02d-%02d--%02d-%02d-%02d", ltime->tm_year+1900, ltime->tm_mon+1, ltime->tm_mday, ltime->tm_hour, ltime->tm_min, ltime->tm_sec); return buf; } /**************************************************************/ void *LocalExec(void *scheduled_run) { FILE *pp; char line[CF_BUFSIZE],filename[CF_BUFSIZE],*sp; char cmd[CF_BUFSIZE]; int print, tid; time_t starttime = time(NULL); FILE *fp; #ifdef HAVE_PTHREAD_SIGMASK sigset_t sigmask; sigemptyset(&sigmask); pthread_sigmask(SIG_BLOCK,&sigmask,NULL); #endif #ifdef HAVE_PTHREAD tid = (int)pthread_self(); #endif Verbose("------------------------------------------------------------------\n\n"); Verbose(" LocalExec(%sscheduled) at %s\n", scheduled_run ? "" : "not ", ctime(&starttime)); Verbose("------------------------------------------------------------------\n"); /* Need to make sure we have LD_LIBRARY_PATH here or children will die */ snprintf(cmd,CF_BUFSIZE-1,"%s/bin/cfagent%s -Dfrom_cfexecd%s", CFWORKDIR, NOSPLAY ? " -q" : "", scheduled_run ? ":scheduled_run" : ""); timestamp(starttime, line, CF_BUFSIZE); snprintf(filename,CF_BUFSIZE-1,"%s/outputs/cf_%s_%s_%u",CFWORKDIR,CanonifyName(VFQNAME),line,time(NULL)); /* What if no more processes? Could sacrifice and exec() - but we need a sentinel */ if ((fp = fopen(filename,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open %s\n",filename); CfLog(cfinform,OUTPUT,"fopen"); return NULL; } if ((pp = cfpopen(cmd,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open pipe to command %s\n",cmd); CfLog(cfinform,OUTPUT,"cfpopen"); fclose(fp); return NULL; } while (!feof(pp) && ReadLine(line,CF_BUFSIZE,pp)) { if (ferror(pp)) { fflush(pp); break; } print = false; for (sp = line; *sp != '\0'; sp++) { if (! isspace((int)*sp)) { print = true; break; } } if (print) { fprintf(fp,"%s\n",line); /* If we can't send mail, log to syslog */ if (strlen(MAILTO) == 0) { strncat(line,"\n",CF_BUFSIZE-1-strlen(line)); if ((strchr(line,'\n')) == NULL) { line[CF_BUFSIZE-2] = '\n'; } CfLog(cfinform,line,""); } line[0] = '\0'; } } cfpclose(pp); Debug("Closing fp\n"); fclose(fp); MailResult(filename,MAILTO); return NULL; } /******************************************************************/ /* Level 4 */ /******************************************************************/ int FileChecksum(char *filename,unsigned char digest[EVP_MAX_MD_SIZE+1],char type) { FILE *file; EVP_MD_CTX context; int len, md_len; unsigned char buffer[1024]; const EVP_MD *md = NULL; Debug2("FileChecksum(%c,%s)\n",type,filename); if ((file = fopen (filename, "rb")) == NULL) { printf ("%s can't be opened\n", filename); } else { switch (type) { case 's': md = EVP_get_digestbyname("sha"); break; case 'm': md = EVP_get_digestbyname("md5"); break; default: FatalError("Software failure in ChecksumFile"); } if (!md) { /* Don't leak file descriptors. */ fclose(file); return 0; } EVP_DigestInit(&context,md); while (len = fread(buffer,1,1024,file)) { EVP_DigestUpdate(&context,buffer,len); } EVP_DigestFinal(&context,digest,&md_len); fclose (file); return(md_len); } return 0; } /*******************************************************************/ int CompareResult(char *filename,char *prev_file) { int i; char digest1[EVP_MAX_MD_SIZE+1]; char digest2[EVP_MAX_MD_SIZE+1]; int md_len1, md_len2; FILE *fp; int rtn = 0; Verbose("Comparing files %s with %s\n", prev_file, filename); if ((fp=fopen(prev_file,"r")) != NULL) { fclose(fp); md_len1 = FileChecksum(prev_file, digest1, 'm'); md_len2 = FileChecksum(filename, digest2, 'm'); if (md_len1 != md_len2) { rtn = 1; } else { for (i = 0; i < md_len1; i++) if (digest1[i] != digest2[i]) { rtn = 1; break; } } } else { /* no previous file */ rtn = 1; } #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_lock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_lock failed","pthread_mutex_lock"); exit(1); } #endif unlink(prev_file); if (symlink(filename, prev_file) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Could not link %s and %s",filename,prev_file); CfLog(cfinform,OUTPUT,"symlink"); rtn = 1; } #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_COUNT) != 0) { CfLog(cferror,"pthread_mutex_unlock failed","pthread_mutex_unlock"); exit(1); } #endif return(rtn); } /***********************************************************************/ void MailResult(char *file,char *to) { int sd, sent, count = 0, anomaly = false; char domain[256], prev_file[CF_BUFSIZE]; struct hostent *hp; struct sockaddr_in raddr; struct servent *server; struct stat statbuf; time_t now = time(NULL); FILE *fp; if ((strlen(VMAILSERVER) == 0) || (strlen(to) == 0)) { /* Syslog should have done this */ return; } if (stat(file,&statbuf) == -1) { exit(0); } snprintf(prev_file,CF_BUFSIZE-1,"%s/outputs/previous",CFWORKDIR); if (statbuf.st_size == 0) { unlink(file); Debug("Nothing to report in %s\n",file); return; } if (CompareResult(file,prev_file) == 0 ) { Verbose("Previous output is the same as current so do not mail it\n"); return; } if (MAXLINES == 0) { Debug("Not mailing: EmailMaxLines was zero\n"); return; } Debug("Mailing results of (%s) to (%s)\n",file,to); if (strlen(to) == 0) { return; } /* Check first for anomalies - for subject header */ if ((fp=fopen(file,"r")) == NULL) { snprintf(VBUFF,CF_BUFSIZE-1,"Couldn't open file %s",file); CfLog(cfinform,VBUFF,"fopen"); return; } while (!feof(fp)) { VBUFF[0] = '\0'; fgets(VBUFF,CF_BUFSIZE,fp); if (strstr(VBUFF,"entropy")) { anomaly = true; break; } } fclose(fp); if ((fp=fopen(file,"r")) == NULL) { snprintf(VBUFF,CF_BUFSIZE-1,"Couldn't open file %s",file); CfLog(cfinform,VBUFF,"fopen"); return; } Debug("Looking up hostname %s\n\n",VMAILSERVER); if ((hp = gethostbyname(VMAILSERVER)) == NULL) { printf("Unknown host: %s\n", VMAILSERVER); printf("Make sure that fully qualified names can be looked up at your site!\n"); printf("i.e. www.gnu.org, not just www. If you use NIS or /etc/hosts\n"); printf("make sure that the full form is registered too as an alias!\n"); fclose(fp); return; } if ((server = getservbyname("smtp","tcp")) == NULL) { CfLog(cfinform,"Unable to lookup smtp service","getservbyname"); fclose(fp); return; } memset(&raddr,0,sizeof(raddr)); raddr.sin_port = (unsigned int) server->s_port; raddr.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; raddr.sin_family = AF_INET; Debug("Connecting...\n"); if ((sd = socket(AF_INET,SOCK_STREAM,0)) == -1) { CfLog(cfinform,"Couldn't open a socket","socket"); fclose(fp); return; } if (connect(sd,(void *) &raddr,sizeof(raddr)) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't connect to host %s\n",VMAILSERVER); CfLog(cfinform,OUTPUT,"connect"); fclose(fp); close(sd); return; } /* read greeting */ if (!Dialogue(sd,NULL)) { goto mail_err; } sprintf(VBUFF,"HELO %s\r\n",VFQNAME); Debug("%s",VBUFF); if (!Dialogue(sd,VBUFF)) { goto mail_err; } if (strlen(MAILFROM) == 0) { sprintf(VBUFF,"MAIL FROM: \r\n",VFQNAME); Debug("%s",VBUFF); } else { sprintf(VBUFF,"MAIL FROM: <%s>\r\n",MAILFROM); Debug("%s",VBUFF); } if (!Dialogue(sd,VBUFF)) { goto mail_err; } sprintf(VBUFF,"RCPT TO: <%s>\r\n",to); Debug("%s",VBUFF); if (!Dialogue(sd,VBUFF)) { goto mail_err; } if (!Dialogue(sd,"DATA\r\n")) { goto mail_err; } if (anomaly) { sprintf(VBUFF,"Subject: **!! (%s/%s)\r\n",VFQNAME,VIPADDRESS); Debug("%s",VBUFF); } else { sprintf(VBUFF,"Subject: (%s/%s)\r\n",VFQNAME,VIPADDRESS); Debug("%s",VBUFF); } sent=send(sd,VBUFF,strlen(VBUFF),0); #if defined LINUX || defined NETBSD || defined FREEBSD || defined OPENBSD strftime(VBUFF,CF_BUFSIZE,"Date: %a, %d %b %Y %H:%M:%S %z\r\n",localtime(&now)); sent=send(sd,VBUFF,strlen(VBUFF),0); #endif if (strlen(MAILFROM) == 0) { sprintf(VBUFF,"From: cfengine@%s\r\n",VFQNAME); Debug("%s",VBUFF); } else { sprintf(VBUFF,"From: %s\r\n",MAILFROM); Debug("%s",VBUFF); } sent=send(sd,VBUFF,strlen(VBUFF),0); sprintf(VBUFF,"To: %s\r\n\r\n",to); Debug("%s",VBUFF); sent=send(sd,VBUFF,strlen(VBUFF),0); while(!feof(fp)) { VBUFF[0] = '\0'; fgets(VBUFF,CF_BUFSIZE,fp); Debug("%s",VBUFF); if (strlen(VBUFF) > 0) { VBUFF[strlen(VBUFF)-1] = '\r'; strcat(VBUFF, "\n"); count++; sent=send(sd,VBUFF,strlen(VBUFF),0); } if ((MAXLINES != INF_LINES) && (count > MAXLINES)) { sprintf(VBUFF,"\r\n[Mail truncated by cfengine. File is at %s on %s]\r\n",file,VFQNAME); sent=send(sd,VBUFF,strlen(VBUFF),0); break; } } if (!Dialogue(sd,".\r\n")) { Debug("mail_err\n"); goto mail_err; } Dialogue(sd,"QUIT\r\n"); Debug("Done sending mail\n"); fclose(fp); close(sd); return; mail_err: fclose(fp); close(sd); sprintf(VBUFF, "Cannot mail to %s.", to); CfLog(cflogonly,VBUFF,""); } /******************************************************************/ /* Level 5 */ /******************************************************************/ int Dialogue(int sd,char *s) { int sent; char ch,f = '\0'; int charpos,rfclinetype = ' '; if ((s != NULL) && (*s != '\0')) { sent=send(sd,s,strlen(s),0); Debug("SENT(%d)->%s",sent,s); } else { Debug("Nothing to send .. waiting for opening\n"); } charpos = 0; while (recv(sd,&ch,1,0)) { charpos++; if (f == '\0') { f = ch; } if (charpos == 4) /* Multiline RFC in form 222-Message with hyphen at pos 4 */ { rfclinetype = ch; } Debug("%c",ch); if (ch == '\n' || ch == '\0') { charpos = 0; if (rfclinetype == ' ') { break; } } } return ((f == '2') || (f == '3')); /* return code 200 or 300 from smtp*/ } /* EOF */ cfengine-2.2.10/src/filedir.c0000644000175000001440000010533011120236601012632 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" #ifdef DARWIN #include #endif /*********************************************************************/ int IsHomeDir(char *name) /* This assumes that the dir lies under mountpattern */ { char *sp; struct Item *ip; int slashes; if (name == NULL || strlen(name) == 0) { return false; } if (VMOUNTLIST == NULL) { return (false); } for (ip = VHOMEPATLIST; ip != NULL; ip=ip->next) { slashes = 0; for (sp = ip->name; *sp != '\0'; sp++) { if (*sp == '/') { slashes++; } } for (sp = name+strlen(name); (*(sp-1) != '/') && (sp >= name) && (slashes >= 0); sp--) { if (*sp == '/') { slashes--; } } /* Full comparison */ if (WildMatch(ip->name,sp)) { Debug("IsHomeDir(true)\n"); return(true); } } Debug("IsHomeDir(%s,false)\n",name); return(false); } /*********************************************************************/ int EmptyDir(char *path) { DIR *dirh; struct dirent *dirp; int count = 0; Debug2("cfengine: EmptyDir(%s)\n",path); if ((dirh = opendir(path)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",path); CfLog(cfverbose,OUTPUT,"opendir"); return true; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,path,NULL)) { continue; } count++; } closedir(dirh); return (!count); } /*********************************************************************/ void CheckExistingFile(char *cf_findertype,char *file,struct stat *dstat,struct File *ptr) { mode_t newperm = dstat->st_mode, maskvalue; int amroot = true, fixmode = true, docompress=false, changed = false; unsigned char digest1[EVP_MAX_MD_SIZE+1]; unsigned char digest2[EVP_MAX_MD_SIZE+1]; enum fileactions action = ptr->action; #if defined HAVE_CHFLAGS u_long newflags; #endif Debug("CheckExistingFile(%s,%s)\n",file,FILEACTIONTEXT[ptr->action]); maskvalue = umask(0); /* This makes the DEFAULT modes absolute */ if (action == compress) { docompress = true; if (ptr != NULL) { AddMultipleClasses(ptr->defines); } action = fixall; /* Fix any permissions which are set */ } Debug("%s: Checking fs-object %s\n",VPREFIX,file); #if defined HAVE_CHFLAGS if (ptr != NULL) { Debug("CheckExistingFile(+%o,-%o,+%o,-%o)\n",ptr->plus,ptr->minus,ptr->plus_flags,ptr->minus_flags); } else { Debug("CheckExistingFile(+%o,-%o)\n",ptr->plus,ptr->minus); } #else Debug("CheckExistingFile(+%o,-%o)\n",ptr->plus,ptr->minus); #endif if (ptr != NULL) { if (IgnoredOrExcluded(files,file,ptr->inclusions,ptr->exclusions)) { Debug("Skipping excluded file %s\n",file); umask(maskvalue); return; } if (!FileObjectFilter(file,dstat,ptr->filters,files)) { Debug("Skipping filtered file %s\n",file); umask(maskvalue); return; } if (action == alert) { snprintf(OUTPUT,CF_BUFSIZE*2,"Alert specified on file %s (m=%o,o=%d,g=%d)",file,(dstat->st_mode & 07777),dstat->st_uid,dstat->st_gid); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); return; } } if (!IsPrivileged()) { amroot = false; } /* directories must have x set if r set, regardless */ newperm = (dstat->st_mode & 07777); newperm |= ptr->plus; newperm &= ~(ptr->minus); if (S_ISREG(dstat->st_mode) && (action == fixdirs || action == warndirs)) { Debug("Regular file, returning...\n"); umask(maskvalue); return; } if (S_ISDIR(dstat->st_mode)) { if (action == fixplain || action == warnplain) { umask(maskvalue); return; } if (ptr->rxdirs != 'n') { Debug("Directory...fixing x bits\n"); if (newperm & S_IRUSR) { newperm |= S_IXUSR; } if (newperm & S_IRGRP) { newperm |= S_IXGRP; } if (newperm & S_IROTH) { newperm |= S_IXOTH; } } else { Verbose("NB: rxdirs is set to false - x for r bits not checked\n"); } } if (dstat->st_uid == 0 && (dstat->st_mode & S_ISUID)) { if (newperm & S_ISUID) { if (! IsItemIn(VSETUIDLIST,file)) { if (amroot) { snprintf(OUTPUT,CF_BUFSIZE*2,"NEW SETUID root PROGRAM %s\n",file); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); } PrependItem(&VSETUIDLIST,file,NULL); } } else { switch (action) { case fixall: case fixdirs: case fixplain: snprintf(OUTPUT,CF_BUFSIZE*2,"Removing setuid (root) flag from %s...\n\n",file); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); if (ptr != NULL) { AddMultipleClasses(ptr->defines); } break; case warnall: case warndirs: case warnplain: if (amroot) { snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING setuid (root) flag on %s...\n\n",file); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); } break; } } } if (dstat->st_uid == 0 && (dstat->st_mode & S_ISGID)) { if (newperm & S_ISGID) { if (!IsItemIn(VSETUIDLIST,file)) { if (S_ISDIR(dstat->st_mode)) { /* setgid directory */ } else { if (amroot) { snprintf(OUTPUT,CF_BUFSIZE*2,"NEW SETGID root PROGRAM %s\n",file); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); } PrependItem(&VSETUIDLIST,file,NULL); } } } else { switch (action) { case fixall: case fixdirs: case fixplain: snprintf(OUTPUT,CF_BUFSIZE*2,"Removing setgid (root) flag from %s...\n\n",file); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); if (ptr != NULL) { AddMultipleClasses(ptr->defines); } break; case warnall: case warndirs: case warnplain: snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING setgid (root) flag on %s...\n\n",file); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); CfLog(cferror,OUTPUT,""); break; default: break; } } } #ifdef DARWIN if (CheckFinderType(file,action, cf_findertype, dstat)) { if (ptr != NULL) { AddMultipleClasses(ptr->defines); } } #endif if (CheckOwner(file,ptr,dstat)) { if (ptr != NULL) { AddMultipleClasses(ptr->defines); } } if ((ptr != NULL) && S_ISREG(dstat->st_mode) && (ptr->checksum != 'n')) { Debug("Checking checksum integrity of %s\n",file); memset(digest1,0,EVP_MAX_MD_SIZE+1); memset(digest2,0,EVP_MAX_MD_SIZE+1); if (ptr->checksum == 'b') { ChecksumFile(file,digest1,'m'); ChecksumFile(file,digest2,'s'); if (!DONTDO) { if (ChecksumChanged(file,digest1,cferror,false,'m') || ChecksumChanged(file,digest2,cferror,false,'s')) { changed = true; } } } else { ChecksumFile(file,digest1,ptr->checksum); if (!DONTDO) { if (ChecksumChanged(file,digest1,cferror,false,ptr->checksum)) { changed = true; } } } } if (changed) { snprintf(VBUFF,CF_BUFSIZE,"checksum_alert"); AddPersistentClass(VBUFF,30,cfpreserve); AddClassToHeap(VBUFF); LogChecksumChange(file); } if (S_ISLNK(dstat->st_mode)) /* No point in checking permission on a link */ { if (ptr != NULL) { KillOldLink(file,ptr->defines); } else { KillOldLink(file,NULL); } umask(maskvalue); return; } if (stat(file,dstat) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat file %s while looking at permissions (was not copied?)\n",file); CfLog(cfverbose,OUTPUT,"stat"); umask(maskvalue); return; } if (CheckACLs(file,action,ptr->acl_aliases)) { if (ptr != NULL) { AddMultipleClasses(ptr->defines); } } #ifndef HAVE_CHFLAGS if (((newperm & 07777) == (dstat->st_mode & 07777)) && (action != touch)) /* file okay */ { Debug("File okay, newperm = %o, stat = %o\n",(newperm & 07777),(dstat->st_mode & 07777)); if (docompress) { CompressFile(file); } if (ptr != NULL) { AddMultipleClasses(ptr->elsedef); } umask(maskvalue); return; } #else if (((newperm & 07777) == (dstat->st_mode & 07777)) && (action != touch)) /* file okay */ { Debug("File okay, newperm = %o, stat = %o\n",(newperm & 07777),(dstat->st_mode & 07777)); fixmode = false; } #endif if (fixmode) { Debug("Trying to fix mode...\n"); switch (action) { case linkchildren: case warnplain: if (S_ISREG(dstat->st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s has permission %o\n",file,dstat->st_mode & 07777); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); snprintf(OUTPUT,CF_BUFSIZE*2,"[should be %o]\n",newperm & 07777); CfLog(cferror,OUTPUT,""); } break; case warndirs: if (S_ISDIR(dstat->st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s has permission %o\n",file,dstat->st_mode & 07777); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); snprintf(OUTPUT,CF_BUFSIZE*2,"[should be %o]\n",newperm & 07777); CfLog(cferror,OUTPUT,""); } break; case warnall: snprintf(OUTPUT,CF_BUFSIZE*2,"%s has permission %o\n",file,dstat->st_mode & 07777); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); snprintf(OUTPUT,CF_BUFSIZE*2,"[should be %o]\n",newperm & 07777); CfLog(cferror,OUTPUT,""); break; case fixplain: if (S_ISREG(dstat->st_mode)) { if (! DONTDO) { if (chmod (file,newperm & 07777) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"chmod failed on %s\n",file); CfLog(cferror,OUTPUT,"chmod"); break; } } snprintf(OUTPUT,CF_BUFSIZE*2,"Plain file %s had permission %o, changed it to %o\n", file,dstat->st_mode & 07777,newperm & 07777); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); if (ptr != NULL) { AddMultipleClasses(ptr->defines); } } break; case fixdirs: if (S_ISDIR(dstat->st_mode)) { if (! DONTDO) { if (chmod (file,newperm & 07777) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"chmod failed on %s\n",file); CfLog(cferror,OUTPUT,"chmod"); break; } } snprintf(OUTPUT,CF_BUFSIZE*2,"Directory %s had permission %o, changed it to %o\n", file,dstat->st_mode & 07777,newperm & 07777); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); if (ptr != NULL) { AddMultipleClasses(ptr->defines); } } break; case fixall: if (! DONTDO) { if (chmod (file,newperm & 07777) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"chmod failed on %s\n",file); CfLog(cferror,OUTPUT,"chmod"); break; } } snprintf(OUTPUT,CF_BUFSIZE*2,"Object %s had permission %o, changed it to %o\n", file,dstat->st_mode & 07777,newperm & 07777); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); if (ptr != NULL) { AddMultipleClasses(ptr->defines); } break; case touch: case create: if (! DONTDO) { if (chmod (file,newperm & 07777) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"chmod failed on %s\n",file); CfLog(cferror,OUTPUT,"chmod"); break; } utime (file,NULL); } if (ptr != NULL) { AddMultipleClasses(ptr->defines); } break; default: FatalError("cfengine: internal error CheckExistingFile(): illegal file action\n"); } } if (CheckOwner(file,ptr,dstat)) /* Again */ { if (ptr != NULL) { AddMultipleClasses(ptr->defines); } } #if defined HAVE_CHFLAGS /* BSD special flags */ if (ptr != NULL) { newflags = (dstat->st_flags & CHFLAGS_MASK) ; newflags |= ptr->plus_flags; newflags &= ~(ptr->minus_flags); if ((newflags & CHFLAGS_MASK) == (dstat->st_flags & CHFLAGS_MASK)) /* file okay */ { Debug("File okay, flags = %o, current = %o\n",(newflags & CHFLAGS_MASK),(dstat->st_flags & CHFLAGS_MASK)); } else { Debug("Fixing %s, newflags = %o, flags = %o\n",file,(newflags & CHFLAGS_MASK),(dstat->st_flags & CHFLAGS_MASK)); switch (action) { case linkchildren: case warnplain: if (S_ISREG(dstat->st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s has flags %o\n",file,dstat->st_flags & CHFLAGS_MASK); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); snprintf(OUTPUT,CF_BUFSIZE*2,"[should be %o]\n",newflags & CHFLAGS_MASK); CfLog(cferror,OUTPUT,""); } break; case warndirs: if (S_ISDIR(dstat->st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s has flags %o\n",file,dstat->st_mode & CHFLAGS_MASK); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); snprintf(OUTPUT,CF_BUFSIZE*2,"[should be %o]\n",newflags & CHFLAGS_MASK); CfLog(cferror,OUTPUT,""); } break; case warnall: snprintf(OUTPUT,CF_BUFSIZE*2,"%s has flags %o\n",file,dstat->st_mode & CHFLAGS_MASK); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); snprintf(OUTPUT,CF_BUFSIZE*2,"[should be %o]\n",newflags & CHFLAGS_MASK); CfLog(cferror,OUTPUT,""); break; case fixplain: if (S_ISREG(dstat->st_mode)) { if (! DONTDO) { if (chflags (file,newflags & CHFLAGS_MASK) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"chflags failed on %s\n",file); CfLog(cferror,OUTPUT,"chflags"); break; } } snprintf(OUTPUT,CF_BUFSIZE*2,"%s had flags %o, changed it to %o\n", file,dstat->st_flags & CHFLAGS_MASK,newflags & CHFLAGS_MASK); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); if (ptr != NULL) { AddMultipleClasses(ptr->defines); } } break; case fixdirs: if (S_ISDIR(dstat->st_mode)) { if (! DONTDO) { if (chflags (file,newflags & CHFLAGS_MASK) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"chflags failed on %s\n",file); CfLog(cferror,OUTPUT,"chflags"); break; } } snprintf(OUTPUT,CF_BUFSIZE*2,"%s had flags %o, changed it to %o\n", file,dstat->st_flags & CHFLAGS_MASK,newflags & CHFLAGS_MASK); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); if (ptr != NULL) { AddMultipleClasses(ptr->defines); } } break; case fixall: if (! DONTDO) { if (chflags (file,newflags & CHFLAGS_MASK) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"chflags failed on %s\n",file); CfLog(cferror,OUTPUT,"chflags"); break; } } snprintf(OUTPUT,CF_BUFSIZE*2,"%s had flags %o, changed it to %o\n", file,dstat->st_flags & CHFLAGS_MASK,newflags & CHFLAGS_MASK); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); if (ptr != NULL) { AddMultipleClasses(ptr->defines); } break; case touch: case create: if (! DONTDO) { if (chflags (file,newflags & CHFLAGS_MASK) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"chflags failed on %s\n",file); CfLog(cferror,OUTPUT,"chflags"); break; } utime (file,NULL); } if (ptr != NULL) { AddMultipleClasses(ptr->defines); } break; default: FatalError("cfengine: internal error CheckExistingFile(): illegal file action\n"); } } } #endif if (docompress) { snprintf(OUTPUT,CF_BUFSIZE,"Compressing %s",file); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); printf("COMPRESS %s\n",file); CompressFile(file); if (ptr != NULL) { AddMultipleClasses(ptr->defines); } } umask(maskvalue); Debug("CheckExistingFile(Done)\n"); } /*********************************************************************/ void CheckCopiedFile(char *cf_findertype,char *file,struct stat *dstat,struct stat *sstat,struct Image *ptr) { mode_t newplus,newminus; enum fileactions convert = fixall; struct File tmp; /* plus/minus must be relative to source file, not to perms of newly created file! */ Debug("CheckCopiedFile(%s,+%o,-%o)\n",file,ptr->plus,ptr->minus); newplus = (sstat->st_mode & 07777) | ptr->plus; newminus = ~(newplus & ~(ptr->minus)) & 07777; if (strcmp(ptr->action,"fix") == 0 || strcmp(ptr->action,"silent") == 0) { convert = fixall; } else if (strcmp(ptr->action,"warn") == 0) { convert = warnall; } memset(&tmp,0,sizeof(struct File)); tmp.plus = newplus; tmp.minus = newminus; tmp.action = convert; tmp.classes = ptr->classes; tmp.defines = ptr->defines; tmp.elsedef = ptr->elsedef; tmp.uid = ptr->uid; tmp.gid = ptr->gid; tmp.xdev = ptr->xdev; tmp.checksum = 'n'; CheckExistingFile(cf_findertype,file,dstat,&tmp); } #ifdef DARWIN /*********************************************************************/ int CheckFinderType(char *file,enum fileactions action,char *cf_findertype, struct stat *statbuf) { /* Code modeled after hfstar's extract.c */ typedef struct t_fndrinfo { long fdType; long fdCreator; short fdFlags; short fdLocationV; short fdLocationH; short fdFldr; short fdIconID; short fdUnused[3]; char fdScript; char fdXFlags; short fdComment; long fdPutAway; } FInfo; struct attrlist attrs; struct { long ssize; struct timespec created; struct timespec modified; struct timespec changed; struct timespec backup; FInfo fi; } fndrInfo; int retval; Debug("CheckFinderType of %s for %s\n", file, cf_findertype); if (strncmp(cf_findertype, "*", CF_BUFSIZE) == 0 || strncmp(cf_findertype, "", CF_BUFSIZE) == 0) { /* No checking - no action */ Debug("CheckFinderType not needed\n"); return 0; } attrs.bitmapcount = ATTR_BIT_MAP_COUNT; attrs.reserved = 0; attrs.commonattr = ATTR_CMN_CRTIME | ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | ATTR_CMN_BKUPTIME | ATTR_CMN_FNDRINFO; attrs.volattr = 0; attrs.dirattr = 0; attrs.fileattr = 0; attrs.forkattr = 0; memset(&fndrInfo, 0, sizeof(fndrInfo)); getattrlist(file, &attrs, &fndrInfo, sizeof(fndrInfo),0); if (fndrInfo.fi.fdType != *(long *)cf_findertype) { /* Need to update Finder Type field */ fndrInfo.fi.fdType = *(long *)cf_findertype; /* Determine action to take */ if (S_ISLNK(statbuf->st_mode) || S_ISDIR(statbuf->st_mode)) { printf("CheckFinderType: Wrong file type for %s -- skipping\n", file); return 0; } if (S_ISREG(statbuf->st_mode) && action == fixdirs) { printf("CheckFinderType: Wrong file type for %s -- skipping\n", file); return 0; } switch (action) { /* Fix it */ case fixplain: case fixdirs: case fixall: case touch: if (DONTDO) { /* well, unless we shouldn't fix it */ printf("CheckFinderType: Dry run. No action taken.\n"); return 0; } /* setattrlist does not take back in the long ssize */ retval = setattrlist(file, &attrs, &fndrInfo.created, 4*sizeof(struct timespec) + sizeof(FInfo), 0); Debug("CheckFinderType setattrlist returned %d\n", retval); if (retval >= 0) { printf("Setting Finder Type code of %s to %s\n", file, cf_findertype); } else { printf("Setting Finder Type code of %s to %s failed!!\n", file, cf_findertype); } return retval; /* Just warn */ case linkchildren: case warnall: case warndirs: case warnplain: printf("Warning: FinderType does not match -- not fixing.\n"); return 0; default: printf("Should never get here. Aroo?\n"); return 0; } } else { Debug("CheckFinderType matched\n"); return 0; } } #endif /*********************************************************************/ int CheckOwner(char *file,struct File *ptr,struct stat *statbuf) { struct passwd *pw; struct group *gp; struct UidList *ulp, *unknownulp; struct GidList *glp, *unknownglp; short uidmatch = false, gidmatch = false; uid_t uid = CF_SAME_OWNER; gid_t gid = CF_SAME_GROUP; Debug("CheckOwner: %d\n",statbuf->st_uid); for (ulp = ptr->uid; ulp != NULL; ulp=ulp->next) { Debug(" uid %d\n",ulp->uid); if (ulp->uid == CF_UNKNOWN_OWNER) /* means not found while parsing */ { unknownulp = MakeUidList(ulp->uidname); /* Will only match one */ if (unknownulp != NULL && statbuf->st_uid == unknownulp->uid) { uid = unknownulp->uid; uidmatch = true; break; } } if (ulp->uid == CF_SAME_OWNER || statbuf->st_uid == ulp->uid) /* "same" matches anything */ { uid = ulp->uid; uidmatch = true; break; } } for (glp = ptr->gid; glp != NULL; glp=glp->next) { if (glp->gid == CF_UNKNOWN_GROUP) /* means not found while parsing */ { unknownglp = MakeGidList(glp->gidname); /* Will only match one */ if (unknownglp != NULL && statbuf->st_gid == unknownglp->gid) { gid = unknownglp->gid; gidmatch = true; break; } } if (glp->gid == CF_SAME_GROUP || statbuf->st_gid == glp->gid) /* "same" matches anything */ { gid = glp->gid; gidmatch = true; break; } } if (uidmatch && gidmatch) { return false; } else { if (! uidmatch) { for (ulp = ptr->uid; ulp != NULL; ulp=ulp->next) { if (ptr->uid->uid != CF_UNKNOWN_OWNER) { Verbose("Setting owner to %d\n",ptr->uid->uid); uid = ptr->uid->uid; /* default is first (not unknown) item in list */ break; } } } if (! gidmatch) { for (glp = ptr->gid; glp != NULL; glp=glp->next) { if (ptr->gid->gid != CF_UNKNOWN_GROUP) { gid = ptr->gid->gid; /* default is first (not unknown) item in list */ break; } } } if (S_ISLNK(statbuf->st_mode) && (ptr->action == fixdirs || ptr->action == fixplain)) { Debug2("File %s incorrect type (link), skipping...\n",file); return false; } if ((S_ISREG(statbuf->st_mode) && ptr->action == fixdirs) || (S_ISDIR(statbuf->st_mode) && ptr->action == fixplain)) { Debug2("File %s incorrect type, skipping...\n",file); return false; } switch (ptr->action) { case fixplain: case fixdirs: case fixall: case create: case touch: if (VERBOSE || DEBUG || D2) { if (uid == CF_SAME_OWNER && gid == CF_SAME_GROUP) { printf("%s: touching %s\n",VPREFIX,file); } else { if (uid != CF_SAME_OWNER) { Debug("(Change owner to uid %d if possible)\n",uid); } if (gid != CF_SAME_GROUP) { Debug("Change group to gid %d if possible)\n",gid); } } } if (! DONTDO && S_ISLNK(statbuf->st_mode)) { #ifdef HAVE_LCHOWN Debug("Using LCHOWN function\n"); if (lchown(file,uid,gid) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot set ownership on link %s!\n",file); CfLog(cflogonly,OUTPUT,"lchown"); } else { return true; } #endif } else if (! DONTDO) { if (!uidmatch) { snprintf(OUTPUT,CF_BUFSIZE,"Owner of %s was %d, setting to %d",file,statbuf->st_uid,uid); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); } if (!gidmatch) { snprintf(OUTPUT,CF_BUFSIZE,"Group of %s was %d, setting to %d",file,statbuf->st_gid,gid); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_CHG); } if (!S_ISLNK(statbuf->st_mode)) { if (chown(file,uid,gid) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot set ownership on file %s!\n",file); CfLog(cflogonly,OUTPUT,"chown"); } else { return true; } } } break; case linkchildren: case warnall: case warndirs: case warnplain: if ((pw = getpwuid(statbuf->st_uid)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is not owned by anybody in the passwd database\n",file); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"(uid = %d,gid = %d)\n",statbuf->st_uid,statbuf->st_gid); CfLog(cferror,OUTPUT,""); break; } if ((gp = getgrgid(statbuf->st_gid)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is not owned by any group in group database\n",file); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); break; } snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is owned by [%s], group [%s]\n",file,pw->pw_name,gp->gr_name); CfLog(cferror,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_WARN); break; } } return false; } /*********************************************************************/ int CheckHomeSubDir(char *testpath,char *tidypath,int recurse) { char *subdirstart, *sp1, *sp2; char buffer[CF_BUFSIZE]; int homelen; Debug("CheckHomeSubDir(%s,%s)\n",testpath,tidypath); if (strncmp(tidypath,"home/",5) == 0) { strcpy(buffer,testpath); for (ChopLastNode(buffer); strlen(buffer) != 0; ChopLastNode(buffer)) { if (IsHomeDir(buffer)) { break; } } homelen = strlen(buffer); if (homelen == 0) /* No homedir */ { return false; } Debug("....CheckHomeSubDir(%s,%s)\n",testpath,tidypath); subdirstart = tidypath + strlen("home"); /* Ptr to start of subdir */ strcpy(buffer,testpath); /* ChopLastNode(buffer); Filename only */ for (sp1 = buffer + homelen + 1; *sp1 != '/' && *sp1 != '\0'; sp1++) /* skip user name dir */ { } sp2 = subdirstart; if (strncmp(sp1,sp2,strlen(sp2)) != 0) { return false; } Debug("CheckHomeSubDir(true)\n"); return(true); } return false; } /**************************************************************/ int FileIsNewer(char *file1,char *file2) /* True if file2 is newer than file 1 */ { struct stat statbuf1, statbuf2; if (stat(file2,&statbuf2) == -1) { CfLog(cferror,"","stat"); return false; } if (stat(file1,&statbuf1) == -1) { CfLog(cferror,"","stat"); return true; } if (statbuf1.st_mtime < statbuf2.st_mtime) { return true; } else { return false; } } /*********************************************************************/ void LogChecksumChange(char *file) { FILE *fp; char fname[CF_BUFSIZE],timebuf[CF_MAXVARSIZE]; time_t now = time(NULL); /* This is inefficient but we don't want to lose any data */ snprintf(fname,CF_BUFSIZE,"%s/state/file_hash_event_history",CFWORKDIR); if ((fp = fopen(fname,"a")) == NULL) { CfLog(cferror,"Could not write to the change log",""); return; } snprintf(timebuf,CF_MAXVARSIZE-1,"%s",ctime(&now)); Chop(timebuf); fprintf(fp,"%s,%s\n",timebuf,file); fclose(fp); } /*********************************************************************/ /* Used by files and tidy modules */ /*********************************************************************/ int IgnoreFile (char *pathto,char *name,struct Item *ignores) { struct Item *ip; Debug("IgnoreFile(%s,%s)\n",pathto,name); if (name == NULL || strlen(name) == 0) { return false; } strncpy(VBUFF,pathto,CF_BUFSIZE-1); AddSlash(VBUFF); strcat(VBUFF,name); if (ignores != NULL) { if (IsWildItemIn(ignores,VBUFF)) { Debug("cfengine: Ignoring private abs path [%s][%s]\n",pathto,name); return true; } if (IsWildItemIn(ignores,name)) { Debug("cfengine: Ignoring private pattern [%s][%s]\n",pathto,name); return true; } } for (ip = VIGNORE; ip != NULL; ip=ip->next) { if (IsExcluded(ip->classes)) { continue; } if (*(ip->name) == '/') { if (strcmp(VBUFF,ip->name) == 0) { Debug("cfengine: Ignoring global abs path [%s][%s]\n",pathto,name); return true; } } else { if (WildMatch(ip->name,name)) { Debug("cfengine: Ignoring global pattern [%s][%s]\n",pathto,name); return true; } } } return false; } /*********************************************************************/ void CompressFile(char *file) { char comm[CF_BUFSIZE]; FILE *pp; if ((COMPRESSCOMMAND == NULL) || strlen(COMPRESSCOMMAND) == 0) { CfLog(cferror,"CompressCommand variable is not defined",""); return; } snprintf(comm,CF_BUFSIZE,"%s %s",COMPRESSCOMMAND,file); snprintf(OUTPUT,CF_BUFSIZE*2,"Compressing file %s",file); CfLog(cfinform,OUTPUT,""); if ((pp=cfpopen(comm,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Compression command failed on %s",file); CfLog(cfverbose,OUTPUT,""); } while (!feof(pp)) { ReadLine(VBUFF,CF_BUFSIZE,pp); CfLog(cfinform,VBUFF,""); } cfpclose(pp); } cfengine-2.2.10/src/do.c0000644000175000001440000030665711154771014011646 00000000000000/* Copyright (C) 1995-2000 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: do.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*******************************************************************/ void GetHomeInfo() { DIR *dirh; struct dirent *dirp; struct Item *ip; char path[CF_BUFSIZE],mountitem[CF_BUFSIZE]; if (!IsPrivileged()) { Debug("Not root, so skipping GetHomeInfo()\n"); return; } if (!MountPathDefined()) { return; } for (ip = VMOUNTLIST; ip != NULL; ip=ip->next) { if (IsExcluded(ip->classes)) { continue; } if ((dirh = opendir(ip->name)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"INFO: Host %s seems to have no (additional) local disks except the OS\n",VDEFAULTBINSERVER.name); CfLog(cfverbose,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2," mounted under %s\n\n",ip->name); CfLog(cfverbose,OUTPUT,""); return; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,ip->name,NULL)) { continue; } strcpy(VBUFF,ip->name); AddSlash(VBUFF); strcat(VBUFF,dirp->d_name); if (IsHomeDir(VBUFF)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Host defines a home directory %s\n",VBUFF); CfLog(cfverbose,OUTPUT,""); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Host defines a potential mount point %s\n",VBUFF); CfLog(cfverbose,OUTPUT,""); } snprintf(path,CF_BUFSIZE,"%s%s",ip->name,dirp->d_name); snprintf(mountitem,CF_BUFSIZE,"%s:%s",VDEFAULTBINSERVER.name,path); if (! IsItemIn(VMOUNTED,mountitem)) { if ( MOUNTCHECK && ! RequiredFileSystemOkay(path) && VERBOSE) { snprintf(OUTPUT,CF_BUFSIZE*2,"Found a mountpoint %s but there was\n",path); CfLog(cfinform,OUTPUT,""); CfLog(cfinform,"nothing mounted on it.\n\n",""); } } } closedir(dirh); } } /*******************************************************************/ void GetMountInfo () /* This is, in fact, the most portable way to read the mount info! */ /* Depressing, isn't it? */ { FILE *pp; char buf1[CF_BUFSIZE],buf2[CF_BUFSIZE],buf3[CF_BUFSIZE]; char host[CF_MAXVARSIZE], mounton[CF_BUFSIZE]; int i; if (!GetLock(ASUniqueName("mountinfo"),"",1,VEXPIREAFTER,VUQNAME,CFSTARTTIME)) { return; } /* sscanf(VMOUNTCOMM[VSYSTEMHARDCLASS],"%s",buf1); */ /* Old BSD scanf crashes here! Why!? workaround: */ for (i=0; VMOUNTCOMM[VSYSTEMHARDCLASS][i] != ' '; i++) { buf1[i] = VMOUNTCOMM[VSYSTEMHARDCLASS][i]; } buf1[i] = '\0'; SetTimeOut(RPCTIMEOUT); if ((pp = cfpopen(buf1,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: Can't open %s\n",VPREFIX,buf1); CfLog(cferror,OUTPUT,"popen"); return; } do { VBUFF[0] = buf1[0] = buf2[0] = buf3[0] = '\0'; if (ferror(pp)) /* abortable */ { GOTMOUNTINFO = false; CfLog(cferror,"Error getting mount info\n","ferror"); break; } ReadLine(VBUFF,CF_BUFSIZE,pp); if (ferror(pp)) /* abortable */ { GOTMOUNTINFO = false; CfLog(cferror,"Error getting mount info\n","ferror"); break; } sscanf(VBUFF,"%s%s%s",buf1,buf2,buf3); if (VBUFF[0] == '\n') { break; } if (strstr(VBUFF,"not responding")) { printf("%s: %s\n",VPREFIX,VBUFF); } if (strstr(VBUFF,"be root")) { CfLog(cferror,"Mount access is denied. You must be root.\n",""); CfLog(cferror,"Use the -n option to run safely.",""); } if (strstr(VBUFF,"retrying") || strstr(VBUFF,"denied") || strstr(VBUFF,"backgrounding")) { continue; } if (strstr(VBUFF,"exceeded") || strstr(VBUFF,"busy")) { continue; } if (strstr(VBUFF,"RPC")) { if (! SILENT) { CfLog(cfinform,"There was an RPC timeout. Aborting mount operations.\n",""); CfLog(cfinform,"Session failed while trying to talk to remote host\n",""); snprintf(OUTPUT,CF_BUFSIZE*2,"%s\n",VBUFF); CfLog(cfinform,OUTPUT,""); } GOTMOUNTINFO = false; ReleaseCurrentLock(); cfpclose(pp); return; } switch (VSYSTEMHARDCLASS) { case darwin: case sun4: case sun3: case ultrx: case irix: case irix4: case irix64: case linuxx: case GnU: case unix_sv: case freebsd: case netbsd: case openbsd: case bsd_i: case nextstep: case bsd4_3: case newsos: case aos: case osf: case qnx: case crayos: case dragonfly: if (buf1[0] == '/') { strcpy(host,VDEFAULTBINSERVER.name); strcpy(mounton,buf3); } else { sscanf(buf1,"%[^:]",host); strcpy(mounton,buf3); } break; case solaris: case solarisx86: case hp: if (buf3[0] == '/') { strcpy(host,VDEFAULTBINSERVER.name); strcpy(mounton,buf1); } else { sscanf(buf3,"%[^:]",host); strcpy(mounton,buf1); } break; case aix: /* skip header */ if (buf1[0] == '/') { strcpy(host,VDEFAULTBINSERVER.name); strcpy(mounton,buf2); } else { strcpy(host,buf1); strcpy(mounton,buf3); } break; case cfnt: strcpy(mounton,buf2); strcpy(host,buf1); break; case unused2: case unused3: break; case cfsco: CfLog(cferror,"Don't understand SCO mount format, no data",""); default: printf("cfengine software error: case %d = %s\n",VSYSTEMHARDCLASS,CLASSTEXT[VSYSTEMHARDCLASS]); FatalError("System error in GetMountInfo - no such class!"); } InstallMountedItem(host,mounton); } while (!feof(pp)); alarm(0); signal(SIGALRM,SIG_DFL); ReleaseCurrentLock(); cfpclose(pp); } /*******************************************************************/ void MakePaths() { struct File *ptr; struct Item *ip1,*ip2; char pathbuff[CF_BUFSIZE],basename[CF_EXPANDSIZE]; for (ptr = VMAKEPATH; ptr != NULL; ptr=ptr->next) { if (IsExcluded(ptr->classes)) { continue; } if (ptr->done == 'y' || strcmp(ptr->scope,CONTEXTID)) { continue; } else { ptr->done = 'y'; } ResetOutputRoute(ptr->log,ptr->inform); if (strncmp(ptr->path,"home/",5) == 0) /* home/subdir */ { if (*(ptr->path+4) != '/') { snprintf(OUTPUT,CF_BUFSIZE*2,"Illegal use of home in directories: %s\n",ptr->path); CfLog(cferror,OUTPUT,""); continue; } for (ip1 = VHOMEPATLIST; ip1 != NULL; ip1=ip1->next) { for (ip2 = VMOUNTLIST; ip2 != NULL; ip2=ip2->next) { if (IsExcluded(ip2->classes)) { continue; } pathbuff[0]='\0'; basename[0]='\0'; strcpy(pathbuff,ip2->name); AddSlash(pathbuff); strcat(pathbuff,ip1->name); AddSlash(pathbuff); strcat(pathbuff,"*/"); strcat(pathbuff,ptr->path+5); ExpandWildCardsAndDo(pathbuff,basename,DirectoriesWrapper,ptr); } } } else { Verbose("MakePath(%s)\n",ptr->path); pathbuff[0]='\0'; basename[0]='\0'; ExpandWildCardsAndDo(ptr->path,basename,DirectoriesWrapper,ptr); } ResetOutputRoute('d','d'); } } /*******************************************************************/ void MakeChildLinks() /* should expand to a best fit filesys */ { struct Link *lp; struct Item *ip; int matched,varstring; char to[CF_EXPANDSIZE],from[CF_EXPANDSIZE],path[CF_EXPANDSIZE]; struct stat statbuf; short saveenforce; short savesilent; if (NOLINKS) { return; } ACTION = links; for (lp = VCHLINK; lp != NULL; lp = lp->next) { if (IsExcluded(lp->classes)) { continue; } if (lp->done == 'y' || strcmp(lp->scope,CONTEXTID)) { continue; } else { lp->done = 'y'; } snprintf(VBUFF,CF_BUFSIZE,"%.50s.%.50s",lp->from,lp->to); /* Unique ID for copy locking */ if (!GetLock(ASUniqueName("link"),CanonifyName(VBUFF),lp->ifelapsed,lp->expireafter,VUQNAME,CFSTARTTIME)) { lp->done = 'y'; continue; } ExpandVarstring(lp->from,from,NULL); ExpandVarstring(lp->to,to,NULL); saveenforce = ENFORCELINKS; ENFORCELINKS = ENFORCELINKS || (lp->force == 'y'); savesilent = SILENT; SILENT = SILENT || lp->silent; ResetOutputRoute(lp->log,lp->inform); matched = varstring = false; for(ip = VBINSERVERS; ip != NULL && (!matched); ip = ip->next) { path[0] = '\0'; if (strcmp(to,"linkchildren") == 0) /* linkchildren */ { if (stat(from,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Makechildlinks() can't stat %s\n",from); CfLog(cferror,OUTPUT,"stat"); ResetOutputRoute('d','d'); continue; } LinkChildren(from,lp->type,&statbuf,0,0,lp); break; } varstring = ExpandVarbinserv(to,path,ip->name); if (lp->recurse != 0) { matched = RecursiveLink(lp,from,path,lp->recurse); } else if (LinkChildFiles(from,path,lp)) { matched = true; } else if (! varstring) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error while trying to childlink %s -> %s\n",from,path); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"The directory %s does not exist. Can't link.\n",path); CfLog(cferror,OUTPUT,""); AuditLog(lp->logaudit,lp->audit,lp->lineno,OUTPUT,CF_FAIL); } if (! varstring) /* don't iterate over binservers if not var */ { ReleaseCurrentLock(); break; } } ENFORCELINKS = saveenforce; SILENT = savesilent; ResetOutputRoute('d','d'); if (matched == false && ip == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"ChildLink didn't find any server to match %s -> %s\n",from,to); CfLog(cferror,OUTPUT,""); AuditLog(lp->logaudit,lp->audit,lp->lineno,OUTPUT,CF_FAIL); } ReleaseCurrentLock(); } } /*******************************************************************/ void MakeLinks() /* should expand to a best fit filesys */ { struct Link *lp; char from[CF_EXPANDSIZE],to[CF_EXPANDSIZE],path[CF_EXPANDSIZE]; struct Item *ip; int matched,varstring; short saveenforce, savekilloldlinks; short savesilent; int (*linkfiles)(char *from, char *to,struct Link *ptr); if (NOLINKS) { return; } ACTION = links; for (lp = VLINK; lp != NULL; lp = lp->next) { if (IsExcluded(lp->classes)) { continue; } if (lp->done == 'y' || strcmp(lp->scope,CONTEXTID)) { continue; } else { lp->done = 'y'; } snprintf(VBUFF,CF_BUFSIZE,"%.50s.%.50s",lp->from,lp->to); /* Unique ID for copy locking */ if (!GetLock(ASUniqueName("link"),CanonifyName(VBUFF),lp->ifelapsed,lp->expireafter,VUQNAME,CFSTARTTIME)) { lp->done = 'y'; continue; } ExpandVarstring(lp->from,from,NULL); ExpandVarstring(lp->to,to,NULL); ResetOutputRoute(lp->log,lp->inform); switch (lp->type) { case 's': linkfiles = LinkFiles; break; case 'r': linkfiles = RelativeLink; break; case 'a': linkfiles = AbsoluteLink; break; case 'h': linkfiles = HardLinkFiles; break; default: printf("%s: internal error, link type was [%c]\n",VPREFIX,lp->type); ReleaseCurrentLock(); continue; } saveenforce = ENFORCELINKS; ENFORCELINKS = ENFORCELINKS || (lp->force == 'y'); savekilloldlinks = KILLOLDLINKS; KILLOLDLINKS = KILLOLDLINKS || lp->nofile; savesilent = SILENT; SILENT = SILENT || lp->silent; matched = varstring = false; for(ip = VBINSERVERS; ip != NULL && (!matched); ip = ip->next) { path[0] = '\0'; varstring = ExpandVarbinserv(to,path,ip->name); if ((*linkfiles)(from,path,lp)) { matched = true; } else if (! varstring) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error while trying to link %s -> %s\n",from,path); CfLog(cfinform,OUTPUT,""); AuditLog(lp->logaudit,lp->audit,lp->lineno,OUTPUT,CF_FAIL); } if (! varstring) /* don't iterate over binservers if not var */ { break; } } ENFORCELINKS = saveenforce; KILLOLDLINKS = savekilloldlinks; SILENT = savesilent; ResetOutputRoute('d','d'); if (matched == false && ip == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Links didn't find any file to match %s -> %s\n",from,to); CfLog(cferror,OUTPUT,""); AuditLog(lp->logaudit,lp->audit,lp->lineno,OUTPUT,CF_FAIL); } ReleaseCurrentLock(); } } /*******************************************************************/ void MailCheck() { char mailserver[CF_BUFSIZE]; char mailhost[CF_MAXVARSIZE]; char rmailpath[CF_BUFSIZE]; char lmailpath[CF_BUFSIZE]; if (!GetLock("Mailcheck",CanonifyName(VFSTAB[VSYSTEMHARDCLASS]),0,VEXPIREAFTER,VUQNAME,CFSTARTTIME)) { return; } if (VMAILSERVER[0] == '\0') { FatalError("Program does not define a mailserver for this host"); } if (!IsPrivileged()) { CfLog(cferror,"Only root can alter the mail configuration.\n",""); ReleaseCurrentLock(); return; } sscanf (VMAILSERVER,"%[^:]:%s",mailhost,rmailpath); if (VMAILSERVER[0] == '\0') { CfLog(cfinform,"\n%s: Host has no defined mailserver!\n",""); ReleaseCurrentLock(); return; } if (strcmp(VDEFAULTBINSERVER.name,mailhost) == 0) /* Is this the mailserver ?*/ { ExpiredUserCheck(rmailpath,false); ReleaseCurrentLock(); return; } snprintf(lmailpath,CF_BUFSIZE,"%s:%s",mailhost,VMAILDIR[VSYSTEMHARDCLASS]); if (IsItemIn(VMOUNTED,lmailpath)) /* Remote file system mounted on */ { /* local mail dir - correct */ Verbose("%s: Mail spool area looks ok\n",VPREFIX); ReleaseCurrentLock(); return; } strcpy(mailserver,VMAILDIR[VSYSTEMHARDCLASS]); AddSlash(mailserver); strcat(mailserver,"."); MakeDirectoriesFor(mailserver,'n'); /* Check directory is in place */ if (IsItemIn(VMOUNTED,VMAILSERVER)) { if (!SILENT) { Verbose("%s: Warning - the mail directory seems to be mounted as on\n",VPREFIX); Verbose("%s: the remote mailserver and not on the correct local directory\n",VPREFIX); Verbose("%s: Should strictly mount on %s\n",VPREFIX,VMAILDIR[VSYSTEMHARDCLASS]); } ReleaseCurrentLock(); return; } if (MatchStringInFstab("mail")) { if (!SILENT) { Verbose("%s: Warning - the mail directory seems to be mounted\n",VPREFIX); Verbose("%s: in a funny way. I can find the string in %s\n",VPREFIX,VFSTAB[VSYSTEMHARDCLASS]); Verbose("%s: but nothing is mounted on %s\n\n",VPREFIX,VMAILDIR[VSYSTEMHARDCLASS]); } ReleaseCurrentLock(); return; } printf("\n%s: Trying to mount %s\n",VPREFIX,VMAILSERVER); if (! DONTDO) { AddToFstab(mailhost,rmailpath,VMAILDIR[VSYSTEMHARDCLASS],"rw",NULL,false); } else { printf("%s: Need to mount %s:%s on %s\n",VPREFIX,mailhost,rmailpath,mailserver); } ReleaseCurrentLock(); } /*******************************************************************/ void ExpiredUserCheck(char *spooldir,int always) { Verbose("%s: Checking for expired users in %s\n",VPREFIX,spooldir); if (always || (strncmp(VMAILSERVER,VFQNAME,strlen(VMAILSERVER)) != 0)) { DIR *dirh; struct dirent *dirp; struct stat statbuf; if ((dirh = opendir(spooldir)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open spool directory %s",spooldir); CfLog(cfverbose,OUTPUT,"opendir"); return; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,spooldir,NULL)) { continue; } strcpy(VBUFF,spooldir); AddSlash(VBUFF); strcat(VBUFF,dirp->d_name); if (stat(VBUFF,&statbuf) != -1) { if (getpwuid(statbuf.st_uid) == NULL) { if (TrueVar("WarnNonOwnerMail")||TrueVar("WarnNonOwnerFiles")) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s in spool dir %s is not owned by any user",dirp->d_name,spooldir); CfLog(cferror,OUTPUT,""); } if (TrueVar("DeleteNonOwnerMail")||TrueVar("DeleteNonOwnerFiles")) { if (DONTDO) { printf("%s: Delete file %s\n",VPREFIX,VBUFF); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Deleting file %s in spool dir %s not owned by any user",dirp->d_name,spooldir); CfLog(cferror,OUTPUT,""); if (unlink(VBUFF) == -1) { CfLog(cferror,"","unlink"); } } } } } if (strstr(dirp->d_name,"lock") || strstr(dirp->d_name,".tmp")) { Verbose("Ignoring non-user file %s\n",dirp->d_name); continue; } if (getpwnam(dirp->d_name) == NULL) { if (TrueVar("WarnNonUserMail")||TrueVar("WarnNonUserFiles")) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s in spool dir %s is not the name of a user",dirp->d_name,spooldir); CfLog(cferror,OUTPUT,""); } if (TrueVar("DeleteNonUserMail")||TrueVar("DeleteNonUserFiles")) { if (DONTDO) { printf("%s: Delete file %s\n",VPREFIX,VBUFF); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Deleting file %s in spool dir %s (not a username)",dirp->d_name,spooldir); CfLog(cferror,OUTPUT,""); if (unlink(VBUFF) == -1) { CfLog(cferror,"","unlink"); } } } } } closedir(dirh); snprintf(OUTPUT,CF_BUFSIZE,"Done checking spool directory %s\n",spooldir); Verbose("%s",OUTPUT); AuditLog('y',NULL,0,OUTPUT,CF_NOP); } } /*******************************************************************/ void MountFileSystems() { FILE *pp; int fd; struct stat statbuf; if (! GOTMOUNTINFO || DONTDO) { return; } if (!IsPrivileged()) { CfLog(cferror,"Only root can mount filesystems.\n",""); return; } if (!GetLock(ASUniqueName("domount"),"",VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME)) { return; } if (VSYSTEMHARDCLASS == cfnt) { /* This is a shell script. Make sure it hasn't been compromised. */ if (stat("/etc/fstab",&statbuf) == -1) { if ((fd = creat("/etc/fstab",0755)) > 0) { write(fd,"#!/bin/sh\n\n",10); close(fd); } else { if (statbuf.st_mode & (S_IWOTH | S_IWGRP)) { CfLog(cferror,"File /etc/fstab was insecure. Cannot mount filesystems.\n",""); GOTMOUNTINFO = false; return; } } } } SetTimeOut(RPCTIMEOUT); if ((pp = cfpopen(VMOUNTCOMM[VSYSTEMHARDCLASS],"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Failed to open pipe from %s\n",VMOUNTCOMM[VSYSTEMHARDCLASS]); CfLog(cferror,OUTPUT,"popen"); ReleaseCurrentLock(); return; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { CfLog(cfinform,"Error mounting filesystems\n","ferror"); AuditLog('y',NULL,0,"Error mounting filesystems",CF_FAIL); break; } ReadLine(VBUFF,CF_BUFSIZE,pp); if (ferror(pp)) /* abortable */ { CfLog(cfinform,"Error mounting filesystems\n","ferror"); AuditLog('y',NULL,0,"Error mounting filesystems",CF_FAIL); break; } if (strstr(VBUFF,"already mounted") || strstr(VBUFF,"exceeded") || strstr(VBUFF,"determined")) { continue; } if (strstr(VBUFF,"not supported")) { continue; } if (strstr(VBUFF,"denied") || strstr(VBUFF,"RPC")) { CfLog(cfinform,"There was a mount error, trying to mount one of the filesystems on this host.\n",""); snprintf(OUTPUT,CF_BUFSIZE*2,"%s\n",VBUFF); CfLog(cfinform,OUTPUT,""); GOTMOUNTINFO = false; AuditLog('y',NULL,0,"Error mounting filesystems",CF_FAIL); break; } if (strstr(VBUFF,"trying") && !strstr(VBUFF,"NFS version 2")&& !strstr(VBUFF, "vers 3")) { CfLog(cferror,"Aborted because MountFileSystems() went into a retry loop.\n",""); GOTMOUNTINFO = false; AuditLog('y',NULL,0,"Error mounting filesystems - retry loop",CF_FAIL); break; } } alarm(0); signal(SIGALRM,SIG_DFL); cfpclose(pp); ReleaseCurrentLock(); } /*******************************************************************/ void CheckRequired() { struct Disk *rp; struct Item *ip; int matched=0,varstring=0,missing = 0; char path[CF_EXPANDSIZE],expand[CF_EXPANDSIZE]; ACTION=required; for (rp = VREQUIRED; rp != NULL; rp = rp->next) { if (IsExcluded(rp->classes)) { continue; } if (rp->done == 'y' || strcmp(rp->scope,CONTEXTID)) { continue; } else { rp->done = 'y'; } if (!GetLock(ASUniqueName("disks"),rp->name,rp->ifelapsed,rp->expireafter,VUQNAME,CFSTARTTIME)) { rp->done = 'y'; continue; } ResetOutputRoute(rp->log,rp->inform); matched = varstring = false; for(ip = VBINSERVERS; ip != NULL && (!matched); ip = ip->next) { ExpandVarstring(rp->name,expand,NULL); varstring = ExpandVarbinserv(expand,path,ip->name); if (RequiredFileSystemOkay(path)) /* simple or reduced item */ { Verbose("Filesystem %s looks sensible\n",path); matched = true; if (rp->freespace == -1) { AddMultipleClasses(rp->elsedef); } } else if (! varstring) { snprintf(OUTPUT,CF_BUFSIZE*2,"The file %s does not exist or is suspicious.\n\n",path); CfLog(cferror,OUTPUT,""); /* Define the class if there was no freespace option. */ if (rp->freespace == -1) { AddMultipleClasses(rp->define); } } if (! varstring) /* don't iterate over binservers if not var */ { break; } } if ((rp->freespace != -1)) { /* HvB : Bas van der Vlies */ if (!CheckFreeSpace(path,rp)) { snprintf(OUTPUT,CF_BUFSIZE,"Free space below %d, defining %s\n",rp->freespace, rp->define); CfLog(cfinform,OUTPUT,""); AddMultipleClasses(rp->define); } else { snprintf(OUTPUT,CF_BUFSIZE,"Free space above %d, defining %s\n",rp->freespace, rp->elsedef); CfLog(cfverbose,OUTPUT,""); AddMultipleClasses(rp->elsedef); } } if (matched == false && ip == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Didn't find any file to match the required filesystem %s\n",rp->name); CfLog(cferror,OUTPUT,""); AuditLog(rp->logaudit,rp->audit,rp->lineno,"OUTPUT",CF_WARN); missing++; } ReleaseCurrentLock(); ResetOutputRoute('d','d'); } if (missing) { time_t tloc; if ((tloc = time((time_t *)NULL)) == -1) { printf("Couldn't read system clock\n"); } snprintf(OUTPUT,CF_BUFSIZE*2,"MESSAGE at %s\n\n",ctime(&tloc)); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"There are %d required file(system)s missing on host <%s>\n",missing,VDEFAULTBINSERVER.name); CfLog(cferror,OUTPUT,""); CfLog(cferror,"even after all mounts have been attempted.\n",""); CfLog(cferror,"This may be caused by a failure to mount a network filesystem (check exports)\n",""); snprintf(OUTPUT,CF_BUFSIZE*2,"or because no valid server was specified in the program %s\n\n",VINPUTFILE); CfLog(cferror,OUTPUT,""); } /* Look for any statistical gathering to be scheduled ... */ if (IGNORELOCK) /* This is too heavy to allow without locks */ { return; } Verbose("Checking for filesystem scans...\n"); for (rp = VREQUIRED; rp != NULL; rp = rp->next) { if (IsExcluded(rp->classes)) { continue; } if (rp->scanarrivals != 'y') { continue; } ResetOutputRoute(rp->log,rp->inform); for(ip = VBINSERVERS; ip != NULL && (!matched); ip = ip->next) { struct stat statbuf; DB *dbp = NULL; DB_ENV *dbenv = NULL; char database[CF_MAXVARSIZE],canon[CF_MAXVARSIZE]; int ifelapsed = rp->ifelapsed; if (ifelapsed < CF_WEEK) { Verbose("IfElapsed time is too short for these data - changes only slowly\n"); ifelapsed = CF_WEEK; } ExpandVarstring(rp->name,expand,NULL); varstring = ExpandVarbinserv(expand,path,ip->name); if (lstat(path,&statbuf) == -1) { continue; } if (!GetLock(ASUniqueName("diskscan"),CanonifyName(rp->name),ifelapsed,rp->expireafter,VUQNAME,CFSTARTTIME)) { continue; } snprintf(canon,CF_MAXVARSIZE-1,"%s",CanonifyName(path)); snprintf(database,CF_MAXVARSIZE-1,"%s/scan:%s.db",VLOCKDIR,canon); Verbose("Scanning filesystem %s for arrival processes...to %s\n",path,database); unlink(database); if ((errno = db_create(&dbp,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open checksum database %s\n",CHECKSUMDB); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,database,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,database,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open database %s\n",database); CfLog(cferror,OUTPUT,"db_open"); dbp->close(dbp,0); continue; } chmod(database,0644); RegisterRecursionRootDevice(statbuf.st_dev); ScanFileSystemArrivals(path,0,&statbuf,dbp); dbp->close(dbp,0); ReleaseCurrentLock(); } ResetOutputRoute('d','d'); } } /*******************************************************************/ void TidyFiles() /* Here we start by scanning for any absolute path wildcards */ /* After that's finished, we go snooping around the homedirs */ { char basename[CF_EXPANDSIZE],pathbuff[CF_BUFSIZE]; struct TidyPattern *tlp; struct Tidy *tp; struct Item *ip1,*ip2; int homesearch = false, pathsearch = false; Banner("Tidying Spool Directories"); for (ip1 = SPOOLDIRLIST; ip1 != NULL; ip1=ip1->next) { if (!IsExcluded(ip1->classes)) { ExpiredUserCheck(ip1->name,true); } } Banner("Tidying by directory"); AuditLog('y',NULL,0,"Commence tidy by directory",CF_NOP); for (tp = VTIDY; tp != NULL; tp=tp->next) { if (strncmp(tp->path,"home",4)==0) { for (tlp = tp->tidylist; tlp != NULL; tlp=tlp->next) { if (!IsExcluded(tlp->classes)) { homesearch = 1; break; } } continue; } pathsearch = false; for (tlp = tp->tidylist; tlp != NULL; tlp=tlp->next) { if (IsExcluded(tlp->classes)) { continue; } pathsearch = true; } if (pathsearch && (tp->done == 'n')) { Debug("\nTidying from base directory %s\n",tp->path); basename[0] = '\0'; ExpandWildCardsAndDo(tp->path,basename,TidyWrapper,tp); tp->done = 'y'; if (tp->tidylist->next != NULL) { tp->done = 'n'; } else { tp->done = 'y'; } } else { Debug("\nNo patterns active in base directory %s\n",tp->path); } } Debug2("End PATHTIDY:\n"); if (!homesearch) /* If there are "home" wildcards */ { /* Don't go rummaging around the disks */ Verbose("No home patterns to search\n"); AuditLog('y',NULL,0,"Finished tidy by directory, no home patterns to search",CF_NOP); return; } Banner("Tidying home directories"); AuditLog('y',NULL,0,"Commence tidy home directories",CF_NOP); if (!IsPrivileged()) { CfLog(cferror,"Only root can delete others' files.\n",""); return; } if (!MountPathDefined()) { return; } for (ip1 = VHOMEPATLIST; ip1 != NULL; ip1=ip1->next) { for (ip2 = VMOUNTLIST; ip2 != NULL; ip2=ip2->next) { if (IsExcluded(ip2->classes)) { continue; } pathbuff[0]='\0'; basename[0]='\0'; strcpy(pathbuff,ip2->name); AddSlash(pathbuff); strcat(pathbuff,ip1->name); ExpandWildCardsAndDo(pathbuff,basename,RecHomeTidyWrapper,NULL); } } Verbose("Done with home directories\n"); AuditLog('y',NULL,0,"Finished tidy home patterns",CF_NOP); } /*******************************************************************/ void Scripts() { struct ShellComm *ptr; char line[CF_BUFSIZE],eventname[CF_BUFSIZE]; char comm[20], *sp; char execstr[CF_EXPANDSIZE]; char chdir_buf[CF_EXPANDSIZE]; char chroot_buf[CF_EXPANDSIZE]; struct timespec start,stop; int measured_ok = true; double dt = 0; int print, outsourced; mode_t maskval = 0; FILE *pp; int preview = false; for (ptr = VSCRIPT; ptr != NULL; ptr=ptr->next) { preview = (ptr->preview == 'y'); if (IsExcluded(ptr->classes)) { continue; } if (ptr->done == 'y' || strcmp(ptr->scope,CONTEXTID)) { continue; } else { ptr->done = 'y'; } ResetOutputRoute(ptr->log,ptr->inform); ExpandVarstring(ptr->name,execstr,NULL); if (!GetLock(ASUniqueName("shellcommand"),execstr,ptr->ifelapsed,ptr->expireafter,VUQNAME,CFSTARTTIME)) { ptr->done = 'y'; continue; } snprintf(OUTPUT,CF_BUFSIZE*2,"\nExecuting script %s...(timeout=%d,uid=%d,gid=%d)\n",execstr,ptr->timeout,ptr->uid,ptr->gid); CfLog(cfinform,OUTPUT,""); if (clock_gettime(CLOCK_REALTIME, &start) == -1) { CfLog(cfverbose,"Clock gettime failure","clock_gettime"); measured_ok = false; } if (DONTDO && preview != 'y') { printf("%s: execute script %s\n",VPREFIX,execstr); } else { for (sp = execstr; *sp != ' ' && *sp != '\0'; sp++) { } if (sp - 10 >= execstr) { sp -= 10; /* copy 15 most relevant characters of command */ } else { sp = execstr; } memset(comm,0,20); strncpy(comm,sp,15); if (ptr->fork == 'y') { Verbose("Backgrounding job %s\n",execstr); outsourced = fork(); if (outsourced == 0) ALARM_PID = -1; } else { outsourced = false; } if (outsourced || ptr->fork != 'y') { if (ptr->timeout != 0) { SetTimeOut(ptr->timeout); } Verbose("(Setting umask to %o)\n",ptr->umask); maskval = umask(ptr->umask); if (ptr->umask == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Programming %s running with umask 0! Use umask= to set\n",execstr); CfLog(cfsilent,OUTPUT,""); } ExpandVarstring(ptr->chdir,chdir_buf,""); ExpandVarstring(ptr->chroot,chroot_buf,""); switch (ptr->useshell) { case 'y': pp = cfpopen_shsetuid(execstr,"r",ptr->uid,ptr->gid,chdir_buf,chroot_buf); break; default: pp = cfpopensetuid(execstr,"r",ptr->uid,ptr->gid,chdir_buf,chroot_buf); break; } if (pp == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open pipe to command %s\n",execstr); CfLog(cferror,OUTPUT,"popen"); ResetOutputRoute('d','d'); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_FAIL); ReleaseCurrentLock(); continue; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_TIMEX); break; } ReadLine(line,CF_BUFSIZE-1,pp); if (strstr(line,"cfengine-die")) { break; } if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_TIMEX); break; } if (preview == 'y') { /* * Preview script - try to parse line as log message. If line does * not parse, then log as error. */ int i; int level = cferror; char *message = line; /* * Table matching cfoutputlevel enums to log prefixes. */ char *prefixes[] = { ":silent:", ":inform:", ":verbose:", ":editverbose:", ":error:", ":logonly:", }; int precount = sizeof(prefixes)/sizeof(char *); if (line[0] == ':') { /* * Line begins with colon - see if it matches a log prefix. */ for (i = 0; i < precount; i++) { int prelen = 0; prelen = strlen(prefixes[i]); if (strncmp(line, prefixes[i], prelen) == 0) { /* * Found log prefix - set logging level, and remove the * prefix from the log message. */ level = i; message += prelen; break; } } } snprintf(OUTPUT,CF_BUFSIZE,"%s (preview of %s)\n",message,comm); CfLog(level,OUTPUT,""); } else { /* * Dumb script - echo non-empty lines to standard output. */ print = false; for (sp = line; *sp != '\0'; sp++) { if (! isspace((int)*sp)) { print = true; break; } } if (print) { printf("%s:%s: %s\n",VPREFIX,comm,line); } } } cfpclose_def(pp,ptr->defines,ptr->elsedef); } if (ptr->timeout != 0) { alarm(0); signal(SIGALRM,SIG_DFL); } umask(maskval); snprintf(OUTPUT,CF_BUFSIZE*2,"Finished script %s\n",execstr); CfLog(cfinform,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_REGULAR); ResetOutputRoute('d','d'); ReleaseCurrentLock(); if (clock_gettime(CLOCK_REALTIME, &stop) == -1) { CfLog(cfverbose,"Clock gettime failure","clock_gettime"); measured_ok = false; } dt = (double)(stop.tv_sec - start.tv_sec)+(double)(stop.tv_nsec-start.tv_nsec)/(double)CF_BILLION; snprintf(eventname,CF_BUFSIZE-1,"Exec(%s)",execstr); if (measured_ok) { RecordPerformance(eventname,start.tv_sec,dt); } if (ptr->fork == 'y' && outsourced) { Verbose("Backgrounded shell command (%s) exiting\n",execstr); exit(0); } } } } /*******************************************************************/ void GetSetuidLog() { struct Item *filetop = NULL; struct Item *ip; FILE *fp; char *sp; if (!IsPrivileged()) /* Ignore this if not root */ { return; } if ((fp = fopen(VSETUIDLOG,"r")) == NULL) { } else { while (!feof(fp)) { ReadLine(VBUFF,CF_BUFSIZE,fp); if (strlen(VBUFF) == 0) { continue; } if ((ip = (struct Item *)malloc (sizeof(struct Item))) == NULL) { perror("malloc"); FatalError("GetSetuidList() couldn't allocate memory #1"); } if ((sp = malloc(strlen(VBUFF)+2)) == NULL) { perror("malloc"); FatalError("GetSetuidList() couldn't allocate memory #2"); } if (filetop == NULL) { VSETUIDLIST = filetop = ip; } else { filetop->next = ip; } Debug2("SETUID-LOG: %s\n",VBUFF); strcpy(sp,VBUFF); ip->name = sp; ip->next = NULL; filetop = ip; } fclose(fp); } } /*******************************************************************/ void CheckFiles() /* Check through file systems */ { struct File *ptr; char ebuff[CF_EXPANDSIZE]; short savetravlinks = TRAVLINKS; short savekilloldlinks = KILLOLDLINKS; if (TRAVLINKS && (VERBOSE || DEBUG || D2)) { printf("(Default in switched to purge stale links...)\n"); } for (ptr = VFILE; ptr != NULL; ptr=ptr->next) { if (IsExcluded(ptr->classes)) { continue; } if (ptr->done == 'y' || strcmp(ptr->scope,CONTEXTID)) { continue; } else { ptr->done = 'y'; } TRAVLINKS = savetravlinks; if (ptr->travlinks == 'T') { TRAVLINKS = true; } else if (ptr->travlinks == 'F') { TRAVLINKS = false; } else if (ptr->travlinks == 'K') { KILLOLDLINKS = true; } ResetOutputRoute(ptr->log,ptr->inform); if (strncmp(ptr->path,"home",4) == 0) { CheckHome(ptr); continue; } snprintf(OUTPUT,CF_BUFSIZE,"Commence checking file(s) in %s\n",ptr->path); CfLog(cfverbose,OUTPUT,""); AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,OUTPUT,CF_NOP); ebuff[0] = '\0'; ExpandWildCardsAndDo(ptr->path,ebuff,CheckFileWrapper,ptr); ResetOutputRoute('d','d'); TRAVLINKS = savetravlinks; KILLOLDLINKS = savekilloldlinks; } } /*******************************************************************/ void SaveSetuidLog() { FILE *fp; struct Item *ip; if (!IsPrivileged()) /* Ignore this if not root */ { return; } if (! DONTDO) { if ((fp = fopen(VSETUIDLOG,"w")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open %s for writing\n",VSETUIDLOG); CfLog(cferror,OUTPUT,"fopen"); return; } Verbose("Saving the setuid log in %s\n",VSETUIDLOG); for (ip = VSETUIDLIST; ip != NULL; ip=ip->next) { if (!isspace((int)*(ip->name)) && strlen(ip->name) != 0) { fprintf(fp,"%s\n",ip->name); Debug2("SAVE-SETUID-LOG: %s\n",ip->name); } } fclose(fp); chmod(VSETUIDLOG,0600); } } /*******************************************************************/ void DisableFiles() { struct Disable *dp; struct stat statbuf; char workname[CF_EXPANDSIZE],path[CF_BUFSIZE]; for (dp = VDISABLELIST; dp != NULL; dp=dp->next) { if (IsExcluded(dp->classes)) { continue; } if (dp->done == 'y' || strcmp(dp->scope,CONTEXTID)) { continue; } else { dp->done = 'y'; } if (!GetLock(ASUniqueName("disable"),CanonifyName(dp->name),dp->ifelapsed,dp->expireafter,VUQNAME,CFSTARTTIME)) { continue; } dp->done = 'y'; ExpandVarstring(dp->name,workname,NULL); ResetOutputRoute(dp->log,dp->inform); if (lstat(workname,&statbuf) == -1) { Verbose("Filetype %s, %s is not there - ok\n",dp->type,workname); AddMultipleClasses(dp->elsedef); ReleaseCurrentLock(); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_NOP); continue; } if (S_ISDIR(statbuf.st_mode)) { if ((strcmp(dp->type,"file") == 0) || (strcmp(dp->type,"link") == 0)) { Verbose("Filetype %s, %s is not there - ok\n",dp->type,workname); ResetOutputRoute('d','d'); ReleaseCurrentLock(); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_NOP); continue; } } Verbose("Disable/rename checking %s\n",workname); if (S_ISLNK(statbuf.st_mode)) { if (strcmp(dp->type,"file") == 0) { Verbose("%s: %s is a link, not disabling\n",VPREFIX,workname); ResetOutputRoute('d','d'); ReleaseCurrentLock(); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_NOP); continue; } memset(VBUFF,0,CF_BUFSIZE); if (readlink(workname,VBUFF,CF_BUFSIZE-1) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"DisableFiles() can't read link %s\n",workname); CfLog(cferror,OUTPUT,"readlink"); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_FAIL); ResetOutputRoute('d','d'); ReleaseCurrentLock(); continue; } if (dp->action == 'd') { snprintf(OUTPUT,CF_BUFSIZE,"Deleting link %s -> %s\n",workname,VBUFF); CfLog(cfinform,OUTPUT,""); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_CHG); if (! DONTDO) { if (unlink(workname) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error while unlinking %s\n",workname); CfLog(cferror,OUTPUT,"unlink"); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_FAIL); ResetOutputRoute('d','d'); ReleaseCurrentLock(); continue; } AddMultipleClasses(dp->defines); } } else { snprintf(OUTPUT,CF_BUFSIZE,"Warning - file %s exists\n",workname); CfLog(cferror,OUTPUT,""); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_WARN); } } else { if (!S_ISREG(statbuf.st_mode) && (strlen(dp->destination) == 0)) { snprintf(OUTPUT,CF_BUFSIZE,"%s: %s is not a plain file - won't rename/disable without specific destination\n",VPREFIX,workname); CfLog(cfverbose,OUTPUT,""); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_FAIL); ResetOutputRoute('d','d'); ReleaseCurrentLock(); continue; } if (strcmp(dp->type,"link") == 0) { snprintf(OUTPUT,CF_BUFSIZE,"%s: %s is a file, not disabling\n",VPREFIX,workname); CfLog(cfverbose,OUTPUT,""); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_FAIL); ResetOutputRoute('d','d'); ReleaseCurrentLock(); continue; } if (stat(workname,&statbuf) == -1) { CfLog(cferror,"Internal; error in Disable\n",""); AuditLog(dp->logaudit,dp->audit,dp->lineno,"Internal error",CF_FAIL); ResetOutputRoute('d','d'); ReleaseCurrentLock(); return; } if (dp->size != CF_NOSIZE) { switch (dp->comp) { case '<': if (statbuf.st_size < dp->size) { Verbose("cfengine %s is smaller than %d bytes\n",workname,dp->size); break; } Verbose("Size is okay\n"); ResetOutputRoute('d','d'); ReleaseCurrentLock(); continue; case '=': if (statbuf.st_size == dp->size) { Verbose("cfengine %s is equal to %d bytes\n",workname,dp->size); break; } Verbose("Size is okay\n"); ResetOutputRoute('d','d'); ReleaseCurrentLock(); continue; default: if (statbuf.st_size > dp->size) { Verbose("cfengine %s is larger than %d bytes\n",workname,dp->size); break; } Verbose("Size is okay\n"); ResetOutputRoute('d','d'); ReleaseCurrentLock(); continue; } } if (dp->rotate == 0) { if (strlen(dp->destination) > 0) { if (IsFileSep(dp->destination[0])) { strncpy(path,dp->destination,CF_BUFSIZE-1); } else { strcpy(path,workname); ChopLastNode(path); AddSlash(path); if (BufferOverflow(path,dp->destination)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Buffer overflow occurred while renaming %s\n",workname); CfLog(cferror,OUTPUT,""); ResetOutputRoute('d','d'); ReleaseCurrentLock(); continue; } strcat(path,dp->destination); } } else { strcpy(path,workname); strcat(path,".cfdisabled"); } snprintf(OUTPUT,CF_BUFSIZE*2,"Disabling/renaming file %s to %s (pending repository move)\n",workname,path); CfLog(cfinform,OUTPUT,""); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_CHG); if (! DONTDO) { chmod(workname, (mode_t)0600); if (! IsItemIn(VREPOSLIST,path)) { if (dp->action == 'd') { if (rename(workname,path) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error occurred while renaming %s\n",workname); CfLog(cferror,OUTPUT,"rename"); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_FAIL); ResetOutputRoute('d','d'); ReleaseCurrentLock(); continue; } snprintf(OUTPUT,CF_BUFSIZE*2,"Renamed %s to %s\n",workname,path); CfLog(cfinform,OUTPUT,""); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_CHG); if (Repository(path,dp->repository)) { unlink(path); } AddMultipleClasses(dp->defines); } else { snprintf(OUTPUT,CF_BUFSIZE,"Warning - file %s exists (need to disable)",workname); CfLog(cferror,OUTPUT,""); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_WARN); } } } } else if (dp->rotate == CF_TRUNCATE) { snprintf(OUTPUT,CF_BUFSIZE*2,"Truncating (emptying) %s\n",workname); CfLog(cfinform,OUTPUT,""); if (dp->action == 'd') { if (! DONTDO) { TruncateFile(workname); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_CHG); AddMultipleClasses(dp->defines); } } else { snprintf(OUTPUT,CF_BUFSIZE,"File %s needs emptying",workname); CfLog(cferror,OUTPUT,""); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_WARN); } } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Rotating files %s by %d\n",workname,dp->rotate); CfLog(cfinform,OUTPUT,""); if (dp->action == 'd') { if (!DONTDO) { RotateFiles(workname,dp->rotate); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_CHG); AddMultipleClasses(dp->defines); } else { snprintf(OUTPUT,CF_BUFSIZE,"File %s needs rotating/emptying",workname); CfLog(cferror,OUTPUT,""); AuditLog(dp->logaudit,dp->audit,dp->lineno,OUTPUT,CF_WARN); } } } } ResetOutputRoute('d','d'); ReleaseCurrentLock(); } } /*******************************************************************/ void MountHomeBinServers() { struct Mountables *mp; char host[CF_MAXVARSIZE]; char mountdir[CF_BUFSIZE]; char maketo[CF_BUFSIZE]; struct Item *ip; /* * HvB: Bas van der Vlies */ char mountmode[CF_BUFSIZE]; if (! GOTMOUNTINFO) { CfLog(cfinform,"Incomplete mount info due to RPC failure.\n",""); snprintf(OUTPUT,CF_BUFSIZE*2,"%s will not be modified on this pass!\n\n",VFSTAB[VSYSTEMHARDCLASS]); CfLog(cfinform,OUTPUT,""); return; } if (!IsPrivileged()) { CfLog(cferror,"Only root can mount filesystems.\n",""); return; } Banner("Checking home and binservers"); Debug("BINSERVER = %s\n",VDEFAULTBINSERVER.name); for (mp = VMOUNTABLES; mp != NULL; mp=mp->next) { sscanf(mp->filesystem,"%[^:]:%s",host,mountdir); if (mp->done == 'y' || strcmp(mp->scope,CONTEXTID)) { continue; } else { mp->done = 'y'; } Debug("Mount: checking %s\n",mp->filesystem); strcpy(maketo,mountdir); if (maketo[strlen(maketo)-1] == '/') { strcat(maketo,"."); } else { strcat(maketo,"/."); } Debug("I am [%s], you are [%s]\n",host,VDEFAULTBINSERVER.name); if (strcmp(host,VDEFAULTBINSERVER.name) == 0) /* A host never mounts itself nfs */ { Debug("Skipping host %s\n",host); continue; } /* HvB: Bas van der Vlies */ if (mp->readonly) { strcpy(mountmode, "ro"); } else { strcpy(mountmode, "rw"); } if (IsHomeDir(mountdir)) { if (!IsItemIn(VMOUNTED,mp->filesystem) && IsClassedItemIn(VHOMESERVERS,host)) { MakeDirectoriesFor(maketo,'n'); AddToFstab(host,mountdir,mountdir,mountmode,mp->mountopts,false); } else if (IsClassedItemIn(VHOMESERVERS,host)) { AddToFstab(host,mountdir,mountdir,mountmode,mp->mountopts,true); } } else { if (!IsItemIn(VMOUNTED,mp->filesystem) && IsClassedItemIn(VBINSERVERS,host)) { MakeDirectoriesFor(maketo,'n'); AddToFstab(host,mountdir,mountdir,mountmode,mp->mountopts,false); AuditLog('y',mp->audit,mp->lineno,"Adding mountpoint, editing filesystem table",CF_CHG); } else if (IsClassedItemIn(VBINSERVERS,host)) { AddToFstab(host,mountdir,mountdir,mountmode,mp->mountopts,true); AuditLog('y',mp->audit,mp->lineno,"Editing filesystem table",CF_CHG); } } } } /*********************************************************************/ void MountMisc() { struct MiscMount *mp; char host[CF_MAXVARSIZE]; char mountdir[CF_BUFSIZE]; char maketo[CF_BUFSIZE]; char mtpt[CF_BUFSIZE]; if (! GOTMOUNTINFO) { CfLog(cfinform,"Incomplete mount info due to RPC failure.\n",""); snprintf(OUTPUT,CF_BUFSIZE*2,"%s will not be modified on this pass!\n\n",VFSTAB[VSYSTEMHARDCLASS]); CfLog(cfinform,OUTPUT,""); return; } if (!IsPrivileged()) { CfLog(cferror,"Only root can mount filesystems.\n",""); return; } Banner("Checking miscellaneous mountables:"); for (mp = VMISCMOUNT; mp != NULL; mp=mp->next) { sscanf(mp->from,"%[^:]:%s",host,mountdir); if (mp->done == 'y' || strcmp(mp->scope,CONTEXTID)) { continue; } else { mp->done = 'y'; } strcpy(maketo,mp->onto); if (maketo[strlen(maketo)-1] == '/') { strcat(maketo,"."); } else { strcat(maketo,"/."); } if (strcmp(host,VDEFAULTBINSERVER.name) == 0) /* A host never mounts itself nfs */ { AuditLog('y',mp->audit,mp->lineno,"MiscMount - no self-mounting",CF_NOP); continue; } snprintf(mtpt,CF_BUFSIZE,"%s:%s",host,mp->onto); if (!IsItemIn(VMOUNTED,mtpt)) { MakeDirectoriesFor(maketo,'n'); AddToFstab(host,mountdir,mp->onto,mp->mode,mp->options,false); AuditLog('y',mp->audit,mp->lineno,"Create mount point, edit fstab",CF_CHG); } else { AddToFstab(host,mountdir,mp->onto,mp->mode,mp->options,true); AuditLog('y',mp->audit,mp->lineno,"Editing fstab",CF_CHG); } } } /*********************************************************************/ void Unmount() { struct UnMount *ptr; char comm[CF_BUFSIZE]; char fs[CF_BUFSIZE]; struct Item *filelist, *item; struct stat statbuf; FILE *pp; if (!IsPrivileged()) { CfLog(cferror,"Only root can unmount filesystems.\n",""); return; } filelist = NULL; if (! LoadItemList(&filelist,VFSTAB[VSYSTEMHARDCLASS])) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open %s!\n",VFSTAB[VSYSTEMHARDCLASS]); CfLog(cferror,OUTPUT,""); AuditLog('y',NULL,0,OUTPUT,CF_FAIL); return; } NUMBEROFEDITS = 0; for (ptr=VUNMOUNT; ptr != NULL; ptr=ptr->next) { if (IsExcluded(ptr->classes)) { continue; } if (ptr->done == 'y' || strcmp(ptr->scope,CONTEXTID)) { continue; } else { ptr->done = 'y'; } if (!GetLock(ASUniqueName("unmount"),CanonifyName(ptr->name),ptr->ifelapsed,ptr->expireafter,VUQNAME,CFSTARTTIME)) { ptr->done = 'y'; continue; } fs[0] = '\0'; sscanf(ptr->name,"%*[^:]:%s",fs); if (strlen(fs) == 0) { ReleaseCurrentLock(); AuditLog('y',ptr->audit,ptr->lineno,"Umount check",CF_NOP); continue; } snprintf(OUTPUT,CF_BUFSIZE*2,"Unmount filesystem %s on %s\n",fs,ptr->name); CfLog(cfverbose,OUTPUT,""); if (strcmp(fs,"/") == 0 || strcmp(fs,"/usr") == 0) { CfLog(cfinform,"Request to unmount / or /usr is refused!\n",""); AuditLog('y',ptr->audit,ptr->lineno,"Will not unmount / or /usr",CF_DENIED); ReleaseCurrentLock(); continue; } if (IsItemIn(VMOUNTED,ptr->name) && (! DONTDO)) { snprintf(comm,CF_BUFSIZE,"%s %s",VUNMOUNTCOMM[VSYSTEMHARDCLASS],fs); if ((pp = cfpopen(comm,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Failed to open pipe from %s\n",VUNMOUNTCOMM[VSYSTEMHARDCLASS]); CfLog(cferror,OUTPUT,""); AuditLog('y',ptr->audit,ptr->lineno,OUTPUT,CF_FAIL); ReleaseCurrentLock(); return; } ReadLine(VBUFF,CF_BUFSIZE,pp); if (strstr(VBUFF,"busy") || strstr(VBUFF,"Busy")) { snprintf(OUTPUT,CF_BUFSIZE*2,"umount warned that the device under %s\n",ptr->name); CfLog(cfinform,OUTPUT,""); CfLog(cfinform,"was busy. Cannot unmount that device.\n",""); /* don't delete the mount dir when unmount's failed */ ptr->deletedir = 'n'; } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Unmounting %s\n",ptr->name); CfLog(cfinform,OUTPUT,""); DeleteItemStarting(&VMOUNTED,ptr->name); /* update mount record */ AuditLog('y',ptr->audit,ptr->lineno,OUTPUT,CF_CHG); } cfpclose(pp); } if (ptr->deletedir == 'y') { if (stat(fs,&statbuf) != -1) { if (!S_ISDIR(statbuf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Warning! %s was not a directory.\n",fs); CfLog(cfinform,OUTPUT,""); CfLog(cfinform,"(Unmount) will not delete this!\n",""); KillOldLink(fs,NULL); } else if (! DONTDO) { if (rmdir(fs) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to remove the directory %s\n",fs); CfLog(cferror,OUTPUT,"rmdir"); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Removing directory %s\n",ptr->name); CfLog(cfinform,OUTPUT,""); AuditLog('y',ptr->audit,ptr->lineno,OUTPUT,CF_CHG); } } } } if (ptr->deletefstab == 'y') { if (VSYSTEMHARDCLASS == aix) { strcpy (VBUFF,fs); strcat (VBUFF,":"); item = LocateNextItemContaining(filelist,VBUFF); if (item == NULL || item->next == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Bad format in %s\n",VFSTAB[aix]); CfLog(cferror,OUTPUT,""); continue; } DeleteItem(&filelist,item->next); while (strstr(item->next->name,"=")) { DeleteItem(&filelist,item->next); /* DeleteItem(NULL) is harmless */ } } else { Debug("Trying to delete filesystem %s from list\n",ptr->name); if (VSYSTEMHARDCLASS == ultrx) /* ensure name is not just a substring */ { strcpy (VBUFF,ptr->name); strcat (VBUFF,":"); DeleteItemContaining(&filelist,VBUFF); } else { switch (VSYSTEMHARDCLASS) { case unix_sv: case solarisx86: case solaris: /* find fs in proper context (": <-> ") */ snprintf(VBUFF,CF_BUFSIZE,"[^:]+:[^ \t]+[ \t]+[^ \t]+[ \t]+%s[ \t]",fs); break; default: /* find fs in proper context (": ") */ snprintf(VBUFF,CF_BUFSIZE,"[^:]+:[^ \t]+[ \t]+%s[ \t]",fs); break; } item = LocateItemContainingRegExp(filelist,VBUFF); DeleteItem(&filelist,item); } } } ReleaseCurrentLock(); } if ((! DONTDO) && (NUMBEROFEDITS > 0)) { SaveItemList(filelist,VFSTAB[VSYSTEMHARDCLASS],VREPOSITORY); AuditLog('y',ptr->audit,ptr->lineno,"Saving filesystem table",CF_CHG); } DeleteItemList(filelist); } /*********************************************************************/ void EditFiles() { struct Edit *ptr; struct stat statbuf; Debug("Editfiles()\n"); for (ptr=VEDITLIST; ptr!=NULL; ptr=ptr->next) { if (ptr->done == 'y' || strcmp(ptr->scope,CONTEXTID)) { continue; } if (strncmp(ptr->fname,"home",4) == 0) { DoEditHomeFiles(ptr); } else { if (lstat(ptr->fname,&statbuf) != -1) { if (S_ISDIR(statbuf.st_mode)) { DoRecursiveEditFiles(ptr->fname,ptr->recurse,ptr,&statbuf); } else { WrapDoEditFile(ptr,ptr->fname); } } else { DoEditFile(ptr,ptr->fname); } } } EDITVERBOSE = false; } /*******************************************************************/ void CheckResolv() { struct Item *filebase = NULL, *referencefile = NULL; struct Item *ip; char ch; int fd, existed = true; Verbose("Checking config in %s\n",VRESOLVCONF[VSYSTEMHARDCLASS]); if (strcmp(VDOMAIN,"") == 0) { CfLog(cferror,"Domain name not specified. Can't configure resolver\n",""); AuditLog('y',NULL,0,"No domain",CF_FAIL); return; } if (!IsPrivileged()) { CfLog(cferror,"Only root can configure the resolver.\n",""); return; } if (! LoadItemList(&referencefile,VRESOLVCONF[VSYSTEMHARDCLASS])) { snprintf(OUTPUT,CF_BUFSIZE*2,"Trying to create %s\n",VRESOLVCONF[VSYSTEMHARDCLASS]); CfLog(cfinform,OUTPUT,""); existed = false; if ((fd = creat(VRESOLVCONF[VSYSTEMHARDCLASS],0644)) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to create file %s\n",VRESOLVCONF[VSYSTEMHARDCLASS]); CfLog(cferror,OUTPUT,"creat"); AuditLog('y',NULL,0,OUTPUT,CF_FAIL); return; } else { close(fd); } } if (existed) { LoadItemList(&filebase,VRESOLVCONF[VSYSTEMHARDCLASS]); } DeleteItemStarting(&filebase,"domain"); while(DeleteItemStarting(&filebase,"search")) { } if (OptionIs(CONTEXTID,"EmptyResolvConf", true)) { DeleteItemList(filebase); filebase = NULL; } EditItemsInResolvConf(VRESOLVE,&filebase); snprintf(VBUFF,CF_BUFSIZE,"domain %s",ToLowerStr(VDOMAIN)); PrependItem(&filebase,VBUFF,NULL); if (DONTDO) { printf("Check %s for editing\n",VRESOLVCONF[VSYSTEMHARDCLASS]); } else if (!ItemListsEqual(filebase,referencefile)) { SaveItemList(filebase,VRESOLVCONF[VSYSTEMHARDCLASS],VREPOSITORY); AuditLog('y',NULL,0,"Resolver config",CF_CHG); chmod(VRESOLVCONF[VSYSTEMHARDCLASS],DEFAULTSYSTEMMODE); } else { Verbose("cfengine: %s is okay\n",VRESOLVCONF[VSYSTEMHARDCLASS]); AuditLog('y',NULL,0,"Resolver config",CF_NOP); } DeleteItemList(filebase); DeleteItemList(referencefile); } /*******************************************************************/ void MakeImages() { struct Image *ip; struct Item *svp; struct stat statbuf,deststatbuf; struct servent *serverent; int savesilent; char path[CF_EXPANDSIZE],destination[CF_EXPANDSIZE],vbuff[CF_BUFSIZE]; char server[CF_EXPANDSIZE],listserver[CF_EXPANDSIZE]; for (svp = VSERVERLIST; svp != NULL; svp=svp->next) /* order servers */ { CONN = NewAgentConn(); /* Global input/output channel */ if (CONN == NULL) { return; } ExpandVarstring(svp->name,listserver,NULL); for (ip = VIMAGE; ip != NULL; ip=ip->next) { struct timespec start,stop; double dt = 0; int measured_ok = true; char eventname[CF_BUFSIZE]; if (clock_gettime(CLOCK_REALTIME, &start) == -1) { CfLog(cfverbose,"Clock gettime failure","clock_gettime"); measured_ok = false; } ExpandVarstring(ip->server,server,NULL); AddMacroValue(CONTEXTID,"this",server); ExpandVarstring(ip->path,path,NULL); ExpandVarstring(ip->destination,destination,NULL); DeleteMacro(CONTEXTID,"this"); if (strcmp(server,"none") == 0) { Verbose("Server none is a no-op\n"); continue; } if (strcmp(listserver,server) != 0) /* group together similar hosts so */ { /* can can do multiple transactions */ continue; /* on one connection */ } if (IsExcluded(ip->classes)) { continue; } if (ip->done == 'y' || strcmp(ip->scope,CONTEXTID)) { continue; } else { ip->done = 'y'; } Verbose("Checking copy from %s:%s to %s\n",server,path,destination); if (!OpenServerConnection(ip)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to establish connection with %s (failover)\n",listserver); CfLog(cfinform,OUTPUT,""); AuditLog('y',ip->audit,ip->lineno,OUTPUT,CF_FAIL); AddMultipleClasses(ip->failover); continue; } if (AUTHENTICATED) { Debug("Authentic connection verified\n"); } IMAGEBACKUP = true; savesilent = SILENT; if (strcmp(ip->action,"silent") == 0) { SILENT = true; } ResetOutputRoute(ip->log,ip->inform); if (cfstat(path,&statbuf,ip) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s in copy\n",path); CfLog(cfverbose,OUTPUT,""); SILENT = savesilent; ResetOutputRoute('d','d'); continue; } snprintf(vbuff,CF_BUFSIZE,"%.255s.%.50s_%.50s",path,destination,server); /* Unique ID for copy locking */ if (!GetLock(ASUniqueName("copy"),CanonifyName(vbuff),ip->ifelapsed,ip->expireafter,VUQNAME,CFSTARTTIME)) { SILENT = savesilent; ResetOutputRoute('d','d'); ip->done = 'y'; continue; } IMAGEBACKUP = ip->backup; if (strncmp(destination,"home",4) == 0) { HOMECOPY = true; /* Don't send home backups to repository */ CheckHomeImages(ip); HOMECOPY = false; } else { if (S_ISDIR(statbuf.st_mode)) { if (ip->purge == 'y') { Verbose("%s: (Destination purging enabled)\n",VPREFIX); } RegisterRecursionRootDevice(statbuf.st_dev); RecursiveImage(ip,path,destination,ip->recurse); if (stat(destination,&deststatbuf) != -1) { if (ip->checkroot != 'n') { if ((ip->uid)->uid == (uid_t)-1) /* Preserve uid and gid */ { (ip->uid)->uid = statbuf.st_uid; } if ((ip->gid)->gid == (gid_t)-1) { (ip->gid)->gid = statbuf.st_gid; } /* Default is to set perms from server on rootdir from 2.2.2 */ CheckCopiedFile(ip->cf_findertype,destination,&deststatbuf,&statbuf,ip); } } } else { if (! MakeDirectoriesFor(destination,'n')) { ReleaseCurrentLock(); SILENT = savesilent; ResetOutputRoute('d','d'); continue; } CheckImage(path,destination,ip); } } ReleaseCurrentLock(); SILENT = savesilent; ResetOutputRoute('d','d'); if (clock_gettime(CLOCK_REALTIME, &stop) == -1) { CfLog(cfverbose,"Clock gettime failure","clock_gettime"); measured_ok = false; } dt = (double)(stop.tv_sec - start.tv_sec)+(double)(stop.tv_nsec-start.tv_nsec)/(double)CF_BILLION; snprintf(eventname,CF_BUFSIZE-1,"Copy(%s:%s > %s)",server,path,destination); if (measured_ok) { RecordPerformance(eventname,start.tv_sec,dt); } } CloseServerConnection(); DeleteAgentConn(CONN); } } /*******************************************************************/ void ConfigureInterfaces() { struct Interface *ifp; Banner("Network interface configuration"); if (GetLock("netconfig",VIFDEV[VSYSTEMHARDCLASS],VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME)) { if (strlen(VNETMASK) != 0) { IfConf(VIFDEV[VSYSTEMHARDCLASS],VIPADDRESS,VNETMASK,VBROADCAST); } SetDefaultRoute(); ReleaseCurrentLock(); } for (ifp = VIFLIST; ifp != NULL; ifp=ifp->next) { if (!GetLock("netconfig",ifp->ifdev,VIFELAPSED,VEXPIREAFTER,VUQNAME,CFSTARTTIME)) { ifp->done = 'y'; continue; } if (ifp->done == 'y' || strcmp(ifp->scope,CONTEXTID)) { continue; } else { ifp->done = 'y'; } AuditLog('y',ifp->audit,ifp->lineno,OUTPUT,CF_UNKNOWN); IfConf(ifp->ifdev,ifp->ipaddress,ifp->netmask,ifp->broadcast); SetDefaultRoute(); ReleaseCurrentLock(); } } /*******************************************************************/ void CheckTimeZone() { struct Item *ip; char tz[CF_MAXVARSIZE]; if (VTIMEZONE == NULL) { CfLog(cferror,"Program does not define a timezone",""); return; } for (ip = VTIMEZONE; ip != NULL; ip=ip->next) { #ifdef OLDNT tzset(); strcpy(tz,timezone()); #else #ifndef AOS #ifndef SUN4 tzset(); strcpy(tz,tzname[0]); #else if ((tloc = time((time_t *)NULL)) == -1) { printf("Couldn't read system clock\n\n"); } strcpy(tz,localtime(&tloc)->tm_zone); #endif /* SUN4 */ #endif /* AOS */ #endif /* NT */ if (TZCheck(tz,ip->name)) { return; } } snprintf(OUTPUT,CF_BUFSIZE*2,"Time zone was %s which is not in the list of acceptable values",tz); CfLog(cferror,OUTPUT,""); } /*******************************************************************/ void CheckProcesses() { struct Process *pp; struct Item *procdata = NULL; char *psopts = VPSOPTS[VSYSTEMHARDCLASS]; if (!LoadProcessTable(&procdata,psopts)) { CfLog(cferror,"Unable to read the process table\n",""); AuditLog('y',NULL,0,"Processes inaccessible",CF_FAIL); return; } for (pp = VPROCLIST; pp != NULL; pp=pp->next) { if (IsExcluded(pp->classes)) { continue; } if (pp->done == 'y' || strcmp(pp->scope,CONTEXTID) != 0) { continue; } else { pp->done = 'y'; } snprintf(VBUFF,CF_BUFSIZE-1,"proc-%s-%s",pp->expr,pp->restart); if (!GetLock(ASUniqueName("processes"),CanonifyName(VBUFF),pp->ifelapsed,pp->expireafter,VUQNAME,CFSTARTTIME)) { pp->done = 'y'; continue; } ResetOutputRoute(pp->log,pp->inform); if (strcmp(pp->expr,"SetOptionString") == 0) { psopts = pp->restart; DeleteItemList(procdata); procdata = NULL; if (!LoadProcessTable(&procdata,psopts)) { CfLog(cferror,"Unable to read the process table\n",""); } } else { DoProcessCheck(pp,procdata); } ResetOutputRoute('d','d'); ReleaseCurrentLock(); } } /*******************************************************************/ void CheckPackages() { struct Package *ptr; int match = 0; char lock[CF_BUFSIZE],name[CF_EXPANDSIZE]; struct Item *pending_pkgs = NULL; enum pkgmgrs prev_pkgmgr = pkgmgr_none; enum pkgactions prev_action = pkgaction_none; for (ptr = VPKG; ptr != NULL; ptr=ptr->next) { if (IsExcluded(ptr->classes)) { continue; } if (ptr->done == 'y' || strcmp(ptr->scope,CONTEXTID) != 0) { continue; } ExpandVarstring(ptr->name,name,""); snprintf(lock,CF_BUFSIZE-1,"%s_%d_%s_%d_%s_%s", name, ptr->cmp, ptr->ver ? ptr->ver: "" ,ptr->action, ptr->defines ?: "", ptr->elsedef ?: ""); if (!GetLock(ASUniqueName("packages"),CanonifyName(lock),ptr->ifelapsed,ptr->expireafter,VUQNAME,CFSTARTTIME)) { ptr->done = 'y'; continue; } match = PackageCheck(ptr,name,ptr->pkgmgr, ptr->ver, ptr->cmp); /* Check for a problem executing the command */ if ((match != 1) && (match != 0)) { snprintf(OUTPUT,CF_BUFSIZE,"Error: Package manager query failed, skipping %s\n", name); CfLog(cferror,OUTPUT,""); ptr->done = 'y'; continue; } /* Process any queued actions (install/remove). */ if ((pending_pkgs != NULL) && ((ptr->action != prev_action) || (ptr->pkgmgr != prev_pkgmgr))) { ProcessPendingPackages(ptr,prev_pkgmgr,prev_action,&pending_pkgs); DeleteItemList( pending_pkgs ); pending_pkgs = NULL; } /* Handle install/remove logic now. */ if (match) { AddMultipleClasses(ptr->defines); if (ptr->action == pkgaction_remove) { PackageList(ptr,name,ptr->pkgmgr,ptr->ver,ptr->cmp,&pending_pkgs); /* Some package managers operate best doing things one at a time. */ if ((ptr->pkgmgr == pkgmgr_freebsd) || (ptr->pkgmgr == pkgmgr_sun)) { RemovePackage(ptr,ptr->pkgmgr,&pending_pkgs); DeleteItemList(pending_pkgs); pending_pkgs = NULL; } } else if (ptr->action == pkgaction_upgrade || (ptr->action == pkgaction_fix)) { UpgradePackage(ptr,name,ptr->pkgmgr,ptr->ver,ptr->cmp); } } else { AddMultipleClasses(ptr->elsedef); if (ptr->action == pkgaction_install) { AppendItem(&pending_pkgs,name, NULL); /* Some package managers operate best doing things one at a time. */ if ((ptr->pkgmgr == pkgmgr_freebsd) || (ptr->pkgmgr == pkgmgr_sun)) { InstallPackage(ptr,ptr->pkgmgr,&pending_pkgs); DeleteItemList(pending_pkgs); pending_pkgs = NULL; } AuditLog(ptr->logaudit,ptr->audit,ptr->lineno,"Package update",CF_CHG); } } ptr->done = 'y'; ReleaseCurrentLock(); if (ptr->action != pkgaction_none) { prev_action = ptr->action; prev_pkgmgr = ptr->pkgmgr; } } if (pending_pkgs != NULL) { /* Use VPKG since ptr is NULL and make AuditLog to SEGV */ ProcessPendingPackages(VPKG,prev_pkgmgr, prev_action, &pending_pkgs); DeleteItemList( pending_pkgs ); pending_pkgs = NULL; } } /*******************************************************************/ void DoMethods() { struct Method *ptr; struct Item *ip, *uniqueid; char label[CF_BUFSIZE]; unsigned char digest[EVP_MAX_MD_SIZE+1]; Banner("Dispatching new methods"); for (ptr = VMETHODS; ptr != NULL; ptr=ptr->next) { if (IsExcluded(ptr->classes)) { continue; } if (ptr->done == 'y' || strcmp(ptr->scope,CONTEXTID) != 0) { continue; } else { ptr->done = 'y'; } uniqueid = NULL; CopyList(&uniqueid,ptr->send_args); /* Append server to make this unique */ for (ip = ptr->servers; ip != NULL; ip=ip->next) { PrependItem(&uniqueid,ip->name,NULL); } ChecksumList(ptr->send_args,digest,'m'); DeleteItemList(uniqueid); snprintf(label,CF_BUFSIZE-1,"%s/rpc_in/localhost+localhost+%s+%s",VLOCKDIR,ptr->name,ChecksumPrint('m',digest)); if (!GetLock(ASUniqueName("methods-dispatch"),CanonifyName(label),ptr->ifelapsed,ptr->expireafter,VUQNAME,CFSTARTTIME)) { ptr->done = 'y'; continue; } DispatchNewMethod(ptr); ptr->done = 'y'; ReleaseCurrentLock(); } Banner("Evaluating incoming methods that policy accepts..."); for (ip = GetPendingMethods(CF_METHODEXEC); ip != NULL; ip=ip->next) { /* Call child process to execute method*/ EvaluatePendingMethod(ip->name); } DeleteItemList(ip); Banner("Fetching replies to finished methods"); for (ip = GetPendingMethods(CF_METHODREPLY); ip != NULL; ip=ip->next) { if (ParentLoadReplyPackage(ip->name)) { } } DeleteItemList(ip); } /*******************************************************************/ /* Level 2 */ /*******************************************************************/ int RequiredFileSystemOkay (char *name) { struct stat statbuf, localstat; DIR *dirh; struct dirent *dirp; long sizeinbytes = 0, filecount = 0; char buff[CF_BUFSIZE]; Debug("Checking required filesystem %s\n",name); if (stat(name,&statbuf) == -1) { return(false); } if (S_ISLNK(statbuf.st_mode)) { KillOldLink(name,NULL); return(true); } if (S_ISDIR(statbuf.st_mode)) { if ((dirh = opendir(name)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s which checking required/disk\n",name); CfLog(cferror,OUTPUT,"opendir"); return false; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,name,NULL)) { continue; } filecount++; strcpy(buff,name); if (buff[strlen(buff)] != '/') { strcat(buff,"/"); } strcat(buff,dirp->d_name); if (lstat(buff,&localstat) == -1) { if (S_ISLNK(localstat.st_mode)) { KillOldLink(buff,NULL); continue; } snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s in required/disk\n",buff); CfLog(cferror,OUTPUT,"lstat"); continue; } sizeinbytes += localstat.st_size; } closedir(dirh); if (sizeinbytes < 0) { Verbose("Internal error: count of byte size was less than zero!\n"); return true; } if (sizeinbytes < SENSIBLEFSSIZE) { snprintf(OUTPUT,CF_BUFSIZE*2,"File system %s is suspiciously small! (%d bytes)\n",name,sizeinbytes); CfLog(cferror,OUTPUT,""); return(false); } if (filecount < SENSIBLEFILECOUNT) { snprintf(OUTPUT,CF_BUFSIZE*2,"Filesystem %s has only %d files/directories.\n",name,filecount); CfLog(cferror,OUTPUT,""); return(false); } } return(true); } /*******************************************************************/ int ScanFileSystemArrivals(char *name,int rlevel,struct stat *sb,DB *dbp) { DIR *dirh; int goback; struct dirent *dirp; char pcwd[CF_BUFSIZE]; struct stat statbuf; if (rlevel > CF_RECURSION_LIMIT) { snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING: Very deep nesting of directories (>%d deep): %s (Aborting files)",rlevel,name); CfLog(cferror,OUTPUT,""); return false; } memset(pcwd,0,CF_BUFSIZE); Debug("ScanFileSystemArrivals(%s)\n",name); if (!DirPush(name,sb)) { return false; } if ((dirh = opendir(".")) == NULL) { return true; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,name,NULL)) { continue; } strcpy(pcwd,name); /* Assemble pathname */ AddSlash(pcwd); if (BufferOverflow(pcwd,dirp->d_name)) { closedir(dirh); return true; } strcat(pcwd,dirp->d_name); if (lstat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"ScanFilesystem was looking at %s when this happened:\n",pcwd); CfLog(cferror,OUTPUT,"lstat"); continue; } if (DeviceChanged(statbuf.st_dev)) { Verbose("Skipping %s on different device\n",pcwd); continue; } if (S_ISDIR(statbuf.st_mode)) { if (IsMountedFileSystem(&statbuf,pcwd,rlevel)) { continue; } else { RecordFileSystemArrivals(dbp,sb->st_mtime); goback = ScanFileSystemArrivals(pcwd,rlevel+1,&statbuf,dbp); DirPop(goback,name,sb); } } else { RecordFileSystemArrivals(dbp,sb->st_mtime); } } closedir(dirh); return true; } /*******************************************************************/ void InstallMountedItem(char *host,char *mountdir) { char buf[CF_BUFSIZE]; strcpy (buf,host); strcat (buf,":"); strcat (buf,mountdir); if (IsItemIn(VMOUNTED,buf)) { if (! SILENT || !WARNINGS) { if (!strstr(buf,"swap")) { snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING mount item %s\n",buf); CfLog(cferror,OUTPUT,""); CfLog(cferror,"is mounted multiple times!\n",""); } } } AppendItem(&VMOUNTED,buf,NULL); } /*******************************************************************/ void AddToFstab(char *host,char *rmountpt,char *mountpt,char *mode,char *options,int ismounted) { char fstab[CF_BUFSIZE]; char *opts; FILE *fp; char aix_lsnfsmnt[CF_BUFSIZE]; Debug("AddToFstab(%s)\n",mountpt); if (mode == NULL) { mode = "rw"; } if ((options != NULL) && (strlen(options) > 0)) { opts = options; } else { opts = VMOUNTOPTS[VSYSTEMHARDCLASS]; } switch (VSYSTEMHARDCLASS) { case osf: case bsd4_3: case irix: case irix4: case irix64: case sun3: case aos: case nextstep: case newsos: case qnx: case sun4: snprintf(fstab,CF_BUFSIZE,"%s:%s \t %s %s\t%s,%s 0 0",host,rmountpt,mountpt,VNFSTYPE,mode,opts); break; case crayos: snprintf(fstab,CF_BUFSIZE,"%s:%s \t %s %s\t%s,%s",host,rmountpt,mountpt,ToUpperStr(VNFSTYPE),mode,opts); break; case ultrx: snprintf(fstab,CF_BUFSIZE,"%s@%s:%s:%s:0:0:%s:%s",rmountpt,host,mountpt,mode,VNFSTYPE,opts); break; case hp: snprintf(fstab,CF_BUFSIZE,"%s:%s %s \t %s \t %s,%s 0 0",host,rmountpt,mountpt,VNFSTYPE,mode,opts); break; case aix: snprintf(fstab,CF_BUFSIZE,"%s:\n\tdev\t= %s\n\ttype\t= %s\n\tvfs\t= %s\n\tnodename\t= %s\n\tmount\t= true\n\toptions\t= %s,%s\n\taccount\t= false\n",mountpt,rmountpt,VNFSTYPE,VNFSTYPE,host,mode,opts); snprintf(aix_lsnfsmnt, CF_BUFSIZE, "%s:%s:%s:%s:%s", mountpt, rmountpt, host, VNFSTYPE, mode ); break; case GnU: case linuxx: snprintf(fstab,CF_BUFSIZE,"%s:%s \t %s \t %s \t %s,%s",host,rmountpt,mountpt,VNFSTYPE,mode,opts); break; case netbsd: case openbsd: case bsd_i: case dragonfly: case freebsd: snprintf(fstab,CF_BUFSIZE,"%s:%s \t %s \t %s \t %s,%s 0 0",host,rmountpt,mountpt,VNFSTYPE,mode,opts); break; case unix_sv: case solarisx86: case solaris: snprintf(fstab,CF_BUFSIZE,"%s:%s - %s %s - yes %s,%s",host,rmountpt,mountpt,VNFSTYPE,mode,opts); break; case cfnt: snprintf(fstab,CF_BUFSIZE,"/bin/mount %s:%s %s",host,rmountpt,mountpt); break; case cfsco: CfLog(cferror,"Don't understand filesystem format on SCO, no data",""); break; case unused2: case unused3: default: FatalError("AddToFstab(): unknown hard class detected!\n"); break; } if (MatchStringInFstab(mountpt)) { if (VSYSTEMHARDCLASS == aix) /* This AIX code by Graham Bevan */ { FILE *pp; int fs_found = 0; int fs_changed = 0; char comm[CF_BUFSIZE]; if ((pp = cfpopen("/usr/sbin/lsnfsmnt -c", "r")) == NULL) { CfLog(cferror,"Failed to open pipe to /usr/sbin/lsnfsmnt command.", ""); return; } while(!feof(pp)) { ReadLine(VBUFF, CF_BUFSIZE, pp); if (VBUFF[0] == '#') { continue; } if (strstr(VBUFF,mountpt)) { fs_found++; if (!strstr(VBUFF,aix_lsnfsmnt)) { fs_changed = 1; } } } fclose(pp); if (fs_found == 1 && !fs_changed) { return; } else { /* if entry not found, duplicates found or entry is different from lookup string * then remove for re-add */ int failed = 0; snprintf(OUTPUT,CF_BUFSIZE*2,"Removing \"%s\" entry from %s to allow update (fs_found=%d):\n", mountpt, VFSTAB[VSYSTEMHARDCLASS], fs_found ); CfLog(cfinform,OUTPUT,""); CfLog(cfinform,"---------------------------------------------------",""); snprintf(comm, CF_BUFSIZE, "/usr/sbin/rmnfsmnt -f %s", mountpt); if ((pp = cfpopen(comm,"r")) == NULL) { CfLog(cferror,"Failed to open pipe to /usr/sbin/rmnfsmnt command.", ""); return; } while(!feof(pp)) { ReadLine(VBUFF, CF_BUFSIZE, pp); if (VBUFF[0] == '#') { continue; } if (strstr(VBUFF,"busy")) { snprintf(OUTPUT,CF_BUFSIZE*2,"umount warned that the device under %s\n",mountpt); CfLog(cfinform,OUTPUT,""); CfLog(cfinform,"was busy. Cannot unmount (rmnfsmnt) that device.\n",""); failed = 1; } } if (fclose(pp) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"rmnfsmnt failed on fclose() for %s: %s\n",mountpt, strerror(errno)); CfLog(cferror,OUTPUT,""); return; } if (failed) { return; } } } /* if aix */ else { /* if the fstab entry has changed, remove the old entry and update */ if (!MatchStringInFstab(fstab)) { struct UnMount *saved_VUNMOUNT = VUNMOUNT; char mountspec[MAXPATHLEN]; struct Item *mntentry = NULL; struct UnMount cleaner; snprintf(OUTPUT,CF_BUFSIZE*2,"Removing \"%s\" entry from %s to allow update:\n",mountpt,VFSTAB[VSYSTEMHARDCLASS]); CfLog(cfinform,OUTPUT,""); CfLog(cfinform,"---------------------------------------------------",""); /* delete current fstab entry and unmount if necessary */ snprintf(mountspec,CF_BUFSIZE,".+:%s",mountpt); mntentry = LocateItemContainingRegExp(VMOUNTED,mountspec); if (mntentry) { sscanf(mntentry->name,"%[^:]:",mountspec); /* extract current host */ strcat(mountspec,":"); strcat(mountspec,mountpt); } else /* mountpt isn't mounted, so Unmount can use dummy host name */ snprintf(mountspec,CF_BUFSIZE,"host:%s",mountpt); /* delete current fstab entry and unmount if necessary (don't rmdir) */ cleaner.name = mountspec; cleaner.classes = NULL; cleaner.deletedir = 'n'; cleaner.deletefstab = 'y'; cleaner.force = 'n'; cleaner.done = 'n'; cleaner.scope = CONTEXTID; cleaner.next = NULL; VUNMOUNT = &cleaner; Unmount(); VUNMOUNT = saved_VUNMOUNT; CfLog(cfinform,"---------------------------------------------------",""); } else /* no need to update fstab - this mount entry is already there */ { /* warn if entry's already in the fstab but hasn't been mounted */ if (!ismounted && !SILENT && !strstr(mountpt,"cdrom")) { snprintf(OUTPUT,CF_BUFSIZE*2,"Warning the file system %s seems to be in %s\n",mountpt,VFSTAB[VSYSTEMHARDCLASS]); CfLog(cfinform,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"already, but I was not able to mount it.\n"); CfLog(cfinform,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"Check the exports file on host %s? Check for file with same name as dir?\n",host); CfLog(cfinform,OUTPUT,""); } return; } } } /* if aix */ if (DONTDO) { printf("%s: add filesystem to %s\n",VPREFIX,VFSTAB[VSYSTEMHARDCLASS]); printf("%s: %s\n",VPREFIX,fstab); } else { struct Item *filelist = NULL; if (! LoadItemList(&filelist,VFSTAB[VSYSTEMHARDCLASS])) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open %s!\n",VFSTAB[VSYSTEMHARDCLASS]); CfLog(cferror,OUTPUT,""); return; } NUMBEROFEDITS = 0; snprintf(OUTPUT,CF_BUFSIZE*2,"Adding filesystem to %s\n",VFSTAB[VSYSTEMHARDCLASS]); CfLog(cfinform,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"%s\n",fstab); CfLog(cfinform,OUTPUT,""); if (!IsItemIn(filelist,fstab)) { AppendItem(&filelist,fstab,NULL); } SaveItemList(filelist,VFSTAB[VSYSTEMHARDCLASS],VREPOSITORY); chmod(VFSTAB[VSYSTEMHARDCLASS],DEFAULTSYSTEMMODE); } } /*******************************************************************/ int CheckFreeSpace (char *file,struct Disk *disk_ptr) { struct stat statbuf; int free; int kilobytes; if (stat(file,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't stat %s checking diskspace\n",file); CfLog(cferror,OUTPUT,""); return true; } /* HvB : Bas van der Vlies if force is specified then skip this check if this is on the file server. */ if (disk_ptr->force != 'y') { if (IsMountedFileSystem(&statbuf,file,1)) { return true; } } kilobytes = disk_ptr->freespace; if (kilobytes < 0) /* percentage */ { free = GetDiskUsage(file,cfpercent); kilobytes = -1 * kilobytes; if (free < kilobytes) { snprintf(OUTPUT,CF_BUFSIZE*2,"Free disk space is under %d%% for partition\n",kilobytes); CfLog(cfinform,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"containing %s (%d%% free)\n",file,free); CfLog(cfinform,OUTPUT,""); return false; } } else { free = GetDiskUsage(file, cfabs); if (free < kilobytes) { snprintf(OUTPUT,CF_BUFSIZE*2,"Disk space under %d kB for partition\n",kilobytes); CfLog(cfinform,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"containing %s (%d kB free)\n",file,free); CfLog(cfinform,OUTPUT,""); return false; } } return true; } /*******************************************************************/ void CheckHome(struct File *ptr) /* iterate check over homedirs */ { struct Item *ip1, *ip2; char basename[CF_EXPANDSIZE],pathbuff[CF_BUFSIZE]; Debug("CheckHome(%s)\n",ptr->path); if (!IsPrivileged()) { CfLog(cferror,"Only root can check others' files.\n",""); return; } if (!MountPathDefined()) { return; } for (ip1 = VHOMEPATLIST; ip1 != NULL; ip1=ip1->next) { for (ip2 = VMOUNTLIST; ip2 != NULL; ip2=ip2->next) { if (IsExcluded(ip2->classes)) { continue; } pathbuff[0]='\0'; basename[0]='\0'; strcpy(pathbuff,ip2->name); AddSlash(pathbuff); strcat(pathbuff,ip1->name); AddSlash(pathbuff); if (strncmp(ptr->path,"home/",5) == 0) /* home/subdir */ { strcat(pathbuff,"*"); AddSlash(pathbuff); if (*(ptr->path+4) != '/') { snprintf(OUTPUT,CF_BUFSIZE*2,"Illegal use of home in files: %s\n",ptr->path); CfLog(cferror,OUTPUT,""); return; } else { strcat(pathbuff,ptr->path+5); } ExpandWildCardsAndDo(pathbuff,basename,RecFileCheck,ptr); } else { ExpandWildCardsAndDo(pathbuff,basename,RecFileCheck,ptr); } } } } /*******************************************************************/ void EditItemsInResolvConf(struct Item *from,struct Item **list) { char buf[CF_MAXVARSIZE],work[CF_EXPANDSIZE]; struct Item *ip; for (ip = from; ip != NULL; ip=ip->next) { if (IsExcluded(ip->classes)) { continue; } ExpandVarstring(ip->name,work,""); if (isdigit((int)*(work))) { snprintf(buf,CF_MAXVARSIZE,"nameserver %s",work); } else { strncpy(buf,work,CF_MAXVARSIZE-1); } DeleteItemMatching(list,buf); /* del+prep = move to head of list */ PrependItem(list,buf,NULL); } } /*******************************************************************/ int TZCheck(char *tzsys,char *tzlist) { if (strncmp(tzsys,"GMT",3) == 0) { return (strncmp(tzsys,tzlist,5) == 0); /* e.g. GMT+1 */ } else { return (strncmp(tzsys,tzlist,3) == 0); /* e.g. MET or CET */ } } /*******************************************************************/ void ExpandWildCardsAndDo(char *wildpath,char *buffer,void (*function)(char *path, void *ptr),void *argptr) /* This function recursively expands a path containing wildcards */ /* and executes the function pointed to by function for each */ /* matching file or directory */ { char *rest, extract[CF_BUFSIZE], construct[CF_BUFSIZE],varstring[CF_EXPANDSIZE],cleaned[CF_BUFSIZE], *work; struct stat statbuf; DIR *dirh; struct dirent *dp; int count, isdir = false,i,j; varstring[0] = '\0'; memset(cleaned,0,CF_BUFSIZE); for (i = j = 0; wildpath[i] != '\0'; i++,j++) { if ((i > 0) && (wildpath[i] == '/') && (wildpath[i-1] == '/')) { j--; } cleaned[j] = wildpath[i]; } ExpandVarstring(cleaned,varstring,NULL); work = varstring; Debug2("ExpandWildCardsAndDo(%s=%s)\n",cleaned,work); extract[0] = '\0'; if (*work == '/') { work++; isdir = true; } sscanf(work,"%[^/]",extract); rest = work + strlen(extract); if (strlen(extract) == 0) { if (isdir) { strcat(buffer,"/"); } (*function)(buffer,argptr); return; } if (! IsWildCard(extract)) { strcat(buffer,"/"); if (BufferOverflow(buffer,extract)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Culprit %s\n",extract); CfLog(cferror,OUTPUT,""); exit(0); } strcat(buffer,extract); ExpandWildCardsAndDo(rest,buffer,function,argptr); return; } else { strcat(buffer,"/"); if ((dirh=opendir(buffer)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open dir: %s\n",buffer); CfLog(cferror,OUTPUT,"opendir"); return; } count = 0; strcpy(construct,buffer); /* save relative path */ for (dp = readdir(dirh); dp != 0; dp = readdir(dirh)) { if (!SensibleFile(dp->d_name,buffer,NULL)) { continue; } count++; strcpy(buffer,construct); strcat(buffer,dp->d_name); if (stat(buffer,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n\n",buffer); CfLog(cferror,OUTPUT,"stat"); continue; } if ((S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode)) && WildMatch(extract,dp->d_name)) { ExpandWildCardsAndDo(rest,buffer,function,argptr); } } if (count == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"No directories matching %s in %s\n",extract,buffer); CfLog(cfinform,OUTPUT,""); return; } closedir(dirh); } } /*******************************************************************/ void RecFileCheck(char *startpath,void *vp) { struct File *ptr; struct stat sb; ptr = (struct File *)vp; Verbose("%s: Checking files in %s...\n",VPREFIX,startpath); if (!GetLock(ASUniqueName("files"),startpath,ptr->ifelapsed,ptr->expireafter,VUQNAME,CFSTARTTIME)) { return; } if (stat(startpath,&sb) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Directory %s cannot be accessed in files",startpath); CfLog(cfinform,OUTPUT,"stat"); ReleaseCurrentLock(); return; } CheckExistingFile("*",startpath,&sb,ptr); RecursiveCheck(startpath,ptr->recurse,0,ptr,&sb); ReleaseCurrentLock(); } /*******************************************************************/ void ProcessPendingPackages (struct Package *ptr,enum pkgmgrs pkgmgr, enum pkgactions action, struct Item **pending_pkgs) { switch(action) { case pkgaction_remove: RemovePackage(ptr,pkgmgr,pending_pkgs); break; case pkgaction_install: InstallPackage(ptr,pkgmgr,pending_pkgs); break; default: snprintf(OUTPUT,CF_BUFSIZE,"Internal error! Tried to process package with an unknown action: %d. This should never happen!\n", action); CfLog(cferror,OUTPUT,""); break; } } /*******************************************************************/ /* Level 3 */ /*******************************************************************/ void RecordFileSystemArrivals(DB *dbp,time_t mtime) { DBT key,value; char *keyval = strdup(ConvTimeKey(ctime(&mtime))); double new = 0,old = 0; Debug("Record fs hit at %s\n",keyval); memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); key.data = keyval; key.size = strlen(keyval)+1; if ((errno = dbp->get(dbp,NULL,&key,&value,0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp,errno,NULL); free(keyval); return; } old = 0.0; } else { memcpy(&old,value.data,sizeof(double)); } new = old + 0.5; /* Arbitrary counting scale (x+(x+1))/2 becomes like principal value / weighted av */ key.data = keyval; key.size = strlen(keyval)+1; value.data = (void *) &new; value.size = sizeof(double); if ((errno = dbp->put(dbp,NULL,&key,&value,0)) != 0) { CfLog(cferror,"db->put failed","db->put"); } free(keyval); } /*******************************************************************/ /* Toolkit fstab */ /*******************************************************************/ int MatchStringInFstab(char *str) { FILE *fp; if ((fp = fopen(VFSTAB[VSYSTEMHARDCLASS],"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open %s for reading\n",VFSTAB[VSYSTEMHARDCLASS]); CfLog(cferror,OUTPUT,"fopen"); return true; /* write nothing */ } while (!feof(fp)) { ReadLine(VBUFF,CF_BUFSIZE,fp); if (VBUFF[0] == '#') { continue; } if (strstr(VBUFF,str)) { fclose(fp); return true; } } fclose(fp); return(false); } cfengine-2.2.10/src/cfenvgraph.c0000644000175000001440000007167111004357776013373 00000000000000/* Copyright (C) 2001- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: cfenvgraph.c */ /* */ /* Created: Wed Apr 18 13:19:22 2001 */ /* */ /* Author: Mark */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include #include /*****************************************************************************/ /* Prototypes */ /*****************************************************************************/ void CheckOpts(int argc, char **argv); void Syntax(void); void ReadAverages(void); void SummarizeAverages(void); void WriteGraphFiles(void); void WriteHistograms(void); void DiskArrivals(void); void PeerIntermittency(void); void GetFQHN(void); void OpenFiles(void); void CloseFiles(void); void MagnifyNow(void); void OpenMagnifyFiles(void); void CloseMagnifyFiles(void); void EraseAverages(void); /*****************************************************************************/ struct option GRAPHOPTIONS[] = { { "help",no_argument,0,'h' }, { "file",required_argument,0,'f' }, { "erasehistory",required_argument,0,'E' }, { "outputdir",required_argument,0,'o' }, { "titles",no_argument,0,'t'}, { "timestamps",no_argument,0,'T'}, { "resolution",no_argument,0,'r'}, { "separate",no_argument,0,'s'}, { "no-error-bars",no_argument,0,'e'}, { "no-scaling",no_argument,0,'n'}, { "now",no_argument,0,'N'}, { "verbose",no_argument,0,'v'}, { NULL,0,0,0 } }; int TITLES = false; int TIMESTAMPS = false; int HIRES = false; int SEPARATE = false; int ERRORBARS = true; int NOSCALING = true; int NOWOPT = false; char FILENAME[CF_BUFSIZE]; unsigned int HISTOGRAM[CF_OBSERVABLES][7][CF_GRAINS]; int SMOOTHHISTOGRAM[CF_OBSERVABLES][7][CF_GRAINS]; char VFQNAME[CF_MAXVARSIZE]; char ERASE[CF_BUFSIZE]; int ERRNO; time_t NOW; DB *DBP; static struct Averages ENTRY,MAX,MIN,DET; char TIMEKEY[CF_SMALLBUF],FLNAME[CF_BUFSIZE],*sp; double AGE; FILE *FPAV=NULL,*FPVAR=NULL, *FPNOW=NULL; FILE *FPE[CF_OBSERVABLES],*FPQ[CF_OBSERVABLES]; FILE *FPM[CF_OBSERVABLES]; /*****************************************************************************/ int main (int argc,char **argv) { CheckOpts(argc,argv); GetFQHN(); if (strlen(ERASE) > 0) { EraseAverages(); exit(0); } ReadAverages(); SummarizeAverages(); if (strlen(FLNAME) == 0) { if (TIMESTAMPS) { if ((NOW = time((time_t *)NULL)) == -1) { Verbose("Couldn't read system clock\n"); } sprintf(FLNAME,"cfenvgraphs-%s-%s",CanonifyName(VFQNAME),ctime(&NOW)); } else { sprintf(FLNAME,"cfenvgraphs-snapshot-%s",CanonifyName(VFQNAME)); } } Verbose("Creating sub-directory %s\n",FLNAME); if (mkdir(FLNAME,0755) == -1) { Verbose("Writing to existing directory\n"); } if (chdir(FLNAME)) { perror("chdir"); exit(0); } Verbose("Writing data to sub-directory %s: \n x,y1,y2,y3...\n ",FLNAME); if (NOWOPT) { MagnifyNow(); } else { WriteGraphFiles(); WriteHistograms(); DiskArrivals(); PeerIntermittency(); } return 0; } /*****************************************************************************/ /* Level 1 */ /*****************************************************************************/ void GetFQHN() { FILE *pp; char cfcom[CF_BUFSIZE]; static char line[CF_BUFSIZE],*sp; snprintf(cfcom,CF_BUFSIZE-1,"%s/bin/cfagent -Q fqhost",CFWORKDIR); if ((pp=popen(cfcom,"r")) == NULL) { Verbose("Couldn't open cfengine data "); perror("popen"); exit(0); } line[0] = '\0'; fgets(line,CF_BUFSIZE,pp); for (sp = line; *sp != '\0'; sp++) { if (*sp == '=') { sp++; break; } } strcpy(VFQNAME,line); if (strlen(VFQNAME) == 0) { struct utsname sys; if (uname(&sys) == -1) { perror("uname "); exit(0); } strcpy(VFQNAME,sys.sysname); } else { VFQNAME[strlen(VFQNAME)-1] = '\0'; Verbose("Got fully qualified name (%s)\n",VFQNAME); } pclose(pp); } /****************************************************************************/ void ReadAverages() { int i; DBT key,value; Verbose("\nLooking for database %s\n",FILENAME); Verbose("\nFinding MAXimum values...\n\n"); Verbose("N.B. socket values are numbers in CLOSE_WAIT. See documentation.\n"); if ((ERRNO = db_create(&DBP,NULL,0)) != 0) { Verbose("Couldn't create average database %s\n",FILENAME); exit(1); } #ifdef CF_OLD_DB if ((ERRNO = (DBP->open)(DBP,FILENAME,NULL,DB_BTREE,DB_RDONLY,0644)) != 0) #else if ((ERRNO = (DBP->open)(DBP,NULL,FILENAME,NULL,DB_BTREE,DB_RDONLY,0644)) != 0) #endif { Verbose("Couldn't open average database %s\n",FILENAME); DBP->err(DBP,ERRNO,NULL); exit(1); } for (i = 0; i < CF_OBSERVABLES; i++) { MAX.Q[i].var = MAX.Q[i].expect = MAX.Q[i].q = 0.01; MIN.Q[i].var = MIN.Q[i].expect = MIN.Q[i].q = 9999.0; FPE[i] = FPQ[i] = NULL; } for (NOW = CF_MONDAY_MORNING; NOW < CF_MONDAY_MORNING+CF_WEEK; NOW += CF_MEASURE_INTERVAL) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); memset(&ENTRY,0,sizeof(ENTRY)); strcpy(TIMEKEY,GenTimeKey(NOW)); key.data = TIMEKEY; key.size = strlen(TIMEKEY)+1; if ((ERRNO = DBP->get(DBP,NULL,&key,&value,0)) != 0) { if (ERRNO != DB_NOTFOUND) { DBP->err(DBP,ERRNO,NULL); exit(1); } } if (value.data != NULL) { memcpy(&ENTRY,value.data,sizeof(ENTRY)); for (i = 0; i < CF_OBSERVABLES; i++) { if (fabs(ENTRY.Q[i].expect) > MAX.Q[i].expect) { MAX.Q[i].expect = fabs(ENTRY.Q[i].expect); } if (fabs(ENTRY.Q[i].q) > MAX.Q[i].q) { MAX.Q[i].q = fabs(ENTRY.Q[i].q); } if (fabs(ENTRY.Q[i].expect) < MIN.Q[i].expect) { MIN.Q[i].expect = fabs(ENTRY.Q[i].expect); } if (fabs(ENTRY.Q[i].q) < MIN.Q[i].q) { MIN.Q[i].q = fabs(ENTRY.Q[i].q); } } } } DBP->close(DBP,0); } /****************************************************************************/ void EraseAverages() { int i; DBT key,value; struct Item *list = NULL; Verbose("\nLooking through current database %s\n",FILENAME); list = SplitStringAsItemList(ERASE,','); if ((ERRNO = db_create(&DBP,NULL,0)) != 0) { Verbose("Couldn't create average database %s\n",FILENAME); exit(1); } #ifdef CF_OLD_DB if ((ERRNO = (DBP->open)(DBP,FILENAME,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((ERRNO = (DBP->open)(DBP,NULL,FILENAME,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { Verbose("Couldn't open average database %s\n",FILENAME); DBP->err(DBP,ERRNO,NULL); exit(1); } memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); for (i = 0; i < CF_OBSERVABLES; i++) { FPE[i] = FPQ[i] = NULL; } for (NOW = CF_MONDAY_MORNING; NOW < CF_MONDAY_MORNING+CF_WEEK; NOW += CF_MEASURE_INTERVAL) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); memset(&ENTRY,0,sizeof(ENTRY)); strcpy(TIMEKEY,GenTimeKey(NOW)); key.data = TIMEKEY; key.size = strlen(TIMEKEY)+1; if ((ERRNO = DBP->get(DBP,NULL,&key,&value,0)) != 0) { if (ERRNO != DB_NOTFOUND) { DBP->err(DBP,ERRNO,NULL); exit(1); } } if (value.data != NULL) { memcpy(&ENTRY,value.data,sizeof(ENTRY)); for (i = 0; i < CF_OBSERVABLES; i++) { if (IsItemIn(list,OBS[i][0])) { /* Set history but not most recent to zero */ ENTRY.Q[i].expect = 0; ENTRY.Q[i].var = 0; } } value.data = &ENTRY; if ((ERRNO = DBP->put(DBP,NULL,&key,&value,0)) != 0) { DBP->err(DBP,ERRNO,NULL); exit(1); } } } DBP->close(DBP,0); } /*****************************************************************************/ void SummarizeAverages() { int i; DBT key,value; Verbose(" x yN (Variable content)\n---------------------------------------------------------\n"); for (i = 0; i < CF_OBSERVABLES; i++) { Verbose("%2d. MAX <%-10s-in> = %10f - %10f u %10f\n",i,OBS[i][0],MIN.Q[i].expect,MAX.Q[i].expect,sqrt(MAX.Q[i].var)); } if ((ERRNO = db_create(&DBP,NULL,0)) != 0) { Verbose("Couldn't open average database %s\n",FILENAME); exit(1); } #ifdef CF_OLD_DB if ((ERRNO = (DBP->open)(DBP,FILENAME,NULL,DB_BTREE,DB_RDONLY,0644)) != 0) #else if ((ERRNO = (DBP->open)(DBP,NULL,FILENAME,NULL,DB_BTREE,DB_RDONLY,0644)) != 0) #endif { Verbose("Couldn't open average database %s\n",FILENAME); exit(1); } memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); key.data = "DATABASE_AGE"; key.size = strlen("DATABASE_AGE")+1; if ((ERRNO = DBP->get(DBP,NULL,&key,&value,0)) != 0) { if (ERRNO != DB_NOTFOUND) { DBP->err(DBP,ERRNO,NULL); exit(1); } } if (value.data != NULL) { AGE = *(double *)(value.data); Verbose("\n\nDATABASE_AGE %.1f (weeks)\n\n",AGE/CF_WEEK*CF_MEASURE_INTERVAL); } } /*****************************************************************************/ void WriteGraphFiles() { int its,i,j,k, count = 0; DBT key,value; struct stat statbuf; OpenFiles(); if (TITLES) { for (i = 0; i < CF_OBSERVABLES; i+=2) { fprintf(FPAV,"# Column %d: %s\n",i,OBS[i][0]); fprintf(FPVAR,"# Column %d: %s\n",i,OBS[i][0]); fprintf(FPNOW,"# Column %d: %s\n",i,OBS[i][0]); } fprintf(FPAV,"##############################################\n"); fprintf(FPVAR,"##############################################\n"); fprintf(FPNOW,"##############################################\n"); } if (HIRES) { its = 1; } else { its = 12; } NOW = CF_MONDAY_MORNING; memset(&ENTRY,0,sizeof(ENTRY)); while (NOW < CF_MONDAY_MORNING+CF_WEEK) { for (j = 0; j < its; j++) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); strcpy(TIMEKEY,GenTimeKey(NOW)); key.data = TIMEKEY; key.size = strlen(TIMEKEY)+1; if ((ERRNO = DBP->get(DBP,NULL,&key,&value,0)) != 0) { if (ERRNO != DB_NOTFOUND) { DBP->err(DBP,ERRNO,NULL); exit(1); } } /* Work out local average over grain size "its" */ if (value.data != NULL) { memcpy(&DET,value.data,sizeof(DET)); for (i = 0; i < CF_OBSERVABLES; i++) { ENTRY.Q[i].expect += DET.Q[i].expect/(double)its; ENTRY.Q[i].var += DET.Q[i].var/(double)its; ENTRY.Q[i].q += DET.Q[i].q/(double)its; } if (NOSCALING) { for (i = 1; i < CF_OBSERVABLES; i++) { MAX.Q[i].expect = 1; MAX.Q[i].q = 1; } } } NOW += CF_MEASURE_INTERVAL; count++; } /* Output the data in a plethora of files */ fprintf(FPAV,"%d ",count); fprintf(FPVAR,"%d ",count); fprintf(FPNOW,"%d ",count); for (i = 0; i < CF_OBSERVABLES; i++) { fprintf(FPAV,"%f ",ENTRY.Q[i].expect/MAX.Q[i].expect); fprintf(FPVAR,"%f ",ENTRY.Q[i].var/MAX.Q[i].var); fprintf(FPNOW,"%f ",ENTRY.Q[i].q/MAX.Q[i].q); } fprintf(FPAV,"\n"); fprintf(FPVAR,"\n"); fprintf(FPNOW,"\n"); if (SEPARATE) { for (i = 0; i < CF_OBSERVABLES; i++) { fprintf(FPE[i],"%d %f %f\n",count, ENTRY.Q[i].expect, sqrt(ENTRY.Q[i].var)); /* Use same scaling for Q so graphs can be merged */ fprintf(FPQ[i],"%d %f 0.0\n",count, ENTRY.Q[i].q); } } memset(&ENTRY,0,sizeof(ENTRY)); } DBP->close(DBP,0); CloseFiles(); } /*****************************************************************************/ void MagnifyNow() { int its,i,j,k, count = 0; DBT key,value; time_t now; OpenMagnifyFiles(); its = 1; /* detailed view */ now = time(NULL); NOW = now - (time_t)(4 * CF_TICKS_PER_HOUR); while (NOW < now) { memset(&ENTRY,0,sizeof(ENTRY)); for (j = 0; j < its; j++) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); strcpy(TIMEKEY,GenTimeKey(NOW)); key.data = TIMEKEY; key.size = strlen(TIMEKEY)+1; if ((ERRNO = DBP->get(DBP,NULL,&key,&value,0)) != 0) { if (ERRNO != DB_NOTFOUND) { DBP->err(DBP,ERRNO,NULL); exit(1); } } /* Work out local average over grain size "its" */ if (value.data != NULL) { memcpy(&DET,value.data,sizeof(DET)); for (i = 0; i < CF_OBSERVABLES; i++) { ENTRY.Q[i].expect += DET.Q[i].expect/(double)its; ENTRY.Q[i].var += DET.Q[i].var/(double)its; ENTRY.Q[i].q += DET.Q[i].q/(double)its; } if (NOSCALING) { for (i = 1; i < CF_OBSERVABLES; i++) { MAX.Q[i].expect = 1; MAX.Q[i].q = 1; } } } NOW += CF_MEASURE_INTERVAL; count++; } /* Output q and E/sig data in a plethora of files */ for (i = 0; i < CF_OBSERVABLES; i++) { fprintf(FPM[i],"%d %f %f %f\n",count, ENTRY.Q[i].expect, sqrt(ENTRY.Q[i].var),ENTRY.Q[i].q); } } DBP->close(DBP,0); CloseMagnifyFiles(); } /*****************************************************************************/ void WriteHistograms() { int i,j,k; /* Finally, look at the histograms */ for (i = 0; i < 7; i++) { for (j = 0; j < CF_OBSERVABLES; j++) { for (k = 0; k < CF_GRAINS; k++) { HISTOGRAM[j][i][k] = 0; } } } if (SEPARATE) { int position,day; int weekly[CF_OBSERVABLES][CF_GRAINS]; FILE *fp; snprintf(FLNAME,CF_BUFSIZE,"%s/state/histograms",CFWORKDIR); if ((fp = fopen(FLNAME,"r")) == NULL) { Verbose("Unable to load histogram data\n"); exit(1); } for (position = 0; position < CF_GRAINS; position++) { fscanf(fp,"%d ",&position); for (i = 0; i < CF_OBSERVABLES; i++) { for (day = 0; day < 7; day++) { fscanf(fp,"%d ",&(HISTOGRAM[i][day][position])); } weekly[i][position] = 0; } } fclose(fp); if (!HIRES) { /* Smooth daily and weekly histograms */ for (k = 1; k < CF_GRAINS-1; k++) { for (j = 0; j < CF_OBSERVABLES; j++) { for (i = 0; i < 7; i++) { SMOOTHHISTOGRAM[j][i][k] = ((double)(HISTOGRAM[j][i][k-1] + HISTOGRAM[j][i][k] + HISTOGRAM[j][i][k+1]))/3.0; } } } } else { for (k = 1; k < CF_GRAINS-1; k++) { for (j = 0; j < CF_OBSERVABLES; j++) { for (i = 0; i < 7; i++) { SMOOTHHISTOGRAM[j][i][k] = (double) HISTOGRAM[j][i][k]; } } } } for (i = 0; i < CF_OBSERVABLES; i++) { sprintf(FLNAME,"%s.distr",OBS[i][0]); if ((FPQ[i] = fopen(FLNAME,"w")) == NULL) { perror("fopen"); exit(1); } } /* Plot daily and weekly histograms */ for (k = 0; k < CF_GRAINS; k++) { int a; for (j = 0; j < CF_OBSERVABLES; j++) { for (i = 0; i < 7; i++) { weekly[j][k] += (int) (SMOOTHHISTOGRAM[j][i][k]+0.5); } } for (a = 0; a < CF_OBSERVABLES; a++) { fprintf(FPQ[a],"%d %d\n",k,weekly[a][k]); } } for (i = 0; i < CF_OBSERVABLES; i++) { fclose(FPQ[i]); } } } /*****************************************************************************/ void DiskArrivals(void) { DIR *dirh; FILE *fp; struct dirent *dirp; int count = 0, index = 0, i; char filename[CF_BUFSIZE],database[CF_BUFSIZE]; double val, maxval = 1.0, *array, grain = 0.0; time_t now; DBT key,value; DB *dbp = NULL; DB_ENV *dbenv = NULL; if ((array = (double *)malloc((int)CF_WEEK)) == NULL) { Verbose("Memory error"); perror("malloc"); return; } if ((dirh = opendir(CFWORKDIR)) == NULL) { Verbose("Can't open directory %s\n",CFWORKDIR); perror("opendir"); return; } Verbose("\n\nLooking for filesystem arrival process data in %s\n",CFWORKDIR); for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (strncmp(dirp->d_name,"scan:",5) == 0) { Verbose("Found %s - generating X,Y plot\n",dirp->d_name); snprintf(database,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,dirp->d_name); if ((ERRNO = db_create(&dbp,dbenv,0)) != 0) { Verbose("Couldn't open arrivals database %s\n",database); return; } #ifdef CF_OLD_DB if ((ERRNO = (dbp->open)(dbp,database,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((ERRNO = (dbp->open)(dbp,NULL,database,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { Verbose("Couldn't open database %s\n",database); dbp->close(dbp,0); continue; } maxval = 1.0; grain = 0.0; count = 0.0; index = 0; for (now = CF_MONDAY_MORNING; now < CF_MONDAY_MORNING+CF_WEEK; now += CF_MEASURE_INTERVAL) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); strcpy(TIMEKEY,GenTimeKey(now)); key.data = TIMEKEY; key.size = strlen(TIMEKEY)+1; if ((ERRNO = dbp->get(dbp,NULL,&key,&value,0)) != 0) { if (ERRNO != DB_NOTFOUND) { DBP->err(DBP,ERRNO,NULL); exit(1); } } if (value.data != NULL) { grain += (double)*(double *)(value.data); } else { grain = 0; } if (HIRES) { if (grain > maxval) { maxval = grain; } array[index] = grain; grain = 0.0; index++; } else { if (count % 12 == 0) { if (grain > maxval) { maxval = grain; } array[index] = grain; index++; grain = 0.0; } } count++; } dbp->close(dbp,0); snprintf(filename,CF_BUFSIZE-1,"%s.cfenv",dirp->d_name); if ((fp = fopen(filename,"w")) == NULL) { Verbose("Unable to open %s for writing\n",filename); perror("fopen"); return; } Verbose("Data points = %d\n",index); for (i = 0; i < index; i++) { if (i > 1 && i < index-1) { val = (array[i-1]+array[i]+array[i+1])/3.0; /* Smoothing */ } else { val = array[i]; } fprintf(fp,"%d %f\n",i,val/maxval*50.0); } fclose(fp); } } closedir(dirh); } /***************************************************************/ void PeerIntermittency() { DBT key,value; DB *dbp,*dbpent; DBC *dbcp; DB_ENV *dbenv = NULL, *dbenv2 = NULL; int i,ret; FILE *fp1,*fp2; char name[CF_BUFSIZE],hostname[CF_BUFSIZE],timekey[CF_MAXVARSIZE]; char out1[CF_BUFSIZE],out2[CF_BUFSIZE]; struct QPoint entry; struct Item *ip, *hostlist = NULL; double entropy,average,var,sum,sum_av; time_t now = time(NULL), then, lastseen = CF_WEEK; snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_LASTDB_FILE); average = (double) CF_HOUR; /* It will take a week for a host to be deemed reliable */ var = 0; if ((errno = db_create(&dbp,dbenv,0)) != 0) { Verbose("Couldn't open last-seen database %s\n",name); return; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbp->open)(dbp,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { Verbose("Couldn't open last-seen database %s\n",name); dbp->close(dbp,0); return; } if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { Verbose("Error reading from last-seen database\n"); dbp->err(dbp, ret, "DB->cursor"); return; } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); Verbose("Examining known peers...\n"); while (dbcp->c_get(dbcp, &key, &value, DB_NEXT) == 0) { strcpy(hostname,IPString2Hostname((char *)key.data+1)); if (!IsItemIn(hostlist,hostname)) { /* Check hostname not recorded twice with +/- */ AppendItem(&hostlist,hostname,NULL); Verbose("Examining intermittent host %s\n",hostname); } } dbcp->c_close(dbcp); dbp->close(dbp,0); /* Now go through each host and recompute entropy */ for (ip = hostlist; ip != NULL; ip=ip->next) { snprintf(out1,CF_BUFSIZE,"lastseen-%s.q",ip->name); Verbose("Opening %s\n",out1); if ((fp1 = fopen(out1,"w")) == NULL) { Verbose("Unable to open %s\n",out1); continue; } snprintf(out2,CF_BUFSIZE,"lastseen-%s.E-sigma",hostname); if ((fp2 = fopen(out2,"w")) == NULL) { Verbose("Unable to open %s\n",out1); continue; } snprintf(name,CF_BUFSIZE-1,"%s/%s.%s",CFWORKDIR,CF_LASTDB_FILE,ip->name); Verbose("Consulting profile %s\n",name); if ((errno = db_create(&dbpent,dbenv2,0)) != 0) { Verbose("Couldn't init reliability profile database %s\n",name); return; } #ifdef CF_OLD_DB if ((errno = (dbpent->open)(dbpent,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (dbpent->open)(dbpent,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { Verbose("Couldn't open last-seen database %s\n",name); continue; } for (now = CF_MONDAY_MORNING; now < CF_MONDAY_MORNING+CF_WEEK; now += CF_MEASURE_INTERVAL) { memset(&key,0,sizeof(key)); memset(&value,0,sizeof(value)); strcpy(timekey,GenTimeKey(now)); key.data = timekey; key.size = strlen(timekey)+1; if ((errno = dbpent->get(dbpent,NULL,&key,&value,0)) != 0) { if (errno != DB_NOTFOUND) { dbpent->err(dbp,errno,NULL); exit(1); } } if (value.data != NULL) { memcpy(&entry,value.data,sizeof(entry)); then = (time_t)entry.q; lastseen = now - then; if (lastseen < 0) { lastseen = 0; /* Never seen before, so pretend */ } average = (double)entry.expect; var = (double)entry.var; fprintf(fp2,"%d %lf %lf\n",now,average,sqrt(var)); } else { /* If we have no data, it means no contact for whatever reason. It could be unable to respond unwilling to respond, policy etc. Assume for argument that we expect regular responses ... */ lastseen += CF_MEASURE_INTERVAL; /* infer based on no data */ } fprintf(fp1,"%d %d\n",now,lastseen); } fclose(fp1); fclose(fp2); dbpent->close(dbpent,0); } DeleteItemList(hostlist); } /*****************************************************************************/ /* Level 2 */ /*****************************************************************************/ void CheckOpts(int argc,char **argv) { extern char *optarg; int optindex = 0; int c; /* XXX Initialize workdir for non privileged users */ strcpy(CFWORKDIR,WORKDIR); FLNAME[0] = '\0'; ERASE[0] = '\0'; VERBOSE = false; if (geteuid() > 0) { char *homedir; if ((homedir = getenv("HOME")) != NULL) { strcpy(CFWORKDIR,homedir); strcat(CFWORKDIR,"/.cfagent"); } } snprintf(FILENAME,CF_BUFSIZE,"%s/state/%s",CFWORKDIR,CF_AVDB_FILE); while ((c=getopt_long(argc,argv,"Thtf:o:rsenNEv:",GRAPHOPTIONS,&optindex)) != EOF) { switch ((char) c) { case 'E': strncpy(ERASE,optarg,CF_BUFSIZE-1); break; case 't': TITLES = true; break; case 'f': strcpy(FILENAME,optarg); break; case 'o': strcpy(FLNAME,optarg); Verbose("Setting output directory to s\n",FLNAME); break; case 'T': TIMESTAMPS = true; break; case 'v': VERBOSE = true; break; case 'r': HIRES = true; break; case 's': SEPARATE = true; break; case 'e': ERRORBARS = false; break; case 'n': NOSCALING = true; break; case 'N': NOWOPT = true; break; default: Syntax(); exit(1); } } } /*****************************************************************************/ void Syntax() { int i; printf("Cfengine Environment Graph Generator\n%s\n%s\n",VERSION,COPYRIGHT); printf("\n"); printf("Options:\n\n"); for (i=0; GRAPHOPTIONS[i].name != NULL; i++) { printf("--%-20s (-%c)\n",GRAPHOPTIONS[i].name,(char)GRAPHOPTIONS[i].val); } printf("\nBug reports to bug-cfengine@cfengine.org\n"); printf("General help to help-cfengine@cfengine.org\n"); printf("Info & fixes at http://www.cfengine.org\n"); } /*********************************************************************/ void OpenFiles() { int i; sprintf(FLNAME,"cfenv-average"); if ((FPAV = fopen(FLNAME,"w")) == NULL) { perror("fopen"); exit(1); } sprintf(FLNAME,"cfenv-stddev"); if ((FPVAR = fopen(FLNAME,"w")) == NULL) { perror("fopen"); exit(1); } sprintf(FLNAME,"cfenv-now"); if ((FPNOW = fopen(FLNAME,"w")) == NULL) { perror("fopen"); exit(1); } /* Now if -s open a file foreach metric! */ if (SEPARATE) { for (i = 0; i < CF_OBSERVABLES; i++) { sprintf(FLNAME,"%s.E-sigma",OBS[i][0]); if ((FPE[i] = fopen(FLNAME,"w")) == NULL) { perror("fopen"); exit(1); } sprintf(FLNAME,"%s.q",OBS[i][0]); if ((FPQ[i] = fopen(FLNAME,"w")) == NULL) { perror("fopen"); exit(1); } } } } /*********************************************************************/ void CloseFiles() { int i; fclose(FPAV); fclose(FPVAR); fclose(FPNOW); if (SEPARATE) { for (i = 0; i < CF_OBSERVABLES; i++) { fclose(FPE[i]); fclose(FPQ[i]); } } } /*********************************************************************/ void OpenMagnifyFiles() { int i; for (i = 0; i < CF_OBSERVABLES; i++) { sprintf(FLNAME,"%s.mag",OBS[i][0]); if ((FPM[i] = fopen(FLNAME,"w")) == NULL) { perror("fopen"); exit(1); } } } /*********************************************************************/ void CloseMagnifyFiles() { int i; for (i = 0; i < CF_OBSERVABLES; i++) { fclose(FPM[i]); } } cfengine-2.2.10/src/eval.c0000644000175000001440000005046311154770231012162 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Class string evaluation toolkit for cfengine */ /* */ /* Dependency: item.c toolkit */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ /* Object variables */ /*********************************************************************/ char *DAYTEXT[] = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; char *MONTHTEXT[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; /*********************************************************************/ int ShowClass(char *c1,char *c2) { regex_t rx,rxcache; regmatch_t pmatch; char buf[CF_BUFSIZE]; int code; if (c1 == NULL || c2 == NULL) { return true; } code = regcomp(&rx,c1,REG_EXTENDED); if (code != 0) { regerror(code,&rx,buf,CF_BUFSIZE-1); printf("Regular expression error %d for %s: %s\n", code,c1,buf); FatalError("Cannot use this for matching"); } else { if (regexec(&rx,c2,1,&pmatch,0) != 0) { return false; } } return true; } /*********************************************************************/ /* Level 1 */ /*********************************************************************/ int Day2Number(char *datestring) { int i = 0; for (i = 0; i < 7; i++) { if (strncmp(datestring,DAYTEXT[i],3) == 0) { return i; } } return -1; } /*********************************************************************/ int CountParentheses(char *str) { char *sp; int count = 0; for (sp = str; *sp != '\0'; sp++) { if (*sp == '(') { count++; } if (*sp == ')') { count--; } } return count; } /*********************************************************************/ int NestedParentheses(char *str) { char *sp; int count = 0; for (sp = str; *sp != '\0'; sp++) { if (*sp == '(') { count++; } } return count; } /*********************************************************************/ void AddInstallable(char *classlist) { char *sp, currentitem[CF_MAXVARSIZE]; if (classlist == NULL) { return; } Debug("AddInstallable(%s)\n",classlist); for (sp = classlist; *sp != '\0'; sp++) { currentitem[0] = '\0'; sscanf(sp,"%[^,:.]",currentitem); sp += strlen(currentitem); if (! IsItemIn(VALLADDCLASSES,currentitem)) { AppendItem(&VALLADDCLASSES,currentitem,NULL); } if (*sp == '\0') { break; } } } /*********************************************************************/ void AddPrefixedMultipleClasses(char *name,char *classlist) { char *sp, currentitem[CF_MAXVARSIZE],local[CF_MAXVARSIZE],pref[CF_BUFSIZE]; if ((classlist == NULL) || strlen(classlist) == 0) { return; } memset(local,0,CF_MAXVARSIZE); strncpy(local,classlist,CF_MAXVARSIZE-1); Debug("AddPrefixedMultipleClasses(%s,%s)\n",name,local); for (sp = local; *sp != '\0'; sp++) { memset(currentitem,0,CF_MAXVARSIZE); sscanf(sp,"%250[^.:,]",currentitem); sp += strlen(currentitem); pref[0] = '\0'; snprintf(pref,CF_BUFSIZE,"%s_%s",name,currentitem); if (IsHardClass(pref)) { FatalError("cfengine: You cannot use -D to define a reserved class!"); } AddClassToHeap(CanonifyName(pref)); } } /*********************************************************************/ void AddMultipleClasses(char *classlist) { char *sp, currentitem[CF_MAXVARSIZE],local[CF_MAXVARSIZE]; if ((classlist == NULL) || strlen(classlist) == 0) { return; } memset(local,0,CF_MAXVARSIZE); strncpy(local,classlist,CF_MAXVARSIZE-1); Debug("AddMultipleClasses(%s)\n",local); for (sp = local; *sp != '\0'; sp++) { memset(currentitem,0,CF_MAXVARSIZE); sscanf(sp,"%250[^.:,]",currentitem); sp += strlen(currentitem); if (IsHardClass(currentitem)) { FatalError("cfengine: You cannot use -D to define a reserved class!"); } AddClassToHeap(CanonifyName(currentitem)); } } /*********************************************************************/ void AddTimeClass(char *str) { int i; char buf2[10], buf3[10], buf4[10], buf5[10], buf[10], out[10]; time_t now = time(NULL); struct tm *tmv = gmtime(&now); snprintf(buf,9,"GMT_Hr%d\n",tmv->tm_hour); AddClassToHeap(buf); for (i = 0; i < 7; i++) { if (strncmp(DAYTEXT[i],str,3)==0) { AddClassToHeap(DAYTEXT[i]); break; } } sscanf(str,"%*s %s %s %s %s",buf2,buf3,buf4,buf5); /* Hours */ sscanf(buf4,"%[^:]",buf); sprintf(out,"Hr%s",buf); AddClassToHeap(out); memset(VHR,0,3); strncpy(VHR,buf,2); /* Minutes */ sscanf(buf4,"%*[^:]:%[^:]",buf); sprintf(out,"Min%s",buf); AddClassToHeap(out); memset(VMINUTE,0,3); strncpy(VMINUTE,buf,2); sscanf(buf,"%d",&i); switch ((i / 5)) { case 0: AddClassToHeap("Min00_05"); break; case 1: AddClassToHeap("Min05_10"); break; case 2: AddClassToHeap("Min10_15"); break; case 3: AddClassToHeap("Min15_20"); break; case 4: AddClassToHeap("Min20_25"); break; case 5: AddClassToHeap("Min25_30"); break; case 6: AddClassToHeap("Min30_35"); break; case 7: AddClassToHeap("Min35_40"); break; case 8: AddClassToHeap("Min40_45"); break; case 9: AddClassToHeap("Min45_50"); break; case 10: AddClassToHeap("Min50_55"); break; case 11: AddClassToHeap("Min55_00"); break; } /* Add quarters */ switch ((i / 15)) { case 0: AddClassToHeap("Q1"); sprintf(out,"Hr%s_Q1",VHR); AddClassToHeap(out); break; case 1: AddClassToHeap("Q2"); sprintf(out,"Hr%s_Q2",VHR); AddClassToHeap(out); break; case 2: AddClassToHeap("Q3"); sprintf(out,"Hr%s_Q3",VHR); AddClassToHeap(out); break; case 3: AddClassToHeap("Q4"); sprintf(out,"Hr%s_Q4",VHR); AddClassToHeap(out); break; } /* Day */ sprintf(out,"Day%s",buf3); AddClassToHeap(out); memset(VDAY,0,3); strncpy(VDAY,buf3,2); /* Month */ for (i = 0; i < 12; i++) { if (strncmp(MONTHTEXT[i],buf2,3)==0) { AddClassToHeap(MONTHTEXT[i]); memset(VMONTH,0,4); strncpy(VMONTH,MONTHTEXT[i],3); break; } } /* Year */ strcpy(VYEAR,buf5); sprintf(out,"Yr%s",buf5); AddClassToHeap(out); } /*******************************************************************/ int Month2Number(char *string) { int i; if (string == NULL) { return -1; } for (i = 0; i < 12; i++) { if (strncmp(MONTHTEXT[i],string,strlen(string))==0) { return i+1; break; } } return -1; } /*******************************************************************/ void AddClassToHeap(char *class) { Chop(class); Debug("AddClassToHeap(%s)\n",class); if (strlen(class) == 0) { return; } if (IsItemIn(ABORTHEAP,class)) { snprintf(OUTPUT,CF_BUFSIZE,"Cfagent aborted on defined class [%s]\n",class); CfLog(cferror,OUTPUT,""); exit(1); } if (IsItemIn(VHEAP,class)) { return; } AppendItem(&VHEAP,class,CONTEXTID); } /*********************************************************************/ void DeleteClassFromHeap(char *class) { DeleteItemLiteral(&VHEAP,class); } /*********************************************************************/ void DeleteClassesFromContext(char *context) { struct Item *ip,*np; Verbose("Purging private classes from context %s\n",context); for (ip = VHEAP; ip != NULL; ip = np) { np = ip->next; if (strcmp(ip->classes,context) == 0) { Verbose(" - Deleting %s \n",ip->name); DeleteItem(&VHEAP,ip); } } } /*********************************************************************/ int IsHardClass(char *sp) /* true if string matches a hardwired class e.g. hpux */ { int i; for (i = 2; CLASSTEXT[i] != '\0'; i++) { if (strcmp(CLASSTEXT[i],sp) == 0) { return(true); } } for (i = 0; i < 7; i++) { if (strcmp(DAYTEXT[i],sp)==0) { return(false); } } return(false); } /*******************************************************************/ int IsSpecialClass(char *class) { int value = -1; if (strncmp(class,"IfElapsed",strlen("IfElapsed")) == 0) { sscanf(class,"IfElapsed%d",&value); if (value < 0) { Silent("%s: silly IfElapsed parameter in action sequence, using default...\n",VPREFIX); return true; } if (!PARSING) { VIFELAPSED = value; Verbose(" IfElapsed time: %d minutes\n",VIFELAPSED); return true; } } if (strncmp(class,"ExpireAfter",strlen("ExpireAfter")) == 0) { sscanf(class,"ExpireAfter%d",&value); if (value <= 0) { Silent("%s: silly ExpireAter parameter in action sequence, using default...\n",VPREFIX); return true; } if (!PARSING) { VEXPIREAFTER = value; Verbose("\n ExpireAfter time: %d minutes\n",VEXPIREAFTER); return true; } } return false; } /*********************************************************************/ int IsExcluded(char *exception) { if (!IsDefinedClass(exception)) { Debug2("%s is excluded!\n",exception); return true; } return false; } /*********************************************************************/ int IsDefinedClass(char *class) /* Evaluates a.b.c|d.e.f etc and returns true if the class */ /* is currently true, given the defined heap and negations */ { int ret; Debug4("IsDefinedClass(%s,VADDCLASSES)\n",class); if (CfShow()) { return true; } if (class == NULL) { return true; } ret = EvaluateORString(class,VADDCLASSES,0); return ret; } /*********************************************************************/ int IsInstallable(char *class) /* Evaluates to true if the class string COULD become true in */ /* the course of the execution - but might not be true now */ { char buffer[CF_BUFSIZE], *sp; int i = 0, val; Debug1("IsInstallable(%s) -",class); if (CfShow()) { return true; } for (sp = class; *sp != '\0'; sp++) { if (*sp == '!') { continue; /* some actions might be presented as !class */ } buffer[i++] = *sp; } buffer[i] = '\0'; /* return (EvaluateORString(buffer,VALLADDCLASSES)||EvaluateORString(class,VADDCLASSES));*/ val = (EvaluateORString(buffer,VALLADDCLASSES,0)||EvaluateORString(class,VALLADDCLASSES,1)||EvaluateORString(class,VADDCLASSES,0)); if (val) { Debug1(" true\n"); } else { Debug1(" false\n"); } return val; } /*********************************************************************/ void NegateCompoundClass(char *class,struct Item **heap) { char *sp = class; char cbuff[CF_MAXVARSIZE]; Debug1("NegateCompoundClass(%s)",class); while(*sp != '\0') { sscanf(sp,"%255[^.]",cbuff); while ((*sp != '\0') && ((*sp !='.')||(*sp == '&'))) { sp++; } if ((*sp == '.') || (*sp == '&')) { sp++; } if (IsHardClass(cbuff)) { char err[CF_BUFSIZE]; yyerror("Illegal exception"); sprintf (err,"Cannot negate the reserved class [%s]\n",cbuff); FatalError(err); } AppendItem(heap,cbuff,NULL); } } /*********************************************************************/ /* Level 2 */ /*********************************************************************/ int EvaluateORString(char *class,struct Item *list,int fromIsInstallable) { char *sp, cbuff[CF_BUFSIZE]; int result = false; if (class == NULL) { return false; } Debug4("\n--------\nEvaluateORString(%s)\n",class); for (sp = class; *sp != '\0'; sp++) { while (*sp == '|') { sp++; } memset(cbuff,0,CF_BUFSIZE); sp += GetORAtom(sp,cbuff); if (strlen(cbuff) == 0) { break; } if (IsBracketed(cbuff)) /* Strip brackets */ { cbuff[strlen(cbuff)-1] = '\0'; result |= EvaluateORString(cbuff+1,list,fromIsInstallable); Debug4("EvalORString-temp-result-y=%d (%s)\n",result,cbuff+1); } else { result |= EvaluateANDString(cbuff,list,fromIsInstallable); Debug4("EvalORString-temp-result-n=%d (%s)\n",result,cbuff); } if (*sp == '\0') { break; } } Debug4("EvaluateORString(%s) returns %d\n",class,result); return result; } /*********************************************************************/ /* Level 3 */ /*********************************************************************/ int EvaluateANDString(char *class,struct Item *list,int fromIsInstallable) { char *sp, *atom; char cbuff[CF_BUFSIZE]; int count = 1; int negation = false; Debug4("EvaluateANDString(%s)\n",class); count = CountEvalAtoms(class); sp = class; while(*sp != '\0') { negation = false; while (*sp == '!') { negation = !negation; sp++; } memset(cbuff,0,CF_BUFSIZE); sp += GetANDAtom(sp,cbuff) + 1; atom = cbuff; /* Test for parentheses */ if (IsBracketed(cbuff)) { atom = cbuff+1; Debug4("Checking AND Atom %s?\n",atom); cbuff[strlen(cbuff)-1] = '\0'; if (EvaluateORString(atom,list,fromIsInstallable)) { if (negation) { Debug4("EvalANDString-temp-result-neg1=false\n"); return false; } else { Debug4("EvalORString-temp-result count=%d\n",count); count--; } } else { if (negation) { Debug4("EvalORString-temp-result2 count=%d\n",count); count--; } else { return false; } } continue; } else { atom = cbuff; } /* End of parenthesis check */ if (*sp == '.' || *sp == '&') { sp++; } Debug4("Checking OR atom (%s)?\n",atom); CheckCommonErrors(atom); if (IsItemIn(VNEGHEAP,atom)) { if (negation) { Debug4("EvalORString-temp-result3 count=%d\n",count); count--; } else { return false; } } else if (IsItemIn(VHEAP,atom)) { if (negation) { Debug4("EvaluateANDString(%s) returns false by negation 1\n",class); return false; } else { Debug4("EvalORString-temp-result3.5 count=%d\n",count); count--; } } else if (IsItemIn(list,atom)) { if (negation && !fromIsInstallable) { Debug4("EvaluateANDString(%s) returns false by negation 2\n",class); return false; } else { Debug4("EvalORString-temp-result3.6 count=%d\n",count); count--; } } else if (negation) /* ! (an undefined class) == true */ { Debug4("EvalORString-temp-result4 count=%d\n",count); count--; } else { Debug4("EvaluateANDString(%s) returns false ny negation 3\n",class); return false; } } if (count == 0) { Debug4("EvaluateANDString(%s) returns true\n",class); return(true); } else { Debug4("EvaluateANDString(%s) returns false\n",class); return(false); } } /*********************************************************************/ int GetORAtom(char *start,char *buffer) { char *sp = start; char *spc = buffer; int bracklevel = 0, len = 0; while ((*sp != '\0') && !((*sp == '|') && (bracklevel == 0))) { if (*sp == '(') { Debug4("+(\n"); bracklevel++; } if (*sp == ')') { Debug4("-)\n"); bracklevel--; } Debug4("(%c)",*sp); *spc++ = *sp++; len++; } *spc = '\0'; Debug4("\nGetORATom(%s)->%s\n",start,buffer); return len; } /*********************************************************************/ /* Level 4 */ /*********************************************************************/ int GetANDAtom(char *start,char *buffer) { char *sp = start; char *spc = buffer; int bracklevel = 0, len = 0; while ((*sp != '\0') && !(((*sp == '.')||(*sp == '&')) && (bracklevel == 0))) { if (*sp == '(') { Debug4("+(\n"); bracklevel++; } if (*sp == ')') { Debug("-)\n"); bracklevel--; } *spc++ = *sp++; len++; } *spc = '\0'; Debug4("\nGetANDATom(%s)->%s\n",start,buffer); return len; } /*********************************************************************/ int CountEvalAtoms(char *class) { char *sp; int count = 0, bracklevel = 0; for (sp = class; *sp != '\0'; sp++) { if (*sp == '(') { Debug4("+(\n"); bracklevel++; continue; } if (*sp == ')') { Debug4("-)\n"); bracklevel--; continue; } if ((bracklevel == 0) && ((*sp == '.')||(*sp == '&'))) { count++; } } if (bracklevel != 0) { sprintf(OUTPUT,"Bracket mismatch, in [class=%s], level = %d\n",class,bracklevel); yyerror(OUTPUT); FatalError("Aborted"); } return count+1; } /*********************************************************************/ /* TOOLKIT : actions */ /*********************************************************************/ enum actions ActionStringToCode (char *str) { char *sp; int i; enum actions action; action = none; for (sp = str; *sp != '\0'; sp++) { *sp = ToLower(*sp); if (*sp == ':') { *sp = '\0'; } } for (i = 1; ACTIONID[i] != '\0'; i++) { if (strcmp(ACTIONID[i],str) == 0) { action = (enum actions) i; break; } } if (action == none) { yyerror("Indexed macro specified no action"); FatalError("Could not compile action"); } return (enum actions) i; } /*********************************************************************/ int IsBracketed(char *s) /* return true if the entire string is bracketed, not just if if contains brackets */ { int i, level= 0; if (*s != '(') { return false; } for (i = 0; i < strlen(s)-1; i++) { if (s[i] == '(') { level++; } if (s[i] == ')') { level--; } if (level == 0) { return false; /* premature ) */ } } return true; } /****************************************************************/ int CfShow() /* is the this cfshow -r parser ? */ { switch (ACTION) { case control: case defaultroute: case import: return false; } if (INSTALLALL) { return true; } else { return false; } } /****************************************************************/ void CheckCommonErrors(char *atom) { } cfengine-2.2.10/src/conf.h.in0000644000175000001440000003022011170173266012562 00000000000000/* src/conf.h.in. Generated from configure.ac by autoheader. */ /* cfengine for GNU Copyright (C) 1995/6 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /* The old route entry structure in newer BSDs */ #undef HAVE_ORTENTRY /* Do we ahve any route entry structure ? */ #undef HAVE_RTENTRY /* Whether to use the local REGEX functions */ #undef REGEX_MALLOC /* Whether to use LCHOWN to change ownerships */ #undef HAVE_LCHOWN /* Whether the thread library has setmask */ #undef HAVE_PTHREAD_SIGMASK /* Whether the thread library has setstacksize */ #undef HAVE_PTHREAD_ATTR_SETSTACKSIZE /* Whether libdb has db_open */ #undef HAVE_DB_CREATE /* Does the host have /var/run directory? */ #undef HAVE_VAR_RUN /* Special OS defines */ #undef SUN3 #undef SUN4 #undef SOLARIS #undef ULTRIX #undef HPuUX #undef AIX #undef OSF #undef IRIX #undef LINUX #undef DEBIAN #undef FREEBSD #undef NETBSD #undef NEWS_OS #undef BSDOS #undef BSD43 #undef AOS #undef SCO #undef NEXTSTEP #undef CFCRAY #undef CFQNX #undef CFGNU #undef UNIXWARE #undef OPENBSD #undef HAVE_SYS_ACL_H #undef NOTBROKEN #undef NT #undef DARWIN /* SVR4 header stuff */ #undef __EXTENSIONS__ #undef _POSIX_C_SOURCE /* Solaris 2.6 */ #undef __BIT_TYPES_DEFINED__ /* LOCK and LOG directories */ #undef WORKDIR /* Special CFEngine symbols */ #undef AUTOCONF_HOSTNAME #undef AUTOCONF_SYSNAME /* Define if old Berkeley API */ #undef CF_OLD_DB /* Define to 1 if using `getloadavg.c'. */ #undef C_GETLOADAVG /* Define to 1 for DGUX with . */ #undef DGUX /* Define to 1 if the `getloadavg' function needs to be run setuid or setgid. */ #undef GETLOADAVG_PRIVILEGED /* Define to 1 if you have the `bcopy' function. */ #undef HAVE_BCOPY /* Define to 1 if you have the `chflags' function. */ #undef HAVE_CHFLAGS /* Define to 1 if the system has the type `clockid_t'. */ #undef HAVE_CLOCKID_T /* Define to 1 if you have the header file. */ #undef HAVE_DCE_DACLIF_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_DIRENT_H /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if you have the `door' function. */ #undef HAVE_DOOR /* Define to 1 if you have the `drand48' function. */ #undef HAVE_DRAND48 /* Define to 1 if you have the header file. */ #undef HAVE_DUSTAT_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `getaddrinfo' function. */ #undef HAVE_GETADDRINFO /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD /* Define to 1 if you have the `gethostname' function. */ #undef HAVE_GETHOSTNAME /* Define to 1 if you have the `getloadavg' function. */ #undef HAVE_GETLOADAVG /* Define to 1 if you have the `getnetgrent' function. */ #undef HAVE_GETNETGRENT /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `crypto' library (-lcrypto). */ #undef HAVE_LIBCRYPTO /* Define to 1 if you have the `db' library (-ldb). */ #undef HAVE_LIBDB /* Define to 1 if you have the `dce' library (-ldce). */ #undef HAVE_LIBDCE /* Define to 1 if you have the `dgc' library (-ldgc). */ #undef HAVE_LIBDGC /* Define to 1 if you have the `kstat' library (-lkstat). */ #undef HAVE_LIBKSTAT /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM /* Define to 1 if you have the `nsl' library (-lnsl). */ #undef HAVE_LIBNSL /* Define to 1 if you have the `nss_nis' library (-lnss_nis). */ #undef HAVE_LIBNSS_NIS /* Define to 1 if you have the `pthread' library (-lpthread). */ #undef HAVE_LIBPTHREAD /* Define to 1 if you have the `pthreads' library (-lpthreads). */ #undef HAVE_LIBPTHREADS /* Define to 1 if you have the `PW' library (-lPW). */ #undef HAVE_LIBPW /* Define to 1 if you have the `rt' library (-lrt). */ #undef HAVE_LIBRT /* Define to 1 if you have the `rx' library (-lrx). */ #undef HAVE_LIBRX /* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET /* Define to 1 if you have the `thread' library (-lthread). */ #undef HAVE_LIBTHREAD /* Define to 1 if you have the header file. */ #undef HAVE_MACH_MACH_H /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `mkfifo' function. */ #undef HAVE_MKFIFO /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_NLIST_H /* Define to 1 if you have the `pstat_getdynamic' function. */ #undef HAVE_PSTAT_GETDYNAMIC /* Define if you have POSIX threads libraries and header files. */ #undef HAVE_PTHREAD /* Define to 1 if you have the header file. */ #undef HAVE_PTHREAD_H /* Define to 1 if you have the `putenv' function. */ #undef HAVE_PUTENV /* Define to 1 if you have the `qsort' function. */ #undef HAVE_QSORT /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH /* Define to 1 if you have the `regcomp' function. */ #undef HAVE_REGCOMP /* Define to 1 if you have the header file. */ #undef HAVE_REGEX_H /* Define to 1 if you have the header file. */ #undef HAVE_RXPOSIX_H /* Define to 1 if you have the header file. */ #undef HAVE_SCHED_H /* Define to 1 if you have the `setegid' function. */ #undef HAVE_SETEGID /* Define to 1 if you have the `seteuid' function. */ #undef HAVE_SETEUID /* Define to 1 if you have the `setlocale' function. */ #undef HAVE_SETLOCALE /* Define to 1 if you have the `setregid' function. */ #undef HAVE_SETREGID /* Define to 1 if you have the `setreuid' function. */ #undef HAVE_SETREUID /* Define to 1 if you have the `setsid' function. */ #undef HAVE_SETSID /* Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF /* Define to 1 if you have the `srand48' function. */ #undef HAVE_SRAND48 /* Define to 1 if you have the `statfs' function. */ #undef HAVE_STATFS /* Define to 1 if you have the `statvfs' function. */ #undef HAVE_STATVFS /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strrchr' function. */ #undef HAVE_STRRCHR /* Define to 1 if you have the `strsep' function. */ #undef HAVE_STRSEP /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if `n_un.n_name' is member of `struct nlist'. */ #undef HAVE_STRUCT_NLIST_N_UN_N_NAME /* Define to 1 if `sa_len' is member of `struct sockaddr'. */ #undef HAVE_STRUCT_SOCKADDR_SA_LEN /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF /* Define to 1 if you have the `sysinfo' function. */ #undef HAVE_SYSINFO /* Define to 1 if you have the header file. */ #undef HAVE_SYS_ACL_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILESYS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_LOADAVG_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MALLOC_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_MOUNT_H /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_NDIR_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PARAM_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKIO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATVFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SYSTEMINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_VFS_H /* Define to 1 if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H /* Define to 1 if you have the header file. */ #undef HAVE_THREAD_H /* Define to 1 if you have the header file. */ #undef HAVE_TIME_H /* Define to 1 if you have the `uname' function. */ #undef HAVE_UNAME /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_UTIME_H /* Define to 1 if you have the header file. */ #undef HAVE_VFS_H /* Define to 1 if you have the `waitpid' function. */ #undef HAVE_WAITPID /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Define to 1 if your `struct nlist' has an `n_un' member. Obsolete, depend on `HAVE_STRUCT_NLIST_N_UN_N_NAME */ #undef NLIST_NAME_UNION /* Define to 1 if your C compiler doesn't accept -c and -o together. */ #undef NO_MINUS_C_MINUS_O /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to the necessary symbol if this constant uses a non-standard name on your system. */ #undef PTHREAD_CREATE_JOINABLE /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 on System V Release 4. */ #undef SVR4 /* Define to 1 if you can safely include both and . */ #undef TIME_WITH_SYS_TIME /* Define to 1 for Encore UMAX. */ #undef UMAX /* Define to 1 for Encore UMAX 4.3 that has instead of . */ #undef UMAX4_3 /* Define if BerkeleyDB is available. */ #undef USE_BERKELEY_DB /* Define if OpenSSL is available. */ #undef USE_OPENSSL_LIB /* Define if PCRE is available. */ #undef USE_PCRE /* Version number of package */ #undef VERSION /* Define if you want to use SELINUX */ #undef WITH_SELINUX /* Define if XEN cpuid-based HVM detection is available. */ #undef XEN_CPUID_SUPPORT /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a `char[]'. */ #undef YYTEXT_POINTER /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to `int' if doesn't define. */ #undef gid_t /* Define to `int' if does not define. */ #undef mode_t /* Define to `int' if does not define. */ #undef pid_t /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to `int' if doesn't define. */ #undef uid_t cfengine-2.2.10/src/image.c0000644000175000001440000012303711154765743012327 00000000000000/* Copyright (C) 1995- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* File Image copying */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ /* Level 1 */ /*********************************************************************/ void GetRemoteMethods() /* Schedule files matching pattern to be collected on next actionsequence -- this function should only be called during parsing since it uses covert variables that belong to the parser */ { struct Item*ip; char client[CF_BUFSIZE]; Banner("Looking for remote method collaborations"); NewParser(); for (ip = VRPCPEERLIST; ip != NULL; ip = ip->next) { strncpy(client,ip->name,MAXHOSTNAMELEN); if (strstr(ip->name,".")||strstr(ip->name,":")) { } else { strcat(client,"."); strcat(client,VDOMAIN); } if ((strcmp(client,VFQNAME) == 0) || (strcmp(client,VUQNAME) == 0)) { /* Do not need to do this to ourselves .. */ continue; } Verbose(" Hailing remote peer %s for messages for us\n",client); InitializeAction(); snprintf(DESTINATION,CF_BUFSIZE,"%s/rpc_in",CFWORKDIR); snprintf(CURRENTOBJECT,CF_BUFSIZE,"%s/rpc_out",CFWORKDIR); snprintf(FINDERTYPE,1,"*"); PLUSMASK = 0400; MINUSMASK = 0377; IMAGEBACKUP = 'n'; ENCRYPT = 'y'; strcpy(IMAGEACTION,"fix"); strcpy(CLASSBUFF,"any"); snprintf(VUIDNAME,CF_MAXVARSIZE,"%d",getuid()); snprintf(VGIDNAME,CF_MAXVARSIZE,"%d",getgid()); IMGCOMP = '>'; VRECURSE = 1; PIFELAPSED = 0; PEXPIREAFTER = 0; COPYTYPE = DEFAULTCOPYTYPE; InstallImageItem(FINDERTYPE,CURRENTOBJECT,PLUSMASK,MINUSMASK,DESTINATION, IMAGEACTION,VUIDNAME,VGIDNAME,IMGSIZE,IMGCOMP, VRECURSE,COPYTYPE,LINKTYPE,client); } DeleteParser(); Verbose("\nFinished with RPC\n\n"); } /*********************************************************************/ /* Level 2 */ /*********************************************************************/ void CheckImage(char *source,char *destination,struct Image *ip) { CFDIR *dirh; char sourcefile[CF_BUFSIZE]; char sourcedir[CF_BUFSIZE]; char destdir[CF_BUFSIZE]; char destfile[CF_BUFSIZE]; struct stat sourcestatbuf, deststatbuf; struct cfdirent *dirp; int save_uid, save_gid, found; Debug2("CheckImage (source=%s destination=%s)\n",source,destination); if (ip->linktype == 'n') { Debug("Treating links as files for %s\n",source); found = cfstat(source,&sourcestatbuf,ip); } else { found = cflstat(source,&sourcestatbuf,ip); } if (found == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",source); CfLog(cferror,OUTPUT,""); FlushClientCache(ip); AddMultipleClasses(ip->elsedef); AuditLog(ip->logaudit,ip->audit,ip->lineno,OUTPUT,CF_FAIL); return; } if (sourcestatbuf.st_nlink > 1) /* Preserve hard link structure when copying */ { RegisterHardLink(sourcestatbuf.st_ino,destination,ip); } save_uid = (ip->uid)->uid; save_gid = (ip->gid)->gid; if ((ip->uid)->uid == (uid_t)-1) /* Preserve uid and gid */ { (ip->uid)->uid = sourcestatbuf.st_uid; } if ((ip->gid)->gid == (gid_t)-1) { (ip->gid)->gid = sourcestatbuf.st_gid; } if (S_ISDIR(sourcestatbuf.st_mode)) { strcpy(sourcedir,source); AddSlash(sourcedir); strcpy(destdir,destination); AddSlash(destdir); if ((dirh = cfopendir(sourcedir,ip)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",sourcedir); CfLog(cfverbose,OUTPUT,"opendir"); FlushClientCache(ip); (ip->uid)->uid = save_uid; (ip->gid)->gid = save_gid; return; } /* Now check any overrides */ if (stat(destdir,&deststatbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat directory %s\n",destdir); CfLog(cferror,OUTPUT,"stat"); } else { CheckCopiedFile(ip->cf_findertype,destdir,&deststatbuf,&sourcestatbuf,ip); } for (dirp = cfreaddir(dirh,ip); dirp != NULL; dirp = cfreaddir(dirh,ip)) { if (!SensibleFile(dirp->d_name,sourcedir,ip)) { continue; } strcpy(sourcefile, sourcedir); if (BufferOverflow(sourcefile,dirp->d_name)) { FatalError("Culprit: CheckImage"); } strcat(sourcefile, dirp->d_name); strcpy(destfile, destdir); if (BufferOverflow(destfile,dirp->d_name)) { FatalError("Culprit: CheckImage"); } strcat(destfile, dirp->d_name); if (ip->linktype == 'n') { if (cfstat(sourcefile,&sourcestatbuf,ip) == -1) { printf("%s: Can't stat %s\n",VPREFIX,sourcefile); FlushClientCache(ip); (ip->uid)->uid = save_uid; (ip->gid)->gid = save_gid; return; } } else { if (cflstat(sourcefile,&sourcestatbuf,ip) == -1) { printf("%s: Can't stat %s\n",VPREFIX,sourcefile); FlushClientCache(ip); (ip->uid)->uid = save_uid; (ip->gid)->gid = save_gid; return; } } ImageCopy(sourcefile,destfile,sourcestatbuf,ip); } cfclosedir(dirh); FlushClientCache(ip); (ip->uid)->uid = save_uid; (ip->gid)->gid = save_gid; return; } strcpy(sourcefile,source); strcpy(destfile,destination); ImageCopy(sourcefile,destfile,sourcestatbuf,ip); (ip->uid)->uid = save_uid; (ip->gid)->gid = save_gid; FlushClientCache(ip); } /*********************************************************************/ void PurgeFiles(struct Item *filelist,char *directory,struct Item *inclusions) { DIR *dirh; struct stat statbuf; struct dirent *dirp; char filename[CF_BUFSIZE]; Debug("PurgeFiles(%s)\n",directory); /* If we purge with no authentication we wipe out EVERYTHING */ if (strlen(directory) < 2) { snprintf(OUTPUT,CF_BUFSIZE,"Purge of %s denied -- too dangerous!",directory); CfLog(cferror,OUTPUT,""); return; } if (!AUTHENTICATED) { Verbose("Not purging %s - no verified contact with server\n",directory); return; } if ((dirh = opendir(directory)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",directory); CfLog(cfverbose,OUTPUT,"cfopendir"); return; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,directory,NULL)) { continue; } if (! IsItemIn(filelist,dirp->d_name)) { strncpy(filename,directory,CF_BUFSIZE-2); AddSlash(filename); strncat(filename,dirp->d_name,CF_BUFSIZE-2); Debug("Checking purge %s..\n",filename); if (DONTDO) { printf("Need to purge %s from copy dest directory\n",filename); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Purging %s in copy dest directory\n",filename); CfLog(cfinform,OUTPUT,""); if (lstat(filename,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't stat %s while purging\n",filename); CfLog(cfverbose,OUTPUT,"stat"); } else if (S_ISDIR(statbuf.st_mode)) { struct Tidy tp; struct TidyPattern tpat; tp.maxrecurse = 2; tp.done = 'n'; tp.tidylist = &tpat; tp.next = NULL; tp.path = filename; tp.exclusions = inclusions; /* exclude means don't purge, i.e. include here */ tp.ignores = NULL; tpat.filters = NULL; tpat.recurse = CF_INF_RECURSE; tpat.age = 0; tpat.size = 0; tpat.pattern = strdup("*"); tpat.classes = strdup("any"); tpat.defines = NULL; tpat.elsedef = NULL; tpat.dirlinks = 'y'; tpat.travlinks = 'n'; tpat.rmdirs = 'y'; tpat.searchtype = 'a'; tpat.compress = 'n'; tpat.log = 'd'; tpat.inform = 'd'; tpat.next = NULL; RecursiveTidySpecialArea(filename,&tp,CF_INF_RECURSE,&statbuf); free(tpat.pattern); free(tpat.classes); chdir(".."); if (rmdir(filename) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't remove directory %s while purging\n",filename); CfLog(cfverbose,OUTPUT,"rmdir"); } continue; } else if (unlink(filename) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't unlink %s while purging\n",filename); CfLog(cfverbose,OUTPUT,""); } } } } closedir(dirh); } /*********************************************************************/ /* Level 3 */ /*********************************************************************/ void ImageCopy(char *sourcefile,char *destfile,struct stat sourcestatbuf,struct Image *ip) { char linkbuf[CF_BUFSIZE],server[CF_EXPANDSIZE],*lastnode; struct stat deststatbuf; struct Link empty; struct Item *ptr, *ptr1; int succeed = false,silent = false, enforcelinks; mode_t srcmode = sourcestatbuf.st_mode; int ok_to_copy = false, found; Debug2("ImageCopy(%s,%s,+%o,-%o)\n",sourcefile,destfile,ip->plus,ip->minus); ExpandVarstring(ip->server,server,NULL); if ((strcmp(sourcefile,destfile) == 0) && (strcmp(ip->server,"localhost") == 0)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Image loop: file/dir %s copies to itself",sourcefile); CfLog(cfinform,OUTPUT,""); return; } memset(&empty,0,sizeof(struct Link)); empty.nofile = true; if (IgnoredOrExcluded(image,sourcefile,ip->inclusions,ip->exclusions)) { return; } if (IsItemIn(VEXCLUDECACHE,destfile)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Skipping single-copied file %s class %s\n",destfile,ip->classes); CfLog(cfverbose,OUTPUT,""); return; } if (ip->linktype != 'n') { lastnode=ReadLastNode(sourcefile); if (IsWildItemIn(VLINKCOPIES,lastnode) || IsWildItemIn(ip->symlink,lastnode)) { Verbose("cfengine: copy item %s marked for linking instead\n",sourcefile); enforcelinks = ENFORCELINKS; ENFORCELINKS = true; switch (ip->linktype) { case 's': succeed = LinkFiles(destfile,sourcefile,&empty); break; case 'r': succeed = RelativeLink(destfile,sourcefile,&empty); break; case 'a': succeed = AbsoluteLink(destfile,sourcefile,&empty); break; default: printf("%s: internal error, link type was [%c] in ImageCopy\n",VPREFIX,ip->linktype); return; } ENFORCELINKS = enforcelinks; if (succeed) { if (lstat(destfile,&deststatbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't lstat %s\n",destfile); CfLog(cferror,OUTPUT,"lstat"); } else { CheckCopiedFile(ip->cf_findertype,destfile,&deststatbuf,&sourcestatbuf,ip); } } return; } } if (strcmp(ip->action,"silent") == 0) { silent = true; } memset(linkbuf,0,CF_BUFSIZE); found = lstat(destfile,&deststatbuf); if (found != -1) { if ((S_ISLNK(deststatbuf.st_mode) && (ip->linktype == 'n')) || (S_ISLNK(deststatbuf.st_mode) && ! S_ISLNK(sourcestatbuf.st_mode))) { if ((!S_ISLNK(sourcestatbuf.st_mode) && (ip->typecheck == 'y')) && (ip->linktype != 'n')) { printf("%s: image exists but destination type is silly (file/dir/link doesn't match) - %c\n",VPREFIX,ip->linktype); printf("%s: source=%s, dest=%s\n",VPREFIX,sourcefile,destfile); return; } if (DONTDO) { Verbose("Need to remove old symbolic link %s to make way for copy\n",destfile); } else { if (unlink(destfile) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't remove link %s",destfile); CfLog(cferror,OUTPUT,"unlink"); return; } Verbose("Removing old symbolic link %s to make way for copy\n",destfile); //ip->returnstatus = CF_CHG; found = -1; } } } if (ip->size != CF_NOSIZE) { switch (ip->comp) { case '<': if (sourcestatbuf.st_size > ip->size) { snprintf(OUTPUT,CF_BUFSIZE*2,"Source file %s is > %d bytes in copy (omitting)\n",sourcefile,ip->size); CfLog(cfinform,OUTPUT,""); return; } break; case '=': if (sourcestatbuf.st_size != ip->size) { snprintf(OUTPUT,CF_BUFSIZE*2,"Source file %s is not %d bytes in copy (omitting)\n",sourcefile,ip->size); CfLog(cfinform,OUTPUT,""); return; } break; default: if (sourcestatbuf.st_size < ip->size) { snprintf(OUTPUT,CF_BUFSIZE*2,"Source file %s is < %d bytes in copy (omitting)\n",sourcefile,ip->size); CfLog(cfinform,OUTPUT,""); return; } break; } } if (found == -1) { if (strcmp(ip->action,"warn") == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s is non-existent\n",destfile); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"(should be copy of %s)\n",sourcefile); CfLog(cferror,OUTPUT,""); return; } if (S_ISREG(srcmode) || (S_ISLNK(srcmode) && ip->linktype == 'n')) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s wasn't at destination (copying)",destfile); if (DONTDO) { printf("Need this: %s\n",OUTPUT); return; } CfLog(cfverbose,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"Copying from %s:%s\n",server,sourcefile); CfLog(cfinform,OUTPUT,""); if (CopyReg(sourcefile,destfile,sourcestatbuf,deststatbuf,ip)) { if (stat(destfile,&deststatbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",destfile); CfLog(cferror,OUTPUT,"stat"); } else { CheckCopiedFile(ip->cf_findertype,destfile,&deststatbuf,&sourcestatbuf,ip); } snprintf(OUTPUT,CF_BUFSIZE*2,"Copied from %s:%s\n",server,sourcefile); AuditLog(ip->logaudit,ip->audit,ip->lineno,OUTPUT,CF_CHG); AddMultipleClasses(ip->defines); if (ALL_SINGLECOPY || IsWildItemIn(VSINGLECOPY,destfile)) { if (!IsItemIn(VEXCLUDECACHE,destfile)) { Debug("Appending image %s class %s to singlecopy list\n",destfile,ip->classes); PrependItem(&VEXCLUDECACHE,destfile,NULL); } } for (ptr = VAUTODEFINE; ptr != NULL; ptr=ptr->next) { if (WildMatch(ptr->name,destfile)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Image %s was set to autodefine class %s\n",ptr->name,ptr->classes); CfLog(cfinform,OUTPUT,""); AddMultipleClasses(ptr->classes); } } } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Copy from %s:%s\n",server,sourcefile); AuditLog(ip->logaudit,ip->audit,ip->lineno,OUTPUT,CF_FAIL); AddMultipleClasses(ip->failover); } Debug2("Leaving ImageCopy\n"); return; } if (S_ISFIFO (srcmode)) { #ifdef HAVE_MKFIFO if (DONTDO) { Silent("%s: Make FIFO %s\n",VPREFIX,destfile); } else if (mkfifo (destfile,srcmode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot create fifo `%s'", destfile); CfLog(cferror,OUTPUT,"mkfifo"); AuditLog(ip->logaudit,ip->audit,ip->lineno,OUTPUT,CF_FAIL); return; } snprintf(OUTPUT,CF_BUFSIZE*2,"Created fifo %s", destfile); AuditLog(ip->logaudit,ip->audit,ip->lineno,OUTPUT,CF_CHG); AddMultipleClasses(ip->defines); #endif } else { if (S_ISBLK (srcmode) || S_ISCHR (srcmode) || S_ISSOCK (srcmode)) { if (DONTDO) { Silent("%s: Make BLK/CHR/SOCK %s\n",VPREFIX,destfile); } else if (mknod (destfile, srcmode, sourcestatbuf.st_rdev)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot create special file `%s'",destfile); CfLog(cferror,OUTPUT,"mknod"); return; } snprintf(OUTPUT,CF_BUFSIZE*2,"Created socket/device %s", destfile); AuditLog(ip->logaudit,ip->audit,ip->lineno,OUTPUT,CF_CHG); AddMultipleClasses(ip->defines); } } if (S_ISLNK(srcmode) && ip->linktype != 'n') { if (cfreadlink(sourcefile,linkbuf,CF_BUFSIZE,ip) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't readlink %s\n",sourcefile); CfLog(cferror,OUTPUT,""); Debug2("Leaving ImageCopy\n"); return; } snprintf(OUTPUT,CF_BUFSIZE*2,"Checking link from %s to %s\n",destfile,linkbuf); CfLog(cfverbose,OUTPUT,""); if (ip->linktype == 'a' && linkbuf[0] != '/') /* Not absolute path - must fix */ { strcpy(VBUFF,sourcefile); ChopLastNode(VBUFF); AddSlash(VBUFF); strncat(VBUFF,linkbuf,CF_BUFSIZE-1); strncpy(linkbuf,VBUFF,CF_BUFSIZE-1); } enforcelinks = ENFORCELINKS; ENFORCELINKS = true; switch (ip->linktype) { case 's': if (*linkbuf == '.') { succeed = RelativeLink(destfile,linkbuf,&empty); } else { succeed = LinkFiles(destfile,linkbuf,&empty); } break; case 'r': succeed = RelativeLink(destfile,linkbuf,&empty); break; case 'a': succeed = AbsoluteLink(destfile,linkbuf,&empty); break; case 'n': /* Link copied instead */ break; default: printf("cfengine: internal error, link type was [%c] in ImageCopy 2\n",ip->linktype); return; } ENFORCELINKS = enforcelinks; if (succeed) { if (lstat(destfile,&deststatbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't lstat %s\n",destfile); CfLog(cferror,OUTPUT,"lstat"); } else { CheckCopiedFile(ip->cf_findertype,destfile,&deststatbuf,&sourcestatbuf,ip); } snprintf(OUTPUT,CF_BUFSIZE*2,"Created link %s", destfile); AuditLog(ip->logaudit,ip->audit,ip->lineno,OUTPUT,CF_CHG); AddMultipleClasses(ip->defines); } } } else { Debug("Destination file %s exists\n",destfile); if (ip->force == 'n') { switch (ip->type) { case 'c': if (S_ISREG(deststatbuf.st_mode) && S_ISREG(srcmode)) { ok_to_copy = CompareCheckSums(sourcefile,destfile,ip,&sourcestatbuf,&deststatbuf); } else { CfLog(cfverbose,"Checksum comparison replaced by ctime: files not regular\n",""); snprintf(OUTPUT,CF_BUFSIZE*2,"%s -> %s\n",sourcefile,destfile); CfLog(cfverbose,OUTPUT,""); ok_to_copy = (deststatbuf.st_ctime < sourcestatbuf.st_ctime)||(deststatbuf.st_mtime < sourcestatbuf.st_mtime); } if (ok_to_copy && strcmp(ip->action,"warn") == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s has a wrong MD5 checksum (should be copy of %s)\n",destfile,sourcefile); CfLog(cfinform,OUTPUT,""); return; } break; case 'b': if (S_ISREG(deststatbuf.st_mode) && S_ISREG(srcmode)) { ok_to_copy = CompareBinarySums(sourcefile,destfile,ip,&sourcestatbuf,&deststatbuf); } else { CfLog(cfverbose,"Byte comparison replaced by ctime: files not regular\n",""); snprintf(OUTPUT,CF_BUFSIZE*2,"%s -> %s\n",sourcefile,destfile); CfLog(cfverbose,OUTPUT,""); ok_to_copy = (deststatbuf.st_ctime < sourcestatbuf.st_ctime)||(deststatbuf.st_mtime < sourcestatbuf.st_mtime); } if (ok_to_copy && strcmp(ip->action,"warn") == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s has a wrong binary checksum (should be copy of %s)\n",destfile,sourcefile); CfLog(cferror,OUTPUT,""); return; } break; case 'm': ok_to_copy = (deststatbuf.st_mtime < sourcestatbuf.st_mtime); if (ok_to_copy && strcmp(ip->action,"warn") == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s out of date (should be copy of %s)\n",destfile,sourcefile); CfLog(cferror,OUTPUT,""); return; } break; case 'a': ok_to_copy = (deststatbuf.st_ctime < sourcestatbuf.st_ctime)||(deststatbuf.st_mtime < sourcestatbuf.st_mtime)||CompareBinarySums(sourcefile,destfile,ip,&sourcestatbuf,&deststatbuf); if (ok_to_copy && strcmp(ip->action,"warn") == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s is updated somehow (should be copy of %s)\n",destfile,sourcefile); CfLog(cferror,OUTPUT,""); return; } break; default: ok_to_copy = (deststatbuf.st_ctime < sourcestatbuf.st_ctime)||(deststatbuf.st_mtime < sourcestatbuf.st_mtime); if (ok_to_copy && strcmp(ip->action,"warn") == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Image file %s out of date (should be copy of %s)\n",destfile,sourcefile); CfLog(cferror,OUTPUT,""); return; } break; } } if (ip->typecheck == 'y' && ip->linktype != 'n') { if ((S_ISDIR(deststatbuf.st_mode) && ! S_ISDIR(sourcestatbuf.st_mode)) || (S_ISREG(deststatbuf.st_mode) && ! S_ISREG(sourcestatbuf.st_mode)) || (S_ISBLK(deststatbuf.st_mode) && ! S_ISBLK(sourcestatbuf.st_mode)) || (S_ISCHR(deststatbuf.st_mode) && ! S_ISCHR(sourcestatbuf.st_mode)) || (S_ISSOCK(deststatbuf.st_mode) && ! S_ISSOCK(sourcestatbuf.st_mode)) || (S_ISFIFO(deststatbuf.st_mode) && ! S_ISFIFO(sourcestatbuf.st_mode)) || (S_ISLNK(deststatbuf.st_mode) && ! S_ISLNK(sourcestatbuf.st_mode))) { snprintf(OUTPUT,CF_BUFSIZE,"Image exists but src/dest type mismatch source=%s, dest=%s\n",sourcefile,destfile); CfLog(cfinform,OUTPUT,""); AuditLog(ip->logaudit,ip->audit,ip->lineno,OUTPUT,CF_FAIL); return; } } if ((ip->force == 'y') || ok_to_copy || S_ISLNK(sourcestatbuf.st_mode)) /* Always check links */ { if (S_ISREG(srcmode) || ip->linktype == 'n') { snprintf(OUTPUT,CF_BUFSIZE*2,"Updated image %s from master %s on %s",destfile,sourcefile,server); if (DONTDO) { printf("Need: %s\n",OUTPUT); return; } CfLog(cfinform,OUTPUT,""); AuditLog(ip->logaudit,ip->audit,ip->lineno,OUTPUT,CF_CHG); AddMultipleClasses(ip->defines); for (ptr = VAUTODEFINE; ptr != NULL; ptr=ptr->next) { if (WildMatch(ptr->name,destfile)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Image %s was set to autodefine class %s\n",ptr->name,ptr->classes); CfLog(cfinform,OUTPUT,""); AddMultipleClasses(ptr->classes); } } if (CopyReg(sourcefile,destfile,sourcestatbuf,deststatbuf,ip)) { if (stat(destfile,&deststatbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",destfile); CfLog(cferror,OUTPUT,"stat"); AuditLog(ip->logaudit,ip->audit,ip->lineno,OUTPUT,CF_FAIL); } else { CheckCopiedFile(ip->cf_findertype,destfile,&deststatbuf,&sourcestatbuf,ip); } if (ALL_SINGLECOPY || IsWildItemIn(VSINGLECOPY,destfile)) { if (!IsItemIn(VEXCLUDECACHE,destfile)) { Debug("Appending image %s class %s to singlecopy list\n",destfile,ip->classes); PrependItem(&VEXCLUDECACHE,destfile,NULL); } } } else { AddMultipleClasses(ip->failover); } return; } if (S_ISLNK(sourcestatbuf.st_mode)) { if (cfreadlink(sourcefile,linkbuf,CF_BUFSIZE,ip) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't readlink %s\n",sourcefile); CfLog(cferror,OUTPUT,""); return; } snprintf(OUTPUT,CF_BUFSIZE*2,"Checking link from %s to %s\n",destfile,linkbuf); CfLog(cfverbose,OUTPUT,""); enforcelinks = ENFORCELINKS; ENFORCELINKS = true; switch (ip->linktype) { case 's': if (*linkbuf == '.') { succeed = RelativeLink(destfile,linkbuf,&empty); } else { succeed = LinkFiles(destfile,linkbuf,&empty); } break; case 'r': succeed = RelativeLink(destfile,linkbuf,&empty); break; case 'a': succeed = AbsoluteLink(destfile,linkbuf,&empty); break; default: snprintf(OUTPUT,CF_BUFSIZE,"Internal error, link type was [%c] in ImageCopy\n",ip->linktype); CfLog(cferror,OUTPUT,""); return; } ENFORCELINKS = enforcelinks; if (succeed) { CheckCopiedFile(ip->cf_findertype,destfile,&deststatbuf,&sourcestatbuf,ip); } ENFORCELINKS = enforcelinks; } } else { /* This check should go into CheckCopiedFile ip->returnstatus = CF_FAIL; */ CheckCopiedFile(ip->cf_findertype,destfile,&deststatbuf,&sourcestatbuf,ip); /* Now we have to check for single copy, even though nothing was copied otherwise we can get oscillations between multipe versions if type is based on a checksum */ if (ALL_SINGLECOPY || IsWildItemIn(VSINGLECOPY,destfile)) { if (!IsItemIn(VEXCLUDECACHE,destfile)) { Debug("Appending image %s class %s to singlecopy list\n",destfile,ip->classes); PrependItem(&VEXCLUDECACHE,destfile,NULL); } } Debug("Image file is up to date: %s\n",destfile); AddMultipleClasses(ip->elsedef); } } } /*********************************************************************/ int cfstat(char *file,struct stat *buf,struct Image *ip) /* wrapper for network access */ { int res; if (ip == NULL) { return stat(file,buf); } if (strcmp(ip->server,"localhost") == 0) { res = stat(file,buf); CheckForHoles(buf,ip); return res; } else { return cf_rstat(file,buf,ip,"file"); } } /*********************************************************************/ int cflstat(char *file,struct stat *buf,struct Image *ip) /* wrapper for network access */ { int res; if (ip == NULL) { return lstat(file,buf); } if (strcmp(ip->server,"localhost") == 0) { res = lstat(file,buf); CheckForHoles(buf,ip); return res; } else { /* read cache if possible */ return cf_rstat(file,buf,ip,"link"); } } /*********************************************************************/ int cfreadlink(char *sourcefile,char *linkbuf,int buffsize,struct Image *ip) /* wrapper for network access */ { struct cfstat *sp; memset(linkbuf,0,buffsize); if (strcmp(ip->server,"localhost") == 0) { return readlink(sourcefile,linkbuf,buffsize-1); } for (sp = ip->cache; sp != NULL; sp=sp->next) { if ((strcmp(ip->server,sp->cf_server) == 0) && (strcmp(sourcefile,sp->cf_filename) == 0)) { if (sp->cf_readlink != NULL) { if (strlen(sp->cf_readlink)+1 > buffsize) { printf("%s: readlink value is too large in cfreadlink\n",VPREFIX); printf("%s: [%s]]n",VPREFIX,sp->cf_readlink); return -1; } else { memset(linkbuf,0,buffsize); strcpy(linkbuf,sp->cf_readlink); return 0; } } } } return -1; } /*********************************************************************/ CFDIR *cfopendir(char *name,struct Image *ip) { CFDIR *cf_ropendir(),*returnval; if (strcmp(ip->server,"localhost") == 0) { if ((returnval = (CFDIR *)malloc(sizeof(CFDIR))) == NULL) { FatalError("Can't allocate memory in cfopendir()\n"); } returnval->cf_list = NULL; returnval->cf_listpos = NULL; returnval->cf_dirh = opendir(name); if (returnval->cf_dirh != NULL) { return returnval; } else { free ((char *)returnval); return NULL; } } else { return cf_ropendir(name,ip); } } /*********************************************************************/ struct cfdirent *cfreaddir(CFDIR *cfdirh,struct Image *ip) /* We need this cfdirent type to handle the weird hack */ /* used in SVR4/solaris dirent structures */ { static struct cfdirent dir; struct dirent *dirp; memset(dir.d_name,0,CF_BUFSIZE); if (strcmp(ip->server,"localhost") == 0) { dirp = readdir(cfdirh->cf_dirh); if (dirp == NULL) { return NULL; } strncpy(dir.d_name,dirp->d_name,CF_BUFSIZE-1); return &dir; } else { if (cfdirh->cf_listpos != NULL) { strncpy(dir.d_name,(cfdirh->cf_listpos)->name,CF_BUFSIZE); cfdirh->cf_listpos = cfdirh->cf_listpos->next; return &dir; } else { return NULL; } } } /*********************************************************************/ void cfclosedir(CFDIR *dirh) { if ((dirh != NULL) && (dirh->cf_dirh != NULL)) { closedir(dirh->cf_dirh); } Debug("cfclosedir()\n"); DeleteItemList(dirh->cf_list); free((char *)dirh); } /*********************************************************************/ /* Level 4 */ /*********************************************************************/ int CopyReg(char *source,char *dest,struct stat sstat,struct stat dstat,struct Image *ip) { char backup[CF_BUFSIZE]; char new[CF_BUFSIZE], *linkable; int remote = false, silent, backupisdir=false, backupok=false; struct stat s; #ifdef HAVE_UTIME_H struct utimbuf timebuf; #endif #ifdef DARWIN /* For later copy from new to dest */ char *rsrcbuf; int rsrcbytesr; /* read */ int rsrcbytesw; /* written */ int rsrcbytesl; /* to read */ int rsrcrd; int rsrcwd; /* Keep track of if a resrouce fork */ char * tmpstr; char * forkpointer; int rsrcfork; rsrcfork=0; #endif #ifdef WITH_SELINUX int selinux_enabled=0; /* need to keep track of security context of destination file (if any) */ security_context_t scontext=NULL; struct stat cur_dest; int dest_exists; selinux_enabled = (is_selinux_enabled()>0); #endif Debug2("CopyReg(%s,%s)\n",source,dest); if (DONTDO) { printf("%s: copy from %s to %s\n",VPREFIX,source,dest); return false; } #ifdef WITH_SELINUX if(selinux_enabled) { dest_exists = stat(dest,&cur_dest); if (dest_exists == 0) { /* get current security context of destination file */ getfilecon(dest,&scontext); } else { /* use default security context when creating destination file */ matchpathcon(dest,0,&scontext); setfscreatecon(scontext); } } #endif /* Make an assoc array of inodes used to preserve hard links */ linkable = CompressedArrayValue(ip->inode_cache,sstat.st_ino); if (sstat.st_nlink > 1) /* Preserve hard links, if possible */ { if (CompressedArrayElementExists(ip->inode_cache,sstat.st_ino) && (strcmp(dest,linkable) != 0)) { unlink(dest); silent = SILENT; SILENT = true; DoHardLink(dest,linkable,NULL); SILENT = silent; return true; } } if (strcmp(ip->server,"localhost") != 0) { Debug("This is a remote copy from server: %s\n",ip->server); remote = true; } #ifdef DARWIN if (strstr(dest, _PATH_RSRCFORKSPEC)) { /* Need to munge the "new" name */ rsrcfork = 1; tmpstr = malloc(CF_BUFSIZE); /* Drop _PATH_RSRCFORKSPEC */ strncpy(tmpstr, dest, CF_BUFSIZE); forkpointer = strstr(tmpstr, _PATH_RSRCFORKSPEC); *forkpointer = '\0'; strncpy(new, tmpstr, CF_BUFSIZE); free(tmpstr); } else { #endif if (BufferOverflow(dest,CF_NEW)) { printf(" culprit: CopyReg\n"); return false; } strcpy(new,dest); #ifdef DARWIN } #endif strcat(new,CF_NEW); if (remote) { if (CONN->error) { return false; } if (!CopyRegNet(source,new,ip,sstat.st_size)) { return false; } } else { if (!CopyRegDisk(source,new,ip)) { return false; } if (ip->stealth == 'y') { #ifdef HAVE_UTIME_H timebuf.actime = sstat.st_atime; timebuf.modtime = sstat.st_mtime; utime(source,&timebuf); #endif } } Debug("CopyReg succeeded in copying to %s to %s\n",source,new); if (IMAGEBACKUP != 'n') { char stamp[CF_BUFSIZE]; time_t STAMPNOW; Debug("Backup file %s\n",source); STAMPNOW = time((time_t *)NULL); sprintf(stamp, "_%d_%s", CFSTARTTIME, CanonifyName(ctime(&STAMPNOW))); if (BufferOverflow(dest,stamp)) { printf(" culprit: CopyReg\n"); return false; } strcpy(backup,dest); if (IMAGEBACKUP == 's') { strcat(backup,stamp); } /* rely on prior BufferOverflow() and on strlen(CF_SAVED) < CF_BUFFERMARGIN */ strcat(backup,CF_SAVED); /* Now in case of multiple copies of same object, try to avoid overwriting original backup */ if (lstat(backup,&s) != -1) { if (S_ISDIR(s.st_mode)) /* if there is a dir in the way */ { backupisdir = true; PurgeFiles(NULL,backup,NULL); rmdir(backup); } unlink(backup); } if (rename(dest,backup) == -1) { /* ignore */ } backupok = (lstat(backup,&s) != -1); /* Did the rename() succeed? NFS-safe */ } else { /* Mainly important if there is a dir in the way */ if (stat(dest,&s) != -1) { if (S_ISDIR(s.st_mode)) { PurgeFiles(NULL,dest,NULL); rmdir(dest); } } } if (stat(new,&dstat) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat new file %s\n",new); CfLog(cferror,OUTPUT,"stat"); return false; } if (dstat.st_size != sstat.st_size) { snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING: new file %s seems to have been corrupted in transit (sizes %d and %d), aborting!\n",new, (int) dstat.st_size, (int) sstat.st_size); CfLog(cfverbose,OUTPUT,""); if (backupok) { rename(backup,dest); /* ignore failure */ } return false; } if (ip->verify == 'y') { Verbose("Final verification of transmission.\n"); if (CompareCheckSums(source,new,ip,&sstat,&dstat)) { snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING: new file %s seems to have been corrupted in transit, aborting!\n",new); CfLog(cfverbose,OUTPUT,""); if (backupok) { rename(backup,dest); /* ignore failure */ } return false; } } #ifdef DARWIN if (rsrcfork) { /* Can't just "mv" the resource fork, unfortunately */ rsrcrd = open(new, O_RDONLY|O_BINARY); rsrcwd = open(dest, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, 0600); if (rsrcrd == -1 || rsrcwd == -1) { snprintf(OUTPUT, CF_BUFSIZE, "Open of rsrcrd/rsrcwd failed\n"); CfLog(cfinform,OUTPUT,"open"); close(rsrcrd); close(rsrcwd); return(false); } rsrcbuf = malloc(CF_BUFSIZE); rsrcbytesr = 0; while(1) { rsrcbytesr = read(rsrcrd, rsrcbuf, CF_BUFSIZE); if (rsrcbytesr == -1) { /* Ck error */ if (errno == EINTR) { continue; } else { snprintf(OUTPUT, CF_BUFSIZE, "Read of rsrcrd failed\n"); CfLog(cfinform,OUTPUT,"read"); close(rsrcrd); close(rsrcwd); free(rsrcbuf); return(false); } } else if (rsrcbytesr == 0) { /* Reached EOF */ close(rsrcrd); close(rsrcwd); free(rsrcbuf); unlink(new); /* Go ahead and unlink .cfnew */ break; } rsrcbytesl = rsrcbytesr; rsrcbytesw = 0; while (rsrcbytesl > 0) { rsrcbytesw += write(rsrcwd, rsrcbuf, rsrcbytesl); if (rsrcbytesw == -1) { /* Ck error */ if (errno == EINTR) { continue; } else { snprintf(OUTPUT, CF_BUFSIZE, "Write of rsrcwd failed\n"); CfLog(cfinform,OUTPUT,"write"); close(rsrcrd); close(rsrcwd); free(rsrcbuf); return(false); } } rsrcbytesl = rsrcbytesr - rsrcbytesw; } } } else { #endif if (rename(new,dest) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Problem: could not install copy file as %s, directory in the way?\n",dest); CfLog(cferror,OUTPUT,"rename"); if (backupok) { rename(backup,dest); /* ignore failure */ } return false; } #ifdef DARWIN } #endif if ((IMAGEBACKUP != 'n') && backupisdir) { snprintf(OUTPUT,CF_BUFSIZE,"Cannot move a directory to repository, leaving at %s",backup); CfLog(cfinform,OUTPUT,""); } else if ((IMAGEBACKUP != 'n') && Repository(backup,ip->repository)) { unlink(backup); } if (ip->preservetimes == 'y') { #ifdef HAVE_UTIME_H timebuf.actime = sstat.st_atime; timebuf.modtime = sstat.st_mtime; utime(dest,&timebuf); #endif } #ifdef WITH_SELINUX if(selinux_enabled) { if(dest_exists == 0) { /* set dest context to whatever it was before copy */ setfilecon(dest,scontext); } else { /* set create context back to default */ setfscreatecon(NULL); } freecon(scontext); } #endif return true; } /*********************************************************************/ /* Level 3 */ /*********************************************************************/ void RegisterHardLink(int i,char *value,struct Image *ip) { if (!FixCompressedArrayValue(i,value,&(ip->inode_cache))) { /* Not root hard link, remove to preserve consistency */ if (DONTDO) { Verbose("Need to remove old hard link %s to preserve structure..\n",value); } else { if (strcmp(ip->action,"warn") == 0) { Verbose("Need to remove old hard link %s to preserve structure..\n",value); } else { Verbose("Removing old hard link %s to preserve structure..\n",value); unlink(value); } } } } cfengine-2.2.10/src/modules.c0000644000175000001440000001325010703322440012666 00000000000000/* cfengine for GNU Copyright (C) 1995- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: modules.c */ /* */ /* Created: Sun Jan 25 13:27:33 2004 */ /* */ /* Author: > */ /* */ /* Revision: $Id$ */ /* */ /* Description: */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" void CheckClass(char *class, char *source); /*******************************************************************/ int CheckForModule(char *actiontxt,char *args) { struct stat statbuf; char line[CF_BUFSIZE],command[CF_EXPANDSIZE],name[CF_MAXVARSIZE],content[CF_BUFSIZE],ebuff[CF_EXPANDSIZE],*sp; FILE *pp; int print; if (NOMODULES) { return false; } if (*actiontxt == '/') { snprintf(OUTPUT,CF_BUFSIZE,"Absolute module path (%s) should be named relative to the authorized module directory",actiontxt); CfLog(cferror,OUTPUT,""); } if (GetMacroValue(CONTEXTID,"moduledirectory")) { ExpandVarstring("$(moduledirectory)",ebuff,NULL); } else { snprintf(ebuff,CF_BUFSIZE,"%s/modules",VLOCKDIR); } AddSlash(ebuff); strcat(ebuff,actiontxt); if (stat(ebuff,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"(Plug-in %s not found)",ebuff); Banner(OUTPUT); return false; } if ((statbuf.st_uid != 0) && (statbuf.st_uid != getuid())) { snprintf(OUTPUT,CF_BUFSIZE*2,"Module %s was not owned by uid=%d executing cfagent\n",ebuff,getuid()); CfLog(cferror,OUTPUT,""); return false; } snprintf(OUTPUT,CF_BUFSIZE*2,"Plug-in `%s\'",actiontxt); Banner(OUTPUT); strcat(ebuff," "); if (BufferOverflow(ebuff,args)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Culprit: class list for module (shouldn't happen)\n" ); CfLog(cferror,OUTPUT,""); return false; } strcat(ebuff,args); ExpandVarstring(ebuff,command,NULL); Verbose("Exec module [%s]\n",command); if ((pp = cfpopen(command,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open pipe from %s\n",actiontxt); CfLog(cferror,OUTPUT,"cfpopen"); return false; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",actiontxt); CfLog(cferror,OUTPUT,"ferror"); break; } ReadLine(line,CF_BUFSIZE,pp); if (strlen(line) > CF_BUFSIZE - 80) { snprintf(OUTPUT,CF_BUFSIZE*2,"Line from module %s is too long to be sensible\n",actiontxt); CfLog(cferror,OUTPUT,""); break; } if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",actiontxt); CfLog(cferror,OUTPUT,"ferror"); break; } print = false; for (sp = line; *sp != '\0'; sp++) { if (! isspace((int)*sp)) { print = true; break; } } switch (*line) { case '+': Verbose("Activated classes: %s\n",line+1); CheckClass(line+1,command); AddMultipleClasses(line+1); break; case '-': Verbose("Deactivated classes: %s\n",line+1); CheckClass(line+1,command); NegateCompoundClass(line+1,&VNEGHEAP); break; case '=': content[0] = '\0'; sscanf(line+1,"%[^=]=%[^\n]",name,content); Verbose("Defined Macro: %s, Value: %s\n",name,content); AddMacroValue(CONTEXTID,name,content); break; default: if (print) { snprintf(OUTPUT,CF_BUFSIZE,"%s: %s\n",actiontxt,line); CfLog(cferror,OUTPUT,""); } } } cfpclose(pp); return true; } /******************************************************************/ void CheckClass(char *name,char *source) { char *sp; for (sp = name; *sp != '\0'; sp++) { if (!isalnum((int)*sp) && (*sp != '_')) { snprintf(OUTPUT,CF_BUFSIZE,"Module class contained an illegal character (%c). Only alphanumeric or underscores in classes.",*sp); CfLog(cferror,OUTPUT,""); } } } cfengine-2.2.10/src/report.c0000644000175000001440000011121111053221201012515 00000000000000/* Copyright (C) 1995-2000 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: report.c */ /* */ /*****************************************************************************/ #define INET #include "cf.defs.h" #include "cf.extern.h" #define CF_SPACER printf("\n. . . . . . . . . . . . . . . .\n\n") /*******************************************************************/ void ListActionSequence() { struct Item *ptr; printf("\nAction sequence = ("); for (ptr=VACTIONSEQ; ptr!=NULL; ptr=ptr->next) { printf("%s ",ptr->name); } printf(")\n"); } /*******************************************************************/ void ListDefinedClasses() { struct Item *ptr; printf ("\nDefined Classes = ( "); for (ptr = VHEAP; ptr != NULL; ptr=ptr->next) { printf("%s ",ptr->name); } printf (")\n"); printf ("\nNegated Classes = ( "); for (ptr = VNEGHEAP; ptr != NULL; ptr=ptr->next) { printf("%s ",ptr->name); } printf (")\n\n"); printf ("Installable classes = ( "); for (ptr = VALLADDCLASSES; ptr != NULL; ptr=ptr->next) { printf("%s ",ptr->name); } printf (")\n"); if (VEXCLUDECOPY != NULL) { printf("Patterns to exclude from copies: = ("); for (ptr = VEXCLUDECOPY; ptr != NULL; ptr=ptr->next) { printf("%s ",ptr->name); } printf (")\n"); } if (VSINGLECOPY != NULL) { printf("Patterns to copy one time: = ("); for (ptr = VSINGLECOPY; ptr != NULL; ptr=ptr->next) { printf("%s ",ptr->name); } printf (")\n"); } if (VAUTODEFINE != NULL) { printf("Patterns to autodefine: = ("); for (ptr = VAUTODEFINE; ptr != NULL; ptr=ptr->next) { printf("%s ",ptr->name); } printf (")\n"); } if (VEXCLUDELINK != NULL) { printf("Patterns to exclude from links: = ("); for (ptr = VEXCLUDELINK; ptr != NULL; ptr=ptr->next) { printf("%s ",ptr->name); } printf (")\n"); } if (VCOPYLINKS != NULL) { printf("Patterns to copy instead of link: = ("); for (ptr = VCOPYLINKS; ptr != NULL; ptr=ptr->next) { printf("%s ",ptr->name); } printf (")\n"); } if (VCOPYLINKS != NULL) { printf("Patterns to link instead of copy: = ("); for (ptr = VLINKCOPIES; ptr != NULL; ptr=ptr->next) { printf("%s ",ptr->name); } printf (")\n"); } } /*********************************************************************/ void ListDefinedHomePatterns(char *classes) { struct Item *ptr; printf ("\nDefined wildcards to match home directories = ( "); for (ptr = VHOMEPATLIST; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } printf("%s ",ptr->name); } printf (")\n"); } /*********************************************************************/ void ListDefinedBinservers(char *classes) { struct Item *ptr; printf ("\nDefined Binservers = ( "); for (ptr = VBINSERVERS; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } printf("%s ",ptr->name); if (ptr->classes) { printf("(pred::%s), ",ptr->classes); } } printf (")\n"); } /*******************************************************************/ void ListDefinedStrategies(char *classes) { struct Strategy *ptr; struct Item *ip; printf("\nDEFINED STRATEGIES\n\n"); for (ptr = VSTRATEGYLIST; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } printf("Strategy %s (type=%c)\n",ptr->name,ptr->type); if (ptr->strategies) { for (ip = ptr->strategies; ip !=NULL; ip=ip->next) { printf(" %s - weight %s\n",ip->name,ip->classes); } } CF_SPACER; } } /*******************************************************************/ void ListDefinedVariables() { struct cfObject *cp = NULL; printf("\nDEFINED MACRO/VARIABLES (by contexts)\n"); for (cp = VOBJ; cp != NULL; cp=cp->next) { printf("\nOBJECT: %s\n",cp->scope); PrintHashTable((char **)cp->hashtable); } } /*******************************************************************/ void ListACLs() { struct CFACL *ptr; struct CFACE *ep; printf("\nDEFINED ACCESS CONTROL BODIES\n\n"); for (ptr = VACLLIST; ptr != NULL; ptr=ptr->next) { printf("%s (type=%d,method=%c)\n",ptr->acl_alias,ptr->type,ptr->method); for (ep = ptr->aces; ep != NULL; ep=ep->next) { if (ep->name != NULL) { printf(" Type = %s, obj=%s, mode=%s (classes=%s)\n",ep->acltype,ep->name,ep->mode,ep->classes); } } CF_SPACER; } } /*********************************************************************/ /* Promises */ /*********************************************************************/ void ListDefinedInterfaces(char *classes) { struct Interface *ifp; printf ("\nDEFINED INTERFACE PROMISES\n\n"); for (ifp = VIFLIST; ifp !=NULL; ifp=ifp->next) { if (!ShowClass(classes,ifp->classes)) { continue; } InterfacePromise(ifp); CF_SPACER; } } /*********************************************************************/ void InterfacePromise(struct Interface *ifp) { printf("Interface %s promise if context is [%s]\n",ifp->ifdev,ifp->classes); printf(" Constraint Body:\n"); printf(" Address ipv4=%s\n",ifp->ipaddress); printf(" netmask=%s and broadcast=%s\n",ifp->netmask,ifp->broadcast); } /*********************************************************************/ void ListDefinedLinks(char *classes) { struct Link *ptr; printf ("\nDEFINED LINK PROMISES\n\n"); for (ptr = VLINK; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } LinkPromise(ptr,"be a link"); CF_SPACER; } } /*********************************************************************/ void ListDefinedLinkchs(char *classes) { struct Link *ptr; struct Item *ip; printf ("\nDEFINED CHILD LINK PROMISES\n\n"); for (ptr = VCHLINK; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } LinkPromise(ptr,"link its children"); CF_SPACER; } } /*********************************************************************/ void LinkPromise(struct Link *ptr, char *type) { struct Item *ip; printf("%s will %s to %s if context matches %s\n",ptr->from,type,ptr->to,ptr->classes); printf(" Behaviour constraint body:\n"); printf(" force=%c, attr=%d type=%c nofile=%d\n",ptr->force,ptr->silent,ptr->type, ptr->nofile); for (ip = ptr->copy; ip != NULL; ip = ip->next) { printf(" Copy %s\n",ip->name); } for (ip = ptr->exclusions; ip != NULL; ip = ip->next) { printf(" Exclude %s\n",ip->name); } for (ip = ptr->inclusions; ip != NULL; ip = ip->next) { printf(" Include %s\n",ip->name); } for (ip = ptr->ignores; ip != NULL; ip = ip->next) { printf(" Ignore %s\n",ip->name); } for (ip = ptr->filters; ip != NULL; ip = ip->next) { printf(" Filters %s\n",ip->name); } if (ptr->defines) { printf(" Define %s\n",ptr->defines); } if (ptr->elsedef) { printf(" ElseDefine %s\n",ptr->elsedef); } printf(" IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } /*********************************************************************/ void PromiseItem(struct Item *ptr) { printf(" Item: \"%s\" is promised",ptr->name); printf(" if context matches [%s]\n",ptr->classes); printf(" ifelapsed %d, expireafter %d\n",ptr->ifelapsed,ptr->expireafter); } /*********************************************************************/ void ListDefinedResolvers(char *classes) { struct Item *ptr; printf ("\nDEFINED RESOLVER CONFIGURATION PROMISES\n\n"); for (ptr = VRESOLVE; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseItem(ptr); CF_SPACER; } } /*********************************************************************/ void ListDefinedAlerts(char *classes) { struct Item *ptr; printf ("\nDEFINED ALERT PROMISES\n\n"); for (ptr = VALERTS; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseItem(ptr); CF_SPACER; } } /*********************************************************************/ void ListDefinedHomeservers(char *classes) { struct Item *ptr; printf ("\nUse home servers = ( "); for (ptr = VHOMESERVERS; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseItem(ptr); CF_SPACER; } printf(" )\n"); } /*********************************************************************/ void ListDefinedImports() { struct Item *ptr; struct Audit *ap; printf ("\nUSE IMPORTS\n\n"); for (ptr = VIMPORT; ptr != NULL; ptr=ptr->next) { PromiseItem(ptr); CF_SPACER; } /* Report these inputs at audit */ for (ap = VAUDIT; ap != NULL; ap=ap->next) { if (ap->version) { printf("File %s %30s - version %s edited %s\n",ChecksumPrint('m',ap->digest),ap->filename, ap->version,ap->date); } else { printf("File %s %30s - (no version string) edited %s\n",ChecksumPrint('m',ap->digest),ap->filename,ap->date); } } } /*********************************************************************/ void ListDefinedIgnore(char *classes) { struct Item *ptr; printf ("\nFILE SEARCH IGNORE\n\n"); for (ptr = VIGNORE; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseItem(ptr); CF_SPACER; } } /*********************************************************************/ void ListDefinedMethods(char *classes) { struct Method *ptr; printf ("\nMETHOD AGREEMENTS\n\n"); for (ptr = VMETHODS; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseMethod(ptr); CF_SPACER; } } /*********************************************************************/ void PromiseMethod(struct Method *ptr) { struct Item *ip; int i,amserver; amserver = (IsItemIn(ptr->servers,IPString2Hostname(VFQNAME)) || IsItemIn(ptr->servers,IPString2UQHostname(VUQNAME)) || IsItemIn(ptr->servers,VIPADDRESS)); if (amserver) { printf("Promises to provide and execute method %s if context [%s]\n",ptr->name,ptr->classes); } else { printf("Promise to use voluntary service %s provided by server list if context [%s]\n",ptr->name,ptr->classes); i = 1; for (ip = ptr->send_args; ip != NULL; ip=ip->next) { printf(" Provide argument %d: %s\n",i++,ip->name); } printf(" %s\n",ChecksumPrint('m',ptr->digest)); i = 1; for (ip = ptr->send_classes; ip != NULL; ip=ip->next) { printf(" Provide class %d: %s\n",i++,ip->name); } i = 1; for (ip = ptr->servers; ip != NULL; ip=ip->next) { printf(" Encrypt for service provider %d: %s\n",i++,ip->name); } i = 1; if (ListLen(ptr->servers) > 1) { for (ip = ptr->return_vars; ip != NULL; ip=ip->next) { printf(" Return value %d: $(%s_X.%s) - X = 1,2,..\n",i++,ptr->name,ip->name); } i = 1; for (ip = ptr->return_classes; ip != NULL; ip=ip->next) { printf(" Will accept return class %d: %s_X_%s\n",i++,ptr->name,ip->name); } } else { for (ip = ptr->return_vars; ip != NULL; ip=ip->next) { printf(" Will accept return value %d: $(%s.%s)\n",i++,ptr->name,ip->name); } i = 1; for (ip = ptr->return_classes; ip != NULL; ip=ip->next) { printf(" Will accept return class %d: %s_%s\n",i++,ptr->name,ip->name); } } } printf(" IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); printf(" Using executable file: %s\n",ptr->file); printf(" Running with Uid=%d,Gid=%d\n",ptr->uid,ptr->gid); printf(" Running in chdir=%s, chroot=%s\n",ptr->chdir,ptr->chroot); printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } /*********************************************************************/ void ListDefinedScripts(char *classes) { struct ShellComm *ptr; printf ("\nPROMISED SHELLCOMMANDS\n\n"); for (ptr = VSCRIPT; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseShellCommand(ptr); CF_SPACER; } } /*********************************************************************/ void ListDefinedSCLI(char *classes) { struct ShellComm *ptr; printf ("\nPROMISED SCLI (snmp) COMMANDS\n\n"); for (ptr = VSCLI; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseShellCommand(ptr); CF_SPACER; } } /*********************************************************************/ void PromiseShellCommand(struct ShellComm *ptr) { printf("\nWill execute \"%s\" if context [%s]\n",ptr->name,ptr->classes); printf(" Behaviour constraint body:\n"); printf(" Timeout=%d\n",ptr->timeout); printf(" Uid=%d,Gid=%d\n",ptr->uid,ptr->gid); printf(" Process umask = %o\n",ptr->umask); printf(" Run in background (no wait) = %c\n",ptr->fork); printf(" ChDir=%s, ChRoot=%s\n",ptr->chdir,ptr->chroot); printf(" IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); if (ptr->defines) { printf(" Define %s on success\n",ptr->defines); } if (ptr->elsedef) { printf(" ElseDefine %s\n",ptr->elsedef); printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } } /*********************************************************************/ void ListDefinedImages(char *classes) { struct Image *ptr; struct Item *svp; printf ("\nDEFINED FILE IMAGE PROMISES\n\n"); for (svp = VSERVERLIST; svp != NULL; svp=svp->next) /* order servers */ { for (ptr = VIMAGE; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } if (strcmp(svp->name,ptr->server) != 0) /* group together similar hosts so */ { /* can can do multiple transactions */ continue; /* on one connection */ } PromiseFileCopy(ptr); CF_SPACER; } } } /*********************************************************************/ void PromiseFileCopy(struct Image *ptr) { struct UidList *up; struct GidList *gp; struct Item *iip; printf("%s promises to be a copy of %s:/%s if context = %s\n",ptr->destination,ptr->server,ptr->path,ptr->classes); printf(" Behaviour constraint body:\n"); printf(" Action on deviation: %s\n",ptr->action); printf(" Comparison method = %c (time/checksum)\n",ptr->type); printf(" Ask server = %s (encrypt=%c,verified=%c)\n",ptr->server,ptr->encrypt,ptr->verify); printf(" Accept the server's public key on trust? %c\n",ptr->trustkey); printf(" Purge local files if not on server = %c\n",ptr->purge); printf(" Override mode with: +%o,-%o\n",ptr->plus,ptr->minus); printf(" Copy if size %c %d\n",ptr->comp,ptr->size); if (ptr->recurse == CF_INF_RECURSE) { printf(" File search recursion limit: infinite\n"); } else { printf(" File search recursion limit %d\n",ptr->recurse); } printf(" File search boundary (xdev) = %c\n",ptr->xdev); printf(" Using uids = ( "); for (up = ptr->uid; up != NULL; up=up->next) { printf("%d ",up->uid); } printf(")\n Using gids = ( "); for (gp = ptr->gid; gp != NULL; gp=gp->next) { printf("%d ",gp->gid); } printf(")\n Using filters:"); for (iip = ptr->filters; iip != NULL; iip=iip->next) { printf(" %s",iip->name); } printf("\n Excluding file patterns:"); for (iip = ptr->acl_aliases; iip != NULL; iip=iip->next) { printf(" Using ACL object %s\n",iip->name); } printf("\n Ignoring file/directory patterns:"); for (iip = ptr->ignores; iip != NULL; iip = iip->next) { printf(" %s",iip->name); } printf("\n"); printf(" Using symlink for patterns:"); for (iip = ptr->symlink; iip != NULL; iip = iip->next) { printf(" %s",iip->name); } printf("\n Including file patterns:"); for (iip = ptr->inclusions; iip != NULL; iip = iip->next) { printf(" %s",iip->name); } printf("\n"); if (ptr->defines) { printf(" Defining %s if deviation corrected\n",ptr->defines); } if (ptr->elsedef) { printf(" ElseDefine %s\n",ptr->elsedef); } if (ptr->failover) { printf(" Providing FailoverClasses %s if server unavailable\n",ptr->failover); } switch (ptr->backup) { case 'n': printf(" Promise no backup copy\n"); break; case 'y': printf(" Promise single backup archive\n"); break; case 's': printf(" Promise Timestamped backups (full history)\n"); break; default: printf (" UNKNOWN BACKUP POLICY!!\n"); } if (ptr->repository) { printf(" Using Local repository = %s\n",ptr->repository); } if (ptr->stealth == 'y') { printf(" Promise stealth copy\n"); } if (ptr->preservetimes == 'y') { printf(" Promise file times preserved\n"); } if (ptr->checkroot == 'y') { printf(" Root directory attributes will be copied from source if applicable\n"); } else { printf(" Root directory attributes will NOT be copied from source\n"); } if (ptr->forcedirs == 'y') { printf(" Promise forcible movement of obstructing files\n"); } printf(" IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); printf("Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } /*********************************************************************/ void ListDefinedTidy(char *classes) { struct Tidy *ptr; struct TidyPattern *tp; printf ("\nDEFINED TIDY PROMISES\n\n"); for (ptr = VTIDY; ptr != NULL; ptr=ptr->next) { int something = false; for (tp = ptr->tidylist; tp != NULL; tp=tp->next) { if (ShowClass(classes,tp->classes)) { something = true; break; } } if (!something) { continue; } PromiseTidy(ptr,classes); CF_SPACER; } } /*********************************************************************/ void PromiseTidy(struct Tidy *ptr, char *classes) { struct TidyPattern *tp; struct Item *ip; if (ptr->maxrecurse == CF_INF_RECURSE) { printf("Promise to tidy/delete files "); } else { printf("Promise to tidy/delete an object "); } printf("in base directory: %s\n",ptr->path); printf(" Search constraint body:\n"); for(tp = ptr->tidylist; tp != NULL; tp=tp->next) { if (!ShowClass(classes,tp->classes)) { continue; } printf(" Use file pattern \"%s\" if context matches [%s]\n",tp->pattern,tp->classes); printf(" Use age policy %c-age=%d\n",tp->searchtype,tp->age); printf(" If size = %d\n",tp->size); if (tp->recurse == CF_INF_RECURSE) { printf(" Will descend into any/all sub-directories\n"); } else { printf(" Pattern will descend %d directory level(s)\n",tp->recurse); } printf(" Options: Linkdirs=%c, Rmdirs=%c, Travlinks=%c, Compress=%c\n",tp->dirlinks,tp->rmdirs,tp->travlinks,tp->compress); if (tp->defines) { printf(" Define \"%s\" on deletion of pattern\n",tp->defines); } if (tp->elsedef) { printf(" ElseDefine \"%s\"\n",tp->elsedef); } for (ip = tp->filters; ip != NULL; ip=ip->next) { printf(" Use file filter %s\n",ip->name); } printf(" Rule from %s at/before line %d\n",tp->audit->filename,tp->lineno); } printf(" Behaviour constraint body:\n IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); printf(" Filesystem boundary policy (xdev) = %c\n",ptr->xdev); for (ip = ptr->exclusions; ip != NULL; ip = ip->next) { printf(" Exclude file pattern: %s\n",ip->name); } for (ip = ptr->ignores; ip != NULL; ip = ip->next) { printf(" Ignore file pattern: %s\n",ip->name); } } /*********************************************************************/ void ListDefinedMountables(char *classes) { struct Mountables *ptr; printf ("\nPROMISED MOUNTABLES\n\n"); for (ptr = VMOUNTABLES; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseMountable(ptr); CF_SPACER; } } /*********************************************************************/ void PromiseMountable(struct Mountables *ptr) { if (ptr == NULL) { return; } if (ptr->classes == NULL) { printf(" Promise to use filesystem %s if context matches [any]\n",ptr->filesystem); } else { printf(" Promise to use filesystem %s if context matches [%s]\n",ptr->filesystem,ptr->classes); } if (ptr->readonly) { printf(" Using option ro\n"); } else { printf(" Using option rw\n"); } if (ptr->mountopts != NULL) { printf(" Using options %s\n", ptr->mountopts); } printf("Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } /*********************************************************************/ void ListMiscMounts(char *classes) { struct MiscMount *ptr; printf ("\nPROMISED MISC MOUNTABLES\n\n"); for (ptr = VMISCMOUNT; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseMiscMount(ptr); CF_SPACER; } } /*********************************************************************/ void PromiseMiscMount(struct MiscMount *ptr) { printf("Promise to mount %s on %s mode if context is [%s]\n",ptr->from,ptr->onto, ptr->classes); printf(" with mode %s and options %s\n",ptr->mode,ptr->options); printf(" Behaviour constraint body:\n IfElapsed=%d\n ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } /*********************************************************************/ void ListDefinedRequired(char *classes) { struct Disk *ptr; printf ("\nDEFINED REQUIRE PROMISES\n\n"); for (ptr = VREQUIRED; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } DiskPromises(ptr); CF_SPACER; } } /*********************************************************************/ void DiskPromises(struct Disk *ptr) { printf("Filesystem %s is promised if context matches [%s]\n",ptr->name,ptr->classes); printf(" Attribute constraint body:\n freespace=%d\n force=%c\n define=%s\n",ptr->freespace, ptr->force,ptr->define); printf(" Behaviour contraint body:\n IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); printf(" Using scanarrivals=%c\n",ptr->scanarrivals); printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } /*********************************************************************/ void ListDefinedDisable(char *classes) { struct Disable *ptr; printf ("\nDEFINED DISABLE PROMISES\n\n"); for (ptr = VDISABLELIST; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseDisable(ptr); CF_SPACER; } } /*********************************************************************/ void PromiseDisable(struct Disable *ptr) { if (strlen(ptr->destination) > 0) { printf("Promise to rename: %s to %s if context is [%s]\n",ptr->name,ptr->destination,ptr->classes); } else { printf("Promise to disable/transform object %s if context is [%s]\n",ptr->name,ptr->classes); printf(" Constraint constraint body:\n Rotate=%d, type=%s, size %c %d, action=%c\n", ptr->rotate,ptr->type,ptr->comp,ptr->size,ptr->action); } printf(" Behaviour constraint body:\n IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); if (ptr->repository) { printf(" Using Local repository = %s\n",ptr->repository); } if (ptr->defines) { printf(" Define: %s if changes made\n",ptr->defines); } if (ptr->elsedef) { printf(" ElseDefine: %s if no changes made\n",ptr->elsedef); } if (ptr->audit) { printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } } /*********************************************************************/ void ListDefinedMakePaths(char *classes) { struct File *ptr; printf ("\nPROMISED DIRECTORIES\n\n"); for (ptr = VMAKEPATH; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseDirectories(ptr); CF_SPACER; } } /*********************************************************************/ void PromiseDirectories(struct File *ptr) { struct UidList *up; struct GidList *gp; struct Item *ip; printf("Promise attributes of %s if context matches",ptr->path,ptr->classes); printf(" Constraint Body:"); printf(" Mode +%o\n -%o\n",ptr->plus,ptr->minus); printf(" uids = ( "); for (up = ptr->uid; up != NULL; up=up->next) { printf("%d ",up->uid); } printf(")\n gids = ( "); for (gp = ptr->gid; gp != NULL; gp=gp->next) { printf("%d ",gp->gid); } printf(")\n\n"); for (ip = ptr->acl_aliases; ip != NULL; ip=ip->next) { printf(" ACL object %s\n",ip->name); } printf(" Behaviour:\n IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); printf(" Action on deviation %s\n",FILEACTIONTEXT[ptr->action]); if (ptr->recurse == CF_INF_RECURSE) { printf(" Recurse depth infinite\n"); } else { printf(" Recursion depth = %d\n",ptr->recurse); } if (ptr->defines) { printf(" Define %s on alteration\n",ptr->defines); } if (ptr->elsedef) { printf(" ElseDefine %s if no action\n",ptr->elsedef); } printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } /*********************************************************************/ void ListFiles(char *classes) { struct File *ptr; printf ("\nDEFINED FILE PROMISES\n\n"); for (ptr = VFILE; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseFiles(ptr); CF_SPACER; } } /*********************************************************************/ void PromiseFiles(struct File *ptr) { struct Item *ip; struct UidList *up; struct GidList *gp; printf("File object %s will promise attributes if context matches [%s]\n",ptr->path,ptr->classes); printf(" Attribute constraint body:\n"); printf(" Mode +%o,-%o | BSD +%o,-%o\n",ptr->plus,ptr->minus,ptr->plus_flags,ptr->minus_flags); printf(" Uids = ( "); for (up = ptr->uid; up != NULL; up=up->next) { printf("%d ",up->uid); } printf(")\n Gids = ( "); for (gp = ptr->gid; gp != NULL; gp=gp->next) { printf("%d ",gp->gid); } printf(")\n"); for (ip = ptr->acl_aliases; ip != NULL; ip=ip->next) { printf(" ACL object %s\n",ip->name); } printf(" Behaviour constraint body:\n"); printf(" Action on deviation: %s\n",FILEACTIONTEXT[ptr->action]); printf(" Traverse links=%c\n",ptr->travlinks); printf(" IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); if (ptr->recurse == CF_INF_RECURSE) { printf(" Search recursion limit=inf\n"); } else { printf(" Search recursion limit=%d\n",ptr->recurse); } printf(" Record checksum-type = %c\n",ptr->checksum); printf(" Filesystem boundaries (xdev) = %c\n",ptr->xdev); for (ip = ptr->filters; ip != NULL; ip=ip->next) { printf(" Using filter %s\n",ip->name); } for (ip = ptr->exclusions; ip != NULL; ip = ip->next) { printf(" Excluding file patterns %s\n",ip->name); } for (ip = ptr->inclusions; ip != NULL; ip = ip->next) { printf(" Including file patterns %s\n",ip->name); } for (ip = ptr->ignores; ip != NULL; ip = ip->next) { printf(" Ignoring file/directory patterns %s\n",ip->name); } if (ptr->defines) { printf(" Define %s on convergent change\n",ptr->defines); } if (ptr->elsedef) { printf(" ElseDefine %s on no change\n",ptr->elsedef); } printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } /*******************************************************************/ void ListUnmounts(char *classes) { struct UnMount *ptr; printf("\nDEFINED UNMOUNT PROMISES\n\n"); for (ptr=VUNMOUNT; ptr!=NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseUnmount(ptr); CF_SPACER; } } /*******************************************************************/ void PromiseUnmount(struct UnMount *ptr) { printf("Promise to unmount %s if context matches [%s]\n",ptr->name,ptr->classes); printf("Behaviour constraint body:\n"); printf(" Deletedir=%c\n deletefstab=%c\n force=%c\n",ptr->deletedir,ptr->deletefstab,ptr->force); printf(" IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } /*******************************************************************/ void ListProcesses(char *classes) { struct Process *ptr; printf("\nPROCESSES PROMISES\n\n"); for (ptr = VPROCLIST; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromiseProcess(ptr); CF_SPACER; } } /*******************************************************************/ void PromiseProcess(struct Process *ptr) { struct Item *ip; if (strcmp(ptr->expr,"SetOptionString") == 0) { printf("Promise to reset process query with body %s\n",ptr->restart); } else { printf("\nProcesses matching \"%s\" in context [%s]\n",ptr->expr,ptr->classes); printf(" Match constraint body:\n"); printf(" Acceptable no. of matches: %c %d\n",ptr->comp,ptr->matches); for (ip = ptr->exclusions; ip != NULL; ip = ip->next) { printf(" Excluding patterns %s\n",ip->name); } for (ip = ptr->inclusions; ip != NULL; ip = ip->next) { printf(" Including patterns %s\n",ip->name); } for (ip = ptr->filters; ip != NULL; ip = ip->next) { printf(" Using filter %s\n",ip->name); } printf(" Behaviour constraint body:\n"); printf(" Matches are promised signal=%s\n",SIGNALS[ptr->signal]); switch (ptr->action) { case 'w': printf(" Action: warn only\n",ptr->action); break; case 'm': printf(" Action: decide by match\n",ptr->action); break; case 's': printf(" Action: signal\n",ptr->action); break; default: printf(" Action: default\n",ptr->action); } if (ptr->restart == NULL || strlen(ptr->restart) == 0) { printf(" No (re)start command is promised\n"); } else { printf(" Will be (re)started with command = %s\n",ptr->restart); } printf(" IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); printf(" Started process constraint body:\n"); printf(" Useshell=%c\n",ptr->useshell); printf(" ChDir=%s\n",ptr->chdir); printf(" ChRoot=%s\n",ptr->chroot); if (ptr->defines) { printf(" Define %s if matches found\n",ptr->defines); } if (ptr->elsedef) { printf(" ElseDefine %s if no matches found\n",ptr->elsedef); } printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } } /*******************************************************************/ void ListFileEdits(char *classes) { struct Edit *ptr; struct Edlist *ep; printf("\nDEFINED FILE EDIT PROMISES\n\n"); for (ptr=VEDITLIST; ptr != NULL; ptr=ptr->next) { int something = false; for (ep = ptr->actions; ep != NULL; ep=ep->next) { if (ShowClass(classes,ep->classes)) { something = true; break; } } if (!something) { continue; } PromiseFileEdits(ptr,classes); CF_SPACER; } } /*******************************************************************/ void PromiseFileEdits(struct Edit *ptr,char *classes) { struct Edlist *ep; struct Item *ip; printf("Edit promises for %s\n",ptr->fname); printf(" Constraint Body of convergent operations: [promise type] with \"body\":\n"); for (ep = ptr->actions; ep != NULL; ep=ep->next) { if (!ShowClass(classes,ep->classes)) { continue; } if (ep->data == NULL) { printf(" [%s] \t with no body if context is [%s]\n",VEDITNAMES[ep->code],ep->classes); } else { printf(" [%s] \t with body \"%s\" if context is [%s]\n",VEDITNAMES[ep->code],ep->data,ep->classes); } } printf(" Behaviour constraint body:\n"); printf(" IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); printf(" File search recursion limit: %d\n",ptr->recurse); if (ptr->repository) { printf(" Using local repository = %s\n",ptr->repository); } for (ip = ptr->filters; ip != NULL; ip=ip->next) { printf (" Using filter %s\n",ip->name); } /* This could be wrong if several stanzas are used...*/ printf(" in %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } /*******************************************************************/ void ListFilters(char *classes) { struct Filter *ptr; int i; printf("\nDEFINED FILTERS\n"); for (ptr=VFILTERLIST; ptr != NULL; ptr=ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } printf("Filter name %s :\n",ptr->alias); if (ptr->defines) { printf(" Defines: %s\n",ptr->defines); } if (ptr->elsedef) { printf(" ElseDefines: %s\n",ptr->elsedef); } for (i = 0; i < NoFilter; i++) { if (ptr->criteria[i] != NULL) { printf(" (%s) [%s]\n",VFILTERNAMES[i],ptr->criteria[i]); } } CF_SPACER; } } /*******************************************************************/ void ListDefinedPackages(char *classes) { struct Package *ptr = NULL; printf("\nPROMISED PACKAGE CHECKS\n\n"); for (ptr = VPKG; ptr != NULL; ptr = ptr->next) { if (!ShowClass(classes,ptr->classes)) { continue; } PromisePackages(ptr); CF_SPACER; } } /*******************************************************************/ void PromisePackages(struct Package *ptr) { char name[CF_EXPANDSIZE]; ExpandVarstring(ptr->name,name,""); printf("Package \"%s\" promises\n",name); printf(" Search constraint body:\n"); if (ptr->ver && *(ptr->ver) != '\0') { printf(" Will have version %s %s\n",CMPSENSETEXT[ptr->cmp], ptr->ver); } else { printf(" Can have any package version.\n"); } printf(" Behaviour constraint body:\n"); if (ptr->action != pkgaction_none) { printf(" Promise to %s package\n",PKGACTIONTEXT[ptr->action]); } printf(" Using Package database: %s\n", PKGMGRTEXT[ptr->pkgmgr]); printf(" IfElapsed=%d, ExpireAfter=%d\n",ptr->ifelapsed,ptr->expireafter); if (ptr->defines) { printf(" Define %s if matches\n",ptr->defines); } if (ptr->elsedef) { printf(" ElseDefine %s if no match\n",ptr->elsedef); } printf(" Rule from %s at/before line %d\n",ptr->audit->filename,ptr->lineno); } cfengine-2.2.10/src/expand-tidy.c0000644000175000001440000003267110664231257013467 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /*****************************************************************************/ /* */ /* File: expand-tidy.c */ /* */ /*****************************************************************************/ int RecursiveHomeTidy(char *name,int level,struct stat *sb) { struct stat statbuf; DIR *dirh; struct dirent *dirp; char pcwd[CF_BUFSIZE]; time_t ticks; int done = false,goback; Debug("\nHomeTidy(%s,%d)\n\n",name,level); if (!DirPush(name,sb)) { return false; } if (strlen(name) == 0) { name = "/"; } if (level > CF_RECURSION_LIMIT) { snprintf(OUTPUT,CF_BUFSIZE*2,"WARNING: Very deep nesting of directories (> %d deep): %s (Aborting tidy)",level,name); CfLog(cferror,OUTPUT,""); return true; } Verbose("HomeTidy: Opening %s as .\n",name); if ((dirh = opendir(".")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",name); CfLog(cfverbose,OUTPUT,"opendir"); return true; } if (level == 2) { if (LOGTIDYHOMEFILES) { int tempfd; strcpy(VLOGFILE,name); strcat(VLOGFILE,"/.cfengine.rm"); /* Unlink here to avoid an exploit which could be used to overwrite a system file with root privileges. */ if (unlink(VLOGFILE) == -1) { Debug("Pre-existing object %s could not be removed\n",VLOGFILE); } if ((tempfd = open(VLOGFILE, O_CREAT|O_EXCL|O_WRONLY,0600)) < 0) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't open a file %s\n",VLOGFILE); CfLog(cferror,OUTPUT,"open"); VLOGFP = stderr; } else if ((VLOGFP = fdopen(tempfd,"w")) == NULL) { sprintf(OUTPUT,"Couldn't open a file %s\n",VLOGFILE); CfLog(cferror,OUTPUT,"fdopen"); VLOGFP = stderr; } else { ticks = time((time_t *)NULL); fprintf(VLOGFP,"This file is generated by cfengine %s\n",VERSION); fprintf(VLOGFP,"It contains a log of the files which have been tidied.\n"); fprintf(VLOGFP,"The time of writing is %s\n",ctime(&ticks)); fprintf(VLOGFP,"If you have any questions about this, send them to %s.\n",VSYSADM); fprintf(VLOGFP,"-(Start transcript)---------------\n"); } } } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,name,NULL)) { continue; } if (IgnoreFile(name,dirp->d_name,NULL)) /* No ref to tp->ignores here...fix?*/ { continue; } strcpy(pcwd,name); /* Assemble pathname */ AddSlash(pcwd); if (BufferOverflow(pcwd,dirp->d_name)) { return true; } strcat(pcwd,dirp->d_name); if (TRAVLINKS) { Verbose("Warning: you are using travlinks=true. It is a potential security hazard if there are untrusted users\n"); if (lstat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",pcwd); CfLog(cferror,OUTPUT,"stat"); continue; } if (S_ISLNK(statbuf.st_mode) && (statbuf.st_mode != getuid())) { snprintf(OUTPUT,CF_BUFSIZE,"File %s is an untrusted link. cfagent will not follow it with a destructive operation (tidy)",pcwd); CfLog(cfinform,OUTPUT,""); continue; } if (stat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",pcwd); CfLog(cferror,OUTPUT,"stat"); continue; } } else { if (lstat(pcwd,&statbuf) == -1) { if (DEBUG || D2 || VERBOSE) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",pcwd); CfLog(cferror,OUTPUT,"lstat"); memset(VBUFF,0,CF_BUFSIZE); if (readlink(pcwd,VBUFF,CF_BUFSIZE-1) != -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"File is link to -> %s\n",VBUFF); CfLog(cferror,OUTPUT,""); } } continue; } } if (S_ISDIR(statbuf.st_mode)) { if (IsMountedFileSystem(&statbuf,pcwd,1)) { continue; } else { if (!done) { /* Note, here we pass on the full path name, not relative name to retain state, but we have statted the right file above with opendir("."), so the race test is still secure for the next recursion level */ goback = RecursiveHomeTidy(pcwd,level+1,&statbuf); DirPop(goback,name,sb); } } } else { if (!TidyHomeFile(pcwd,dirp->d_name,&statbuf,level)) { done = true; } } } if (level == 2) { if (LOGTIDYHOMEFILES) { fclose(VLOGFP); chmod(VLOGFILE,DEFAULTMODE); } } closedir(dirh); return true; } /*********************************************************************/ int TidyHomeFile(char *path,char *name,struct stat *statbuf,int level) /* Tidy a file if it's past its sell-by date in kB, and if it is greater than the specified size. Don't need an OR, since size age can just be set to zero. */ { struct Tidy *tp; struct TidyPattern *tlp; short savetravlinks = TRAVLINKS, savekilloldlinks = KILLOLDLINKS; /* Note that we have to go through the whole tidy list here, even non-home, so be careful to pick out the rules the affect us! The info about home dissappears here, since we have expanded the home/ directive into an actual path, so we make sure that no non-home rules can be applied to home directories */ for (tp = VTIDY; tp != NULL; tp=tp->next) { if ((strncmp(tp->path,"home/",5) != 0) && (strcmp(tp->path,"home") != 0)) { continue; } if (tp->tidylist == NULL || tp->done == 'y') { continue; } if ((tp->maxrecurse != CF_INF_RECURSE) && (level > tp->maxrecurse+1)) { Debug("Recursion maxed out at level %d/%d\n",level,tp->maxrecurse+1); /*return false;*/ continue; } for (tlp = tp->tidylist; tlp != NULL; tlp=tlp->next) { if (IsExcluded(tlp->classes)) { continue; } savetravlinks = TRAVLINKS; savekilloldlinks = KILLOLDLINKS; ResetOutputRoute(tlp->log,tlp->inform); if (tlp->travlinks == 'T') { TRAVLINKS = true; } else if (tlp->travlinks == 'F') { TRAVLINKS = false; } else if (tlp->travlinks == 'K') { KILLOLDLINKS = true; } if (!FileObjectFilter(path,statbuf,tlp->filters,tidy)) { continue; } if (IgnoredOrExcluded(tidy,path,NULL,tp->exclusions)) { Debug("Skipping ignored/excluded file %s\n",path); continue; } if (WildMatch(tlp->pattern,name) && CheckHomeSubDir(path,tp->path,tp->maxrecurse)) { if ((tlp->recurse != CF_INF_RECURSE) && (level > tlp->recurse+1)) { Debug("Not tidying %s - level %d > limit %d\n",path,level,tlp->recurse+1); continue; } DoTidyFile(path,name,tlp,statbuf,CF_USELOGFILE,false,false); } ResetOutputRoute('d','d'); } } TRAVLINKS = savetravlinks; KILLOLDLINKS = savekilloldlinks; return true; } /*********************************************************************/ int RecursiveTidySpecialArea(char *name,struct Tidy *tp,int maxrecurse,struct stat *sb) { struct stat statbuf,topstatbuf; DIR *dirh; struct dirent *dirp; char pcwd[CF_BUFSIZE], *parentdir; int is_dir,level,goback; static char *defaultname = "/"; Debug("RecursiveTidySpecialArea(%s)\n",name); memset(&statbuf,0,sizeof(statbuf)); if (!DirPush(name,sb)) { return false; } if (maxrecurse == -1) { Debug2("MAXRECURSE ran out, quitting at %s\n",name); return true; } if (IgnoredOrExcluded(tidy,name,NULL,tp->exclusions)) { Debug("Skipping ignored/excluded file %s\n",name); return true; } if (IgnoreFile(name,"",tp->ignores)) { Debug2("cfengine: Ignoring directory %s\n",name); return true; } if (strlen(name) == 0) /* Check for root dir */ { name = defaultname; } if (maxrecurse == tp->maxrecurse) { if (lstat(name,&topstatbuf) == -1) { if (DEBUG || D2 || VERBOSE) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",name); CfLog(cferror,OUTPUT,""); memset(VBUFF,0,CF_BUFSIZE); if (readlink(name,VBUFF,CF_BUFSIZE-1) != -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"File is link to -> %s\n",VBUFF); CfLog(cferror,OUTPUT,""); } } return true; } } if ((dirh = opendir(".")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory [%s]\n",name); CfLog(cfverbose,OUTPUT,"opendir"); free(name); return true; } Debug("Tidy: opening dir %s\n",name); for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,name,NULL)) { continue; } if (IgnoreFile(name,dirp->d_name,tp->ignores)) { continue; } strcpy(pcwd,name); /* Assemble pathname */ AddSlash(pcwd); if (BufferOverflow(pcwd,dirp->d_name)) { return true; } level = tp->maxrecurse - maxrecurse; strcat(pcwd,dirp->d_name); if (lstat(dirp->d_name,&statbuf) == -1) /* Check for links first */ { Verbose("Can't stat %s (%s)\n",dirp->d_name,pcwd); continue; } else { if (S_ISLNK(statbuf.st_mode) && (statbuf.st_uid != getuid())) { snprintf(OUTPUT,CF_BUFSIZE,"File %s is an untrusted link. cfagent will not follow it with a destructive operation (tidy)",pcwd); if (getuid() == 0) { TidyParticularFile(pcwd,dirp->d_name,tp,&statbuf,false,level,false); } continue; } } if (TRAVLINKS && (stat(dirp->d_name,&statbuf) == -1)) { Verbose("Can't stat %s (%s)\n",dirp->d_name,pcwd); continue; } if (tp->xdev =='y' && DeviceChanged(statbuf.st_dev)) { Verbose("Skipping %s on different device\n",pcwd); continue; } if (S_ISDIR(statbuf.st_mode)) { is_dir = true; } else { is_dir = false; } if (S_ISDIR(statbuf.st_mode)) /* note lstat above! */ { if (IsMountedFileSystem(&statbuf,pcwd,1)) { continue; } else { /* Note, here we pass on the full path name, not relative name to retain state, but we have statted the right file above with opendir("."), so the race test is still secure for the next recursion level */ goback = RecursiveTidySpecialArea(pcwd,tp,maxrecurse-1,&statbuf); DirPop(goback,name,sb); } TidyParticularFile(pcwd,dirp->d_name,tp,&statbuf,is_dir,level,false); } else { TidyParticularFile(pcwd,dirp->d_name,tp,&statbuf,is_dir,level,false); } } closedir(dirh); if (maxrecurse == tp->maxrecurse) { struct TidyPattern *tlp; int ok = true; Debug("Checking tidy topmost directory %s\n",name); for (tlp = tp->tidylist; tlp != NULL; tlp=tlp->next) { if (IsExcluded(tlp->classes)) { continue; } if (tlp->rmdirs == 's') { ok = false; } } if (ok) { char* basename=ReadLastNode(name); /* the last node of a pathname string */ if (strlen(name) == strlen(basename)) /* if name is something like "tmp" */ { chdir("/"); } else /* if the names are like "/tmp", or "/var/tmp" */ { if ((parentdir = strdup(name)) == NULL) { FatalError("memory failure"); } *(parentdir+strlen(name)-strlen(basename)) = '\0'; chdir(parentdir); /* now it can chdir to "/var". */ free(parentdir); } TidyParticularFile(name,basename,tp,&topstatbuf,true,tp->maxrecurse,true); } } return true; } cfengine-2.2.10/src/macro.c0000644000175000001440000002361710662060564012341 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /*******************************************************************/ /* Macro substitution based on HASH-table */ /*******************************************************************/ void SetContext(char *id) { InstallObject(id); Verbose("\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n"); Verbose(" * (Changing context state to: %s) *",id); Verbose("\n$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n"); strncpy(CONTEXTID,id,31); } /*******************************************************************/ void InstallObject(char *name) { struct cfObject *ptr; Debug1("Adding object %s", name); /* if ( ! IsInstallable(CLASSBUFF)) { return; } */ for (ptr = VOBJ; ptr != NULL; ptr=ptr->next) { if (strcmp(ptr->scope,name) == 0) { Debug("Object %s already exists\n",name); return; } } if ((ptr = (struct cfObject *)malloc(sizeof(struct cfObject))) == NULL) { FatalError("Memory Allocation failed for cfObject"); } if (VOBJTOP == NULL) { VOBJ = ptr; } else { VOBJTOP->next = ptr; } InitHashTable((char **)ptr->hashtable); ptr->next = NULL; ptr->scope = strdup(name); VOBJTOP = ptr; } /*******************************************************************/ int ScopeIsMethod() { if (strcmp(CONTEXTID,"private-method") == 0) { return true; } else { return false; } } /*******************************************************************/ void InitHashTable(char **table) { int i; for (i = 0; i < CF_HASHTABLESIZE; i++) { table[i] = NULL; } } /*******************************************************************/ void BlankHashTable(char *scope) { int i; struct cfObject *ptr; for (ptr = VOBJ; ptr != NULL; ptr=ptr->next) { if (strcmp(ptr->scope,scope) == 0) { Verbose("Clearing macros in scope(%s)\n",scope); for (i = 0; i < CF_HASHTABLESIZE; i++) { if (ptr->hashtable[i] != NULL) { free(ptr->hashtable[i]); ptr->hashtable[i] = NULL; } } } } } /*******************************************************************/ void PrintHashTable(char **table) { int i; for (i = 0; i < CF_HASHTABLESIZE; i++) { if (table[i] != NULL) { printf (" %d : %s\n",i,table[i]); } } } /*******************************************************************/ int Hash(char *name) { int i, slot = 0; for (i = 0; name[i] != '\0'; i++) { slot = (CF_MACROALPHABET * slot + name[i]) % CF_HASHTABLESIZE; } return slot; } /*******************************************************************/ int ElfHash(char *key) { unsigned int h = 0; unsigned int g; while (*key) { h = (h << 4) + *key++; g = h & 0xF0000000; /* Assumes int is 32 bit */ if (g) { h ^= g >> 24; } h &= ~g; } return (h % CF_HASHTABLESIZE); } /*******************************************************************/ void AddMacroValue(char *scope,char *name,char *value) { char *sp, buffer[CF_BUFSIZE],exp[CF_EXPANDSIZE]; struct cfObject *ptr; int slot; Debug("AddMacroValue(%s.%s=%s)\n",scope,name,value); if (name == NULL || value == NULL || scope == NULL) { yyerror("Bad macro or scope"); CfLog(cferror,"Empty macro",""); } if (strlen(name) > CF_MAXVARSIZE) { yyerror("macro name too long"); return; } snprintf(exp,CF_BUFSIZE,"${%s}",name); if (strstr(value,exp)) { yyerror("Macro contains itself and is previously undefined"); return; } snprintf(exp,CF_BUFSIZE,"$(%s)",name); if (strstr(value,exp)) { yyerror("Macro contains itself and is previously undefined"); return; } ExpandVarstring(value,exp,NULL); ptr = ObjectContext(scope); snprintf(buffer,CF_BUFSIZE,"%s=%s",name,exp); if ((sp = malloc(strlen(buffer)+1)) == NULL) { perror("malloc"); FatalError("aborting"); } strcpy(sp,buffer); slot = Hash(name); if (ptr->hashtable[slot] != 0) { Debug("Macro Collision!\n"); if (CompareMacro(name,ptr->hashtable[slot]) == 0) { if (PARSING && !IsItemIn(VREDEFINES,name)) { snprintf(VBUFF,CF_BUFSIZE,"Redefinition of macro %s=%s (or perhaps missing quote)",name,exp); Warning(VBUFF); } free(ptr->hashtable[slot]); ptr->hashtable[slot] = sp; Debug("Stored %s in context %s\n",sp,name); return; } while ((ptr->hashtable[++slot % CF_HASHTABLESIZE] != 0)) { if (slot == CF_HASHTABLESIZE-1) { slot = 0; } if (slot == Hash(name)) { FatalError("AddMacroValue - internal error #1"); } if (CompareMacro(name,ptr->hashtable[slot]) == 0) { if (PARSING && !IsItemIn(VREDEFINES,name)) { snprintf(VBUFF,CF_BUFSIZE,"Redefinition of macro %s=%s",name,exp); Warning(VBUFF); } free(ptr->hashtable[slot]); ptr->hashtable[slot] = sp; return; } } } ptr->hashtable[slot] = sp; Debug("Added Macro at hash address %d to object %s with value %s\n",slot,scope,sp); } /****************************************************************************/ /* * HvB: Bas van der Vlies * This function checks if the given name has * the requested value: * 1 --> check for values on or true * 0 --> check for values off or false * return true if the name has the requested value */ int OptionIs(char *scope,char *name,short on) { char *result; Debug("OptionIs(%s,%s,%d)\n",scope,name,on); result = GetMacroValue(scope,name); if (result == NULL) { return(false); } if (on) { if ( (strcmp(result, "on") == 0) || ( strcmp(result, "true") == 0) ) { return(true); } } else { if ( (strcmp(result, "off") == 0) || (strcmp(result, "false") == 0) ) { return(true); } } return(false); } /*******************************************************************/ char *GetMacroValue(char *scope,char *name) { char *sp; int slot,i; struct cfObject *ptr = NULL; char objscope[CF_MAXVARSIZE],vname[CF_MAXVARSIZE]; /* Check the class.id identity to see if this is private .. and replace HASH[slot] by objectptr->hash[slot] */ Debug("GetMacroValue(%s,%s)\n",scope,name); if (strstr(name,".")) { objscope[0] = '\0'; sscanf(name,"%[^.].%s",objscope,vname); Debug("Macro identifier %s is prefixed with an object %s\n",vname,objscope); ptr = ObjectContext(objscope); } if (ptr == NULL) { strcpy(vname,name); ptr = ObjectContext(scope); } Debug("GetMacroValue(%s,%s): using scope '%s' for variable '%s'\n", scope,name,ptr->scope,vname); i = slot = Hash(vname); if (CompareMacro(vname,ptr->hashtable[slot]) != 0) { while (true) { i++; if (i >= CF_HASHTABLESIZE-1) { i = 0; } if (CompareMacro(vname,ptr->hashtable[i]) == 0) { for(sp = ptr->hashtable[i]; *sp != '='; sp++) { } return(sp+1); } if (i == slot-1) { return(getenv(vname)); /* Look in environment if not found */ } } } else { for(sp = ptr->hashtable[slot]; *sp != '='; sp++) { } Debug1("Return Macrovalue={%s}\n",sp+1); return(sp+1); } } /*******************************************************************/ void DeleteMacro(char *scope,char *id) { int slot,i; struct cfObject *ptr; i = slot = Hash(id); ptr = ObjectContext(scope); if (CompareMacro(id,ptr->hashtable[slot]) != 0) { while (true) { i++; if (i == slot) { Debug("No macro matched\n"); break; } if (i >= CF_HASHTABLESIZE-1) { i = 0; } if (CompareMacro(id,ptr->hashtable[i]) == 0) { free(ptr->hashtable[i]); ptr->hashtable[i] = NULL; } } } else { free(ptr->hashtable[i]); ptr->hashtable[i] = NULL; } } /*******************************************************************/ int CompareMacro(char *name,char *macro) { char buffer[CF_BUFSIZE]; if (macro == NULL || name == NULL) { return 1; } sscanf(macro,"%[^=]",buffer); return(strcmp(buffer,name)); } /*******************************************************************/ void DeleteMacros(char *scope) { int i; struct cfObject *ptr; ptr = ObjectContext(scope); for (i = 0; i < CF_HASHTABLESIZE; i++) { if (ptr->hashtable[i] != NULL) { free(ptr->hashtable[i]); ptr->hashtable[i] = NULL; } } } /*******************************************************************/ struct cfObject *ObjectContext(char *scope) { struct cfObject *cp = NULL; for (cp = VOBJ; cp != NULL; cp=cp->next) { if (strcmp(cp->scope,scope) == 0) { break; } } return cp; } cfengine-2.2.10/src/log.c0000644000175000001440000003207611003402032011774 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: log.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*****************************************************************************/ extern char CFLOCK[CF_BUFSIZE]; /*****************************************************************************/ void CfOpenLog() { char value[CF_BUFSIZE]; int facility = LOG_USER; static int lastsyslog = 0; if (GetMacroValue(CONTEXTID,"SyslogFacility")) { strncpy(value,GetMacroValue(CONTEXTID,"SyslogFacility"),32); if (strcmp(value,"LOG_USER") == 0) { facility = LOG_USER; } if (strcmp(value,"LOG_DAEMON") == 0) { facility = LOG_DAEMON; } if (strcmp(value,"LOG_LOCAL0") == 0) { facility = LOG_LOCAL0; } if (strcmp(value,"LOG_LOCAL1") == 0) { facility = LOG_LOCAL1; } if (strcmp(value,"LOG_LOCAL2") == 0) { facility = LOG_LOCAL2; } if (strcmp(value,"LOG_LOCAL3") == 0) { facility = LOG_LOCAL3; } if (strcmp(value,"LOG_LOCAL4") == 0) { facility = LOG_LOCAL4; } if (strcmp(value,"LOG_LOCAL5") == 0) { facility = LOG_LOCAL5; } if (strcmp(value,"LOG_LOCAL6") == 0) { facility = LOG_LOCAL6; } if (strcmp(value,"LOG_LOCAL7") == 0) { facility = LOG_LOCAL7; } if (lastsyslog != 1) { if (lastsyslog) { closelog(); } } lastsyslog=1; openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,facility); } else if (ISCFENGINE) { if (lastsyslog != 2) { if (lastsyslog) { closelog(); } } lastsyslog=2; openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,LOG_USER); } else { if (lastsyslog != 3) { if (lastsyslog) { closelog(); } } lastsyslog=3; openlog(VPREFIX,LOG_PID|LOG_NOWAIT|LOG_ODELAY,LOG_DAEMON); } } /*****************************************************************************/ void CfCheckAudit() { DB_ENV *dbenv = NULL; char name[CF_BUFSIZE]; snprintf(name,CF_BUFSIZE-1,"%s/%s",CFWORKDIR,CF_AUDITDB_FILE); if (AUDIT) { if ((errno = db_create(&AUDITDBP,dbenv,0)) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open performance database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } #ifdef CF_OLD_DB if ((errno = (AUDITDBP->open)(AUDITDBP,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #else if ((errno = (AUDITDBP->open)(AUDITDBP,NULL,name,NULL,DB_BTREE,DB_CREATE,0644)) != 0) #endif { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open auditing database %s\n",name); CfLog(cferror,OUTPUT,"db_open"); return; } AuditLog('y',NULL,0,"Cfagent starting",CF_NOP); } } /*****************************************************************************/ void CloseAuditLog() { double total; char *sp; total = (double)(PR_KEPT+PR_NOTKEPT+PR_REPAIRED)/100.0; if (sp = GetMacroValue(CONTEXTID,"cfinputs_version")) { } else { sp = "(not specified)"; } if (total == 0) { snprintf(OUTPUT,CF_BUFSIZE,"Outcome of version %s: No checks were scheduled\n",sp); return; } else { snprintf(OUTPUT,CF_BUFSIZE,"Outcome of version %s: Promises observed to be kept %.0f%%, Promises repaired %.0f%%, Promises not repaired %.0f\%\n", sp, (double)PR_KEPT/total, (double)PR_REPAIRED/total, (double)PR_NOTKEPT/total); } CfLog(cfverbose,OUTPUT,""); AuditLog('y',NULL,0,OUTPUT,CF_REPORT); if (AUDIT && AUDITDBP) { AuditLog('y',NULL,0,"Cfagent closing",CF_NOP); AUDITDBP->close(AUDITDBP,0); } } /*****************************************************************************/ void AuditLog(char yesno,struct Audit *ap,int lineno,char *str,char status) { time_t now = time(NULL); char date[CF_BUFSIZE],lock[CF_BUFSIZE],key[CF_BUFSIZE],operator[CF_BUFSIZE]; struct AuditLog newaudit; struct timespec t; double keyval; Debug("AuditLog(%s)\n",str); switch(status) { case CF_CHG: PR_REPAIRED++; break; case CF_WARN: PR_NOTKEPT++; break; case CF_TIMEX: PR_NOTKEPT++; break; case CF_FAIL: PR_NOTKEPT++; break; case CF_DENIED: PR_NOTKEPT++; break; case CF_INTERPT: PR_NOTKEPT++; break; case CF_REGULAR: PR_REPAIRED++; break; case CF_NOP: PR_KEPT++; break; case CF_UNKNOWN: PR_KEPT++; break; } if (AUDITDBP == NULL) { return; } snprintf(date,CF_BUFSIZE,"%s",ctime(&now)); Chop(date); if (ap == NULL) { snprintf(operator,CF_BUFSIZE,"Cycle complete %s, lock acquired",date); strncpy(newaudit.operator,operator,CF_AUDIT_COMMENT-1); } else { ExtractOpLock(lock); snprintf(operator,CF_BUFSIZE-1,"[%s] op %s",date,lock); strncpy(newaudit.operator,operator,CF_AUDIT_COMMENT-1); } if (clock_gettime(CLOCK_REALTIME,&t) == -1) { CfLog(cfverbose,"Clock gettime failure during audit transaction","clock_gettime"); return; } keyval = (double)(t.tv_sec)+(double)(t.tv_nsec)/(double)CF_BILLION; snprintf(key,CF_BUFSIZE-1,"%lf",keyval); if (DEBUG) { AuditStatusMessage(status); } if (ap != NULL) { strncpy(newaudit.comment,str,CF_AUDIT_COMMENT-1); strncpy(newaudit.filename,ap->filename,CF_AUDIT_COMMENT-1); if (ap->version == NULL || strlen(ap->version) == 0) { Debug("Promised in %s (unamed version last edited at %s) at/before line %d\n",ap->filename,ap->date,lineno); newaudit.version[0] = '\0'; } else { Debug("Promised in %s (version %s last edited at %s) at/before line %d\n",ap->filename,ap->version,ap->date,lineno); strncpy(newaudit.version,ap->version,CF_AUDIT_VERSION-1); } strncpy(newaudit.date,ap->date,CF_AUDIT_DATE); newaudit.lineno = lineno; } else { strcpy(newaudit.date,date); strcpy(newaudit.comment,str); strcpy(newaudit.filename,"schedule"); strcpy(newaudit.version,""); newaudit.lineno = 0; } newaudit.status = status; if (yesno == 'n') { return; } WriteDB(AUDITDBP,key,&newaudit,sizeof(newaudit)); } /*****************************************************************************/ void CfLog(enum cfoutputlevel level,char *string,char *errstr) { int endl = false; char *sp, buffer[1024]; if ((string == NULL) || (strlen(string) == 0)) { return; } strncpy(buffer,string,1022); buffer[1023] = '\0'; /* Check for %s %m which someone might be able to insert into an error message in order to get a syslog buffer overflow... bug reported by Pekka Savola */ for (sp = buffer; *sp != '\0'; sp++) { if ((*sp == '%') && (*(sp+1) >= 'a')) { *sp = '?'; } } #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (!SILENT && (pthread_mutex_lock(&MUTEX_SYSCALL) != 0)) { /* If we can't lock this could be dangerous to proceed with threaded file descriptors */ return; /* CfLog(cferror,"pthread_mutex_lock failed","lock"); would lead to sick recursion */ } #endif switch(level) { case cfsilent: if (! SILENT || VERBOSE || DEBUG || D2) { ShowAction(); printf("%s: %s",VPREFIX,buffer); endl = true; } break; case cfinform: if (SILENT) { return; } if (INFORM || VERBOSE || DEBUG || D2) { ShowAction(); printf("%s: %s",VPREFIX,buffer); endl = true; } if (LOGGING && IsPrivileged() && !DONTDO) { syslog(LOG_NOTICE, "%s", buffer); if ((errstr != NULL) && (strlen(errstr) != 0)) { syslog(LOG_ERR,"%s: %s",errstr,strerror(errno)); } } break; case cfverbose: if (VERBOSE || DEBUG || D2) { if ((errstr == NULL) || (strlen(errstr) > 0)) { ShowAction(); printf("%s: %s\n",VPREFIX,buffer); printf("%s: %s",VPREFIX,errstr); endl = true; } else { ShowAction(); printf("%s: %s",VPREFIX,buffer); endl = true; } } break; case cfeditverbose: if (EDITVERBOSE || DEBUG) { ShowAction(); printf("%s: %s",VPREFIX,buffer); endl = true; } break; case cflogonly: if (LOGGING && IsPrivileged() && !DONTDO) { syslog(LOG_ERR," %s",buffer); if ((errstr != NULL) && (strlen(errstr) > 0)) { syslog(LOG_ERR," %s",errstr); } } break; case cfloginform: if (LOGGING && IsPrivileged() && !DONTDO) { syslog(LOG_INFO," %s",buffer); if ((errstr != NULL) && (strlen(errstr) > 0)) { syslog(LOG_INFO," %s",errstr); } } break; case cferror: printf("%s: %s",VPREFIX,buffer); if (LOGGING && IsPrivileged() && !DONTDO) { syslog(LOG_ERR," %s",buffer); } if (buffer[strlen(buffer)-1] != '\n') { printf("\n"); } if ((errstr != NULL) && (strlen(errstr) > 0)) { ShowAction(); printf("%s: %s: %s\n",VPREFIX,errstr,strerror(errno)); endl = true; if (LOGGING && IsPrivileged() && !DONTDO) { syslog(LOG_ERR, " %s: %s",errstr,strerror(errno)); } } } #if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) if (pthread_mutex_unlock(&MUTEX_SYSCALL) != 0) { /* CfLog(cferror,"pthread_mutex_unlock failed","lock");*/ } #endif if (endl && (buffer[strlen(buffer)-1] != '\n')) { printf("\n"); } } /*****************************************************************************/ void ResetOutputRoute (char log,char inform) { if ((log == 'y') || (log == 'n') || (inform == 'y') || (inform == 'n')) { INFORM_save = INFORM; LOGGING_save = LOGGING; switch (log) { case 'y': LOGGING = true; break; case 'n': LOGGING = false; break; } switch (inform) { case 'y': INFORM = true; break; case 'n': INFORM = false; break; } } else { INFORM = INFORM_save; LOGGING = LOGGING_save; } } /*****************************************************************************/ void ShowAction() { if (SHOWACTIONS) { printf("%s:",CFLOCK); } } /*****************************************************************************/ void AuditStatusMessage(char status) { switch (status) /* Reminder */ { case CF_CHG: printf("made a system correction\n"); break; case CF_WARN: printf("promise not kept, no action taken"); break; case CF_TIMEX: printf("timed out\n"); break; case CF_FAIL: printf("failed to make a correction\n"); break; case CF_DENIED: printf("was denied access to an essential resource\n"); break; case CF_INTERPT: printf("was interrupted\n"); break; case CF_REGULAR: printf("was a regular (repeatable) maintenance task"); break; case CF_NOP: printf("was applied but performed no required actions\n"); break; case CF_UNKNOWN: printf("was applied but status unknown\n"); break; case CF_REPORT: printf("report\n"); break; } } cfengine-2.2.10/src/dtypes.c0000644000175000001440000000536410425436161012544 00000000000000 /* Copyright (C) 1995- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: dtypes.c */ /* */ /* Created: Sun Apr 18 17:16:51 2004 */ /* */ /* Author: > */ /* */ /* Revision: $Id$ */ /* */ /* Description: */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #include /*****************************************************************/ int IsSocketType(char *s) { int i; for (i = 0; i < ATTR; i++) { if (strstr(s,ECGSOCKS[i].name)) { Debug("IsSocketType(%s=%s)\n",s,ECGSOCKS[i].name); return true; } } return false; } /*****************************************************************/ int IsTCPType(char *s) { int i; for (i = 0; i < CF_NETATTR; i++) { if (strstr(s,TCPNAMES[i])) { Debug("IsTCPType(%s)\n",s); return true; } } return false; } /*****************************************************************/ int IsProcessType(char *s) { int i; if (strcmp(s,"procs") == 0) { return true; } return false; } cfengine-2.2.10/src/cfetool.c0000644000175000001440000021654711045550641012675 00000000000000/* cfetool for GNU Copyright (C) 2001- Free Software Foundation, Inc. This file is part of GNU cfetool - an addition to GNU cfengine. It is written by Elizabeth Cassell and Alf Wachsmann, Stanford Linear Accelerator Center (SLAC), SLAC Computing Services, 2575 Sand Hill Road M/S 97, Menlo Park, CA 94025, USA. GNU cfengine is written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: cfetool.c */ /* */ /* Description: Standalone UI for Long term state registry */ /* */ /*****************************************************************************/ #include "../pub/getopt.h" #include "cf.defs.h" #include "cf.extern.h" #include "cfetooldefs.h" struct option CREATEOPTIONS[] = { {"step", required_argument, 0, 's'}, {"cfenvd", no_argument, 0, 'c'}, {"weekly", no_argument, 0, 'w'}, {"daily", no_argument, 0, 'd'}, {"yearly", no_argument, 0, 'y'}, {"path", required_argument, 0, 'p'}, {"debug", optional_argument, 0, 'D'}, {"histograms", no_argument, 0, 'H'}, {"verbose", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {"file", required_argument, 0, 'f'}, {NULL, 0, 0, 0} }; struct option UPDATEOPTIONS[] = { {"cfenvd", no_argument, 0, 'c'}, {"weekly", no_argument, 0, 'w'}, {"daily", no_argument, 0, 'd'}, {"yearly", no_argument, 0, 'y'}, {"path", required_argument, 0, 'p'}, {"help", no_argument, 0, 'h'}, {"debug", optional_argument, 0, 'D'}, {"verbose", no_argument, 0, 'v'}, {"time", required_argument, 0, 't'}, {"histograms", no_argument, 0, 'H'}, {"value", required_argument, 0, 'V'}, {"debugging", no_argument, 0, 'E'}, {"debugging2", no_argument, 0, 'Y'}, {NULL, 0, 0, 0} }; struct option CHECKOPTIONS[] = { {"weekly", no_argument, 0, 'w'}, {"daily", no_argument, 0, 'd'}, {"yearly", no_argument, 0, 'y'}, {"path", required_argument, 0, 'p'}, {"help", no_argument, 0, 'h'}, {"debug", optional_argument, 0, 'D'}, {"verbose", no_argument, 0, 'v'}, {"time", required_argument, 0, 't'}, {"histograms", no_argument, 0, 'H'}, {"value", required_argument, 0, 'V'}, {"debugging", no_argument, 0, 'E'}, {"debugging2", no_argument, 0, 'Y'}, {NULL, 0, 0, 0} }; struct option INFOOPTIONS[] = { {"weekly", no_argument, 0, 'w'}, {"daily", no_argument, 0, 'd'}, {"yearly", no_argument, 0, 'y'}, {"path", required_argument, 0, 'p'}, {"help", no_argument, 0, 'h'}, {"debug", optional_argument, 0, 'D'}, {"verbose", no_argument, 0, 'v'}, {NULL, 0, 0, 0} }; struct option DUMPOPTIONS[] = { {"weekly", no_argument, 0, 'w'}, {"daily", no_argument, 0, 'd'}, {"yearly", no_argument, 0, 'y'}, {"path", required_argument, 0, 'p'}, {"help", no_argument, 0, 'h'}, {"debug", optional_argument, 0, 'D'}, {"verbose", no_argument, 0, 'v'}, {"file", required_argument, 0, 'f'}, {NULL, 0, 0, 0} }; struct option IMPORTOPTIONS[] = { {"weekly", no_argument, 0, 'w'}, {"daily", no_argument, 0, 'd'}, {"yearly", no_argument, 0, 'y'}, {"path", required_argument, 0, 'p'}, {"help", no_argument, 0, 'h'}, {"debug", optional_argument, 0, 'D'}, {"verbose", no_argument, 0, 'v'}, {"file", required_argument, 0, 'f'}, {NULL, 0, 0, 0} }; /*************************************************************************/ /* GLOBALS */ /*************************************************************************/ int weekly = false; int daily = false; int yearly = false; int cfenvd_compatible = false; unsigned int HISTOGRAM[24][CF_GRAINS]; int HISTO = false; double VALUE=0; char *NAME; char LOCATION[CF_BUFSIZE]; struct Average LOCALAV; char OUTPUT[CF_BUFSIZE * 2]; char BATCHFILE[CF_BUFSIZE]; char AVDB[1024]; char PATHNAME[CF_BUFSIZE]; double ITER=0; /* Iteration since start */ double AGE=0, WAGE=0; /* Age and weekly age of database */ time_t update_time=0; time_t last_time=0; int STEP = 5; int INTERVAL=0; char *PROG_NAME; int BATCH_MODE = false; DBT key, value; DB *dbp; int time_to_update = false; int DEBUGGING = false; int DEBUGGING2 = false; char ENVCF_NEW[CF_BUFSIZE]; char ENVCF[CF_BUFSIZE]; /*************************************************************************/ #define Debugging if(DEBUGGING) printf #define Debugging2 if(DEBUGGING2) printf /*************************************************************************/ void parse_create_opts (int argc, char **argv); void parse_update_opts (int argc, char **argv); void parse_check_opts (int argc, char **argv); void parse_info_opts (int argc, char **argv); void parse_dump_opts (int argc, char **argv); void parse_import_opts (int argc, char **argv); void Create (int step, int dbtype); int Update (double value, time_t u_time, int dbtype); int Check (double value, time_t u_time, int dbtype, int *bucket); void Info (int dbtype); void Dump (FILE * fp, int dbtype); void Import (FILE * fp, int dbtype); void skip (char **buf); void parse_entry (char **buffer); void GetDatabaseAge (int dbtype); struct Average EvalAvQ (char *t, int dbtype, int update); struct Average *GetCurrentAverage (char *timekey, int dbtype); void UpdateAverage (char *timekey, struct Average newvals); void UpdateDistribution (char *timekey, struct Average * av, int dbtype); double RejectAnomaly (double new, double av, double var, double av2, double var2); double WAverage (double newvals, double oldvals, double age); void LoadHistogram (int dbtype); int ArmClasses (struct Average av, char *timekey); int SetClasses (char *name, double variable, double av_expect, double av_var, double localav_expect, double localav_var, struct Item ** classlist, char *timekey, int *code); void SetVariable (char *name,double now, double average, double stddev, struct Item **list); void Syntax (void); void CreateSyntax (void); void UpdateSyntax (void); void CheckSyntax (void); void InfoSyntax (void); void DumpSyntax (void); void ImportSyntax (void); void FatalError (char *s); void yyerror (char *s); void DoBatch (int dbtype); void CloseDatabase (void); int OpenDatabase (int create); /*************************************************************************/ /* Level 0 */ /*************************************************************************/ int main(int argc, char **argv) { char *command; int i; IGNORELOCK = false; OUTPUT[0] = '\0'; PROG_NAME = argv[0]; memset(PATHNAME, 0, sizeof(PATHNAME)); if (argc < 2) { Syntax(); exit(1); } command = argv[1]; if(argc < 3 || argv[2][0] == '-') { if (strcmp(command, "import") == 0) ImportSyntax(); else if (strcmp(command, "update") == 0) UpdateSyntax(); else if (strcmp(command, "check") == 0) CheckSyntax(); else if (strcmp(command, "info") == 0) InfoSyntax(); else if (strcmp(command, "dump") == 0) DumpSyntax(); else if (strcmp(command, "create") == 0) CreateSyntax(); else Syntax(); exit(1); } NAME = argv[2]; for( i = 0; NAME[i] != '\0'; i++) { if(!isalnum(NAME[i])) { fprintf(stderr, "Name must contain only letters (A to Z or a to z) or digits (0 to 9)\n"); exit(1); } } if (strcmp(NAME, "value") == 0) { fprintf(stderr, "Name cannot be \"value\"\n"); exit(1); } if(strcmp(NAME, "average") == 0) { fprintf(stderr, "Name cannot be \"average\"\n"); exit(1); } if(strcmp(NAME, "stddev") == 0) { fprintf(stderr, "Name cannot be \"stddev\"\n"); exit(1); } strncpy(VLOCKDIR,WORKDIR,CF_BUFSIZE-1); strncpy(VLOGDIR,WORKDIR,CF_BUFSIZE-1); snprintf(ENVCF_NEW,CF_BUFSIZE,"%s/state/%s",WORKDIR,CF_ENVNEW_FILE); snprintf(ENVCF,CF_BUFSIZE,"%s/state/%s",WORKDIR,CF_ENV_FILE); argv += 2; argc -= 2; if (strcmp(command, "create") == 0) { parse_create_opts(argc, argv); } else if (strcmp(command, "update") == 0) { parse_update_opts(argc, argv); } else if (strcmp(command, "check") == 0) { parse_check_opts(argc, argv); } else if (strcmp(command, "info") == 0) { parse_info_opts(argc, argv); } else if (strcmp(command, "dump") == 0) { parse_dump_opts(argc, argv); } else if (strcmp(command, "import") == 0) { parse_import_opts(argc, argv); } else { Syntax(); exit(1); } return 0; } /*********************************************************************/ void parse_create_opts(int argc, char **argv) { extern char *optarg; int optindex = 0; int c; while ((c = getopt_long(argc, argv, "p:s:dwyf:DHhvc", CREATEOPTIONS, &optindex)) != EOF) { switch ((char)c) { case 'D': DEBUG = true; break; case 'c': cfenvd_compatible = true; break; case 'f': BATCH_MODE = true; strcpy(BATCHFILE, optarg); break; case 'v': VERBOSE = true; break; case 'H': HISTO = true; break; case 'p': strcpy(PATHNAME,optarg); break; case 's': STEP = atoi(optarg); if (STEP > 1440 || STEP < 1 || 1440 % STEP) { fprintf(stderr, "step must be an integer number of minutes that divides evenly into 24 hours.\n"); exit(1); } break; case 'd': daily = true; break; case 'w': weekly = true; break; case 'y': yearly = true; break; default: printf("Syntax:\n\n"); CreateSyntax(); exit(1); } } if (daily) { Create(STEP, DAILY); } if (weekly || (!daily && !yearly)) { Create(STEP, WEEKLY); } if (yearly) { Create(STEP, YEARLY); } } /*********************************************************************/ void parse_update_opts(int argc, char **argv) { int dcode=0, wcode=0, ycode=0; double value = 0; time_t u_time = 0; extern char *optarg; int c, got_time = 0, got_val = 0; int optindex = 0; while ((c = getopt_long(argc, argv, "ct:V:DvhYHEdwyp:", UPDATEOPTIONS, &optindex)) != EOF) { switch ((char)c) { case 'c': cfenvd_compatible = true; break; case 'D': DEBUG = true; break; case 'E': DEBUGGING = true; break; case 'Y': DEBUGGING2 = true; break; case 'v': VERBOSE = true; break; case 'H': HISTO = true; break; case 'p': strcpy(PATHNAME,optarg); break; case 't': u_time = (time_t) atoi(optarg); got_time = 1; break; case 'V': value = atof(optarg); got_val = 1; break; case 'd': daily = true; break; case 'w': weekly = true; break; case 'y': yearly = true; break; default: printf("Syntax:\n\n"); UpdateSyntax(); exit(1); } } if (!got_val) { printf("Syntax:\n\n"); UpdateSyntax(); exit(1); } if (!got_time) { u_time = time(NULL); Verbose("using current time\n"); } if(daily) { dcode = Update(value, u_time, DAILY); } if (weekly || (!daily && !yearly)) { wcode = Update(value, u_time, WEEKLY); } if (yearly) { ycode = Update(value, u_time, YEARLY); } printf("yrly=%d,wkly=%d,dly=%d\n", ycode, wcode, dcode); Verbose("\n"); if (dcode <= wcode && dcode <= ycode) { exit(dcode); } else if(wcode <= dcode && wcode <= ycode) { exit(wcode); } else { exit(ycode); } } /*********************************************************************/ void parse_check_opts(int argc, char **argv) { int dcode=0, wcode=0, ycode=0; int dbucket=0, wbucket=0, ybucket=0; double value = 0; time_t u_time = 0; extern char *optarg; int c, got_time = 0, got_val = 0; int optindex = 0; while ((c = getopt_long(argc, argv, "t:V:vhHDEYdwyp:", CHECKOPTIONS, &optindex)) != EOF) { switch ((char)c) { case 'D': DEBUG = true; break; case 'E': DEBUGGING = true; break; case 'Y': DEBUGGING2 = true; break; case 'v': VERBOSE = true; break; case 'H': HISTO = true; break; case 'p': strcpy(PATHNAME,optarg); break; case 't': u_time = (time_t) atoi(optarg); got_time = 1; break; case 'V': value = atof(optarg); got_val = 1; break; case 'd': daily = true; break; case 'w': weekly = true; break; case 'y': yearly = true; break; default: printf("Syntax:\n\n"); CheckSyntax(); exit(1); } } if (!got_val) { printf("Syntax:\n\n"); CheckSyntax(); exit(1); } if (!got_time) { u_time = time(NULL); Verbose("using current time\n"); } if (daily) { dcode = Check(value, u_time, DAILY, &dbucket); } if (weekly || (!daily && !yearly)) { wcode = Check(value, u_time, WEEKLY, &wbucket); } if (yearly) { ycode = Check(value, u_time, YEARLY, &ybucket); } printf("yrly=%d,bkt=%d;wkly=%d,bkt=%d;dly=%d,bkt=%d\n", ycode, ybucket, wcode, wbucket, dcode, dbucket); Verbose("\n"); if (dcode <= wcode && dcode <= ycode) { exit(dcode); } if (wcode <= dcode && wcode <= ycode) { exit(wcode); } if (ycode <= dcode && ycode <= wcode) { exit(ycode); } } /*********************************************************************/ void parse_info_opts(int argc, char **argv) { int optindex = 0, c; while ((c = getopt_long(argc, argv, "DvYEhdwyp:", INFOOPTIONS, &optindex)) != EOF) { switch ((char)c) { case 'D': DEBUG = true; break; case 'p': strcpy(PATHNAME,optarg); break; case 'E': DEBUGGING = true; break; case 'Y': DEBUGGING2 = true; break; case 'v': VERBOSE = true; break; case 'd': daily = true; break; case 'w': weekly = true; break; case 'y': yearly = true; break; default: printf("Syntax:\n\n"); InfoSyntax(); exit(1); } } if (daily) { printf("\nDaily average database:\n"); Info(DAILY); } if (weekly || (!daily && !yearly)) { printf("\nWeekly average database:\n"); Info(WEEKLY); } if (yearly) { printf("\nYearly average database:\n"); Info(YEARLY); } } /*********************************************************************/ void parse_dump_opts(int argc, char **argv) { int optindex = 0, c; char DUMPFILE[CF_BUFSIZE]; FILE *fp; DUMPFILE[0] = '\0'; while ((c = getopt_long(argc, argv, "DvYEhf:dwyp:", DUMPOPTIONS, &optindex)) != EOF) { switch ((char)c) { case 'D': DEBUG = true; break; case 'E': DEBUGGING = true; break; case 'p': strcpy(PATHNAME,optarg); break; case 'Y': DEBUGGING2 = true; break; case 'v': VERBOSE = true; break; case 'f': strcpy(DUMPFILE, optarg); break; case 'd': daily = true; break; case 'w': weekly = true; break; case 'y': yearly = true; break; default: printf("Syntax:\n\n"); DumpSyntax(); exit(1); } } if (DUMPFILE[0] == '\0') { fprintf(stdout, "\n", PROG_NAME); if(daily) { Dump(stdout, DAILY); } if(weekly || (!daily && !yearly)) { Dump(stdout, WEEKLY); } if(yearly) { Dump(stdout, YEARLY); } } else if ((fp = fopen(DUMPFILE, "w")) != NULL) { fprintf(fp, "\n", PROG_NAME); if (daily) { Dump(fp, DAILY); } if (weekly || (!daily && !yearly)) { Dump(fp, WEEKLY); } if (yearly) { Dump(fp, YEARLY); } fclose(fp); } else { fprintf(stderr, "Unable to open file \"%s\"\n", DUMPFILE); fprintf(stderr, "fopen: %s\n", strerror(errno)); } } /*********************************************************************/ void parse_import_opts(int argc, char **argv) { int optindex = 0, c; char IMPORTFILE[CF_BUFSIZE]; FILE *fp; IMPORTFILE[0] = '\0'; while ((c = getopt_long(argc, argv, "DvYEhf:dwy", IMPORTOPTIONS, &optindex)) != EOF) { switch ((char)c) { case 'D': DEBUG = true; break; case 'E': DEBUGGING = true; break; case 'Y': DEBUGGING2 = true; break; case 'p': strcpy(PATHNAME,optarg); break; case 'v': VERBOSE = true; break; case 'f': strcpy(IMPORTFILE, optarg); break; case 'd': daily = true; break; case 'w': weekly = true; break; case 'y': yearly = true; break; default: printf("Syntax:\n\n"); ImportSyntax(); exit(1); } } if (IMPORTFILE[0] == '\0') { printf("Syntax:\n\n"); ImportSyntax(); exit(1); } else if ((fp = fopen(IMPORTFILE, "r")) != NULL) { if (daily) { Import(fp, DAILY); rewind(fp); } if (weekly || (!daily && !yearly)) { Import(fp, WEEKLY); rewind(fp); } if (yearly) { Import(fp, YEARLY); rewind(fp); } fclose(fp); } else { fprintf(stderr, "Unable to open file \"%s\"\n", IMPORTFILE); fprintf(stderr, "fopen: %s\n", strerror(errno)); } } /*********************************************************************/ void Create(int step, int dbtype) { time_t timestamp; char filename[CF_BUFSIZE]; int cwdbufsize = CF_BUFSIZE - strlen(PATHNAME) - strlen(NAME); char current_dir[CF_BUFSIZE]; AGE = WAGE = 0; ITER = 0; LOCALAV.expect = 0.0; LOCALAV.var = 0.0; /* make file */ if (getcwd(current_dir, cwdbufsize) == NULL) { perror("getcwd"); } if (PATHNAME[0] == '\0') { sprintf(LOCATION, "%s/%s", current_dir, NAME); } else if(PATHNAME[0] == '/') { sprintf(LOCATION, "%s/%s", PATHNAME, NAME); } else { sprintf(LOCATION, "%s/%s/%s", current_dir, PATHNAME, NAME); } switch(dbtype) { case DAILY: sprintf(AVDB, "%s/daily.db", LOCATION); break; case YEARLY: sprintf(AVDB, "%s/yearly.db", LOCATION); break; default: /* weekly */ sprintf(AVDB, "%s/weekly.db", LOCATION); break; } Verbose("Creating new database: %s\n", AVDB); MakeDirectoriesFor(AVDB, 'n'); if (HISTO) { switch(dbtype) { case DAILY: snprintf(filename, CF_BUFSIZE, "%s/daily.hist", LOCATION); break; case YEARLY: snprintf(filename, CF_BUFSIZE, "%s/yearly.hist", LOCATION); break; default: /* weekly */ snprintf(filename, CF_BUFSIZE, "%s/weekly.hist", LOCATION); break; } Verbose("Creating histogram file: %s\n", filename); CreateEmptyFile(filename); } if (OpenDatabase(true) != 0) { exit(1); } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &AGE; value.size = sizeof(double); key.data = "DATABASE_AGE"; key.size = strlen("DATABASE_AGE") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } timestamp = time(NULL); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = ×tamp; value.size = sizeof(timestamp); key.data = "TIMESTAMP"; key.size = strlen("TIMESTAMP") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &LOCALAV; value.size = sizeof(LOCALAV); key.data = "LOCALAV"; key.size = strlen("LOCALAV") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &step; value.size = sizeof(step); key.data = "STEP"; key.size = strlen("STEP") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &ITER; value.size = sizeof(ITER); key.data = "ITERATIONS"; key.size = strlen("ITERATIONS") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } Verbose("Successfully created database at %s\n", AVDB); if (BATCH_MODE) { DoBatch(dbtype); } CloseDatabase(); } /*********************************************************************/ int Update(double value, time_t u_time, int dbtype) { struct Average average; char *timekey; int i, j; update_time = u_time; VALUE = value; if(PATHNAME[0] != '\0') { sprintf(LOCATION, "%s/%s", PATHNAME, NAME); } else { sprintf(LOCATION, "./%s", NAME); } switch(dbtype) { case DAILY: sprintf(AVDB, "%s/daily.db", LOCATION); break; case YEARLY: sprintf(AVDB, "%s/yearly.db", LOCATION); break; default: /* weekly */ sprintf(AVDB, "%s/weekly.db", LOCATION); break; } Verbose("Updating database: %s\n", AVDB); LOCALAV.expect = 0.0; LOCALAV.var = 0.0; ITER = 0.0; for (i = 0; i < 7; i++) { for (j = 0; j < CF_GRAINS; j++) { HISTOGRAM[i][j] = 0; } } if (OpenDatabase(false) != 0) { exit(1); } srand((unsigned int)time(NULL)); LoadHistogram(dbtype); GetDatabaseAge(dbtype); timekey = GenTimeKey2(update_time, dbtype); Verbose("Time key is: %s\n", timekey); average = EvalAvQ(timekey, dbtype, true); CloseDatabase(); return ArmClasses(average, timekey); } /*********************************************************************/ int Check(double value, time_t u_time, int dbtype, int *bucket) { struct Average average; char *timekey; int i, j, sig; Verbose("Checking %.3lf, time %d\n", value, u_time); update_time = u_time; VALUE = value; if(PATHNAME[0] != '\0') { sprintf(LOCATION, "%s/%s", PATHNAME, NAME); } else { sprintf(LOCATION, "./%s", NAME); } switch(dbtype) { case DAILY: sprintf(AVDB, "%s/daily.db", LOCATION); break; case YEARLY: sprintf(AVDB, "%s/yearly.db", LOCATION); break; default: /* weekly */ sprintf(AVDB, "%s/weekly.db", LOCATION); break; } Verbose("Updating database: %s\n", AVDB); LOCALAV.expect = 0.0; LOCALAV.var = 0.0; ITER = 0.0; for (i = 0; i < 7; i++) { for (j = 0; j < CF_GRAINS; j++) { HISTOGRAM[i][j] = 0; } } if (OpenDatabase(false) != 0) { exit(1); } srand((unsigned int)time(NULL)); LoadHistogram(dbtype); GetDatabaseAge(dbtype); timekey = GenTimeKey2(update_time, dbtype); Verbose("Time key is: %s\n", timekey); average = EvalAvQ(timekey, dbtype, false); *bucket = CF_GRAINS / 2 + (int)(0.5 + (VALUE - average.expect) * CF_GRAINS / (4.0 * sqrt(average.var))); CloseDatabase(); return ArmClasses(average, timekey); } /*********************************************************************/ void Info(int dbtype) { int i; char lastupdate[CF_BUFSIZE]; char histfile[CF_BUFSIZE]; FILE *tempfile; memset(lastupdate, 0, CF_BUFSIZE); Verbose("Gathering database info...\n"); if (PATHNAME[0] != '\0') { sprintf(LOCATION, "%s/%s", PATHNAME, NAME); } else { sprintf(LOCATION, "./%s", NAME); } switch(dbtype) { case DAILY: sprintf(AVDB, "%s/daily.db", LOCATION); sprintf(histfile, "%s/daily.hist", LOCATION); break; case YEARLY: sprintf(AVDB, "%s/yearly.db", LOCATION); sprintf(histfile, "%s/yearly.hist", LOCATION); break; default: /* weekly */ sprintf(AVDB, "%s/weekly.db", LOCATION); sprintf(histfile, "%s/weekly.hist", LOCATION); break; } printf("Database Location: %s\n", AVDB); if((tempfile = fopen(histfile, "r")) != NULL) { printf("Histogram file: %s\n", histfile); fclose(tempfile); } else { printf("No histogram file\n"); } LOCALAV.expect = 0.0; LOCALAV.var = 0.0; ITER = 0.0; if(OpenDatabase(false) != 0) { exit(1); } GetDatabaseAge(dbtype); printf("Step: %d minutes\n", (int)STEP); switch(dbtype) { case DAILY: printf("Database Age: %lf days (%d steps)\n", (double)WAGE, (int)AGE); break; case YEARLY: printf("Database Age: %lf years (%d steps)\n", (double)WAGE, (int)AGE); break; default: /* weekly */ printf("Database Age: %lf weeks (%d steps)\n", (double)WAGE, (int)AGE); break; } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); key.data = "TIMESTAMP"; key.size = strlen("TIMESTAMP") + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } } if (value.data != NULL) { last_time = *(time_t *) value.data; strncpy(lastupdate, ctime(&last_time), strlen(ctime(&last_time)) - 1); printf("Last update: %s (%d)\n", lastupdate, (int)last_time); } else { Debug("No timestamp\n"); } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); key.data = "LOCALAV"; key.size = strlen("LOCALAV") + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } } if (value.data != NULL) { memcpy(&LOCALAV, value.data, sizeof(LOCALAV)); printf("Current average: %lf, Var: %lf\n", (double)LOCALAV.expect,(double)LOCALAV.var); } else Debug("No LOCALAV\n"); CloseDatabase(); } /*********************************************************************/ void Dump(FILE * fp, int dbtype) { time_t NOW; char str[256]; char *timekey; struct Average entry; int begin_time; int total_time; if(PATHNAME[0] != '\0') { sprintf(LOCATION, "%s/%s", PATHNAME, NAME); } else { sprintf(LOCATION, "./%s", NAME); } memset(str, 0, 256); switch(dbtype) { case DAILY: sprintf(AVDB, "%s/daily.db", LOCATION); begin_time = MONDAY_MORNING; total_time = ONE_DAY; break; case YEARLY: sprintf(AVDB, "%s/yearly.db", LOCATION); begin_time = JANUARY_FIRST; total_time = ONE_YEAR; break; default: /* weekly */ sprintf(AVDB, "%s/weekly.db", LOCATION); begin_time = MONDAY_MORNING; total_time = ONE_WEEK; break; } Verbose("Dumping database: %s\n",AVDB); if (OpenDatabase(false) != 0) { exit(1); } GetDatabaseAge(dbtype); memset(&value, 0, sizeof(value)); key.data = "TIMESTAMP"; key.size = strlen("TIMESTAMP") + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } } if (value.data != NULL) { last_time = *(time_t *) value.data; } else { Debug("No timestamp\n"); } Verbose("Timestamp is %d\n", last_time); memset(&value, 0, sizeof(value)); key.data = "LOCALAV"; key.size = strlen("LOCALAV") + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } } if (value.data != NULL) { memcpy(&LOCALAV, value.data, sizeof(LOCALAV)); } else { Debug("No previous LOCALAV\n"); } Verbose("LOCALAV.expect=%lf, LOCALAV.var=%lf\n", LOCALAV.expect, LOCALAV.var); memset(&value, 0, sizeof(value)); key.data = "ITERATIONS"; key.size = strlen("ITERATIONS") + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } } if (value.data != NULL) { ITER = *(double *)value.data; } else { Debug("No previous iterations\n"); } Verbose("ITER = %d\n", (int)ITER); switch(dbtype) { case DAILY: fprintf(fp, "\n\n\n"); break; case YEARLY: fprintf(fp, "\n\n\n"); break; default: /* weekly */ fprintf(fp, "\n\n\n"); break; } fprintf(fp, "\t %s \n\n", NAME); fprintf(fp, "\t %d \n\n"); break; case YEARLY: fprintf(fp, " years) -->\n\n"); break; default: /* weekly */ fprintf(fp, " weeks) -->\n\n"); break; } fprintf(fp, "\t %d \n\n", (int)STEP); fprintf(fp, "\t\n"); fprintf(fp, "\t %d \n\n", (int)ITER); strncpy(str, ctime(&last_time), strlen(ctime(&last_time)) - 1); fprintf(fp, "\t\n", str); fprintf(fp, "\t %d \n\n", (int)last_time); fprintf(fp, "\t\n"); fprintf(fp, "\t %lf \n\n", (double)LOCALAV.expect); fprintf(fp, "\t\n"); fprintf(fp, "\t %lf \n\n", (double)LOCALAV.var); fprintf(fp, "\n\n"); for (NOW = begin_time; NOW < begin_time + total_time; NOW += INTERVAL) { sprintf(str, "%s", ctime(&NOW)); timekey = ConvTimeKey2(str, dbtype); memset(&value, 0, sizeof(value)); memset(&entry, 0, sizeof(entry)); memset(&key, 0, sizeof(key)); key.data = timekey; key.size = strlen(timekey) + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } } if (value.data != NULL) { memcpy(&entry, value.data, sizeof(entry)); fprintf(fp, "\t"); fprintf(fp, "\t %s \n", timekey); fprintf(fp, "\t\t %lf \n", (double)entry.expect); fprintf(fp, "\t\t %lf \n", (double)entry.var); fprintf(fp, "\t\n"); } else Debug("No previous value for time index %s\n", timekey); } switch(dbtype) { case DAILY: fprintf(fp, "\n\n"); break; case YEARLY: fprintf(fp, "\n\n"); break; default: /* weekly */ fprintf(fp, "\n\n"); break; } CloseDatabase(); } /*********************************************************************/ void Import(FILE * fp, int dbtype) { char *buffer; char command[CF_BUFSIZE]; int i=0, j=0; char info[CF_BUFSIZE], temp[CF_BUFSIZE]; char *dumpcommand; char begincommand[128], endcommand[128]; if (PATHNAME[0] != '\0') { sprintf(LOCATION, "%s/%s", PATHNAME, NAME); } else { sprintf(LOCATION, "./%s", NAME); } LOCALAV.expect = 0.0; LOCALAV.var = 0.0; STEP = 5; AGE = 0; last_time = 0; ITER = 0; mkdir(LOCATION, 0755); switch(dbtype) { case DAILY: dumpcommand = "dailydump"; sprintf(AVDB, "%s/daily.db", LOCATION); break; case YEARLY: dumpcommand = "yearlydump"; sprintf(AVDB, "%s/yearly.db", LOCATION); break; default: /* weekly */ dumpcommand = "weeklydump"; sprintf(AVDB, "%s/weekly.db", LOCATION); break; } sprintf(begincommand, "<%s>", dumpcommand); sprintf(endcommand, "/%s", dumpcommand); Verbose("Importing to database: %s\n", AVDB); if (OpenDatabase(true) != 0) { exit(1); } while (!feof(fp)) { getc(fp); i++; } rewind(fp); if ((buffer = (char *)malloc(i * sizeof(char))) == NULL) { fprintf(stderr, "Couldn't allocate buffer of %d chars\n", i); CloseDatabase(); exit(1); } j = (int)fread((void *)buffer, sizeof(char), (size_t) i, fp); if (j < i - 1) { fprintf(stderr, "Couldn't read file into buffer, got %d\n", j); CloseDatabase(); exit(1); } while (*buffer && strncmp(buffer, begincommand, strlen(dumpcommand)) != 0) { buffer++; skip(&buffer); } while (*buffer) { sscanf(buffer, "<%[^<> \t\r\n]>", command); buffer += strlen(command) + 2; skip(&buffer); if (strlen(command) == 0) { fprintf(stderr, "Couldn't get next command!\n"); CloseDatabase(); exit(1); } else if (strcmp(command, dumpcommand) == 0) { continue; } else if (strcmp(command, endcommand) == 0) { break; } else if (strcmp(command, "name") == 0) { sscanf(buffer, "%[^<> \t\r\n]", info); buffer += strlen(info); if (strcmp(info, NAME) != 0) Verbose("Previous database name was %s (now %s)\n", info, NAME); } else if (strcmp(command, "age") == 0) { sscanf(buffer, "%lf", &AGE); sscanf(buffer, "%[^<> \t\r\n]", info); buffer += strlen(info); } else if (strcmp(command, "step") == 0) { sscanf(buffer, "%d", &STEP); sscanf(buffer, "%[^<> \t\r\n]", info); buffer += strlen(info); } else if (strcmp(command, "iterations") == 0) { sscanf(buffer, "%lf", &ITER); sscanf(buffer, "%[^<> \t\r\n]", info); buffer += strlen(info); } else if (strcmp(command, "timestamp") == 0) { sscanf(buffer, "%d", &last_time); sscanf(buffer, "%[^<> \t\r\n]", info); buffer += strlen(info); } else if (strcmp(command, "expect") == 0) { sscanf(buffer, "%lf", &(LOCALAV.expect)); sscanf(buffer, "%[^<> \t\r\n]", info); buffer += strlen(info); } else if (strcmp(command, "var") == 0) { sscanf(buffer, "%lf", &(LOCALAV.var)); sscanf(buffer, "%[^<> \t\r\n]", info); buffer += strlen(info); } else if (strcmp(command, "entry") == 0) { parse_entry(&buffer); } else { fprintf(stderr, "Unrecognized tag: <%s>\n", command); CloseDatabase(); exit(1); } skip(&buffer); sprintf(temp, "", command); if (strncmp(buffer, temp, strlen(temp)) != 0) { fprintf(stderr, "Couldn't find !\n", command); memset(temp, 0, sizeof(temp)); strncpy(temp, buffer, 20); Debug("Next 20 chars in buffer: \"%s\"\n", temp); CloseDatabase(); exit(1); } buffer += strlen(temp); skip(&buffer); } Verbose("Storing database age (%d)\n", (int)AGE); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &AGE; value.size = sizeof(double); key.data = "DATABASE_AGE"; key.size = strlen("DATABASE_AGE") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } Verbose("Storing timestamp (%d)\n", (int)last_time); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &last_time; value.size = sizeof(last_time); key.data = "TIMESTAMP"; key.size = strlen("TIMESTAMP") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } Verbose("Storing LOCALAV (expect: %.3lf, var: %.3lf)\n", LOCALAV.expect, LOCALAV.var); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &LOCALAV; value.size = sizeof(LOCALAV); key.data = "LOCALAV"; key.size = strlen("LOCALAV") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } Verbose("Storing step (%d)\n", (int)STEP); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &STEP; value.size = sizeof(STEP); key.data = "STEP"; key.size = strlen("STEP") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } Verbose("Storing iterations (%d)\n", (int)ITER); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &ITER; value.size = sizeof(ITER); key.data = "ITERATIONS"; key.size = strlen("ITERATIONS") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } CloseDatabase(); } /*********************************************************************/ /* copied from RRD tool */ void skip(char **buf) { char *ptr; ptr = (*buf); do { (*buf) = ptr; while ((*(ptr + 1)) && ((*ptr) == ' ' || (*ptr) == '\r' || (*ptr) == '\n' || (*ptr) == '\t')) { ptr++; } if (strncmp(ptr, ""); if (ptr) ptr += 3; else { fprintf(stderr, "Syntax error: Dangling Comment"); CloseDatabase(); exit(1); } } } while ((*buf) != ptr); } /*********************************************************************/ void parse_entry(char **buffer) { int t=0, e=0, v=0; struct Average current; char timekey[CF_BUFSIZE], temp[CF_BUFSIZE]; char command[CF_BUFSIZE]; while(strncmp(*buffer, "", 8) != 0) { sscanf(*buffer, "<%[^<> \t\r\n]>", command); (*buffer) += strlen(command) + 2; skip(buffer); if (strlen(command) == 0) { fprintf(stderr, "Couldn't get next command!\n"); CloseDatabase(); exit(1); } else if(strcmp(command, "timekey") == 0) { sscanf(*buffer, "%[^<> \t\r\n]", timekey); (*buffer) += strlen(timekey); if(strlen(timekey) != 0) { t++; } } else if(strcmp(command, "expect") == 0) { sscanf(*buffer, "%[^<> \t\r\n]", temp); sscanf(temp, "%lf", &(current.expect)); (*buffer) += strlen(temp); if (strlen(temp) != 0) { e++; } } else if(strcmp(command, "var") == 0) { sscanf(*buffer, "%[^<> \t\r\n]", temp); sscanf(temp, "%lf", &(current.var)); (*buffer) += strlen(temp); if(strlen(temp) != 0) { v++; } } else { fprintf(stderr, "Unrecognized tag: <%s>\n", command); CloseDatabase(); exit(1); } skip(buffer); sprintf(temp, "", command); if (strncmp(*buffer, temp, strlen(temp)) != 0) { fprintf(stderr, "Couldn't find !\n", command); memset(temp, 0, sizeof(temp)); strncpy(temp, *buffer, 20); Debug("Next 20 chars in buffer: \"%s\"\n", temp); CloseDatabase(); exit(1); } (*buffer) += strlen(temp); skip(buffer); } if (t != 1 || e != 1 || v != 1) { fprintf(stderr, "Couldn't find exactly one , and inside tag\n" ); CloseDatabase(); exit(1); } memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); key.data = timekey; key.size = strlen(timekey) + 1; value.data = ¤t; value.size = sizeof(current); if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); exit(1); } } /*********************************************************************/ void GetDatabaseAge(int dbtype) { int errno; STEP = 5; AGE = 0; WAGE = 0; Verbose("Getting database age and step\n"); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); key.data = "STEP"; key.size = strlen("STEP") + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } } if (value.data != NULL) { STEP = *(int *)(value.data); } else { Debug("No STEP!\n"); } INTERVAL = STEP * 60; Verbose("Step: %d (Interval: %d)\n", (int)STEP, (int)INTERVAL); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); key.data = "DATABASE_AGE"; key.size = strlen("DATABASE_AGE") + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } } if (value.data != NULL) { AGE = *(double *)(value.data); switch(dbtype) { case DAILY: WAGE = (double)(AGE*STEP)/1440.0; break; case YEARLY: WAGE = (double)(AGE*STEP)/(1440.0*365.242); break; default: /* weekly */ WAGE = AGE / ONE_WEEK * INTERVAL; break; } } else { Debug("No previous AGE\n"); } Verbose("Age: %d (%.3lf", (int)AGE, (double)WAGE); switch(dbtype) { case DAILY: Verbose(" days)\n"); break; case YEARLY: Verbose(" years)\n"); break; default: /* weekly */ Verbose(" weeks)\n"); break; } } /*********************************************************************/ struct Average EvalAvQ(char *t, int dbtype, int update) { struct Average *currentvals, newvals; int i; double new_value; if ((currentvals = GetCurrentAverage(t, dbtype)) == NULL) { fprintf(stderr, "Error reading average database\n"); exit(1); } /* Discard any apparently anomalous behaviour before renormalizing database */ if (update) { new_value = RejectAnomaly(VALUE, currentvals->expect, currentvals->var, LOCALAV.expect, LOCALAV.var); } else { new_value = VALUE; } Verbose("new_value = %lf\n", (double)new_value); Debugging("new_value = RejectAnomaly(%lf, %lf, %lf, %lf, %lf) = %lf\n", (double)VALUE, (double)currentvals->expect, (double)currentvals->var, (double)LOCALAV.expect, (double)LOCALAV.var, (double)new_value); newvals.expect = WAverage(new_value, currentvals->expect, WAGE); Verbose("newvals.expect = %lf\n", (double)newvals.expect); Debugging("newvals.expect = WAverage(%lf, %lf, %lf) = %lf\n", (double)new_value, (double)currentvals->expect, (double)WAGE, (double)newvals.expect); LOCALAV.expect = WAverage(newvals.expect, LOCALAV.expect, ITER); Verbose("LOCALAV.expect = %lf\n", (double)LOCALAV.expect); Debugging("LOCALAV.expect = WAverage(%lf, %lf, %lf) = %lf\n", (double)newvals.expect, (double)LOCALAV.expect, (double)ITER, (double)LOCALAV.expect); newvals.var = WAverage((new_value - newvals.expect) * (new_value - newvals.expect), currentvals->var, WAGE); Verbose("newvals.var = %lf\n", (double)newvals.var); Debugging("newvals.var = WAverage(%lf, %lf, %lf) = %lf\n", (double)(new_value - newvals.expect) * (new_value - newvals.expect), (double)currentvals->var, (double)WAGE, (double)newvals.var); LOCALAV.var = WAverage((new_value - LOCALAV.expect) * (new_value - LOCALAV.expect), LOCALAV.var, ITER); Verbose("LOCALAV.var = %lf\n", (double)LOCALAV.var); Debugging("LOCALAV.var = WAverage(%lf, %lf, %lf) = %lf\n", (double)(new_value - LOCALAV.expect) * (new_value - LOCALAV.expect), (double)LOCALAV.var, (double)ITER, (double)LOCALAV.var); Debugging("VALUE: %d, new_value: %lf\n", (int)VALUE, new_value); Debugging("newvals.expect: %lf, sqrt(newvals.var): %lf\n", newvals.expect, sqrt(newvals.var)); Debugging(" LOCALAV.expect: %lf, sqrt(LOCALAV.var): %lf\n", LOCALAV.expect, sqrt(LOCALAV.var)); if (update) { UpdateAverage(t, newvals); if (WAGE > CFGRACEPERIOD) { UpdateDistribution(t, currentvals, dbtype); /* Distribution about mean */ } } return newvals; } /*********************************************************************/ struct Average *GetCurrentAverage(char *timekey, int dbtype) { int errno; static struct Average entry; char str[64]; memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); key.data = "TIMESTAMP"; key.size = strlen("TIMESTAMP") + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); return NULL; } } if (value.data != NULL && (last_time = *(time_t *) value.data) + 2 * INTERVAL > update_time) { key.data = "ITERATIONS"; key.size = strlen("ITERATIONS") + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); return NULL; } } if (value.data != NULL) { ITER = *(double *)value.data; } else { Debug("No previous iterations\n"); } } else { Debug("Resetting ITER\n"); } Verbose("timestamp is %d, ITER = %d\n", (int)last_time, (int)ITER); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); key.data = "LOCALAV"; key.size = strlen("LOCALAV") + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); return NULL; } } if (value.data != NULL) { memcpy(&LOCALAV, value.data, sizeof(LOCALAV)); } else { Debug("No previous LOCALAV\n"); } Verbose("LOCALAV.expect=%.3lf, LOCALAV.var=%.3lf\n", LOCALAV.expect, LOCALAV.var); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); memset(&entry, 0, sizeof(entry)); key.data = timekey; key.size = strlen(timekey) + 1; if ((errno = dbp->get(dbp, NULL, &key, &value, 0)) != 0) { Debugging("Error getting previous value\n"); if (errno != DB_NOTFOUND) { dbp->err(dbp, errno, NULL); CloseDatabase(); return NULL; } } if (value.data != NULL) { memcpy(&entry, value.data, sizeof(entry)); Verbose("Got value (%.3lf,%.3lf) at time key %s\n", entry.expect, entry.var, timekey); Debugging("Previous value (%lf,%lf) for time index %s\n\n", entry.expect, entry.var, timekey); } else { Debugging("No previous value for time index %s\n", timekey); Debug("No previous value for time index %s\n", timekey); } sprintf(str, "%s", ctime(&last_time)); Verbose("time key for last update was %s\n", ConvTimeKey2(str, dbtype)); Verbose("comparing to current timekey %s\n", timekey); if (strcmp(ConvTimeKey2(str, dbtype), timekey) != 0) { Verbose("incrementing age\n"); AGE++; } else { Verbose("NOT incrementing age\n"); } switch(dbtype) { case DAILY: WAGE = (double)(AGE*STEP)/1440.0; break; case YEARLY: WAGE = (double)(AGE*STEP)/(1440.0*365.242); break; default: /* weekly */ WAGE = AGE / ONE_WEEK * INTERVAL; break; } return &entry; } /*****************************************************************************/ void UpdateAverage(char *timekey, struct Average newvals) { int errno; time_t timestamp; Verbose("Storing (%.3lf,%.3lf) at key %s\n", newvals.expect, newvals.var, timekey); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); Debugging("Storing %s (expect: %lf, var: %lf)\n", timekey, (double)newvals.expect, (double)newvals.var); key.data = timekey; key.size = strlen(timekey) + 1; value.data = &newvals; value.size = sizeof(newvals); if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } Verbose("Storing age (%d)\n", (int)AGE); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &AGE; value.size = sizeof(double); key.data = "DATABASE_AGE"; key.size = strlen("DATABASE_AGE") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } Verbose("Storing localav (%.3lf,%.3lf)\n", LOCALAV.expect, LOCALAV.var); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &LOCALAV; value.size = sizeof(LOCALAV); key.data = "LOCALAV"; key.size = strlen("LOCALAV") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } ITER++; Verbose("Storing iterations (%d)\n", (int)ITER); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &ITER; value.size = sizeof(ITER); key.data = "ITERATIONS"; key.size = strlen("ITERATIONS") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } Verbose("Storing timestamp (%d)\n", update_time); memset(&key, 0, sizeof(key)); memset(&value, 0, sizeof(value)); value.data = &update_time; value.size = sizeof(update_time); key.data = "TIMESTAMP"; key.size = strlen("TIMESTAMP") + 1; if ((errno = dbp->put(dbp, NULL, &key, &value, 0)) != 0) { dbp->err(dbp, errno, NULL); CloseDatabase(); return; } } /*****************************************************************************/ void UpdateDistribution(char *timekey, struct Average *av, int dbtype) { int position; int day, i, tmp, sig; char tempstr[4]; tempstr[3] = '\0'; /* Take an interval of 4 standard deviations from -2 to +2, divided into * CF_GRAINS parts. Centre each measurement on CF_GRAINS/2 and scale each * measurement by the std-deviation for the current time. */ if (HISTO) { Verbose("Updating histogram\n"); switch(dbtype) { case DAILY: tmp = atoi(timekey); day = (double)(tmp*STEP)/60.0; /* day is actually hour */ break; case YEARLY: strncpy(tempstr, timekey, 3); day = Month2Number(tempstr); /* day is actually month */ if(day == -1) { fprintf(stderr, "Couldn't convert month to number\n"); CloseDatabase(); exit(1); } break; default: /* weekly */ day = Day2Number(timekey); /* day really means day */ break; } position = CF_GRAINS / 2 + (int)(0.5 + (VALUE - av->expect) * CF_GRAINS / (4.0 * sqrt(av->var))); if (0 <= position && position < CF_GRAINS) { HISTOGRAM[day][position]++; } if (!BATCH_MODE || time_to_update) { FILE *fp; char filename[CF_BUFSIZE]; switch(dbtype) { case DAILY: snprintf(filename, CF_BUFSIZE, "%s/daily.hist", LOCATION); break; case YEARLY: snprintf(filename, CF_BUFSIZE, "%s/yearly.hist", LOCATION); break; default: /* weekly */ snprintf(filename, CF_BUFSIZE, "%s/weekly.hist", LOCATION); break; } if ((fp = fopen(filename, "w")) == NULL) { fprintf(stderr, "Unable to save histograms\n"); fprintf(stderr, "fopen: %s\n", strerror(errno)); return; } for (position = 0; position < CF_GRAINS; position++) { fprintf(fp, "%u ", position); for (day = 0; day < 24; day++) { fprintf(fp, "%u ", HISTOGRAM[day][position]); } fprintf(fp, "\n"); } fclose(fp); } } } /*********************************************************************/ double RejectAnomaly(double new, double average, double variance, double localav, double localvar) { double dev = sqrt(variance + localvar); /* Geometrical average dev */ double delta; int bigger; Verbose("Checking %.3lf for an anomaly..\n", new); if (average == 0) { Verbose("Keeping value; no previous average\n"); return new; } if (new > big_number) { Verbose("Using previous average (%.3lf); new value is too big\n", average); return average; } if ((new - average) * (new - average) < cf_noise_threshold * cf_noise_threshold) { Verbose("Keeping value; value is within noise threshold\n"); return new; } if (new - average > 0) { bigger = true; } else { bigger = false; } /* This routine puts some inertia into the changes, so that the system * doesn't respond to every little change ... IR and UV cutoff */ delta = sqrt((new - average) * (new - average) + (new - localav) * (new - localav)); if (delta > 4.0 * dev) /* IR */ { srand48((unsigned int)time(NULL)); if (drand48() < 0.7) /* 70% chance of using full value - as in * * learning policy */ { Verbose("Keeping value; using full value of anomaly\n"); return new; } else { if (bigger) { Verbose("Using previous ave (%.3lf) + 2 std dev (%.3lf); rejecting anomaly\n", average, dev); return average+2.0*dev; } else { Verbose("Using previous ave (%.3lf) - 2 std dev (%.3lf); rejecting anomaly\n", average, dev); return average-2.0*dev; } } } else { Verbose("Keeping value; value is reasonable\n"); return new; } } /*****************************************************************************/ double WAverage(double anew, double aold, double age) /* For a couple of weeks, learn eagerly. Otherwise variances will be way too * large. Then downplay newer data somewhat, and rely on experience of a * couple of months of data ... */ { double av; double wnew, wold; if (age < 2.0) { wnew = 0.7; wold = 0.3; } else { wnew = 0.3; wold = 0.7; } av = (wnew * anew + wold * aold) / (wnew + wold); if (av > big_number) /* some kind of bug? */ { Verbose("New average is too big; cutting it to 10.0\n"); return 10.0; } return av; } /*****************************************************************************/ void LoadHistogram(int dbtype) { FILE *fp; int position, i, day; Verbose("LoadHistogram()\n"); if (HISTO) { char filename[CF_BUFSIZE]; switch(dbtype) { case DAILY: snprintf(filename, CF_BUFSIZE, "%s/daily.hist", LOCATION); break; case YEARLY: snprintf(filename, CF_BUFSIZE, "%s/yearly.hist", LOCATION); break; default: /* weekly */ snprintf(filename, CF_BUFSIZE, "%s/weekly.hist", LOCATION); break; } Verbose("Loading histogram: %s\n", filename); if ((fp = fopen(filename, "r")) == NULL) { fprintf(stderr, "fopen: %s\n", strerror(errno)); fprintf(stderr, "Unable to load histogram data\n"); return; } for (position = 0; position < CF_GRAINS; position++) { fscanf(fp, "%d ", &position); for (day = 0; day < 7; day++) { fscanf(fp, "%d ", &(HISTOGRAM[day][position])); } } Verbose("Done loading histogram.\n"); fclose(fp); } } /*********************************************************************/ int ArmClasses(struct Average av, char *timekey) { double sig; int code; struct Item *classlist = NULL, *ip; int i; char buffer[CF_BUFSIZE]; char temp1[256], temp2[256]; FILE *newfp; FILE *oldfp; struct flock lock; /* printf("Arm classes for %s\n", timekey); */ sig = SetClasses(NAME, VALUE, av.expect, av.var, LOCALAV.expect, LOCALAV.var, &classlist, timekey, &code); SetVariable(NAME,VALUE,av.expect,sig,&classlist); if(cfenvd_compatible) { unlink(ENVCF_NEW); strcpy(temp1, NAME); strcat(temp1, "_"); temp2[0] = '_'; temp2[1] = '\0'; strcat(temp2, NAME); strcat(temp2, "="); for (i=0; i<10; i++) { lock.l_type = F_RDLCK; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; if ((newfp = fopen(ENVCF_NEW,"a")) == NULL) { DeleteItemList(classlist); return code; } if ((oldfp = fopen(ENVCF, "r")) != NULL) { if (fcntl(fileno(oldfp), F_SETLK, &lock) == -1) { Debug("Couldn't get lock, attempt %d of 10\n", i+1); fclose(oldfp); sleep(1); continue; } while(fgets(buffer, CF_BUFSIZE, oldfp) != NULL) { if(strstr(buffer, temp2) == NULL && strncmp(buffer, temp1, strlen(temp1)) != 0) { fprintf(newfp, "%s", buffer); } } fclose(oldfp); } for (ip = classlist; ip != NULL; ip=ip->next) { fprintf(newfp,"%s\n",ip->name); } fclose(newfp); rename(ENVCF_NEW,ENVCF); break; } } DeleteItemList(classlist); return code; } /*********************************************************************/ int SetClasses(char *name, double variable, double av_expect, double av_var, double localav_expect, double localav_var, struct Item **classlist, char *timekey, int *code) { char buffer[CF_BUFSIZE], buffer2[CF_BUFSIZE]; double dev, delta, sigma, ldelta, lsigma, sig; delta = variable - av_expect; sigma = sqrt(av_var); ldelta = variable - localav_expect; lsigma = sqrt(localav_var); sig = sqrt(sigma * sigma + lsigma * lsigma); if (sigma == 0.0 || lsigma == 0.0) { Debugging2(" No sigma variation .. can't measure class\n"); Verbose("Returning -2 (No sigma variation)\n"); *code = -2; return sig; } if (fabs(delta) < cf_noise_threshold) /* Arbitrary limits on sensitivity */ { Debug(" Sensitivity too high ..\n"); buffer[0] = '\0'; strcpy(buffer, name); if ((delta > 0) && (ldelta > 0)) { strcat(buffer, "_high"); *code = -6; } else if ((delta < 0) && (ldelta < 0)) { strcat(buffer, "_low"); *code = -4; } else { strcat(buffer, "_normal"); *code = -5; } dev = sqrt(delta * delta / (1.0 + sigma * sigma) + ldelta * ldelta / (1.0 + lsigma * lsigma)); if (dev > 2.0 * sqrt(2.0)) { strcpy(buffer2, buffer); strcat(buffer2, "_microanomaly"); Debugging2("!! %s !!\n", buffer2); *code += -10; AppendItem(classlist,buffer2,"2"); if(cfenvd_compatible) AddPersistentClass(buffer2,40,cfpreserve); } } else { buffer[0] = '\0'; strcpy(buffer, name); if ((delta > 0) && (ldelta > 0)) { strcat(buffer, "_high"); *code = -6; } else if ((delta < 0) && (ldelta < 0)) { strcat(buffer, "_low"); *code = -4; } else { strcat(buffer, "_normal"); *code = -5; } dev = sqrt(delta * delta / (1.0 + sigma * sigma) + ldelta * ldelta / (1.0 + lsigma * lsigma)); if (dev <= sqrt(2.0)) { strcpy(buffer2, buffer); strcat(buffer2, "_normal"); Debugging2("!! %s !!\n", buffer2); *code += -20; AppendItem(classlist,buffer2,"0"); } else { strcpy(buffer2, buffer); strcat(buffer2, "_dev1"); Debugging2("!! %s !!\n", buffer2); *code += -30; AppendItem(classlist,buffer2,"0"); } if (dev > 2.0*sqrt(2.0)) { strcpy(buffer2, buffer); strcat(buffer2, "_dev2"); Debugging2("!! %s !!\n", buffer2); *code += -10; AppendItem(classlist,buffer2,"2"); if(cfenvd_compatible) AddPersistentClass(buffer2,40,cfpreserve); } if (dev > 3.0*sqrt(2.0)) { strcpy(buffer2, buffer); strcat(buffer2, "_anomaly"); Debugging2("!! %s !!\n", buffer2); *code += -10; AppendItem(classlist,buffer2,"3"); if(cfenvd_compatible) AddPersistentClass(buffer2,40,cfpreserve); } } Verbose("Returning %d", *code); if (*code < -40) { Verbose(" (Anomaly!)"); } Verbose("\n"); return sig; } /*****************************************************************************/ void SetVariable(char *name,double value,double average,double stddev,struct Item **classlist) { char var[CF_BUFSIZE]; sprintf(var,"value_%s=%d",name,(int)value); AppendItem(classlist,var,""); sprintf(var,"average_%s=%1.1f",name,average); AppendItem(classlist,var,""); sprintf(var,"stddev_%s=%1.1f",name,stddev); AppendItem(classlist,var,""); } /*********************************************************************/ void DoBatch(int dbtype) { FILE *fp; char buffer[1024], timekey[256]; char name1[256], name2[256], timebuf[256]; struct tm timevals; double val=0; float val1=0, val2=0, val3=0, val4=0, val5=0, val6=0, val7=0, val8=0, val9=0, val10=0; int i = 0, j = 0, n = 0, y = 0, k = 0, w = 0; int timeint = -1; struct Average av; time_to_update = false; Verbose("Batch mode\n"); LOCALAV.expect = 0.0; LOCALAV.var = 0.0; ITER = 0.0; for (i = 0; i < 7; i++) { for (j = 0; j < CF_GRAINS; j++) { HISTOGRAM[i][j] = 0; } } i = 0; srand((unsigned int)time(NULL)); LoadHistogram(dbtype); GetDatabaseAge(dbtype); if ((fp = fopen(BATCHFILE, "r")) == NULL) { fprintf(stderr, "Cannot open %s\n", BATCHFILE); return; } printf("\n [ ]"); printf("\ryear 01, month 01: ["); k++; bzero(buffer, 1024); fgets(buffer, 1024, fp); while (!feof(fp)) { if (n >= 11) { y++; n = -1; } if (k >= 5 * 24 * 60 * w / STEP) { w++; printf("."); fflush(stdout); } if (k >= 30 * 24 * 60 / STEP) { n++; printf("\r [ ]\ryear %02d, month %02d: [", y+1, n+1); fflush(stdout); k = 0; w = 0; } if (strlen(buffer) == 0) { bzero(buffer, 1024); fgets(buffer, 1024, fp); continue; } if (sscanf(buffer, "%d/%d/%d %d:%d:%d %s %s %lf", &(timevals.tm_mon), &(timevals.tm_mday), &(timevals.tm_year), &(timevals.tm_hour), &(timevals.tm_min), &(timevals.tm_sec), name1, name2, &val) != 9) { if (sscanf(buffer, "%*d %d %*d %lf %f %f %f %f %f %f %f %f %f %f", &timeint, &val, &val1, &val2, &val3, &val4, &val5, &val6, &val7, &val8, &val9, &val10) == 12) { timevals.tm_year = timeint / 10000; timevals.tm_mon = (timeint / 100) % 100; timevals.tm_mday = timeint % 100; timevals.tm_hour = 12; timevals.tm_min = 0; timevals.tm_sec = 0; timeint = -1; } else if(sscanf(buffer, "%d/%d/%d %d:%d:%d %lf", &(timevals.tm_mon), &(timevals.tm_mday), &(timevals.tm_year), &(timevals.tm_hour), &(timevals.tm_min), &(timevals.tm_sec), &val) == 7) { } else if (sscanf(buffer, "%d %lf", &timeint,&val) == 2) { } else { fprintf(stderr, "\nSkipping incomplete line: \"%s\"\n", buffer); bzero(buffer, 1024); fgets(buffer, 1024, fp); continue; } } Debug("%d/%d/%d %d:%d:%d %s %s %f\n", timevals.tm_mon, timevals.tm_mday, timevals.tm_year, timevals.tm_hour, timevals.tm_min, timevals.tm_sec, name1, name2, val); bzero(buffer, 1024); fgets(buffer, 1024, fp); timevals.tm_year = timevals.tm_year - 1900; timevals.tm_mon = timevals.tm_mon - 1; VALUE = (double)val; if (timeint < 0) { update_time = mktime(&timevals); } else { update_time = (time_t) timeint; } strcpy(timebuf, ctime(&update_time)); Debug("- Time converted to %s, ", timebuf); if(strcmp(timekey, ConvTimeKey2(timebuf, dbtype)) != 0) k++; strcpy(timekey, ConvTimeKey2(timebuf, dbtype)); Debug("then to %s\n", timekey); if (feof(fp)) time_to_update = true; av = EvalAvQ(timekey, dbtype, true); ArmClasses(av, timekey); } fclose(fp); printf("\rDone \ndatabase saved to: %s\n", AVDB); printf("Run cfetoolgraph %s [-tTrndwy] [--path %s] to generate graphs\n\n", NAME, PATHNAME); } /*****************************************************************************/ void Syntax() { int i; printf("Syntax:\n\n"); CreateSyntax(); printf("\n"); UpdateSyntax(); printf("\n"); CheckSyntax(); printf("\n"); InfoSyntax(); printf("\n"); DumpSyntax(); printf("\n"); ImportSyntax(); } /*********************************************************************/ void CreateSyntax() { int i; printf("%s create name ", PROG_NAME); for (i = 0; CREATEOPTIONS[i].name != NULL; i++) { printf("(--%s|-%c", CREATEOPTIONS[i].name, (char)CREATEOPTIONS[i].val); if (CREATEOPTIONS[i].has_arg == required_argument) { printf(" ..."); } else if (CREATEOPTIONS[i].has_arg == optional_argument) { printf(" [...]"); } printf(") "); } printf("\n"); } /*********************************************************************/ void UpdateSyntax() { int i; printf("%s update name ", PROG_NAME); for (i = 0; UPDATEOPTIONS[i].name != NULL; i++) { printf("(--%s|-%c", UPDATEOPTIONS[i].name, (char)UPDATEOPTIONS[i].val); if (UPDATEOPTIONS[i].has_arg == required_argument) { printf(" ..."); } else if (UPDATEOPTIONS[i].has_arg == optional_argument) { printf(" [...]"); } printf(") "); } printf("\n"); } /*********************************************************************/ void CheckSyntax() { int i; printf("%s check name ", PROG_NAME); for (i = 0; CHECKOPTIONS[i].name != NULL; i++) { printf("(--%s|-%c", CHECKOPTIONS[i].name, (char)CHECKOPTIONS[i].val); if (CHECKOPTIONS[i].has_arg == required_argument) { printf(" ..."); } else if (CHECKOPTIONS[i].has_arg == optional_argument) { printf(" [...]"); } printf(") "); } printf("\n"); } /*********************************************************************/ void InfoSyntax() { int i; printf("%s info name ", PROG_NAME); for (i = 0; INFOOPTIONS[i].name != NULL; i++) { printf("(--%s|-%c", INFOOPTIONS[i].name, (char)INFOOPTIONS[i].val); if (INFOOPTIONS[i].has_arg == required_argument) { printf(" ..."); } else if (INFOOPTIONS[i].has_arg == optional_argument) { printf(" [...]"); } printf(") "); } printf("\n"); } /*********************************************************************/ void DumpSyntax() { int i; printf("%s dump name ", PROG_NAME); for (i = 0; DUMPOPTIONS[i].name != NULL; i++) { printf("(--%s|-%c", DUMPOPTIONS[i].name, (char)DUMPOPTIONS[i].val); if (DUMPOPTIONS[i].has_arg == required_argument) { printf(" ..."); } else if (DUMPOPTIONS[i].has_arg == optional_argument) { printf(" [...]"); } printf(") "); } printf("\n"); } /*********************************************************************/ void ImportSyntax() { int i; printf("%s import name ", PROG_NAME); for (i = 0; IMPORTOPTIONS[i].name != NULL; i++) { printf("(--%s|-%c", IMPORTOPTIONS[i].name, (char)IMPORTOPTIONS[i].val); if (IMPORTOPTIONS[i].has_arg == required_argument) { printf(" ..."); } else if (IMPORTOPTIONS[i].has_arg == optional_argument) { printf(" [...]"); } printf(") "); } printf("\n"); } /*********************************************************************/ void CloseDatabase() { Verbose("Closing database\n"); dbp->close(dbp, 0); } /*********************************************************************/ int OpenDatabase(int create) { int flags; if(create) { flags = DB_CREATE|DB_EXCL; } else { flags = 0; } if ((errno = db_create(&dbp, NULL, 0)) != 0) { snprintf(OUTPUT, CF_BUFSIZE, "Couldn't create database handle\n"); fprintf(stderr, "db_create: %s\n", strerror(errno)); fprintf(stderr, OUTPUT); return -1; } #ifdef CF_OLD_DB if ((errno = (dbp->open)(dbp, AVDB, NULL, DB_BTREE, flags, 0644)) != 0) #else if ((errno = (dbp->open)(dbp, NULL, AVDB, NULL, DB_BTREE, flags, 0644)) != 0) #endif { snprintf(OUTPUT, CF_BUFSIZE, "Couldn't open average database %s\n", AVDB); fprintf(stderr, "db_open: %s\n", strerror(errno)); fprintf(stderr, OUTPUT); return -1; } Verbose("Opened database\n"); return 0; } /*********************************************************************/ char *GenTimeKey2(time_t now, int dbtype) { char str[64]; sprintf(str, "%s", ctime(&now)); return ConvTimeKey2(str, dbtype); } /*********************************************************************/ char *ConvTimeKey2(char *str, int dbtype) { int i, hr, min, timeinmins; char buf1[10], buf2[10], buf3[10], buf4[10], buf5[10], buf[10], out[10]; char minbuf[10]; char *timekey; timekey = calloc(64, sizeof(char)); sscanf(str, "%s %s %s %s %s", buf1, buf2, buf3, buf4, buf5); timekey[0] = '\0'; /* Day */ switch(dbtype) { case DAILY: break; case YEARLY: sprintf(timekey, "%s%s:", buf2, buf3); break; default: /* weekly */ sprintf(timekey, "%s:", buf1); break; } /* Hours */ sscanf(buf4, "%d:%d", &hr, &min); timeinmins = 60*hr + min; if(STEP == 1) { sprintf(minbuf, "%04d", timeinmins / STEP ); } else if (STEP < 15) { sprintf(minbuf, "%03d", timeinmins / STEP ); } else if (STEP < 145) { sprintf(minbuf, "%02d", timeinmins / STEP ); } else { sprintf(minbuf, "%d", timeinmins / STEP ); } strcat(timekey, minbuf); return timekey; } /*********************************************************************/ void FatalError(char *s) { fprintf(stderr, "%s\n", s); exit(1); } void yyerror(char *s) { /* Dummy */ } void RotateFiles(char *name, int number) { /* Dummy */ } /*********************************************************************/ int RecursiveTidySpecialArea(char *name, struct Tidy *tp, int maxrecurse, struct stat *sb) { return true; } int Repository(char *file, char *repository) { return false; } char *GetMacroValue(char *s, char *sp) { return NULL; } void Banner(char *s) { } void AddMacroValue(char *scope, char *name, char *value) { } cfengine-2.2.10/src/ip.c0000644000175000001440000001533011014777033011637 00000000000000/* Copyright (C) 1995- Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: ip.c */ /* */ /* Created: Sun Feb 17 13:47:19 2002 */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*****************************************************************************/ int RemoteConnect(char *host,char forceipv4,short oldport, char *newport) { int err; #if defined(HAVE_GETADDRINFO) if (forceipv4 == 'n') { struct addrinfo query, *response, *ap; struct addrinfo query2, *response2, *ap2; int err,connected = false; memset(&query,0,sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; if ((err = getaddrinfo(host,newport,&query,&response)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to find hostname or cfengine service: (%s/%s) %s",host,STR_CFENGINEPORT,gai_strerror(err)); CfLog(cfinform,OUTPUT,""); return false; } for (ap = response; ap != NULL; ap = ap->ai_next) { Verbose("Connect to %s = %s on port %s\n",host,sockaddr_ntop(ap->ai_addr),newport); if ((CONN->sd = socket(ap->ai_family,ap->ai_socktype,ap->ai_protocol)) == -1) { CfLog(cfinform,"Couldn't open a socket","socket"); continue; } if (BINDINTERFACE[0] != '\0') { memset(&query2,0,sizeof(struct addrinfo)); query.ai_family = AF_UNSPEC; query.ai_socktype = SOCK_STREAM; if ((err = getaddrinfo(BINDINTERFACE,NULL,&query2,&response2)) != 0) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to lookup hostname or cfengine service: %s",gai_strerror(err)); CfLog(cferror,OUTPUT,""); return false; } for (ap2 = response2; ap2 != NULL; ap2 = ap2->ai_next) { if (bind(CONN->sd, ap2->ai_addr, ap2->ai_addrlen) == 0) { freeaddrinfo(response2); response2 = NULL; break; } } if (response2) { freeaddrinfo(response2); } } signal(SIGALRM,(void *)TimeOut); alarm(CF_TIMEOUT); if (connect(CONN->sd,ap->ai_addr,ap->ai_addrlen) >= 0) { connected = true; alarm(0); signal(SIGALRM,SIG_DFL); break; } alarm(0); signal(SIGALRM,SIG_DFL); } if (connected) { CONN->family = ap->ai_family; snprintf(CONN->remoteip,CF_MAX_IP_LEN-1,"%s",sockaddr_ntop(ap->ai_addr)); } else { close(CONN->sd); snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't connect to host %s\n",host); CONN->sd = CF_NOT_CONNECTED; } if (response != NULL) { freeaddrinfo(response); } if (!connected) { return false; } } else #endif /* ---------------------- only have ipv4 ---------------------------------*/ { struct hostent *hp; struct sockaddr_in cin; memset(&cin,0,sizeof(cin)); if ((hp = gethostbyname(host)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE,"Unable to look up IP address of %s",host); CfLog(cferror,OUTPUT,"gethostbyname"); return false; } cin.sin_port = oldport; cin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr; cin.sin_family = AF_INET; Verbose("Connect to %s = %s, port =%u\n",host,inet_ntoa(cin.sin_addr),SHORT_CFENGINEPORT); if ((CONN->sd = socket(AF_INET,SOCK_STREAM,0)) == -1) { CfLog(cferror,"Couldn't open a socket","socket"); return false; } if (BINDINTERFACE[0] != '\0') { Verbose("Cannot bind interface with this OS.\n"); /* Could fix this - any point? */ } CONN->family = AF_INET; snprintf(CONN->remoteip,CF_MAX_IP_LEN-1,"%s",inet_ntoa(cin.sin_addr)); signal(SIGALRM,(void *)TimeOut); alarm(CF_TIMEOUT); if (err=connect(CONN->sd,(void *)&cin,sizeof(cin)) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't connect to host %s\n",host); CfLog(cfinform,OUTPUT,"connect"); return false; } alarm(0); signal(SIGALRM,SIG_DFL); } LastSeen(host,cf_connect); return true; } /*******************************************************************/ void CfenginePort() { struct servent *server; if ((server = getservbyname(CFENGINE_SERVICE,"tcp")) == NULL) { CfLog(cflogonly,"Couldn't get cfengine service, using default","getservbyname"); SHORT_CFENGINEPORT = htons((unsigned short)5308); } else { SHORT_CFENGINEPORT = server->s_port; } Debug("Setting cfengine new port to %u\n",ntohs(SHORT_CFENGINEPORT)); } /*********************************************************************/ struct cfagent_connection *NewAgentConn() { struct cfagent_connection *ap; if ((ap = (struct cfagent_connection *)malloc(sizeof(struct cfagent_connection))) == NULL) { return NULL; } Debug("New server connection...\n"); ap->sd = CF_NOT_CONNECTED; ap->family = AF_INET; ap->trust = false; ap->localip[0] = '\0'; ap->remoteip[0] = '\0'; ap->session_key = NULL; ap->error = false; return ap; }; /*********************************************************************/ void DeleteAgentConn(struct cfagent_connection *ap) { if (ap->session_key != NULL) { free(ap->session_key); } free(ap); ap = NULL; } cfengine-2.2.10/src/scli.c0000644000175000001440000001371210645412275012166 00000000000000/* Copyright (C) 1995-2000 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /****************************************************************************/ /* */ /* File: scli.c */ /* */ /****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /* This is a special case of shell commands for the SCLI interpreter. */ void SCLIScript() { struct ShellComm *ptr; char line[CF_BUFSIZE],eventname[CF_BUFSIZE],dummy[1]; char execstr[CF_EXPANDSIZE],tmpfile[CF_BUFSIZE]; char chdir_buf[CF_EXPANDSIZE]; char chroot_buf[CF_EXPANDSIZE]; char *defines = dummy,*elsedef = dummy; time_t start,end; int error,i,ifelapsed = -1,expireafter = -1; mode_t maskval = 0; FILE *pp,*fout; int have_chdir = false, have_chroot = false; int uid = -1, gid = -1, timeout = -1; if (VSCLI == NULL) { return; } Banner("SCLI / SNMP script phase"); dummy[0] = '\0'; snprintf(tmpfile,CF_BUFSIZE,"%s/scli_monologue_pipe",CFWORKDIR); unlink(tmpfile); if ((fout = fopen(tmpfile,"w")) == NULL) { CfLog(cferror,"Unable to open scli monologue pipe","fopen"); return; } for (ptr = VSCLI; ptr != NULL; ptr=ptr->next) { if (IsExcluded(ptr->classes)) { continue; } if (ptr->done == 'y') { continue; } ResetOutputRoute(ptr->log,ptr->inform); ExpandVarstring(ptr->name,execstr,NULL); snprintf(OUTPUT,CF_BUFSIZE*2,"\nConstructing scli monologue %s...(timeout=%d,uid=%d,gid=%d)\n",execstr,ptr->timeout,ptr->uid,ptr->gid); CfLog(cfinform,OUTPUT,""); if (ptr->fork == 'y') { Verbose("Cannot background SCLI scripts %s\n",execstr); } if (have_chdir) { CfLog(cferror,"Multiple declaration of chdir option in scli - does not make sense",""); } else { if (strlen(ptr->chdir) != 0) { have_chdir = true; ExpandVarstring(ptr->chdir,chdir_buf,""); } } /* This is fragile to silly coding in the config file - a lot of work to fix this. Not worth it unless this all proves useful */ uid = ptr->uid; gid = ptr->gid; defines = ptr->defines; elsedef = ptr->elsedef; ifelapsed = ptr->ifelapsed; expireafter = ptr->expireafter; if (have_chroot) { CfLog(cferror,"Multiple declaration of chroot option in scli - does not make sense",""); } else { if (strlen(ptr->chroot) != 0) { have_chroot = true; ExpandVarstring(ptr->chdir,chdir_buf,""); } } if (timeout > 0) { if (timeout != ptr->timeout) { CfLog(cferror,"Multiple declaration of timeout option in scli - does not make sense",""); } } else { timeout = ptr->timeout; } ExpandVarstring(ptr->name,execstr,NULL); fprintf(fout,"%s\n",execstr); Verbose("to-scli: %s\n",execstr); } fclose(fout); if (DONTDO) { return; } if (!GetLock(ASUniqueName("scli"),CF_SCLI_COMM,ifelapsed,expireafter,VUQNAME,CFSTARTTIME)) { return; } if (timeout > 0) { signal(SIGALRM,(void *)TimeOut); alarm(timeout); } start = time(NULL); snprintf(VBUFF,CF_BUFSIZE,"%s < %s",CF_SCLI_COMM,tmpfile); pp = cfpopen_shsetuid(VBUFF,"r",uid,gid,chdir_buf,chroot_buf); if (pp == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open pipe to command %s\n",execstr); CfLog(cferror,OUTPUT,"popen"); ResetOutputRoute('d','d'); ReleaseCurrentLock(); return; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); break; } ReadLine(line,CF_BUFSIZE-1,pp); if (strstr(line,"cfengine-die")) { break; } if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",execstr); CfLog(cferror,OUTPUT,"ferror"); break; } for (i = 0; CF_SCLICODES[i][0] != NULL; i++) { if (strncmp(CF_SCLICODES[cfscli_noconnect][0],line,3) == 0 || strncmp(CF_SCLICODES[cfscli_snmp_return][0],line,3) == 0 ) { error = true; snprintf(OUTPUT,CF_BUFSIZE,"Unable to enter snmp dialogue, %s\n",line+strlen(CF_SCLICODES[0][0])+1); CfLog(cfinform,OUTPUT,""); break; } } snprintf(OUTPUT,CF_BUFSIZE,"%s\n",line+strlen(CF_SCLICODES[0][0])+1); CfLog(cfinform,OUTPUT,""); if (error) { break; } } cfpclose_def(pp,defines,elsedef); if (timeout != 0) { alarm(0); signal(SIGALRM,SIG_DFL); } snprintf(OUTPUT,CF_BUFSIZE*2,"End scli script\n"); CfLog(cfinform,OUTPUT,""); end = time(NULL); snprintf(eventname,CF_BUFSIZE-1,"SCLIdialogue(%s)",execstr); RecordPerformance(eventname,start,(double)(end-start)); ResetOutputRoute('d','d'); ReleaseCurrentLock(); unlink(tmpfile); } cfengine-2.2.10/src/errors.c0000644000175000001440000000411210202123551012523 00000000000000/* Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Errors */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" void FatalError(s) char *s; { fprintf (stderr,"%s:%s:%s\n",VPREFIX,VCURRENTFILE,s); SILENT = true; ReleaseCurrentLock(); closelog(); exit(1); } /*********************************************************************/ void Warning(char *s) { if (WARNINGS) { fprintf (stderr,"%s:%s:%d: Warning: %s\n",VPREFIX,VCURRENTFILE,LINENUMBER,s); } } /*********************************************************************/ void ResetLine(char *s) { int c; int v; char *p; v = 0; while (isdigit((int)*s)) { v = 10*v + *s++ - '0'; } LINENUMBER = v-1; c = *s++; while (c == ' ') { c = *s++; } if (c == '"') { p = VCURRENTFILE; c = *s++; while (c && c != '"') { *p++ = c; c = *s++; } *p = '\0'; } } cfengine-2.2.10/src/acl.c0000644000175000001440000015704411045654077012005 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /**************************************************************************/ /* */ /* File: acl.c */ /* Author: Mark / Demosthenes / Patch by Goran Oberg */ /* NT code by Bjoern Gustafson and Joergen Kjensli */ /* */ /**************************************************************************/ #include #include "cf.defs.h" #include "cf.extern.h" #ifdef HAVE_SYS_ACL_H # include #endif #ifdef NT void LogWinError(void); #endif #ifndef HAVE_DCE_DACLIF_H int CheckDFSACE(struct CFACE *aces, char method, char *filename, enum fileactions action) { CfLog(cferror,"DCE operation attempted, without DCE support",""); return false; } #endif /*****************************************************************************/ char *CFFSTYPES[] = { "posix", "solaris", "dfs", "afs", "hpux", "nt", NULL }; /*****************************************************************************/ #if defined SOLARIS && defined HAVE_SYS_ACL_H void aclsortperror(int error) { switch (error) { case GRP_ERROR: CfLog(cferror,"acl: There is more than one group_obj ACL entry.\n",""); break; case USER_ERROR: CfLog(cferror,"acl: There is more than one user_obj ACL entry.\n",""); break; case CLASS_ERROR: CfLog(cferror,"acl: There is more than one class_obj ACL entry.\n", ""); break; case OTHER_ERROR: CfLog(cferror,"acl: There is more than one other_obj ACL entry.\n", ""); break; case DUPLICATE_ERROR: CfLog(cferror,"acl: Duplicate entries of user or group.\n", ""); break; case ENTRY_ERROR: CfLog(cferror,"acl: The entry type is invalid.\n", ""); break; case MISS_ERROR: CfLog(cferror,"acl: Missing group_obj, user_obj, class_obj, or other_obj entries.\n", ""); break; case MEM_ERROR: CfLog(cferror,"acl: The system can't allocate any memory.\n", ""); break; default: snprintf(OUTPUT,CF_BUFSIZE*2,"acl: Unknown ACL error code: %d !\n", error); CfLog(cferror,OUTPUT,""); break; } return; } #endif /*****************************************************************************/ #if 0 /* XXX alb - moved to dce_acl.c */ #ifdef HAVE_DCE sec_acl_entry_type_t BuildDceAclEntry_Type(char *t, char *n) { if (strcmp(t, "user") == 0) { if (*n == 0) { return sec_acl_e_type_user_obj; } else { return sec_acl_e_type_user; } } else if (strcmp(t, "group") == 0) { if (*n == 0) { return sec_acl_e_type_group_obj; } else { return sec_acl_e_type_group; } } else if (strcmp(t, "other") == 0) { return sec_acl_e_type_other_obj; } else if (strcmp(t, "mask") == 0) { return sec_acl_e_type_mask_obj; } else if (strcmp(t, "any") == 0) { return sec_acl_e_type_any_other; } else if (strcmp(t, "unauthenticated") == 0) { return sec_acl_e_type_unauthenticated; } else if (strcmp(t, "foreign_other") == 0) { return sec_acl_e_type_foreign_other; } else if (strcmp(t, "foreign_user") == 0) { return sec_acl_e_type_foreign_user; } else if (strcmp(t, "foreign_group") == 0) { return sec_acl_e_type_foreign_group; } return 0; } /*****************************************************************************/ sec_acl_permset_t BuildDceAclEntry_Perms(char *mode, sec_acl_permset_t oldmode) { sec_acl_permset_t perm = 0; char *a; enum {add, del} o; perm = oldmode; if (strcmp(mode, "noaccess") == 0) { return 0; /* No access for this user/group */ } o = add; for (a = mode; *a != '\0' ; *a++) { if (*a == '+' || *a == ',') { o = add; } else if (*a == '-') { o = del; } else if (*a == '=') { o = add; perm = 0; } else { switch (*a) { case 'r': if (o == add) { perm |= sec_acl_perm_read; } else { perm &= ~sec_acl_perm_read; } break; case 'w': if (o == add) { perm |= sec_acl_perm_write; } else { perm &= ~sec_acl_perm_write; } break; case 'x': if (o == add) { perm |= sec_acl_perm_execute; } else { perm &= ~sec_acl_perm_execute; } break; case 'c': if (o == add) { perm |= sec_acl_perm_control; } else { perm &= ~sec_acl_perm_control; } break; case 'i': if (o == add) { perm |= sec_acl_perm_insert; } else { perm &= ~sec_acl_perm_insert; } break; case 'd': if (o == add) { perm |= sec_acl_perm_delete; } else { perm &= ~sec_acl_perm_delete; } break; default: snprintf(OUTPUT,2*CF_BUFSIZE,"Invalid mode string in DCE/DFS acl: %s\n", mode); CfLog(cferror,OUTPUT,""); } } } return perm; } /*****************************************************************************/ uuid_t BuildDceAclEntry_Id(sec_rgy_handle_t rgy_site, sec_rgy_name_t name, sec_acl_entry_type_t type) { uuid_t id; error_status_t status; memset(id,0,sizeof(id)); switch (type) { case sec_acl_e_type_group: sec_id_parse_group(rgy_site, name, NULL, NULL, NULL, &id, &status); if (status != error_status_ok) { snprintf(OUTPUT,CF_BUFSIZE*2,"sec_rgy_parse_group: %ld\n", status); CfLog(cferror,OUTPUT,""); } break; case sec_acl_e_type_user: sec_id_parse_name(rgy_site, name, NULL, NULL, NULL, &id, &status); if (status != error_status_ok) { snprintf(OUTPUT,CF_BUFSIZE*2,"sec_rgy_parse_name: %ld\n", status); CfLog(cferror,OUTPUT,""); } break; case sec_acl_e_type_foreign_group: CfLog(cferror,"acl type c_acl_e_type_foreign_group not supported yet\n",""); break; case sec_acl_e_type_foreign_user: CfLog(cferror,"acl type sec_acl_e_type_foreign_user not supported yet.\n",""); break; case sec_acl_e_type_foreign_other: CfLog(cferror,"acl type sec_acl_e_type_foreign_other not supported yet.\n",""); break; default: CfLog(cferror,"Unknown acl type in BuildDceAclEntry_Id!\n",""); break; } return id; } #endif #endif /* XXX alb */ /*****************************************************************************/ #if defined SOLARIS && defined HAVE_SYS_ACL_H int ParseSolarisMode(char* mode, mode_t oldmode) { char *a; mode_t perm; enum {add, del} o; perm = oldmode; if (strcmp(mode, "noaccess") == 0) { return 0; /* No access for this user/group */ } o = add; for (a = mode; *a != '\0' ; *a++) { if (*a == '+' || *a == ',') { o = add; } else if (*a == '-') { o = del; } else if (*a == '=') { o = add; perm = 0; } else { switch (*a) { case 'r': if (o == add) { perm |= 04; } else { perm &= ~04; } break; case 'w': if (o == add) { perm |= 02; } else { perm &= ~02; } break; case 'x': if (o == add) { perm |= 01; } else { perm &= ~01; } break; default: snprintf(OUTPUT,CF_BUFSIZE*2,"Invalid mode string in solaris acl: %s\n", mode); CfLog(cferror,OUTPUT,""); } } } return perm; } /*****************************************************************************/ int BuildAclEntry(struct stat *sb, char *acltype, char *name, struct acl *newaclbufp) { struct passwd *pw; struct group *gr; if (strcmp(acltype, "user") == 0) { if (*name == 0) { newaclbufp->a_type = USER_OBJ; newaclbufp->a_id = sb->st_uid; } else { newaclbufp->a_type = USER; if ((pw = getpwnam(name)) != NULL) { newaclbufp->a_id = pw->pw_uid; } else { snprintf(OUTPUT,CF_BUFSIZE*2,"acl: no such user: %s\n",name); CfLog(cferror,OUTPUT,""); return -1; } } } else if (strcmp(acltype, "group") == 0) { if (*name == 0) { newaclbufp->a_type = GROUP_OBJ; newaclbufp->a_id = sb->st_gid; } else { newaclbufp->a_type = GROUP; if ((gr = getgrnam(name)) != NULL) { newaclbufp->a_id = gr->gr_gid; } else { snprintf(OUTPUT,CF_BUFSIZE*2,"acl: no such group: %s\n",name); CfLog(cferror,OUTPUT,""); return -1; } } } else if (strcmp(acltype, "mask") == 0) { newaclbufp->a_type = CLASS_OBJ; newaclbufp->a_id = 0; } else if (strcmp(acltype, "other") == 0) { newaclbufp->a_type = OTHER_OBJ; newaclbufp->a_id = 0; } else if (strcmp(acltype, "default_user") == 0) { if (*name == 0) { newaclbufp->a_type = DEF_USER_OBJ; newaclbufp->a_id = 0; } else { newaclbufp->a_type = DEF_USER; if ((pw = getpwnam(name)) != NULL) { newaclbufp->a_id = pw->pw_uid; } else { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: no such user: %s\n", VPREFIX, name); CfLog(cferror,OUTPUT,""); return -1; } } } else if (strcmp(acltype, "default_group") == 0) { if (*name == 0) { newaclbufp->a_type = DEF_GROUP_OBJ; newaclbufp->a_id = 0; } else { newaclbufp->a_type = DEF_GROUP; if ((gr = getgrnam(name)) != NULL) { newaclbufp->a_id = gr->gr_gid; } else { snprintf(OUTPUT,CF_BUFSIZE*2,"acl: no such group: %s\n",name); CfLog(cferror,OUTPUT,""); return -1; } } } else if (strcmp(acltype, "default_mask") == 0) { newaclbufp->a_type = DEF_CLASS_OBJ; newaclbufp->a_id = 0; } else if (strcmp(acltype, "default_other") == 0) { newaclbufp->a_type = DEF_OTHER_OBJ; newaclbufp->a_id = 0; } newaclbufp->a_perm = 0; return 0; } #endif /*****************************************************************************/ void InstallACL(char *alias,char *classes) { struct CFACL *ptr; char ebuff[CF_EXPANDSIZE]; Debug1("InstallACL(%s,%s)\n",alias,classes); if (! IsInstallable(classes)) { Debug1("Not installing ACL no match\n"); return; } ExpandVarstring(alias,ebuff,""); if ((ptr = (struct CFACL *)malloc(sizeof(struct CFACL))) == NULL) { FatalError("Memory Allocation failed for InstallACL() #1"); } if ((ptr->acl_alias = strdup(ebuff)) == NULL) { FatalError("Memory Allocation failed for InstallEditFile() #2"); } if (VACLLISTTOP == NULL) /* First element in the list */ { VACLLIST = ptr; } else { VACLLISTTOP->next = ptr; } ptr->aces = NULL; ptr->next = NULL; ptr->method = 'o'; ptr->type = StringToFstype("none"); VACLLISTTOP = ptr; } /****** Code added for NT by Jørgen Kjensli & Bjørn Gustafson, May 1999 *****/ #ifdef NT #include DWORD getNTModeMask (char *new_mode, DWORD old_mode); DWORD getNTACEs_Size (struct CFACE *); SECURITY_DESCRIPTOR* getNTACLInformation (char *filename, PACL *old_pacl, BOOL *haveACL, ACL_SIZE_INFORMATION *oldACLSize); void attachToNTACEs (struct CFACE *new_aces, char *user, char *mode, char *access, char *classes, DWORD NTMask); void appendNTACEs (struct CFACE *aces, struct CFACE *new_aces, ACL_SIZE_INFORMATION oldACLSize, PACL old_pacl); void AddNTACEs (char *accessType, struct CFACE *new_aces, PACL *new_pacl); void createNTACL (struct CFACE *aces, char method, char *filename, enum fileactions action); #endif int CheckNTACE (struct CFACE *aces, char method, char *filename, enum fileactions action); #ifdef NT DWORD getNTModeMask(new_mode, old_mode) char *new_mode; /* The desired mode */ DWORD old_mode; /* The old access mask */ { /* Declare and initialize variables */ char *a; /* Character to iterate the mode with */ enum {add, del} o; /* Flag saying whether to add or remove rights */ DWORD accessMask; /* Variable to hold the final mask */ o = add; /* Start function with raised flag */ accessMask = old_mode; /* Initilaize the mask to the original/old mask */ /* modetype: noaccess, default, all, change, read, rwxdop */ /* No access. Should never get here (noaccess => all and denied ACE). If it does get here, return the old mask (nothing is done) */ if (strcmp(new_mode, "noaccess") == 0) { Debug2("Setting ACE-mode to old_mode: %x\n",old_mode); return (old_mode); } /* Default - remove ACE. Set mask to 0 */ if (strcmp(new_mode, "default") == 0) { Verbose("Mode was default.\n"); Debug2("Setting ACE-mode to 0\n"); return (0); } /* All. Return the NT's predefined bit mask for all rights */ if (strcmp(new_mode, "all") == 0) { Debug2("Setting ACE-mode to GENERIC_ALL: %d\n",GENERIC_ALL); return (GENERIC_ALL); } /* Change. Return the "rwxd" rights ORed with the existing mask */ if (strcmp(new_mode, "change") == 0) { Debug2("Setting ACE-mode to CHANGE: %d\n",(old_mode | GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE)); return (old_mode | GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE); } /* Read. Return the "rx" rights ORed with the existing mask */ if (strcmp(new_mode, "read") == 0) { Debug2("Setting ACE-mode to READ: %d\n",(old_mode | GENERIC_READ | GENERIC_EXECUTE)); return (old_mode | GENERIC_READ | GENERIC_EXECUTE); } /* If the code gets here we must treat the string character by character We cannot remove rights if NT's predefined bit mask for all rights is used. Translate this mask to a mask containing all rights (rwxdop) */ if (accessMask == GENERIC_ALL) { accessMask = (0x120089 | 0x120116 | 0x1200A0 | DELETE | WRITE_OWNER | WRITE_DAC); } /* Iterate string with desired mode. Check each character */ for (a = new_mode; *a != '\0' ; *a++) { /* Decide wheteher to add or subtract permission bits */ if (*a == '+' || *a == ',') { o = add; } /* If equal sign, throw away old mask. Get ready to add permissions */ else if (*a == '=') { o = add; accessMask = 0; } else if (*a == '-') { /* Prevent subtracting rights from user with no rights */ if (accessMask == 0) { /* Return the old, original mask. Nothing is changed */ return old_mode; } o = del; } /* Character was a 'permission' character. Check which permission and manipulate the mask */ else { /* Check permission bits and set accessMask */ switch (*a) { case 'r': if (o == add) { /* Adding read rights */ Debug2("Setting ACE-mode to READ.\n"); accessMask |= 0x120089; } else { /* Removing read rights */ Debug2("Removing READ from ACE-mode\n"); /* Execute allready set in mask. Remove relevant read-bits. */ if ((accessMask & 0x1200A0) == 0x1200A0) { accessMask &= 0xFFFFF6; } /* Write is allready set in mask. Remove relevant read-bits. */ else if ((accessMask & 0x120116) == 0x120116) { accessMask &= 0xFFFF76; } /* Neither write nor execute is set. Remove relevant read-bits. */ else { accessMask &= 0xEDFF76; } } break; case 'w': if (o == add) { /* Adding write rights */ Debug2("Setting ACE-mode to WRITE.\n"); accessMask |= 0x120116; } else { /* Removing write rights */ Debug2("Removing WRITE from ACE-mode\n"); Verbose("Old mask: %x\n",accessMask); /* Execute or read is already set in mask. Remove relevant write-bits. */ if (((accessMask & 0x120089) == 0x120089) || ((accessMask & 0x1200A0) == 0x1200A0)) { accessMask &= 0xFFFEE9; } /* Neither read nor execute is set. Remove relevant write-bits. */ else { accessMask &= 0xEDFEE9; } } break; case 'x': if (o == add) { /* Adding execute rights */ Debug2("Setting ACE-mode to EXECUTE.\n"); accessMask |= 0x1200A0; } else { /* Removing execute rights */ Debug2("Removing EXECUTE from ACE-mode\n"); /* Read allready set in mask. Remove relevant execute-bits. */ if ((accessMask & 0x120089) == 0x120089) { accessMask &= 0xFFFFDF; } /* Write is allready set in mask. Remove relevant execute-bits. */ else if ((accessMask & 0x120116) == 0x120116) { accessMask &= 0xFFFF5F; } /* Neither write nor read is set. Remove relevant execute-bits. */ else { accessMask &= 0xEDFF5F; } } break; case 'd': if (o == add) { /* Adding delete rights */ Debug2("Setting ACE-mode to DELETE: %d\n",DELETE); accessMask |= DELETE; } else { /* Removing delete rights */ Debug2("Setting ACE-mode to ~DELETE: %d\n",~DELETE); accessMask &= ~DELETE; } break; case 'o': if (o == add) { /* Adding owner rights */ Debug2("Setting ACE-mode to WRITE_OWNER: %d\n",WRITE_OWNER); accessMask |= WRITE_OWNER; } else { /* Removing owner rights */ Debug2("Setting ACE-mode to ~WRITE_OWNER: %d\n",~WRITE_OWNER); accessMask &= ~WRITE_OWNER; } break; case 'p': if (o == add) { /* Adding "change permission" rights */ Debug2("Setting ACE-mode to WRITE_DAC: %d\n",WRITE_DAC); accessMask |= WRITE_DAC; } else { /* Removing "change permission" rights */ Debug2("Setting ACE-mode to ~WRITE_DAC: %d\n",~WRITE_DAC); accessMask &= ~WRITE_DAC; } break; default: /* The character was not a valid permission */ snprintf(OUTPUT,CF_BUFSIZE*2,"Invalid mode string in NT acl: %s. No changes made.\n", new_mode); CfLog(cferror,OUTPUT,""); return old_mode; } } } /* Make sure the standard "ALL" is returned instead of RWXDOP. This is done so that "All" is showed in NT's GUI */ if (accessMask == (0x120089 | 0x120116 | 0x1200A0 | DELETE | WRITE_OWNER | WRITE_DAC)) { return (GENERIC_ALL); } /* Return the new mask */ return (accessMask); } #endif /*************************** END NT Addition *******************************/ void AddACE(char *acl,char *string,char *classes) { struct CFACL *ptr; struct CFACE *new, *top; char varbuff[CF_EXPANDSIZE], *cp, ebuff[CF_EXPANDSIZE]; char comm[CF_MAXVARSIZE],data1[CF_MAXVARSIZE],data2[CF_MAXVARSIZE]; /****** Code added for NT by Jørgen Kjensli & Bjørn Gustafson, May 1999 *****/ char data3[CF_MAXVARSIZE]; /* To hold the extra variable accesstype */ /*************************** END NT Addition *******************************/ int i; Debug1("AddACE(%s,%s,[%s])\n",acl,string,classes); if ( ! IsInstallable(CLASSBUFF)) { Debug1("Not installing ACE no match\n"); return; } for (ptr = VACLLIST; ptr != NULL; ptr=ptr->next) { varbuff[0] = '\0'; ExpandVarstring(acl,varbuff,""); if (strcmp(ptr->acl_alias,varbuff) == 0) { comm[0] = data1[0] = data2[0] = '\0'; /****** Code added for NT by Jørgen Kjensli & Bjørn Gustafson, May 1999 *****/ data3[0] = '\0'; /* Initialize variable */ /*************************** END NT Addition *******************************/ if ((new = (struct CFACE *)calloc(1,sizeof(struct CFACE))) == NULL) { FatalError("Memory Allocation failed for AddEditAction() #1"); } if (ptr->aces == NULL) { ptr->aces = new; } else { for (top = ptr->aces; top->next != NULL; top=top->next) { } top->next = new; new->next = NULL; } if (string == NULL) { new->name = NULL; new->next = NULL; } else { memset(ebuff,0,sizeof(ebuff)); ebuff[0]='\0'; /* Expand any variables */ ExpandVarstring(string,ebuff,""); cp = ebuff; i = 0; while (*cp != ':' && *cp != '\0') { comm[i++] = *cp++; } comm[i] = 0; *cp++; i = 0; while (*cp != ':' && *cp != '\0') { data1[i++] = *cp++; } data1[i] = 0; *cp++; i = 0; while (*cp != ':' && *cp != '\0') { data2[i++] = *cp++; } data2[i] = 0; /****** Code added for NT by Jørgen Kjensli & Bjørn Gustafson, May 1999 *****/ /* Parse the string to get the access type */ #ifdef NT *cp++; i = 0; while (*cp != ':' && *cp != '\0') { data3[i++] = *cp++; } data3[i] = 0; #endif /*************************** END NT Addition *******************************/ if (strncmp("fstype",comm,strlen(comm)) == 0) { ptr->type = StringToFstype(data1); new->next = NULL; return; } if (strncmp("method",comm,strlen(comm)) == 0) { ptr->method = ToLower(*data1); new->next = NULL; return; } if ((new->acltype = strdup(comm)) == NULL) { FatalError("Memory Allocation failed for AddACE() #1"); } if ((new->name = strdup(data1)) == NULL) { FatalError("Memory Allocation failed for AddACE() #2"); } /****** Code added for NT by Jørgen Kjensli & Bjørn Gustafson, May 1999 *****/ #ifdef NT /* Give all users defined in config file a default mask of 0 */ new->NTMode = 0; /* If "noaccess" is the specified permission, store the permission "all" on an access denied ACE to get the wanted effect of "No Access" showed in NT's GUI */ if (strcmp(data2,"noaccess") == 0) { if ((new->mode = strdup("all")) == NULL) { FatalError("Memory Allocation failed for AddACE() #2"); } if ((new->access = strdup("denied")) == NULL) { FatalError("Memory Allocation failed for AddACE() #3"); } } /* Unless "noaccess" is specified, store the specified values as usual */ else { if ((new->mode = strdup(data2)) == NULL) { FatalError("Memory Allocation failed for AddACE() #2"); } if ((new->access = strdup(data3)) == NULL) { FatalError("Memory Allocation failed for AddACE() #3"); } } #else /*************************** END NT Addition *******************************/ if ((new->mode = strdup(data2)) == NULL) { FatalError("Memory Allocation failed for AddACE() #2"); } #endif } if ((new->classes = strdup(classes)) == NULL) { FatalError("Memory Allocation failed for InstallEditFile() #3"); } return; } } printf("cfengine: software error - no ACL matched installing %s \n",acl); } /*****************************************************************************/ int CheckACLs(char *filename,enum fileactions action,struct Item *acl_aliases) { struct Item *ip; struct CFACL *ap; int status = false; Debug1("CheckACLs(%s)\n",filename); for (ip = acl_aliases; ip != NULL; ip = ip->next) { if ((ap = GetACL(ip->name)) != NULL) { Verbose(" ACL method (overwrite/append) = %c on %s\n",ap->method,filename); switch(ap->type) { case solarisfs: case posixfs: status = CheckPosixACE(ap->aces,ap->method,filename,action); break; case dfsfs: status = CheckDFSACE(ap->aces,ap->method,filename,action); break; /****** Code added for NT by Jørgen Kjensli & Bjørn Gustafson, May 1999 *****/ case ntfs: /* The nt filesystem is defined. Call our function to implement the ACLs on NT. */ status = CheckNTACE(ap->aces,ap->method,filename,action); break; /*************************** END NT Addition *******************************/ default: /* XXX alb - fix, was missing OUTPUT initial parameter */ snprintf(OUTPUT,CF_BUFSIZE*2, "Unknown filesystem type in ACL %s\n",ip->name); CfLog(cferror,OUTPUT,""); } } else { Verbose("ACL %s does not exist (file=%s)\n",ip->name,filename); } } return status; } /*****************************************************************************/ /* Level 2 */ /*****************************************************************************/ enum cffstype StringToFstype(char *string) { int i; for (i = 0; CFFSTYPES[i] != NULL; i++) { if (strcmp(string,CFFSTYPES[i]) == 0) { return (enum cffstype) i; } } return (enum cffstype) i; } /*****************************************************************************/ struct CFACL *GetACL(char *acl_alias) { struct CFACL *ap; for (ap = VACLLIST; ap != NULL; ap = ap->next) { if (strcmp(acl_alias,ap->acl_alias) == 0) { return ap; } } return NULL; } /****** Code added for NT by Jørgen Kjensli & Bjørn Gustafson, May 1999 *****/ #ifdef NT DWORD getNTACEs_Size(aces) struct CFACE *aces; /* List of CFACEs */ { /* Declarations */ struct CFACE *ep; /* Pointer to a CFACE struct. To iterate through the existing list (received as parameter) */ DWORD sidSize = 256; /* The maximum size of the users SID */ DWORD domainSize = 256; /* The maximum size of the name of the domain */ char domain[256]; /* Allocate max memory for the domain name */ PSID psid; /* A pointer to a security identifier (SID) */ SID_NAME_USE snu; /* Enumerated type indicating type of account */ DWORD totalACESize = 0; /* Total accumulated size of all ACEs in list */ DWORD accessSize = 0; /* Variable to hold the size of the ACE */ DWORD psidSize = 0; /* Variable to hold the size of the SID */ /* Iterate through every CFACE in the list sent to the function */ for (ep = aces; ep != NULL; ep=ep->next) { /* Do not count ACE if name is null or if class is excluded or if mode is "default"*/ if ((ep->name == NULL) || (IsExcluded(ep->classes)) || (strcmp(ep->mode,"default") == 0)) { continue; } /* Finding size of SID */ sidSize = 0; domainSize = 256; LookupAccountName(NULL, ep->name, NULL, &sidSize, domain, &domainSize, &snu); /* If SID doesn't exist, continue loop */ if (!sidSize) { continue; } /* Reset accessSize and get the size of the ACE */ accessSize = 0; if ((strcmp(ep->access,"allowed") == 0) || (ep->access == '\0')) { accessSize = sizeof(ACCESS_ALLOWED_ACE); } else if (strcmp(ep->access,"denied") == 0) { accessSize = sizeof(ACCESS_DENIED_ACE); } /* Finally add up the size of the sid, the accesstype, and subtract a DWORD. We subtract a DWORD because the ACE size by default contains one DWORD while we know the exact size of it (sidBufferSize) */ totalACESize += (sidSize + accessSize - sizeof(DWORD)); } /* Return the total size of all ACEs */ return totalACESize; } #endif /*****************************************************************************/ #ifdef NT SECURITY_DESCRIPTOR* getNTACLInformation(filename, old_pacl, haveACL, oldACLSize) char *filename; /* The name of the file */ PACL *old_pacl; /* Pointer to an ACL */ BOOL *haveACL; /* Flag to say wheteher ACL exists or not */ ACL_SIZE_INFORMATION *oldACLSize; /*Pointer to a struct with info about ACL*/ { DWORD sizeRqd; /* Size needed to hold the file's SD */ DWORD old_sdSize; /* Size needed to hold the SD */ SECURITY_DESCRIPTOR *old_sd; /* Pointer to a SD */ BOOL byDef; /* Flag needed for a function call */ /* Find the size of the old security descriptor */ sizeRqd = 0; GetFileSecurity(filename, DACL_SECURITY_INFORMATION, NULL, 0, &sizeRqd); if (sizeRqd == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to get size of old SD\n", VPREFIX); CfLog(cferror,OUTPUT,""); return NULL; } /* Allocate memory for the old security descriptor */ if ((old_sd = (SECURITY_DESCRIPTOR *) malloc(sizeRqd)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to allocate memory for the old SD\n", VPREFIX); CfLog(cferror,OUTPUT,""); return NULL; } /* Retrieve the old security descriptor */ old_sdSize = sizeRqd; if (!GetFileSecurity(filename, DACL_SECURITY_INFORMATION, old_sd, old_sdSize, &sizeRqd)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to get the old SD\n", VPREFIX); CfLog(cferror,OUTPUT,""); return NULL; } /* Retrieve information about the old security descriptor */ if (!GetSecurityDescriptorDacl(old_sd, haveACL, old_pacl, &byDef)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to get information about the old SD\n", VPREFIX); CfLog(cferror,OUTPUT,""); return NULL; } /* File did have an ACL */ if (*haveACL) { /* Retrieve size information about the old ACL and add it to the size of the new */ if (!GetAclInformation(*old_pacl, oldACLSize, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to get information about the old ACL\n", VPREFIX); CfLog(cferror,OUTPUT,""); return NULL; } } else { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: The old security descriptor does not contain an ACL\n", VPREFIX); CfLog(cferror,OUTPUT,""); return NULL; } return old_sd; } #endif /*****************************************************************************/ #ifdef NT void attachToNTACEs(struct CFACE *new_aces,char *user,char *mode, char *access, char *classes, DWORD NTMask) /* struct CFACE *new_aces; Pointer to an empty list of CFACEs char *user; Name of user char *mode; User's mode char *access; User's type of access char *classes; Class DWORD NTMask; User's accessmask */ { /* Declaration of variables */ struct CFACE *newACE; /* Pointer to a CFACE to hold new information */ struct CFACE *ep; /* Pointer to a CFACE. To iterate through list */ /* Check if mode was default i.e. NTMask = 0 */ if (NTMask == 0) { return; } /* Allocate memory for new ACE */ if ((newACE = (struct CFACE *)malloc(sizeof(struct CFACE))) == NULL) { FatalError("Memory Allocation failed for AddEditAction() #1"); } /* Hook the new ACE to the end list */ if (new_aces == NULL) { new_aces = newACE; } else { for (ep = new_aces; ep->next != NULL; ep=ep->next) { } ep->next = newACE; } newACE->next = NULL; /* Set the values of the new ACE */ if ((newACE->name = strdup(user)) == NULL) { FatalError("Memory Allocation failed for name-member."); } if ((newACE->mode = strdup(mode)) == NULL) { FatalError("Memory Allocation failed for mode-member."); } if ((newACE->access = strdup(access)) == NULL) { FatalError("Memory Allocation failed for access-member."); } if ((newACE->classes = strdup(classes)) == NULL) { FatalError("Memory Allocation failed for classes-member."); } newACE->NTMode = NTMask; } #endif /*****************************************************************************/ #ifdef NT void appendNTACEs(struct CFACE *aces,struct CFACE * new_aces,ACL_SIZE_INFORMATION oldACLSize,PACL old_pacl) /* struct CFACE *aces; List of CFACEs struct CFACE *new_aces; List of CFACEs ACL_SIZE_INFORMATION oldACLSize; Will hold info about the file's ACL PACL old_pacl; Pointer to an ACL */ { int x; /* Counter */ struct CFACE *ep; /* Pointer to CFACE. For iteration purposes */ ACCESS_ALLOWED_ACE *aceType;/* A Pointer to an ACE */ SID_NAME_USE sidType; /* Indicating type of account*/ char user[256]; /* Buffer to hold username */ char domain[256]; /* Buffer to hold domain name */ DWORD uLength = 256; /* Maximum length of username */ DWORD dLength = 256; /* Maximum length of domain name */ DWORD NTMode = 0; Verbose("Existing users: %d\n",oldACLSize.AceCount); /* Iterate through all existing ACEs */ for (x = 0; x < oldACLSize.AceCount; x++) { /* Get ace information */ if (GetAce(old_pacl, x, (LPVOID *) &aceType)) { /* Reset maximum lengths and check that the user exists */ uLength = dLength = 256; if (!LookupAccountSid(NULL, (PSID)(&aceType->SidStart), user, &uLength, domain, &dLength, &sidType)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to get allowed ACE's username\n", VPREFIX); CfLog(cferror,OUTPUT,""); continue; } /* Remember the existing ACEs mask */ NTMode = aceType->Mask; /* If user allready exists in our old CFACE list, give him a new mask */ for (ep = aces; ep != NULL; ep=ep->next) { /* Skip ACE if name is null or if class is excluded or if mode is "default"*/ if ((ep->name == NULL) || (IsExcluded(ep->classes))) { continue; } /* If user is listed in config file with access allowed, and existing ACE-type is also allowed, or user is listed in config file with access denied, and existing ACE-type is also denied, then find new updated and proper NTModeMask for that user*/ if (strcmp(ep->name,user) == 0) { if (((strcmp(ep->access,"allowed") == 0) && ((aceType->Header.AceType) == ACCESS_ALLOWED_ACE_TYPE)) || ((strcmp(ep->access,"denied") == 0) && ((aceType->Header.AceType) == ACCESS_DENIED_ACE_TYPE))) { /* Get new mask (combination of old mask and new mode) */ ep->NTMode = NTMode = getNTModeMask(ep->mode,aceType->Mask); break; } } } /* User didn't exist in config file. NTMode has the ACEs mask then. Attach the user to our new list */ if ((aceType->Header.AceType) == ACCESS_ALLOWED_ACE_TYPE) { Debug1("Attaching allowed ace for %s with mask: %x\n",user,NTMode); attachToNTACEs(new_aces, user, "", "allowed", "any", NTMode); } else if ((aceType->Header.AceType) == ACCESS_DENIED_ACE_TYPE) { Debug1("Attaching denied ace for %s with mask: %x\n",user,NTMode); attachToNTACEs(new_aces, user, "", "denied", "any", NTMode); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Existing ACE lost due to it's unfamiliar ACE type(#%x) (allowed=0, denied=1)\n", VPREFIX,(aceType->Header.AceType)); CfLog(cferror,OUTPUT,""); } } /* Unable to get old ACE */ else { printf("Unable to get ACE.\n"); continue; } } } #endif /*****************************************************************************/ #ifdef NT void AddNTACEs(char *accessType,struct CFACE *new_aces,PACL *new_pacl) /* char *accessType; type of ACEs to add (allowed/denied) struct CFACE *new_aces; List of ACEs to check for the accesstype PACL *new_pacl; Pointer to the ACL that shoul be altered */ { /* Declarations of variables */ struct CFACE *ep; /* To iterate through list of CFACEs */ PSID psid; /* Pointer to a SID */ DWORD sidSize; /* To hold size of SID */ char domain[256]; /* Buffer to hold domain name */ DWORD domainSize=256;/*Maximum size of domain */ SID_NAME_USE snu; /* Indicating type of account*/ int counter = -1; /* Counter for verbose reasons */ Verbose("---------------------- ACE info-------------------------------\n"); /* Iterate through list of CFACEs */ for (ep = new_aces; ep != NULL; ep=ep->next) { counter++; /* Do not create ACE if name is null or if class is excluded or if mode is "default"*/ if ((ep->name == NULL) || (IsExcluded(ep->classes)) || (ep->NTMode == 0) || (strcmp(ep->mode,"default") == 0)) { continue; } /* Finding size of SID */ sidSize = 0; domainSize = 256; LookupAccountName(NULL, ep->name, NULL, &sidSize, domain, &domainSize, &snu); /* If SID doesn't exist, continue loop */ if (!sidSize) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: User %s doesn't exist. ACE not created.\n", VPREFIX, ep->name); CfLog(cferror,OUTPUT,""); continue; } /* Allocate memory for list with new ACEs */ if ((psid = (PSID)malloc(sidSize)) == NULL) { FatalError("Memory Allocation failed for SID\n"); } /* Reset buffersize, get the SID and create ACE if user or group exists */ domainSize = 256; if (!LookupAccountName(NULL, ep->name, psid, &sidSize, domain, &domainSize, &snu)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: User doesn't exist. Will not create ACE for: %s\n", VPREFIX, ep->name); CfLog(cferror,OUTPUT,""); free(psid); continue; } /* Check accesstype and add either an Access Denied or Allowed ACE. */ if ((strcmp(accessType,"denied") == 0) && (strcmp(ep->access,"denied") == 0)) { if (!AddAccessDeniedAce(*new_pacl, ACL_REVISION, ep->NTMode, psid)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to add new denied ACE for user %s\n", VPREFIX, ep->name); CfLog(cferror,OUTPUT,""); free(psid); return; } Debug2("- Ace #%d info:\n",counter); Debug2(" mode (permission flags) is %x\n",ep->NTMode); Debug2(" name (id name) is %s\n",ep->name); Debug2(" access type (allow/deny) is %s\n",ep->access); Debug2(" classes is %s\n",ep->classes); Debug2(" ----------------------------------\n"); Debug2("Adding access denied for user: %s\n\n",ep->name); } else if ((strcmp(accessType,"allowed") == 0) && ((strcmp(ep->access,"allowed") == 0) || (ep->access == '\0'))) { if (!AddAccessAllowedAce(*new_pacl, ACL_REVISION, ep->NTMode, psid)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to add new allowed ACE for user %s\n", VPREFIX, ep->name); CfLog(cferror,OUTPUT,""); free(psid); return; } Debug2("- Ace #%d info:\n",counter); Debug2(" mode (permission flags) is %x\n",ep->NTMode); Debug2(" name (id name) is %s\n",ep->name); Debug2(" access type (allow/deny) is %s\n",ep->access); Debug2(" classes is %s\n",ep->classes); Debug2(" ----------------------------------\n"); Debug2("Adding access allowed for user: %s\n",ep->name); } /* Free memory */ free(psid); } Verbose("----------------------end-------------------------------\n"); } #endif /*****************************************************************************/ #ifdef NT /* Extra buffer size (beyond length of original string) needed to convert * file names, worst case should be "c:\" -> "/cygdrive/c/" (plus one for * null terminatory) - so 9 should be sufficient. */ #define CONVERT_PAD 12 /* Write error message to log from last failed windows API function. */ void LogWinError() { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ (LPTSTR) &lpMsgBuf, 0, NULL ); CfLog(cferror,(char *) lpMsgBuf,""); LocalFree( lpMsgBuf ); } void createNTACL(aces, method, filename, action) struct CFACE *aces; /* List built up during parsing of config file */ char method; /* ACL operation method (o/a) */ char *filename; /* The filename */ enum fileactions action;/* The action to be performed */ { /* Declarations */ struct CFACE *ep; /* Pointer for iteration purposes */ struct CFACE *new_aces = 0; /* Pointer to a new list of CFACEs */ struct CFACE *temp_ace; /* Temporary pointer to iterate a list later */ SECURITY_DESCRIPTOR *old_sd = 0;/* Pointer to the file's old SD */ SECURITY_ATTRIBUTES sa; /* To hold security info */ SECURITY_DESCRIPTOR sd; /* Pointer to a new SD */ PACL new_pacl = 0; /* Pointer to a new ACL */ PACL old_pacl = 0; /* Pointer to the old ACL */ DWORD newACLSize; /* To hold the size of all the ACEs */ BOOL haveACL; /* Flag to say whether old ACL existed */ ACL_SIZE_INFORMATION oldACLSize; /* To hold inof about old ACL */ ACL_SIZE_INFORMATION newACLSizeInfo;/* To hold inof about new ACL */ char *win_path = 0; /* Convert cygnus-style file path to native win32 one. */ win_path = malloc(strlen(filename) + CONVERT_PAD); if (!win_path) { FatalError("Memory Allocation failed"); } cygwin_conv_to_win32_path(filename, win_path); /* Allocate memory for list with new ACEs */ if ((new_aces = (struct CFACE *)calloc(1,sizeof(struct CFACE))) == NULL) { FatalError("Memory Allocation failed for new_aces\n"); } new_aces->next = NULL; /* Get information about existing ACL if append method */ if (method == 'a') { /* Get information about existing ACL */ old_sd = getNTACLInformation(win_path, &old_pacl, &haveACL, &oldACLSize); if (haveACL) { /* The file had an ACL. Append existing ACEs to our new list */ appendNTACEs(aces, new_aces, oldACLSize, old_pacl); } else { Verbose("File: %s has no security descriptor (Unrestricted access)!!\n"); } } /* All users from old ACL are added to our list with correct mask (if append). Users in our CFACE list with NTModeMask=0 are users that didn't exist before. Give them a proper mask */ for (ep = aces; ep != NULL; ep=ep->next) { /* Skip ACE if name is null or if class is excluded or if mode is "default"*/ if ((ep->name == NULL) || (IsExcluded(ep->classes)) || (strcmp(ep->mode,"default") == 0)) { continue; } /* User has noNTModeMask. Give him one and attach him to our new list. */ if (ep->NTMode == 0) { attachToNTACEs(new_aces, ep->name, ep->mode, ep->access, ep->classes, getNTModeMask(ep->mode,ep->NTMode)); } } /* Get the size of all ACE's that will be inserted in the new ACL */ if ((newACLSize = getNTACEs_Size(new_aces)) == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Size of ACEs is zero.\n", VPREFIX); CfLog(cferror,OUTPUT,""); goto done; } /* Add the size of an empty ACL */ newACLSize += sizeof(ACL); /* Initialize a Security Descriptor for the new ACL*/ if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to init new SD\n", VPREFIX); CfLog(cferror,OUTPUT,""); goto done; } /* Allocate memory for the new ACL */ if ((new_pacl = (PACL)calloc(1,newACLSize)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to allocate memory for new ACL\n", VPREFIX); CfLog(cferror,OUTPUT,""); goto done; } /* Initialize the new ACL */ if (!InitializeAcl(new_pacl, newACLSize, ACL_REVISION)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to initialize the new ACL\n", VPREFIX); CfLog(cferror,OUTPUT,""); goto done; } /* Adding all denied aces first, then all allowed aces */ AddNTACEs("denied",new_aces,&new_pacl); AddNTACEs("allowed",new_aces,&new_pacl); /* Set the new ACL into the Security Descriptor */ if (!SetSecurityDescriptorDacl(&sd, TRUE, new_pacl, FALSE)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to install new ACL\n", VPREFIX); CfLog(cferror,OUTPUT,""); goto done; } /* Check the new Security Descriptor */ if (!IsValidSecurityDescriptor(&sd)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: New Security Descriptor is invalid\n", VPREFIX); CfLog(cferror,OUTPUT,""); goto done; } /* Install new ACL and new Security Descriptor */ if (!SetFileSecurity(win_path, DACL_SECURITY_INFORMATION, &sd)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: acl: Unable to set file security on file: %s\n", VPREFIX, filename); CfLog(cferror,OUTPUT,""); LogWinError(); goto done; } done: /* Release memory */ if (win_path) free(win_path); if (new_pacl) free(new_pacl); if (old_sd) free(old_sd); ep = new_aces; while (ep) { temp_ace = ep; ep = ep->next; free(temp_ace); } Verbose("ACL installed successfully for file: %s\n",filename); } #endif /*****************************************************************************/ int CheckNTACE( struct CFACE *aces, /* List built up during parsing of config file */ char method, /* ACL operation method (o/a) */ char *filename, /* The filename */ enum fileactions action)/* The action to be performed */ { #ifdef NT struct CFACE *ep; Debug2("\n------------------------ ACL info ---------------------------------\n"); Debug2("- Filesystem is ntfs.\n"); Debug2("- Filename is %s\n",filename); Debug2("- Method is %c\n",method); Debug2("- Action is element # %d of enum fileactions\n",action); /* Create the new ACL */ createNTACL(aces, method, filename, action); return true; #else Verbose("This system is not NT. Can't create ACLs on this system...\n"); return false; #endif } /*************************** END NT Addition *******************************/ int CheckPosixACE(struct CFACE *aces,char method,char *filename,enum fileactions action) { #if defined(HAVE_SYS_ACL_H) && defined(SOLARIS) struct CFACE *ep; aclent_t aclbufp[MAX_ACL_ENTRIES], newaclbufp[MAX_ACL_ENTRIES], tmpacl; int nacl = 0, newacls = 0, status = 0, update = 0, i, j; struct stat sb; uid_t myuid; memset(aclbufp,0,sizeof(aclbufp)); memset(newaclbufp,0,sizeof(newaclbufp)); nacl = acl (filename, GETACLCNT, 0, NULL); nacl = acl (filename, GETACL, nacl, aclbufp); if (stat(filename, &sb) != 0) { CfLog(cferror,"","stat"); return -1; } Verbose(" Old acl has %d entries and is:\n", nacl); for (i = 0; i < nacl; i++) { Debug1(" a_type = %x, \ta_id = %d, \ta_perm = %o\n", aclbufp[i].a_type, aclbufp[i].a_id, aclbufp[i].a_perm); } Debug1("method = %c\n", method); if (method == 'a') { newacls = nacl; for (i = 0; i < nacl; i++) { newaclbufp[i].a_id = aclbufp[i].a_id; newaclbufp[i].a_type = aclbufp[i].a_type; newaclbufp[i].a_perm = aclbufp[i].a_perm; } } for (ep = aces; ep !=NULL; ep = ep->next) { if (ep->name == NULL) { continue; } if(IsExcluded(ep->classes)) { continue; } Verbose("%s: Mode =%s, name=%s, type=%s\n",VPREFIX,ep->mode,ep->name,ep->acltype); if (strcmp(ep->name, "*") == 0) { memset(ep->name,0,sizeof(ep->name)); } if (BuildAclEntry(&sb,ep->acltype,ep->name,&tmpacl) == 0) { status = 0; for (i = 0; i < newacls; i++) { if (newaclbufp[i].a_id == tmpacl.a_id && newaclbufp[i].a_type == tmpacl.a_type) { status = 1; if (strcmp(ep->mode, "default") == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Deleting ACL entry %d: type = %x,\tid = %d,\tperm = %o\n", i, newaclbufp[i].a_type, newaclbufp[i].a_id, newaclbufp[i].a_perm); CfLog(cfverbose,OUTPUT,""); newacls--; newaclbufp[i].a_id = newaclbufp[newacls].a_id; newaclbufp[i].a_type = newaclbufp[newacls].a_type; newaclbufp[i].a_perm = newaclbufp[newacls].a_perm; } else { tmpacl.a_perm = ParseSolarisMode(ep->mode, newaclbufp[i].a_perm); if (tmpacl.a_perm != newaclbufp[i].a_perm) { newaclbufp[i].a_id = tmpacl.a_id; newaclbufp[i].a_type = tmpacl.a_type; newaclbufp[i].a_perm = tmpacl.a_perm; snprintf(OUTPUT,CF_BUFSIZE*2,"Replaced ACL entry %d: type = %x,\tid = %d,\tperm = %o\n", i, newaclbufp[i].a_type, newaclbufp[i].a_id, newaclbufp[i].a_perm); CfLog(cfverbose,OUTPUT,""); } } } } } if (status == 0 && (strcmp(ep->mode, "default") != 0)) { newaclbufp[newacls].a_id = tmpacl.a_id; newaclbufp[newacls].a_type = tmpacl.a_type; newaclbufp[newacls].a_perm = ParseSolarisMode(ep->mode, 0); newacls++; snprintf(OUTPUT,CF_BUFSIZE*2,"Added ACL entry %d: type = %x,\tid = %d,\tperm = %o\n", i, newaclbufp[i].a_type, newaclbufp[i].a_id, newaclbufp[i].a_perm); CfLog(cfverbose,OUTPUT,""); } } if (newacls != nacl) { update = 1; } else { for (i = 0 ; i < nacl ; i++) { status = 0; for (j = 0 ; j < newacls ; j++) { if (aclbufp[i].a_id == newaclbufp[j].a_id && aclbufp[i].a_type == newaclbufp[j].a_type && aclbufp[i].a_perm == newaclbufp[j].a_perm) { status = 1; } } if (status == 0) update = 1; } } if (update == 0) { Verbose("no update necessary\n"); return false; } if (action == warnall || action == warnplain || action == warndirs) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s needs ACL update\n",filename); CfLog(cfinform,OUTPUT,""); return false; } if ((status = aclcheck(newaclbufp, newacls, &i)) != 0) { printf("aclcheck failed\n"); aclsortperror(status); return false; } if (aclsort(newacls, 0, (aclent_t *) newaclbufp) != 0) { printf("%s: aclsort failed\n", VPREFIX); return false; } Debug1("new acl has %d entries and is:\n", newacls); for (i = 0; i < newacls; i++) { Debug1 ("a_type = %x,\ta_id = %d,\ta_perm = %o\n", newaclbufp[i].a_type, newaclbufp[i].a_id, newaclbufp[i].a_perm); } Debug1("setting acl of %s with %d acl-entries\n", filename, newacls); myuid = getuid(); if (sb.st_uid != myuid) { if (myuid == 0) { Verbose("Changing effective uid to %ld\n", (long)sb.st_uid); if (seteuid(sb.st_uid) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't set effective uid from %ld to %ld\n",(long)myuid,(long)sb.st_uid); CfLog(cferror,OUTPUT,"seteuid"); return false; } Debug1("effective uid now %ld\n", (long)sb.st_uid); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't set effective uid from %ld to %ld, not super-user!\n", (long)myuid, (long)sb.st_uid); CfLog(cferror,OUTPUT,"seteuid"); return false; } Debug1("now the correct uid to manage acl of %s\n", filename, newacls); if (acl (filename, SETACL, newacls, newaclbufp) != newacls) { CfLog(cferror,"","acl"); return false; } Debug1("setting acl of %s resulted in %d acl-entries\n", filename, newacls); if (seteuid(myuid) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to regain privileges of user %ld\n", (long)myuid); CfLog(cferror,OUTPUT,"seteuid"); FatalError("Aborting cfengine"); } } else { if (acl(filename, SETACL, newacls, newaclbufp) != newacls) { CfLog(cferror,"","acl"); return false; } Debug1("setting acl of %s resulted in %d acl-entries\n", filename, newacls); } snprintf(OUTPUT,CF_BUFSIZE*2,"ACL for file %s updated\n",filename); CfLog(cfinform,OUTPUT,""); return true; #else Verbose("Can't do ACLs on this system...\n"); return false; #endif } cfengine-2.2.10/src/process.c0000644000175000001440000003210011055250436012675 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* Process handling */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" int DEADLOCK = false; FILE *PIPE; /*******************************************************************/ int LoadProcessTable(struct Item **procdata,char *psopts) { FILE *pp; char pscomm[CF_MAXLINKSIZE], imgbackup; struct Item *rootprocs = NULL; struct Item *otherprocs = NULL; snprintf(pscomm,CF_MAXLINKSIZE,"%s %s",VPSCOMM[VSYSTEMHARDCLASS],psopts); Verbose("%s: Running process command %s\n",VPREFIX,pscomm); if ((pp = cfpopen(pscomm,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open the process list with command %s\n",pscomm); CfLog(cferror,OUTPUT,"popen"); return false; } while (!feof(pp)) { memset(VBUFF,0,CF_BUFSIZE); ReadLine(VBUFF,CF_BUFSIZE,pp); AppendItem(procdata,VBUFF,""); } cfpclose(pp); /* Now save the data */ imgbackup = IMAGEBACKUP; IMAGEBACKUP = 'n'; snprintf(VBUFF,CF_MAXVARSIZE,"%s/state/cf_procs",CFWORKDIR); SaveItemList(*procdata,VBUFF,"none"); CopyList(&rootprocs,*procdata); CopyList(&otherprocs,*procdata); while (DeleteItemNotContaining(&rootprocs,"root")) { } while (DeleteItemContaining(&otherprocs,"root")) { } PrependItem(&rootprocs,otherprocs->name,NULL); snprintf(VBUFF,CF_MAXVARSIZE,"%s/state/cf_rootprocs",CFWORKDIR); SaveItemList(rootprocs,VBUFF,"none"); DeleteItemList(rootprocs); snprintf(VBUFF,CF_MAXVARSIZE,"%s/state/cf_otherprocs",CFWORKDIR); SaveItemList(otherprocs,VBUFF,"none"); DeleteItemList(otherprocs); IMAGEBACKUP = imgbackup; return true; } /*******************************************************************/ void DoProcessCheck(struct Process *pp,struct Item *procdata) { char line[CF_BUFSIZE]; int matches=0,dosignals=true; mode_t maskval; struct stat statbuf; struct Item *killlist = NULL; Debug("DoProcessCheck()\n"); matches = FindMatches(pp,procdata,&killlist); if (matches > 0) { Verbose("Defining classes %s\n",pp->defines); AddMultipleClasses(pp->defines); } else { Verbose("Defining classes %s\n",pp->elsedef); AddMultipleClasses(pp->elsedef); } if (pp->matches >= 0) { if (pp->action == 'm') { dosignals = false; } switch (pp->comp) { case '=': if (matches != (int)pp->matches) { snprintf(OUTPUT,CF_BUFSIZE*2,"%d processes matched %s (should be %d)\n",matches,pp->expr,pp->matches); CfLog(cfinform,OUTPUT,""); if (pp->action == 'm') { dosignals = true; } } break; case '>': if (matches < (int)pp->matches) { snprintf(OUTPUT,CF_BUFSIZE*2,"%d processes matched %s (should be >=%d)\n",matches,pp->expr,pp->matches); CfLog(cfinform,OUTPUT,""); if (pp->action == 'm') { dosignals = true; } } break; case '<': if (matches > (int)pp->matches) { snprintf(OUTPUT,CF_BUFSIZE*2,"%d processes matched %s (should be <=%d)\n",matches,pp->expr,pp->matches); CfLog(cfinform,OUTPUT,""); if (pp->action == 'm') { dosignals = true; } } } } if (dosignals) { DoSignals(pp,killlist); } DeleteItemList(killlist); if ((pp->action == 'm') && !dosignals && (matches != 0)) { Verbose("%s: Matches found for %s - no restart sequence\n",VPREFIX,pp->expr); return; } if (strlen(pp->restart) != 0) { char argz[256]; Verbose("Existing restart sequence found (%s)\n",pp->restart); if ((matches != 0) && (pp->signal != cfkill) && (pp->signal != cfterm)) { Verbose("%s: Matches found for %s - no restart sequence\n",VPREFIX,pp->expr); return; } sscanf(pp->restart,"%255s",argz); if ((stat(argz,&statbuf) != -1) && (statbuf.st_mode & 0111 == 0)) { snprintf(OUTPUT,CF_BUFSIZE,"Restart sequence %s could not be executed (mode=%o), while searching (%s)",pp->restart,statbuf.st_mode &7777,pp->expr); CfLog(cferror,OUTPUT,""); return; } snprintf(OUTPUT,CF_BUFSIZE*2,"Executing shell command: %s\n",pp->restart); CfLog(cfinform,OUTPUT,""); if (DONTDO) { return; } Verbose ("(Setting umask to %o)\n",pp->umask); maskval = umask(pp->umask); if (pp->umask == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Programming %s running with umask 0! Use umask= to set\n",pp->restart); CfLog(cfsilent,OUTPUT,""); } if (pp->useshell == 'y') { if ((PIPE = cfpopen_shsetuid(pp->restart,"r",pp->uid,pp->gid,pp->chdir,pp->chroot)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Process restart execution failed on %s\n",pp->restart); CfLog(cferror,OUTPUT,"popen"); //pp->returnstatus = CF_FAIL; return; } } else { if ((PIPE = cfpopensetuid(pp->restart,"r",pp->uid,pp->gid,pp->chdir,pp->chroot)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Process restart execution failed on %s\n",pp->restart); CfLog(cferror,OUTPUT,"popen"); //pp->returnstatus = CF_FAIL; return; } } DEADLOCK = false; while (!feof(PIPE)) { if (pp->useshell == 'd') /* dumb shell */ { fgets(line,1,PIPE); break; } ReadLine(line,CF_BUFSIZE,PIPE); if (feof(PIPE) || ferror(PIPE)) { break; } if (strstr(line,"cfengine-die")) { break; } /* patch for ERESTARTSYSTEM bug in popen */ if (strstr(line,"cfd: start") || DEADLOCK) { break; } snprintf(OUTPUT,CF_BUFSIZE*2,"Restart: %s",line); CfLog(cfinform,OUTPUT,""); } if (pp->useshell == 'y') { pclose(PIPE); } else { cfpclose(PIPE); } snprintf(OUTPUT,CF_BUFSIZE*2,"(Done with %s)\n",pp->restart); CfLog(cfinform,OUTPUT,""); umask(maskval); //pp->returnstatus = CF_CHG; } } /**********************************************************************************/ int FindMatches(struct Process *pp,struct Item *procdata,struct Item **killlist) { struct Item *ip, *ip2; char *sp,saveuid[16]; int pid=-1, ret, matches=0, got, i, one_space; regex_t rx,rxcache; regmatch_t pmatch; pid_t cfengine_pid = getpid(); char *names[CF_PROCCOLS]; /* ps headers */ int start[CF_PROCCOLS]; int end[CF_PROCCOLS]; Debug2("Looking for process %s\n",pp->expr); if (CfRegcomp(&rxcache,pp->expr,REG_EXTENDED) != 0) { return 0; } GetProcessColumns(procdata->name,(char **)names,start,end); for (ip = procdata; ip != NULL; ip=ip->next) { memcpy(&rx,&rxcache,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */ if (regexec(&rx,ip->name,1,&pmatch,0) == 0) { pid = -1; got = true; Debug("Regex %s matched %s\n",ip->name,pp->expr); for (ip2 = pp->inclusions; ip2 != NULL; ip2 = ip2->next) { got = false; if (strstr(ip->name,ip2->name) || WildMatch(ip2->name,ip->name)) { got = true; break; } } if (!got) { continue; } got = false; for (ip2 = pp->exclusions; ip2 != NULL; ip2 = ip2->next) { if (strstr(ip->name,ip2->name) || WildMatch(ip2->name,ip->name)) { got = true; break; } } if (!ProcessFilter(ip->name,pp->filters,names,start,end)) { Debug("%s Filtered away\n",ip->name); continue; } if (got) { continue; } Debug("Matched proc[%s]\n",ip->name); for (sp = ip->name; *sp != '\0'; sp++) /* if first field contains alpha, skip */ { while (true) { /* HvB If start with alpha then skip it till the first space */ if (isalnum((int)*sp)) { while ((*sp != ' ') && (*sp != '\0')) { sp++; } } /* skip spaces and tabs */ while ((*sp == ' ') && (*sp == '\t')) { sp++; } break; } /* end while */ sscanf(sp,"%d",&pid); if (pid != -1) { break; } } /* end for */ if (pid == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to extract pid while looking for %s\n",pp->expr); CfLog(cfverbose,OUTPUT,""); continue; } Debug2("Found matching pid %d\n",pid); matches++; if (pid == 1 && pp->signal == cfhup) { Verbose("(Okay to send HUP to init)\n"); } else if (pid < 4) { Verbose("%s: will not signal or restart processes 0,1,2,3\n",VPREFIX); Verbose("%s: occurred while looking for %s\n",VPREFIX,pp->expr); continue; } if (pp->action == 'w') { snprintf(OUTPUT,CF_BUFSIZE*2,"Process alert: %s\n",procdata->name); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"Process alert: %s\n",ip->name); CfLog(cferror,OUTPUT,""); continue; } if (pp->signal != cfnosignal) { if (!DONTDO) { if (pid == cfengine_pid) { CfLog(cfverbose,"Cfengine will not kill itself!\n",""); continue; } if (pp->action == 'm') { sprintf(saveuid,"%d",pid); PrependItem(killlist,saveuid,""); } else { if ((ret = kill((pid_t)pid,pp->signal)) < 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't send signal to pid %d\n",pid); CfLog(cfverbose,OUTPUT,"kill"); continue; } snprintf(OUTPUT,CF_BUFSIZE*2,"Signalled process %d (%s) with %s\n",pid,pp->expr,SIGNALS[pp->signal]); CfLog(cfinform,OUTPUT,""); if ((pp->signal == cfkill || pp->signal == cfterm) && ret >= 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Killed: %s\n",ip->name); CfLog(cfinform,OUTPUT,""); } } } } } } for (i = 0; i < CF_PROCCOLS; i++) { if (names[i] != NULL) { free(names[i]); } } regfree(&rx); return matches; } /**********************************************************************************/ void DoSignals(struct Process *pp,struct Item *list) { struct Item *ip; pid_t pid; int ret; Verbose("DoSignals(%s)\n",pp->expr); if (list == NULL) { return; } if (pp->signal == cfnosignal) { snprintf(OUTPUT,CF_BUFSIZE,"No signal to send for %s\n",pp->expr); CfLog(cfinform,OUTPUT,""); return; } for (ip = list; ip != NULL; ip=ip->next) { pid = (pid_t)-1; sscanf(ip->name,"%d",&pid); if (pid == (pid_t)-1) { CfLog(cferror,"Software error: Unable to decypher pid list",""); return; } if (!DONTDO) { if ((ret = kill((pid_t)pid,pp->signal)) < 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't send signal to pid %d\n",pid); CfLog(cfverbose,OUTPUT,"kill"); //pp->returnstatus = CF_FAIL; return; } if ((pp->signal == cfkill || pp->signal == cfterm) && ret >= 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Killed: %s\n",ip->name); CfLog(cfinform,OUTPUT,""); //pp->returnstatus = CF_CHG; } } } } cfengine-2.2.10/src/Makefile.am0000644000175000001440000000701211045631340013107 00000000000000AM_CFLAGS = $(GCC_CFLAG) @CFLAGS@ AM_YFLAGS = -d LEXLIB = @LEXLIB@ LDADD = libcfengine.la $(BERKELEY_DB_LDFLAGSD) $(BERKELEY_DB_LIB) $(OPENSSL_LIB_LDFLAGS) $(OPENSSL_LIB_LIB) INCLUDES = $(BERKELEY_DB_CFLAGS) $(OPENSSL_LIB_CPPFLAGS) AM_LDFLAGS = $(BERKELEY_DB_LDFLAGS) $(OPENSSL_LIB_LDFLAGS) @LDFLAGS@ sbin_PROGRAMS = cfagent cfservd cfrun cfkey cfenvd cfenvgraph cfexecd cfshow cfetool cfetoolgraph # # Fix this generically # lib_LTLIBRARIES = libcfengine.la libcfengine_la_LDFLAGS = -version-info 1:0:0 -no-undefined libcfengine_la_LIBADD = $(BERKELEY_DB_LDFLAGSD) $(BERKELEY_DB_LIB) $(OPENSSL_LIB_LDFLAGS) $(OPENSSL_LIB_LIB) libcfengine_la_CFLAGS = $(AM_CFLAGS) # Separate out a library libcfengine_la_SOURCES = \ init.c \ modules.c \ alerts.c \ report.c \ client.c \ ip.c \ ipname.c \ instrument.c \ process.c \ timeout.c \ ifconf.c \ image.c \ item.c \ item-ext.c \ item-file.c \ 2Dlist.c \ globals.c \ classes.c \ misc.c \ parse.c \ functions.c \ edittools.c \ patches.c \ install.c \ link.c \ tidy.c \ filedir.c \ eval.c \ modes.c \ sockaddr.c \ chflags.c \ locks.c \ mount.c \ macro.c \ filenames.c \ varstring.c \ wildcard.c \ cfparse.y \ comparray.c \ read.c \ checksums.c \ proto.c \ filters.c \ copy.c \ repository.c \ rotate.c \ errors.c \ cflex.l \ net.c \ df.c \ log.c \ crypto.c \ popen.c \ popen_def.c \ sensible.c \ acl.c \ dce_acl.c \ nameinfo.c \ strategies.c \ granules.c \ methods.c \ dtypes.c \ state.c \ checksum_db.c \ expand-files.c \ expand-tidy.c \ expand-image.c \ expand-editfiles.c \ package.c \ scli.c #libcfengine_la_LIBADD = -L../pub -lcfpub cfshow_SOURCES = \ cfshow.c cfagent_SOURCES = \ cfagent.c \ wrapper.c \ do.c cfservd_SOURCES = \ cfservd.c cfexecd_SOURCES = \ cfexecd.c #cfexecd_LDADD = $(LEXLIB) $(BERKELEY_DB_LIB) $(OPENSSL_LIB_LIB) cfrun_SOURCES = \ cfrun.c cfkey_SOURCES = \ cfkey.c cfenvd_SOURCES = \ cfenvd.c \ env_monitor.c cfenvgraph_SOURCES = \ cfenvgraph.c cfetool_SOURCES = \ cfetool.c cfetoolgraph_SOURCES = \ cfetoolgraph.c # # Pickup header files here so Automake knows about them # noinst_HEADERS = \ cfservd.h \ cfparse.h \ cf.defs.h \ cf.extern.h \ prototypes.h \ cfetooldefs.h # # Some basic clean ups # MOSTLYCLEANFILES = *~ *.orig *.rej # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = cflex.c cfparse.c cfparse.h # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = cflex.c cfparse.c cfparse.h # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in conf.h.in stamp-h.in cfengine-2.2.10/src/sensible.c0000644000175000001440000001472410361142606013035 00000000000000/* Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: sensible.c */ /* */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ /* Files to be ignored when parsing directories */ /*********************************************************************/ char *VSKIPFILES[] = { ".", "..", "lost+found", ".cfengine.rm", NULL }; /*********************************************************************/ int SensibleFile(char *nodename,char *path,struct Image *ip) { int i, suspicious = true; struct stat statbuf; unsigned char *sp, newname[CF_BUFSIZE],vbuff[CF_BUFSIZE]; if (strlen(nodename) < 1) { snprintf(OUTPUT,CF_BUFSIZE,"Empty (null) filename detected in %s\n",path); CfLog(cferror,OUTPUT,""); return true; } if (IsItemIn(SUSPICIOUSLIST,nodename)) { struct stat statbuf; if (stat(nodename,&statbuf) != -1) { if (S_ISREG(statbuf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE,"Suspicious file %s found in %s\n",nodename,path); CfLog(cferror,OUTPUT,""); return false; } } } if (strcmp(nodename,"...") == 0) { Verbose("Possible DFS/FS cell node detected in %s...\n",path); return true; } for (i = 0; VSKIPFILES[i] != NULL; i++) { if (strcmp(nodename,VSKIPFILES[i]) == 0) { Debug("Filename %s/%s is classified as ignorable\n",path,nodename); return false; } } if ((strcmp("[",nodename) == 0) && (strcmp("/usr/bin",path) == 0)) { if (VSYSTEMHARDCLASS == linuxx) { return true; } } suspicious = true; for (sp = nodename; *sp != '\0'; sp++) { if ((*sp > 31) && (*sp < 127)) { suspicious = false; break; } } strcpy(vbuff,path); AddSlash(vbuff); strcat(vbuff,nodename); if (suspicious && NONALPHAFILES) { snprintf(OUTPUT,CF_BUFSIZE,"Suspicious filename %s in %s has no alphanumeric content (security)",CanonifyName(nodename),path); CfLog(cfsilent,OUTPUT,""); strcpy(newname,vbuff); for (sp = newname+strlen(path); *sp != '\0'; sp++) { if ((*sp > 126) || (*sp < 33)) { *sp = 50 + (*sp / 50); /* Create a visible ASCII interpretation */ } } strcat(newname,".cf-nonalpha"); snprintf(OUTPUT,CF_BUFSIZE,"Renaming file %s to %s",vbuff,newname); CfLog(cfsilent,OUTPUT,""); if (rename(vbuff,newname) == -1) { CfLog(cfverbose,"Rename failed - foreign filesystem?\n","rename"); } if (chmod(newname,0644) == -1) { CfLog(cfverbose,"Mode change failed - foreign filesystem?\n","chmod"); } return false; } if (strstr(nodename,".") && (EXTENSIONLIST != NULL)) { if (cflstat(vbuff,&statbuf,ip) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't examine %s - foreign filesystem?\n",vbuff); CfLog(cfverbose,OUTPUT,"lstat"); return true; } if (S_ISDIR(statbuf.st_mode)) { if (strcmp(nodename,"...") == 0) { Verbose("Hidden directory ... found in %s\n",path); return true; } for (sp = nodename+strlen(nodename)-1; *sp != '.'; sp--) { } if ((char *)sp != nodename) /* Don't get .dir */ { sp++; /* Find file extension, look for known plain files */ if ((strlen(sp) > 0) && IsItemIn(EXTENSIONLIST,sp)) { snprintf(OUTPUT,CF_BUFSIZE,"Suspicious directory %s in %s looks like plain file with extension .%s",nodename,path,sp); CfLog(cfsilent,OUTPUT,""); return false; } } } } for (sp = nodename; *sp != '\0'; sp++) /* Check for files like ".. ." */ { if ((*sp != '.') && ! isspace(*sp)) { suspicious = false; return true; } } /* removed if (EXTENSIONLIST==NULL) mb */ if (cflstat(vbuff,&statbuf,ip) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Couldn't stat %s",vbuff); CfLog(cfverbose,OUTPUT,"lstat"); return true; } if (statbuf.st_size == 0 && ! (VERBOSE||INFORM)) /* No sense in warning about empty files */ { return false; } snprintf(OUTPUT,CF_BUFSIZE,"Suspicious looking file object \"%s\" masquerading as hidden file in %s\n",nodename,path); CfLog(cfsilent,OUTPUT,""); Debug("Filename looks suspicious\n"); if (S_ISLNK(statbuf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE," %s is a symbolic link\n",nodename); CfLog(cfsilent,OUTPUT,""); } else if (S_ISDIR(statbuf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE," %s is a directory\n",nodename); CfLog(cfsilent,OUTPUT,""); } snprintf(OUTPUT,CF_BUFSIZE,"[%s] has size %ld and full mode %o\n",nodename,(unsigned long)(statbuf.st_size),(unsigned int)(statbuf.st_mode)); CfLog(cfsilent,OUTPUT,""); return true; } /********************************************************************/ void RegisterRecursionRootDevice(dev_t device) { Debug("Registering root device as %d\n",device); ROOTDEVICE = device; } /********************************************************************/ int DeviceChanged(dev_t thisdevice) { if (thisdevice == ROOTDEVICE) { return false; } else { Verbose("Device change from %d to %d\n",ROOTDEVICE,thisdevice); return true; } } cfengine-2.2.10/src/dce_acl.c0000644000175000001440000006004610202123551012571 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*****************************************************************************/ /* */ /* File: dce_acl.c */ /* Author: Allan L. Bazinet */ /* */ /*****************************************************************************/ /*****************************************************************************/ /* Includes */ /*****************************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #ifdef HAVE_DCE_DACLIF_H #include #include #include #include #include #include #include #include #include #include #include #include /*****************************************************************************/ /* Macros */ /*****************************************************************************/ #define MGR_TYPES_SIZE_AVAIL (2) #define ArraySize(x) ((sizeof(x))/(sizeof(x[0]))) #define SetBit(f,b) (f |= b) #define UnSetBit(f,b) (f &= ~(b)) /*****************************************************************************/ /* Local Types */ /*****************************************************************************/ struct rgyData { boolean32 isId; uuid_t uuid; sec_rgy_name_t name; sec_acl_entry_type_t type; }; struct aclData { sec_rgy_name_t name; sec_acl_handle_t handle; uuid_t mgrTypes[MGR_TYPES_SIZE_AVAIL]; unsigned32 mgrTypesNum; unsigned32 mgrTypesSizeUsed; sec_acl_list_t list; sec_acl_p_t new; sec_acl_p_t old; }; /*****************************************************************************/ /* Local Prototypes */ /*****************************************************************************/ static void setupACL(int, struct aclData *, error_status_t *); static void resetACL(struct aclData *); static void logError(const char *, enum cfoutputlevel, error_status_t); static void getRgyData(const char *, const char *, struct rgyData *, error_status_t *); static boolean32 isMatchingACLEntry(sec_acl_entry_t * aclEntry, struct rgyData * rgyData, error_status_t * status); static void nameToUUID(sec_rgy_name_t, sec_acl_entry_type_t, uuid_p_t, error_status_t *); static sec_acl_permset_t permPrintableToBitmask(char); static sec_acl_permset_t permSetPrintableToBinary(const char *, sec_acl_permset_t, error_status_t *); static sec_acl_entry_type_t aclTypePrintableToBinary(const char *, boolean32, error_status_t *); static boolean32 equalACLEntry(sec_acl_entry_t * lhs, sec_acl_entry_t * rhs, error_status_t * status); static boolean32 equalACLEntries(sec_acl_t * lhs, sec_acl_t * rhs, error_status_t * status); static void copyACLEntries(sec_acl_t const * source, sec_acl_t * target); /*****************************************************************************/ /* Exposed Routines */ /*****************************************************************************/ /* ** CheckDFSACE() ** ** This is called by CheckACLs, and should return true on success, ** false on failure. */ int CheckDFSACE(struct CFACE * aces, char method, char * filename, enum fileactions action) { struct CFACE * ep; struct aclData aclData; struct rgyData rgyData; int aclIndex; boolean32 entryMatch; error_status_t aclStatus; error_status_t fooStatus; /* Setup aclData structure by copying requested filename to name member */ strncpy((char *)&(aclData.name[0]), (const char *)filename, sizeof(aclData.name)); sec_acl_bind(aclData.name, FALSE, &aclData.handle, &aclStatus); if (aclStatus == error_status_ok) { sec_acl_get_manager_types(aclData.handle, sec_acl_type_object, ArraySize(aclData.mgrTypes), &aclData.mgrTypesSizeUsed, &aclData.mgrTypesNum, aclData.mgrTypes, &aclStatus); if (aclStatus == error_status_ok) { if (aclData.mgrTypesSizeUsed < aclData.mgrTypesNum) { CfLog(cfsilent, "Warning: some manager types missed\n", ""); } sec_acl_lookup(aclData.handle, aclData.mgrTypes, sec_acl_type_object, &aclData.list, &aclStatus); if (aclStatus == error_status_ok) { setupACL(MAXDFSACL, &aclData, &aclStatus); if (aclStatus == error_status_ok) { /* If this is an append, copy all existing acls to the new ** ACL list allocated by setupACL() */ if (method == 'a') copyACLEntries(aclData.old, aclData.new); /* Walk CFACE list until end-of-list or fatal error */ for (ep = aces; ep && (aclStatus == error_status_ok); ep = ep->next) { if ((ep->name == NULL) || (IsExcluded(ep->classes))) continue; Verbose("%s: Mode =%s, name=%s, type=%s\n", VPREFIX, ep->mode, ep->name, ep->acltype); /* Translate external ACL representation to internal */ getRgyData(ep->name, ep->acltype, &rgyData, &aclStatus); if (aclStatus == error_status_ok) { /* Zip through the ACL, looking for a match */ entryMatch = FALSE; for (aclIndex = 0; aclIndex < aclData.new->num_entries; aclIndex++) { entryMatch = isMatchingACLEntry(&(aclData.new-> sec_acl_entries[aclIndex]), &rgyData, &aclStatus); if (aclStatus == error_status_ok) { if (entryMatch) { /* ** "default" means remove the named user from the ACL, ** so that default permissions apply. If this is a ** "default", then decrease number of entries in the ACL; ** if this wasn't the topmost entry, then move the topmost ** to this slot. ** ** Otherwise, set the permissions set on this entry ** using the mode provided. */ if (strcmp(ep->mode, "default") == 0) { aclData.new->num_entries--; if (aclData.new->num_entries != aclIndex) { aclData.new->sec_acl_entries[aclIndex] = aclData.new->sec_acl_entries[aclData.new-> num_entries]; } } else { aclData.new->sec_acl_entries[aclIndex].perms = permSetPrintableToBinary(ep->mode, aclData.new-> sec_acl_entries[aclIndex]. perms, &aclStatus); } /* ACL entry has been matched; stop looking. */ break; } } } /* At this point, we've either experienced a fatal error or ** have searched the ACL list for the entry, successfully or ** unsuccessfully. If we are still alive and yet haven't ** found a matching entry, then either this is a default entry, ** in which case we do nothing (since there's nothing to remove), ** or a new entry, in which case we set it up. */ if (aclStatus == error_status_ok) { if ((entryMatch == FALSE) && (strcmp(ep->mode, "default") != 0)) { aclIndex = aclData.new->num_entries; aclData.new->num_entries = aclIndex + 1; if (rgyData.isId) { aclData.new->sec_acl_entries[aclIndex]. entry_info.tagged_union.id.uuid = rgyData.uuid; } aclData.new->sec_acl_entries[aclIndex]. entry_info.entry_type = rgyData.type; aclData.new->sec_acl_entries[aclIndex]. perms = permSetPrintableToBinary(ep->mode, 0, &aclStatus); } } } } /* We've now either successfully run the list of CFACE elements ** and have a new ACL, or we've been killed by a fatal error. ** If we are alive, and the new ACL is different from the ** preexisting one, then we will attempt to update; otherwise, ** we are a no-op. */ if (aclStatus == error_status_ok) { entryMatch = equalACLEntries(aclData.old, aclData.new, &aclStatus); if (aclStatus == error_status_ok) { if (entryMatch) { Verbose("%s: No update necessary\n", VPREFIX); aclStatus = sec_acl_duplicate_entry; } else { if ((action == warnall) || (action == warnplain) || (action == warndirs)) { snprintf(OUTPUT,CF_BUFSIZE,"File %s needs ACL update\n", filename); CfLog(cfinform, OUTPUT, ""); aclStatus = sec_acl_not_authorized; } else { sec_acl_replace(aclData.handle, aclData.mgrTypes, sec_acl_type_object, &(aclData.list), &aclStatus); if (aclStatus == error_status_ok) { snprintf(OUTPUT,CF_BUFSIZE,"ACL for file %s updated\n", filename); CfLog(cfinform, OUTPUT, ""); } else { logError("sec_acl_replace", cferror, aclStatus); } } } } } /* Reset aclData structure to initial state */ resetACL(&aclData); } /* ** Free ACL storage that the system provided via sec_acl_lookup(). */ for (aclIndex = 0; aclIndex < aclData.list.num_acls; aclIndex++) { sec_acl_release(aclData.handle, aclData.list.sec_acls[aclIndex], &fooStatus); if (fooStatus != error_status_ok) { logError("sec_acl_release", cferror, fooStatus); } } } else { logError("sec_acl_lookup", cferror, aclStatus); } } else { logError("sec_acl_get_manager_types", cferror, aclStatus); } sec_acl_release_handle(&aclData.handle, &fooStatus); if (fooStatus != error_status_ok) { logError("sec_acl_release_handle", cferror, fooStatus); } } else { logError("sec_acl_bind", cferror, aclStatus); } return ((aclStatus == error_status_ok) ? true : false); } /*****************************************************************************/ /* Private Routines */ /*****************************************************************************/ /* ** getRgyData() ** ** Attempt to populate provided rgyData structure using provided name ** and acl information. Status returned via status parameter. ** */ static void getRgyData(const char * aclName, const char * aclType, struct rgyData * rgyData, error_status_t * status) { /* ** asterisk in "name" field means that the user or group id ** is implicitly specified as the owner of the file, or that ** no id is applicable at all (as is the case for "other"). */ if ((strlen(aclName) == 0) || (strcmp(aclName, "*") == 0)) { rgyData->isId = FALSE; } else { rgyData->isId = TRUE; strncpy((char *)&(rgyData->name[0]), aclName, sizeof(rgyData->name)); } rgyData->type = aclTypePrintableToBinary(aclType, rgyData->isId, status); if (*status == error_status_ok) { if (rgyData->isId) nameToUUID(rgyData->name, rgyData->type, &(rgyData->uuid), status); } } /* ** isMatchingACLEntry() ** ** Compare provided ACL entry to information contained in provided rgyData ** structure, returning boolean value representing matched/not matched ** status. Status returned via status parameter. */ static boolean32 isMatchingACLEntry(sec_acl_entry_t * aclEntry, struct rgyData * rgyData, error_status_t * status) { boolean32 isMatching; if (aclEntry->entry_info.entry_type == rgyData->type) { if (rgyData->isId) { isMatching = uuid_equal(&(aclEntry->entry_info.tagged_union.id.uuid), &(rgyData->uuid), status); } else { isMatching = TRUE; } } else { isMatching = FALSE; } return(isMatching); } /* ** aclTypePrintableToBinary() ** ** If type information is found to be valid, return binary type. ** Return status via provided status parameter. ** ** Notes: Since sec_acl_entry_type_t is an enumerated type (see ** /usr/include/dce/aclbase.h), we can't simply return 0 on ** failure, as that is equivalent to sec_acl_e_type_user_obj. */ static sec_acl_entry_type_t aclTypePrintableToBinary(const char * tString, boolean32 nUsed, error_status_t * status) { static const struct Type { const char * tString; sec_acl_entry_type_t tType; sec_acl_entry_type_t nType; } TypeTable[] = { {"any", sec_acl_e_type_any_other, 0 }, {"foreign_group", sec_acl_e_type_foreign_group, 0 }, {"foreign_other", sec_acl_e_type_foreign_other, 0 }, {"foreign_user", sec_acl_e_type_foreign_user, 0 }, {"group", sec_acl_e_type_group_obj, sec_acl_e_type_group }, {"mask", sec_acl_e_type_mask_obj, 0 }, {"other", sec_acl_e_type_other_obj, 0 }, {"unauthenticated", sec_acl_e_type_unauthenticated, 0 }, {"user", sec_acl_e_type_user_obj, sec_acl_e_type_user } }; struct Type const * bot = &TypeTable[0]; struct Type const * top = &TypeTable[ArraySize(TypeTable)]; struct Type const * mid; int cmp; while (bot < top) { mid = bot + ((top - bot) >> 1); cmp = strcmp(tString, mid->tString); if (cmp < 0) top = mid; else if (cmp > 0) bot = mid + 1; else { *status = error_status_ok; if ((mid->nType) && (nUsed)) return mid->nType; else return mid->tType; } } snprintf(OUTPUT,CF_BUFSIZE,"Invalid DCE/DFS acl type '%s'\n", tString); CfLog(cferror, OUTPUT, ""); *status = sec_acl_invalid_acl_type; return(0); } /* ** permSetPrintableToBinary() ** ** Convert provided permissions set to sec_acl_permset_t binary ** representation and return. Status returned via status ** paramter. */ static sec_acl_permset_t permSetPrintableToBinary(const char * perms, sec_acl_permset_t oldPermSet, error_status_t * status) { error_status_t localStatus = error_status_ok; int isAdd; const char * permsPtr; char curPerm; sec_acl_permset_t bitmask; sec_acl_permset_t newPermSet; if ((strcmp(perms, "noaccess")) == 0) { newPermSet = 0; } else { newPermSet = oldPermSet; isAdd = true; permsPtr = perms; while (curPerm = *permsPtr++) { if ((curPerm == '+') || (curPerm == ',')) { isAdd = true; } else if (curPerm == '-') { isAdd = false; } else if (curPerm == '=') { isAdd = true; newPermSet = 0; } else { if (bitmask = permPrintableToBitmask(curPerm)) { if (isAdd) SetBit(newPermSet, bitmask); else UnSetBit(newPermSet, bitmask); } else { snprintf(OUTPUT,CF_BUFSIZE, "Invalid mode '%c' in DCE/DFS acl: %s\n", curPerm, perms); CfLog(cferror, OUTPUT, ""); localStatus = sec_acl_invalid_dfs_acl; break; } } } } *status = localStatus; return newPermSet; } /* ** permPrintableToBitmask() ** ** Convert the provided DCE/DFS printable permission to the corresponding ** binary representation. Returns nonzero binary representation on ** success, zero on failure. */ static sec_acl_permset_t permPrintableToBitmask(char printable) { static const struct Convert { char printable; sec_acl_permset_t bitmask; } ConvertTable[] = { { 'c', sec_acl_perm_control }, { 'd', sec_acl_perm_delete }, { 'i', sec_acl_perm_insert }, { 'r', sec_acl_perm_read }, { 'w', sec_acl_perm_write }, { 'x', sec_acl_perm_execute } }; struct Convert const * bot = &ConvertTable[0]; struct Convert const * top = &ConvertTable[ArraySize(ConvertTable)]; struct Convert const * mid; int cmp; while (bot < top) { mid = bot + ((top - bot) >> 1); cmp = printable - mid->printable; if (cmp < 0) top = mid; else if (cmp > 0) bot = mid + 1; else return mid->bitmask; } return(0); } /* ** logError() ** ** Convert provided DCE status code to printable representation, if ** possible, and output error message at specified level. */ static void logError(const char * routine, enum cfoutputlevel level, error_status_t status) { error_status_t msgStatus; unsigned_char_p_t msgText; if (msgText = dce_msg_get_msg(status, &msgStatus)) { CfLog(level, msgText, routine); free(msgText); } else { snprintf(OUTPUT,CF_BUFSIZE, "\n", status, msgStatus); CfLog(level, OUTPUT, routine); } } /* ** nameToUUID() ** ** Convert provided name to uuid as known by the registry. Status ** returned via status parameter. */ static void nameToUUID(sec_rgy_name_t name, sec_acl_entry_type_t type, uuid_p_t uuid, error_status_t * status) { sec_rgy_handle_t rgySite; error_status_t rgyStatus; error_status_t fooStatus; sec_rgy_site_open((unsigned_char_p_t)"/.:", &rgySite, &rgyStatus); if (rgyStatus == error_status_ok) { switch (type) { case sec_acl_e_type_user: { sec_id_parse_name(rgySite, name, NULL, NULL, NULL, uuid, &rgyStatus); if (rgyStatus != error_status_ok) { logError("sec_rgy_parse_name", cferror, rgyStatus); } } break; case sec_acl_e_type_group: { sec_id_parse_group(rgySite, name, NULL, NULL, NULL, uuid, &rgyStatus); if (rgyStatus != error_status_ok) { logError("sec_rgy_parse_group", cferror, rgyStatus); } } break; case sec_acl_e_type_foreign_user: { CfLog(cferror, "acl type sec_acl_e_type_foreign_user not supported yet.\n", ""); rgyStatus = sec_acl_not_implemented; } break; case sec_acl_e_type_foreign_group: { CfLog(cferror, "acl type sec_acl_e_type_foreign_group not supported yet\n", ""); rgyStatus = sec_acl_not_implemented; } break; case sec_acl_e_type_foreign_other: { CfLog(cferror, "acl type sec_acl_e_type_foreign_other not supported yet.\n", ""); rgyStatus = sec_acl_not_implemented; } break; default: { CfLog(cferror, "Unknown acl type in nameToUUID!\n", ""); rgyStatus = sec_acl_invalid_acl_type; } break; } sec_rgy_site_close(rgySite, &fooStatus); if (fooStatus != error_status_ok) { logError("sec_rgy_site_close", cferror, fooStatus); } } else { logError("sec_rgy_site_open", cferror, rgyStatus); } *status = rgyStatus; } /* ** setupACL() ** ** dceACLData structure setup routine. Allocate new ACL structure of the ** requested size at aclData->new, saves old value of aclData->list.sec_acls[0] ** at aclData->old for subsequent usage by resetACL(), sets ** aclData->list.sec_acls[0] to the new ACL structure allocated for ** replacement usage. ** ** Status returned via provided status parameter. */ static void setupACL(int aclNumEntries, struct aclData * aclData, error_status_t * status) { if ( (aclData->new = (sec_acl_t *)calloc(1, sizeof(sec_acl_t))) && (aclData->new->sec_acl_entries = (sec_acl_entry_t *)calloc(aclNumEntries, sizeof(sec_acl_entry_t))) ) { aclData->old = aclData->list.sec_acls[0]; aclData->new->default_realm = aclData->old->default_realm; aclData->new->sec_acl_manager_type = aclData->old->sec_acl_manager_type; aclData->new->num_entries = 0; aclData->list.sec_acls[0] = aclData->new; *status = error_status_ok; } else { CfLog(cferror, "Unable to allocate ACL storage\n", ""); *status = sec_acl_cant_allocate_memory; } } /* ** resetACL() ** ** Return dceACLData structure to initial value, i.e., return the original ** primary ACL to the appropriate location and free the modified new ** ACL that was allocated by setupACL(). ** ** Notes: This routine should only be called after a successful call to ** setupACL(). */ static void resetACL(struct aclData * aclData) { aclData->list.sec_acls[0] = aclData->old; free(aclData->new->sec_acl_entries); free(aclData->new); } /* ** equalACLEntry() ** ** Compare two sec_acl_entry_ts, returning TRUE if they match in ** permissions, type, and uuid, FALSE otherwise. */ static boolean32 equalACLEntry(sec_acl_entry_t * lhs, sec_acl_entry_t * rhs, error_status_t * status) { return ((lhs->perms == rhs->perms) && (lhs->entry_info.entry_type == rhs->entry_info.entry_type) && (uuid_equal(&(lhs->entry_info.tagged_union.id.uuid), &(rhs->entry_info.tagged_union.id.uuid), status))); } /* ** equalACLEntries() ** ** Compare to sec_acl_ts, returning TRUE if they match in number and ** composition of ACL entries, FALSE otherwise. ** ** Notes: The provided sec_acl_ts may have equivalent entries, but it ** is somewhat unlikely that they are in equivalent order; thus ** an exhaustive search must be performed to determine equality. */ static boolean32 equalACLEntries(sec_acl_t * lhs, sec_acl_t * rhs, error_status_t * status) { boolean32 equalEntry; unsigned32 lhsIdx; unsigned32 rhsIdx; /* Obviously, if the number of entries in the ACLS aren't equal, then ** they aren't equal ACLs. */ if (lhs->num_entries != rhs->num_entries) return(FALSE); /* ** ACL entries have the same number of entries, which is promising. ** search the rhs entries for items exactly matching all lhs entries. ** If we don't find an equivalent rhs entry for a given lhs entry, ** then the ACLs aren't equal; return immediately in this case. */ for (lhsIdx = 0; lhsIdx < lhs->num_entries; lhsIdx++) { equalEntry = FALSE; for (rhsIdx = 0; rhsIdx < rhs->num_entries; rhsIdx++) { if (equalACLEntry(&(lhs->sec_acl_entries[lhsIdx]), &(rhs->sec_acl_entries[rhsIdx]), status)) { equalEntry = TRUE; break; } } if (equalEntry == FALSE) return(FALSE); } /* If we've made it this far, then either the ACLs are equal ** in all respects, or some error occurred, as indicated by ** the status parameter. Let the caller deal with it... */ return(TRUE); } /* ** copyACLEntries() ** ** Copy source sec_acl_t entries to target sec_acl_t. ** ** Notes: Target must contain adequate storage space. */ static void copyACLEntries(sec_acl_t const * source, sec_acl_t * target) { int numEntries = source->num_entries; int curEntry; target->num_entries = numEntries; for (curEntry = 0; curEntry < numEntries; curEntry++) { target->sec_acl_entries[curEntry].entry_info.entry_type = source->sec_acl_entries[curEntry].entry_info.entry_type; target->sec_acl_entries[curEntry].perms = source->sec_acl_entries[curEntry].perms; target->sec_acl_entries[curEntry].entry_info.tagged_union = source->sec_acl_entries[curEntry].entry_info.tagged_union; } } /*****************************************************************************/ #endif /* HAVE_DCE_DACLIF_H */ cfengine-2.2.10/src/globals.c0000644000175000001440000011453111144464130012650 00000000000000/* cfengine for GNU Copyright (C) 1995/6 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* GLOBAL variables for cfengine */ /* */ /* Although these are global in C, they are layed out in */ /* terms of their ownership to certain logical "objects", */ /* to illustrate the object oriented structure. */ /* */ /*******************************************************************/ #include "../pub/getopt.h" #include "cf.defs.h" #define PUBLIC /* Just for fun */ #define PRIVATE #define PROTECTED /*******************************************************************/ /* Pthreads */ /*******************************************************************/ #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP pthread_attr_t PTHREADDEFAULTS; pthread_mutex_t MUTEX_COUNT = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; pthread_mutex_t MUTEX_HOSTNAME = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; #else # if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) pthread_attr_t PTHREADDEFAULTS; pthread_mutex_t MUTEX_COUNT = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t MUTEX_HOSTNAME = PTHREAD_MUTEX_INITIALIZER; # endif #endif /*******************************************************************/ /* */ /* Global : Truly global variables here */ /* */ /*******************************************************************/ char VBUFF[CF_BUFSIZE]; /* General workspace, contents not guaranteed */ char OUTPUT[CF_BUFSIZE*2]; int AUTHENTICATED = false; int CHECKSUMUPDATES = false; int PASS; char *CHECKSUMDB; char PADCHAR = ' '; char CONTEXTID[32]; char CFPUBKEYFILE[CF_BUFSIZE]; char CFPRIVKEYFILE[CF_BUFSIZE]; char AVDB[CF_MAXVARSIZE]; char CFWORKDIR[CF_BUFSIZE]; char PIDFILE[CF_BUFSIZE]; RSA *PRIVKEY = NULL, *PUBKEY = NULL; #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP pthread_mutex_t MUTEX_SYSCALL = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; pthread_mutex_t MUTEX_LOCK = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; #else # if defined HAVE_PTHREAD_H && (defined HAVE_LIBPTHREAD || defined BUILDTIN_GCC_THREAD) pthread_mutex_t MUTEX_SYSCALL = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t MUTEX_LOCK = PTHREAD_MUTEX_INITIALIZER; # endif #endif /*******************************************************************/ /* */ /* cfd.main object : the root application object */ /* */ /* */ /*******************************************************************/ PROTECTED struct Auth *VADMIT = NULL; PROTECTED struct Auth *VADMITTOP = NULL; PROTECTED struct Auth *VDENY = NULL; PROTECTED struct Auth *VDENYTOP = NULL; /*******************************************************************/ /* */ /* cfengine.main object : the root application object */ /* */ /*******************************************************************/ PUBLIC char *COPYRIGHT = "Free Software Foundation 1994-\nDonated by Mark Burgess, Oslo University College, Norway"; PRIVATE char *VPRECONFIG = "cf.preconf"; PRIVATE char *VRCFILE = "cfrc"; PUBLIC char *VSETUIDLOG = NULL; PUBLIC char *VARCH = NULL; PUBLIC char *VARCH2 = NULL; PUBLIC char *VREPOSITORY = NULL; PUBLIC char *COMPRESSCOMMAND = NULL; PUBLIC char VPREFIX[CF_MAXVARSIZE]; PUBLIC char VINPUTFILE[CF_BUFSIZE]; PUBLIC char VCURRENTFILE[CF_BUFSIZE]; PUBLIC char VLOGFILE[CF_BUFSIZE]; PUBLIC char ALLCLASSBUFFER[CF_ALLCLASSSIZE]; PUBLIC char ELSECLASSBUFFER[CF_BUFSIZE]; PUBLIC char FAILOVERBUFFER[CF_BUFSIZE]; PUBLIC char CHROOT[CF_BUFSIZE]; PUBLIC char EDITBUFF[CF_BUFSIZE]; PUBLIC short AUDIT = false; PUBLIC short DEBUG = false; PUBLIC short D1 = false; PUBLIC short D2 = false; PUBLIC short D3 = false; PUBLIC short D4 = false; PUBLIC short LASTSEEN = true; PUBLIC short VERBOSE = false; PUBLIC short INFORM = false; PUBLIC short CHECK = false; PUBLIC short EXCLAIM = true; PUBLIC short COMPATIBILITY_MODE = false; PUBLIC short LOGGING = false; PUBLIC short INFORM_save; PUBLIC short LOGGING_save; PUBLIC short CFPARANOID = false; PUBLIC short SHOWACTIONS = false; PUBLIC short LOGTIDYHOMEFILES = true; PUBLIC short UPDATEONLY = false; PUBLIC short SKIPIDENTIFY = false; PUBLIC short ALL_SINGLECOPY = false; PUBLIC short FULLENCRYPT = false; PUBLIC char FORK = 'n'; PRIVATE int RPCTIMEOUT = 60; /* seconds */ PUBLIC pid_t ALARM_PID = -1; PROTECTED int SENSIBLEFILECOUNT = 2; PROTECTED int SENSIBLEFSSIZE = 1000; PUBLIC time_t CFSTARTTIME; PUBLIC time_t CFINITSTARTTIME; PUBLIC dev_t ROOTDEVICE = 0; PUBLIC char STR_CFENGINEPORT[16]; PUBLIC unsigned short SHORT_CFENGINEPORT; PUBLIC enum classes VSYSTEMHARDCLASS; PUBLIC struct Item VDEFAULTBINSERVER = /* see GetNameInfo(), main.c */ { 'n', NULL, NULL, 0, 0, 0, NULL }; PUBLIC struct utsname VSYSNAME; /* For uname (2) */ PUBLIC mode_t DEFAULTMODE = (mode_t) 0755; PUBLIC mode_t DEFAULTSYSTEMMODE = (mode_t) 0644; PROTECTED int VIFELAPSED = 1; PROTECTED int VEXPIREAFTER = 120; PROTECTED int VDEFAULTIFELAPSED = 1; PROTECTED int VDEFAULTEXPIREAFTER = 120; /* minutes */ PUBLIC struct cfagent_connection *CONN = NULL; PUBLIC struct Item *VEXCLUDECACHE = NULL; PUBLIC struct Item *QUERYVARS = NULL; PUBLIC struct cfObject *OBJECTLIST = NULL; PUBLIC struct Item *IPADDRESSES = NULL; /*******************************************************************/ /* Anomaly */ /*******************************************************************/ struct sock ECGSOCKS[ATTR] = /* extended to map old to new using enum*/ { {"137","netbiosns",ob_netbiosns_in,ob_netbiosns_out}, {"138","netbiosdgm",ob_netbiosdgm_in,ob_netbiosdgm_out}, {"139","netbiosssn",ob_netbiosssn_in,ob_netbiosssn_out}, {"194","irc",ob_irc_in,ob_irc_out}, {"5308","cfengine",ob_cfengine_in,ob_cfengine_out}, {"2049","nfsd",ob_nfsd_in,ob_nfsd_out}, {"25","smtp",ob_smtp_in,ob_smtp_out}, {"80","www",ob_www_in,ob_www_out}, {"21","ftp",ob_ftp_in,ob_ftp_out}, {"22","ssh",ob_ssh_in,ob_ssh_out}, {"443","wwws",ob_wwws_in,ob_wwws_out} }; char *TCPNAMES[CF_NETATTR] = { "icmp", "udp", "dns", "tcpsyn", "tcpack", "tcpfin", "misc" }; char *OBS[CF_OBSERVABLES][2] = { "users","Users logged in", "rootprocs","Privileged system processes", "otherprocs","Non-privileged process", "diskfree","Free disk on / partition", "loadavg","% kernel load utilization", "netbiosns_in","netbios name lookups (in)", "netbiosns_out","netbios name lookups (out)", "netbiosdgm_in","netbios name datagrams (in)", "netbiosdgm_out","netbios name datagrams (out)", "netbiosssn_in","netbios name sessions (in)", "netbiosssn_out","netbios name sessions (out)", "irc_in","IRC connections (in)", "irc_out","IRC connections (out)", "cfengine_in","cfengine connections (in)", "cfengine_out","cfengine connections (out)", "nfsd_in","nfs connections (in)", "nfsd_out","nfs connections (out)", "smtp_in","smtp connections (in)", "smtp_out","smtp connections (out)", "www_in","www connections (in)", "www_out","www connections (out)", "ftp_in","ftp connections (in)", "ftp_out","ftp connections (out)", "ssh_in","ssh connections (in)", "ssh_out","ssh connections (out)", "wwws_in","wwws connections (in)", "wwws_out","wwws connections (out)", "icmp_in","ICMP packets (in)", "icmp_out","ICMP packets (out)", "udp_in","UDP dgrams (in)", "udp_out","UDP dgrams (out)", "dns_in","DNS requests (in)", "dns_out","DNS requests (out)", "tcpsyn_in","TCP sessions (in)", "tcpsyn_out","TCP sessions (out)", "tcpack_in","TCP acks (in)", "tcpack_out","TCP acks (out)", "tcpfin_in","TCP finish (in)", "tcpfin_out","TCP finish (out)", "tcpmisc_in","TCP misc (in)", "tcpmisc_out","TCP misc (out)", "webaccess","Webserver hits", "weberrors","Webserver errors", "syslog","New log entries (Syslog)", "messages","New log entries (messages)", "temp0","CPU Temperature 0", "temp1","CPU Temperature 1", "temp2","CPU Temperature 2", "temp3","CPU Temperature 3", "cpu","%CPU utilization (all)", "cpu0","%CPU utilization 0", "cpu1","%CPU utilization 1", "cpu2","%CPU utilization 2", "cpu3","%CPU utilization 3", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", "spare","unused", }; /*******************************************************************/ /* Methods */ /*******************************************************************/ PUBLIC int GOTMETHODARGS = false; PUBLIC struct Item *METHODARGS = NULL; PUBLIC char ** METHODARGV = NULL; PUBLIC int METHODARGC = 0; PRIVATE char *VMETHODPROTO[] = { "NAME:", "TRUSTEDFILE:", "TIMESTAMP:", "REPLYTO:", "SENDCLASS:", "ATTACH-ARG:", "ISREPLY:", NULL }; PUBLIC char METHODNAME[CF_BUFSIZE]; PUBLIC char METHODFILENAME[CF_BUFSIZE]; PUBLIC char METHODREPLYTO[CF_BUFSIZE]; PUBLIC char METHODFOR[CF_BUFSIZE]; PUBLIC char METHODFORCE[CF_BUFSIZE]; PUBLIC struct Item *METHODRETURNVARS = NULL; PUBLIC struct Item *METHODRETURNCLASSES = NULL; PUBLIC char METHODMD5[CF_BUFSIZE]; /*******************************************************************/ /* Data/list structures - root pointers */ /*******************************************************************/ PUBLIC struct Item *ABORTHEAP = NULL; PROTECTED struct Item *VTIMEZONE = NULL; PROTECTED struct Item *VMOUNTLIST = NULL; PROTECTED struct Item *VEXCLUDECOPY = NULL; PROTECTED struct Item *VAUTODEFINE = NULL; PROTECTED struct Item *VEXCLUDELINK = NULL; PROTECTED struct Item *VCOPYLINKS = NULL; PROTECTED struct Item *VLINKCOPIES = NULL; PROTECTED struct Item *VEXCLUDEPARSE = NULL; PROTECTED struct Item *VCPLNPARSE = NULL; PROTECTED struct Item *VINCLUDEPARSE = NULL; PROTECTED struct Item *VIGNOREPARSE = NULL; PROTECTED struct Item *VSERVERLIST = NULL; PROTECTED struct Item *VRPCPEERLIST = NULL; PROTECTED struct Item *VREDEFINES = NULL; PROTECTED struct Item *VHEAP = NULL; /* Points to the base of the attribute heap */ PROTECTED struct Item *VNEGHEAP = NULL; PROTECTED struct Mountables *VMOUNTABLES = NULL; /* Points to the list of mountables */ PROTECTED struct Mountables *VMOUNTABLESTOP = NULL; PUBLIC struct cfObject *VOBJTOP = NULL; PUBLIC struct cfObject *VOBJ = NULL; PROTECTED struct Item *VALERTS = NULL; PROTECTED struct Item *VMOUNTED = NULL; PROTECTED struct Tidy *VTIDY = NULL; /* Points to the list of tidy specs */ PROTECTED struct Tidy *VTIDYTOP = NULL; PROTECTED struct Item *VPROCESSES = NULL; /* Points to proc list */ PROTECTED struct Disk *VREQUIRED = NULL; /* List of required file systems */ PROTECTED struct Disk *VREQUIREDTOP = NULL; PROTECTED struct ShellComm *VSCRIPT = NULL; /* List of scripts to execute */ PROTECTED struct ShellComm *VSCRIPTTOP = NULL; PROTECTED struct ShellComm *VSCLI = NULL; /* List of scli coms to execute */ PROTECTED struct ShellComm *VSCLITOP = NULL; PROTECTED struct Interface *VIFLIST = NULL; PROTECTED struct Interface *VIFLISTTOP = NULL; PROTECTED struct Mounted *MOUNTED = NULL; /* Files systems already mounted */ PROTECTED struct MiscMount *VMISCMOUNT = NULL; PROTECTED struct MiscMount *VMISCMOUNTTOP = NULL; PROTECTED struct Item *VBINSERVERS = NULL; PROTECTED struct Link *VLINK = NULL; PROTECTED struct Link *VLINKTOP = NULL; PROTECTED struct File *VFILE = NULL; PROTECTED struct File *VFILETOP = NULL; PROTECTED struct Image *VIMAGE = NULL; PROTECTED struct Image *VIMAGETOP=NULL; PROTECTED struct Method *VMETHODS = NULL; PROTECTED struct Method *VMETHODSTOP=NULL; PROTECTED struct Item *VHOMESERVERS = NULL; PROTECTED struct Item *VSETUIDLIST = NULL; PROTECTED struct Disable *VDISABLELIST = NULL; PROTECTED struct Disable *VDISABLETOP = NULL; PROTECTED struct File *VMAKEPATH = NULL; PROTECTED struct File *VMAKEPATHTOP = NULL; PROTECTED struct Link *VCHLINK = NULL; PROTECTED struct Link *VCHLINKTOP = NULL; PROTECTED struct Item *VIGNORE = NULL; PROTECTED struct Item *VHOMEPATLIST = NULL; PROTECTED struct Item *EXTENSIONLIST = NULL; PROTECTED struct Item *SUSPICIOUSLIST = NULL; PROTECTED struct Item *SCHEDULE = NULL; PROTECTED struct Item *SPOOLDIRLIST = NULL; PROTECTED struct Item *NONATTACKERLIST = NULL; PROTECTED struct Item *MULTICONNLIST = NULL; PROTECTED struct Item *TRUSTKEYLIST = NULL; PROTECTED struct Item *DHCPLIST = NULL; PROTECTED struct Item *ALLOWUSERLIST = NULL; PROTECTED struct Item *SKIPVERIFY = NULL; PROTECTED struct Item *ATTACKERLIST = NULL; PROTECTED struct Item *MOUNTOPTLIST = NULL; PROTECTED struct Item *VRESOLVE = NULL; PROTECTED struct Item *VIMPORT = NULL; PROTECTED struct Item *VACTIONSEQ=NULL; PROTECTED struct Item *VACCESSLIST=NULL; PROTECTED struct Item *VADDCLASSES=NULL; /* Action sequence defs */ PROTECTED struct Item *VALLADDCLASSES=NULL; /* All classes */ PROTECTED struct Item *VJUSTACTIONS=NULL; PROTECTED struct Item *VAVOIDACTIONS=NULL; PROTECTED struct Item *VDEFAULTROUTE=NULL; PROTECTED struct UnMount *VUNMOUNT=NULL; PROTECTED struct UnMount *VUNMOUNTTOP=NULL; PROTECTED struct Edit *VEDITLIST=NULL; PROTECTED struct Edit *VEDITLISTTOP=NULL; PROTECTED struct Filter *VFILTERLIST=NULL; PROTECTED struct Filter *VFILTERLISTTOP=NULL; PROTECTED struct CFACL *VACLLIST=NULL; PROTECTED struct CFACL *VACLLISTTOP=NULL; PROTECTED struct Strategy *VSTRATEGYLIST=NULL; PROTECTED struct Strategy *VSTRATEGYLISTTOP=NULL; PROTECTED struct Item *VCLASSDEFINE=NULL; PROTECTED struct Process *VPROCLIST=NULL; PROTECTED struct Process *VPROCTOP=NULL; PROTECTED struct Item *VREPOSLIST=NULL; PROTECTED struct Package *VPKG=NULL; /* Head of the packages item list */ PROTECTED struct Package *VPKGTOP=NULL; /* The last packages item we added */ /*********************************************************************/ /* Resource names */ /*********************************************************************/ PRIVATE char *VRESOURCES[] = /* one for each major variable in class.c */ { "mountcomm", "unmountcomm", "ethernet", "mountopts", "unused", "fstab", "maildir", "netstat", "pscomm", "psopts", NULL }; /*******************************************************************/ /* Reserved variables */ /*******************************************************************/ PROTECTED char VMAILSERVER[CF_BUFSIZE]; PROTECTED char VFACULTY[CF_MAXVARSIZE]; PROTECTED char VDOMAIN[CF_MAXVARSIZE]; PROTECTED char VSYSADM[CF_MAXVARSIZE]; PROTECTED char VNETMASK[CF_MAXVARSIZE]; PROTECTED char VBROADCAST[CF_MAXVARSIZE]; PROTECTED char VNFSTYPE[CF_MAXVARSIZE]; PROTECTED char VFQNAME[CF_MAXVARSIZE]; PROTECTED char VUQNAME[CF_MAXVARSIZE]; PROTECTED char LOGFILE[CF_MAXVARSIZE]; PROTECTED char VYEAR[5]; PROTECTED char VDAY[3]; PROTECTED char VMONTH[4]; PROTECTED char VHR[3]; PROTECTED char VMINUTE[3]; PROTECTED char VSEC[3]; /*********************************************************************/ /* Actions */ /*********************************************************************/ PRIVATE char *ACTIONTEXT[] = { "", "Control Defintions:", "Alerts:", "Groups:", "File Imaging:", "Resolve:", "Processes:", "Files:", "Tidy:", "Home Servers:", "Binary Servers:", "Mail Server:", "Required Filesystems", "Disks (Required)", "Reading Mountables", "Links:", "Import files:", "User Shell Commands:", "Rename or Disable Files:", "Rename files:", "Make Directory Path:", "Ignore File Paths:", "Broadcast Mode:", "Default Packet Route:", "Miscellaneous Mountables:", "Edit Simple Text File:", "Unmount filesystems:", "Admit network access:", "Deny network access:", "Access control lists:", "Additional network interfaces:", "Search filter objects:", "Strategies:", "Package Checks:", "Method Function Calls", "SCLI SNMP Agent Calls", NULL }; PRIVATE char *ACTIONID[] = /* The actions which may be specified as indexed */ { /* macros in the "special" section of the file */ "", "control", "alerts", "groups", "copy", "resolve", "processes", "files", "tidy", "homeservers", "binservers", "mailserver", "required", "disks", "mountables", "links", "import", "shellcommands", "disable", "rename", "directories", "ignore", "broadcast", "defaultroute", "miscmounts", "editfiles", "unmount", "admit", "deny", "acl", "interfaces", "filters", "strategies", "packages", "methods", "scli", NULL }; PRIVATE char *BUILTINS[] = /* The actions which may be specified as indexed */ { "", "randomint", "isnewerthan", "accessedbefore", "changedbefore", "fileexists", "isdir", "islink", "isplain", "execresult", "execshellresult", "returnszero", "returnszeroshell", "iprange", "hostrange", "isdefined", "strcmp", "regcmp", "classmatch", "showstate", "friendstatus", "readfile", "returnvariables", "returnclasses", "syslog", "setstate", "unsetstate", "prepmodule", "a", "readarray", "readtable", "readlist", "selectpartitionleader", "selectpartitionneighbours", "selectpartitionneighbors", "isgreaterthan", "islessthan", "readtcp", "printfile", "userexists", "groupexists", NULL }; /*********************************************************************/ /* file/image actions */ /*********************************************************************/ PROTECTED char *FILEACTIONTEXT[] = { "warnall", "warnplain", "warndirs", "fixall", "fixplain", "fixdirs", "touch", "linkchildren", "create", "compress", "alert", NULL }; /*********************************************************************/ PRIVATE char *ACTIONSEQTEXT[] = { "directories", "links", "mailcheck", "required", "disks", "tidy", "shellcommands", "files", "disable", "rename", "addmounts", "editfiles", "mountall", "unmount", "resolve", "copy", "netconfig", "checktimezone", "mountinfo", "processes", "packages", "methods", "none", NULL }; /*********************************************************************/ /* Package check actions */ /*********************************************************************/ /* The sense of the comparison (greater than, less than...) */ PRIVATE char *CMPSENSETEXT[] = { "eq", "gt", "lt", "ge", "le", "ne", "none", NULL }; PRIVATE char *CMPSENSEOPERAND[] = { "=", ">", "<", ">=", "<=", "!=", NULL, NULL }; /*********************************************************************/ /* The names of the available package managers */ PRIVATE char *PKGMGRTEXT[] = { "rpm", "dpkg", /* aptget ? */ "sun", /* pkginfo/pkgadd/pkgrm */ "aix", /* lslpp/installp */ "portage", "freebsd", NULL }; /*********************************************************************/ PRIVATE char *PKGACTIONTEXT[] = { "install", "remove", "upgrade", "fix", NULL }; /*******************************************************************/ /* */ /* parse object : variables belonging to the Parse object */ /* */ /*******************************************************************/ PUBLIC short ISCFENGINE; /* for re-using parser code in cfd */ PUBLIC struct Audit *AUDITPTR; PUBLIC struct Audit *VAUDIT = NULL; PUBLIC short SHOWDB = false; PUBLIC short PARSING = false; PUBLIC short INSTALLALL = false; PRIVATE short TRAVLINKS = false; PRIVATE short PTRAVLINKS = false; PRIVATE short DEADLINKS = true; PRIVATE short DONTDO = false; PRIVATE short IFCONF = true; PRIVATE short PARSEONLY = false; PRIVATE short GOTMOUNTINFO = true; PRIVATE short NOMOUNTS = false; PRIVATE short NOMODULES = false; PRIVATE short NOFILECHECK = false; PRIVATE short NOTIDY = false; PRIVATE short NOSCRIPTS = false; PRIVATE short PRSYSADM = false; PRIVATE short PRSCHEDULE = false; PRIVATE short MOUNTCHECK = false; PRIVATE short NOPROCS = false; PRIVATE short NOMETHODS = false; PRIVATE short NOEDITS = false; PRIVATE short KILLOLDLINKS = false; PRIVATE short IGNORELOCK = false; PRIVATE short NOPRECONFIG = false; PRIVATE short WARNINGS = true; PRIVATE short NONALPHAFILES = false; PRIVATE short MINUSF = false; PRIVATE short NOLINKS = false; PRIVATE short ENFORCELINKS = false; PRIVATE short NOCOPY = false; PRIVATE short FORCENETCOPY = false; PRIVATE short SILENT=false; PRIVATE short EDITVERBOSE=false; PRIVATE short LINKSILENT; PRIVATE short ROTATE=0; PRIVATE short USEENVIRON=false; PRIVATE short PROMATCHES=-1; PRIVATE short EDABORTMODE=false; PRIVATE short UNDERSCORE_CLASSES=false; PRIVATE short NOHARDCLASSES=false; PRIVATE short NOSPLAY = false; PRIVATE short DONESPLAY = false; PUBLIC struct Item *VSINGLECOPY = NULL; PROTECTED struct Item *VACLBUILD = NULL; PROTECTED struct Item *VFILTERBUILD = NULL; PROTECTED struct Item *VSTRATEGYBUILD = NULL; PRIVATE char NOABSPATH = 'n'; PRIVATE char CHKROOT = 'n'; PRIVATE char TIDYDIRS = 'n'; PRIVATE char XDEV = 'n'; PRIVATE char RXDIRS = 'y'; PRIVATE char IMAGEBACKUP='y'; PRIVATE char TRUSTKEY = 'n'; PRIVATE char PRESERVETIMES = 'n'; PRIVATE char TYPECHECK = 'y'; PRIVATE char SCAN = 'n'; PRIVATE char LINKTYPE = 's'; PRIVATE char AGETYPE = 'a'; PRIVATE char COPYTYPE = 't'; PRIVATE char DEFAULTCOPYTYPE = 't'; PRIVATE char REPOSCHAR = '_'; PRIVATE char LISTSEPARATOR = ':'; PRIVATE char LINKDIRS = 'k'; PRIVATE char DISCOMP = '='; PRIVATE char USESHELL = 'y'; /* yes or no or dumb */ PRIVATE char PREVIEW = 'n'; /* yes or no */ PRIVATE char PURGE = 'n'; PRIVATE char LOGP = 'd'; /* y,n,d=default*/ PRIVATE char INFORMP = 'd'; PRIVATE char AUDITP = 'd'; PRIVATE char MOUNTMODE = 'w'; /* o or w for rw/ro*/ PRIVATE char DELETEDIR = 'y'; /* t=true */ PRIVATE char DELETEFSTAB = 'y'; PRIVATE char FORCE = 'n'; PRIVATE char FORCEIPV4 = 'n'; PRIVATE char FORCELINK = 'n'; PRIVATE char FORCEDIRS = 'n'; PRIVATE char STEALTH = 'n'; PRIVATE char CHECKSUM = 'n'; /* n,m,s */ PRIVATE char COMPRESS = 'n'; PRIVATE char *FINDERTYPE; PRIVATE char *PARSEMETHODRETURNCLASSES; PRIVATE char *VUIDNAME; PRIVATE char *VGIDNAME; PRIVATE char *FILTERNAME; PRIVATE char *STRATEGYNAME; PRIVATE char *GROUPBUFF; PRIVATE char *ACTIONBUFF; PRIVATE char *CURRENTOBJECT; PRIVATE char *CURRENTITEM; PRIVATE char *CLASSBUFF; PRIVATE char *LINKFROM; PRIVATE char *LINKTO; PRIVATE char *ERROR; PRIVATE char *MOUNTFROM; PRIVATE char *MOUNTONTO; PRIVATE char *MOUNTOPTS; PRIVATE char *DESTINATION; PRIVATE char *IMAGEACTION; PRIVATE char VIFNAME[16]; PRIVATE char VIFNAMEOVERRIDE[16]; PRIVATE char *CHDIR; PRIVATE char *LOCALREPOS; PRIVATE char *EXPR; PRIVATE char *CURRENTAUTHPATH; PRIVATE char *RESTART; PRIVATE char *FILTERDATA; PRIVATE char *STRATEGYDATA; PRIVATE char *PKGVER; /* value of ver option in packages: */ PRIVATE short PROSIGNAL; PRIVATE char PROACTION; PRIVATE char PROCOMP; PRIVATE char IMGCOMP; PRIVATE int IMGSIZE; PUBLIC int ERRORCOUNT = 0; PUBLIC int LINENUMBER = 1; PRIVATE int HAVEUID = 0; PRIVATE int DISABLESIZE=99999999; PRIVATE int TIDYSIZE=0; PRIVATE int VRECURSE; PRIVATE int VAGE; PRIVATE int VTIMEOUT=0; PRIVATE int PIFELAPSED=0; PRIVATE int PEXPIREAFTER=0; PRIVATE mode_t UMASK=0; PRIVATE mode_t PLUSMASK; PRIVATE mode_t MINUSMASK; PRIVATE u_long PLUSFLAG; PRIVATE u_long MINUSFLAG; /* Parsing flags etc */ PUBLIC enum actions ACTION = none; PRIVATE enum vnames CONTROLVAR = nonexistentvar; PRIVATE enum fileactions FILEACTION = warnall; PRIVATE enum cmpsense CMPSENSE = cmpsense_eq; /* Comparison for packages: */ PRIVATE enum pkgmgrs PKGMGR = pkgmgr_none; /* Which package mgr to query */ PRIVATE enum pkgmgrs DEFAULTPKGMGR = pkgmgr_none; PRIVATE enum pkgactions PKGACTION = pkgaction_none; PRIVATE flag ACTION_IS_LINK = false; PRIVATE flag ACTION_IS_LINKCHILDREN = false; PRIVATE flag MOUNT_ONTO = false; PRIVATE flag MOUNT_FROM = false; PRIVATE flag HAVE_RESTART = false; PRIVATE flag ACTIONPENDING = false; PRIVATE flag HOMECOPY = false; PRIVATE char ENCRYPT = 'n'; PRIVATE char VERIFY = 'n'; PRIVATE char COMPATIBILITY = 'n'; /* * HvB: Bas van der Vlies */ PRIVATE flag CF_MOUNT_RO = false; PRIVATE char *COMMATTRIBUTES[] = { "findertype", "recurse", "mode", "owner", "group", "age", "action", "pattern", "links", "type", "destination", "force", "forcedirs", "forceipv4", "forcereplyto", "backup", "rotate", "size", "matches", "signal", "exclude", "copy", "symlink", "copytype", "linktype", "include", "dirlinks", "rmdirs", "server", "define", "elsedefine", "failover", "timeout", "freespace", "nofile", "acl", "purge", "useshell", "syslog", "inform", "ipv4", "netmask", "broadcast", "ignore", "deletedir", "deletefstab", "stealth", "checksum", "flags", "encrypt", "verify", "root", "typecheck", "umask", "compress", "filter", "background", "chdir", "chroot", "preview", "repository", "timestamps", "trustkey", "oldserver", "mountoptions", /* HvB : Bas van der Vlies */ "readonly", /* HvB : Bas van der Vlies */ "version", "cmp", "pkgmgr", "xdev", "rxdirs", "returnvars", "returnclasses", "sendclasses", "ifelapsed", "expireafter", "scanarrivals", "noabspath", "checkroot", "audit", NULL }; PUBLIC char *VFILTERNAMES[] = { "Result", /* quoted string of combinatorics, classes of each result */ "Owner", "Group", "Mode", "Type", "FromCtime", "ToCtime", "FromMtime", "ToMtime", "FromAtime", "ToAtime", "FromSize", "ToSize", "ExecRegex", "NameRegex", "DefineClasses", "ElseDefineClasses", "ExecProgram", "IsSymLinkTo", "PID", "PPID", "PGID", "RSize", "VSize", "Status", "Command", "FromTTime", "ToTTime", "FromSTime", "ToSTime", "TTY", "Priority", "Threads", "NoFilter", NULL }; /*******************************************************************/ /* */ /* editfiles object : variables belonging to Editfiles */ /* editfiles uses Item */ /* */ /*******************************************************************/ PRIVATE char VEDITABORT[CF_BUFSIZE]; PUBLIC int EDITFILESIZE = 10000; PUBLIC int EDITBINFILESIZE = 10000000; PRIVATE int NUMBEROFEDITS = 0; PRIVATE int CURRENTLINENUMBER = 1; /* current line number in file */ PRIVATE struct Item *CURRENTLINEPTR = NULL; /* Ptr to current line */ PRIVATE struct re_pattern_buffer *SEARCHPATTBUFF; PRIVATE struct re_pattern_buffer *PATTBUFFER; PRIVATE int EDITGROUPLEVEL=0; PRIVATE int SEARCHREPLACELEVEL=0; PRIVATE int FOREACHLEVEL = 0; PRIVATE int AUTOCREATED = 0; PRIVATE char COMMENTSTART[CF_MAXVARSIZE]; PRIVATE char COMMENTEND[CF_MAXVARSIZE]; PUBLIC char *VEDITNAMES[] = { "NoEdit", "DeleteLinesStarting", "DeleteLinesNotStarting", "DeleteLinesContaining", "DeleteLinesNotContaining", "DeleteLinesMatching", "DeleteLinesNotMatching", "DeleteLinesStartingFileItems", "DeleteLinesContainingFileItems", "DeleteLinesMatchingFileItems", "DeleteLinesNotStartingFileItems", "DeleteLinesNotContainingFileItems", "DeleteLinesNotMatchingFileItems", "AppendIfNoSuchLine", "PrependIfNoSuchLine", "WarnIfNoSuchLine", "WarnIfLineMatching", "WarnIfNoLineMatching", "WarnIfLineStarting", "WarnIfLineContaining", "WarnIfNoLineStarting", "WarnIfNoLineContaining", "HashCommentLinesContaining", "HashCommentLinesStarting", "HashCommentLinesMatching", "SlashCommentLinesContaining", "SlashCommentLinesStarting", "SlashCommentLinesMatching", "PercentCommentLinesContaining", "PercentCommentLinesStarting", "PercentCommentLinesMatching", "ResetSearch", "SetSearchRegExp", "LocateLineMatching", "InsertLine", "AppendIfNoSuchLinesFromFile", "IncrementPointer", "ReplaceLineWith", "ExpandVariables", "DeleteToLineMatching", "HashCommentToLineMatching", "PercentCommentToLineMatching", "SetScript", "RunScript", "RunScriptIfNoLineMatching", "RunScriptIfLineMatching", "AppendIfNoLineMatching", "PrependIfNoLineMatching", "DeleteNLines", "EmptyEntireFilePlease", "GotoLastLine", "BreakIfLineMatches", "BeginGroupIfNoMatch", "BeginGroupIfMatch", "BeginGroupIfNoLineMatching", "BeginGroupIfNoSuchLine", "BeginGroupIfLineMatching", "EndGroup", "Append", "Prepend", "SetCommentStart", "SetCommentEnd", "CommentLinesMatching", "CommentLinesStarting", "CommentToLineMatching", "UnCommentToLineMatching", "CommentNLines", "UnCommentNLines", "ReplaceAll", "ReplaceFirst", "With", "SetLine", "FixEndOfLine", "AbortAtLineMatching", "UnsetAbort", "AutomountDirectResources", "UnCommentLinesContaining", "UnCommentLinesMatching", "InsertFile", "CommentLinesContaining", "BeginGroupIfFileIsNewer", "BeginGroupIfFileExists", "BeginGroupIfNoLineContaining", "BeginGroupIfLineContaining", "BeginGroupIfDefined", "BeginGroupIfNotDefined", "AutoCreate", "WarnIfFileMissing", "ForEachLineIn", "EndLoop", "ReplaceLinesMatchingField", "SplitOn", "AppendToLineIfNotContains", "DeleteLinesAfterThisMatching", "DefineClasses", "ElseDefineClasses", "CatchAbort", "Backup", "Syslog", "Inform", "Recurse", "EditMode", "WarnIfContainsString", "WarnIfContainsFile", "Ignore", "Exclude", "Include", "Repository", "Umask", "UseShell", "Filter", "DefineInGroup", "IfElapsed", "ExpireAfter", "EditSplit", "Audit", NULL }; /*******************************************************************/ /* */ /* Processes object : Process */ /* */ /* */ /*******************************************************************/ PUBLIC char *SIGNALS[highest_signal]; /* This is initialized to zero */ /*******************************************************************/ /* */ /* Network client-server object : Net */ /* */ /*******************************************************************/ PRIVATE char CFSERVER[CF_MAXVARSIZE]; PRIVATE char BINDINTERFACE[CF_BUFSIZE]; PRIVATE unsigned short PORTNUMBER = 0; PRIVATE char VIPADDRESS[18]; PRIVATE int CF_TIMEOUT = 10; PRIVATE int CFSIGNATURE = 0; PRIVATE char CFDES1[9]; PRIVATE char CFDES2[9]; PRIVATE char CFDES3[9]; PUBLIC char *PROTOCOL[] = { "EXEC", "AUTH", /* old protocol */ "GET", "OPENDIR", "SYNCH", "CLASSES", "MD5", "SMD5", "CAUTH", "SAUTH", "SSYNCH", "SGET", "VERSION", "SOPENDIR", NULL }; /*******************************************************************/ /* */ /* Adaptive lock object : Lock */ /* */ /*******************************************************************/ PUBLIC char VLOCKDIR[CF_BUFSIZE]; PUBLIC char VLOGDIR[CF_BUFSIZE]; PUBLIC char *VCANONICALFILE = NULL; PUBLIC FILE *VLOGFP = NULL; PUBLIC DB *AUDITDBP = NULL; PUBLIC char CFLOCK[CF_BUFSIZE]; PUBLIC char SAVELOCK[CF_BUFSIZE]; PUBLIC char CFLOG[CF_BUFSIZE]; PUBLIC char CFLAST[CF_BUFSIZE]; PUBLIC char LOCKDB[CF_BUFSIZE]; PUBLIC int PR_KEPT = 0; PUBLIC int PR_REPAIRED = 0; PUBLIC int PR_NOTKEPT = 0; /*******************************************************************/ /* */ /* Checksums */ /* */ /*******************************************************************/ /* These string lengths should not exceed CF_MAXDIGESTNAMELEN characters for packing */ PUBLIC char *CF_DIGEST_TYPES[9][2] = { "md5","m", "sha224","c", "sha256","C", "sha384","h", "sha512","H", "sha1","S", "sha","s", /* Should come last, since substring */ "best","b", NULL,NULL }; PUBLIC int CF_DIGEST_SIZES[9] = { CF_MD5_LEN, CF_SHA224_LEN, CF_SHA256_LEN, CF_SHA384_LEN, CF_SHA512_LEN, CF_SHA1_LEN, CF_SHA_LEN, CF_BEST_LEN, 0 }; /*******************************************************************/ /* */ /* SCLI interface */ /* */ /*******************************************************************/ PRIVATE char *CF_SCLICODES[CF_MAX_SCLICODES][2] = { "100","Arbitrary message", "200","Normal return code", "201","Return and exit the command loop", "300","Generic error return code", "301","No association to SNMP peer", "302","Command does not support XML", "400","Generic syntax error", "401","Syntax error in number of args", "402","Syntax error in regexp", "403","Syntax error in number", "404","Syntax error in value", "405","Syntax error in tokenizer", "406","Syntax error unknown command", "500","Snmp error return code", "501","Snmp name lookup error", NULL,NULL }; /* EOF */ cfengine-2.2.10/src/link.c0000644000175000001440000007053611036327731012175 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 "cf.defs.h" #include "cf.extern.h" /*********************************************************************/ /* TOOLKIT : links */ /*********************************************************************/ int LinkChildFiles(char *from,char *to,struct Link *ptr) { DIR *dirh; struct dirent *dirp; char pcwdto[CF_BUFSIZE],pcwdfrom[CF_BUFSIZE]; struct stat statbuf; int (*linkfiles)(char *from, char *to,struct Link *ptr); Debug("LinkChildFiles(%s,%s)\n",from,to); if (stat(to,&statbuf) == -1) { return(false); /* no error warning, since the higher level routine uses this */ } if ((dirh = opendir(to)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",to); CfLog(cferror,OUTPUT,"opendir"); return false; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,to,NULL)) { continue; } strcpy(pcwdto,to); /* Assemble pathnames */ AddSlash(pcwdto); if (BufferOverflow(pcwdto,dirp->d_name)) { FatalError("Can't build filename in LinkChildFiles"); } strcat(pcwdto,dirp->d_name); strcpy(pcwdfrom,from); AddSlash(pcwdfrom); if (BufferOverflow(pcwdfrom,dirp->d_name)) { FatalError("Can't build filename in LinkChildFiles"); } strcat(pcwdfrom,dirp->d_name); switch (ptr->type) { case 's': linkfiles = LinkFiles; break; case 'r': linkfiles = RelativeLink; break; case 'a': linkfiles = AbsoluteLink; break; case 'h': linkfiles = HardLinkFiles; break; default: printf("Internal error, link type was [%c]\n",ptr->type); continue; } (*linkfiles)(pcwdfrom,pcwdto,ptr); } closedir(dirh); return true; } /*********************************************************************/ void LinkChildren(char *path,char type,struct stat *rootstat,uid_t uid,gid_t gid,struct Link *ptr) /* -------------------------------------------------------------------- Here we try to break up the path into a part which will match the last element of a mounted filesytem mountpoint and the remainder after that. We parse the path backwards to get a math e.g. /fys/lib/emacs -> lib /emacs fys /lib/emacs /fys/lib/emacs we try to match lib and fys to the binserver list e.g. /mn/anyon/fys and hope for the best. If it doesn't match, tough! --------------------------------------------------------------------- */ { char *sp; char lastlink[CF_BUFSIZE],server[CF_BUFSIZE],from[CF_BUFSIZE],to[CF_BUFSIZE],relpath[CF_BUFSIZE]; char odir[CF_BUFSIZE]; DIR *dirh; struct dirent *dirp; struct stat statbuf; int matched = false; int (*linkfiles)(char *from, char *to, struct Link *ptr); Debug("LinkChildren(%s)\n",path); if (! S_ISDIR(rootstat->st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"File %s is not a directory: it has no children to link!\n",path); CfLog(cferror,OUTPUT,""); return; } Verbose("Linking the children of %s\n",path); for (sp = path+strlen(path); sp != path-1; sp--) { if (*(sp-1) == '/') { relpath[0] = '\0'; sscanf(sp,"%[^/]%s", lastlink,relpath); if (MatchAFileSystem(server,lastlink)) { strcpy(odir,server); if (BufferOverflow(odir,relpath)) { FatalError("culprit: LinkChildren()"); } strcat(odir,relpath); if ((dirh = opendir(odir)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory %s\n",path); CfLog(cferror,OUTPUT,"opendir"); return; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,odir,NULL)) { continue; } strcpy(from,path); AddSlash(from); if (BufferOverflow(from,dirp->d_name)) { FatalError("culprit: LinkChildren()"); } strcat(from,dirp->d_name); strcpy(to,odir); AddSlash(to); if (BufferOverflow(to,dirp->d_name)) { FatalError("culprit: LinkChildren()"); } strcat(to,dirp->d_name); Debug2("LinkChild from = %s to = %s\n",from,to); if (stat(to,&statbuf) == -1) { continue; } else { switch (type) { case 's': linkfiles = LinkFiles; break; case 'r': linkfiles = RelativeLink; break; case 'a': linkfiles = AbsoluteLink; break; case 'h': linkfiles = HardLinkFiles; break; default: snprintf(OUTPUT,CF_BUFSIZE*2,"Internal error, link type was [%c]\n",type); CfLog(cferror,OUTPUT,""); continue; } matched = (*linkfiles)(from,to,ptr); if (matched && !DONTDO) { chown(from,uid,gid); } } } if (matched) return; } } } snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't link the children of %s to anything because no\n",path); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"file system was found to mirror it in the defined binservers list.\n"); CfLog(cferror,OUTPUT,""); } /*********************************************************************/ int RecursiveLink(struct Link *lp,char *from,char *to,int maxrecurse) { struct stat statbuf; DIR *dirh; struct dirent *dirp; char newfrom[CF_BUFSIZE]; char newto[CF_BUFSIZE]; void *bug_check; int (*linkfiles)(char *from, char *to, struct Link *ptr); if (maxrecurse == 0) /* reached depth limit */ { Debug2("MAXRECURSE ran out, quitting at level %s with endlist = %d\n",to,lp->next); return false; } if (IgnoreFile(to,"",lp->ignores)) { Verbose("%s: Ignoring directory %s\n",VPREFIX,from); return false; } if (strlen(to) == 0) /* Check for root dir */ { to = "/"; } bug_check = lp->next; if ((dirh = opendir(to)) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't open directory [%s]\n",to); CfLog(cferror,OUTPUT,"opendir"); return false; } if (lp->next != bug_check) { printf("%s: solaris BSD compat bug: opendir wrecked the heap memory!!",VPREFIX); printf("%s: in copy to %s, using workaround...\n",VPREFIX,from); lp->next = bug_check; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,to,NULL)) { continue; } if (IgnoreFile(to,dirp->d_name,lp->ignores)) { continue; } strcpy(newfrom,from); /* Assemble pathname */ AddSlash(newfrom); strcpy(newto,to); AddSlash(newto); if (BufferOverflow(newfrom,dirp->d_name)) { closedir(dirh); return true; } strcat(newfrom,dirp->d_name); if (BufferOverflow(newto,dirp->d_name)) { closedir(dirh); return true; } strcat(newto,dirp->d_name); if (TRAVLINKS) { if (stat(newto,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",newto); CfLog(cfverbose,OUTPUT,""); continue; } } else { if (lstat(newto,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",newto); CfLog(cfverbose,OUTPUT,""); memset(VBUFF,0,CF_BUFSIZE); if (readlink(newto,VBUFF,CF_BUFSIZE-1) != -1) { Verbose("File is link to -> %s\n",VBUFF); } continue; } } if (!FileObjectFilter(newto,&statbuf,lp->filters,links)) { Debug("Skipping filtered file %s\n",newto); continue; } if (S_ISDIR(statbuf.st_mode)) { RecursiveLink(lp,newfrom,newto,maxrecurse-1); } else { switch (lp->type) { case 's': linkfiles = LinkFiles; break; case 'r': linkfiles = RelativeLink; break; case 'a': linkfiles = AbsoluteLink; break; case 'h': linkfiles = HardLinkFiles; break; default: printf("cfengine: internal error, link type was [%c]\n",lp->type); continue; } (*linkfiles)(newfrom,newto,lp); } } closedir(dirh); return true; } /*********************************************************************/ int LinkFiles(char *from,char *to_tmp,struct Link *lp) /* should return true if 'to' found */ { struct stat buf,savebuf; char to[CF_BUFSIZE],linkbuf[CF_BUFSIZE],saved[CF_BUFSIZE],absto[CF_BUFSIZE],*lastnode; struct UidList fakeuid; struct Image ip; char stamp[CF_BUFSIZE]; time_t STAMPNOW; int nofile = false; STAMPNOW = time((time_t *)NULL); memset(to,0,CF_BUFSIZE); memset(&ip,0,sizeof(ip)); if ((*to_tmp != '/') && (*to_tmp != '.')) /* links without a directory reference */ { strcpy(to,"./"); } if (strlen(to_tmp)+3 > CF_BUFSIZE) { printf("%s: CF_BUFSIZE boundaries exceeded in LinkFiles(%s->%s)\n",VPREFIX,from,to_tmp); return false; } strcat(to,to_tmp); Debug2("Linkfiles(%s,%s)\n",from,to); for (lastnode = from+strlen(from); *lastnode != '/'; lastnode--) { } lastnode++; if (IgnoredOrExcluded(links,lastnode,lp->inclusions,lp->exclusions)) { Verbose("%s: Skipping non-included pattern %s\n",VPREFIX,from); return true; } if (IsWildItemIn(VCOPYLINKS,lastnode) || IsWildItemIn(lp->copy,lastnode)) { fakeuid.uid = CF_SAME_OWNER; fakeuid.next = NULL; ip.plus = CF_SAMEMODE; ip.minus = CF_SAMEMODE; ip.uid = &fakeuid; ip.gid = (struct GidList *) &fakeuid; ip.action = "do"; ip.recurse = 0; ip.type = 't'; ip.defines = lp->defines; ip.elsedef = lp->elsedef; ip.backup = true; ip.exclusions = NULL; ip.inclusions = NULL; ip.symlink = NULL; ip.classes = NULL; ip.plus_flags = 0; ip.size = CF_NOSIZE; ip.linktype = 's'; ip.minus_flags = 0; ip.server = strdup("localhost"); Verbose("%s: Link item %s marked for copying instead\n",VPREFIX,from); MakeDirectoriesFor(to,'n'); CheckImage(to,from,&ip); free(ip.server); return true; } if (*to != '/') /* relative path, must still check if exists */ { Debug("Relative link destination detected: %s\n",to); strcpy(absto,AbsLinkPath(from,to)); Debug("Absolute path to relative link = %s, from %s\n",absto,from); } else { strcpy(absto,to); } Debug("Check for source (kill old=%d)\n",lp->nofile); if (stat(absto,&buf) == -1) { Debug("The file's destination does not seem to exist.\n"); nofile = true; } if (!ENFORCELINKS && !KILLOLDLINKS && nofile) { Debug("Returning since the destination is absent\n"); AddMultipleClasses(lp->elsedef); return false; /* no error warning, since the higher level routine uses this */ } if (KILLOLDLINKS && nofile) { KillOldLink(from,lp->defines); /* Check whether link points somewhere */ return true; } Debug2("Trying to link %s -> %s (%s)\n",from,to,absto); /* Move existing object out of way? */ if (lstat(from,&buf) == 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Link (%s->%s) exists.\n",from,to_tmp); CfLog(cfverbose,OUTPUT,""); if (! S_ISLNK(buf.st_mode) && ! ENFORCELINKS) { snprintf(OUTPUT,CF_BUFSIZE*2,"Error linking %s -> %s\n",from,to); CfLog(cfsilent,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"Cannot make link: %s exists and is not a link! (uid %d)\n",from,buf.st_uid); CfLog(cfsilent,OUTPUT,""); return(true); } if (S_ISREG(buf.st_mode) && ENFORCELINKS) { snprintf(OUTPUT,CF_BUFSIZE*2,"Moving %s to %s%s\n",from,from,CF_SAVED); CfLog(cfsilent,OUTPUT,""); if (DONTDO) { return true; } saved[0] = '\0'; strcpy(saved,from); sprintf(stamp, "_%d_%s", CFSTARTTIME, CanonifyName(ctime(&STAMPNOW))); strcat(saved,stamp); strcat(saved,CF_SAVED); if (rename(from,saved) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't rename %s to %s\n",from,saved); CfLog(cferror,OUTPUT,"rename"); return(true); } if (Repository(saved,VREPOSITORY)) { unlink(saved); } } if (S_ISDIR(buf.st_mode) && ENFORCELINKS) { snprintf(OUTPUT,CF_BUFSIZE*2,"Moving directory %s to %s%s.dir\n",from,from,CF_SAVED); CfLog(cfsilent,OUTPUT,""); if (DONTDO) { return true; } saved[0] = '\0'; strcpy(saved,from); sprintf(stamp, "_%d_%s", CFSTARTTIME, CanonifyName(ctime(&STAMPNOW))); strcat(saved,stamp); strcat(saved,CF_SAVED); strcat(saved,".dir"); if (stat(saved,&savebuf) != -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't save directory %s, since %s exists already\n",from,saved); CfLog(cferror,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"Unable to force link to existing directory %s\n",from); CfLog(cferror,OUTPUT,""); return true; } if (rename(from,saved) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't rename %s to %s\n",from,saved); CfLog(cferror,OUTPUT,"rename"); return(true); } } } /* Finished moving object out of the way */ memset(linkbuf,0,CF_BUFSIZE); if (readlink(from,linkbuf,CF_BUFSIZE-1) == -1) { if (! MakeDirectoriesFor(from,'n')) /* link doesn't exist */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't build directory tree up to %s!\n",from); CfLog(cfsilent,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"One element was a plain file, not a directory!\n"); CfLog(cfsilent,OUTPUT,""); return(true); } } else { int off1 = 0, off2 = 0; /* Link exists */ DeleteSlash(linkbuf); if (strncmp(linkbuf,"./",2) == 0) /* Ignore ./ at beginning */ { off1 = 2; } if (strncmp(to,"./",2) == 0) { off2 = 2; } if (strcmp(linkbuf+off1,to+off2) != 0) { if (ENFORCELINKS) { snprintf(OUTPUT,CF_BUFSIZE*2,"Removing link %s\n",from); CfLog(cfinform,OUTPUT,""); if (!DONTDO) { if (unlink(from) == -1) { perror("unlink"); return true; } return DoLink(from,to,lp->defines); } } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Old link %s points somewhere else. Doing nothing!\n",from); CfLog(cfsilent,OUTPUT,""); snprintf(OUTPUT,CF_BUFSIZE*2,"(Link points to %s not %s)\n\n",linkbuf,to); CfLog(cfsilent,OUTPUT,""); return(true); } } return true; } return DoLink(from,to,lp->defines); } /*********************************************************************/ int RelativeLink(char *from,char *to,struct Link *ptr) { char *sp, *commonto, *commonfrom; char buff[CF_BUFSIZE],linkto[CF_BUFSIZE]; int levels=0; Debug2("RelativeLink(%s,%s)\n",from,to); if (*to == '.') { return LinkFiles(from,to,ptr); } if (!CompressPath(linkto,to)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Failed to link %s to %s\n",from,to); CfLog(cferror,OUTPUT,""); return false; } commonto = linkto; commonfrom = from; if (strcmp(commonto,commonfrom) == 0) { CfLog(cferror,"Can't link file to itself!\n",""); snprintf(OUTPUT,CF_BUFSIZE*2,"(%s -> %s)\n",from,to); CfLog(cferror,OUTPUT,""); return false; } while (*commonto == *commonfrom) { commonto++; commonfrom++; } while (!((*commonto == '/') && (*commonfrom == '/'))) { commonto--; commonfrom--; } commonto++; Debug("Commonto = %s, common from = %s\n",commonto,commonfrom); for (sp = commonfrom; *sp != '\0'; sp++) { if (*sp == '/') { levels++; } } Debug("LEVELS = %d\n",levels); memset(buff,0,CF_BUFSIZE); strcat(buff,"./"); while(--levels > 0) { if (BufferOverflow(buff,"../")) { return false; } strcat(buff,"../"); } if (BufferOverflow(buff,commonto)) { return false; } strcat(buff,commonto); return LinkFiles(from,buff,ptr); } /*********************************************************************/ int AbsoluteLink(char *from,char *to,struct Link *ptr) /* global LINKTO */ { char absto[CF_BUFSIZE]; char expand[CF_BUFSIZE]; Debug2("AbsoluteLink(%s,%s)\n",from,to); if (*to == '.') { strcpy(LINKTO,from); ChopLastNode(LINKTO); AddSlash(LINKTO); strcat(LINKTO,to); } else { strcpy(LINKTO,to); } CompressPath(absto,LINKTO); expand[0] = '\0'; if (!ptr->nofile) { if (!ExpandLinks(expand,absto,0)) /* begin at level 1 and beam out at 15 */ { CfLog(cferror,"Failed to make absolute link in\n",""); snprintf(OUTPUT,CF_BUFSIZE*2,"%s -> %s\n",from,to); CfLog(cferror,OUTPUT,""); return false; } else { Debug2("ExpandLinks returned %s\n",expand); } } else { strcpy(expand,absto); } CompressPath(LINKTO,expand); return LinkFiles(from,LINKTO,ptr); } /*********************************************************************/ int DoLink (char *from,char *to,char *defines) { if (DONTDO) { printf("cfengine: Need to link files %s -> %s\n",from,to); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Linking files %s -> %s\n",from,to); CfLog(cfinform,OUTPUT,""); if (symlink(to,from) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't link %s to %s\n",to,from); CfLog(cferror,OUTPUT,"symlink"); return false; } else { AddMultipleClasses(defines); return true; } } return true; } /*********************************************************************/ void KillOldLink(char *name,char *defs) { char linkbuf[CF_BUFSIZE]; char linkpath[CF_BUFSIZE],*sp; struct stat statbuf; Debug("KillOldLink(%s)\n",name); memset(linkbuf,0,CF_BUFSIZE); memset(linkpath,0,CF_BUFSIZE); if (readlink(name,linkbuf,CF_BUFSIZE-1) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"(Can't read link %s while checking for deadlinks)\n",name); CfLog(cfverbose,OUTPUT,""); return; } if (linkbuf[0] != '/') { strcpy(linkpath,name); /* Get path to link */ for (sp = linkpath+strlen(linkpath); (*sp != '/') && (sp >= linkpath); sp-- ) { *sp = '\0'; } } strcat(linkpath,linkbuf); CompressPath(VBUFF,linkpath); if (stat(VBUFF,&statbuf) == -1) /* link points nowhere */ { if (KILLOLDLINKS || DEBUG || D2) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s is a link which points to %s, but that file doesn't seem to exist\n",name,VBUFF); CfLog(cfverbose,OUTPUT,""); } if (KILLOLDLINKS) { snprintf(OUTPUT,CF_BUFSIZE*2,"Removing dead link %s\n",name); CfLog(cfinform,OUTPUT,""); if (! DONTDO) { unlink(name); /* May not work on a client-mounted system ! */ AddMultipleClasses(defs); } } } } /*********************************************************************/ int HardLinkFiles(char *from,char *to,struct Link *ptr) /* should return true if 'to' found */ { struct stat frombuf,tobuf; char saved[CF_BUFSIZE], *lastnode; struct UidList fakeuid; struct Image ip; char stamp[CF_BUFSIZE]; time_t STAMPNOW; STAMPNOW = time((time_t *)NULL); for (lastnode = from+strlen(from); *lastnode != '/'; lastnode--) { } lastnode++; if (ptr->inclusions != NULL && !IsWildItemIn(ptr->inclusions,lastnode)) { Verbose("%s: Skipping non-included pattern %s\n",VPREFIX,from); return true; } if (IsWildItemIn(VEXCLUDELINK,lastnode) || IsWildItemIn(ptr->exclusions,lastnode)) { Verbose("%s: Skipping excluded pattern %s\n",VPREFIX,from); return true; } if (IsWildItemIn(VCOPYLINKS,lastnode) || IsWildItemIn(ptr->copy,lastnode)) { fakeuid.uid = CF_SAME_OWNER; fakeuid.next = NULL; ip.plus = CF_SAMEMODE; ip.minus = CF_SAMEMODE; ip.uid = &fakeuid; ip.gid = (struct GidList *) &fakeuid; ip.action = "do"; ip.recurse = 0; ip.type = 't'; ip.backup = true; ip.plus_flags = 0; ip.minus_flags = 0; ip.exclusions = NULL; ip.symlink = NULL; Verbose("%s: Link item %s marked for copying instead\n",VPREFIX,from); CheckImage(to,from,&ip); return true; } if (stat(to,&tobuf) == -1) { return(false); /* no error warning, since the higher level routine uses this */ } if (! S_ISREG(tobuf.st_mode)) { snprintf(OUTPUT,CF_BUFSIZE*2,"%s: will only hard link regular files and %s is not regular\n",VPREFIX,to); CfLog(cfsilent,OUTPUT,""); return true; } Debug2("Trying to (hard) link %s -> %s\n",from,to); if (stat(from,&frombuf) == -1) { DoHardLink(from,to,ptr->defines); return true; } /* both files exist, but are they the same file? POSIX says */ /* the files could be on different devices, but unix doesn't */ /* allow this behaviour so the tests below are theoretical...*/ if (frombuf.st_ino != tobuf.st_ino && frombuf.st_dev != frombuf.st_dev) { Verbose("If this is POSIX, unable to determine if %s is hard link is correct\n",from); Verbose("since it points to a different filesystem!\n"); if (frombuf.st_mode == tobuf.st_mode && frombuf.st_size == tobuf.st_size) { snprintf(OUTPUT,CF_BUFSIZE*2,"Hard link (%s->%s) on different device APPEARS okay\n",from,to); CfLog(cfverbose,OUTPUT,""); AddMultipleClasses(ptr->elsedef); return true; } } if (frombuf.st_ino == tobuf.st_ino && frombuf.st_dev == frombuf.st_dev) { snprintf(OUTPUT,CF_BUFSIZE*2,"Hard link (%s->%s) exists and is okay.\n",from,to); CfLog(cfverbose,OUTPUT,""); AddMultipleClasses(ptr->elsedef); return true; } snprintf(OUTPUT,CF_BUFSIZE*2,"%s does not appear to be a hard link to %s\n",from,to); CfLog(cfinform,OUTPUT,""); if (ENFORCELINKS) { snprintf(OUTPUT,CF_BUFSIZE*2,"Moving %s to %s.%s\n",from,from,CF_SAVED); CfLog(cfinform,OUTPUT,""); if (DONTDO) { return true; } saved[0] = '\0'; strcpy(saved,from); sprintf(stamp, "_%d_%s", CFSTARTTIME, CanonifyName(ctime(&STAMPNOW))); strcat(saved,stamp); strcat(saved,CF_SAVED); if (rename(from,saved) == -1) { perror("rename"); return(true); } DoHardLink(from,to,ptr->defines); } return(true); } /*********************************************************************/ void DoHardLink (char *from,char *to,char *defines) { if (DONTDO) { printf("Hardlink files %s -> %s\n\n",from,to); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Hardlinking files %s -> %s\n",from,to); CfLog(cfinform,OUTPUT,""); if (link(to,from) == -1) { CfLog(cferror,"","link"); } else { AddMultipleClasses(defines); } } } /*********************************************************************/ int ExpandLinks(char *dest,char *from,int level) /* recursive */ /* Expand a path contaning symbolic links, up to 4 levels */ /* of symbolic links and then beam out in a hurry ! */ { char *sp, buff[CF_BUFSIZE]; char node[CF_MAXLINKSIZE]; struct stat statbuf; int lastnode = false; memset(dest,0,CF_BUFSIZE); Debug2("ExpandLinks(%s,%d)\n",from,level); if (level >= CF_MAXLINKLEVEL) { CfLog(cferror,"Too many levels of symbolic links to evaluate absolute path\n",""); return false; } for (sp = from; *sp != '\0'; sp++) { if (*sp == '/') { continue; } sscanf(sp,"%[^/]",node); sp += strlen(node); if (*sp == '\0') { lastnode = true; } if (strcmp(node,".") == 0) { continue; } if (strcmp(node,"..") == 0) { if (! ChopLastNode(LINKTO)) { Debug("cfengine: used .. beyond top of filesystem!\n"); return false; } continue; } else { strcat(dest,"/"); } strcat(dest,node); if (lstat(dest,&statbuf) == -1) /* File doesn't exist so we can stop here */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s in ExpandLinks\n",dest); CfLog(cferror,OUTPUT,"stat"); return false; } if (S_ISLNK(statbuf.st_mode)) { memset(buff,0,CF_BUFSIZE); if (readlink(dest,buff,CF_BUFSIZE-1) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Expand links can't stat %s\n",dest); CfLog(cferror,OUTPUT,"readlink"); return false; } else { if (buff[0] == '.') { ChopLastNode(dest); AddSlash(dest); if (BufferOverflow(dest,buff)) { return false; } strcat(dest,buff); } else if (buff[0] == '/') { strcpy(dest,buff); DeleteSlash(dest); if (strcmp(dest,from) == 0) { Debug2("No links to be expanded\n"); return true; } if (!lastnode && !ExpandLinks(buff,dest,level+1)) { return false; } } else { ChopLastNode(dest); AddSlash(dest); strcat(dest,buff); DeleteSlash(dest); if (strcmp(dest,from) == 0) { Debug2("No links to be expanded\n"); return true; } memset(buff,0,CF_BUFSIZE); if (!lastnode && !ExpandLinks(buff,dest,level+1)) { return false; } } } } } return true; } /*********************************************************************/ char *AbsLinkPath (char *from,char *relto) /* Take an abolute source and a relative destination object and find the absolute name of the to object */ { char *sp; int pop = 1; static char destination[CF_BUFSIZE]; if (*relto == '/') { printf("Cfengine internal error: call to AbsLInkPath with absolute pathname\n"); FatalError(""); } strcpy(destination,from); /* reuse to save stack space */ for (sp = relto; *sp != '\0'; sp++) { if (strncmp(sp,"../",3) == 0) { pop++; sp += 2; continue; } if (strncmp(sp,"./",2) == 0) { sp += 1; continue; } break; /* real link */ } while (pop > 0) { ChopLastNode(destination); pop--; } if (strlen(destination) == 0) { strcpy(destination,"/"); } else { AddSlash(destination); } strcat(destination,sp); Debug("Reconstructed absolute linkname = %s\n",destination); return destination; } cfengine-2.2.10/src/ifconf.c0000644000175000001440000004056411005277354012503 00000000000000/* cfengine for GNU Copyright (C) 1995 Free Software Foundation, Inc. This file is part of GNU cfengine - written and maintained by Mark Burgess, Dept of Computing and Engineering, Oslo College, Dept. of Theoretical physics, University of Oslo 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, 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 */ /*******************************************************************/ /* */ /* INET checking for cfengine */ /* */ /* This is based on the action of "ifconfig" for IP protocols */ /* It assumes that we are on the internet and uses ioctl to get */ /* the necessary info from the device. Sanity checking is done... */ /* */ /* Sockets are very poorly documented. The basic socket adress */ /* struct sockaddr is a generic type. Specific socket addresses */ /* must be specified depending on the family or protocol being */ /* used. e.g. if you're using the internet inet protocol, then */ /* the fmaily is AF_INT and the socket address type is sockadr_in */ /* Although it is not obvious, the documentation assures us that */ /* we can cast a pointer of one type into a pointer of the other: */ /* */ /* Here's an example */ /* */ /* #include */ /* */ /* struct in_addr adr; */ /* e.g. adr.s_addr = inet_addr("129.240.22.34"); */ /* printf("addr is %s\n",inet_ntoa(adr)); */ /* */ /* */ /* We have to do the following in order to convert */ /* a sockaddr struct into a sockaddr_in struct required by the */ /* ifreq struct!! These calls have no right to work, but somehow */ /* they do! */ /* */ /* struct sockaddr_in sin; */ /* sin.sin_addr.s_addr = inet_addr("129.240.22.34"); */ /* */ /* IFR.ifr_addr = *((struct sockaddr *) &sin); */ /* */ /* sin = *(struct sockaddr_in *) &IFR.ifr_addr; */ /* */ /* printf("IP address: %s\n",inet_ntoa(sin.sin_addr)); */ /* */ /*******************************************************************/ #include "cf.defs.h" #include "cf.extern.h" #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN sizeof("255.255.255.255") #endif #if !defined(NT) && !defined(IRIX) /* IRIX makes the routing stuff obsolete unless we do this */ # undef sgi struct ifreq IFR; char VNUMBROADCAST[256]; # define cfproto 0 # ifndef IPPROTO_IP /* Old boxes, hpux 7 etc */ # define IPPROTO_IP 0 # endif # ifndef SIOCSIFBRDADDR # define SIOCSIFBRDADDR SIOCGIFBRDADDR # endif /*******************************************************************/ void IfConf (char *vifdev,char *vaddress,char *vnetmask,char *vbroadcast) { int sk, flags, metric, isnotsane = false; Verbose("Assumed interface name: %s %s %s\n",vifdev,vnetmask,vbroadcast); if (!IsPrivileged()) { printf("%s: Only root can configure the net interface.\n",VPREFIX); return; } if (vnetmask[0] == '\0') { CfLog(cferror,"Program does not define a subnetmask",""); return; } if (vbroadcast[0] == '\0') { CfLog(cferror,"Program does not define a broadcast mode for this host",""); return; } strcpy(IFR.ifr_name,vifdev); IFR.ifr_addr.sa_family = AF_INET; if ((sk = socket(AF_INET,SOCK_DGRAM,IPPROTO_IP)) == -1) { CfLog(cferror,"","socket"); FatalError("Error in IfConfig()"); } if (ioctl(sk,SIOCGIFFLAGS, (caddr_t) &IFR) == -1) /* Get the device status flags */ { CfLog(cferror,"No such network device","ioctl"); return; } flags = IFR.ifr_flags; strcpy(IFR.ifr_name,vifdev); /* copy this each time */ if (ioctl(sk,SIOCGIFMETRIC, (caddr_t) &IFR) == -1) /* Get the routing priority */ { CfLog(cferror,"","ioctl"); FatalError("Software error: error getting metric"); } metric = IFR.ifr_metric; isnotsane = GetIfStatus(sk,vifdev,vaddress,vnetmask,vbroadcast); if (! DONTDO && isnotsane) { SetIfStatus(sk,vifdev,vaddress,vnetmask,vbroadcast); GetIfStatus(sk,vifdev,vaddress,vnetmask,vbroadcast); } close(sk); } /*******************************************************************/ int GetIfStatus(int sk,char *vifdev,char *vaddress,char *vnetmask,char *vbroadcast) { struct sockaddr_in *sin; struct sockaddr_in netmask; int insane = false; struct hostent *hp; struct in_addr inaddr; Verbose("Checking interface status...\n"); if ((hp = gethostbyname(VSYSNAME.nodename)) == NULL) { CfLog(cferror,"","gethostbyname"); return false; } else { memcpy(&inaddr,hp->h_addr,hp->h_length); Verbose("Address given by nameserver: %s\n",inet_ntoa(inaddr)); } strcpy(IFR.ifr_name,vifdev); if (ioctl(sk,SIOCGIFADDR, (caddr_t) &IFR) == -1) /* Get the device status flags */ { return false; } sin = (struct sockaddr_in *) &IFR.ifr_addr; if (strlen(vaddress) > 0) { if (strcmp(vaddress,(char *)inet_ntoa(sin->sin_addr)) != 0) { CfLog(cferror,"This machine is configured with an address which differs from\n",""); CfLog(cferror,"the cfagent configuration\n",""); CfLog(cferror,"Don't know what to do yet...\n",""); insane = true; } } if (strcmp((char *)inet_ntoa(*(struct in_addr *)(hp->h_addr)),(char *)inet_ntoa(sin->sin_addr)) != 0) { CfLog(cferror,"This machine is configured with an address which differs from\n",""); CfLog(cferror,"the nameserver's information! (Insane!)\n",""); CfLog(cferror,"Don't quite know what to do...\n",""); insane = true; } if (ioctl(sk,SIOCGIFNETMASK, (caddr_t) &IFR) == -1) { return false; } netmask.sin_addr = ((struct sockaddr_in *) &IFR.ifr_addr)->sin_addr; Verbose("Found netmask: %s\n",inet_ntoa(netmask.sin_addr)); strcpy(VBUFF,inet_ntoa(netmask.sin_addr)); if (strcmp(VBUFF,vnetmask)) { CfLog(cferror,"The netmask is incorrectly configured, resetting...\n",""); insane = true; } if (ioctl(sk,SIOCGIFBRDADDR, (caddr_t) &IFR) == -1) { return false; } sin = (struct sockaddr_in *) &IFR.ifr_addr; strcpy(VBUFF,inet_ntoa(sin->sin_addr)); Verbose("Found broadcast address: %s\n",inet_ntoa(sin->sin_addr)); GetBroadcastAddr(inet_ntoa(inaddr),vifdev,vnetmask,vbroadcast); if (strcmp(VBUFF,VNUMBROADCAST) != 0) { snprintf(OUTPUT,CF_BUFSIZE*2,"Broadcast address was %s not %s (should be bit-type %s)\n",VBUFF,VNUMBROADCAST,vbroadcast); CfLog(cferror,OUTPUT,""); insane = true; } return(insane); } /*******************************************************************/ void SetIfStatus(int sk,char *vifdev,char *vaddress,char *vnetmask,char *vbroadcast) { struct sockaddr_in *sin; struct sockaddr_in netmask, broadcast; /********************************* Don't try to set the address yet... if (ioctl(sk,SIOCSIFADDR, (caddr_t) &IFR) == -1) { perror ("Can't set IP address"); return; } REWRITE THIS TO USE ifconfig / ipconfig **********************************/ /* set netmask */ Verbose("Resetting interface...\n"); memset(&IFR, 0, sizeof(IFR)); strncpy(IFR.ifr_name,vifdev,sizeof(IFR.ifr_name)); netmask.sin_addr.s_addr = inet_network(vnetmask); netmask.sin_family = AF_INET; IFR.ifr_addr = *((struct sockaddr *) &netmask); sin = (struct sockaddr_in *) &IFR.ifr_addr; if (ioctl(sk,SIOCSIFNETMASK, (caddr_t) &IFR) < 0) { CfLog(cferror,"Permission to reconfigure netmask denied.\n","ioctl"); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Set Netmask to: %s\n",inet_ntoa(netmask.sin_addr)); CfLog(cfinform,OUTPUT,""); } /* broadcast addr */ strcpy(IFR.ifr_name,vifdev); broadcast.sin_addr.s_addr = inet_addr(VNUMBROADCAST); IFR.ifr_addr = *((struct sockaddr *) &broadcast); sin = (struct sockaddr_in *) &IFR.ifr_addr; Verbose("Trying to set broad to %s = %s\n",VNUMBROADCAST,inet_ntoa(sin->sin_addr)); if (ioctl(sk,SIOCSIFBRDADDR, (caddr_t) &IFR) == -1) { CfLog(cferror,"Permission to reconfigure broadcast denied.\n","ioctl"); return; } if ((void *)(sin->sin_addr.s_addr) == (void *)NULL) { CfLog(cferror,"No broadcast address on socket after configuration!!\n",""); } else { snprintf(OUTPUT,CF_BUFSIZE*2,"Set Broadcast address to: %s\n",inet_ntoa(sin->sin_addr)); CfLog(cfinform,OUTPUT,""); } } /*****************************************************/ void GetBroadcastAddr(char *ipaddr,char *vifdev,char *vnetmask,char *vbroadcast) { unsigned int na,nb,nc,nd; unsigned int ia,ib,ic,id; unsigned int ba,bb,bc,bd; unsigned netmask,ip,broadcast; sscanf(vnetmask,"%u.%u.%u.%u",&na,&nb,&nc,&nd); netmask = nd + 256*nc + 256*256*nb + 256*256*256*na; sscanf(ipaddr,"%u.%u.%u.%u",&ia,&ib,&ic,&id); ip = id + 256*ic + 256*256*ib + 256*256*256*ia; if (strcmp(vbroadcast,"zero") == 0) { broadcast = ip & netmask; } else if (strcmp(vbroadcast,"one") == 0) { broadcast = ip | (~netmask); } else { return; } ba = broadcast / (256 * 256 * 256); bb = (broadcast / (256 * 256)) % 256; bc = broadcast / (256) % 256; bd = broadcast % 256; sprintf(VNUMBROADCAST,"%u.%u.%u.%u",ba,bb,bc,bd); } /****************************************************************/ /* */ /* Routing Tables: */ /* */ /* To check that we have at least one static route entry to */ /* the nearest gateway -- i.e. the wildcard entry for "default" */ /* we need some way of accessing the routing tables. There is */ /* no elegant way of doing this, alas. */ /* */ /****************************************************************/ void SetDefaultRoute() { int sk, defaultokay = 1; struct sockaddr_in sindst,singw; char oldroute[INET_ADDRSTRLEN]; char routefmt[CF_MAXVARSIZE]; /* These OSes have these structs defined but use the route command */ # if defined DARWIN || defined FREEBSD || defined OPENBSD || defined SOLARIS # undef HAVE_RTENTRY # undef HAVE_ORTENTRY # endif # ifdef HAVE_ORTENTRY struct ortentry route; # else # if HAVE_RTENTRY struct rtentry route; # endif # endif FILE *pp; Verbose("Looking for a default route...\n"); if (!IsPrivileged()) { snprintf(OUTPUT,CF_BUFSIZE*2,"Only root can set a default route."); CfLog(cfinform,OUTPUT,""); return; } if (VDEFAULTROUTE == NULL) { Verbose("cfengine: No default route is defined. Ignoring the routing tables.\n"); return; } if ((pp = cfpopen(VNETSTAT[VSYSTEMHARDCLASS],"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Failed to open pipe from %s\n",VNETSTAT[VSYSTEMHARDCLASS]); CfLog(cferror,OUTPUT,"popen"); return; } while (!feof(pp)) { ReadLine(VBUFF,CF_BUFSIZE,pp); Debug("LINE: %s = %s?\n",VBUFF,VDEFAULTROUTE->name); if ((strncmp(VBUFF,"default",7) == 0)||(strncmp(VBUFF,"0.0.0.0",7) == 0)) { /* extract the default route */ /* format: default|0.0.0.0 route etc */ if ((sscanf(VBUFF, "%*[default0. ]%s%*[ ]", &oldroute)) == 1) { if ((strncmp(VDEFAULTROUTE->name, oldroute, INET_ADDRSTRLEN)) == 0) { Verbose("cfengine: default route is already set to %s\n",VDEFAULTROUTE->name); defaultokay = 1; break; } else { Verbose("cfengine: default route is set to %s, but should be %s.\n",oldroute,VDEFAULTROUTE->name); defaultokay = 2; break; } } } else { Debug("No default route is yet registered\n"); defaultokay = 0; } } cfpclose(pp); if (defaultokay == 1) { Verbose("Default route is set and agrees with conditional policy\n"); return; } if (defaultokay == 0) { AddMultipleClasses("no_default_route"); } if (IsExcluded(VDEFAULTROUTE->classes)) { Verbose("cfengine: No default route is applicable. Ignoring the routing tables.\n"); return; } CfLog(cferror,"The default route is incorrect, trying to correct\n",""); if ( strcmp(VROUTE[VSYSTEMHARDCLASS], "-") != 0 ) { Debug ("Using route shell commands to set default route\n"); if (defaultokay == 2) { if (! DONTDO) { /* get the route command and the format for the delete argument */ snprintf(routefmt,CF_MAXVARSIZE,"%s %s",VROUTE[VSYSTEMHARDCLASS],VROUTEDELFMT[VSYSTEMHARDCLASS]); snprintf(VBUFF,CF_MAXVARSIZE,routefmt,"default",VDEFAULTROUTE->name); if (ShellCommandReturnsZero(VBUFF,false)) { CfLog(cfinform,"Removing old default route",""); CfLog(cfinform,VBUFF,""); } else { CfLog(cferror,"Error removing route",""); } } } if (! DONTDO) { snprintf(routefmt,CF_MAXVARSIZE,"%s %s",VROUTE[VSYSTEMHARDCLASS],VROUTEADDFMT[VSYSTEMHARDCLASS]); snprintf(VBUFF,CF_MAXVARSIZE,routefmt,"default",VDEFAULTROUTE->name); if (ShellCommandReturnsZero(VBUFF,false)) { CfLog(cfinform,"Setting default route",""); CfLog(cfinform,VBUFF,""); } else { CfLog(cferror,"Error setting route",""); } } return; } else { #if defined HAVE_RTENTRY || defined HAVE_ORTENTRY Debug ("Using route ioctl to set default route\n"); if ((sk = socket(AF_INET,SOCK_RAW,0)) == -1) { CfLog(cferror,"System class: ", CLASSTEXT[VSYSTEMHARDCLASS]); CfLog(cferror,"","Error in SetDefaultRoute():"); perror("cfengine: socket"); } else { sindst.sin_family = AF_INET; singw.sin_family = AF_INET; sindst.sin_addr.s_addr = INADDR_ANY; singw.sin_addr.s_addr = inet_addr(VDEFAULTROUTE->name); route.rt_dst = *(struct sockaddr *)&sindst; /* This disgusting method is necessary */ route.rt_gateway = *(struct sockaddr *)&singw; route.rt_flags = RTF_GATEWAY; if (! DONTDO) { if (ioctl(sk,SIOCADDRT, (caddr_t) &route) == -1) /* Get the device status flags */ { CfLog(cferror,"Error setting route:",""); perror("cfengine: ioctl SIOCADDRT:"); } else { CfLog(cferror,"Setting default route.\n",""); snprintf(OUTPUT,CF_BUFSIZE*2,"I'm setting it to %s\n",VDEFAULTROUTE->name); CfLog(cferror,OUTPUT,""); } } } #else /* Socket routing - don't really know how to do this yet */ Verbose("Sorry don't know how to do routing on this platform\n"); #endif } } #else /* NT or IRIX */ void IfConf (vifdev,vaddress,vnetmask,vbroadcast) char *vifdev,*vaddress,*vnetmask, *vbroadcast; { Verbose("Network configuration is not implemented on this OS\n"); } void SetDefaultRoute() { Verbose("Setting default route is not implemented on this OS\n"); } #endif cfengine-2.2.10/ylwrap0000744000175000001440000000764410202123462011534 00000000000000#! /bin/sh # ylwrap - wrapper for lex/yacc invocations. # Copyright 1996, 1997, 1998, 1999 Free Software Foundation, Inc. # Written by Tom Tromey . # # 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, 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. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Usage: # ylwrap INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]... # * INPUT is the input file # * OUTPUT is file PROG generates # * DESIRED is file we actually want # * PROGRAM is program to run # * ARGS are passed to PROG # Any number of OUTPUT,DESIRED pairs may be used. # The input. input="$1" shift case "$input" in [\\/]* | ?:[\\/]*) # Absolute path; do nothing. ;; *) # Relative path. Make it absolute. input="`pwd`/$input" ;; esac # The directory holding the input. input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'` # Quote $INPUT_DIR so we can use it in a regexp. # FIXME: really we should care about more than `.' and `\'. input_rx=`echo "$input_dir" | sed -e 's,\\\\,\\\\\\\\,g' -e 's,\\.,\\\\.,g'` echo "got $input_rx" pairlist= while test "$#" -ne 0; do if test "$1" = "--"; then shift break fi pairlist="$pairlist $1" shift done # The program to run. prog="$1" shift # Make any relative path in $prog absolute. case "$prog" in [\\/]* | ?:[\\/]*) ;; *[\\/]*) prog="`pwd`/$prog" ;; esac # FIXME: add hostname here for parallel makes that run commands on # other machines. But that might take us over the 14-char limit. dirname=ylwrap$$ trap "cd `pwd`; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15 mkdir $dirname || exit 1 cd $dirname $prog ${1+"$@"} "$input" status=$? if test $status -eq 0; then set X $pairlist shift first=yes # Since DOS filename conventions don't allow two dots, # the DOS version of Bison writes out y_tab.c instead of y.tab.c # and y_tab.h instead of y.tab.h. Test to see if this is the case. y_tab_nodot="no" if test -f y_tab.c || test -f y_tab.h; then y_tab_nodot="yes" fi while test "$#" -ne 0; do from="$1" # Handle y_tab.c and y_tab.h output by DOS if test $y_tab_nodot = "yes"; then if test $from = "y.tab.c"; then from="y_tab.c" else if test $from = "y.tab.h"; then from="y_tab.h" fi fi fi if test -f "$from"; then # If $2 is an absolute path name, then just use that, # otherwise prepend `../'. case "$2" in [\\/]* | ?:[\\/]*) target="$2";; *) target="../$2";; esac # Edit out `#line' or `#' directives. We don't want the # resulting debug information to point at an absolute srcdir; # it is better for it to just mention the .y file with no # path. sed -e "/^#/ s,$input_rx,," "$from" > "$target" || status=$? else # A missing file is only an error for the first file. This # is a blatant hack to let us support using "yacc -d". If -d # is not specified, we don't want an error when the header # file is "missing". if test $first = yes; then status=1 fi fi shift shift first=no done else status=$? fi # Remove the directory. cd .. rm -rf $dirname exit $status cfengine-2.2.10/Makefile.in0000644000175000001440000005333011170173245012341 00000000000000# Makefile.in generated by automake 1.10.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, # 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ subdir = . DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in $(top_srcdir)/configure AUTHORS COPYING \ ChangeLog INSTALL NEWS TODO acconfig.h compile config.guess \ config.sub depcomp install-sh ltmain.sh mdate-sh missing \ mkinstalldirs ylwrap ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/src/conf.h CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-dvi-recursive install-exec-recursive \ install-html-recursive install-info-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; am__installdirs = "$(DESTDIR)$(docdir)" docDATA_INSTALL = $(INSTALL_DATA) DATA = $(doc_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive ETAGS = etags CTAGS = ctags DIST_SUBDIRS = pub src contrib inputs doc DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ { test ! -d $(distdir) \ || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -fr $(distdir); }; } DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best distuninstallcheck_listfiles = find . -type f -print distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ BERKELEY_DB_CFLAGS = @BERKELEY_DB_CFLAGS@ BERKELEY_DB_LDFLAGS = @BERKELEY_DB_LDFLAGS@ BERKELEY_DB_LIB = @BERKELEY_DB_LIB@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ DVIPS = @DVIPS@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EIGHTBIT = @EIGHTBIT@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GCC_CFLAG = @GCC_CFLAG@ GETCONF = @GETCONF@ GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ GREP = @GREP@ HOSTNAME = @HOSTNAME@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KMEM_GROUP = @KMEM_GROUP@ LATEX = @LATEX@ LD = @LD@ LDFLAGS = @LDFLAGS@ LEX = @LEX@ LEXLIB = @LEXLIB@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIB_SELINUX = @LIB_SELINUX@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ NEED_SETGID = @NEED_SETGID@ NM = @NM@ NMEDIT = @NMEDIT@ NOWRAP = @NOWRAP@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OPENSSL_LIB_CPPFLAGS = @OPENSSL_LIB_CPPFLAGS@ OPENSSL_LIB_LDFLAGS = @OPENSSL_LIB_LDFLAGS@ OPENSSL_LIB_LIB = @OPENSSL_LIB_LIB@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PS2PDF = @PS2PDF@ PTHREAD_CC = @PTHREAD_CC@ PTHREAD_CFLAGS = @PTHREAD_CFLAGS@ PTHREAD_CPPFLAGS = @PTHREAD_CPPFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ TEXI2DVI = @TEXI2DVI@ VERSION = @VERSION@ YACC = @YACC@ YFLAGS = @YFLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = $(pkgdatadir) dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target = @target@ target_alias = @target_alias@ target_cpu = @target_cpu@ target_os = @target_os@ target_vendor = @target_vendor@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @BUILD_DOC_FALSE@DOC_DIR = @BUILD_DOC_TRUE@DOC_DIR = doc SUBDIRS = pub src contrib inputs $(DOC_DIR) EXTRA_DIST = acconfig.h doc/cfengine.8 COPYING ChangeLog INSTALL NEWS README LICENSE doc_DATA = README ChangeLog INSTALL NEWS # # Some basic clean ups # MOSTLYCLEANFILES = *~ # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.sub \ configure install-sh missing mkinstalldirs depcomp ylwrap \ ltmain.sh mdate-sh all: all-recursive .SUFFIXES: am--refresh: @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu '; \ cd $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ cd $(top_srcdir) && \ $(AUTOMAKE) --gnu Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) cd $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) test -z "$(docdir)" || $(MKDIR_P) "$(DESTDIR)$(docdir)" @list='$(doc_DATA)'; for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ f=$(am__strip_dir) \ echo " $(docDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(docdir)/$$f'"; \ $(docDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(docdir)/$$f"; \ done uninstall-docDATA: @$(NORMAL_UNINSTALL) @list='$(doc_DATA)'; for p in $$list; do \ f=$(am__strip_dir) \ echo " rm -f '$(DESTDIR)$(docdir)/$$f'"; \ rm -f "$(DESTDIR)$(docdir)/$$f"; \ done # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. # To change the values of `make' variables: instead of editing Makefiles, # (1) if the variable is set in `config.status', edit `config.status' # (which will cause the Makefiles to be regenerated when you run `make'); # (2) otherwise, pass the desired values on the `make' command line. $(RECURSIVE_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ list='$(SUBDIRS)'; for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" $(RECURSIVE_CLEAN_TARGETS): @failcom='exit 1'; \ for f in x $$MAKEFLAGS; do \ case $$f in \ *=* | --[!k]*);; \ *k*) failcom='fail=yes';; \ esac; \ done; \ dot_seen=no; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ rev=''; for subdir in $$list; do \ if test "$$subdir" = "."; then :; else \ rev="$$subdir $$rev"; \ fi; \ done; \ rev="$$rev ."; \ target=`echo $@ | sed s/-recursive//`; \ for subdir in $$rev; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done && test -z "$$fail" tags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ done ctags-recursive: list='$(SUBDIRS)'; for subdir in $$list; do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ done ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ mkid -fID $$unique tags: TAGS TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$tags $$unique; \ fi ctags: CTAGS CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ $(TAGS_FILES) $(LISP) tags=; \ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | \ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in files) print i; }; }'`; \ test -z "$(CTAGS_ARGS)$$tags$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$tags $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && cd $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) $$here distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) $(am__remove_distdir) test -d $(distdir) || mkdir $(distdir) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ fi; \ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ else \ test -f $(distdir)/$$file \ || cp -p $$d/$$file $(distdir)/$$file \ || exit 1; \ fi; \ done list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ distdir=`$(am__cd) $(distdir) && pwd`; \ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ (cd $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$top_distdir" \ distdir="$$distdir/$$subdir" \ am__remove_distdir=: \ am__skip_length_check=: \ distdir) \ || exit 1; \ fi; \ done -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r $(distdir) dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 $(am__remove_distdir) dist-lzma: distdir tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma $(am__remove_distdir) dist-tarZ: distdir tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__remove_distdir) dist-shar: distdir shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__remove_distdir) dist dist-all: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lzma*) \ unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && cd $(distdir)/_build \ && ../configure --srcdir=.. --prefix="$$dc_install_base" \ $(DISTCHECK_CONFIGURE_FLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck $(am__remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(docdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ `test -z '$(STRIP)' || \ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install mostlyclean-generic: -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-libtool \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive info: info-recursive info-am: install-data-am: install-docDATA install-dvi: install-dvi-recursive install-exec-am: install-html: install-html-recursive install-info: install-info-recursive install-man: install-pdf: install-pdf-recursive install-ps: install-ps-recursive installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-docDATA .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ install-strip .PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ all all-am am--refresh check check-am clean clean-generic \ clean-libtool ctags ctags-recursive dist dist-all dist-bzip2 \ dist-gzip dist-lzma dist-shar dist-tarZ dist-zip distcheck \ distclean distclean-generic distclean-libtool distclean-tags \ distcleancheck distdir distuninstallcheck dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-docDATA install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-recursive uninstall uninstall-am uninstall-docDATA # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: cfengine-2.2.10/config.guess0000744000175000001440000011304510202123447012604 00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002 Free Software Foundation, Inc. timestamp='2002-03-04' # This file 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. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner . # Please send patches to . Submit a context # diff and a properly formatted ChangeLog entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # The plan is that this can be called by configure scripts if you # don't specify an explicit build system type. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit 0 ;; --version | -v ) echo "$version" ; exit 0 ;; --help | --h* | -h ) echo "$usage"; exit 0 ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi dummy=dummy-$$ trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int dummy(){}" > $dummy.c ; for c in cc gcc c89 ; do ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; if test $? = 0 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; rm -f $dummy.c $dummy.o $dummy.rel ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep __ELF__ >/dev/null then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit 0 ;; amiga:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; arc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mac68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; macppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme68k:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvme88k:OpenBSD:*:*) echo m88k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; mvmeppc:OpenBSD:*:*) echo powerpc-unknown-openbsd${UNAME_RELEASE} exit 0 ;; pmax:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sgi:OpenBSD:*:*) echo mipseb-unknown-openbsd${UNAME_RELEASE} exit 0 ;; sun3:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; wgrisc:OpenBSD:*:*) echo mipsel-unknown-openbsd${UNAME_RELEASE} exit 0 ;; *:OpenBSD:*:*) echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} exit 0 ;; alpha:OSF1:*:*) if test $UNAME_RELEASE = "V4.0"; then UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` fi # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. cat <$dummy.s .data \$Lformat: .byte 37,100,45,37,120,10,0 # "%d-%x\n" .text .globl main .align 4 .ent main main: .frame \$30,16,\$26,0 ldgp \$29,0(\$27) .prologue 1 .long 0x47e03d80 # implver \$0 lda \$2,-1 .long 0x47e20c21 # amask \$2,\$1 lda \$16,\$Lformat mov \$0,\$17 not \$1,\$18 jsr \$26,printf ldgp \$29,0(\$26) mov 0,\$16 jsr \$26,exit .end main EOF eval $set_cc_for_build $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null if test "$?" = 0 ; then case `./$dummy` in 0-0) UNAME_MACHINE="alpha" ;; 1-0) UNAME_MACHINE="alphaev5" ;; 1-1) UNAME_MACHINE="alphaev56" ;; 1-101) UNAME_MACHINE="alphapca56" ;; 2-303) UNAME_MACHINE="alphaev6" ;; 2-307) UNAME_MACHINE="alphaev67" ;; 2-1307) UNAME_MACHINE="alphaev68" ;; esac fi rm -f $dummy.s $dummy echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit 0 ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit 0 ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit 0;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit 0 ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit 0 ;; *:OS/390:*:*) echo i370-ibm-openedition exit 0 ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit 0;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit 0 ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; i86pc:SunOS:5.*:*) echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit 0 ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit 0 ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit 0 ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit 0 ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit 0 ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit 0 ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit 0 ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit 0 ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit 0 ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit 0 ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit 0 ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD $dummy.c -o $dummy \ && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit 0 ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit 0 ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit 0 ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit 0 ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit 0 ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit 0 ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit 0 ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit 0 ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit 0 ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit 0 ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit 0 ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit 0 ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit 0 ;; *:AIX:*:[45]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit 0 ;; *:AIX:*:*) echo rs6000-ibm-aix exit 0 ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit 0 ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit 0 ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit 0 ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit 0 ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit 0 ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit 0 ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy` if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi rm -f $dummy.c $dummy fi ;; esac echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit 0 ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit 0 ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit 0 ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit 0 ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit 0 ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit 0 ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3D:*:*:*) echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit 0 ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit 0 ;; i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit 0 ;; x86:Interix*:3*) echo i386-pc-interix3 exit 0 ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i386-pc-interix exit 0 ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit 0 ;; *:GNU:*:*) echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit 0 ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit 0 ;; arm*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux exit 0 ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; mips:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef mips #undef mipsel #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=mipsel #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=mips #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` rm -f $dummy.c test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit 0 ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit 0 ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit 0 ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit 0 ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit 0 ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit 0 ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit 0 ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit 0 ;; i*86:Linux:*:*) # The BFD linker knows what the default object file format is, so # first see if it will tell us. cd to the root directory to prevent # problems with other programs or directories called `ld' in the path. # Set LC_ALL=C to ensure ld outputs messages in English. ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ | sed -ne '/supported targets:/!d s/[ ][ ]*/ /g s/.*supported targets: *// s/ .*// p'` case "$ld_supported_targets" in elf32-i386) TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" ;; a.out-i386-linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" exit 0 ;; coff-i386) echo "${UNAME_MACHINE}-pc-linux-gnucoff" exit 0 ;; "") # Either a pre-BFD a.out linker (linux-gnuoldld) or # one that does not give us useful --help. echo "${UNAME_MACHINE}-pc-linux-gnuoldld" exit 0 ;; esac # Determine whether the default compiler is a.out or elf eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include #ifdef __ELF__ # ifdef __GLIBC__ # if __GLIBC__ >= 2 LIBC=gnu # else LIBC=gnulibc1 # endif # else LIBC=gnulibc1 # endif #else #ifdef __INTEL_COMPILER LIBC=gnu #else LIBC=gnuaout #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` rm -f $dummy.c test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit 0 ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit 0 ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit 0 ;; i*86:*:5:[78]*) case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit 0 ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit 0 ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit 0 ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i386. echo i386-pc-msdosdjgpp exit 0 ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit 0 ;; paragon:*:*:*) echo i860-intel-osf1 exit 0 ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit 0 ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit 0 ;; M68*:*:R3V[567]*:*) test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4.3${OS_REL} && exit 0 /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && echo i486-ncr-sysv4 && exit 0 ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit 0 ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit 0 ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit 0 ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit 0 ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit 0 ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit 0 ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit 0 ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit 0 ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit 0 ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit 0 ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit 0 ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit 0 ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit 0 ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit 0 ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit 0 ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; *:Darwin:*:*) echo `uname -p`-apple-darwin${UNAME_RELEASE} exit 0 ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) if test "${UNAME_MACHINE}" = "x86pc"; then UNAME_MACHINE=pc echo i386-${UNAME_MACHINE}-nto-qnx else echo `uname -p`-${UNAME_MACHINE}-nto-qnx fi exit 0 ;; *:QNX:*:4*) echo i386-pc-qnx exit 0 ;; NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit 0 ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit 0 ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit 0 ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit 0 ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit 0 ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit 0 ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit 0 ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit 0 ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit 0 ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit 0 ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit 0 ;; *:ITS:*:*) echo pdp10-unknown-its exit 0 ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit 0 ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0 rm -f $dummy.c $dummy # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit 0 ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit 0 ;; c34*) echo c34-convex-bsd exit 0 ;; c38*) echo c38-convex-bsd exit 0 ;; c4*) echo c4-convex-bsd exit 0 ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: cfengine-2.2.10/ChangeLog0000644000175000001440000023173011170173446012053 000000000000002.2.10 Protocol fix, potential integer error in server decoding. 2.2.9 2.2.8 Patch for cfservd serving wrong data when link->copy Checksum changes now trigger persistent class "checksum_alerts" and log to WORKDIR/state/file_hash_event_history Threading error fix for cfexecd Windows compilation fixes. Note that windows users might have to move keys and files from /home/user/.cfagent to /var/cfengine after the standardization of administrator paths for windows where getuid != 0. 2.2.7 Memory leak in database access, affecting cfenvd 2.2.6 Xen detection Bug in popen - incorrect placement of conditional in setting groups added in 2.2.4. Sensor code added for linux cfenvd. Ready for patches for other systems. Cpu utilization and temperature measurement added for linux where available Bug reported in installable-negated classes. Patch by jack/SiliconSlick Bugfix for class defined by directories 2.2.5 No content changes since 2.2.4, just fixes a packaging error. (Mark's Easter turkey) 2.2.4p Blunder in makefile change. Compilation error fixed. 2.2.4 Build changes. libpub is now an installed library libcfpub.so/a so that cfengine 3 can find it. Documentation is no longer distributed in the tarball, since most people will use the online version. Also, enhanced documentation is now available for any user who registers (free) at cfengine.com. compress=true option in tidy was missing from documentation, and left uninitialized during purging leading to attempts to compress files instead of deleting. Bugfix for empty strings in editfiles. Links did not get removed with nolink=kill. Code changes apparently broken earlier. Fixed. rxdirs= added to files. Default is false. If set to true, cfengine will not assume that x-bits should be set when r is set on directory permissions. Group initialization to popen, so shellcommands groups are consistent with uid login id Rpm fix for package removal. 2.2.3 Feedback release after 2.2.2 and LISA 07, minor tweaks and bug fixes "Harmless features" IgnoreInterfaceRegex( "vm.*" ) added to control function added for removing data from special interfaces from class data Option checkroot=true/false added to copy directive. This switches on/off the change in 2.2.2 about setting permissions on the destination root when recursively copying files. Default is now false. Can escape colons in the strings now to avoid confusion with expansion separator. cfenvgraph --erasehistory users,www_in etc will now set the average and variance of learned cfenvd data to zero. The current week's trace is not affected. audit=true/false flag added to most actions 2.2.2 The build procedure for cfengine changes in this version to incorporate an intermediate library. The default behaviour is now to build a static library which will be used by cfengine 3 and other application interfaces. To build a shared library, use --enable-shared=yes NOTE to developers: if running from the compiled code you now need to delete the files cfagent cfservd etc and recompile to see changes appear in the code. This is due to the libtool build process. libtoolizing compilation process for migration to cfengine shared library (this is to support mulitple interfaces in future, and cf 3) -- XML and HTML output options added to equip the internal instrumentation with readable output in cfshow e.g. cfshow --performance --html > output.html firefox output.html provides an easier summary and searchability in browser function Instrumentation changed to use realtime functions where possible. Standard unix timer is too insensitive to measure performance. The beginning of an integrated auditing system has been added. See references to AuditLog() in the code. This logs to a compressed database and can be extracted in ascii, html, xml using cfshow, e.g. cfshow --audit --html > output.html Auditing is switched on by control: cfinputs_version = ( 1.2.1 ) # record this version in log, e.g. cvs revision Auditing = true -- cfshow --classes also shows the relative frequencies of classes that have occurred on the system and the last time these were observed. cfshow -f cfagent.conf --regex "lin.*" displays all rules in the named file whose classes match the named regular expression. Note that the class "any" is not automatically matched and the search is based on the class text from the file. The output is not related to which classes are currently defined, and it will not recognise the history of classes implicit through class-restricted imported files. -- SCLI interface modifications. -- Intermittency entropy code added to the copy instrumentation for automatic host reliability measurements. Special variable IgnoreFriendRegex = ( regex ) prevents last-seen warnings about hosts matching the named regex -- UserExists("name") and GroupExists("name") functions added to builtin functions. ClassMatch function added in classes/groups to match regular expressions of other classes -- Additional octet variables added on default IPv4 address, for convenience: e.g. 590 : ipv4_2[eth1]=192.168 1895 : ipv4[eth1]=192.168.1.101 2100 : ipv4_1[eth1]=192 4049 : ipv4_3[eth1]=192.168.1 Methods can now expand some list variables, one list only per argument set. This is a limited compromise pending cfengine 3. A patch for expansion of variables in the control part of a program in methods has also been added. Bug fix and code simplication of variable expansion. ----- tied variable expansion added. Allows method workaround for file dissemination by name, e.g. copy from host1.conf -> /dir/host1/file.conf host2.conf -> /dir/host2/file.conf e.g. for virtual or diskless machines ----- Major changes to package manager code by Jo Rhett. Variable expansion fixed by Mark. ----- Option "best" added to checksum= in files action, this allows cross checking of the two best known hash algorithms for each file. Currently this is md5 and sha due to limitations in OpenSSL libcrypto. UnCommentToLineMatching regex added 2.2.1 scli: type section added. This is a special case of shellcommands, which send commands to the special shell scli by Juergen Schoenwaelder for communicating with snmp devices. Code refactoring for package management. Bug fixes for problems introduced in 2.2.0. Copy directory would not set owner correctly on root 2.2.0 Apart from minor changes, this version is about structural internal changes that ease the eventual confluence with cfengine 3 and the work going on behind the scenes there. Every effort is being made to make this change easy for users and existing installations. New features will be introduced into 2.2.x gradually, and the new front-end will eventually merge into this. This version accompanies a new introduction to cfengine published as a SAGE Short Topics book. * Some changes EMANICS extensions and reference testing for context sensitive network navigation patterns using voluntary cooperation contracts. PrintFile("name") function added to alerts !! List expansion in editfiles actions. This is an important change because it can potentially affect existing configurations that contain variables with a list separator in them. EditSplit is used for this. elsdefine fixed in tidy processes with action=warn only install fix ifelapsed/expireafter fixed in editfiles Instrumentation of copy/shellcommands measuring time/averages use cfshow --performance background=true in shellcommands was not implemented! (Fixed) SLES10 recognition RedHat/Fedora further classes SELinux support begun by Jeff Sheltren UCSB, who notes. > Currently, I have editfiles and copy working with selinux security > contexts, although so far copy only has support for regular files; I > haven't worked on links, etc. yet. > Use --enable-selinux during compilation Bug / misleading error message in ReadArray fixed HostRange bug for numericals in hostname fixed by Steve Radar. 2.1.22 IMPORTANT: cfshow output formatting changes database internal format changes Rewritten the checksum subsystem to allow for future development and improvements and tidied the fragile Berkeley DB code. Cfservd no longer caches checksums, as this causes update issues. This could lead to additional load. The checksum code has been rewritten with a new database model, so all old data will be rebuilt. The checksum database has been renamed. ChecksumDatabase variable is not longer used. Package manager debian patch added to iterate over packages under installation. Package manager for AIX code added, courtesy of Anthony Rassin Package manager for Gentoo added, courtesy of Eric Searcy ShowState(rootprocs), ShowState(otherprocs) added for better process reporting General code reorganization for better separation of concerns, looking towards cfengine 3. cfconvert removed. Change of future strategy for cfengine 3 migration. Rationalization of internal instrumentation and better integration with cfenvd. Bug fixes to miscmounts. Editing was broken with respect to editfilesize variable. Option processing for miscmounts was also broken. Support for old Berkeley DB APIs abandoned. Encryption level added for full encryption of opendir traffic. Must set FullEncryption = ( true ) in control for compatability server=none now signals noop in method execution and copy. Varstring expansion bug for nested variables. 2.1.21 copy action now supports this $(this) variable which is made equal to the current server. This allows separating files from multiple hosts when downloading. cfenvd LDT fixes Bugs in PeerLeader/Group functions fixed. Some buffer limits too small and hardcoded in item.c - fix PH support removed from cfenvd during code rationalization - never used Cfenvd code rationalization and channge in database format. THe first time cfenvd runs, it will convert the database into the new format, be aware that this could take some time as it is disk intensive. Matt Shibla (ARM) ReturnsZeroShell function added. Cfrun ignored port number, fix 2.1.20 ipv6 structure compilation error for Tru64 Tested for compilation with latest Berkeley4.4-NC New option in cfservd.conf "LogEncryptedTransfers" (true/false). If true, any file that is granted access and is marked "encrypt=true" will be logged in syslog. i.e. one can keep a record of sensitive transfers. Linkcopy fix in 2.1.19 broke copying of links that point nowhere. Fixed. Copy was missing from the multi-pass detection. Fixed Patch to debian package management. (bastiaans@sara.nl) fixed - debian package always returned eq/true without cmp/version statement" (checking if a package is installed, regardless of version, now works However the "Comparison result" is always "eq" (equal) somehow for me... " If you are experiencing problems with 2.1.19 please get 2.1.19a. One of the changes in 2.1.19 has had bizarre side effects in links and disks. 2.1.19 cfagent will now exit and cease processing if any class in the defined control list AbortClasses = ( class_name_1 class_name_2 ... ) The singlecopy feature has been rewritten after reports of it not working, besides, the code was bizarre and the documentation was even worse. The autodefine code also patched and tested. In both these cases, there are lists of *patterns* or wildcards. The code and docs now agree ExecResult now runs its command in -n mode Error parsing strings (esp shellcommands) that contain the $ symbol due to a bug in 2D-lists. VMWare ESX recognition. Bug in cfservd stat-mode on symbolic links not correctly evaluated. Bug in linktype=copy for copy fixed. Bug in array expansion fixed - would truncate string after expansion Constant-cosmetics and length alterations. CF_SMALLBUF introduced, and MAXHOSTNAMELEN used PID file added for each daemin in WORKDIR == /var/cfengine Patch for function argument parsing Typo in docs. SelectPartitionGroup -> SelectPartitionNeighbours Inform=true support for packages HostRange bug - recoding not implemented properly from 2.1.16. Caused seg fault. Joe Buehler's harmless patch to cfexecd to flag daemon and batch mode. Serious bug in binserver handling fixed. (Rarely used feature) home tidying did not set the "done flag" for multiple pass avoidance. Patches to setting unqualified and qualified names SuSE 10 detection patch Minor error fixes discovered by Joe Buehler and his wonderful software. Files is the "suspicious" list were marked "not sensible" so that follow-up rules e.g. to delete them would not be triggered This is now considered a confusion of roles. Suspicious files are no longer skipped. More memory leaks in cfservd Compilation fix for non-IPv6 savvy machines 2.1.18 Error in FileExists() left over from 2.1.16 changes. Fixed elsedefine was not defined if a copy was requested of a non-existent file. Fixed. HostnameKeys (dynamic keys for dhcp clients) fix for cfservd. Error in stat'ing links that point to non-existent files in cfservd. Missing "else" caused this to be reported as an error in remote file copy. 5 second timeout reduced to 10 in cfservd file change check. Error message returned by cfservd is non-specific and previously said authentication denied, regardless of failure. The daemon now replies "Unspecified refusal". Users should use -v or -d2 on both sides of a connection to diagnose the true cause of failure, Segmentation fault when in verbose mode fixed - editfiles pointer. Error in parsing quotes and escaped quotes in functions. Bug in implementation of tidy scheduling during dependent classes fixed. BeginGroupIfLineMatch BeginGroupIfMatch BeginGroupIfLineContaining operations added Function ExecShellResult similar to ExecResult, but a shell is used, cfservd some additional memory reclamation during file updates, could cause memory leaks.. 2.1.17 This is a minor bugfix release WARNING - the handling of function arguments has been changed. You are recommended to use normal C/Perl quoting of argument strings., e.g. result = ( ExecResult("/bin/sh -c \"${pf_cc} -V | head -1 | cut -d\ -f3\"") ) not result = ( ExecResult(/bin/sh -c "${pf_cc} -V | head -1 | cut -d\ -f3") ) IsWildItemIn now has reflexive check - some confusion in the code about whether the needle or the haystack is the wildcard. Templating in editfiles. A new editfiles directive "ExpandVariables" adds an "m4" like function to cfengine -- allowing predefined variable strings to be expanded into text. Patch contributed to expansvariables: Davor Ocelic Alerts patch - some alerts not installed, if classes not defined. Patch for missing variable expansion after function parameter rewrite in 2.1.16. Some functions were not fully ported. vicf eliminated from distribution PrepModule environment fix Compilation error C++ mixed into cfetool fix Chdir to / when ascting as a daemon for cfservd, cfexecd etc 2.1.16 Bugfix release Moved method parameter setting to fix a bug where parameters would be set too late to be used in the parser action=warn in copy required inform=true to work, fixed. Function arg expansion bug and improvement fix Include directive added to cfrun.hosts (Olivier Fauchon) MOUNT_RO name collision fix SEG fault fixed when signalling cfenvd SkipIdentify partial fix Alf Wachsmann and Elizabeth Cassel's cfetool added, based on cfenvd. "cfetool makes a standalone tool out of cfenvd that accepts arbitrary periodic data. In addition, it has support for yearly periodic data. It's function and the user interface is in many aspects like rrdtool's. cfetoolgraph was added to work with the new features of cfetool. It works basically like cfenvgraph." Bug fix for multipass evaluation when resolving dependencies. Cfservd reread patch. Timeout on polling for linux, Default route code now uses "route" command exclusively for portability. EmailFrom patch to cfexecd / redundant code was paste error Increase pass depth in evaluation of action sequence. Skipident patch Size increase for interface buffer list HPUX,AIX ifconfig location fix Methods documentation improved. New control function for testing tcp services var = ReadTCP(host,port,"send string",maxbytes) 2.1.15 -f removal in cfservd patch Segmentation fault in cfservd with RSA key exchange fixed. Disk freespace alerting bug - did not agree with manual specification. Message appears only in verbose. Fixed. Autodefine install patch. Abspath in shellcommands was not parsed and acted on... Warnall action was not respected in copy. Permissions were altered on destination file anyway. cfcolon added to special symbols. 2.1.14 Alerts processed now in update context. More locking canonification fixes Exception for ReplaceALL convergence warning. Warning is not fatal if the operation is inside an editgroup. md5/sha1 message incorrect on new file found. Fixup Makefile.am and doc/Makefile.am. Docs are now installed in the CFEngine "share" directory where they belong. Directory iteration fixed. New: owner=LastNode sets the owner of the directory to the name of the last node in the dir name. This allows the creation of homedirs. CentOS support added. Extra encryption stage added in C5 protocol. NOTE: This makes 2.1.14 cfagent clients unable to talk to older servers. (Upgrade servers first, or at the same time.) Class "no_default_route" is now defined if a default route is not previously set, and a default route is defined for the current host. Added class functions IsGreaterThan, IsLessThan for numerical or string comparisons control: actionsequence = ( files ) a = ( 2.12 ) b = ( 2.11 ) classes: lt = ( LessThan(${a},${b}) ) gt = ( GreaterThan(${a},${b}) ) alerts: lt:: "$(a) LESS THAN $(b)" gt:: "$(a) GREATER THAN $(b)" Bugfix for cfshow -c options (Nathan Hruby) 2.1.13 Mistake in placement of update.conf runs fixed. Alteration to lock hashing to avoid conflicts Mandrake version type patch/repatched Error message in disable now underlines move to respository where defined. Locking patch to tidy. Did not release lock when tidying recursively with subdirectory deletions. (Eric Sorensen). Host range patched (again) (Bas VdV) 2.1.12 cf.preconf can now cause an abort if the script prints out a string containing the substring "cfengine-preconf-abort". An exit code of 2 signals this failure Cfrun bug in placement of workdir initialization. Would try to open /inputs/cfrun.hosts instead of /var/cfengine/inputs/cfrun.hosts Moved mutex locks in address purging, to see if it prevents some segmentation faults. In image.c: /* if (TRAVLINKS || ip->linktype == 'n') */ Took out linktype reference. This appears to be erroneous. Patch to tidy: "Guolin Cheng" Patch to -Q to prevent update.conf from being executed. Patch to rationalize choice of port number for new getaddrinfo interfaces. (ip.c) small patch to allow the use of PCRE if it is compiled with --with-pcre. This is using the POSIX compatible API that PCRE provides, so the change necessary is to use pcreposix.h instead of regex.h and to link in pcreposix.so. cindy.marasco@pnl.gov) 2.1.11 SUPPORT FOR POSIX ACLS IN LINUX IS NOT AS STRAIGHTFORWARD AS ORIGINALLY THOUGHT. THE API DOES NOT MATCH EXISTING IMPLEMENTATIONS AND SEEMS SIGNIFICANTLY MORE COMPLEX. IN THE INTERESTS OF STABILITY THIS WILL HAVE TO BE DEFERRED TO A LATER RELEASE. Comma in function argument bug in FileExists etc, fixed Option -z (--schedule) now prints only the run schedule. Option -Q (--query) added to print values of variables defined in configuration cfagent -Q sysadm,domain,site,ipaddress in format varname=value New variables can be used in cfagent.conf for cfexecd control: EmailFrom = ( ) EmailTo = ( ) - overrides sysadm if set White Box linux class recognition added When setting classes or variables by function call, the function evaluation is no longer performed if it is not in an active class. Cfexecd now calls cfagent with -D from_cfexecd to define the class "from_cfexecd::" when run from the executor WarnIfFileMissing added to editfiles and default is not to warn of non-existent files, except in inform/verbose modes. Check added for DefineInGroup, signals error if not in group Added copy type "any" for any matching criteria, date/sum etc. Respository variable was not expanded like a normal variable cfshow tool added for consulting the databases Better autodetection of Berkeley DB in some distros of Linux (SuSE) - has anyone heard of "standards"? Date format changed in cfexecd output files Errors if remote copy is not encrypted when server demands encryption. (patch) Renaming of directories is now allowed if dest= is set specifically. Check added for variables defined in terms of undefined variables. Patch for solaris package manager added (Louis Erickson - wwonko@rdwarf.com) file added as synonym til reg in filter Patch to HostRange (item.c) (rader@ginseng.hep.wisc.edu) Internal variable determining WORKDIR for non-privileged users. Various minor changes and cosmetics. Lock string must include server name in copy - added Method reply bundles fixed to work correctly with ipv6 addresses SIGPIPE and SIGCHLD added to signal handler (SIGCHILD ignored against posix, but how the hell do you sort this out?) srand -> srand48 typo in cfenvd Multiple method reply variables were incorrectly separated. Added options to disable LastSeen data recording feature. fclose used instead of pclose when calling ifconfig - resulted in zombies 2.1.10 Persistent class protection added to returned remote vrpc calls to prevent meaningless multiple replies. Change added to IPRange to avoid possible bootstrap problem with unconfigured resolver. IP address setting was contingent on having DNS. Misplaced } fixed in nameinfo EmptyResolvConf removed only nameserver entries. Now removes everything. Due to an error in constructing 2.1.9 some of the advertised changes below were not included. They are included in this version. Workaround error message for parser bug with nested variables. 2.1.9 WORKDIR/state/allclasses file caches all class date during cfagent execution, just like the $(allclasses) variable, but the file can grow much larger without overflow. .cfengine -> .cfagent in non-root public keys (some missing conversions) Expand buffer incorrectly zeroed out public name key causing empty keyname in RSA dialogue Old style bind reverse lookup added to Hostname2IPAddress 2.1.8 Additional checks added to bolster server transaction security. Fix of bug in copy server variable list expansion (unexpanded variables) introduced in 2.1.7 Typo in locks fixed Mutex deadlock fix in cfservd for systems with up to date POSIX implementations. QNX class data added Syslog facility patches to cfservd. (Leonardo Helman) Fix to avoid recursive imports Variables were not expanded in PrepModule Symbolic links were not tidied Missing initializations in links could dump core Logging route switching bug in disk/required fixed Bugs in implementation of remote method protocol. Classes were not transferred properly. Bug in HostnameKeys for cfrun fixed. 2.1.7p1 Bug in resolv node introduced in 2.1.7. Ordering of nameservers was reverse. 2.1.7 Mandrake Linux detect patch Unbelievably no documentation about strategies ever found its way into the manual!! Fixed. Sorting of anomaly histogram data Date patch for SMTP in cfexecd Bugfix for TTime filters in ParseTTime() - submitted Bob B. Crosbie. Trinity Centre for High Performance Computing, ReplaceFirst function to replace first occurrence of a string in line. Umask saving patch in editfiles (Sergio Gelato) Patch for variable socket length structs (BSD) Apparent bug in local methods from recent change. Name localhost would be converted into an address which would then fail to match hail. Iteration over server= variable in copy added Iteration over resolver variables added Bug in class evaluation was introduced in 2.1.6 by a sorting algorithm. Some classes would evaluate to false even though true. Default route setting has been broken in linux for a long time. A workaround has been added using the shellcommand /sbin/route Bug in rmdirs in tidy - old type mismatch corrected. Might cause cfengine to delete an empty root-search directory undesirably. Some bizarre coding in the resolver section replaced. Could lead to incomplete class data. Added option SkipIdentify = ( true ) for avoiding DNS lookup in client side authentication. Bug in method evaluation if peers have inconsistent resolvers and cannot agree on whether to use IPv6/v4. ReadList() function added to control for reading an iterator from a file 2.1.6 Patch for incorrect symbolic link resolution with ".." internals. Would chop off a leading slash. Patches for alerts appearing twice. InitAction added in install.c --with-docs option added and default is to not build the docs Change to df.c to avoid rounding errors in small blocks for linux wait status patch for returnszero() dpkg debian package management support (Morten Werner) tidy rmdirs=all did not remove top directory since v2.0.0. Fixed. Problem was new method to aviod races can never reach this location, so have to use absolute path for top dir. DARWIN patches to cfservd.c/ip.c to fix definitions Separate ExpandVarstring buffer-size with new expandsize value This removes some spurious use of VBUFF scratch space. One bug in tidy path expansion found here. Variables were not expanded. 2.1.5 KNOWN BUG in persistent state memory for tcpdump data - long ipv6 addresses can make a byte count > old for fewer incoming so it remembers wrong snapshot Double DeleteParser() fixed. Code cosmetics: Annoying tabs removed from sources bzero -> memset explicitly bcopy -> memcpy Segmentation fault in list handling fixed (seldom occurrence) 2.1.4 "Bug" found in method recognition - only constant parameters allowed. Time of day or relative hostames as parameters will not work Mutexes around locking now. Variable expansion of server deferred in copy to allow dynamic server choice Removed old dns lookup caching for ipv4 - means no prior check for existing hostnames, but allows running with dynamical variables -q option added to cfexecd. If set it invokes cfagent with -q flag (--no-splay) Rewritten function analysis for multiple arguments in assignments ReadTable() and ReadArray() functions to read associative arrays from files hpux class changed from 9000* to * in class matching. Assume old versions now dead tcpdump interface for cfenvd Attempt to detect ipv6 address from ifconfig on unix and add classes. Cannot yet bind to interface. Make internal list representation of IP addresses. Error in -f evaluation introduced in recent version fixed. Bind to outgoing interface implemented for new getaddrinfo libs functions. Same of fior cfservd BindToInterface = ( ) editfiles additions: DeleteLinesContainingFileItems @var{filename} DeleteLinesMatchingFileItems @var{filename} DeleteLinesStartingFileItems @var{filename} DeleteLinesNotContainingFileItems @var{filename} DeleteLinesNotMatchingFileItems @var{filename} DeleteLinesNotStartingFileItems @var{filename} AppendIfNoSuchLinesFromFile @var{filename} Special function added to alerts: FriendStatus(hours) shows hosts that have not reported in for hours. 2.1.3 Voluntary RPC remote methods implemented. Bug in ignore when doing file recursion fixed. Wildcard match did not include plain files when expanding wildcards Internal array representation added to expression evaluation $(array[key]) $(array[$(key)]) Arrays may be defined using the association function: assoc_array = ( A(B,"is for bird") A(C,"is for cat") ) 2.1.2 Various minor patches singlecopy locking patch (Eric Sorenson) Patches Iain Morgen (NASA) cfexecd add From line to mail RegCmp(regex,$listvar) function added to match classes Documentation of iteration added to reference manual - was missing. Domain variable was overwritten in 2.1.0 when methods were initialized. Corrected. Cfexecd #ifdefs not compatible with cygwin - rewritten workaround Entropy measure anomaly classes Comparator uninitialized in process matches, creating bogus outout with -d3 Chop function removes all trailing spaces. interfaces now records ip addreses Variables can override context using a dot notation: ${context.variable} ${global.env_time} Interface addresses on multiple interfaces: ${global.ipv4[hme0]} ${global.ipv4[eth1]} cfservd list handling bugs after user patch, plus enchanced iteration: e.g. now make multiple rules in a sinlgle stanza control: Split = ( " " ) hostlist = ( "10.10.10.1 10.10.10.2 10.10.10.3" ) dirs = ( "bin etc lib" ) base = ( /usr ) ######################################################### admit: $(base)/$(dirs) $(hostlist) results in: Path: /usr/bin (encrypt=0) Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root= Path: /usr/etc (encrypt=0) Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root= Path: /usr/lib (encrypt=0) Admit: 10.10.10.1 10.10.10.2 10.10.10.3 root= Allow modules during parsing to initialize classes etc. control: gotinit = ( PrepModule(startup1,"arg1 arg2...") ) classes: gotinit = ( PrepModule(startup2,"arg1 arg2"}) ) 2.1.1 Permissions on explicitly mentioned links to files could result in file permission being changed instead. Error in permission evaluation for copied files fixed. Mac OSX finder patches added ID classes rationalized into nameinfo.c scanarrivals option to disks/required - for research. Improved anomaly analysis. setting repository in cfservd.conf caused crash - fixed. & is now a synonym for "." - the AND operator in class evaluation ! negation of functions in class assignments is now handled New option noabspath=true for copy allows one to override the need for a full path in certain situations, e.g. "export A=x; /dothis"" Redhat 9 class names patch JY. Case insensitive domain matching 2.1.0 ************************************************************************************ * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * * * * * Main addition to 2.1.0 is * methods *. Methods replace modules for most applications ========= * * * * * * * * * * * * * * * ** * * * * * * * * * * * * * * * * * * * * * * * * * * ************************************************************************************ Error in cfenvd update policy for huge anomalies. Could never learn large values. New parser did not pick up restart sequence in processes if not enclosed by quotes. Bug in AppendIfNoLineMatching - infinite loop is SetLine not set, fixed, ExecProgram was incorrectly listed as Exec in filters. fixed Minor alterations to cfenvd policy. Calculational details, and persistent information now lasts up to 30 minutes. Patch for red hat enterprise server classes New variable HostnameKeys = ( true ) if this is set, public keys are stored as user-hostname rather than user-ipaddress. This can be useful for dhcp hosts. However, there is a potential loss of security during key-exchange due to implicit reliance on DNS or asserted identity. ------------------------------------------------------------------------------ DeleteItemNotMatching added to editfiles DeleteItemNotStarting added to editfiles DeleteItemNotContaining added to editfiles SyslogFacility = ( ) new variable to alter syslog facility level. Possible values: LOG_USER, LOG_DAEMON, LOG_LOCAL0-4 -------------------------------------------------------------------------------- Persistent state memory can be added through a system alert functions: SetState(name,ttl,policy) Set a class that acts like a non-resettable timer. It is defined for exactly 10 minutes SetState("preserved_class",10,Preserve) Set a class that acts as a resettable timer. It is defined for 10 minutes unless the SetState call is called again to extend its lifetime. SetState(non_preserved_class,6,Reset) Delete a persistent class. Delete an existing class: UnsetState(myclass) -------------------------------------------------------------------------------- rename: is now a synonym for disable: and a new option dest= is added to these so that you can formally rename a file with any destination, not just suffix ".cfdisabled" (though this remains the default). Classes now allowed in group / classes definitions for consistency and ANDing of classes Added to Alerts to send messages directly and silently to syslog SysLog(LOG_ERR,"Test syslog message") -------------------------------------------------------------------------------- b2 cfservd no longer does reverse DNS lookup on keys that do not have to be trusted, i.e. existing keys whose identity has been confirmed. Strategy evaluation was performed too late, so that it could not be used to define variables. Fixed. Now strategies are evaluated as soon as they are defined,, just define them at the start of the program.. Various minor patches. 2.1.0b1 Patch to packages for non linux rpm localhost method calls implemented - todo: multiple methods calls --------------------------------------------------------------------------------- KNOWN BUGS : Functions cannot contain both subfunctions and spaces in strings This will not be fixed until the language becomes fixed --------------------------------------------------------------------------------- Error in init.c erroneously referred to old directory .cfengine instead of .cfagent for non-root users. Builtin function ReadFile(filename,maxbytes) allows us to read a maximum number of bytes from a file into a variable e.g. control: mylist = ( ReadFile("/etc/passwd",20) ) Split = ( "_" ) # NOTE careful with split character myvar = ( ReadFile(/etc/passwd,220) ) 2.0.8 - released this far as a 2.0.x patch Check for illegal characters in classes. Able to bind to a specific IP addressed interface in cfservd. BindToInterface = ( 10.10.43.6 ) Security fix to transaction lengths in remote copying. Suspicious names now applies only to regular files 2.1.a8 Imports allowed in update.conf Extra locking applied to methods Parser error in cfservd fixed. Would ignore single character objects (ordering error in lexer). 2.10a7 Methods parsing added Granular locking added to all parts of cfengine ifelapsed expireafter added to each action as options e.g. ifelapsed=20 2.1.0a6 Admit /deny did not do variable expansion on pathnames - fixed Reduced stating level during file transfer in cfservd - helps to prevent thrashing when transferring files with server fragmentation. class "windows" is added as a synonym for "nt" xdev=true option to image, tidy, files Timeout added to receive in file copying mounts are only performed in pass 1 edit warnings are only carried out during pass 1 Bug fix for Mode class in file filters - was not matching modes properly Can't copy files less than 17 bytes now supposedly fixed Add mutex around syslog() to see if it helps weird file errors. 2.0.7p3 Parser bugfix for group defintions from script (in old compat obsolete syntax) 2.0.7 Resolv.conf search directive removed from code. This was wrong, in spite of pressure to put it in. EditBackup -> Backup corrected in manual Check for class definitions that are not installable SMTP client handling patch in cfexecd - must wait for reply AppendIfNoLineMatching replaced with regex, not Setline value ChecksumPurge = ( on ) causes cfagent to purge its checksum database of files that no longer exist. Forgotten built in function RandomInt(a,b) - returns a random number in variable assignments. Actually introduced in 2.0.6. Forgot this control: rand = ( RandomInt(4,7) ) Major rewrite of parser - code simplifications - Allowed escaping of quotes in strings and newlines e.g. var1 = ( "a b c\"substring\" d e" ) var2 = ( "a b c" ) Tidy code tidied and bug fixed for new scheduler Moduledirectory defaults to /var/cfengine/modules 2.0.6 SKIPVERIFY removed from AccessControl checks. This was wrongly allowing access to files if they only had an accepted encryption key. SetLine added to AppendIfNoLineMatching to allow current line to be added. ForEachLineIn "/tmp/in" AppendIfNoLineMatching "ThisLine" EndLoop Changed /etc/services reference to port 5308 in ipv6 compatible calls. Efficiency, removed getpwnam from GetFile(). Was unnecessarily looking up the uid multiple times, which delays copying speed. Copy rates improved by five to ten times!! Single copy uses too much cache memory. Optimize by only caching copies that use the singlecopy keyword. Message status change: %s is a link which points to %s, but that file doesn't seem to exist Verbose only Patches to editfiles to check empty files. DefineinGroup added. 2.0.5 Cfrun ipv6 patch Syslog messages name patch mountables, binservers variable usage fix backup=timestamp added in copy so that multiple backups can coexist. Other backups use this by default. Cfenvd records loadaverage - and av.db renamed to cf_averages.db since records in av.db no longer compatible. Iteration added to disk paths Typo in filters.c UID -> USER meant that Owner field in filters would not always work for processes. Bug in removal of spaces in process-filter matches could cause some criteria to fail to match. Netstat changed entry in solaris 2.9 Hard class hpux10 -> hpux and the old hpux is deprecated tidy //tmp would start tidying / due to error in ExpandWildcardsAndDo. FIxed Cfenvd netstat state recorded in separate files now in WORKDIR, by protocol and incoming/outgoing. This allows accurate record of the state to which classes refer. excludes and ignores would not appended in a tidy command if a path already existed in another previous command. Fixed so that all excludes and ignores are concatenated for all related paths. Local AF_LOCAL addresses not handled by sockaddr in IPv6 compatible functions. Now returns 127.0.0.1 (why not ::1??) Typo in tidy.c prevented tidy old links from working. Documentation patches. Checksums no longer performed on dry run (-n) in files, but still in copy. No errors written to syslog in dryrun mode. Umask patch in editfiles - umask was not properly installed New copy options / variables singlecopy= and autodefine added. Alerts added as own section alerts: allow users to define a custom message triggered by a class activation. Alerts can also quote state information from cfenvd and the process table. tidy define= does not set class if file could not be tidied. debian detect patch (Andy Stribblehill) cfservd descriptor leak (Andy Stribblehill) cfservd daemonize modification 2.0.4 cfexecd now reports identical messages only once per day. (Bas) *************************************************************************** File copying failover=classes sets classes if open server connection fails, or file is unavailable -- this allows failover rules to be activated instead. *************************************************************************** *************************************************************************** Evaluated classes added: IsDefined(varname) StrCmp(s1,s2) *************************************************************************** If a public key authentication succeeds, cfservd now adds a host to the skipverify list, so that we don't waste time checking ID by two separate methods. It has to succeed once though... and the is emptied if the config file changes, and we start over again. elsedef didn't work in processes New test in processes for executability of restart sequence would fail if the sequence had arguments. Fixed. --------------------------------------------------------------------------- "AUTHENTICATION" BUGS: This seems to have been due to threading collisions. Malloc is not thread-safe. Added mutex to NewConn in cfservd. This could cause new connections to be mixed up in memory, under heavy load and result in authentication failure on multiprocessor systems. Also changed pthread_mutex locking around gethostbyname - could cause reverse lookup to fail and create the illusion of a bad public key authentication. Implicit mallocs are also in some of the public/private key functions. Moved some of the mutexs to encompass these, and it seems to have fixed the authentication errors. Change in mutex locking policy of CheckFileChanges. Don't need a mutex there, just check that ACTIVE_THREADS is 0 and we're single threaded. --------------------------------------------------------------------------- Tidying directories with atime is meaningless, since the necessary stat'ing automatically invalidates the result except for age=0. Thus all directory time comparisons are now changed to mtime, regardless of the type. Default preview value for shellcommands was true - shuld be false. cfrun - with -T did not accept keys on trust (typo) fixed Classes defined within update.conf are now also private, like a separate module. These go away before cfagent.conf Typo in item-ext.c in regfree of GlobalRreplace led to segmentation fault for some edits. AllowRedefinitionOf = ( variable name list ) allows redefintion of the named variables during parsing. Editfiles scheduling error for classes not immediately defined, fixed. Inform=false didn't affect purge=true Setting chmod 000 on a directory could prevent 2.0.3 from fixing it. Fix for hyphen fix - can have numbers and hyphens in hostnames... Fix for freebsd fix...ugh IP address range minor fix >= -> > in lower range $ cfagent --avoid resolve,copy $ cfagent --just tidy --just shellcommands The latter does tidy and shellcommands, but nothing else in the action sequence. 2.0.3 import in cfservd.conf was blocked. update.conf run when doing -a or -z DESTINATION used in link.c (legacy) without allocation - caused segfault. IMPORT in cfservd was excluded -b for --update-only was used up, changed to -B (too many options!) hyphen in cfservd.conf admit/deny hostname was misinterpreted as IP range in 2.0.2 Fixed Interface detection on FreeBSD messed up. Fixed. Unknown edit command error in include/exclude. SECURITY : Recursive descent functions vulernable to race conditions. Directories could be replaced by symbolic links and this would affect any operation that relies on directory parsing; files, tidy, editfiles (copy is non-destructive). Recursive descent functions are reworked to check inode numbers and device numbers in order to detect attacks. This leads to a small inefficiency in recursive descent. The solution is to chdir to the actual directory concerned, check that it is the same one we stat'ed and scan only those relative names afterwards, so we freeze each directory one at a time. The problem only applies to systems who have non-trusted users. Editfiles error messages added for class definitions within conditionals. Some segmentation faults corrected. Check added to prevent cfagent from following links it does not own. Work around to delete cfparse.c from the distribution cause autoconf won't do it. This was causing incorrect alloca() usage for HPUX and AIX. 2.0.2 New option -b --update-only (changed in 2.0.3 to -B) Runs only the update.conf script Host ranges in IP addresses 128.39.89.10-34 or CIDR notation 129.39.89.1/24 to specify groups / classes or host lists in cfservd.conf. groups: myseries = ( IpRange(128.39.74-75.10-20) ) myseries = ( IpRange(128.39.74.10/24) ) 128.39.74.10/23 == 128.39.75.56 128.39.74-75.10-20 == 128.39.75.12 2001:700:700:3:290:27ff:fea2:4730-4790 == 2001:700:700:3:290:27ff:fea2:477b 2001:700:700:3:290:27ff:fea2:4730/64 == 2001:700:700:3:290:27ff:fea2:477b New list in cfservd.conf, DynamicAddresses = ( ipranges ) this assumes that hosts get IP addresses from DHCP or someting and can change over time. This changes the security model somewhat. (see reference manual) Bug in cfservd for files which were unreadably by the daemon. Could lead to incorrect file being transmitted instead of rejection. Changes to mount list. Can now include mount options in the cfengine mount model (see reference manual) Bug in classification of variable assignment and authorization assignments fixed. Structures for convergence analysis added. Option -g (future work) NAT handling in cfservd.c patch Signal names were wrong in some cases due to differing conventions - OS dependent. Incorrect code in file time filter comparisons fixed. License ammendment in COPYING makes it clear that users are encouraged to use the OpenSSL library. I see no problems with this. Purge exclusions segfault bug fix. Purge should not purge patterns in include= (fixed) Purge symbolic link error fixed. (Bas) /* Bas The following patch helps with the, for me at least, irritating problem where I have a cf. file which has sections depending upon classes which do file checks or copy based upon a user/group which doesn't exist on certain machines :- flagisoff:: file owner=user group=group cfengine complains about this even though flagisoff is off :-) It also means that a user can be created earlier in a configuration and used later on without the warnings. Anyway patch does :- - don't complain about missing uid/gid while parsing - set uid/gid to -2 if missing and copy the name to the uid/gid structure - when actually doing things, recheck to see if the user exists use it if its now found, otherwise complain */ SMTP \r added to cfexecd, caused problems for stricter mailers. (I wasn't reading RFC2822!!) Connection from version 1 client could cause version 2 server to segfault. Fixed uninitialized field. If we specify purge, then the following options will also be set and cannot be altered: forcedirs=true typecheck=false - for safety sake. Some windows patches. 2.0.1 Some error messages demoted to verbose only Some documentation corrections cfenvd given a -H option for histogram measurement. (research) More problems with configure finding libraries fixed Extra time classes Q1,Q2,Q3,Q4 are set in each quarter of the hour. Also abbreviations of HrXX.Q1 ca write Hr12_Q1, for instance. VSYSTEMHARDCLASS was not defined in cfservd tidy .cfengine files could have permission 777. Missing permission added. openbsd bind() fix in cfservd - openbsd does not map ipv4 addresses in ipv6!!! error in assigning hardclass for openbsd (typo) and this affected several other operating systems. Fixed 2.0.0 Hpux config changes Red Hat compilation issues with Berekely DB cfservd.conf did not re-read input file properly if -f was used. mode checks patch (Martin Jost) GNU autoconf classes renamed to compiled_on_solaris2.7 Cfengine 2.0 ---------------------------------------------------------------- b4 configure changes to compile on systems without pthread. Increase thread stacksize to avoid seg fault on some systems, which set a small basic pthread stack. parser checks update.conf on -p bug in reading imported files if CFINPUTS set to non-abolsute path b3 Some typos and solaris memory error fixed, in cfpopen(). Add optional argument to disable to warn only about existing files. Modules no longer time-locked b2 IPv6 implementation Bug fix in access lists of cfservd a23 Added support for variable and class built-in functions. a21 Martin Andrews' NT/Windows patches incorporated. a20 Code tidying a19 cfrun fixed for RSA usage, and AllowUsers = ( ) added to cfservd.conf Bas' NAT fixes to cfrun included BeginGroupIfDefined in editfiles incorporated a18 Symmetric key encryption rewritten, using Blowfish and RSA key exchange Several efficiency modifications have been added, and this change allows for future multiple enryption schemes. install.c rationalized, to standardize true/false switches Standardedized true/false api in switches with HandleCharSwitch. Internal representation is now 'y'/'n' not t/f and y/n. verify= added to file transfers allowing cfengine to compute an MD5 verification of the transmitted data before installling. secure= -> (encrypt=,type=) split up, so encryption can be used independentently of the update method. a17 RSA authentication added cfkey changed to generate public/private keys a16: Cfagent will now attempt to rename non-directories which are "in the way" during copying, if forcedirs=true The function MakeDirectoriesFor thus has a new argument for whether this should be forced or not. THe policy regarding other uses of the function has changed: - For creation of essential cfengine directories, it is compulsory - For other optional actions dirs a re not forced exclude= and ignore= now allowed in tidy include= is a synonym for pattern= Replace old checksum functions with OpenSSL interfaces. Larger checksum database, due to longer hashes. Can now have checksum=sha1 in files. Checksum databases will be rewritten in a new format, as the datasize has changed. Might result in checksum changed warnings when installing new version. Editfiles scheduling bug, with new scheduler, fixed. Classes specified in the action sequence would not be executed. Exclamation = ( off ) - to switch of exclamations in alerts % included in filename spec a14/15: Compilation issues. Restructuring and fiddling with cfenvd. a13: control option EmptyResolvConf = ( true ) removes old nameserver entries. Bug fix in file copying. A missing test could cause problems when cfservd was remote copied by itself, if error strings were aligned on page boundaries. Typo in popen.c fixed. Shouldn't have any effect on code. Hosts with multiple interfaces now register all subnets as classes. Now adds ipv4 address groups in the form ipv4_128_39_89 ip43_128_39 ipv4_128 Owner filter added to process filters (oversight) a12: Editfiles filters implemented cfengine.conf -> cfagent.conf WORKDIR = LOGDIR = LOCKDIR = /var/cfengine (like /var/mail) /var/cfengine/bin - default local binary /inputs - default inputs dir /outputs - record of old runs cfexecd a replacement scheduler. Used as cfexecd -F (no fork) it can be placed in cron to replace "cfwrap cfengine". It needs you to define smtphost = ( smtpmailer ) in cfagent.conf. This program stores the output of cfagent in the outputs directory and then mails a copy if smtphost or sysadm are defined. It truncates long mail. Cfengine could be used to pick up the output files for collation by a central monitor, if desired. Cfengine now looks for a config file called /var/cfengine/inputs/cf.update which is run before the main configuration. This is intended to be used to get an updated configuration, so that it can be parsed immediately afterwards. If there is an error in cfagent.conf, cf.update will still be able to run. Don't forget to move the keys file to /var/cfengine a11: resolver uses search directive, deprecating "domain" once and for all. This might hit really old systems...? Using shellcommands to set classes noe suppresses output from command. a8: snprintf for added security or just for certainty, where appropriate. If CFINPUTS is not defined, cfengine will look in CONFIGDIR for input. Files are always checked for their security by checking the owner and permissions. --with-lockdir=LOCKDIR deprecated --with-CFINPUTS=CONFIGDIR - default CFINPUTS internal (/etc/cfengine/inputs) Extensive changes to locking policy. LockDirectory = () LogDirectory = () --- are no longer configurable from cfengine.conf due to required compatibilty with cfenvd.c cfenvd added. Records long term data and transfers class information to cfengine aboutthe average state of the system. Classes pin- also defined for every open service-port on the host. a6: undefined_domain is now removed from the class list when a proper doman is defined. This allows us to test for this as a class for debugging. recurse option in home tidy now allowed. Option LogTidyHomeFiles to switch off generation of log files in user homedirs. Bug in DeleteToLineMatching, mismatch with documentation functionality. Fixed. Process options changes from ax to auxw for BSD-like ps. cfenvd introduced Some FreeBSD patches. Locking changed to use Berkeley DB if available Default workdir changed to /var/cfengine from /var/run since /var/run gets emplied on reboot in linux. Cfengine 2.0 -alphas--------------------------------------------------- * Expansion of $(dollar) broken in 1.6.0 - fixed * Locking problem in cfd fixed. Problem causing access denied while re-reading config files. MAXTRIES increased for high volume services, was causing premature apoptosis. dest= could not refer to a filename with spaces, fixed. * Made recipient variables in client.c long instead of size_t in rstat, for 64 bits. With %ld in scanf. * Cfengine 1.6.0-1.6.3 introduces filters into processes and files. * 1.6.3 change from Berkeley DB2 to DB3 - not backward compatible!!! Update Berkeley db with cd build_unix ../dist/configure make; make install ln -s /usr/local/BerkeleyDB.3.2 /usr/local/BerkeleyDB 2000-06-13 David Masterson * 1.6.0.a2: re-released to Mark after stupid mistakes. * src/Makefile.am (noinst_HEADERS): add cfparse.h * Makefile.am (EXTRA_DIST): add acconfig.h 2000-06-12 David Masterson * 1.6.0.a2: released to Mark * General: Attempted to convert to reincorporate all my Automake stuff into the release. 2000-06-12 Mark Burgess * 1.6.0-alpha1: released * General: Rewrite of DCE code by Transarc/IBM. Add elsedefine= tag as complement to define=. CompressCommand action=compress in files, tidy, compress=true for compressing files on the fly. Bug in copy with size= fixed. Was ignored if file didn't exist. Modules: in addition to setting classes, can return lines =ENVVAR=value which sets cfengine environment variables. This allows modules to set variables which can be inherited directly by scripts. 2000-05-11 David Masterson * contrib/Makefile.am (pkgdata_SCRIPTS): change cfemacs.el to cfengine.el in keeping with internal documentation. Also renamed the file as well. 2000-05-08 David Masterson * Release: V1.6 released to Mark for verification. * Everything: Many things have been changed and reorganized for the shift to automake generated Makefiles. See the end of the NEWS file for more information. 2000-04-24 David Masterson * ChangeLog: Created and initialized with old VERSION.DIFF ***************** Minor Version 5 ******************** KNOWN BUGS: linux, when making directories, ownership can perms can be wrong. 1.5.4 Added security message in checksum=md5 for cfengine if new files appear Bug in class evaluation with multiple embedded groups fixed Bug in file transfer could hang a server in special circumstances. Bug in secure recursive copy (access denied incorrectly). Type change, size is off_t in cfstat struct Multiple define bug in copy: could cause endless loop Thread counting error fixed in cfd Required/disk suspicious warnings now cause classes to be defined Resolver could delete substring lines Extra measures against Denial of Service attacks on cfd, only one instance of a host-IP may be connected at one time. 1) Multiple connections from the same host are refused by default (before any recv()) 2) A DenyConnectionsFrom list will prevent named IP adresses from connecting (before any recv) or a general AllowConnectionsFrom mask... 3) If the thread table is full for more than five requests, cfd commits suicide (apoptosis) to avoid resource usage by spamming. The control variable "DenyConnectionsFrom = ( ip1 ip2 ... )" allows a list of numerical IP masks to be specified, which cfd will deny connections from. This can be used to prevent hanging connection attacks from malicous hosts and other Denial of Service attacks. e.g. cfd.conf control: AllowConnectionsFrom ( 128.39.89 ) DenyConnectionsFrom = ( 128.39.89.4 ) This is in addition to tcp wrapper stuff, but the TCP wrapper code cannot protect against denial of service attacks. typecheck=false in copy switches off error messages on type mismatch. 1.5.3 Configuration fixes for strange platforms. Segmentation fault with long hostnames in cfd. A number of security minded improvements to coding. 1.5.2 (Minor patches) DeleteNonOwnerMail excluded check of NonUserMail Almost complete port to SCO, missing data on mount model Some compilation problems addressed. Move to OpenSSL latest version. Domain name issue fix in remote copying between domains. Exec strings in variable assignments are now chopped. 1.5.1 (bugfixes only) Segmentation fault with blank lines fixed in editfiles. Segmentation fault with remote copy access denied fixed. IP address and subnet (first three bytes of IP) are now added as classes e.g. 128_39_89 and 128_39_89_10 Checksum update bug fix ->! works on directories, with some care checks mutex variables in cfd made static. Serialized gethostbyname() to avoid races in multithreaded lookup. BUG: cfd seems unable to copy itself on memory mapped solaris 1.5.0 Security enhancements and bug fixes. !! GNU Regular expression library replaced by POSIX calls. !! !! The old code is still present for legacy systems but !! !! this will not be supported in the future. Legacy systems !! !! should install the GNU Posix library rx-1.5 for compatibility. !! !! *** check complex regex's before using this! *** !! RFC931 user authentication for cfd, on systems supporting/running identd. Editfiles: Checks that the file differs from the disk version after multiple edits before saving (fixes circular do-undo problems) All pthread libraries are now trusted to work by default (make of this what you will). BSD chflags attributes now handled (by Andreas KluBmann) home/ in directories LogDirectory LockDirectory - variables in control: can override defaults. define= added to shellcommands. Defined if shellcommand returns zero. Cfengine will not edit a link to a file unless the owner of the link is the owner of the file. Careful attempts to avoid exploitation of race conditions during file writing. New copy option, secure=true allows 3DES encryption with secret keys in file LOCKDIR/keys. Filenames and contents are encrypted only. New threading policy makes compatibility with earlier versions of cfd impossible. Should be more effective now. Discontinued -m flag. cfd options: root=host1,host2 determines whether a connecting host can read files on the remote system which are not owned by the initiator of the connection. secure=true means that cfd will only serve the file on a secure line. New cfkey program which generates a key file, e.g. cfkey > /var/run/cfengine/keys; chmod 600 /var/run/cfengine/keys New copy type "mtime" Control variable: DefaultCopyType = ( mtime ) can be used to set on all copies following this. Problem with pthreads and GNU/Linux fixed ***************** Minor Version 4 ******************** 1.4.17 Multihomed host fixes for hosts with multiple names on interfaces. 1.4.16 Options owner= group= in shellcommands, allow running programs with effective user id, i.e. su -c user command ShowActions = ( on ) makes cfengine print out the exact action in output, using the adaptive lock string. For specialized processing only. Symbolic link attack security hole closed. 1.4.15 Bug in size= in tidy files which could cause parsed value to be incorrect if the size value had many digits. Setuid logs were not saved after copy: stealth on remote copies was broken. Username authentication added (weak and discretionary). Bug with new Berkeley database v2 fixed. Seems to work now. New class name digital added causing incorrect class id's! Option checksum=md5 added to files to give Tripwire functionality. (Requires libdb v2 from sleepycat) 1.4.14a Editfiles Replace/With error incorrectly fixed in 1.4.13. Caused segmentation fault if last line of file. 1.4.14 (Post LISA changes) SuspiciousNames = ( .mo lrk3 ) in control adds a list of filenames which cfengine will warn about if it detects them in the course of scanning directories. SecureInput = ( false/true ) option which switches on checking of the permissions on the input files. If this is set cfengine will not read files which are not owned by the uid running the program, or which are writable by groups or others. Copy default to source=destination name if dest not specified (assumes that server is not localhost) 1.4.13 N.B. When upgrading to this version. ALL systems should be upgraded. Debian ID changed to use /etc/debian_version. Special GNU/linux distributions detected incorrectly. cfd patches: removed forking from 1.4.12 and fixed error protocol bug which allowed files to be overwritten with an error message (ouch!) Multi-homed host fix which works with solaris nsswitch/nis When copying symbolic links, both image and link, the file pointed to by the link could end up with the permissions of the link. Fixed. File recursion was broken in some earlier version. Process match/define fix. Classes got defined even when processes missing. In file,copy,link new option ignore= allows locally defined ignores. Often a better alternative to the global ignore list which affects all three and tidy as well. (This is like include/exclude but also works on directories/recursion) AutoCreate/dry-run created file. Fixed. Variable expansion in import. Imported files which are not found now give only warning in verbose mode. They do not stop execution. This allows inclusion of possibly existing files like cf.local Obscure bug in class evaluation fixed. OpenBSD classes added. Purging without authentication disabled, otherwise possible to wipe out a whole directory. Link defaults changed during copying so that links will be created to nonexistent files. Didn't find some processes if username contained a number on sys V. Bug in macro hashing could cause segmentation fault. When recursively copying dirctories with non-alphanumeric filenames it was possible to enter into enter into silly loops which looked for non-existent files. Fixed. Variables allowed in defaultroute. control: variable = ( `exec shellcommand` ) now sets variable to output of command. New options for unmount deletefstab=true/false deletedir=true/false New option stealth=true/false determines whether the access/ctime of source files are modified during copy. Security feature tests ownership and permissions of input files. Files writable by others than the owner are skipped. If cfengine.conf is not secure program terminates. New List in control FileExtensions = ( c gif txt ) etc If directories have these names they will be reported as security warnings. NonAlphaNumFiles = ( on ) switches on disabling (marking) of files with control character filenames and other non-alphanumeric names, with some exceptions. These are suffixed with .cf-nonalpha which can then be removed if desired by tidy. 1.4.12 Ownership of links was not checked, fixed for those systems which have lchown() (solaris and osf/digital) Automatic domain name detection in cases where sites use fully qualified domain names locally (eg in /etc/hosts) Helps to solve the problem of what to do if you havge multiple domains in a cfengine.conf file and want to define classes based on the domain name which hasn'r been set yet. processes: include and exclude lists can be added to match or exclude specific literals in addition to the regular expressions (which don't seem to work very reliably) when searching through the process table. Tidy with single / as root ignored command. Fixed miscmounts rw/ro only option made more like other options with mode=rw,mode=ro etc. Default value is rw. Backward compatibility maintained. Variable expansion now performed in owner= and group= Error capture while checking link permissions fixed. Old perror() method missed. Multithreaded cfd. stat error message fixed. -m option to cfd to switch on multithreaded operation. Systems which do not have working pthreads fork() processes during copy commands only. Note that solaris 2.[56] is the only working pthread implementation that is implemented, since I only have linux and solaris to test on. To get pthreads working on other platforms you have to add a NOTBROKEN to configure.in and rerun autoconf/autoheader. cfd now is able to run cfengine at timely intervals in collaboration with, or instead of cron. This allows cron to be restarted by cfengine/cfd on linux boxes, where it crashes all the time, and it allows cfd to be restarted by cfengine/cron if it crashes (occasionally). See AutoExecInterval/AutoExecCommand Purging files didn't remove deep directories on client, fixed. Domain name case control tweaks. File recursion bug fix. Bug in execute bit permissions on directories. Support for multiple network interfaces Copy could lead to empty file. New db v2* api used. dirlinks=tidy didn't work, fixed. Bug in home expansion of user patterns Multiple timezone aliases 1.4.11 Copy repatched. Erroneous patch in filedir.c copy modes not settable Lexer tweaking Travlinks patch in tidyfiles. Did not detect links properly. Home tidy optimization. Bug in IsMountedFileSystem fixed Bug in relative linking from / , missing / fixed. Link update in copy files repaired. Editfiles: Backup, Syslog, Inform New class additions are automatically canonified to protect from plugins. Can now set syslog=on/off, inform=on/off per action so that output can be routed as desired, overriding global settings. (For Greg Maples) processes, useshell=dumb ignores I/O and allows programs like cron to be restarted without hanging cfengine with a zombie. This doesn't work via cfrun, unfortunately... Bug in parser, defaults not reset if previous action was not installed. Global replace bug fixed. internal variable $(ipaddress) contains numerical form of IP for current host. addinstallable for declaring dynamical classes before they are used. Memory leak in cfd fixed. 1.4.10 Multi-homed host fix for cfd. Mail check extras: test for dubious files Warn/DeleteNonOwnerMail Warn/DeleteNonUserMail Edit: CatchAbort markers introduced to add a kind of exception handling so searches do not have to abort an edit compeltely. Some typos fixed in the logging code. Segmentation faults caught and erronenous messages fixed. Extra new lines from logging code fixed, e.g. with cfengine -a Bug fix to edit command DeleteLinesAfter... TimeOut parameter added to adjust network timeouts on slow networks. Access control in cfrun (access = mark,uid,uid2 in cfrun.hosts) matches=0 allowed in processes Unixware support added 8-bit clean for flex users percentages added for filessystem checking (diskusage=) extra options for rmdirs so top directory needn't be removed in tidy 1.4.9 ReleaseCurrentLock exited if remove failed. This was wrong, should only have returned and caused a truncation of the action sequence. ERESTARTSYS deadlock patch for POSIX.1/SVR4 while restarting daemons. Processes would hang, never receiving end-of-file on the pipe. A timeout has been added as a workaround. Support for Access Control Lists in files and copy. Currently implemented for solaris, and dfs only. blocksize calculations rewritten to avoid division by zero error. Error in installing required class info. Introduced in 1.4.8 define= directives added to process, editfiles, files, tidy, link and disable DNS lookup case control to avoid unusual problems with case mismatch. $(host) not expanded when domain not set: fixed. Output rationalization in different modes, including possibility of logging. Note that the status of some messages has changed. You might need to set Inform = ( on ) in order to see the messages you want to see. Messages may now be routed to syslog. Bug in server= fixed for net copy. Previously a pointer error New option to shellcomand: useshell=true/false. If false, cfengine uses an internal popen replacement which does not use an intermediary shell to start programs. This addresses several security issues in starting programs with root privileges. New option to copy: purge=true/false. If true, cfengine will remove files in the destination dir which do not exist in the source dir when recursively copying directories. control options Verbose = ( on ), Inform = ( on ), Syslog = ( on ) which switches the output level from within the config file. Also: Warnings = ( on ), DryRun = ( on ) to set other command line options. Bug in relative linking fixed. Bug in overlaying permissions mostly fixed in copy. Still some residual weirdness when using complex masks. Garbage appeared in copy define=classes. AutoCreate would not work with BeginIfFileNewer 1.4.8 Cfengine now detects redhat linux and defines a class. Welcome redhat. Variables can now be used in the control section itself, to define other variables and so forth. Drop setpgrp and use setsid instead, if it is found, to get around the incompatible argument. Non canonical $(arch) canonified so that it is not confused as a list variable. OutputPrefix doesn't automatically append hostname now, since you can always do this yourself with variables in the OutputPrefix string. Bug in copy, permissions finally fixed? Pleeeaasse? Output format changes. New option to links, nofile=force allows you to create links to files which do not presntly exist. 1.4.7 Copy : "return" instead of "continue" in GetLock. Meant that if one lock failed, all copies were abandoned. Setuid root files copied without setuid bit. Fixed. Segmentation fault in "InsertFile" Fixed for empty files. Scanf workaround for linux in remote copying, caused incorrect values to be read and thereby incorrect file modes. Problem in variable expansion fixed? setpgrp() in cfd Documentation updates. Possible segmentation fault in inode caching fixed. Minor suggestions to autoconf implemented. 1.4.6 CompressPath moved to filename.c to avoid linking problem in OSF. More Too Many open files bloopers fixed. cfd: transfer synchronization problem could break filenames in readdir() fixed. Recursive tidy including directories fixed so that top directory is now deleted. cfwrap altered so that identical multiple messages are filtered, or shown only once per day 1.4.5 Symbolic link inode number transferred incorrectly from cfd, leads to remaking symbolic links during remote copies, owing to confusion of hard and soft links. Some unclosed socket loopholes fixed. Too many open files error. Variable syntax error, misdiagnozed if other braces used. Fixed. 1.4.4 Repository error, files not being properly backed up. Fixed. Documentation config changes. 1.4.3 AIX4 -> AIX in df.c. Typo in freespace code. Incorrect locking of editfiles fixed. Unique names previously omitted. Editfilesize can be set to zero to be ignored. Class defines in required: bugfix, items not installed. BeginGroupIfFileExists checked the wrong file!! cdrom filesystems do not generate warnings if not immediately mountable html files no longer distributed Binaries are now installed in sbin instead of bin. scripts are now installed in lib/cfengine instead of sbin 1.4.2 Timeout for reading input files (can happen during hanging NFS) could lead to multiple cfengines being started unwillfully. Emacs major-mode contributed by Rolf Ebert include/exclude patterns in files fixed (broken in 1.4.0) Broken pipe error in cfrun fixed. Variable OutputPrefix can be used to change the default "cfengine:" prefix on output lines. 1.4.1 Bug in parser. Trailing slashes defeat 2Dlist expansion. Fixed for tidy. cfd rereads system clock. Copy permission bug fixed. File reorganization to reflect inheritance structure. Change in cosmetic details of locking implementation. Some manual inconsistencies fixed. Bug in cfrun parsing comments fixed. (Missed next line) Bug in editfiles increment pointer fixed. Decrement to before start of file is not longer a fatal error. Permissions on rotated files were not preserved in 1.4.0. Fixed. Trailing dots from DNS/gethostbyname are now truncated away Editing symbolic links, edits file instead. Default value of IfElapsed is now zero, so that antispam locks are turned off by default. 1.4.0 Debian systems now detected and have an additional class "debian" in addition to linux New option "define=class1,class2" to "copy" command defines a list of classes only if a file is copied. This allows followup actions to be added to other sections. Variable list iteration in shell-commands. Enhanced iteration source code. New option in disable: size=, size=>, size=< for byte size comparisons. Files are only disabled if the criterion is met. Hourly classes are added to the automatic class engine: Hr00 to Hr23 can now be used. Update messages in copy were erroneous in some cases, although copying was performed correctly. Fixed. Hyphens in hp-ux etc hard classes changed to underscores. It is now possible to override the name of the network interface in the control section of the program. This allows funny OS installations on unusual hardware to set the net interface for a specific class. control: nextstep:: interfacename = ( blah0 ) New editing commands: CommentLinesContaining, BeginGroupIfFileIsNewer, BeginGroupIfFileExists, BeginGroupIfNoLineContaining, AutoCreate Bug in alpha/netbsd with segmentation fault in exit() repaired, some kind of pointer misunderstanding with a null string. New safer algorithm for copying files, first copies a modified file to a new file on the local filesystem. When transfer is complete it is renamed into place. This helps avoid race-conditions and problems where copying is halted underway due to network lossage. New debugging option d3 provides summarial info. Timeout option in shellcommands allows timeouts after a fixed number of seconds. Timeouts in place for all RPC operations connected with "mount". Sizes in disable and tidy now may specify units, bytes, kilobytes, megabytes (b,k,m) First character significant only. e.g. size=30kilobytes is okay. include=, exclude= patterns in file searches Remote copying partially implemented with server daemon cfd. Typo in tidy concatenation with multiple wildcards fixed. Extra time classes added allowing a complete front end for cron. Additional manual chapter on this. copying of links without a directory reference now prepends "./" Copying now preserves hard links where possible. File Rotation in disable does not break file handles any more. Copied/disabled files now back up to .cfsaved whereas edited files back up to .cfedited, to avoid overwriting the backup in copy-then-edit scenarios. Checksum comparisons are now optimized by checking the number of bytes before launching into a checksum computation. Several new edit commands. New locking mechanism with atomic locks which allow several cfengine's to coexist. Also antispamming mechanisms built in. CheckResolv reworked to avoid editing each time. AddToFstab will add to file if fs mounted SplayTimes added. causes cfengine to sleep a unique amount of time for each host, up to a maximum time. Can be used to avoid race conditions and contention. Improved expression evaluation with parentheses. Support for Cray. (Unsure whether these choices will match all cray systems). beta2: New options -q -K for switching off locks cfengine-2.2.10/ltmain.sh0000644000175000001440000073310411141071233012110 00000000000000# Generated from ltmain.m4sh. # ltmain.sh (GNU libtool) 2.2.6 # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, # or obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Usage: $progname [OPTION]... [MODE-ARG]... # # Provide generalized library-building support services. # # --config show all configuration variables # --debug enable verbose shell tracing # -n, --dry-run display commands without modifying any files # --features display basic configuration information and exit # --mode=MODE use operation mode MODE # --preserve-dup-deps don't remove duplicate dependency libraries # --quiet, --silent don't print informational messages # --tag=TAG use configuration variables from tag TAG # -v, --verbose print informational messages (default) # --version print version information # -h, --help print short or long help message # # MODE must be one of the following: # # clean remove files from the build directory # compile compile a source file into a libtool object # execute automatically set library path, then run a program # finish complete the installation of libtool libraries # install install libraries or executables # link create a library or an executable # uninstall remove libraries from an installed directory # # MODE-ARGS vary depending on the MODE. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # # host-triplet: $host # shell: $SHELL # compiler: $LTCC # compiler flags: $LTCFLAGS # linker: $LD (gnu? $with_gnu_ld) # $progname: (GNU libtool) 2.2.6 # automake: $automake_version # autoconf: $autoconf_version # # Report bugs to . PROGRAM=ltmain.sh PACKAGE=libtool VERSION=2.2.6 TIMESTAMP="" package_revision=1.3012 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # NLS nuisances: We save the old values to restore during execute mode. # Only set LANG and LC_ALL to C if already set. # These must not be set unconditionally because not all systems understand # e.g. LANG=C (notably SCO). lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${$lt_var+set}\" = set; then save_$lt_var=\$$lt_var $lt_var=C export $lt_var lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done $lt_unset CDPATH : ${CP="cp -f"} : ${ECHO="echo"} : ${EGREP="/usr/bin/grep -E"} : ${FGREP="/usr/bin/grep -F"} : ${GREP="/usr/bin/grep"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SED="/opt/local/bin/gsed"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} # Global variables: EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. exit_status=$EXIT_SUCCESS # Make sure IFS has a sensible default lt_nl=' ' IFS=" $lt_nl" dirname="s,/[^/]*$,," basename="s,^.*/,," # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } # Generated shell functions inserted here. # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath="$0" # The name of this program: # In the unlikely event $progname began with a '-', it would play havoc with # func_echo (imagine progname=-n), so we prepend ./ in that case: func_dirname_and_basename "$progpath" progname=$func_basename_result case $progname in -*) progname=./$progname ;; esac # Make sure we have an absolute path for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=$func_dirname_result progdir=`cd "$progdir" && pwd` progpath="$progdir/$progname" ;; *) save_IFS="$IFS" IFS=: for progdir in $PATH; do IFS="$save_IFS" test -x "$progdir/$progname" && break done IFS="$save_IFS" test -n "$progdir" || progdir=`pwd` progpath="$progdir/$progname" ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed="${SED}"' -e 1s/^X//' sed_quote_subst='s/\([`"$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Re-`\' parameter expansions in output of double_quote_subst that were # `\'-ed in input to the same. If an odd number of `\' preceded a '$' # in input to double_quote_subst, that '$' was protected from expansion. # Since each input `\' is now two `\'s, look for any number of runs of # four `\'s followed by two `\'s and then a '$'. `\' that '$'. bs='\\' bs2='\\\\' bs4='\\\\\\\\' dollar='\$' sed_double_backslash="\ s/$bs4/&\\ /g s/^$bs2$dollar/$bs&/ s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g s/\n//g" # Standard options: opt_dry_run=false opt_help=false opt_quiet=false opt_verbose=false opt_warning=: # func_echo arg... # Echo program name prefixed message, along with the current mode # name if it has been set yet. func_echo () { $ECHO "$progname${mode+: }$mode: $*" } # func_verbose arg... # Echo program name prefixed message in verbose mode only. func_verbose () { $opt_verbose && func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_error arg... # Echo program name prefixed message to standard error. func_error () { $ECHO "$progname${mode+: }$mode: "${1+"$@"} 1>&2 } # func_warning arg... # Echo program name prefixed warning message to standard error. func_warning () { $opt_warning && $ECHO "$progname${mode+: }$mode: warning: "${1+"$@"} 1>&2 # bash bug again: : } # func_fatal_error arg... # Echo program name prefixed message to standard error, and exit. func_fatal_error () { func_error ${1+"$@"} exit $EXIT_FAILURE } # func_fatal_help arg... # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { func_error ${1+"$@"} func_fatal_error "$help" } help="Try \`$progname --help' for more information." ## default # func_grep expression filename # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $GREP "$1" "$2" >/dev/null 2>&1 } # func_mkdir_p directory-path # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { my_directory_path="$1" my_dir_list= if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then # Protect directory names starting with `-' case $my_directory_path in -*) my_directory_path="./$my_directory_path" ;; esac # While some portion of DIR does not yet exist... while test ! -d "$my_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. my_dir_list="$my_directory_path:$my_dir_list" # If the last portion added has no slash in it, the list is done case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` done my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do IFS="$save_mkdir_p_IFS" # mkdir can fail with a `File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$my_dir" 2>/dev/null || : done IFS="$save_mkdir_p_IFS" # Bail out if we (or some other process) failed to create a directory. test -d "$my_directory_path" || \ func_fatal_error "Failed to create \`$1'" fi } # func_mktempdir [string] # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, STRING is the basename for that directory. func_mktempdir () { my_template="${TMPDIR-/tmp}/${1-$progname}" if test "$opt_dry_run" = ":"; then # Return a directory name, but don't create it in dry-run mode my_tmpdir="${my_template}-$$" else # If mktemp works, use that first and foremost my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` if test ! -d "$my_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race my_tmpdir="${my_template}-${RANDOM-0}$$" save_mktempdir_umask=`umask` umask 0077 $MKDIR "$my_tmpdir" umask $save_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$my_tmpdir" || \ func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi $ECHO "X$my_tmpdir" | $Xsed } # func_quote_for_eval arg # Aesthetically quote ARG to be evaled later. # This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT # is double-quoted, suitable for a subsequent eval, whereas # FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters # which are still active within double quotes backslashified. func_quote_for_eval () { case $1 in *[\\\`\"\$]*) func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac case $func_quote_for_eval_unquoted_result in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and and variable # expansion for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" ;; *) func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" esac } # func_quote_for_expand arg # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { case $1 in *[\\\`\"]*) my_arg=`$ECHO "X$1" | $Xsed \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; esac case $my_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") my_arg="\"$my_arg\"" ;; esac func_quote_for_expand_result="$my_arg" } # func_show_eval cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$my_cmd" my_status=$? if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_show_eval_locale cmd [fail_exp] # Unless opt_silent is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { my_cmd="$1" my_fail_exp="${2-:}" ${opt_silent-false} || { func_quote_for_expand "$my_cmd" eval "func_echo $func_quote_for_expand_result" } if ${opt_dry_run-false}; then :; else eval "$lt_user_locale $my_cmd" my_status=$? eval "$lt_safe_locale" if test "$my_status" -eq 0; then :; else eval "(exit $my_status); $my_fail_exp" fi fi } # func_version # Echo version message to standard output and exit. func_version () { $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ p }' < "$progpath" exit $? } # func_usage # Echo short help message to standard output and exit. func_usage () { $SED -n '/^# Usage:/,/# -h/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" $ECHO $ECHO "run \`$progname --help | more' for full usage" exit $? } # func_help # Echo long help message to standard output and exit. func_help () { $SED -n '/^# Usage:/,/# Report bugs to/ { s/^# // s/^# *$// s*\$progname*'$progname'* s*\$host*'"$host"'* s*\$SHELL*'"$SHELL"'* s*\$LTCC*'"$LTCC"'* s*\$LTCFLAGS*'"$LTCFLAGS"'* s*\$LD*'"$LD"'* s/\$with_gnu_ld/'"$with_gnu_ld"'/ s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ p }' < "$progpath" exit $? } # func_missing_arg argname # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { func_error "missing argument for $1" exit_cmd=exit } exit_cmd=: # Check that we have a working $ECHO. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then # Yippee, $ECHO works! : else # Restart under the correct shell, and then maybe $ECHO will work. exec $SHELL "$progpath" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # Parse options once, thoroughly. This comes as soon as possible in # the script to make things like `libtool --version' happen quickly. { # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Parse non-mode specific arguments: while test "$#" -gt 0; do opt="$1" shift case $opt in --config) func_config ;; --debug) preserve_args="$preserve_args $opt" func_echo "enabling shell trace mode" opt_debug='set -x' $opt_debug ;; -dlopen) test "$#" -eq 0 && func_missing_arg "$opt" && break execute_dlfiles="$execute_dlfiles $1" shift ;; --dry-run | -n) opt_dry_run=: ;; --features) func_features ;; --finish) mode="finish" ;; --mode) test "$#" -eq 0 && func_missing_arg "$opt" && break case $1 in # Valid mode arguments: clean) ;; compile) ;; execute) ;; finish) ;; install) ;; link) ;; relink) ;; uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $opt" exit_cmd=exit break ;; esac mode="$1" shift ;; --preserve-dup-deps) opt_duplicate_deps=: ;; --quiet|--silent) preserve_args="$preserve_args $opt" opt_silent=: ;; --verbose| -v) preserve_args="$preserve_args $opt" opt_silent=false ;; --tag) test "$#" -eq 0 && func_missing_arg "$opt" && break preserve_args="$preserve_args $opt $1" func_enable_tag "$1" # tagname is set here shift ;; # Separate optargs to long options: -dlopen=*|--mode=*|--tag=*) func_opt_split "$opt" set dummy "$func_opt_split_opt" "$func_opt_split_arg" ${1+"$@"} shift ;; -\?|-h) func_usage ;; --help) opt_help=: ;; --version) func_version ;; -*) func_fatal_help "unrecognized option \`$opt'" ;; *) nonopt="$opt" break ;; esac done case $host in *cygwin* | *mingw* | *pw32* | *cegcc*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_duplicate_deps ;; esac # Having warned about all mis-specified options, bail out if # anything was wrong. $exit_cmd $EXIT_FAILURE } # func_check_version_match # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } ## ----------- ## ## Main. ## ## ----------- ## $opt_help || { # Sanity checks first: func_check_version_match if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then func_fatal_configuration "not configured to build any kind of library" fi test -z "$mode" && func_fatal_error "error: you must specify a MODE." # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then func_error "unrecognized option \`-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$progname --help --mode=$mode' for more information." } # func_lalib_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null \ | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_unsafe_p file # True iff FILE is a libtool `.la' library or `.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if `file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case "$lalib_p_line" in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test "$lalib_p" = yes } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { func_lalib_p "$1" } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_ltwrapper_scriptname_result="" if func_ltwrapper_executable_p "$1"; then func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" fi } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $opt_debug save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$save_ifs eval cmd=\"$cmd\" func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # `FILE.' does not work on cygwin managed mounts. func_source () { $opt_debug case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $opt_debug if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_quote_for_eval "$arg" CC_quoted="$CC_quoted $func_quote_for_eval_result" done case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_quote_for_eval "$arg" CC_quoted="$CC_quoted $func_quote_for_eval_result" done case "$@ " in " $CC "* | "$CC "* | " `$ECHO $CC` "* | "`$ECHO $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$ECHO $CC_quoted` "* | "`$ECHO $CC_quoted` "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with \`--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=${1} if test "$build_libtool_libs" = yes; then write_lobj=\'${2}\' else write_lobj=none fi if test "$build_old_libs" = yes; then write_oldobj=\'${3}\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T <?"'"'"' &()|`$[]' \ && func_warning "libobj name \`$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname="$func_basename_result" xdir="$func_dirname_result" lobj=${xdir}$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$ECHO "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi removelist="$removelist $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist removelist="$removelist $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test "$build_libtool_libs" = yes; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test "$pic_mode" != no; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir command="$command -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test "$suppress_opt" = yes; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test "$build_old_libs" = yes; then if test "$pic_mode" != yes; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test "$compiler_c_o" = yes; then command="$command -o $obj" fi # Suppress compiler output if we already did a PIC compilation. command="$command$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test "$need_locks" = warn && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test "$need_locks" != no; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test "$mode" = compile && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -shared do not build a \`.o' file suitable for static linking -static only build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode \`$mode'" ;; esac $ECHO $ECHO "Try \`$progname --help' for more information about other modes." exit $? } # Now that we've collected a possible --mode arg, show help if necessary $opt_help && func_mode_help # func_mode_execute arg... func_mode_execute () { $opt_debug # The first argument is the command name. cmd="$nonopt" test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $execute_dlfiles; do test -f "$file" \ || func_fatal_help "\`$file' is not a file" dir= case $file in *.la) # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "\`$file' was not linked with \`-export-dynamic'" continue fi func_dirname "$file" "" "." dir="$func_dirname_result" if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir="$func_dirname_result" ;; *) func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file="$progdir/$program" elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). func_quote_for_eval "$file" args="$args $func_quote_for_eval_result" done if test "X$opt_dry_run" = Xfalse; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" $ECHO "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS fi } test "$mode" = execute && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $opt_debug libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. $opt_silent && exit $EXIT_SUCCESS $ECHO "X----------------------------------------------------------------------" | $Xsed $ECHO "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done $ECHO $ECHO "If you ever happen to want to link against installed libraries" $ECHO "in a given directory, LIBDIR, you must either use libtool, and" $ECHO "specify the full pathname of the library, or use the \`-LLIBDIR'" $ECHO "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then $ECHO " - add LIBDIR to the \`$shlibpath_var' environment variable" $ECHO " during execution" fi if test -n "$runpath_var"; then $ECHO " - add LIBDIR to the \`$runpath_var' environment variable" $ECHO " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then $ECHO " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi $ECHO $ECHO "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) $ECHO "more information, such as the ld(1), crle(1) and ld.so(8) manual" $ECHO "pages." ;; *) $ECHO "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac $ECHO "X----------------------------------------------------------------------" | $Xsed exit $EXIT_SUCCESS } test "$mode" = finish && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $opt_debug # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $ECHO "X$nonopt" | $GREP shtool >/dev/null; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" install_prog="$install_prog$func_quote_for_eval_result" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest=$arg continue fi case $arg in -d) isdir=yes ;; -f) case " $install_prog " in *[\\\ /]cp\ *) ;; *) prev=$arg ;; esac ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" install_prog="$install_prog $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else func_dirname_and_basename "$dest" "" "." destdir="$func_dirname_result" destname="$func_basename_result" # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "\`$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "\`$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "\`$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi func_dirname "$file" "/" "" dir="$func_dirname_result" dir="$dir$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname="$1" shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme="" ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try `ln -sf' first, because the `ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib="$destdir/$realname" func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name="$func_basename_result" instname="$dir/$name"i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest="$destfile" destfile= ;; *) func_fatal_help "cannot copy a libtool object to \`$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else func_basename "$file" destfile="$func_basename_result" destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script \`$wrapper'" finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no fi done relink_command= func_source "$wrapper" outputname= if test "$fast_install" = no && test -n "$relink_command"; then $opt_dry_run || { if test "$finalize" = yes; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink \`$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file="$outputname" else func_warning "cannot relink \`$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name="$func_basename_result" # Set up the ranlib parameters. oldlib="$destdir/$name" func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run \`$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test "$mode" = install && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $opt_debug my_outputname="$1" my_originator="$2" my_pic_p="${3-no}" my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms="${my_outputname}S.c" else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${my_outputname}.nm" func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then func_verbose "generating symbol list for \`$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for progfile in $progfiles; do func_verbose "extracting global C symbols from \`$progfile'" $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$outputname.exp" $opt_dry_run || { $RM $export_symbols eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from \`$dlprefile'" func_basename "$dlprefile" name="$func_basename_result" $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' eval "$NM $dlprefile 2>/dev/null | $global_symbol_pipe >> '$nlist'" } done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" fi $ECHO >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; " case $host in *cygwin* | *mingw* | *cegcc* ) $ECHO >> "$output_objdir/$my_dlsyms" "\ /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */" lt_dlsym_const= ;; *osf5*) echo >> "$output_objdir/$my_dlsyms" "\ /* This system does not cope well with relocations in const data */" lt_dlsym_const= ;; *) lt_dlsym_const=const ;; esac $ECHO >> "$output_objdir/$my_dlsyms" "\ extern $lt_dlsym_const lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; $lt_dlsym_const lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = {\ { \"$my_originator\", (void *) 0 }," case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac $ECHO >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) if test "X$my_pic_p" != Xno; then pic_flag_for_symtable=" $pic_flag" fi ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) symtab_cflags="$symtab_cflags $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' # Transform the symbol file into the correct name. symfileobj="$output_objdir/${my_outputname}S.$objext" case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for \`$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. func_win32_libid () { $opt_debug win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | $SED -n -e ' 1,100{ / I /{ s,.*,import, p q } }'` case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_extract_an_archive dir oldlib func_extract_an_archive () { $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $opt_debug my_gentop="$1"; shift my_oldlibs=${1+"$@"} my_oldobjs="" my_xlib="" my_xabs="" my_xdir="" for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib="$func_basename_result" my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir="$my_gentop/$my_xlib_u" func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` darwin_base_archive=`basename "$darwin_archive"` darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches ; do func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" func_extract_an_archive "`pwd`" "${darwin_base_archive}" cd "$darwin_curdir" $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` done func_extract_archives_result="$my_oldobjs" } # func_emit_wrapper_part1 [arg=no] # # Emit the first part of a libtool wrapper script on stdout. # For more information, see the description associated with # func_emit_wrapper(), below. func_emit_wrapper_part1 () { func_emit_wrapper_part1_arg1=no if test -n "$1" ; then func_emit_wrapper_part1_arg1=$1 fi $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then ECHO=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then # Yippee, \$ECHO works! : else # Restart under the correct shell, and then maybe \$ECHO will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $ECHO "\ # Find the directory that this script lives in. thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` done " } # end: func_emit_wrapper_part1 # func_emit_wrapper_part2 [arg=no] # # Emit the second part of a libtool wrapper script on stdout. # For more information, see the description associated with # func_emit_wrapper(), below. func_emit_wrapper_part2 () { func_emit_wrapper_part2_arg1=no if test -n "$1" ; then func_emit_wrapper_part2_arg1=$1 fi $ECHO "\ # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # end: func_emit_wrapper_part2 # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory in which it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=no if test -n "$1" ; then func_emit_wrapper_arg1=$1 fi # split this up so that func_emit_cwrapperexe_src # can call each part independently. func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" } # func_to_host_path arg # # Convert paths to host format when used with build tools. # Intended for use with "native" mingw (where libtool itself # is running under the msys shell), or in the following cross- # build environments: # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # where wine is equipped with the `winepath' executable. # In the native mingw case, the (msys) shell automatically # converts paths for any non-msys applications it launches, # but that facility isn't available from inside the cwrapper. # Similar accommodations are necessary for $host mingw and # $build cygwin. Calling this function does no harm for other # $host/$build combinations not listed above. # # ARG is the path (on $build) that should be converted to # the proper representation for $host. The result is stored # in $func_to_host_path_result. func_to_host_path () { func_to_host_path_result="$1" if test -n "$1" ; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' case $build in *mingw* ) # actually, msys # awkward: cmd appends spaces to result lt_sed_strip_trailing_spaces="s/[ ]*\$//" func_to_host_path_tmp1=`( cmd //c echo "$1" |\ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_path_tmp1=`cygpath -w "$1"` func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` ;; * ) # Unfortunately, winepath does not exit with a non-zero # error code, so we are forced to check the contents of # stdout. On the other hand, if the command is not # found, the shell will set an exit code of 127 and print # *an error message* to stdout. So we must check for both # error code of zero AND non-empty stdout, which explains # the odd construction: func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ $SED -e "$lt_sed_naive_backslashify"` else # Allow warning below. func_to_host_path_result="" fi ;; esac if test -z "$func_to_host_path_result" ; then func_error "Could not determine host path corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_path_result="$1" fi ;; esac fi } # end: func_to_host_path # func_to_host_pathlist arg # # Convert pathlists to host format when used with build tools. # See func_to_host_path(), above. This function supports the # following $build/$host combinations (but does no harm for # combinations not listed here): # $build $host # mingw (msys) mingw [e.g. native] # cygwin mingw # *nix + wine mingw # # Path separators are also converted from $build format to # $host format. If ARG begins or ends with a path separator # character, it is preserved (but converted to $host format) # on output. # # ARG is a pathlist (on $build) that should be converted to # the proper representation on $host. The result is stored # in $func_to_host_pathlist_result. func_to_host_pathlist () { func_to_host_pathlist_result="$1" if test -n "$1" ; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_to_host_pathlist_tmp2="$1" # Once set for this call, this variable should not be # reassigned. It is used in tha fallback case. func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e 's|^:*||' -e 's|:*$||'` case $build in *mingw* ) # Actually, msys. # Awkward: cmd appends spaces to result. lt_sed_strip_trailing_spaces="s/[ ]*\$//" func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ $SED -e "$lt_sed_naive_backslashify"` ;; * ) # unfortunately, winepath doesn't convert pathlists func_to_host_pathlist_result="" func_to_host_pathlist_oldIFS=$IFS IFS=: for func_to_host_pathlist_f in $func_to_host_pathlist_tmp1 ; do IFS=$func_to_host_pathlist_oldIFS if test -n "$func_to_host_pathlist_f" ; then func_to_host_path "$func_to_host_pathlist_f" if test -n "$func_to_host_path_result" ; then if test -z "$func_to_host_pathlist_result" ; then func_to_host_pathlist_result="$func_to_host_path_result" else func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" fi fi fi IFS=: done IFS=$func_to_host_pathlist_oldIFS ;; esac if test -z "$func_to_host_pathlist_result" ; then func_error "Could not determine the host path(s) corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This may break if $1 contains DOS-style drive # specifications. The fix is not to complicate the expression # below, but for the user to provide a working wine installation # with winepath so that path translation in the cross-to-mingw # case works properly. lt_replace_pathsep_nix_to_dos="s|:|;|g" func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp1" |\ $SED -e "$lt_replace_pathsep_nix_to_dos"` fi # Now, add the leading and trailing path separators back case "$1" in :* ) func_to_host_pathlist_result=";$func_to_host_pathlist_result" ;; esac case "$1" in *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" ;; esac ;; esac fi } # end: func_to_host_pathlist # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include # define setmode _setmode #else # include # include # ifdef __CYGWIN__ # include # define HAVE_SETENV # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif # endif #endif #include #include #include #include #include #include #include #include #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif #ifdef _MSC_VER # define S_IXUSR _S_IEXEC # define stat _stat # ifndef _INTPTR_T_DEFINED # define intptr_t int # endif #endif #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifdef __CYGWIN__ # define FOPEN_WB "wb" #endif #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) #undef LTWRAPPER_DEBUGPRINTF #if defined DEBUGWRAPPER # define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args static void ltwrapper_debugprintf (const char *fmt, ...) { va_list args; va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } #else # define LTWRAPPER_DEBUGPRINTF(args) #endif const char *program_name = NULL; void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_fatal (const char *message, ...); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_opt_process_env_set (const char *arg); void lt_opt_process_env_prepend (const char *arg); void lt_opt_process_env_append (const char *arg); int lt_split_name_value (const char *arg, char** name, char** value); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); static const char *script_text_part1 = EOF func_emit_wrapper_part1 yes | $SED -e 's/\([\\"]\)/\\\1/g' \ -e 's/^/ "/' -e 's/$/\\n"/' echo ";" cat <"))); for (i = 0; i < newargc; i++) { LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); } EOF case $host_os in mingw*) cat <<"EOF" /* execv doesn't actually work on mingw as expected on unix */ rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); if (rval == -1) { /* failed to start process */ LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); return 127; } return rval; EOF ;; *) cat <<"EOF" execv (lt_argv_zero, newargz); return rval; /* =127, but avoids unused variable warning */ EOF ;; esac cat <<"EOF" } void * xmalloc (size_t num) { void *p = (void *) malloc (num); if (!p) lt_fatal ("Memory exhausted"); return p; } char * xstrdup (const char *string) { return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL; } const char * base_name (const char *name) { const char *base; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) /* Skip over the disk name in MSDOS pathnames. */ if (isalpha ((unsigned char) name[0]) && name[1] == ':') name += 2; #endif for (base = name; *name; name++) if (IS_DIR_SEPARATOR (*name)) base = name + 1; return base; } int check_executable (const char *path) { struct stat st; LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!")); if ((!path) || (!*path)) return 0; if ((stat (path, &st) >= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!")); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; int tmp_len; char *concat_name; LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined (HAVE_DOS_BASED_FILE_SYSTEM) } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = q - p; p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", tmp_pathspec)); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { char *errstr = strerror (errno); lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal ("Could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (strcmp (str, pat) == 0) *str = '\0'; } return str; } static void lt_error_core (int exit_status, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s: %s: ", program_name, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, "FATAL", message, ap); va_end (ap); } void lt_setenv (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", (name ? name : ""), (value ? value : ""))); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else int len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { int orig_value_len = strlen (orig_value); int add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } int lt_split_name_value (const char *arg, char** name, char** value) { const char *p; int len; if (!arg || !*arg) return 1; p = strchr (arg, (int)'='); if (!p) return 1; *value = xstrdup (++p); len = strlen (arg) - strlen (*value); *name = XMALLOC (char, len); strncpy (*name, arg, len-1); (*name)[len - 1] = '\0'; return 0; } void lt_opt_process_env_set (const char *arg) { char *name = NULL; char *value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); } lt_setenv (name, value); XFREE (name); XFREE (value); } void lt_opt_process_env_prepend (const char *arg) { char *name = NULL; char *value = NULL; char *new_value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); } new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); XFREE (name); XFREE (value); } void lt_opt_process_env_append (const char *arg) { char *name = NULL; char *value = NULL; char *new_value = NULL; if (lt_split_name_value (arg, &name, &value) != 0) { XFREE (name); XFREE (value); lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); } new_value = lt_extend_str (getenv (name), value, 1); lt_setenv (name, new_value); XFREE (new_value); XFREE (name); XFREE (value); } void lt_update_exe_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ int len = strlen (new_value); while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[len-1] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", (name ? name : ""), (value ? value : ""))); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF } # end: func_emit_cwrapperexe_src # func_mode_link arg... func_mode_link () { $opt_debug case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # which system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll which has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=no prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module="${wl}-single_module" func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test "$build_libtool_libs" != yes && \ func_fatal_configuration "can not build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" test -f "$arg" \ || func_fatal_error "symbol file \`$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) deplibs="$deplibs $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # moreargs="$moreargs $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file \`$arg' does not exist" fi arg=$save_arg prev= continue ;; precious_regex) precious_files_regex="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds="$arg" prev= continue ;; weak) weak_libs="$weak_libs $arg" prev= continue ;; xcclinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "\`-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname '-L' '' "$arg" dir=$func_stripname_result if test -z "$dir"; then if test "$#" -gt 0; then func_fatal_error "require no space between \`-L' and \`$1'" else func_fatal_error "need path for \`-L' option" fi fi # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of \`$dir'" dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) dllsearchpath="$dllsearchpath:$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework deplibs="$deplibs System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test "X$arg" = "X-lc" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test "X$arg" = "X-lc" && continue ;; esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot) compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $arg" ;; esac continue ;; -multi_module) single_module="${wl}-multi_module" continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "\`-no-install' is ignored for $host" func_warning "assuming \`-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" arg="$arg $wl$func_quote_for_eval_result" compiler_flags="$compiler_flags $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" arg="$arg $wl$func_quote_for_eval_result" compiler_flags="$compiler_flags $wl$func_quote_for_eval_result" linker_flags="$linker_flags $func_quote_for_eval_result" done IFS="$save_ifs" func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; # -64, -mips[0-9] enable 64-bit mode on the SGI compiler # -r[0-9][0-9]* specifies the processor on the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler # +DA*, +DD* enable 64-bit mode on the HP compiler # -q* pass through compiler args for the IBM compiler # -m*, -t[45]*, -txscale* pass through architecture-specific # compiler args for GCC # -F/path gives path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC # @file GCC response files -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" func_append finalize_command " $arg" compiler_flags="$compiler_flags $arg" continue ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; *.$objext) # A standard object. objs="$objs $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test "$pic_object" = none && test "$non_pic_object" = none; then func_fatal_error "cannot find name of object for \`$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object="$pic_object" func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir="$func_dirname_result" func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "\`$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the \`$prevarg' option requires an argument" if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname="$func_basename_result" libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" func_dirname "$output" "/" "" output_objdir="$func_dirname_result$objdir" # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_duplicate_deps ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; esac pre_post_deps="$pre_post_deps $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test "$linkmode,$pass" = "lib,link"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs="$tmp_deplibs" fi if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$linkmode,$pass" = "lib,dlpreopen"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= case $lib in *.la) func_source "$lib" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` case " $weak_libs " in *" $deplib_base "*) ;; *) deplibs="$deplibs $deplib" ;; esac done done libs="$dlprefiles" fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else compiler_flags="$compiler_flags $deplib" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; esac fi fi continue ;; -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then func_warning "\`-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test "$linkmode" = lib; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no func_dirname "$lib" "" "." ladir="$func_dirname_result" lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l *.ltframework) if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test "$linkmode" = lib ; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) new_inherited_linker_flags="$new_inherited_linker_flags $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; *) func_warning "\`-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then func_stripname '-R' '' "$deplib" dir=$func_stripname_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=no case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi ;; pass_all) valid_a_lib=yes ;; esac if test "$valid_a_lib" != yes; then $ECHO $ECHO "*** Warning: Trying to link with static lib archive $deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because the file extensions .$libext of this argument makes me believe" $ECHO "*** that it is just a static archive that I should not use here." else $ECHO $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi ;; esac continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" fi # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "\`$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir="$func_dirname_result" dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) new_inherited_linker_flags="$new_inherited_linker_flags $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" elif test "$linkmode" != prog && test "$linkmode" != lib; then func_fatal_error "\`$lib' is not a convenience library" fi tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then func_fatal_error "cannot find name of link library for \`$lib'" fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then func_fatal_error "cannot -dlopen a convenience library: \`$lib'" fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. dlprefiles="$dlprefiles $lib $dependency_libs" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of \`$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir="$ladir" fi ;; esac func_basename "$lib" laname="$func_basename_result" # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library \`$lib' was moved." dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir="$ladir" absdir="$abs_ladir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir" && test "$linkmode" = prog; then func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ dlpreconveniencelibs="$dlpreconveniencelibs $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" newlib_search_path="$newlib_search_path $func_stripname_result" ;; esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { { test "$prefer_static_libs" = no || test "$prefer_static_libs,$installed" = "built,yes"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then # Make sure the rpath contains only unique directories. case "$temp_rpath:" in *"$absdir:"*) ;; *) temp_rpath="$temp_rpath$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test "$use_static_libs" = built && test "$installed" = yes; then use_static_libs=no fi if test -n "$library_names" && { test "$use_static_libs" = no || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc*) # No point in relinking DLLs because paths are not encoded notinst_deplibs="$notinst_deplibs $lib" need_relink=no ;; *) if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule="" for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule="$dlpremoduletest" break fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then $ECHO if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname="$1" shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc*) func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" func_basename "$soroot" soname="$func_basename_result" func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from \`$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for \`$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; *-*-sysv4*uw2*) add_dir="-L$dir" ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we can not # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null ; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then $ECHO $ECHO "*** And there doesn't seem to be a static archive available" $ECHO "*** The link will probably fail, sorry" else add="$dir/$old_library" fi elif test -n "$old_library"; then add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && test "$hardcode_minus_L" != yes && test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes && test "$hardcode_direct_absolute" = no; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. $ECHO $ECHO "*** Warning: This system can not link to static lib archive $lib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then $ECHO "*** But as you try to build a module library, libtool will still create " $ECHO "*** a static module, that should work as long as the dlopening application" $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then $ECHO $ECHO "*** However, this would only work if libtool was able to extract symbol" $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" $ECHO "*** not find such a program. So, this module is probably useless." $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if $opt_duplicate_deps ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do case $deplib in -L*) path="$deplib" ;; *.la) func_dirname "$deplib" "" "." dir="$func_dirname_result" # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of \`$dir'" absdir="$dir" fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl" ; then depdepl="$absdir/$objdir/$depdepl" darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi compiler_flags="$compiler_flags ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" linker_flags="$linker_flags -dylib_file ${darwin_install_name}:${depdepl}" path= fi fi ;; *) path="-L$absdir/$objdir" ;; esac else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "\`$deplib' seems to be moved" path="-L$absdir" fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test "$pass" = link; then if test "$linkmode" = "prog"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then tmp_libs="$tmp_libs $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" fi if test "$linkmode" = prog || test "$linkmode" = lib; then dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "\`-R' is ignored for archives" test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "\`-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "\`-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test "$module" = no && \ func_fatal_help "libtool library \`$output' must begin with \`lib'" if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else $ECHO $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi test "$dlself" != no && \ func_warning "\`-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test "$#" -gt 1 && \ func_warning "ignoring multiple \`-rpath's for a libtool library" install_libdir="$1" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "\`-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "\`-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 shift IFS="$save_ifs" test -n "$7" && \ func_fatal_help "too many parameters to \`-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$1" number_minor="$2" number_revision="$3" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age="$number_minor" revision="$number_minor" lt_irix_increment=no ;; esac ;; no) current="$1" revision="$2" age="$3" ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT \`$current' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION \`$revision' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE \`$age' must be a nonnegative integer" func_fatal_error "\`$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE \`$age' is greater than the current interface number \`$current'" func_fatal_error "\`$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current" ;; irix | nonstopux) if test "X$lt_irix_increment" = "Xno"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) func_arith $current - $age major=.$func_arith_result versuffix="$major.$age.$revision" ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; qnx) major=".$current" versuffix=".$current" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. func_arith $current - $age major=$func_arith_result versuffix="-$major" ;; *) func_fatal_configuration "unknown library version type \`$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then func_warning "undefined symbols not allowed in $host shared libraries" build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi func_generate_dlsyms "$libname" "$libname" "yes" libobjs="$libobjs $symfileobj" test "X$libobjs" = "X " && libobjs= if test "$mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) if test "X$precious_files_regex" != "X"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi removelist="$removelist $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $ECHO $ECHO "*** Warning: linker path does not have real file for library $a_deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) newdeplibs="$newdeplibs $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $ECHO $ECHO "*** Warning: linker path does not have real file for library $a_deplib." $ECHO "*** I have the capability to make that library automatically link in when" $ECHO "*** you link to this library. But I can only do this if you have a" $ECHO "*** shared version of the library, which you do not appear to have" $ECHO "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` done fi if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | $GREP . >/dev/null; then $ECHO if test "X$deplibs_check_method" = "Xnone"; then $ECHO "*** Warning: inter-library dependencies are not supported in this platform." else $ECHO "*** Warning: inter-library dependencies are not known to be supported." fi $ECHO "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then $ECHO $ECHO "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" $ECHO "*** a static module, that should work as long as the dlopening" $ECHO "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then $ECHO $ECHO "*** However, this would only work if libtool was able to extract symbol" $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" $ECHO "*** not find such a program. So, this module is probably useless." $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else $ECHO "*** The inter-library dependencies that have been dropped here will be" $ECHO "*** automatically added whenever a program is linked with this library" $ECHO "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then $ECHO $ECHO "*** Since this library must not contain undefined symbols," $ECHO "*** because either the platform does not support them or" $ECHO "*** it was explicitly requested with -no-undefined," $ECHO "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done deplibs="$new_libs" # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname="$1" shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" linknames= for link do linknames="$linknames $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols="$output_objdir/$libname.uexp" delfiles="$delfiles $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile if test "x`$SED 1q $export_symbols`" != xEXPORTS; then # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols="$export_symbols" export_symbols= always_export_symbols=yes fi fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" func_len " $cmd" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then func_show_eval "$cmd" 'exit $?' skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS="$save_ifs" if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) tmp_deplibs="$tmp_deplibs $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test "$compiler_needs_object" = yes && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $convenience libobjs="$libobjs $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test "X$skipped_export" != "X:" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output output_la=`$ECHO "X$output" | $Xsed -e "$basename"` # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" $ECHO 'INPUT (' > $output for obj in $save_libobjs do $ECHO "$obj" >> $output done $ECHO ')' >> $output delfiles="$delfiles $output" elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test "$compiler_needs_object" = yes; then firstobj="$1 " shift fi for obj do $ECHO "$obj" >> $output done delfiles="$delfiles $output" output=$firstobj\"$file_list_spec$output\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-${k}.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test "X$objlist" = X || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. eval concat_cmds=\"$reload_cmds $objlist $last_robj\" else # All subsequent reloadable object files will link in # the last one created. eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext objlist=$obj func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi delfiles="$delfiles $output" else output= fi if ${skipped_export-false}; then func_verbose "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi fi test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi if ${skipped_export-false}; then if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter delfiles="$delfiles $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi fi libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $dlprefiles libobjs="$libobjs $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" eval cmd=\"$cmd\" $opt_silent || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test "$mode" = relink; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then func_warning "\`-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "\`-l' and \`-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "\`-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "\`-R' is ignored for objects" test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for objects" test -n "$release" && \ func_warning "\`-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object \`$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec and hope we can get by with # turning comma into space.. wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` else gentop="$output_objdir/${obj}x" generated="$generated $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "\`-version-info' is ignored for programs" test -n "$release" && \ func_warning "\`-release' is ignored for programs" test "$preload" = yes \ && test "$dlopen_support" = unknown \ && test "$dlopen_self" = unknown \ && test "$dlopen_self_static" = unknown && \ func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test "$tagname" = CXX ; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) compile_command="$compile_command ${wl}-bind_at_load" finalize_command="$finalize_command ${wl}-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) new_libs="$new_libs -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$new_libs $deplib" ;; esac ;; *) new_libs="$new_libs $deplib" ;; esac done compile_deplibs="$new_libs" compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) dllsearchpath="$dllsearchpath:$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) dllsearchpath="$dllsearchpath:$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=yes case $host in *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; *cegcc) # Disable wrappers for cegcc, we are cross compiling anyway. wrappers_required=no ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; esac if test "$wrappers_required" = no; then # Replace the output file specification. compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' # Delete the generated files. if test -f "$output_objdir/${outputname}S.${objext}"; then func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' fi exit $exit_status fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' exit $EXIT_SUCCESS fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" func_warning "this platform does not like uninstalled shared libraries" func_warning "\`$output' will be relinked during installation" else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $ECHO for shipping. if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then case $progpath in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; esac qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource="$output_path/$objdir/lt-$output_name.c" cwrapper="$output_path/$output_name.exe" $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host" ; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save $symfileobj" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" if test "$preload" = yes && test -f "$symfileobj"; then oldobjs="$oldobjs $symfileobj" fi fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $addlibs oldobjs="$oldobjs $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_extract_archives $gentop $dlprefiles oldobjs="$oldobjs $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else $ECHO "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase="$func_basename_result" case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" oldobjs="$oldobjs $gentop/$newobj" ;; *) oldobjs="$oldobjs $obj" ;; esac done fi eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "\`$deplib' is not a valid libtool archive" newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" newdlfiles="$newdlfiles $libdir/$name" ;; *) newdlfiles="$newdlfiles $lib" ;; esac done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name="$func_basename_result" eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "\`$lib' is not a valid libtool archive" newdlprefiles="$newdlprefiles $libdir/$name" ;; esac done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlfiles="$newdlfiles $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlprefiles="$newdlprefiles $abs" done dlprefiles="$newdlprefiles" fi $RM $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that can not go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } { test "$mode" = link || test "$mode" = relink; } && func_mode_link ${1+"$@"} # func_mode_uninstall arg... func_mode_uninstall () { $opt_debug RM="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) RM="$RM $arg"; rmforce=yes ;; -*) RM="$RM $arg" ;; *) files="$files $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= origobjdir="$objdir" for file in $files; do func_dirname "$file" "" "." dir="$func_dirname_result" if test "X$dir" = X.; then objdir="$origobjdir" else objdir="$dir/$origobjdir" fi func_basename "$file" name="$func_basename_result" test "$mode" = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test "$mode" = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" case "$mode" in clean) case " $library_names " in # " " in the beginning catches empty $dlname *" $dlname "*) ;; *) rmfiles="$rmfiles $objdir/$dlname" ;; esac test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test "$pic_object" != none; then rmfiles="$rmfiles $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test "$non_pic_object" != none; then rmfiles="$rmfiles $dir/$non_pic_object" fi fi ;; *) if test "$mode" = clean ; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe rmfiles="$rmfiles $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result rmfiles="$rmfiles $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi if test "X$noexename" != "X$name" ; then rmfiles="$rmfiles $objdir/lt-${noexename}.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done objdir="$origobjdir" # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } { test "$mode" = uninstall || test "$mode" = clean; } && func_mode_uninstall ${1+"$@"} test -z "$mode" && { help="$generic_help" func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode \`$mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: # vi:sw=2 cfengine-2.2.10/configure.ac0000644000175000001440000005755711170173233012576 00000000000000dnl ########################################################################## dnl # dnl # Process this file with autoconf then autoheader to build a configure dnl # script => aclocal; automake -a -c; autoconf dnl # dnl ########################################################################## AC_PREREQ(2.52) AC_INIT(src/cfagent.c) AC_CANONICAL_TARGET dnl dnl The version in the next line is the only one to set dnl AM_INIT_AUTOMAKE(cfengine, 2.2.10) dnl remember to set version AM_CONFIG_HEADER(src/conf.h) # # Add to the default list of places in LDFLAGS to compensate for # ... the configure default value of LIBS on some systems # for x in /usr/lib64 /usr/local/gnu/lib /usr/local/gnulib /opt/dce/lib /sw/lib do if test -d "$x"; then y=`expr " $LDFLAGS " : ".* -L$x "` if test $y -eq 0; then LDFLAGS="$LDFLAGS -L$x" fi fi done # # Add to the default list of places in CPPFLAGS to match LDFLAGS above # for x in /usr/local/gnu/include /opt/dce/include /sw/include do if test -d "$x"; then y=`expr " $CPPFLAGS " : ".* -I$x "` if test $y -eq 0; then CPPFLAGS="$CPPFLAGS -I$x" fi fi done ACX_PTHREAD CC=$PTHREAD_CC CFLAGS="$PTHREAD_CFLAGS $CFLAGS" CPPFLAGS="$PTHREAD_CPPFLAGS $CPPFLAGS" LDFLAGS="$PTHREAD_LDFLAGS $LDFLAGS" dnl ###################################################################### dnl Checks for programs. dnl ###################################################################### AC_PROG_CC AM_PROG_LEX AC_PROG_YACC AC_PROG_RANLIB AC_PROG_INSTALL AM_PROG_CC_C_O AC_DISABLE_SHARED dnl AC_DISABLE_STATIC - maybe use shared libs later AC_PROG_LIBTOOL AC_CONFIG_LIBOBJ_DIR(pub) AC_FUNC_GETLOADAVG AC_PATH_PROG(LATEX, latex, false, $PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin) AC_PATH_PROG(TEXI2DVI, texi2dvi, false, $PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin) AC_PATH_PROG(DVIPS, dvips, false, $PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin) AC_PATH_PROG(MAKEINFO, makeinfo, false, $PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin) AC_PATH_PROG(PS2PDF, ps2pdf, false, $PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin) AC_PATH_PROG(GETCONF, getconf, false, $PATH:$prefix/bin:/usr/bin:/usr/local/bin:/sw/bin) dnl ###################################################################### dnl Checks for libraries. dnl ###################################################################### AC_CHECK_LIB(m,main) AC_CHECK_FUNC(door_create,door) AC_CHECK_FUNC(setsockopt, , AC_CHECK_LIB(socket, setsockopt)) AC_CHECK_FUNC(gethostent, , AC_CHECK_LIB(nsl, gethostent)) AC_CHECK_FUNC(getaddrinfo, , AC_CHECK_LIB(socket, getaddrinfo)) dnl AC_CHECK_FUNC(yp_get_default_domain, , AC_CHECK_LIB(nsl, yp_get_default_domain)) AC_SEARCH_LIBS(socket, socket, , [AC_CHECK_LIB(nsl, socket, LIBS="$LIBS -lsocket -lnsl", , -lsocket)]) dnl dnl Look for Berkeley DB. dnl AC_ARG_WITH(berkeleydb, [ --with-berkeleydb[=PATH] directory where BerkeleyDB exists], BERKELEY_DB_DIR=$with_berkeleydb, BERKELEY_DB_DIR=default) AC_MSG_CHECKING(for BerkeleyDB location in $BERKELEY_DB_DIR) if test "x$BERKELEY_DB_DIR" = "xno" ; then AC_MSG_RESULT( ) AC_MSG_ERROR(This release of cfengine requires a version of BerkeleyDB 4.4 or later) else if test "x$BERKELEY_DB_DIR" = "xdefault" ; then for v in BerkeleyDB.4.2 BerkeleyDB.4.3 BerkeleyDB.4.4 BerkeleyDB.4.5 BerkeleyDB.4.6 BerkeleyDB.4.7; do for d in $prefix /opt /usr/local /usr; do test -d "$d/$v" && BERKELEY_DB_DIR="$d/$v" done done fi if test "x$BERKELEY_DB_DIR" = "xdefault" ; then for d in $prefix /opt /usr/local /usr; do for v in db-4 db4 db3 db db40; do if test -f "$d/include/$v/db.h" ; then echo "Found header in $d/include/$v " test "x$d" != "x/usr" && BERKELEY_DB_LDFLAGS="-L$d/lib" BERKELEY_DB_CFLAGS="-I$d/include/$v" late_LIBS=$LIBS # In RedHat 8, for instance, we have /usr/include/db4 # and libdb-4.0.a. Debian has /usr/lib/libdb-4.1.a, for # instance. Look for the appropriate library. if test $v = db4 -o $v = db40; then save_CFLAGS="$CFLAGS" save_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $BERKELEY_DB_CFLAGS" LDFLAGS="$LDFLAGS $BERKELEY_DB_LDFLAGS" AC_SEARCH_LIBS(db_create, [db-4 db4 db-4.7 db-4.6 db-4.5 db-4.4 db-4.3 db-4.2 db-4.1 db-4.0], [BERKELEY_DB_LIB=$ac_cv_search_db_create]) CFLAGS="$save_CFLAGS" LDFLAGS="$save_LDFLAGS" else BERKELEY_DB_LIB="-l$v" fi LIBS=$late_LIBS AC_MSG_RESULT($d) break fi done test "x$BERKELEY_DB_LIB" != "x" && break if test -f "$d/include/db.h"; then if test "x$d" != "x/usr"; then BERKELEY_DB_LDFLAGS="-L$d/lib64 -L$d/lib" BERKELEY_DB_CFLAGS="-I$d/include" fi BERKELEY_DB_LIB="-ldb" AC_MSG_RESULT($d) break fi done if test "x$BERKELEY_DB_LIB" = "x" ; then AC_MSG_ERROR(Cannot find BerkeleyDB) fi elif test -f "$BERKELEY_DB_DIR/include/db.h";then case "$target_os" in solaris*) #If we are staticlly linking the BDB files, we do not want a #-R flag. If .so's are present, assume we are dynamic linking if test -n "`ls $BERKELEY_DB_DIR/lib/*.so 2>/dev/null`" then BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib -R$BERKELEY_DB_DIR/lib" else BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib" fi;; *) BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib";; esac BERKELEY_DB_CFLAGS="-I$BERKELEY_DB_DIR/include" BERKELEY_DB_LIB="-ldb" AC_MSG_RESULT($BERKELEY_DB_DIR) elif test -d "$BERKELEY_DB_DIR"; then BERKELEY_DB_CFLAGS="-I$BERKELEY_DB_DIR/include" for v in . db47 db46 db45 db44 db43 db42 db41 db40 db4 db33 db32 db3 db; do if test -f "$BERKELEY_DB_DIR/include/$v/db.h"; then BERKELEY_DB_CFLAGS="-I$BERKELEY_DB_DIR/include/$v" break fi done BERKELEY_DB_LIB="-ldb" for v in db-4.7 db4.7 db47 db-4.6 db4.6 db46 db-4.5 db4.5 db45 db-4.4 db4.4 db44; do if test -f "$BERKELEY_DB_DIR/lib/lib$v.so"; then BERKELEY_DB_LIB="-l$v" break fi if test -f "$BERKELEY_DB_DIR/lib64/lib$v.so"; then BERKELEY_DB_LIB="-l$v" break fi done case "$target_os" in solaris*) #If we are staticlly linking the BDB files, we do not want a #-R flag. If .so's are present, assume we are dynamic linking if test -n "`ls $BERKELEY_DB_DIR/lib/*.so 2>/dev/null`" then BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib -R$BERKELEY_DB_DIR/lib" else BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib" fi;; *) BERKELEY_DB_LDFLAGS="-L$BERKELEY_DB_DIR/lib";; esac AC_MSG_RESULT($BERKELEY_DB_DIR) else AC_MSG_ERROR(Cannot find BerkeleyDB) fi AC_DEFINE(USE_BERKELEY_DB, 1, [Define if BerkeleyDB is available.]) BERKELEY_DB_SAVE_LDFLAGS=$LDFLAGS BERKELEY_DB_SAVE_CPPFLAGS=$CPPFLAGS BERKELEY_DB_SAVE_LIBS=$LIBS LDFLAGS="$LDFLAGS $BERKELEY_DB_LDFLAGS" CFLAGS="$CFLAGS $BERKELEY_DB_CFLAGS" LIBS="$LIBS $BERKELEY_DB_LIB" AC_MSG_CHECKING(Berkeley DB Version) AC_TRY_RUN( [ #include #include int main(void) { printf("%d.%d.%d ",DB_VERSION_MAJOR,DB_VERSION_MINOR,DB_VERSION_PATCH); if (DB_VERSION_MAJOR < 3 || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 2)) exit(1); exit(0); } ], [AC_MSG_RESULT(OK)], [AC_MSG_ERROR(This release of cfengine requires BerkeleyDB 3.2 or later)] ) AC_MSG_CHECKING(Berkeley DB API) AC_TRY_RUN( [ #include #include int main(void) { printf("%d.%d.%d ",DB_VERSION_MAJOR,DB_VERSION_MINOR,DB_VERSION_PATCH); if (DB_VERSION_MAJOR < 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 1)) exit(1); exit(0); } ], [AC_MSG_RESULT(OK)], [AC_DEFINE(CF_OLD_DB,1,Define if old Berkeley API)] ) AC_CHECK_LIB(db, db_create) LDFLAGS=$BERKELEY_DB_SAVE_LDFLAGS CPPFLAGS=$BERKELEY_DB_SAVE_CPPFLAGS LIBS=$BERKELEY_DB_SAVE_LIBS fi AC_SUBST(BERKELEY_DB_LDFLAGS) AC_SUBST(BERKELEY_DB_CFLAGS) AC_SUBST(BERKELEY_DB_LIB) ### ### Search for openssl ### AC_ARG_WITH(openssl, [ --with-openssl[=PATH] directory where OpenSSL exists], OPENSSL_LIB_DIR=$with_openssl, OPENSSL_LIB_DIR=default) AC_MSG_CHECKING(for OpenSSL location) if test x"$OPENSSL_LIB_DIR" = xno ; then AC_MSG_RESULT(no) AC_MSG_ERROR(This release of cfengine requires OpenSSL 0.9.7 or later) else if test x"$OPENSSL_LIB_DIR" = xdefault ; then for d in $prefix /opt/ssl /usr/local/ssl /usr/local /usr; do if test -f "$d/include/openssl/opensslv.h"; then OPENSSL_LIB_LDFLAGS="-L$d/lib64 -L$d/lib" OPENSSL_LIB_CPPFLAGS="-I$d/include" OPENSSL_LIB_LIB="-lcrypto" AC_MSG_RESULT($d) break fi done if test x"$OPENSSL_LIB_LIB" = x ; then AC_MSG_ERROR(Cannot find OpenSSL) fi elif test -f "$OPENSSL_LIB_DIR/include/openssl/ssl.h";then case "$target_os" in solaris*) #If we are staticlly linking the SSL files, we do not want a #-R flag. If .so's are present, assume we are dynamic linking if test -n "`ls $OPENSSL_LIB_DIR/lib/*.so 2>/dev/null`" then OPENSSL_LIB_LDFLAGS="-L$OPENSSL_LIB_DIR/lib -R$OPENSSL_LIB_DIR/lib" else OPENSSL_LIB_LDFLAGS="-L$OPENSSL_LIB_DIR/lib" fi;; *) OPENSSL_LIB_LDFLAGS="-L$OPENSSL_LIB_DIR/lib";; esac OPENSSL_LIB_CPPFLAGS="-I$OPENSSL_LIB_DIR/include" OPENSSL_LIB_LIB="-lcrypto" AC_MSG_RESULT($OPENSSL_LIB_DIR) else AC_MSG_ERROR(Cannot find OpenSSL) fi AC_DEFINE(USE_OPENSSL_LIB, 1, [Define if OpenSSL is available.]) OPENSSL_SAVE_LDFLAGS=$LDFLAGS OPENSSL_SAVE_CPPFLAGS=$CPPFLAGS OPENSSL_SAVE_LIBS=$LIBS LDFLAGS="$LDFLAGS $OPENSSL_LIB_LDFLAGS" CPPFLAGS="$CPPFLAGS $OPENSSL_LIB_CPPFLAGS" LIBS="$LIBS $OPENSSL_LIB_LIB" AC_MSG_CHECKING(OpenSSL Version) AC_TRY_RUN( [ #include int main(void) { if (OPENSSL_VERSION_NUMBER < 0x0090602fL) exit(1); exit(0); } ], [AC_MSG_RESULT(OK)], [AC_MSG_ERROR(This release of cfengine requires openssl 0.9.7 or later)] ) dnl ###################################################################### dnl Checks for OpenSSL crypto lib dnl ###################################################################### AC_CHECK_LIB(crypto,main) LDFLAGS=$OPENSSL_SAVE_LDFLAGS CPPFLAGS=$OPENSSL_SAVE_CPPFLAGS LIBS=$OPENSSL_SAVE_LIBS fi AC_SUBST(OPENSSL_LIB_LDFLAGS) AC_SUBST(OPENSSL_LIB_CPPFLAGS) AC_SUBST(OPENSSL_LIB_LIB) dnl ###################################################################### dnl Checks for perl compatible regular expressions dnl ###################################################################### AC_ARG_WITH(pcre, [ --with-pcre[[=PATH]] directory where Perl compatible regex exists (optionally in PATH)], [ AC_MSG_CHECKING(pcre) if test "x$withval" != "xno" ; then if test "x$withval" != "xyes" ; then if test "x$withval" = "xdefault" ; then for d in $prefix /usr/local /usr; do if test -f "$d/include/pcreposix.h" ; then CPPFLAGS="$CPPFLAGS -I$d/include" LDFLAGS="$LDFLAGS -L$d/lib" PCRE_LIB="-lpcreposix" AC_MSG_RESULT($d) break fi done if test x"$PCRE_LIB" = x ; then AC_MSG_ERROR(Cannot find PCRE) fi else if test -f "${withval}/include/pcreposix.h" ; then CPPFLAGS="$CPPFLAGS -I${withval}/include" LDFLAGS="$LDFLAGS -L${withval}/lib" AC_MSG_RESULT("${withval}") else AC_MSG_ERROR(Cannot find PCRE) fi fi else AC_MSG_RESULT("yes") fi LIBS="$LIBS -lpcreposix" AC_DEFINE(USE_PCRE, 1, [Define if PCRE is available.]) fi ] ) dnl ###################################################################### dnl Checks for regular expressions dnl GNU regex lib if you have regcomp in libc you should NOT have this lib too dnl ###################################################################### AC_CHECK_LIB(rx, main) AC_CHECK_LIB(rt, main) dnl ###################################################################### dnl Checks for header files. dnl ###################################################################### AC_CHECK_HEADERS(unistd.h stdlib.h sys/loadavg.h) AC_CHECK_HEADERS(sys/mount.h) AC_CHECK_HEADERS(utime.h) AC_CHECK_HEADERS(time.h) AC_CHECK_HEADERS(sys/time.h) AC_CHECK_HEADERS(malloc.h sys/malloc.h) AC_CHECK_HEADERS(vfs.h) AC_CHECK_HEADERS(sys/vfs.h) AC_CHECK_HEADERS(sys/sockio.h) AC_CHECK_HEADERS(sys/statvfs.h) AC_CHECK_HEADERS(sys/statfs.h) AC_CHECK_HEADERS(sys/param.h) AC_CHECK_HEADERS(fcntl.h) AC_CHECK_HEADERS(sys/filesys.h) AC_CHECK_HEADERS(dustat.h) AC_CHECK_HEADERS(regex.h rxposix.h) AC_CHECK_HEADERS(sys/systeminfo.h) AC_CHECK_HEADERS(sys/acl.h) AC_HEADER_STDC AC_HEADER_TIME AC_HEADER_SYS_WAIT AC_HEADER_DIRENT dnl ###################################################################### dnl Checks for data types dnl ###################################################################### AC_TYPE_MODE_T AC_TYPE_SIZE_T AC_TYPE_UID_T AC_TYPE_PID_T AC_CHECK_TYPES(clockid_t) dnl ###################################################################### dnl Checks for typedefs, structures, and compiler characteristics. dnl ###################################################################### AC_C_CONST dnl ###################################################################### dnl Check for special functions dnl ###################################################################### AC_CHECK_FUNCS(getcwd getnetgrent waitpid seteuid setegid setreuid setregid) AC_CHECK_FUNCS(uname gethostname realpath regcomp chflags) AC_CHECK_FUNCS(strstr strsep putenv drand48 srand48 getaddrinfo) AC_CHECK_FUNCS(bcopy mkfifo statfs statvfs door qsort) AC_CHECK_FUNCS(sysinfo setsid strdup strrchr strerror snprintf sysconf) dnl ###################################################################### dnl Check for sa_len in struct sockaddr dnl ###################################################################### AC_CHECK_MEMBERS([struct sockaddr.sa_len], , , [ #include #include ]) dnl ####################################################################### dnl Newer BSD systems don't have a compatible rtentry - use ortentry dnl ####################################################################### rtry=none AC_MSG_CHECKING(for either struct rtentry or struct ortentry) AC_EGREP_HEADER(rtentry, net/route.h, rtry=rtentry) if test "$rtry" = rtentry; then AC_DEFINE(HAVE_RTENTRY) fi AC_EGREP_HEADER(ortentry, net/route.h, rtry=ortentry) if test "$rtry" = ortentry; then AC_DEFINE(HAVE_ORTENTRY) fi AC_MSG_RESULT([$rtry]) dnl ####################################################################### dnl Large File Support dnl ####################################################################### lfsresult=no AC_MSG_CHECKING(whether to compile with large file support) if test "$GETCONF" != "false"; then lfscflags=`$GETCONF LFS_CFLAGS 2>/dev/null` if test -n "$lfscflags"; then CFLAGS="$CFLAGS $lfscflags" lfsresult=yes fi lfsldflags=`$GETCONF LFS_LDFLAGS 2>/dev/null` test -n "$lfsldflags" && LDFLAGS="$LDFLAGS $lfsldflags" fi AC_MSG_RESULT([$lfsresult]) dnl ####################################################################### dnl Handle DCE + threading stuff dnl ####################################################################### AC_CHECK_LIB(pthread,main) dnl POSIX threads if test "$ac_cv_lib_pthread_main" = "yes"; then AC_CHECK_HEADERS(pthread.h) AC_CHECK_HEADERS(sched.h) fi AC_CHECK_FUNC(lchown, AC_DEFINE(HAVE_LCHOWN)) AC_CHECK_FUNC(pthread_attr_setstacksize, AC_DEFINE(HAVE_PTHREAD_ATTR_SETSTACKSIZE), AC_CHECK_LIB(pthread, pthread_create)) AC_CHECK_FUNC(pthread_sigmask, AC_DEFINE(HAVE_PTHREAD_SIGMASK), AC_CHECK_LIB(pthread, pthread_create)) AC_ARG_ENABLE(DCE,[ --enable-DCE support for DCE and ACLs],[ case "$enableval" in no) ;; *) AC_CHECK_LIB(thread, main) AC_CHECK_LIB(dce, main) dnl DFS AC_CHECK_HEADERS(dce/daclif.h) AC_CHECK_HEADERS(pthread.h) AC_CHECK_HEADERS(sched.h) ;; esac ]) dnl ###################################################################### dnl Give the chance to enable SELINUX dnl ###################################################################### dnl AC_ARG_ENABLE(selinux, dnl [ --enable-selinux Enable use of the SELINUX libraries], [AC_DEFINE(WITH_SELINUX, 1, [Define if you want to use SELINUX]) LIB_SELINUX="-lselinux" LIBS="$LIBS $LIB_SELINUX" AC_SUBST(LIB_SELINUX)]) dnl ###################################################################### dnl OS specific stuff dnl ###################################################################### dnl To ensure conf.h is picked up via VPATH if test "$srcdir" != "."; then CPPFLAGS="$CPPFLAGS -I`pwd`/src" fi case "$target_os" in sunos3*) AC_DEFINE(SUN3) ;; sunos4*) AC_DEFINE(SUN4) ;; solaris2.4*) AC_DEFINE(SOLARIS) AC_DEFINE(HAVE_SYS_ACL_H,) CPPFLAGS="-w $CPPFLAGS" LIBS="$LIBS -lelf" ;; solaris2.5*) AC_DEFINE(SOLARIS) AC_DEFINE(_POSIX_C_SOURCE) AC_DEFINE(__EXTENSIONS__) LIBS="$LIBS -lelf -lsec" ;; solaris2*) AC_DEFINE(SOLARIS) AC_DEFINE(__BIT_TYPES_DEFINED__) # avoid conflict with db.h AC_PREPROC_IFELSE([ AC_LANG_PROGRAM([[ #define _POSIX_C_SOURCE 1 #include ]], [])], [AC_DEFINE(_POSIX_C_SOURCE)], [AC_DEFINE(_POSIX_C_SOURCE, 200112loL)]) AC_DEFINE(__EXTENSIONS__) LIBS="$LIBS -lelf -lsec" ;; ultrix*) AC_DEFINE(ULTRIX) ;; hpux*|hp-ux*) AC_DEFINE(HPuUX) if test "$GCC" != "yes"; then AC_DEFINE(REGEX_MALLOC) fi LIBS="$LIBS -lc" AC_CHECK_LIB(PW, main) ;; aix*) AC_DEFINE(AIX) CPPFLAGS="$CPPFLAGS -w" AC_CHECK_LIB(pthreads, main) AC_CHECK_HEADER(pthreads.h) ;; osf*) AC_DEFINE(OSF) if test "$GCC" = yes; then AC_MSG_WARN([pthreads may not work with GCC under Tru64]) AC_MSG_WARN([If you get build errors mentioning PTHREADDEFAULTS etc.,]) AC_MSG_WARN([re-configure with CC=cc.]) fi ;; irix6*) # rtentry is detected OK on a 6.5.19 system. AC_DEFINE(HAVE_ORTENTRY) # Have to hack this for 6.* owing to bug AC_DEFINE(IRIX) CFLAGS="$CFLAGS -w" ;; irix4*) AC_DEFINE(IRIX) CFLAGS="$CFLAGS -w" LIBS="$LIBS -lsun" ;; irix*) AC_DEFINE(IRIX) CFLAGS="$CFLAGS -w" ;; linux*) AC_DEFINE(LINUX) AC_CHECK_LIB(nss_nis, yp_get_default_domain) ;; freebsd*|dragonfly*) AC_DEFINE(FREEBSD) CFLAGS="$CFLAGS -pthread -D_THREAD_SAFE -DBUILDTIN_GCC_THREAD" AC_CHECK_HEADERS(pthread.h) ;; netbsd*) AC_DEFINE(NETBSD) ;; newsos*) AC_DEFINE(NEWS_OS) ;; bsd/os*) AC_DEFINE(BSDOS) ;; bsd*) AC_DEFINE(BSD43) ;; aos*) AC_DEFINE(AOS) ;; nextstep*) AC_DEFINE(NEXTSTEP) ;; unicos*) AC_DEFINE(CFCRAY) ;; cray*) AC_DEFINE(CFCRAY) ;; qnx*) AC_DEFINE(CFQNX) ;; openbsd*|obsd*) AC_DEFINE(OPENBSD) ;; gnu*) AC_DEFINE(CFGNU) ;; sysv4.2MP|unix_sv*) AC_DEFINE(UNIXWARE) AC_CHECK_LIB(thread,main) dnl POSIX threads, weird setup if test "$ac_cv_lib_thread_main" = "yes"; then AC_CHECK_HEADERS(thread.h) fi ;; cygwin*) AC_DEFINE(NT) ;; sco*) AC_DEFINE(SCO) ;; darwin*) AC_DEFINE(DARWIN) LDFLAGS="-Xlinker -m $LDFLAGS" ;; *) AC_MSG_ERROR(Unknown system type $target_os) ;; esac dnl ##################################################################### dnl Configure LOCKDIR and LOGDIR dnl ##################################################################### AC_ARG_WITH(workdir, [ --with-workdir=WORKDIR default internal for trusted cache ], [ if test x$withval != x ; then WORKDIR=$withval else WORKDIR=/var/cfengine fi AC_DEFINE_UNQUOTED(WORKDIR, "${WORKDIR}") ], [ WORKDIR=/var/cfengine AC_DEFINE_UNQUOTED(WORKDIR, "${WORKDIR}") ] ) dnl ##################################################################### dnl Fix for lex/flex dnl ##################################################################### AC_MSG_CHECKING(8-bit support in Flex) if test "$LEX" = "flex"; then EIGHTBIT="\200-\377" AC_SUBST(EIGHTBIT) AC_MSG_RESULT(8-bit support added) NOWRAP="%option noyywrap" else AC_MSG_RESULT(no 8-bit support) NOWRAP="" fi AC_SUBST(NOWRAP) LIBS="-L../pub -lcfpub $LIBS" dnl #################################################################### dnl Set GCC CFLAGS only if using GCC. dnl #################################################################### AC_MSG_CHECKING(Checking for GCC Specific compile flags) if test x"$GCC" = "xyes"; then dnl # -Wformat - to be considered GCC_CFLAG="-g -O2 -Wreturn-type -Wmissing-prototypes -Wuninitialized" AC_MSG_RESULT(yes) AC_SUBST(GCC_CFLAG) else GCC_CFLAG="" AC_MSG_RESULT(no) AC_SUBST(GCC_CFLAG) fi dnl ##################################################################### dnl Hostname and Version stuff dnl ##################################################################### AC_PATH_PROG(HOSTNAME, hostname, "", $PATH) AC_DEFINE_UNQUOTED(AUTOCONF_HOSTNAME, "`$HOSTNAME`") AC_DEFINE_UNQUOTED(AUTOCONF_SYSNAME, "$target_os") dnl ##################################################################### dnl xen cpuid-based hvm detection dnl ##################################################################### AC_MSG_CHECKING(Checking for Xen cpuid-based HVM detection) if test x"$GCC" = "xyes"; then case $host_cpu in i[[3456]]86*|x86_64*) AC_DEFINE(XEN_CPUID_SUPPORT, 1, [Define if XEN cpuid-based HVM detection is available.]) AC_MSG_RESULT(yes) ;; *) AC_MSG_RESULT(no) ;; esac else AC_MSG_RESULT(no) fi dnl ###################################################################### dnl Now make the Makefiles dnl ###################################################################### AC_ARG_WITH(docs, [ --with-docs build the documentation], [ want_doc=true ], [ want_doc=false ]) AM_CONDITIONAL(BUILD_DOC, test x$want_doc = xtrue) AC_OUTPUT(pub/Makefile src/Makefile doc/Makefile contrib/Makefile inputs/Makefile \ Makefile src/cflex.l ) AC_MSG_WARN(=====================================================) AC_MSG_WARN( ) AC_MSG_WARN( DFS users should use --enable-DCE) AC_MSG_WARN( ) AC_MSG_WARN( Cfengine depends on the Berkeley db and OpenSSL ) AC_MSG_WARN( Most recent versions are always recommended ) AC_MSG_WARN(=====================================================) rm -f src/cfparse.c src/cfparse.h AC_MSG_RESULT(DONE: Configuration done. Run make/gmake to build cfengine.) cfengine-2.2.10/aclocal.m40000644000175000001440000115121711170173241012134 00000000000000# generated automatically by aclocal 1.10.1 -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(AC_AUTOCONF_VERSION, [2.63],, [m4_warning([this file was generated for autoconf 2.63. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) # serial 56 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_CC_BASENAME(CC) # ------------------- # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. m4_defun([_LT_CC_BASENAME], [for cc_temp in $1""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl _LT_PROG_ECHO_BACKSLASH case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # `config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain="$ac_aux_dir/ltmain.sh" ])# _LT_PROG_LTMAIN # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the `libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to `config.status' so that its # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "X$" | $Xsed -e "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags="_LT_TAGS"dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the `libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into `config.status', and then the shell code to quote escape them in # for loops in `config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Fix-up fallback echo if it was mangled by the above quoting rules. case \$lt_ECHO in *'\\\[$]0 --fallback-echo"')dnl " lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\` ;; esac _LT_OUTPUT_LIBTOOL_INIT ]) # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) cat >"$CONFIG_LT" <<_LTEOF #! $SHELL # Generated by $as_me. # Run this file to recreate a libtool stub with the current configuration. lt_cl_silent=false SHELL=\${CONFIG_SHELL-$SHELL} _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ \`$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2008 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test $[#] != 0 do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try \`$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try \`$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. if test "$no_create" != yes; then lt_cl_success=: test "$silent" = yes && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) fi ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # _LT_COPYING _LT_LIBTOOL_TAGS # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) _LT_PROG_XSI_SHELLFNS sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[[012]]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES # -------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(whole_archive_flag_spec, $1)='' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=echo _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" m4_if([$1], [CXX], [ if test "$lt_cv_apple_cc_single_mod" != "yes"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX # ----------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl AC_LINK_IFELSE(AC_LANG_PROGRAM,[ lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/ p } }' aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [ifdef([AC_DIVERSION_NOTICE], [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], [AC_DIVERT_PUSH(NOTICE)]) $1 AC_DIVERT_POP ])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Add some code to the start of the generated configure script which # will find an echo command which doesn't interpret backslashes. m4_defun([_LT_PROG_ECHO_BACKSLASH], [_LT_SHELL_INIT([ # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$lt_ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` ;; esac ECHO=${lt_ECHO-echo} if test "X[$]1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X[$]1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then # Yippee, $ECHO works! : else # Restart under the correct shell. exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} fi if test "X[$]1" = X--fallback-echo; then # used as fallback echo shift cat <<_LT_EOF [$]* _LT_EOF exit 0 fi # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test -z "$lt_ECHO"; then if test "X${echo_test_string+set}" != Xset; then # find a string as large as possible, as long as the shell can cope with it for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... if { echo_test_string=`eval $cmd`; } 2>/dev/null && { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null then break fi done fi if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$ECHO" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. ECHO='print -r' elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} else # Try using printf. ECHO='printf %s\n' if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL ECHO="$CONFIG_SHELL [$]0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then ECHO="$CONFIG_SHELL [$]0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "[$]0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} else # Oops. We lost completely, so just stick with echo. ECHO=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. lt_ECHO=$ECHO if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" fi AC_SUBST(lt_ECHO) ]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that does not interpret backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '[#]line __oline__ "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" ])# _LT_ENABLE_LOCK # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [AC_CHECK_TOOL(AR, ar, false) test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1]) AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test x"[$]$2" = xyes; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" ]) if test x"[$]$2" = xyes; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ = "XX$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n $lt_cv_sys_max_cmd_len ; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "$cross_compiling" = yes; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line __oline__ "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen="shl_load"], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen="dlopen"], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) ]) ]) ]) ]) ]) ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links="nottested" if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test "$hard_links" = no; then AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then # We can hardcode non-existent directories. if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` else lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[[4-9]]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[123]]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; interix[[3-9]]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[[89]] | openbsd2.[[89]].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([], [sys_lib_dlsearch_path_spec], [2], [Run-time system search path for libraries]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program which can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$1; then lt_cv_path_MAGIC_CMD="$ac_dir/$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac]) MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program which can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test "$withval" = no || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method == "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi]) if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ const struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= AC_MSG_CHECKING([for $compiler option to produce PIC]) m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' if test "$host_cpu" != ia64; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64 which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC*) # IBM XL 8.0 on PPC _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; pgcc* | pgf77* | pgf90* | pgf95*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl*) # IBM XL C 8.0/Fortran 10.1 on PPC _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Sun\ F*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw* | cegcc*) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag= tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; freebsd1*) _LT_TAGVAR(ld_shlibs, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac fi if test "$with_gnu_ld" = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE(int foo(void) {}, _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' ) LDFLAGS="$save_LDFLAGS" else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_MSG_CHECKING([whether -lc should be explicitly linked in]) $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then _LT_TAGVAR(archive_cmds_need_lc, $1)=no else _LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)]) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], [[If ld is used when linking, flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting ${shlibpath_var} if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [fix_srcfile_path], [1], [Fix the shell variable $srcfile for the compiler]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report which library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG # _LT_PROG_CXX # ------------ # Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++ # compiler, we have our own version here. m4_defun([_LT_PROG_CXX], [ pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes]) AC_PROG_CXX if test -n "$CXX" && ( test "X$CXX" != "Xno" && ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || (test "X$CXX" != "Xg++"))) ; then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_CXX dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_CXX], []) # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [AC_REQUIRE([_LT_PROG_CXX])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_caught_CXX_error" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' if test "$GXX" = yes; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd[[12]]*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; *) # Version 6 will use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; xl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd2*) # C++ shared libraries are fairly broken _LT_TAGVAR(ld_shlibs, $1)=no ;; openbsd*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi output_verbose_link_cmd=echo else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='echo' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_TAGVAR(GCC, $1)="$GXX" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test "$_lt_caught_CXX_error" != yes AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ]) dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" || test $p = "-R"; then prev=$p continue else prev= fi if test "$pre_test_object_deps_done" = no; then case $p in -L* | -R*) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)="${prev}${p}" else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" fi fi ;; *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)="$p" else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)="$p" else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; solaris*) case $cc_basename in CC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as # -library=stlport4 depends on it. case " $CXX $CXXFLAGS " in *" -library=stlport4 "*) solaris_use_stlport4=yes ;; esac # Adding this requires a known-good setup of shared libraries for # Sun compiler versions before 5.6, else PIC objects from an old # archive will be linked into the output, leading to subtle bugs. if test "$solaris_use_stlport4" != yes; then _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' fi ;; esac ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_PROG_F77 # ------------ # Since AC_PROG_F77 is broken, in that it returns the empty string # if there is no fortran compiler, we have our own version here. m4_defun([_LT_PROG_F77], [ pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes]) AC_PROG_F77 if test -z "$F77" || test "X$F77" = "Xno"; then _lt_disable_F77=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_F77 dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_F77], []) # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_REQUIRE([_LT_PROG_F77])dnl AC_LANG_PUSH(Fortran 77) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_F77" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC CC=${F77-"f77"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$G77" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" fi # test "$_lt_disable_F77" != yes AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_PROG_FC # ----------- # Since AC_PROG_FC is broken, in that it returns the empty string # if there is no fortran compiler, we have our own version here. m4_defun([_LT_PROG_FC], [ pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes]) AC_PROG_FC if test -z "$FC" || test "X$FC" = "Xno"; then _lt_disable_FC=yes fi popdef([AC_MSG_ERROR]) ])# _LT_PROG_FC dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([_LT_PROG_FC], []) # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_REQUIRE([_LT_PROG_FC])dnl AC_LANG_PUSH(Fortran) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test "$_lt_disable_FC" != yes; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC CC=${FC-"f95"} compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" _LT_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC="$lt_save_CC" fi # test "$_lt_disable_FC" != yes AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)="$LD" _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC="$lt_save_CC" ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC="$CC" lt_save_GCC=$GCC GCC= CC=${RC-"windres"} compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC="$lt_save_CC" ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [AC_MSG_CHECKING([whether the shell understands some XSI constructs]) # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes AC_MSG_RESULT([$xsi_shell]) _LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) AC_MSG_CHECKING([whether the shell understands "+="]) lt_shell_append=no ( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes AC_MSG_RESULT([$lt_shell_append]) _LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PROG_XSI_SHELLFNS # --------------------- # Bourne and XSI compatible variants of some useful shell functions. m4_defun([_LT_PROG_XSI_SHELLFNS], [case $xsi_shell in yes) cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac } # func_basename file func_basename () { func_basename_result="${1##*/}" } # func_dirname_and_basename file append nondir_replacement # perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # Implementation must be kept synchronized with func_dirname # and func_basename. For efficiency, we do not delegate to # those functions but instead duplicate the functionality here. func_dirname_and_basename () { case ${1} in */*) func_dirname_result="${1%/*}${2}" ;; * ) func_dirname_result="${3}" ;; esac func_basename_result="${1##*/}" } # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). func_stripname () { # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary parameter first. func_stripname_result=${3} func_stripname_result=${func_stripname_result#"${1}"} func_stripname_result=${func_stripname_result%"${2}"} } # func_opt_split func_opt_split () { func_opt_split_opt=${1%%=*} func_opt_split_arg=${1#*=} } # func_lo2o object func_lo2o () { case ${1} in *.lo) func_lo2o_result=${1%.lo}.${objext} ;; *) func_lo2o_result=${1} ;; esac } # func_xform libobj-or-source func_xform () { func_xform_result=${1%.*}.lo } # func_arith arithmetic-term... func_arith () { func_arith_result=$(( $[*] )) } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=${#1} } _LT_EOF ;; *) # Bourne compatible functions. cat << \_LT_EOF >> "$cfgfile" # func_dirname file append nondir_replacement # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. func_dirname () { # Extract subdirectory from the argument. func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi } # func_basename file func_basename () { func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` } dnl func_dirname_and_basename dnl A portable version of this function is already defined in general.m4sh dnl so there is no need for it here. # func_stripname prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # func_strip_suffix prefix name func_stripname () { case ${2} in .*) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; *) func_stripname_result=`$ECHO "X${3}" \ | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; esac } # sed scripts: my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q' my_sed_long_arg='1s/^-[[^=]]*=//' # func_opt_split func_opt_split () { func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` } # func_lo2o object func_lo2o () { func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` } # func_xform libobj-or-source func_xform () { func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'` } # func_arith arithmetic-term... func_arith () { func_arith_result=`expr "$[@]"` } # func_len string # STRING may not start with a hyphen. func_len () { func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len` } _LT_EOF esac case $lt_shell_append in yes) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$[1]+=\$[2]" } _LT_EOF ;; *) cat << \_LT_EOF >> "$cfgfile" # func_append var value # Append VALUE to the end of shell variable VAR. func_append () { eval "$[1]=\$$[1]\$[2]" } _LT_EOF ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option `$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl `shared' nor `disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) ]) ])# _LT_SET_OPTIONS # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [0], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the `shared' and # `disable-shared' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the `static' and # `disable-static' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the `fast-install' # and `disable-fast-install' LT_INIT options. # DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the `pic-only' and `no-pic' # LT_INIT options. # MODE is either `yes' or `no'. If omitted, it defaults to `both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [pic_mode="$withval"], [pic_mode=default]) test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the `pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) # ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59 which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) # ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # Generated from ltversion.in. # serial 3012 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.2.6]) m4_define([LT_PACKAGE_REVISION], [1.3012]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.2.6' macro_revision='1.3012' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # serial 4 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) # Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.10' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.10.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.10.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(AC_AUTOCONF_VERSION)]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to # `$srcdir', `$srcdir/..', or `$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is `.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [dnl Rely on autoconf to set up CDPATH properly. AC_PREREQ([2.50])dnl # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ(2.52)dnl ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 9 # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "GCJ", or "OBJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl ifelse([$1], CC, [depcc="$CC" am_compiler_list=], [$1], CXX, [depcc="$CXX" am_compiler_list=], [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], UPC, [depcc="$UPC" am_compiler_list=], [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named `D' -- because `-MD' means `put the output # in D'. mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with # Solaris 8's {/usr,}/bin/sh. touch sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf case $depmode in nosideeffect) # after this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; none) break ;; esac # We check with `-c' and `-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle `-M -o', and we need to detect this. if depmode=$depmode \ source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE(dependency-tracking, [ --disable-dependency-tracking speeds up one-time build --enable-dependency-tracking do not reject slow dependency extractors]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. #serial 3 # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [for mf in $CONFIG_FILES; do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named `Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running `make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # When using ansi2knr, U may be empty or an underscore; expand it U=`sed -n 's/^U = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each `.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 8 # AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, # 2005, 2006, 2008 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 13 # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.60])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) AM_MISSING_PROG(AUTOCONF, autoconf) AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) AM_MISSING_PROG(AUTOHEADER, autoheader) AM_MISSING_PROG(MAKEINFO, makeinfo) AM_PROG_INSTALL_SH AM_PROG_INSTALL_STRIP AC_REQUIRE([AM_PROG_MKDIR_P])dnl # We need awk for the "check" target. The system "awk" is bad on # some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES(CC)], [define([AC_PROG_CC], defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES(CXX)], [define([AC_PROG_CXX], defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES(OBJC)], [define([AC_PROG_OBJC], defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl ]) ]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} AC_SUBST(install_sh)]) # Copyright (C) 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_PROG_LEX # ----------- # Autoconf leaves LEX=: if lex or flex can't be found. Change that to a # "missing" invocation, for better error output. AC_DEFUN([AM_PROG_LEX], [AC_PREREQ(2.50)dnl AC_REQUIRE([AM_MISSING_HAS_RUN])dnl AC_REQUIRE([AC_PROG_LEX])dnl if test "$LEX" = :; then LEX=${am_missing_run}flex fi]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo done .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # We grep out `Entering directory' and `Leaving directory' # messages which can occur if `w' ends up in MAKEFLAGS. # In particular we don't look at `^make:' because GNU make might # be invoked under some other name (usually "gmake"), in which # case it prints its new name instead of `make'. if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then am__include=include am__quote= _am_result=GNU fi # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then am__include=.include am__quote="\"" _am_result=BSD fi fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_PROG_CC_C_O # -------------- # Like AC_PROG_CC_C_O, but changed for automake. AC_DEFUN([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC_C_O])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC ac_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi dnl Make sure AC_PROG_CC is never called again, or it will override our dnl setting of CC. m4_define([AC_PROG_CC], [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 5 # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it supports --run. # If it does, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" # Use eval to expand $SHELL if eval "$MISSING --run true"; then am_missing_run="$MISSING --run " else am_missing_run= AC_MSG_WARN([`missing' script is too old or missing]) fi ]) # Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_MKDIR_P # --------------- # Check for `mkdir -p'. AC_DEFUN([AM_PROG_MKDIR_P], [AC_PREREQ([2.60])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, dnl while keeping a definition of mkdir_p for backward compatibility. dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of dnl Makefile.ins that do not define MKDIR_P, so we do our own dnl adjustment using top_builddir (which is defined more often than dnl MKDIR_P). AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl case $mkdir_p in [[\\/$]]* | ?:[[\\/]]*) ;; */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; esac ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 3 # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # ------------------------------ # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) # _AM_SET_OPTIONS(OPTIONS) # ---------------------------------- # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 # Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 4 # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Just in case sleep 1 echo timestamp > conftest.file # Do `set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t $srcdir/configure conftest.file` fi rm -f conftest.file if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT(yes)]) # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor `install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in `make install-strip', and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using `strip' when the user # run `make install-strip'. However `strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the `STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be `maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004, 2005 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # serial 2 # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of `v7', `ustar', or `pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. AM_MISSING_PROG([AMTAR], [tar]) m4_if([$1], [v7], [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], [m4_case([$1], [ustar],, [pax],, [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' _am_tools=${am_cv_prog_tar_$1-$_am_tools} # Do not fold the above two line into one, because Tru64 sh and # Solaris sh will not grok spaces in the rhs of `-'. for _am_tool in $_am_tools do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([acinclude.m4]) cfengine-2.2.10/Makefile.am0000644000175000001440000000146711033624675012342 00000000000000if BUILD_DOC DOC_DIR = doc else DOC_DIR = endif SUBDIRS = pub src contrib inputs $(DOC_DIR) EXTRA_DIST = acconfig.h doc/cfengine.8 COPYING ChangeLog INSTALL NEWS README LICENSE docdir = $(pkgdatadir) doc_DATA = README ChangeLog INSTALL NEWS # # Some basic clean ups # MOSTLYCLEANFILES = *~ # # Get everything removed down to where rebuilding requires: # "make; make install" # CLEANFILES = # # Get everything removed down to where rebuilding requires: # "configure; make; make install" # DISTCLEANFILES = # # Get everything removed down to where rebuilding requires: # "aclocal; autoconf; autoheader; automake --add-missing" # "configure; make; make install" # MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.sub \ configure install-sh missing mkinstalldirs depcomp ylwrap \ ltmain.sh mdate-sh cfengine-2.2.10/depcomp0000744000175000001440000003554510202124332011643 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2004-05-31.23 # Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. # 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, 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. # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try \`$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by `PROGRAMS ARGS'. object Object file output by `PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputing dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit 0 ;; -v | --v*) echo "depcomp $scriptversion" exit 0 ;; esac if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ## The second -e expression handles DOS-style file names with drive letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the `deleted header file' problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. tr ' ' ' ' < "$tmpdepfile" | ## Some versions of gcc put a space before the `:'. On the theory ## that the space means something, we add a space to the output as ## well. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like `#:fec' to the end of the # dependency line. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ tr ' ' ' ' >> $depfile echo >> $depfile # The second pass generates a dummy entry for each header file. tr ' ' ' ' < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> $depfile else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts `$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` tmpdepfile="$stripped.u" if test "$libtool" = yes; then "$@" -Wc,-M else "$@" -M fi stat=$? if test -f "$tmpdepfile"; then : else stripped=`echo "$stripped" | sed 's,^.*/,,'` tmpdepfile="$stripped.u" fi if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi if test -f "$tmpdepfile"; then outname="$stripped.o" # Each line is of the form `foo.o: dependent.h'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" else # The sourcefile does not contain any dependencies, so just # store a dummy comment line, to avoid errors with the Makefile # "include basename.Plo" scheme. echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; icc) # Intel's C compiler understands `-MD -MF file'. However on # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c # ICC 7.0 will fill foo.d with something like # foo.o: sub/foo.c # foo.o: sub/foo.h # which is wrong. We want: # sub/foo.o: sub/foo.c # sub/foo.o: sub/foo.h # sub/foo.c: # sub/foo.h: # ICC 7.1 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using \ : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in `foo.d' instead, so we check for that too. # Subdirectories are respected. dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` test "x$dir" = "x$object" && dir= base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` if test "$libtool" = yes; then # Dependencies are output in .lo.d with libtool 1.4. # With libtool 1.5 they are output both in $dir.libs/$base.o.d # and in $dir.libs/$base.o.d and $dir$base.o.d. We process the # latter, because the former will be cleaned when $dir.libs is # erased. tmpdepfile1="$dir.libs/$base.lo.d" tmpdepfile2="$dir$base.o.d" tmpdepfile3="$dir.libs/$base.d" "$@" -Wc,-MD else tmpdepfile1="$dir$base.o.d" tmpdepfile2="$dir$base.d" tmpdepfile3="$dir$base.d" "$@" -MD fi stat=$? if test $stat -eq 0; then : else rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi if test -f "$tmpdepfile1"; then tmpdepfile="$tmpdepfile1" elif test -f "$tmpdepfile2"; then tmpdepfile="$tmpdepfile2" else tmpdepfile="$tmpdepfile3" fi if test -f "$tmpdepfile"; then sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" # That's a tab and a space in the []. sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" else echo "#dummy" > "$depfile" fi rm -f "$tmpdepfile" ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for `:' # in the target name. This is to cope with DOS-style filenames: # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. "$@" $dashmflag | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" tr ' ' ' ' < "$tmpdepfile" | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # X makedepend shift cleared=no for arg in "$@"; do case $cleared in no) set ""; shift cleared=yes ;; esac case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix="`echo $object | sed 's/^.*\././'`" touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" sed '1,2d' "$tmpdepfile" | tr ' ' ' ' | \ ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test $1 != '--mode=compile'; do shift done shift fi # Remove `-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E | sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o, # because we must use -o when running libtool. "$@" || exit $? IFS=" " for arg do case "$arg" in "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" echo " " >> "$depfile" . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-end: "$" # End: cfengine-2.2.10/mkinstalldirs0000744000175000001440000000132210202123436013062 00000000000000#! /bin/sh # mkinstalldirs --- make directory hierarchy # Author: Noah Friedman # Created: 1993-05-16 # Public domain # $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ errstatus=0 for file do set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` shift pathcomp= for d do pathcomp="$pathcomp$d" case "$pathcomp" in -* ) pathcomp=./$pathcomp ;; esac if test ! -d "$pathcomp"; then echo "mkdir $pathcomp" mkdir "$pathcomp" || lasterr=$? if test ! -d "$pathcomp"; then errstatus=$lasterr fi fi pathcomp="$pathcomp/" done done exit $errstatus # mkinstalldirs ends here