isync-1.3.0/0000755000175000001440000000000013164163467007650 500000000000000isync-1.3.0/compile0000755000175000001440000001624513164125572011151 00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2014 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, see . # 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 # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= 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'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= 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 $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= 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 's|^.*[\\/]||; s|^[a-zA-Z]:||; 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 test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || 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-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: isync-1.3.0/configure0000755000175000001440000057266513164125571011516 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for isync 1.3.0. # # # Copyright (C) 1992-1996, 1998-2012 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 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 # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (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 # 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. as_myself= 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 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="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_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { 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_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error 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 if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi 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'` # 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_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # 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; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # 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 } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac 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 -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' 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='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # 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'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/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= # Identity of this package. PACKAGE_NAME='isync' PACKAGE_TARNAME='isync' PACKAGE_VERSION='1.3.0' PACKAGE_STRING='isync 1.3.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' # 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_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS with_mdconvert_FALSE with_mdconvert_TRUE with_compat_FALSE with_compat_TRUE Z_LIBS DB_LIBS SASL_LIBS SSL_LIBS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG SOCK_LIBS EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V 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_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_maintainer_mode enable_dependency_tracking with_ssl with_sasl with_zlib enable_compat ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR' # 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' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' 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= ;; *) 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_fn_error $? "invalid feature name: $ac_useropt" 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_fn_error $? "invalid feature name: $ac_useropt" 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 ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -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_fn_error $? "invalid package name: $ac_useropt" 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_fn_error $? "invalid package name: $ac_useropt" 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_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac 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_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $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 runstatedir 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_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" 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 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_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # 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_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" 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 isync 1.3.0 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] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --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/isync] --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 _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of isync 1.3.0:";; esac 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] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --disable-maintainer-mode disable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --disable-compat don't include isync compatibility wrapper [no] Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-ssl=PATH where to look for SSL [detect] --with-sasl=PATH where to look for SASL [detect] --with-zlib use zlib [detect] 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 (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _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 isync configure 1.3.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 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 ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 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:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 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:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { 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:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 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 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 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:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack 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:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* 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 $2 (); /* 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_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func 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 isync $as_me 1.3.0, which was generated by GNU Autoconf 2.69. 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) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append 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 as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset 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 $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" 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:${as_lineno-$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= ;; #( *) { eval $ac_var=; 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 $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" 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 $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" 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 $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" 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'; as_fn_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 $as_echo "/* confdefs.h */" > 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 cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _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 # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac 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 /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$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" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } 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. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$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:${as_lineno-$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:${as_lineno-$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:${as_lineno-$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:${as_lineno-$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:${as_lineno-$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:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$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. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$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_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## 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_config_headers="$ac_config_headers autodefs.h" am__api_version='1.15' 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_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 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. # 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:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; 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 as_fn_executable_p "$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:${as_lineno-$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:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # 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 ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file 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 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_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file 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` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # 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:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$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:${as_lineno-$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" { $as_echo "$as_me:${as_lineno-$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 ${ac_cv_path_mkdir+:} false; 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 as_fn_executable_p "$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 test -d ./--version && rmdir ./--version 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. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } 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:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$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 eval \${ac_cv_prog_make_${ac_make}_set+:} false; 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:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$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 # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' 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_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 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='isync' VERSION='1.3.0' 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"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$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 # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$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='\' am__nodep='_no' 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:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$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:${as_lineno-$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:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$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:${as_lineno-$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:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$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:${as_lineno-$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:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&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:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; 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 if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$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:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; 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:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { 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:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; 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:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$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 ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else 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:${as_lineno-$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:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes 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:${as_lineno-$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:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* 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" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg 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:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : 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_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:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_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 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:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; 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". rm -rf conftest.dir 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 am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac 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 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # 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. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; 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 ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj 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 $am__obj 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:${as_lineno-$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 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 $as_echo_n "checking for $CC option to accept ISO C99... " >&6; } if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include // Check varargs macros. These examples are taken from C99 6.10.3.5. #define debug(...) fprintf (stderr, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK your preprocessor is broken; #endif #if BIG_OK #else your preprocessor is broken; #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\0'; ++i) continue; return 0; } // Check varargs and va_copy. static void test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str; int number; float fnumber; while (*format) { switch (*format++) { case 's': // string str = va_arg (args_copy, const char *); break; case 'd': // int number = va_arg (args_copy, int); break; case 'f': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); } int main () { // Check bool. _Bool success = false; // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. test_varargs ("s, d' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' || dynamic_array[ni.number - 1] != 543); ; return 0; } _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c99" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c99" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 $as_echo "$ac_cv_prog_cc_c99" >&6; } ;; esac if test "x$ac_cv_prog_cc_c99" != xno; then : fi if test "$GCC" = yes; then CFLAGS="$CFLAGS -pipe -W -Wall -Wshadow -Wstrict-prototypes -std=c99 -pedantic -Wno-overlength-strings" fi CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strftime supports %z" >&5 $as_echo_n "checking whether strftime supports %z... " >&6; } if ${ob_cv_strftime_z+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ob_cv_strftime_z="yes (assumed)" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main(void) { time_t t = 0; char buf[32]; strftime(buf, sizeof(buf), "%z", localtime(&t)); return !(buf[0] == '+' || buf[0] == '-'); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ob_cv_strftime_z=yes else ob_cv_strftime_z=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ob_cv_strftime_z" >&5 $as_echo "$ob_cv_strftime_z" >&6; } if test "x$ob_cv_strftime_z" = x"no"; then as_fn_error $? "libc lacks necessary feature" "$LINENO" 5 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:${as_lineno-$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 ${ac_cv_prog_CPP+:} false; 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i 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:${as_lineno-$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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } 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:${as_lineno-$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 ${ac_cv_path_GREP+:} false; 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" as_fn_executable_p "$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 as_fn_arith $ac_count + 1 && ac_count=$as_val 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_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; 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" as_fn_executable_p "$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 as_fn_arith $ac_count + 1 && ac_count=$as_val 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_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h 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` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = 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/poll.h sys/select.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in vasprintf strnlen memrchr timegm do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 $as_echo_n "checking for socket in -lsocket... " >&6; } if ${ac_cv_lib_socket_socket+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_socket=yes else ac_cv_lib_socket_socket=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 $as_echo "$ac_cv_lib_socket_socket" >&6; } if test "x$ac_cv_lib_socket_socket" = xyes; then : SOCK_LIBS="-lsocket" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnsl" >&5 $as_echo_n "checking for inet_ntoa in -lnsl... " >&6; } if ${ac_cv_lib_nsl_inet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 inet_ntoa (); int main () { return inet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nsl_inet_ntoa=yes else ac_cv_lib_nsl_inet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_inet_ntoa" >&5 $as_echo "$ac_cv_lib_nsl_inet_ntoa" >&6; } if test "x$ac_cv_lib_nsl_inet_ntoa" = xyes; then : SOCK_LIBS="$SOCK_LIBS -lnsl" fi have_ipv6=true sav_LIBS=$LIBS LIBS="$LIBS $SOCK_LIBS" for ac_func in getaddrinfo inet_ntop do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else have_ipv6=false fi done LIBS=$sav_LIBS if $have_ipv6; then $as_echo "#define HAVE_IPV6 1" >>confdefs.h fi have_ssl_paths= # Check whether --with-ssl was given. if test "${with_ssl+set}" = set; then : withval=$with_ssl; ob_cv_with_ssl=$withval fi if test "x$ob_cv_with_ssl" != xno; then case $ob_cv_with_ssl in ""|yes) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$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 PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi if test "x$PKG_CONFIG" != "x" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking OpenSSL presence with pkg-config" >&5 $as_echo_n "checking OpenSSL presence with pkg-config... " >&6; } if $PKG_CONFIG --exists openssl; then SSL_LIBS=`$PKG_CONFIG --libs-only-l openssl` SSL_LDFLAGS=`$PKG_CONFIG --libs-only-L openssl` SSL_CPPFLAGS=`$PKG_CONFIG --cflags-only-I openssl` have_ssl_paths=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5 $as_echo "found" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } fi fi ;; *) SSL_LDFLAGS=-L$ob_cv_with_ssl/lib$libsuff SSL_CPPFLAGS=-I$ob_cv_with_ssl/include ;; esac if test -z "$have_ssl_paths"; then sav_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $SSL_LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : LIBDL=-ldl fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CRYPTO_lock in -lcrypto" >&5 $as_echo_n "checking for CRYPTO_lock in -lcrypto... " >&6; } if ${ac_cv_lib_crypto_CRYPTO_lock+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcrypto $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 CRYPTO_lock (); int main () { return CRYPTO_lock (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_crypto_CRYPTO_lock=yes else ac_cv_lib_crypto_CRYPTO_lock=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_CRYPTO_lock" >&5 $as_echo "$ac_cv_lib_crypto_CRYPTO_lock" >&6; } if test "x$ac_cv_lib_crypto_CRYPTO_lock" = xyes; then : LIBCRYPTO=-lcrypto fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_connect in -lssl" >&5 $as_echo_n "checking for SSL_connect in -lssl... " >&6; } if ${ac_cv_lib_ssl_SSL_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lssl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 SSL_connect (); int main () { return SSL_connect (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ssl_SSL_connect=yes else ac_cv_lib_ssl_SSL_connect=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_SSL_connect" >&5 $as_echo "$ac_cv_lib_ssl_SSL_connect" >&6; } if test "x$ac_cv_lib_ssl_SSL_connect" = xyes; then : SSL_LIBS="-lssl $LIBCRYPTO $LIBDL" have_ssl_paths=yes fi LDFLAGS=$sav_LDFLAGS fi sav_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $SSL_CPPFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default" if test "x$ac_cv_header_openssl_ssl_h" = xyes; then : else have_ssl_paths= fi CPPFLAGS=$sav_CPPFLAGS if test -z "$have_ssl_paths"; then if test -n "$ob_cv_with_ssl"; then as_fn_error $? "OpenSSL libs and/or includes were not found where specified" "$LINENO" 5 fi else $as_echo "#define HAVE_LIBSSL 1" >>confdefs.h CPPFLAGS="$CPPFLAGS $SSL_CPPFLAGS" LDFLAGS="$LDFLAGS $SSL_LDFLAGS" fi fi have_sasl_paths= # Check whether --with-sasl was given. if test "${with_sasl+set}" = set; then : withval=$with_sasl; ob_cv_with_sasl=$withval fi if test "x$ob_cv_with_sasl" != xno; then case $ob_cv_with_sasl in ""|yes) ;; *) SASL_LDFLAGS=-L$ob_cv_with_sasl/lib$libsuff SASL_CPPFLAGS=-I$ob_cv_with_sasl/include ;; esac if test -z "$have_sasl_paths"; then sav_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $SASL_LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sasl_client_init in -lsasl2" >&5 $as_echo_n "checking for sasl_client_init in -lsasl2... " >&6; } if ${ac_cv_lib_sasl2_sasl_client_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsasl2 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 sasl_client_init (); int main () { return sasl_client_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_sasl2_sasl_client_init=yes else ac_cv_lib_sasl2_sasl_client_init=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_sasl2_sasl_client_init" >&5 $as_echo "$ac_cv_lib_sasl2_sasl_client_init" >&6; } if test "x$ac_cv_lib_sasl2_sasl_client_init" = xyes; then : SASL_LIBS="-lsasl2" have_sasl_paths=yes fi LDFLAGS=$sav_LDFLAGS fi sav_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $SASL_CPPFLAGS" ac_fn_c_check_header_mongrel "$LINENO" "sasl/sasl.h" "ac_cv_header_sasl_sasl_h" "$ac_includes_default" if test "x$ac_cv_header_sasl_sasl_h" = xyes; then : else have_sasl_paths= fi CPPFLAGS=$sav_CPPFLAGS if test -z "$have_sasl_paths"; then if test -n "$ob_cv_with_sasl"; then as_fn_error $? "SASL libs and/or includes were not found where specified" "$LINENO" 5 fi else $as_echo "#define HAVE_LIBSASL 1" >>confdefs.h CPPFLAGS="$CPPFLAGS $SASL_CPPFLAGS" LDFLAGS="$LDFLAGS $SASL_LDFLAGS" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Berkeley DB >= 4.1" >&5 $as_echo_n "checking for Berkeley DB >= 4.1... " >&6; } if ${ac_cv_berkdb4+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_berkdb4=no sav_LIBS=$LIBS LIBS="$LIBS -ldb" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { DB *db; db_create(&db, 0, 0); db->truncate(db, 0, 0, 0); db->open(db, 0, "foo", "foo", DB_HASH, DB_CREATE, 0) ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_berkdb4=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$sav_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_berkdb4" >&5 $as_echo "$ac_cv_berkdb4" >&6; } if test "x$ac_cv_berkdb4" = xyes; then DB_LIBS="-ldb" $as_echo "#define USE_DB 1" >>confdefs.h fi have_zlib= # Check whether --with-zlib was given. if test "${with_zlib+set}" = set; then : withval=$with_zlib; ob_cv_with_zlib=$withval fi if test "x$ob_cv_with_zlib" != xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for deflate in -lz" >&5 $as_echo_n "checking for deflate in -lz... " >&6; } if ${ac_cv_lib_z_deflate+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* 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 deflate (); int main () { return deflate (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_z_deflate=yes else ac_cv_lib_z_deflate=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_deflate" >&5 $as_echo "$ac_cv_lib_z_deflate" >&6; } if test "x$ac_cv_lib_z_deflate" = xyes; then : ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" if test "x$ac_cv_header_zlib_h" = xyes; then : have_zlib=1 Z_LIBS="-lz" $as_echo "#define HAVE_LIBZ 1" >>confdefs.h fi fi fi # Check whether --enable-compat was given. if test "${enable_compat+set}" = set; then : enableval=$enable_compat; ob_cv_enable_compat=$enableval fi if test "x$ob_cv_enable_compat" != xno; then for ac_func in getopt_long do : ac_fn_c_check_func "$LINENO" "getopt_long" "ac_cv_func_getopt_long" if test "x$ac_cv_func_getopt_long" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETOPT_LONG 1 _ACEOF fi done fi if test "x$ob_cv_enable_compat" != xno -a "x$ac_cv_berkdb4" = xyes; then with_compat_TRUE= with_compat_FALSE='#' else with_compat_TRUE='#' with_compat_FALSE= fi if test "x$ac_cv_berkdb4" = xyes; then with_mdconvert_TRUE= with_mdconvert_FALSE='#' else with_mdconvert_TRUE='#' with_mdconvert_FALSE= fi ac_config_files="$ac_config_files Makefile src/Makefile src/compat/Makefile isync.spec" 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:${as_lineno-$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= ;; #( *) { eval $ac_var=; 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 if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$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= U= 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. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${with_compat_TRUE}" && test -z "${with_compat_FALSE}"; then as_fn_error $? "conditional \"with_compat\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${with_mdconvert_TRUE}" && test -z "${with_mdconvert_FALSE}"; then as_fn_error $? "conditional \"with_mdconvert\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 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:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_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} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_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 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 # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (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 # 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. as_myself= 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 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith 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 if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi 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'` # 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 ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac 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 -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { 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_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # 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 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=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 isync $as_me 1.3.0, which was generated by GNU Autoconf 2.69. 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 and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, 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 the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ isync config.status 1.3.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 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=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= 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 ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; 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"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append 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 as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --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_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append 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" _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 "autodefs.h") CONFIG_HEADERS="$CONFIG_HEADERS autodefs.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; "src/compat/Makefile") CONFIG_FILES="$CONFIG_FILES src/compat/Makefile" ;; "isync.spec") CONFIG_FILES="$CONFIG_FILES isync.spec" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; 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= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # 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=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi 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 {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 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_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 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_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 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 >>"\$ac_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 >>"\$ac_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 < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries 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[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// 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 >"$ac_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_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 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_fn_error $? "could not setup config headers machinery" "$LINENO" 5 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_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[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="$ac_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_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append 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:${as_lineno-$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 >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; 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"; as_fn_mkdir_p 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:${as_lineno-$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 "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$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 "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 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:${as_lineno-$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"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf 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"` # 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'`; 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; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # 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 || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } if test -n "$have_ssl_paths"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using SSL" >&5 $as_echo "Using SSL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: Not using SSL" >&5 $as_echo "Not using SSL" >&6; } fi if test -n "$have_sasl_paths"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using SASL" >&5 $as_echo "Using SASL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: Not using SASL" >&5 $as_echo "Not using SASL" >&6; } fi if test -n "$have_zlib"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using zlib" >&5 $as_echo "Using zlib" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: Not using zlib" >&5 $as_echo "Not using zlib" >&6; } fi if test "x$ac_cv_berkdb4" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using Berkeley DB" >&5 $as_echo "Using Berkeley DB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: Not using Berkeley DB" >&5 $as_echo "Not using Berkeley DB" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } isync-1.3.0/Makefile.am0000644000175000001440000000511013164163214011607 00000000000000SUBDIRS = src bin_SCRIPTS = mbsync-get-cert EXTRA_DIST = debian isync.spec $(bin_SCRIPTS) LOG_PL = \ use POSIX qw(strftime); \ use Date::Parse; \ use Text::Wrap; \ $$Text::Wrap::columns = 72; \ while (defined($$_ = <>)) { \ /^commit / or die "commit missing: $$_"; \ <> =~ /^log size (\d+)$$/ or die "wrong size"; \ $$len = $$1; \ read(STDIN, $$log, $$len) == $$len or die "unexpected EOF"; \ $$log =~ s/^Author: ([^>]+>)\nDate: (\d{4}-\d\d-\d\d \d\d:\d\d:\d\d [-+]\d{4})\n(.*)$$/$$3/s or die "unexpected log format"; \ $$author = $$1; $$date = str2time($$2); \ scalar(<>); \ @files = (); \ $$pfx = ""; \ while (defined($$l = <>) and $$l ne "\n") { \ chomp $$l; \ next if ($$l =~ m,^(ChangeLog$$|NEWS$$|TODO$$|debian/),); \ if (!@files) { \ $$pfx = $$l; \ $$pfx =~ s,/?[^/]+$$,,; \ } else { \ while (length($$pfx)) { \ $$l =~ m,^\Q$$pfx/\E, and last; \ $$pfx =~ s,/?[^/]+$$,,; \ } \ } \ push @files, $$l; \ } \ next if (!@files); \ print strftime("%F %H:%M", gmtime($$date))." ".$$author."\n\n"; \ if (@files > 1 and ($$len = length($$pfx))) { \ @efiles = (); \ for $$f (@files) { push @efiles, substr($$f, $$len + 1); } \ $$fstr = $$pfx."/: "; \ } else { \ @efiles = @files; \ $$fstr = ""; \ } \ print wrap("\t* ", "\t ", $$fstr.join(", ", @efiles).":")."\n"; \ $$log =~ s, +$$,,gm; \ $$log =~ s,^ ,\t,gm; \ print $$log."\n"; \ } $(srcdir)/ChangeLog: log log: @test -z "$(srcdir)" || cd $(srcdir) && \ ( ! test -d .git || \ git log --pretty=medium --date=iso --log-size --name-only --no-merges | \ perl -e '$(LOG_PL)' > ChangeLog ) cov-scan: clean /opt/cov-analysis-*/bin/cov-build --dir cov-int $(MAKE) tar cavf isync.tar.xz cov-int deb: CFLAGS= INSTALL= dpkg-buildpackage -b --no-sign dist-hook: find $(distdir)/debian \( -name .#\*# -o -type l \) -print0 | xargs -0r rm -rf -cd $(distdir)/debian && test -f .gitignore && rm -rf `cut -c2- .gitignore` .gitignore dist-sign: dist gpg -b -a $(PACKAGE)-$(VERSION).tar.gz rpm: dist CFLAGS="-O2 -mtune=core2" rpmbuild --clean -ta $(PACKAGE)-$(VERSION).tar.gz rpm-ia32: dist CFLAGS="-O2 -m32 -march=i686" rpmbuild --target i686-unknown-linux --clean -ta $(PACKAGE)-$(VERSION).tar.gz doc_DATA = README TODO NEWS ChangeLog AUTHORS isync-1.3.0/debian/0000755000175000001440000000000013164163470011064 500000000000000isync-1.3.0/debian/source/0000755000175000001440000000000013164125071012357 500000000000000isync-1.3.0/debian/source/format0000644000175000001440000000001413164125071013505 000000000000003.0 (quilt) isync-1.3.0/debian/rules0000755000175000001440000000023013164125323012052 00000000000000#!/usr/bin/make -f %: dh $@ --with=autoreconf override_dh_auto_install: dh_auto_install $(RM) $(CURDIR)/debian/isync/usr/share/doc/isync/ChangeLog isync-1.3.0/debian/changelog0000644000175000001440000003112613164125071012654 00000000000000isync (1.2.3-0) unstable; urgency=low * Upload to unstable (with urgency=low) -- Oswald Buddenhagen Sun, 01 Oct 2017 12:12:12 +0000 isync (1.2.1-2) unstable; urgency=low * Upload to unstable (with urgency=low) * Don't call uupdate after uscan * Import patch to fix build with OpenSSL 1.1 (Closes: #828357) * Bump Standards-Version to 3.9.8 (no changes needed) * Add pkg-config to Build-Depends * Update Vcs-* URLs * Fix spelling-error-in-binary -- Alessandro Ghedini Sat, 19 Nov 2016 17:14:42 +0000 isync (1.2.1-1) experimental; urgency=medium [ Evgeni Golov ] * New upstream release. * Explicitly Build-Depend on zlib1g-dev -- Alessandro Ghedini Sat, 09 Jan 2016 12:56:39 +0000 isync (1.2.0-1) experimental; urgency=medium * New upstream release - Only show sync progress by default (Closes: #765052) * Enable libsasl support -- Alessandro Ghedini Mon, 06 Apr 2015 13:42:24 +0200 isync (1.1.2-1) unstable; urgency=medium * New upstream release * Bump Standards-Version to 3.9.6 (no changes needed) -- Alessandro Ghedini Sun, 01 Feb 2015 20:42:25 +0100 isync (1.1.1-1) unstable; urgency=medium * New upstream release - Don't lie about the default of User (Closes: #744389) - Don't forget to reset message counts when skipping scan (Closes: #744259) - Rework maildir store mapping (Closes: #737708) * Drop 01_fix-manpages.patch (merged upstream) * Drop 02_fix-empty-folder-sync.patch (merged upstream) -- Alessandro Ghedini Tue, 03 Jun 2014 21:00:44 +0200 isync (1.1.0-2) unstable; urgency=medium * Drop 02_fix-duplicate-changelog.patch (rm the file after installation instead) * Update 01_fix-manpages.patch * Add 02_fix-empty-folder-sync.patch (Closes: #738873) -- Alessandro Ghedini Fri, 14 Feb 2014 20:41:49 +0100 isync (1.1.0-1) unstable; urgency=low * New upstream release (Closes: #674403) - Fix overlapping memcpy (Closes: #650373) - Fix segfault while syncing mailboxes (Closes: #411120) - Fix segfault when invoked with arguments without configuration (Closes: #727239) * Bump debhelper compat level, update Build-Depends * Switch to short-form dh rules, remove useless files * Switch to 3.0 (quilt) source format * Remove empty patches/ directory * Drop local source modifications * Update short/long descriptions * Add 01_fix-manpages.patch to fix manpage errors and typos * Add Homepage field * Update copyright file to Copyright-Format 1.0 * Add Vcs-* fields * Add 02_fix-duplicate-changelog.patch to avoid duplicate changelog install * Add myself to Uploaders * Bump Standards-Version to 3.9.5 (no changes needed) * Use dh-autoreconf instead of autotools-dev -- Alessandro Ghedini Sun, 12 Jan 2014 16:35:52 +0100 isync (1.0.4-2.2) unstable; urgency=low * Non-maintainer upload. * Apply upstream patch for CVE-2013-0289. Fix incorrect server's SSL x509.v3 certificate validation when performing IMAP synchronization. (Closes: #701052) -- Salvatore Bonaccorso Sun, 24 Feb 2013 09:27:55 +0100 isync (1.0.4-2.1) unstable; urgency=low * Non-maintainer upload. * Drop debconf note that deals with a pre-Etch transition. Closes: #492194 -- Christian Perrier Sat, 25 Oct 2008 08:40:52 +0200 isync (1.0.4-2) unstable; urgency=low * Change the libdb4.4-dev build-dependency to libdb-dev. Thanks Luk for pointing this. (Closes: #499165) -- Nicolas Boullis Wed, 17 Sep 2008 23:58:58 +0200 isync (1.0.4-1) unstable; urgency=low * The second "thanks Christian" release. * New upstream release. - Accept empty "* SEARCH" response. (Closes: #413336) - Quote user name in generated config. (Closes: #456783) * Explain the isync->mbsync change in the package description. (Closes: #430648) * Fix the debian/watch file that lacked the version and action fields. * Disable the upstream "deb-clean" stuff in the top-level Makefile, as in breaks cleaning the build directory. * Bump Standards-Version to 3.7.3. (No change required.) -- Nicolas Boullis Sat, 03 May 2008 01:42:55 +0200 isync (1.0.3-3.1) unstable; urgency=low * Non-maintainer upload to fix pending l10n issues. * Debconf translations: - Portuguese. Closes: #418283 - Italian. Closes: #418246 - Dutch. Closes: #422244 - Spanish. Closes: #426184 - Finnish. Closes: #468214 - Galician. Closes: #470529 * [Lintian] Do not include debian revision in the build dependency for libssl-dev * [Lintian] No longer ignore errors from "make distclean" -- Christian Perrier Wed, 12 Mar 2008 07:24:01 +0100 isync (1.0.3-3) unstable; urgency=low * The "thanks Christian" release. * Update German debconf templates translation. Thanks to Erik Schanze (for the translation) and Christian Perrier (for forwarding the translation). (Closes: #407615) -- Nicolas Boullis Mon, 5 Feb 2007 00:17:15 +0100 isync (1.0.3-2.1) unstable; urgency=low * Non-maintainer upload with maintainer's permission * Debconf templates translations: - French updated by me - Brazilian Portuguese translation added - Czech translation added. Closes: #403473 - Russian translation added. Closes: #403510 - Vietnamese translation added - Norwegian BokmÃ¥l translation added. Closes: #403523 -- Christian Perrier Sun, 17 Dec 2006 15:31:04 +0100 isync (1.0.3-2) unstable; urgency=low * Back to unstable, with permission from Steve Langasek. (Message-ID: <20061121015225.GF28035@borges.dodds.net>) * Rewrite the debconf note, thanks to the debian-l10n-english team (and especially MJ Ray). * Also add some information about the new version into NEWS.Debian. * Remove the information about the need to set the T (trashed) flag from README.Debian. * Also install the isyncrc.sample sample configuration file. * Bump Standards-Version to 3.7.2. (No change required.) -- Nicolas Boullis Tue, 5 Dec 2006 00:34:54 +0100 isync (1.0.3-1) experimental; urgency=low * New upstream release. (Closes: #315423) - Isync now supports breaking and linking threads. (Closes: #177280) - It also supports unflagging messages. (Closes: #111286) - IMAP commands are sent asynchronously. (Closes: #226222) * Kill the old debconf question about upgrades from pre-0.8 versions. * Use the (now obsolete) swedish and portugese translations anyway. (Closes: #337771, #378891) * New debconf note that warns about upgrades from pre-1.0 versions. * Add a build dependency on po-debconf. -- Nicolas Boullis Sun, 19 Nov 2006 15:04:31 +0100 isync (0.9.2-4) unstable; urgency=low * Add Czech debconf translation, thanks to Martin Šín. (Closes: #317571) * Build with the newest libssl-dev. * Load the debconf library in postinst to ensure that everything works as expected, thanks to lintian for noticing the problem and to Josselin Mouette for pointing to the right doc. * Fix a bashism in the config script, thanks to lintian. * Update the postal address of the FSF in the copyright file. * Bump Standards-Version to 3.6.2. (No change required.) -- Nicolas Boullis Mon, 10 Oct 2005 01:37:50 +0200 isync (0.9.2-3) unstable; urgency=low * Bump build-dependency from libdb4.0-dev to libdb4.2-dev, thanks to Andreas Jochens. (Closes: #280268) -- Nicolas Boullis Tue, 9 Nov 2004 18:21:12 +0100 isync (0.9.2-2) unstable; urgency=low * Add german debconf templates translation, thanks to Erik Schanze. (Closes: #267675) -- Nicolas Boullis Tue, 24 Aug 2004 00:32:32 +0200 isync (0.9.2-1) unstable; urgency=low * New upstream release. - Password prompt now includes the mailbox/server. (Closes: #92893) * Backported from CVS: - A few prinf converted to info (disabled with -q). - A few other printf converted to warn (disabled with -q -q) to be able to disable the warning when SSL is not available. (Closes: #228086) - Update the manpage accordingly (about -q). - Improve the manpage (about using isync with mutt). * Add Theodore Y. Ts'o as a co-maintainter. -- Nicolas Boullis Tue, 13 Apr 2004 02:12:42 +0200 isync (0.9.1-4) unstable; urgency=low * The "Why do I keep adding such stupid bugs?" release. * Remove the extra parenthesis that caused UID FETCH syntax errors, thanks to Niels den Otter for pointing the bug and giving the solution. (Closes: #224803) * Use configure's --build and --host options to prevent wrong optimizations (such as building for sparc64 rather than for sparc). -- Nicolas Boullis Wed, 7 Jan 2004 01:06:53 +0100 isync (0.9.1-3) unstable; urgency=low * Do not segfault when using both tunneled end non-tunneled connections, thanks to Nik A. Melchior for reporting and for his patch. (Closes: #220667) * Save uid of messages when interrupted, thanks to Theodore Y. Ts'o for reporting and for his patch. (Closes: #220346) * Do not get the sizes of the messages if unneeded (if MaxSize=0). -- Nicolas Boullis Thu, 18 Dec 2003 00:55:04 +0100 isync (0.9.1-2) unstable; urgency=low * Add french debconf templates translation, thanks to Christian Perrier. (Closes: #218118) -- Nicolas Boullis Mon, 3 Nov 2003 18:50:56 +0100 isync (0.9.1-1) unstable; urgency=low * New maintainer. (Closes: #180050) * New upstream release. - With the new option -R, isync is now able to create non-existent remote mailboxes. (Closes: #170388) * Update debian/copyright to match the current copyright: - Add Oswald Buddenhagen as copyright owner. - Add special exception for OpenSSL. * Add support for noopt in $DEB_BUILD_OPTIONS in debian/rules. * Switch to po-debconf. * Remove sample.isyncrc from debian/docs: no need to have it both as a doc and as an example. * Move package from section non-US/main (?) to mail. (Closes: #154216) * Update versionned build-dependency on debhelper to >= 4.1.16. * Bump Standards-Version to 3.6.1. (No change required.) -- Nicolas Boullis Tue, 14 Oct 2003 22:02:20 +0200 isync (0.8-4) unstable; urgency=low * Orphaned the package, as I no longer use it. -- Joey Hess Thu, 6 Feb 2003 15:46:38 -0500 isync (0.8-3) unstable; urgency=low * New upstream maintainer; updated copyright file web site address, and watch file. NB: new upstream has not made any new releases yet. -- Joey Hess Sat, 1 Feb 2003 16:03:49 -0500 isync (0.8-2) unstable; urgency=low * Only reset debconf question if user chooses to abort upgrade. Closes: #167363 * Don't open lock files O_EXCL. As seen in upstream cvs. * Description and build-deps updates. * Added README.Debian with notes on mutt integration. -- Joey Hess Fri, 1 Nov 2002 18:02:44 -0500 isync (0.8-1) unstable; urgency=low * New upstream release. Closes: #134080 **WARNING** You need to remove all the messages in your local folder if you were previously using another version of isync or else you will end up with duplicate messages on your IMAP server. * Has better support for uploading locally added messages. Closes: #120272 * Added a debconf queston with some info about this that lets you abort the upgrade. * Added NEWS.Debian with same info. * New maintainer. * Removed upstream debianization stuff. * Updated copyright file. * Updated to current policy throughout. * Added uscan watch file. * Updated build-deps. * Now that isync needs berkeley databases, go with db4, so I don't have to transition from db3 later. * Fix fd leak (forgot to close tmp dir in maildir). Closes: #150762 -- Joey Hess Tue, 29 Oct 2002 17:02:14 -0500 isync (0.7-1) unstable; urgency=low * New upstream version (Closes: #121312, #92051). * Rumors say this might fix bugs #102255 and #120272, but I have no test setup right now, so I'm leaving them open. * Updated standards-version. -- Tommi Virtanen Sat, 5 Jan 2002 16:13:35 +0200 isync (0.5-1) unstable; urgency=low * New upstream version (Closes: #98642). * Install sample.isyncrc too (Closes: #90464). -- Tommi Virtanen Sat, 23 Jun 2001 01:19:07 +0300 isync (0.4-1) unstable; urgency=low * Initial Release. -- Tommi Virtanen Sat, 10 Mar 2001 18:43:35 +0200 isync-1.3.0/debian/README.Debian0000644000175000001440000000110513164125071013035 00000000000000A note from isync's web site: isync can be integrated into Mutt fairly easily with a few hooks: folder-hook ~A bind index $ folder-hook +maildir 'macro index $ "!isync -e maildir\n"' where maildir is the name of the local mailbox (or its alias). This works well so long as you are not modifying the IMAP mailbox outside of Mutt. However, if you are using another mail program simultaneously Mutt will have the wrong idea of the local mailbox flags and messages will start disappearing from its index display (don't worry, they are still on disk). isync-1.3.0/debian/compat0000644000175000001440000000000213164125071012175 000000000000009 isync-1.3.0/debian/copyright0000644000175000001440000000242013164125071012730 00000000000000Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: isync Source: http://isync.sourceforge.net Files: * Copyright: 2000-2002, Michael R. Elkins 2002-2017, Oswald Buddenhagen 2004, Theodore Y. Ts'o License: GPL-2+ Files: debian/* Copyright: 2013, Alessandro Ghedini License: GPL-2+ License: GPL-2+ 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 package 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 . . As a special exception, mbsync may be linked with the OpenSSL library, despite that library's more restrictive license. . On Debian systems, the complete text of the GNU General Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". isync-1.3.0/debian/watch0000644000175000001440000000006313164125071012027 00000000000000version=3 http://sf.net/isync/ isync-(.*)\.tar\.gz isync-1.3.0/debian/control0000644000175000001440000000311613164125071012403 00000000000000Source: isync Section: mail Priority: optional Maintainer: Nicolas Boullis Uploaders: Theodore Y. Ts'o , Alessandro Ghedini Standards-Version: 3.9.8 Build-Depends: debhelper (>= 9), dh-autoreconf, libdb-dev, libsasl2-dev, libssl-dev, pkg-config, zlib1g-dev Vcs-Git: https://anonscm.debian.org/git/collab-maint/isync.git Vcs-Browser: https://anonscm.debian.org/gitweb/?p=collab-maint/isync.git Homepage: http://isync.sourceforge.net/ Package: isync Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Suggests: mutt Description: IMAP and MailDir mailbox synchronizer mbsync/isync is a command line application which synchronizes mailboxes; currently Maildir and IMAP4 mailboxes are supported. New messages, message deletions and flag changes can be propagated both ways. isync is suitable for use in IMAP-disconnected mode. . The main application was much improved in version 1.0. Those improvements lead to interface changes and the application being renamed to mbsync. The application isync is now only a wrapper to keep compatibility with earlier versions. . Features: * Fine-grained selection of synchronization operations to perform * Synchronizes single mailboxes or entire mailbox collections * Partial mirrors possible: keep only the latest messages locally * Trash functionality: backup messages before removing them IMAP features: * Security: supports TLS/SSL via imaps: (port 993) and STARTTLS; SASL for authentication * Supports NAMESPACE for simplified configuration * Pipelining for maximum speed isync-1.3.0/mbsync-get-cert0000755000175000001440000000351312530344363012513 00000000000000#!/bin/sh # # This script will extract the necessary certificate from the IMAP server # It assumes that an attacker isn't trying to spoof you when you connect # to the IMAP server! You're better off downloading the certificate # from a trusted source. # # Copyright (C) 2003 Theodore Ts'o # 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # if [ $# != 1 ]; then echo "Usage: $0 " >&2 exit 1 fi HOST=$1 seed=`date '+%s'` try=0 while :; do TMPDIR=/tmp/get-cert.$$.$seed mkdir $TMPDIR 2> /dev/null && break if [ $try = 1000 ]; then echo "Cannot create temporary directory." >&2 exit 1 fi try=`expr $try + 1` seed=`expr \( \( $seed \* 1103515245 \) + 12345 \) % 2147483648` done TMPFILE=$TMPDIR/get-cert ERRFILE=$TMPDIR/get-cert-err CERTFILE=$TMPDIR/cert echo QUIT | openssl s_client -connect $HOST:993 -showcerts \ > $TMPFILE 2> $ERRFILE sed -e '1,/^-----BEGIN CERTIFICATE-----/d' \ -e '/^-----END CERTIFICATE-----/,$d' < $TMPFILE > $CERTFILE if test -s $CERTFILE ; then echo -----BEGIN CERTIFICATE----- cat $CERTFILE echo -----END CERTIFICATE----- else echo "Couldn't retrieve certificate. openssl reported the following errors:" cat $ERRFILE fi rm -r $TMPDIR isync-1.3.0/COPYING0000644000175000001440000004311012452527622010616 00000000000000 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. isync-1.3.0/configure.ac0000644000175000001440000001351613164124566012061 00000000000000AC_INIT([isync], [1.3.0]) AC_CONFIG_HEADERS([autodefs.h]) AM_INIT_AUTOMAKE AM_MAINTAINER_MODE AC_PROG_CC_C99 if test "$GCC" = yes; then CFLAGS="$CFLAGS -pipe -W -Wall -Wshadow -Wstrict-prototypes -std=c99 -pedantic -Wno-overlength-strings" fi CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE" AC_CACHE_CHECK([whether strftime supports %z], ob_cv_strftime_z, [AC_TRY_RUN( [#include #include int main(void) { time_t t = 0; char buf[32]; strftime(buf, sizeof(buf), "%z", localtime(&t)); return !(buf[0] == '+' || buf[0] == '-'); } ], [ob_cv_strftime_z=yes], [ob_cv_strftime_z=no], [ob_cv_strftime_z="yes (assumed)"])]) if test "x$ob_cv_strftime_z" = x"no"; then AC_MSG_ERROR([libc lacks necessary feature]) fi AC_CHECK_HEADERS(sys/poll.h sys/select.h) AC_CHECK_FUNCS(vasprintf strnlen memrchr timegm) AC_CHECK_LIB(socket, socket, [SOCK_LIBS="-lsocket"]) AC_CHECK_LIB(nsl, inet_ntoa, [SOCK_LIBS="$SOCK_LIBS -lnsl"]) AC_SUBST(SOCK_LIBS) have_ipv6=true sav_LIBS=$LIBS LIBS="$LIBS $SOCK_LIBS" AC_CHECK_FUNCS(getaddrinfo inet_ntop, , [have_ipv6=false]) LIBS=$sav_LIBS if $have_ipv6; then AC_DEFINE(HAVE_IPV6, 1, [if your libc has IPv6 support]) fi have_ssl_paths= AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl[=PATH]], [where to look for SSL [detect]]), [ob_cv_with_ssl=$withval]) if test "x$ob_cv_with_ssl" != xno; then case $ob_cv_with_ssl in ""|yes) dnl Detect the pkg-config tool, as it may have extra info about the openssl dnl installation we can use. I *believe* this is what we are expected to do dnl on really recent Redhat Linux hosts. PKG_PROG_PKG_CONFIG if test "x$PKG_CONFIG" != "x" ; then AC_MSG_CHECKING([OpenSSL presence with pkg-config]) if $PKG_CONFIG --exists openssl; then SSL_LIBS=`$PKG_CONFIG --libs-only-l openssl` SSL_LDFLAGS=`$PKG_CONFIG --libs-only-L openssl` SSL_CPPFLAGS=`$PKG_CONFIG --cflags-only-I openssl` have_ssl_paths=yes AC_MSG_RESULT([found]) else AC_MSG_RESULT([not found]) fi fi ;; *) SSL_LDFLAGS=-L$ob_cv_with_ssl/lib$libsuff SSL_CPPFLAGS=-I$ob_cv_with_ssl/include ;; esac if test -z "$have_ssl_paths"; then sav_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $SSL_LDFLAGS" AC_CHECK_LIB(dl, dlopen, [LIBDL=-ldl]) AC_CHECK_LIB(crypto, CRYPTO_lock, [LIBCRYPTO=-lcrypto]) AC_CHECK_LIB(ssl, SSL_connect, [SSL_LIBS="-lssl $LIBCRYPTO $LIBDL" have_ssl_paths=yes]) LDFLAGS=$sav_LDFLAGS fi sav_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $SSL_CPPFLAGS" AC_CHECK_HEADER(openssl/ssl.h, , [have_ssl_paths=]) CPPFLAGS=$sav_CPPFLAGS if test -z "$have_ssl_paths"; then if test -n "$ob_cv_with_ssl"; then AC_MSG_ERROR([OpenSSL libs and/or includes were not found where specified]) fi else AC_DEFINE(HAVE_LIBSSL, 1, [if you have the OpenSSL libraries]) CPPFLAGS="$CPPFLAGS $SSL_CPPFLAGS" LDFLAGS="$LDFLAGS $SSL_LDFLAGS" fi fi AC_SUBST(SSL_LIBS) have_sasl_paths= AC_ARG_WITH(sasl, AS_HELP_STRING([--with-sasl[=PATH]], [where to look for SASL [detect]]), [ob_cv_with_sasl=$withval]) if test "x$ob_cv_with_sasl" != xno; then case $ob_cv_with_sasl in ""|yes) dnl FIXME: Try various possible paths here... ;; *) SASL_LDFLAGS=-L$ob_cv_with_sasl/lib$libsuff SASL_CPPFLAGS=-I$ob_cv_with_sasl/include ;; esac if test -z "$have_sasl_paths"; then sav_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $SASL_LDFLAGS" AC_CHECK_LIB(sasl2, sasl_client_init, [SASL_LIBS="-lsasl2" have_sasl_paths=yes]) LDFLAGS=$sav_LDFLAGS fi sav_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $SASL_CPPFLAGS" AC_CHECK_HEADER(sasl/sasl.h, , [have_sasl_paths=]) CPPFLAGS=$sav_CPPFLAGS if test -z "$have_sasl_paths"; then if test -n "$ob_cv_with_sasl"; then AC_MSG_ERROR([SASL libs and/or includes were not found where specified]) fi else AC_DEFINE(HAVE_LIBSASL, 1, [if you have the SASL libraries]) CPPFLAGS="$CPPFLAGS $SASL_CPPFLAGS" LDFLAGS="$LDFLAGS $SASL_LDFLAGS" fi fi AC_SUBST(SASL_LIBS) AC_CACHE_CHECK([for Berkeley DB >= 4.1], ac_cv_berkdb4, [ac_cv_berkdb4=no sav_LIBS=$LIBS LIBS="$LIBS -ldb" AC_TRY_LINK([#include ], [DB *db; db_create(&db, 0, 0); db->truncate(db, 0, 0, 0); db->open(db, 0, "foo", "foo", DB_HASH, DB_CREATE, 0)], [ac_cv_berkdb4=yes]) LIBS=$sav_LIBS ]) if test "x$ac_cv_berkdb4" = xyes; then AC_SUBST([DB_LIBS], ["-ldb"]) AC_DEFINE(USE_DB, 1, [if Berkeley DB should be used]) fi have_zlib= AC_ARG_WITH(zlib, AS_HELP_STRING([--with-zlib], [use zlib [detect]]), [ob_cv_with_zlib=$withval]) if test "x$ob_cv_with_zlib" != xno; then AC_CHECK_LIB([z], [deflate], [AC_CHECK_HEADER(zlib.h, [have_zlib=1 AC_SUBST([Z_LIBS], ["-lz"]) AC_DEFINE([HAVE_LIBZ], 1, [if you have the zlib library])] )] ) fi AC_ARG_ENABLE(compat, AC_HELP_STRING([--disable-compat], [don't include isync compatibility wrapper [no]]), [ob_cv_enable_compat=$enableval]) if test "x$ob_cv_enable_compat" != xno; then AC_CHECK_FUNCS(getopt_long) fi AM_CONDITIONAL(with_compat, test "x$ob_cv_enable_compat" != xno -a "x$ac_cv_berkdb4" = xyes) AM_CONDITIONAL(with_mdconvert, test "x$ac_cv_berkdb4" = xyes) AC_CONFIG_FILES([Makefile src/Makefile src/compat/Makefile isync.spec]) AC_OUTPUT AC_MSG_RESULT() if test -n "$have_ssl_paths"; then AC_MSG_RESULT([Using SSL]) else AC_MSG_RESULT([Not using SSL]) fi if test -n "$have_sasl_paths"; then AC_MSG_RESULT([Using SASL]) else AC_MSG_RESULT([Not using SASL]) fi if test -n "$have_zlib"; then AC_MSG_RESULT([Using zlib]) else AC_MSG_RESULT([Not using zlib]) fi if test "x$ac_cv_berkdb4" = xyes; then AC_MSG_RESULT([Using Berkeley DB]) else AC_MSG_RESULT([Not using Berkeley DB]) fi AC_MSG_RESULT() isync-1.3.0/acinclude.m40000644000175000001440000000275212452527622011763 00000000000000# Add --enable-maintainer-mode option to configure. # From Jim Meyering # Change it to enable maintainer mode by default by Nicolas Boullis. # Copyright 1996, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. # Copyright 2004 Nicolas Boullis. # 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 AC_DEFUN([AM_MAINTAINER_MODE], [AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode is enabled by default AC_ARG_ENABLE(maintainer-mode, [ --disable-maintainer-mode disable make rules and dependencies not useful (and sometimes confusing) to the casual installer], USE_MAINTAINER_MODE=$enableval, USE_MAINTAINER_MODE=yes) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST(MAINT)dnl ] ) isync-1.3.0/AUTHORS0000644000175000001440000000076312530344363010636 00000000000000Oswald Buddenhagen * Contributor, current maintainer Theodore Ts'o * Contributor, Debian package co-maintainer Nicolas Boullis * Debian package maintainer and minor upstream contributions Michael Elkins * Original author Send questions and bug reports to the isync-devel@lists.sourceforge.net mailing list. _DON'T_ report bugs to Michael, not even in a CC: - he is not actively involved in isync development any more. isync-1.3.0/Makefile.in0000644000175000001440000007504713164163406011643 00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 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@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@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 = : subdir = . 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) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = autodefs.h CONFIG_CLEAN_FILES = isync.spec CONFIG_CLEAN_VPATH_FILES = 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 = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(docdir)" SCRIPTS = $(bin_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-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 \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(doc_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)autodefs.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/autodefs.h.in \ $(srcdir)/isync.spec.in AUTHORS COPYING ChangeLog INSTALL NEWS \ README TODO compile depcomp install-sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DB_LIBS = @DB_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ SASL_LIBS = @SASL_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOCK_LIBS = @SOCK_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ Z_LIBS = @Z_LIBS@ 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@ 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_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = src bin_SCRIPTS = mbsync-get-cert EXTRA_DIST = debian isync.spec $(bin_SCRIPTS) LOG_PL = \ use POSIX qw(strftime); \ use Date::Parse; \ use Text::Wrap; \ $$Text::Wrap::columns = 72; \ while (defined($$_ = <>)) { \ /^commit / or die "commit missing: $$_"; \ <> =~ /^log size (\d+)$$/ or die "wrong size"; \ $$len = $$1; \ read(STDIN, $$log, $$len) == $$len or die "unexpected EOF"; \ $$log =~ s/^Author: ([^>]+>)\nDate: (\d{4}-\d\d-\d\d \d\d:\d\d:\d\d [-+]\d{4})\n(.*)$$/$$3/s or die "unexpected log format"; \ $$author = $$1; $$date = str2time($$2); \ scalar(<>); \ @files = (); \ $$pfx = ""; \ while (defined($$l = <>) and $$l ne "\n") { \ chomp $$l; \ next if ($$l =~ m,^(ChangeLog$$|NEWS$$|TODO$$|debian/),); \ if (!@files) { \ $$pfx = $$l; \ $$pfx =~ s,/?[^/]+$$,,; \ } else { \ while (length($$pfx)) { \ $$l =~ m,^\Q$$pfx/\E, and last; \ $$pfx =~ s,/?[^/]+$$,,; \ } \ } \ push @files, $$l; \ } \ next if (!@files); \ print strftime("%F %H:%M", gmtime($$date))." ".$$author."\n\n"; \ if (@files > 1 and ($$len = length($$pfx))) { \ @efiles = (); \ for $$f (@files) { push @efiles, substr($$f, $$len + 1); } \ $$fstr = $$pfx."/: "; \ } else { \ @efiles = @files; \ $$fstr = ""; \ } \ print wrap("\t* ", "\t ", $$fstr.join(", ", @efiles).":")."\n"; \ $$log =~ s, +$$,,gm; \ $$log =~ s,^ ,\t,gm; \ print $$log."\n"; \ } doc_DATA = README TODO NEWS ChangeLog AUTHORS all: autodefs.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu 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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): autodefs.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/autodefs.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status autodefs.h $(srcdir)/autodefs.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f autodefs.h stamp-h1 isync.spec: $(top_builddir)/config.status $(srcdir)/isync.spec.in cd $(top_builddir) && $(SHELL) ./config.status $@ install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-docDATA: @$(NORMAL_UNINSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(am__uninstall_files_from_dir) # 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. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ 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; \ ($(am__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" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ 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 || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files 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 "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$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 \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -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) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_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*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(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 \ && cd "$$am__cwd" \ || exit 1 $(am__post_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: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { 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 $(SCRIPTS) $(DATA) autodefs.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)" "$(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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-docDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binSCRIPTS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: 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 pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binSCRIPTS uninstall-docDATA .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-hook dist-lzip dist-shar dist-tarZ dist-xz \ dist-zip distcheck distclean distclean-generic distclean-hdr \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ install-binSCRIPTS 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 pdf \ pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binSCRIPTS uninstall-docDATA .PRECIOUS: Makefile $(srcdir)/ChangeLog: log log: @test -z "$(srcdir)" || cd $(srcdir) && \ ( ! test -d .git || \ git log --pretty=medium --date=iso --log-size --name-only --no-merges | \ perl -e '$(LOG_PL)' > ChangeLog ) cov-scan: clean /opt/cov-analysis-*/bin/cov-build --dir cov-int $(MAKE) tar cavf isync.tar.xz cov-int deb: CFLAGS= INSTALL= dpkg-buildpackage -b --no-sign dist-hook: find $(distdir)/debian \( -name .#\*# -o -type l \) -print0 | xargs -0r rm -rf -cd $(distdir)/debian && test -f .gitignore && rm -rf `cut -c2- .gitignore` .gitignore dist-sign: dist gpg -b -a $(PACKAGE)-$(VERSION).tar.gz rpm: dist CFLAGS="-O2 -mtune=core2" rpmbuild --clean -ta $(PACKAGE)-$(VERSION).tar.gz rpm-ia32: dist CFLAGS="-O2 -m32 -march=i686" rpmbuild --target i686-unknown-linux --clean -ta $(PACKAGE)-$(VERSION).tar.gz # 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: isync-1.3.0/src/0000755000175000001440000000000013164163470010431 500000000000000isync-1.3.0/src/mbsync.10000644000175000001440000007432013164125173011732 00000000000000.ig \" mbsync - mailbox synchronizer \" Copyright (C) 2000-2002 Michael R. Elkins \" Copyright (C) 2002-2004,2011-2015 Oswald Buddenhagen \" Copyright (C) 2004 Theodore Y. Ts'o \" \" 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, see . \" \" As a special exception, mbsync may be linked with the OpenSSL library, \" despite that library's more restrictive license. .. .TH mbsync 1 "2015 Mar 22" .. .SH NAME mbsync - synchronize IMAP4 and Maildir mailboxes .. .SH SYNOPSIS \fBmbsync\fR [\fIoptions\fR ...] {{\fIchannel\fR[\fB:\fIbox\fR[{\fB,\fR|\fB\\n\fR}...]]|\fIgroup\fR} ...|\fB-a\fR} .. .SH DESCRIPTION \fBmbsync\fR is a command line application which synchronizes mailboxes; currently Maildir and IMAP4 mailboxes are supported. New messages, message deletions and flag changes can be propagated both ways; the operation set can be selected in a fine-grained manner. .br Synchronization is based on unique message identifiers (UIDs), so no identification conflicts can occur (unlike with some other mail synchronizers). OTOH, \fBmbsync\fR is susceptible to UID validity changes (but will recover just fine if the change is unfounded). Synchronization state is kept in one local text file per mailbox pair; these files are protected against concurrent \fBmbsync\fR processes. Mailboxes can be safely modified while \fBmbsync\fR operates (see \fBINHERENT PROBLEMS\fR below for a minor exception). Multiple replicas of each mailbox can be maintained. .. .SH OPTIONS .TP \fB-c\fR, \fB--config\fR \fIfile\fR Read configuration from \fIfile\fR. By default, the configuration is read from ~/.mbsyncrc. .TP \fB-a\fR, \fB--all\fR Select all configured channels. Any channel/group specifications on the command line are ignored. .TP \fB-l\fR, \fB--list\fR Don't synchronize anything, but list all mailboxes in the selected channels and exit. .TP \fB-C\fR[\fBm\fR][\fBs\fR], \fB--create\fR[\fB-master\fR|\fB-slave\fR] Override any \fBCreate\fR options from the config file. See below. .TP \fB-R\fR[\fBm\fR][\fBs\fR], \fB--remove\fR[\fB-master\fR|\fB-slave\fR] Override any \fBRemove\fR options from the config file. See below. .TP \fB-X\fR[\fBm\fR][\fBs\fR], \fB--expunge\fR[\fB-master\fR|\fB-slave\fR] Override any \fBExpunge\fR options from the config file. See below. .TP {\fB-n\fR|\fB-N\fR|\fB-d\fR|\fB-f\fR|\fB-0\fR|\fB-F\fR},\ {\fB--new\fR|\fB--renew\fR|\fB--delete\fR|\fB--flags\fR|\fB--noop\fR|\fB--full\fR} .TP \r{\fB-L\fR|\fB-H\fR}[\fBn\fR][\fBN\fR][\fBd\fR][\fBf\fR],\ {\fB--pull\fR|\fB--push\fR}[\fB-new\fR|\fB-renew\fR|\fB-delete\fR|\fB-flags\fR] Override any \fBSync\fR options from the config file. See below. .TP \fB-h\fR, \fB--help\fR Display a summary of command line options. .TP \fB-v\fR, \fB--version\fR Display version information. .TP \fB-V\fR, \fB--verbose\fR Enable \fIverbose\fR mode, which displays what is currently happening. .TP \fB-D\fR[\fBC\fR][\fBd\fR|\fBD\fR][\fBm\fR][\fBM\fR][\fBn\fR|\fBN\fR][\fBs\fR]\fR]\fR,\ \fB--debug\fR[\fB-crash\fR|\fB-driver\fR|\fB-driver-all\fR|\fB-maildir\fR|\fB-main\fR|\fB-net\fR|\fB-net-all\fR|\fB-sync\fR] Enable debugging categories: .in +4 \fBC\fR, \fBcrash\fR - use built-in crash handler .br \fBd\fR, \fBdriver\fR - print driver calls (metadata only) .br \fBD\fR, \fBdriver-all\fR - print driver calls (including messages) .br \fBm\fR, \fBmaildir\fR - print maildir debug info .br \fBM\fR, \fBmain\fR - print main debug info .br \fBn\fR, \fBnet\fR - print network traffic (protocol only) .br \fBN\fR, \fBnet-all\fR - print network traffic (including payloads) .br \fBs\fR, \fBsync\fR - print synchronization debug info .in -4 All categories except \fBcrash\fR implictly enable \fIverbose\fR mode. Without category specification, all categories except net-all are enabled. .TP \fB-q\fR, \fB--quiet\fR Suppress progress counters (this is implicit if stdout is no TTY, or any debugging categories are enabled) and notices. If specified twice, suppress warning messages as well. .. .SH CONFIGURATION The configuration file is mandatory; \fBmbsync\fR will not run without it. Lines starting with a hash mark (\fB#\fR) are comments and are ignored entirely. Configuration items are keywords followed by one or more arguments; arguments containing spaces must be enclosed in double quotes (\fB"\fR), and literal double quotes and backslashes (\fB\\\fR) must be backslash-escaped. All keywords (including those used as arguments) are case-insensitive. Bash-like home directory expansion using the tilde (\fB~\fR) is supported in all options which represent local paths. There are a few global options, the rest applies to particular sections. Sections are started by a section keyword and are terminated by an empty line or end of file. Every section defines an object with an identifier unique within that object class. .P There are two basic object classes: Stores and Channels. A Store defines a collection of mailboxes; basically a folder, either local or remote. A Channel connects two Stores, describing the way the two are synchronized. .br There are two auxiliary object classes: Accounts and Groups. An Account describes the connection part of remote Stores, so a server connection can be shared between multiple Stores. A Group aggregates multiple Channels to save typing on the command line. .P File system locations (in particular, \fBPath\fR and \fBInbox\fR) use the Store's internal path separators, which may be slashes, periods, etc., or even combinations thereof. .br Mailbox names, OTOH, always use canonical path separators, which are Unix-like forward slashes. .. .SS All Stores These options can be used in all supported Store types. .br In this context, the term "remote" describes the second Store within a Channel, and not necessarily a remote server. .br The special mailbox \fBINBOX\fR exists in every Store; its physical location in the file system is Store type specific. .. .TP \fBPath\fR \fIpath\fR The location of the Store in the (server's) file system. If this is no absolute path, the reference point is Store type specific. This string is prepended to the mailbox names addressed in this Store, but is not considered part of them; this is important for \fBPatterns\fR in the Channels section. Note that you \fBmust\fR append a slash if you want to specify an entire directory. (Default: none) .. .TP \fBMaxSize\fR \fIsize\fR[\fBk\fR|\fBm\fR][\fBb\fR] Messages larger than that will not be propagated into this Store. This is useful for weeding out messages with large attachments. \fBK\fR and \fBM\fR can be appended to the size to specify KiBytes resp. MeBytes instead of bytes. \fBB\fR is accepted but superfluous. If \fIsize\fR is 0, the maximum message size is \fBunlimited\fR. (Default: \fI0\fR) .. .TP \fBMapInbox\fR \fImailbox\fR Create a virtual mailbox (relative to \fBPath\fR) which aliases the \fBINBOX\fR. Makes sense in conjunction with \fBPatterns\fR in the Channels section, though with a Maildir slave, you probably want to place \fBInbox\fR under \fBPath\fR instead. This virtual mailbox does not support subfolders. .. .TP \fBFlatten\fR \fIdelim\fR Flatten the hierarchy within this Store by substituting the canonical hierarchy delimiter \fB/\fR with \fIdelim\fR. This can be useful when the MUA used to access the Store provides suboptimal handling of hierarchical mailboxes, as is the case with \fBMutt\fR. A common choice for the delimiter is \fB.\fR. .br Note that flattened sub-folders of the \fBINBOX\fR always end up under \fBPath\fR, including the "INBOX\fIdelim\fR" prefix. .. .TP \fBTrash\fR \fImailbox\fR Specifies a mailbox (relative to \fBPath\fR) to copy deleted messages to prior to expunging. See \fBRECOMMENDATIONS\fR and \fBINHERENT PROBLEMS\fR below. (Default: none) .. .TP \fBTrashNewOnly\fR \fByes\fR|\fBno\fR When trashing, copy only not yet propagated messages. This makes sense if the remote Store has a \fBTrash\fR as well (with \fBTrashNewOnly\fR \fBno\fR). (Default: \fBno\fR) .. .TP \fBTrashRemoteNew\fR \fByes\fR|\fBno\fR When expunging the remote Store, copy not yet propagated messages to this Store's \fBTrash\fR. When using this, the remote Store does not need an own \fBTrash\fR at all, yet all messages are archived. (Default: \fBno\fR) .. .SS Maildir Stores The reference point for relative \fBPath\fRs is the current working directory. .P As \fBmbsync\fR needs UIDs, but no standardized UID storage scheme exists for Maildir, \fBmbsync\fR supports two schemes, each with its pros and cons. .br The \fBnative\fR scheme is stolen from the latest Maildir patches to \fBc-client\fR and is therefore compatible with \fBpine\fR. The UID validity is stored in a file named .uidvalidity; the UIDs are encoded in the file names of the messages. .br The \fBalternative\fR scheme is based on the UID mapping used by \fBisync\fR versions 0.8 and 0.9.x. The invariant parts of the file names of the messages are used as keys into a Berkeley database named .isyncuidmap.db, which holds the UID validity as well. .br The \fBnative\fR scheme is faster, more space efficient, endianness independent and "human readable", but will be disrupted if a message is copied from another mailbox without getting a new file name; this would result in duplicated UIDs sooner or later, which in turn results in a UID validity change, making synchronization fail. The \fBalternative\fR scheme would fail if a MUA changed a message's file name in a part \fBmbsync\fR considers invariant; this would be interpreted as a message deletion and a new message, resulting in unnecessary traffic. .br \fBMutt\fR is known to work fine with both schemes. .br Use \fBmdconvert\fR to convert mailboxes from one scheme to the other. .. .TP \fBMaildirStore\fR \fIname\fR Define the Maildir Store \fIname\fR, opening a section for its parameters. .. .TP \fBAltMap\fR \fByes\fR|\fBno\fR Use the \fBalternative\fR UID storage scheme for mailboxes in this Store. This does not affect mailboxes that do already have a UID storage scheme; use \fBmdconvert\fR to change it. See \fBRECOMMENDATIONS\fR below. (Default: \fBno\fR) .. .TP \fBInbox\fR \fIpath\fR The location of the \fBINBOX\fR. This is \fInot\fR relative to \fBPath\fR, but it is allowed to place the \fBINBOX\fR inside the \fBPath\fR. (Default: \fI~/Maildir\fR) .. .TP \fBInfoDelimiter\fR \fIdelim\fR The character used to delimit the info field from a message's basename. The Maildir standard defines this to be the colon, but this is incompatible with DOS/Windows file systems. (Default: the value of \fBFieldDelimiter\fR) .. .TP \fBSubFolders\fR \fBVerbatim\fR|\fBMaildir++\fR|\fBLegacy\fR The on-disk folder naming style used for hierarchical mailboxes. This has option has no effect when \fBFlatten\fR is used. .br Suppose mailboxes with the canonical paths \fBtop/sub/subsub\fR and \fBINBOX/sub/subsub\fR, the styles will yield the following on-disk paths: .br \fBVerbatim\fR - \fIPath\fB/top/sub/subsub\fR and \fIInbox\fB/sub/subsub\fR (this is the style you probably want to use) .br \fBMaildir++\fR - \fIInbox\fB/.top.sub.subsub\fR and \fIInbox\fB/..sub.subsub\fR (this style is compatible with Courier and Dovecot - but note that the mailbox metadata format is \fInot\fR compatible). Note that attempts to set \fBPath\fR are rejected in this mode. .br \fBLegacy\fR - \fIPath\fB/top/.sub/.subsub\fR and \fIInbox\fB/.sub/.subsub\fR (this is \fBmbsync\fR's historical style) .br (Default: unset; will error out when sub-folders are encountered) .. .SS IMAP4 Accounts .TP \fBIMAPAccount\fR \fIname\fR Define the IMAP4 Account \fIname\fR, opening a section for its parameters. .. .TP \fBHost\fR \fIhost\fR Specify the DNS name or IP address of the IMAP server. .br If \fBTunnel\fR is used, this setting is needed only if \fBSSLType\fR is not \fBNone\fR and \fBCertificateFile\fR is not used, in which case the host name is used for certificate subject verification. .. .TP \fBPort\fR \fIport\fR Specify the TCP port number of the IMAP server. (Default: 143 for IMAP, 993 for IMAPS) .br If \fBTunnel\fR is used, this setting is ignored. .. .TP \fBTimeout\fR \fItimeout\fR Specify the connect and data timeout for the IMAP server in seconds. Zero means unlimited. (Default: \fI20\fR) .. .TP \fBUser\fR \fIusername\fR Specify the login name on the IMAP server. .. .TP \fBPass\fR \fIpassword\fR Specify the password for \fIusername\fR on the IMAP server. Note that this option is \fInot\fR required. If neither a password nor a password command is specified in the configuration file, \fBmbsync\fR will prompt you for a password. .. .TP \fBPassCmd\fR [\fB+\fR]\fIcommand\fR Specify a shell command to obtain a password rather than specifying a password directly. This allows you to use password files and agents. The command must produce exactly one line on stdout; the trailing newline is optional. Prepend \fB+\fR to the command to indicate that it produces TTY output (e.g., a decryption password prompt); failure to do so will merely produce messier output. .. .TP \fBTunnel\fR \fIcommand\fR Specify a command to run to establish a connection rather than opening a TCP socket. This allows you to run an IMAP session over an SSH tunnel, for example. .. .TP \fBAuthMechs\fR \fItype\fR ... The list of acceptable authentication mechanisms. In addition to the mechanisms listed in the SASL registry (link below), the legacy IMAP \fBLOGIN\fR mechanism is known. The wildcard \fB*\fR represents all mechanisms that are deemed secure enough for the current \fBSSLType\fR setting. The actually used mechanism is the most secure choice from the intersection of this list, the list supplied by the server, and the installed SASL modules. (Default: \fB*\fR) .. .TP \fBSSLType\fR {\fBNone\fR|\fBSTARTTLS\fR|\fBIMAPS\fR} Select the connection security/encryption method: .br \fBNone\fR - no security. This is the default when \fBTunnel\fR is set, as tunnels are usually secure. .br \fBSTARTTLS\fR - security is established via the STARTTLS extension after connecting the regular IMAP port 143. Most servers support this, so it is the default (unless a tunnel is used). .br \fBIMAPS\fR - security is established by starting SSL/TLS negotiation right after connecting the secure IMAP port 993. .. .TP \fBSSLVersions\fR [\fBSSLv3\fR] [\fBTLSv1\fR] [\fBTLSv1.1\fR] [\fBTLSv1.2\fR] Select the acceptable SSL/TLS versions. Use old versions only when the server has problems with newer ones. (Default: [\fBTLSv1\fR] [\fBTLSv1.1\fR] [\fBTLSv1.2\fR]). .. .TP \fBSystemCertificates\fR \fByes\fR|\fBno\fR Whether the system's default root cerificate store should be loaded. (Default: \fByes\fR) .. .TP \fBCertificateFile\fR \fIpath\fR File containing additional X.509 certificates used to verify server identities. Directly matched peer certificates are always trusted, regardless of validity. .br Note that the system's default certificate store is always used (unless \fBSystemCertificates\fR is disabled) and should not be specified here. .. .TP \fBClientCertificate\fR \fIpath\fR File containing a client certificate to send to the server. \fBClientKey\fR should also be specified. .br Note that client certificate verification is usually not required, so it is unlikely that you need this option. .. .TP \fBClientKey\fR \fIpath\fR File containing the private key corresponding to \fBClientCertificate\fR. .. .TP \fBPipelineDepth\fR \fIdepth\fR Maximum number of IMAP commands which can be simultaneously in flight. Setting this to \fI1\fR disables pipelining. This is mostly a debugging option, but may also be used to limit average bandwidth consumption (GMail may require this if you have a very fast connection), or to spare flaky servers like M$ Exchange. (Default: \fIunlimited\fR) .. .TP \fBDisableExtension\fR[\fBs\fR] \fIextension\fR ... Disable the use of specific IMAP extensions. This can be used to work around bugs in servers (and possibly \fBmbsync\fR itself). (Default: empty) .. .SS IMAP Stores The reference point for relative \fBPath\fRs is whatever the server likes it to be; probably the user's $HOME or $HOME/Mail on that server. The location of \fBINBOX\fR is up to the server as well and is usually irrelevant. .TP \fBIMAPStore\fR \fIname\fR Define the IMAP4 Store \fIname\fR, opening a section for its parameters. .. .TP \fBAccount\fR \fIaccount\fR Specify which IMAP4 Account to use. Instead of defining an Account and referencing it here, it is also possible to specify all the Account options directly in the Store's section - this makes sense if an Account is used for one Store only anyway. .. .TP \fBUseNamespace\fR \fByes\fR|\fBno\fR Selects whether the server's first "personal" NAMESPACE should be prefixed to mailbox names. Disabling this makes sense for some broken IMAP servers. This option is meaningless if a \fBPath\fR was specified. (Default: \fByes\fR) .. .TP \fBPathDelimiter\fR \fIdelim\fR Specify the server's hierarchy delimiter. (Default: taken from the server's first "personal" NAMESPACE) .br Do \fInot\fR abuse this to re-interpret the hierarchy. Use \fBFlatten\fR instead. .. .SS Channels .TP \fBChannel\fR \fIname\fR Define the Channel \fIname\fR, opening a section for its parameters. .. .TP {\fBMaster\fR|\fBSlave\fR} \fB:\fIstore\fB:\fR[\fImailbox\fR] Specify the Master resp. Slave Store to be connected by this Channel. If \fBPatterns\fR are specified, \fImailbox\fR is interpreted as a prefix which is not matched against the patterns, and which is not affected by mailbox list overrides. Otherwise, if \fImailbox\fR is omitted, \fBINBOX\fR is assumed. .. .TP \fBPattern\fR[\fBs\fR] [\fB!\fR]\fIpattern\fR ... Instead of synchronizing only one mailbox pair, synchronize all mailboxes that match the \fIpattern\fR(s). The mailbox names are the same on both Master and Slave. Patterns are IMAP4 patterns, i.e., \fB*\fR matches anything and \fB%\fR matches anything up to the next hierarchy delimiter. Prepending \fB!\fR to a pattern makes it an exclusion. Multiple patterns can be specified (either by supplying multiple arguments or by using \fBPattern\fR multiple times); later matches take precedence. .br Note that \fBINBOX\fR is not matched by wildcards, unless it lives under \fBPath\fR. .br The mailbox list selected by \fBPatterns\fR can be overridden by a mailbox list in a channel reference (a \fBGroup\fR specification or the command line). .br Example: "\fBPatterns\fR\ \fI%\ !Trash\fR" .. .TP \fBMaxSize\fR \fIsize\fR[\fBk\fR|\fBm\fR][\fBb\fR] Analogous to the homonymous option in the Stores section, but applies equally to Master and Slave. Note that this actually modifies the Stores, so take care not to provide conflicting settings if you use the Stores in multiple Channels. .. .TP \fBMaxMessages\fR \fIcount\fR Sets the maximum number of messages to keep in each Slave mailbox. This is useful for mailboxes where you keep a complete archive on the server, but want to mirror only the last messages (for instance, for mailing lists). The messages that were the first to arrive in the mailbox (independently of the actual date of the message) will be deleted first. Messages that are flagged (marked as important) and (by default) unread messages will not be automatically deleted. If \fIcount\fR is 0, the maximum number of messages is \fBunlimited\fR (Default: \fI0\fR). .. .TP \fBExpireUnread\fR \fByes\fR|\fBno\fR Selects whether unread messages should be affected by \fBMaxMessages\fR. Normally, unread messages are considered important and thus never expired. This ensures that you never miss new messages even after an extended absence. However, if your archive contains large amounts of unread messages by design, treating them as important would practically defeat \fBMaxMessages\fR. In this case you need to enable this option. (Default: \fBno\fR). .. .TP \fBSync\fR {\fBNone\fR|[\fBPull\fR] [\fBPush\fR] [\fBNew\fR] [\fBReNew\fR] [\fBDelete\fR] [\fBFlags\fR]|\fBAll\fR} Select the synchronization operation(s) to perform: .br \fBPull\fR - propagate changes from Master to Slave. .br \fBPush\fR - propagate changes from Slave to Master. .br \fBNew\fR - propagate newly appeared messages. .br \fBReNew\fR - previously refused messages are re-evaluated for propagation. Useful after flagging affected messages in the source Store or enlarging MaxSize in the destination Store. .br \fBDelete\fR - propagate message deletions. This applies only to messages that are actually gone, i.e., were expunged. The affected messages in the remote Store are marked as deleted only, i.e., they won't be really deleted until that Store is expunged. .br \fBFlags\fR - propagate flag changes. Note that Deleted/Trashed is a flag as well; this is particularly interesting if you use \fBmutt\fR with the maildir_trash option. .br \fBAll\fR (\fB--full\fR on the command line) - all of the above. This is the global default. .br \fBNone\fR (\fB--noop\fR on the command line) - don't propagate anything. Useful if you want to expunge only. .IP \fBPull\fR and \fBPush\fR are direction flags, while \fBNew\fR, \fBReNew\fR, \fBDelete\fR and \fBFlags\fR are type flags. The two flag classes make up a two-dimensional matrix (a table). Its cells are the individual actions to perform. There are two styles of asserting the cells: .br In the first style, the flags select entire rows/colums in the matrix. Only the cells which are selected both horizontally and vertically are asserted. Specifying no flags from a class is like specifying all flags from this class. For example, "\fBSync\fR\ \fBPull\fR\ \fBNew\fR\ \fBFlags\fR" will propagate new messages and flag changes from the Master to the Slave, "\fBSync\fR\ \fBNew\fR\ \fBDelete\fR" will propagate message arrivals and deletions both ways, and "\fBSync\fR\ \fBPush\fR" will propagate all changes from the Slave to the Master. .br In the second style, direction flags are concatenated with type flags; every compound flag immediately asserts a cell in the matrix. In addition to at least one compound flag, the individual flags can be used as well, but as opposed to the first style, they immediately assert all cells in their respective row/column. For example, "\fBSync\fR\ \fBPullNew\fR\ \fBPullDelete\fR\ \fBPush\fR" will propagate message arrivals and deletions from the Master to the Slave and any changes from the Slave to the Master. Note that it is not allowed to assert a cell in two ways, e.g. "\fBSync\fR\ \fBPullNew\fR\ \fBPull\fR" and "\fBSync\fR\ \fBPullNew\fR\ \fBDelete\fR\ \fBPush\fR" induce error messages. .. .TP \fBCreate\fR {\fBNone\fR|\fBMaster\fR|\fBSlave\fR|\fBBoth\fR} Automatically create missing mailboxes [on the Master/Slave]. Otherwise print an error message and skip that mailbox pair if a mailbox and the corresponding sync state does not exist. (Global default: \fBNone\fR) .. .TP \fBRemove\fR {\fBNone\fR|\fBMaster\fR|\fBSlave\fR|\fBBoth\fR} Propagate mailbox deletions [to the Master/Slave]. Otherwise print an error message and skip that mailbox pair if a mailbox does not exist but the corresponding sync state does. .br For MailDir mailboxes it is sufficient to delete the cur/ subdirectory to mark them as deleted. This ensures compatibility with \fBSyncState *\fR. .br Note that for safety, non-empty mailboxes are never deleted. .br (Global default: \fBNone\fR) .. .TP \fBExpunge\fR {\fBNone\fR|\fBMaster\fR|\fBSlave\fR|\fBBoth\fR} Permanently remove all messages [on the Master/Slave] marked for deletion. See \fBRECOMMENDATIONS\fR below. (Global default: \fBNone\fR) .. .TP \fBCopyArrivalDate\fR {\fByes\fR|\fBno\fR} Selects whether their arrival time should be propagated together with the messages. Enabling this makes sense in order to keep the time stamp based message sorting intact. Note that IMAP does not guarantee that the time stamp (termed \fBinternal date\fR) is actually the arrival time, but it is usually close enough. (Default: \fBno\fR) .. .P \fBSync\fR, \fBCreate\fR, \fBRemove\fR, \fBExpunge\fR, \fBMaxMessages\fR, and \fBCopyArrivalDate\fR can be used before any section for a global effect. The global settings are overridden by Channel-specific options, which in turn are overridden by command line switches. .. .TP \fBSyncState\fR {\fB*\fR|\fIpath\fR} Set the location of this Channel's synchronization state files. \fB*\fR means that the state should be saved in a file named .mbsyncstate in the Slave mailbox itself; this has the advantage that you needn't to care for the state file if you delete the mailbox, but it works only with Maildir mailboxes, obviously. Otherwise this is interpreted as a string to prepend to the Slave mailbox name to make up a complete path. .br This option can be used outside any section for a global effect. In this case the appended string is made up according to the pattern \fB:\fImaster\fB:\fImaster-box\fB_:\fIslave\fB:\fIslave-box\fR (see also \fBFieldDelimiter\fR below). .br (Global default: \fI~/.mbsync/\fR). .. .SS Groups .TP \fBGroup\fR \fIname\fR [\fIchannel\fR[\fB:\fIbox\fR[\fB,\fR...]]] ... Define the Group \fIname\fR, opening a section for its parameters. Note that even though Groups have an own namespace, they will "hide" Channels with the same name on the command line. .br One or more Channels can be specified on the same line. .br If you supply one or more \fIbox\fRes to a \fIchannel\fR, they will be used instead of what is specified in the Channel's Patterns. The same can be done on the command line, except that there newlines can be used as mailbox name separators as well. .. .TP \fBChannel\fR[\fBs\fR] \fIchannel\fR[\fB:\fIbox\fR[\fB,\fR...]] ... Add the specified channels to the group. This option can be specified multiple times within a Group. .. .SS Global Options .TP \fBFSync\fR \fByes\fR|\fBno\fR .br Selects whether \fBmbsync\fR performs forced flushing, which determines the level of data safety after system crashes and power outages. Disabling it is reasonably safe for file systems which are mounted with data=ordered mode. Enabling it is a wise choice for file systems mounted with data=writeback, in particular modern systems like ext4, btrfs and xfs. The performance impact on older file systems may be disproportionate. (Default: \fByes\fR) .. .TP \fBFieldDelimiter\fR \fIdelim\fR The character to use to delimit fields in the string appended to a global \fBSyncState\fR. \fBmbsync\fR prefers to use the colon, but this is incompatible with DOS/Windows file systems. This option is meaningless for \fBSyncState\fR if the latter is \fB*\fR, obviously. However, it also determines the default of \fBInfoDelimiter\fR. (Global default: \fI;\fR on Windows, \fI:\fR everywhere else) .. .TP \fBBufferLimit\fR \fIsize\fR[\fBk\fR|\fBm\fR][\fBb\fR] The per-Channel, per-direction instantaneous memory usage above which \fBmbsync\fR will refrain from using more memory. Note that this is no absolute limit, as even a single message can consume more memory than this. (Default: \fI10M\fR) .. .SH CONSOLE OUTPUT If \fBmbsync\fR's output is connected to a console, it will print progress counters by default. The output will look like this: .P .in +4 C: 1/2 B: 3/4 M: +13/13 *23/42 #0/0 S: +0/7 *0/0 #0/0 .in -4 .P This represents the cumulative progress over channels, boxes, and messages affected on master and slave, respectively. The message counts represent added messages, messages with updated flags, and trashed messages, respectively. No attempt is made to calculate the totals in advance, so they grow over time as more information is gathered. .. .SH RECOMMENDATIONS Make sure your IMAP server does not auto-expunge deleted messages - it is slow, and semantically somewhat questionable. Specifically, Gmail needs to be configured not to do it. .P By default, \fBmbsync\fR will not delete any messages - deletions are propagated by marking the messages as deleted on the remote store. Once you have verified that your setup works, you will typically want to set \fBExpunge\fR to \fBBoth\fR, so that deletions become effective. .P \fBmbsync\fR's built-in trash functionality relies on \fBmbsync\fR doing the expunging of deleted messages. This is the case when it propagates deletions of previously propagated messages, and the trash is on the target store (typically your IMAP server). .br However, when you intend \fBmbsync\fR to trash messages which were not propagated yet, the MUA must mark the messages as deleted without expunging them (e.g., \fBMutt\fR's \fBmaildir_trash\fR option). Note that most messages are propagated a long time before they are deleted, so this is a corner case you probably do not want to optimize for. This also implies that the \fBTrashNewOnly\fR and \fBTrashRemoteNew\fR options are typically not very useful. .P If your server supports auto-trashing (as Gmail does), it is probably a good idea to rely on that instead of \fBmbsync\fR's trash functionality. If you do that, and intend to synchronize the trash like other mailboxes, you should not use \fBmbsync\fR's \fBTrash\fR option at all. .P Use of the \fBTrash\fR option with M$ Exchange 2013 requires the use of \fBDisableExtension MOVE\fR due to a server bug. .P When using the more efficient default UID mapping scheme, it is important that the MUA renames files when moving them between Maildir folders. Mutt always does that, while mu4e needs to be configured to do it: .br .in +4 (setq mu4e-change-filenames-when-moving t) .in -4 .. .SH INHERENT PROBLEMS Changes done after \fBmbsync\fR has retrieved the message list will not be synchronised until the next time \fBmbsync\fR is invoked. .P Using \fBTrash\fR on IMAP Stores without the UIDPLUS extension (notably, M$ Exchange up to at least 2010) bears a race condition: messages will be lost if they are marked as deleted after the message list was retrieved but before the mailbox is expunged. There is no risk as long as the IMAP mailbox is accessed by only one client (including \fBmbsync\fR) at a time. .. .SH FILES .TP .B ~/.mbsyncrc Default configuration file .TP .B ~/.mbsync/ Directory containing synchronization state files .. .SH SEE ALSO mdconvert(1), isync(1), mutt(1), maildir(5) .P Up to date information on \fBmbsync\fR can be found at http://isync.sf.net/ .P SASL mechanisms are listed at http://www.iana.org/assignments/sasl-mechanisms/sasl-mechanisms.xhtml .. .SH AUTHORS Originally written by Michael R. Elkins, rewritten and currently maintained by Oswald Buddenhagen, contributions by Theodore Y. Ts'o. isync-1.3.0/src/tst_timers.c0000644000175000001440000000564613141404045012714 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2014 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #include "common.h" #include #include #include /* Just to satisfy the references in util.c */ int DFlags; const char *Home; typedef struct { int id; int first, other, morph_at, morph_to; time_t start; wakeup_t timer; wakeup_t morph_timer; } tst_t; static void timer_start( tst_t *timer, int to ) { printf( "starting timer %d, should expire after %d\n", timer->id, to ); time( &timer->start ); conf_wakeup( &timer->timer, to ); } static void timed_out( void *aux ) { tst_t *timer = (tst_t *)aux; printf( "timer %d expired after %d, repeat %d\n", timer->id, (int)(time( 0 ) - timer->start), timer->other ); if (timer->other >= 0) { timer_start( timer, timer->other ); } else { wipe_wakeup( &timer->timer ); wipe_wakeup( &timer->morph_timer ); free( timer ); } } static void morph_timed_out( void *aux ) { tst_t *timer = (tst_t *)aux; printf( "morphing timer %d after %d\n", timer->id, (int)(time( 0 ) - timer->start) ); timer_start( timer, timer->morph_to ); } static int nextid; int main( int argc, char **argv ) { int i; for (i = 1; i < argc; i++) { char *val = argv[i]; tst_t *timer = nfmalloc( sizeof(*timer) ); init_wakeup( &timer->timer, timed_out, timer ); init_wakeup( &timer->morph_timer, morph_timed_out, timer ); timer->id = ++nextid; timer->first = strtol( val, &val, 0 ); if (*val == '@') { timer->other = timer->first; timer->first = strtol( ++val, &val, 0 ); } else { timer->other = -1; } if (*val == ':') { timer->morph_to = strtol( ++val, &val, 0 ); if (*val != '@') goto fail; timer->morph_at = strtol( ++val, &val, 0 ); } else { timer->morph_at = -1; } if (*val) { fail: fprintf( stderr, "Fatal: syntax error in %s, use [@][:@]\n", argv[i] ); return 1; } timer_start( timer, timer->first ); if (timer->morph_at >= 0) { printf( "timer %d, should morph after %d\n", timer->id, timer->morph_at ); conf_wakeup( &timer->morph_timer, timer->morph_at ); } } main_loop(); return 0; } isync-1.3.0/src/driver.h0000644000175000001440000002512113141404045012005 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2010-2012 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #ifndef DRIVER_H #define DRIVER_H #include "config.h" typedef struct driver driver_t; #define FAIL_TEMP 0 /* Retry immediately (also: no error) */ #define FAIL_WAIT 1 /* Retry after some time (if at all) */ #define FAIL_FINAL 2 /* Don't retry until store reconfiguration */ typedef struct store_conf { struct store_conf *next; char *name; driver_t *driver; const char *path; /* should this be here? its interpretation is driver-specific */ const char *flat_delim; const char *map_inbox; const char *trash; int max_size; /* off_t is overkill */ char trash_remote_new, trash_only_new; } store_conf_t; /* For message->flags */ /* Keep the mailbox driver flag definitions in sync! */ /* The order is according to alphabetical maildir flag sort */ #define F_DRAFT (1<<0) /* Draft */ #define F_FLAGGED (1<<1) /* Flagged */ #define F_ANSWERED (1<<2) /* Replied */ #define F_SEEN (1<<3) /* Seen */ #define F_DELETED (1<<4) /* Trashed */ #define NUM_FLAGS 5 /* For message->status */ #define M_RECENT (1<<0) /* unsyncable flag; maildir_* depend on this being 1<<0 */ #define M_DEAD (1<<1) /* expunged */ #define M_FLAGS (1<<2) /* flags fetched */ #define TUIDL 12 typedef struct message { struct message *next; struct sync_rec *srec; char *msgid; /* owned */ /* string_list_t *keywords; */ int size; /* zero implies "not fetched" */ uint uid; uchar flags, status; char tuid[TUIDL]; } message_t; /* For opts, both in store and driver_t->select() */ #define OPEN_OLD (1<<0) #define OPEN_NEW (1<<1) #define OPEN_FLAGS (1<<2) #define OPEN_OLD_SIZE (1<<3) #define OPEN_NEW_SIZE (1<<4) #define OPEN_EXPUNGE (1<<5) #define OPEN_SETFLAGS (1<<6) #define OPEN_APPEND (1<<7) #define OPEN_FIND (1<<8) #define OPEN_OLD_IDS (1<<9) #define UIDVAL_BAD ((uint)-1) typedef struct store { struct store *next; driver_t *driver; store_conf_t *conf; /* foreign */ } store_t; typedef struct { char *data; int len; time_t date; uchar flags; } msg_data_t; #define DRV_OK 0 /* Message went missing, or mailbox is full, etc. */ #define DRV_MSG_BAD 1 /* Something is wrong with the current mailbox - probably it is somehow inaccessible. */ #define DRV_BOX_BAD 2 /* Failed to connect store. */ #define DRV_STORE_BAD 3 /* The command has been cancel()ed or cancel_store()d. */ #define DRV_CANCELED 4 /* All memory belongs to the driver's user, unless stated otherwise. */ /* This flag says that the driver CAN store messages with CRLFs, not that it must. The lack of it OTOH implies that it CANNOT, and as CRLF is the canonical format, we convert. */ #define DRV_CRLF 1 /* This flag says that the driver will act upon (DFlags & VERBOSE). */ #define DRV_VERBOSE 2 #define LIST_INBOX 1 #define LIST_PATH 2 #define LIST_PATH_MAYBE 4 #define xint int // For auto-generation of appropriate printf() formats. struct driver { /* Return driver capabilities. */ xint (*get_caps)( store_t *ctx ); /* Parse configuration. */ int (*parse_store)( conffile_t *cfg, store_conf_t **storep ); /* Close remaining server connections. All stores must be discarded first. */ void (*cleanup)( void ); /* Allocate a store with the given configuration. This is expected to * return quickly, and must not fail. */ store_t *(*alloc_store)( store_conf_t *conf, const char *label ); /* When this callback is invoked (at most once per store), the store is fubar; * call cancel_store() to dispose of it. */ void (*set_bad_callback)( store_t *ctx, void (*cb)( void *aux ), void *aux ); /* Open/connect the store. This may recycle existing server connections. */ void (*connect_store)( store_t *ctx, void (*cb)( int sts, void *aux ), void *aux ); /* Discard the store. Underlying server connection may be kept alive. */ void (*free_store)( store_t *ctx ); /* Discard the store after a bad_callback. The server connections will be closed. * Pending commands will have their callbacks synchronously invoked with DRV_CANCELED. */ void (*cancel_store)( store_t *ctx ); /* List the mailboxes in this store. Flags are ORed LIST_* values. * The returned box list remains owned by the driver. */ void (*list_store)( store_t *ctx, int flags, void (*cb)( int sts, string_list_t *boxes, void *aux ), void *aux ); /* Invoked before open_box(), this informs the driver which box is to be opened. */ int (*select_box)( store_t *ctx, const char *name ); /* Get the selected box' on-disk path, if applicable, null otherwise. */ const char *(*get_box_path)( store_t *ctx ); /* Create the selected mailbox. */ void (*create_box)( store_t *ctx, void (*cb)( int sts, void *aux ), void *aux ); /* Open the selected mailbox. * Note that this should not directly complain about failure to open. */ void (*open_box)( store_t *ctx, void (*cb)( int sts, int uidvalidity, void *aux ), void *aux ); /* Return the minimal UID the next stored message will have. */ int (*get_uidnext)( store_t *ctx ); /* Confirm that the open mailbox is empty. */ int (*confirm_box_empty)( store_t *ctx ); /* Delete the open mailbox. The mailbox is expected to be empty. * Subfolders of the mailbox are *not* deleted. * Some artifacts of the mailbox may remain, but they won't be * recognized as a mailbox any more. */ void (*delete_box)( store_t *ctx, void (*cb)( int sts, void *aux ), void *aux ); /* Remove the last artifacts of the open mailbox, as far as possible. */ int (*finish_delete_box)( store_t *ctx ); /* Invoked before load_box(), this informs the driver which operations (OP_*) * will be performed on the mailbox. The driver may extend the set by implicitly * needed or available operations. Returns this possibly extended set. */ xint (*prepare_load_box)( store_t *ctx, xint opts ); /* Load the message attributes needed to perform the requested operations. * Consider only messages with UIDs between minuid and maxuid (inclusive) * and those named in the excs array (smaller than minuid). * The driver takes ownership of the excs array. * Messages starting with newuid need to have the TUID populated when OPEN_FIND is set. * Messages up to seenuid need to have the Message-Id populated when OPEN_OLD_IDS is set. * Messages up to seenuid need to have the size populated when OPEN_OLD_SIZE is set; * likewise messages above seenuid when OPEN_NEW_SIZE is set. * The returned message list remains owned by the driver. */ void (*load_box)( store_t *ctx, uint minuid, uint maxuid, uint newuid, uint seenuid, uint_array_t excs, void (*cb)( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ), void *aux ); /* Fetch the contents and flags of the given message from the current mailbox. */ void (*fetch_msg)( store_t *ctx, message_t *msg, msg_data_t *data, void (*cb)( int sts, void *aux ), void *aux ); /* Store the given message to either the current mailbox or the trash folder. * If the new copy's UID can be immediately determined, return it, otherwise 0. */ void (*store_msg)( store_t *ctx, msg_data_t *data, int to_trash, void (*cb)( int sts, uint uid, void *aux ), void *aux ); /* Index the messages which have newly appeared in the mailbox, including their * temporary UID headers. This is needed if store_msg() does not guarantee returning * a UID; otherwise the driver needs to implement only the OPEN_FIND flag. * The returned message list remains owned by the driver. */ void (*find_new_msgs)( store_t *ctx, uint newuid, void (*cb)( int sts, message_t *msgs, void *aux ), void *aux ); /* Add/remove the named flags to/from the given message. The message may be either * a pre-fetched one (in which case the in-memory representation is updated), * or it may be identifed by UID only. The operation may be delayed until commit() * is called. */ void (*set_msg_flags)( store_t *ctx, message_t *msg, uint uid, int add, int del, /* msg can be null, therefore uid as a fallback */ void (*cb)( int sts, void *aux ), void *aux ); /* Move the given message from the current mailbox to the trash folder. * This may expunge the original message immediately, but it needn't to. */ void (*trash_msg)( store_t *ctx, message_t *msg, /* This may expunge the original message immediately, but it needn't to */ void (*cb)( int sts, void *aux ), void *aux ); /* Expunge deleted messages from the current mailbox and close it. * There is no need to explicitly close a mailbox if no expunge is needed. */ void (*close_box)( store_t *ctx, /* IMAP-style: expunge inclusive */ void (*cb)( int sts, void *aux ), void *aux ); /* Cancel queued commands which are not in flight yet; they will have their * callbacks invoked with DRV_CANCELED. Afterwards, wait for the completion of * the in-flight commands. If the store is canceled before this command completes, * the callback will *not* be invoked. */ void (*cancel_cmds)( store_t *ctx, void (*cb)( void *aux ), void *aux ); /* Commit any pending set_msg_flags() commands. */ void (*commit_cmds)( store_t *ctx ); /* Get approximate amount of memory occupied by the driver. */ int (*get_memory_usage)( store_t *ctx ); /* Get the FAIL_* state of the driver. */ int (*get_fail_state)( store_conf_t *conf ); }; void free_generic_messages( message_t * ); void parse_generic_store( store_conf_t *store, conffile_t *cfg ); store_t *proxy_alloc_store( store_t *real_ctx, const char *label ); #define N_DRIVERS 2 extern driver_t *drivers[N_DRIVERS]; extern driver_t maildir_driver, imap_driver, proxy_driver; #endif isync-1.3.0/src/Makefile.am0000644000175000001440000000170313141404045012375 00000000000000if with_compat compat_dir = compat endif SUBDIRS = $(compat_dir) mbsync_SOURCES = main.c sync.c config.c util.c socket.c driver.c drv_imap.c drv_maildir.c drv_proxy.c mbsync_LDADD = $(DB_LIBS) $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS) noinst_HEADERS = common.h config.h driver.h sync.h socket.h drv_proxy.$(OBJEXT): drv_proxy.inc drv_proxy.inc: $(srcdir)/driver.h $(srcdir)/drv_proxy.c $(srcdir)/drv_proxy_gen.pl perl $(srcdir)/drv_proxy_gen.pl $(srcdir)/driver.h $(srcdir)/drv_proxy.c drv_proxy.inc mdconvert_SOURCES = mdconvert.c mdconvert_LDADD = $(DB_LIBS) if with_mdconvert mdconvert_prog = mdconvert mdconvert_man = mdconvert.1 endif EXTRA_PROGRAMS = tst_timers tst_timers_SOURCES = tst_timers.c util.c bin_PROGRAMS = mbsync $(mdconvert_prog) man_MANS = mbsync.1 $(mdconvert_man) exampledir = $(docdir)/examples example_DATA = mbsyncrc.sample EXTRA_DIST = drv_proxy_gen.pl run-tests.pl $(example_DATA) $(man_MANS) CLEANFILES = drv_proxy.inc isync-1.3.0/src/drv_maildir.c0000644000175000001440000014674113164125071013021 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2010-2013 Oswald Buddenhagen * Copyright (C) 2004 Theodore Y. Ts'o * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #include "driver.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(_POSIX_SYNCHRONIZED_IO) || _POSIX_SYNCHRONIZED_IO <= 0 # define fdatasync fsync #endif #ifdef USE_DB #include #endif /* USE_DB */ #define SUB_UNSET 0 #define SUB_VERBATIM 1 #define SUB_MAILDIRPP 2 #define SUB_LEGACY 3 typedef struct { store_conf_t gen; char *inbox; #ifdef USE_DB int alt_map; #endif /* USE_DB */ char info_delimiter; char sub_style; char failed; char *info_prefix, *info_stop; /* precalculated from info_delimiter */ } maildir_store_conf_t; typedef struct { message_t gen; char *base; } maildir_message_t; typedef struct { store_t gen; uint opts; int uvfd, uvok, is_inbox, fresh[3]; uint minuid, maxuid, newuid, seenuid, uidvalidity, nuid; uint_array_t excs; char *path; /* own */ char *trash; #ifdef USE_DB DB *db; char *usedb; #endif /* USE_DB */ string_list_t *boxes; // _list results char listed; // was _list already run with these flags? // note that the message counts do _not_ reflect stats from msgs, // but mailbox totals. also, don't trust them beyond the initial load. int total_msgs, recent_msgs; message_t *msgs; wakeup_t lcktmr; void (*bad_callback)( void *aux ); void *bad_callback_aux; } maildir_store_t; #ifdef USE_DB static DBT key, value; /* no need to be reentrant, and this saves lots of memset()s */ #endif /* USE_DB */ static struct flock lck; static int MaildirCount; static void ATTR_PRINTFLIKE(1, 2) debug( const char *msg, ... ) { va_list va; va_start( va, msg ); vdebug( DEBUG_SYNC, msg, va ); va_end( va ); } static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' }; static uchar maildir_parse_flags( const char *info_prefix, const char *base ) { const char *s; uint i; uchar flags; flags = 0; if ((s = strstr( base, info_prefix ))) for (s += 3, i = 0; i < as(Flags); i++) if (strchr( s, Flags[i] )) flags |= (1 << i); return flags; } static int maildir_ensure_path( maildir_store_conf_t *conf ) { if (!conf->gen.path) { error( "Maildir error: store '%s' has no Path\n", conf->gen.name ); conf->failed = FAIL_FINAL; return -1; } return 0; } /* Subdirs of INBOX include a leading slash. */ /* Path includes a trailing slash, Inbox does not. */ static char * maildir_join_path( maildir_store_conf_t *conf, int in_inbox, const char *box ) { char *out, *p; const char *prefix; int pl, bl, n; char c; if (in_inbox || conf->sub_style == SUB_MAILDIRPP) { prefix = conf->inbox; } else { if (maildir_ensure_path( conf ) < 0) return 0; prefix = conf->gen.path; } pl = strlen( prefix ); for (bl = 0, n = 0; (c = box[bl]); bl++) if (c == '/') { if (conf->sub_style == SUB_UNSET) { error( "Maildir error: accessing subfolder '%s', but store '%s' does not specify SubFolders style\n", box, conf->gen.name ); return 0; } n++; } else if (c == '.' && conf->sub_style == SUB_MAILDIRPP) { error( "Maildir error: store '%s', folder '%s': SubFolders style Maildir++ does not support dots in mailbox names\n", conf->gen.name, box ); return 0; } switch (conf->sub_style) { case SUB_VERBATIM: n = 0; break; case SUB_MAILDIRPP: n = 2; break; default: /* SUB_LEGACY and SUB_UNSET */ break; } out = nfmalloc( pl + bl + n + 1 ); memcpy( out, prefix, pl ); p = out + pl; if (conf->sub_style == SUB_MAILDIRPP) { *p++ = '/'; *p++ = '.'; } while ((c = *box++)) { if (c == '/') { switch (conf->sub_style) { case SUB_VERBATIM: *p++ = c; break; case SUB_LEGACY: *p++ = c; FALLTHROUGH default: /* SUB_MAILDIRPP */ *p++ = '.'; break; } } else { *p++ = c; } } *p = 0; return out; } static int maildir_validate_path( maildir_store_conf_t *conf ) { struct stat st; if (stat( conf->gen.path, &st ) || !S_ISDIR(st.st_mode)) { error( "Maildir error: cannot open store '%s'\n", conf->gen.path ); conf->failed = FAIL_FINAL; return -1; } return 0; } static void lcktmr_timeout( void *aux ); static store_t * maildir_alloc_store( store_conf_t *gconf, const char *label ATTR_UNUSED ) { maildir_store_t *ctx; ctx = nfcalloc( sizeof(*ctx) ); ctx->gen.driver = &maildir_driver; ctx->gen.conf = gconf; ctx->uvfd = -1; init_wakeup( &ctx->lcktmr, lcktmr_timeout, ctx ); return &ctx->gen; } static void maildir_connect_store( store_t *gctx, void (*cb)( int sts, void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; maildir_store_conf_t *conf = (maildir_store_conf_t *)ctx->gen.conf; if (conf->gen.path && maildir_validate_path( conf ) < 0) { cb( DRV_STORE_BAD, aux ); return; } if (conf->gen.trash && !(ctx->trash = maildir_join_path( conf, 0, conf->gen.trash ))) { cb( DRV_STORE_BAD, aux ); return; } cb( DRV_OK, aux ); } static void free_maildir_messages( message_t *msg ) { message_t *tmsg; for (; (tmsg = msg); msg = tmsg) { tmsg = msg->next; free( ((maildir_message_t *)msg)->base ); free( msg ); } } static void maildir_cleanup( store_t *gctx ) { maildir_store_t *ctx = (maildir_store_t *)gctx; free_maildir_messages( ctx->msgs ); #ifdef USE_DB if (ctx->db) ctx->db->close( ctx->db, 0 ); free( ctx->usedb ); #endif /* USE_DB */ free( ctx->path ); free( ctx->excs.data ); if (ctx->uvfd >= 0) close( ctx->uvfd ); conf_wakeup( &ctx->lcktmr, -1 ); } static void maildir_free_store( store_t *gctx ) { maildir_store_t *ctx = (maildir_store_t *)gctx; maildir_cleanup( gctx ); wipe_wakeup( &ctx->lcktmr ); free( ctx->trash ); free_string_list( ctx->boxes ); free( gctx ); } static void maildir_cleanup_drv( void ) { } static void maildir_set_bad_callback( store_t *gctx, void (*cb)( void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; ctx->bad_callback = cb; ctx->bad_callback_aux = aux; } static void maildir_invoke_bad_callback( maildir_store_t *ctx ) { ctx->bad_callback( ctx->bad_callback_aux ); } static int maildir_list_maildirpp( maildir_store_t *ctx, int flags, const char *inbox ) { DIR *dir; struct dirent *de; int warned = 0; struct stat st; if (ctx->listed & LIST_PATH) // Implies LIST_INBOX return 0; if (!(ctx->listed & LIST_INBOX)) add_string_list( &ctx->boxes, "INBOX" ); char path[_POSIX_PATH_MAX]; int pathLen = nfsnprintf( path, _POSIX_PATH_MAX, "%s/", inbox ); if (!(dir = opendir( path ))) { if (errno == ENOENT || errno == ENOTDIR) return 0; sys_error( "Maildir error: cannot list %s", path ); return -1; } while ((de = readdir( dir ))) { const char *ent = de->d_name; if (*ent++ != '.' || !*ent) continue; char name[_POSIX_PATH_MAX]; char *effName = name; if (*ent == '.') { if (ctx->listed & LIST_INBOX) continue; if (!*++ent) continue; // The Maildir++ Inbox is technically not under Path (as there is none), so // "*" would never match INBOX*, which is rather unintuitive. Matching INBOX* // implicitly instead makes it consistent with an IMAP Store with an empty Path. } else { if (!(flags & (LIST_PATH | LIST_PATH_MAYBE))) continue; if (starts_with( ent, -1, "INBOX", 5 ) && (!ent[5] || ent[5] == '.')) { if (!warned) { warned = 1; path[pathLen] = 0; warn( "Maildir warning: ignoring INBOX in %s\n", path ); } continue; } effName += 6; } nfsnprintf( path + pathLen, _POSIX_PATH_MAX - pathLen, "%s/cur", de->d_name ); if (!stat( path, &st ) && S_ISDIR(st.st_mode)) { int nl = nfsnprintf( name, _POSIX_PATH_MAX, "INBOX/%s", ent ); for (int i = 6; i < nl; i++) { if (name[i] == '.') name[i] = '/'; } add_string_list( &ctx->boxes, effName ); } } closedir (dir); if (flags & (LIST_PATH | LIST_PATH_MAYBE)) ctx->listed |= LIST_PATH; ctx->listed |= LIST_INBOX; return 0; } static int maildir_list_inbox( maildir_store_t *ctx, int flags, const char *basePath ); static int maildir_list_path( maildir_store_t *ctx, int flags, const char *inbox ); static int maildir_list_recurse( maildir_store_t *ctx, int isBox, int flags, const char *inbox, int inboxLen, const char *basePath, int basePathLen, char *path, int pathLen, char *name, int nameLen ) { DIR *dir; int style = ((maildir_store_conf_t *)ctx->gen.conf)->sub_style; int pl, nl; struct dirent *de; struct stat st; if (!(dir = opendir( path ))) { if (isBox && (errno == ENOENT || errno == ENOTDIR)) return 0; sys_error( "Maildir error: cannot list %s", path ); return -1; } if (isBox > 1 && style == SUB_UNSET) { error( "Maildir error: found subfolder '%.*s', but store '%s' does not specify SubFolders style\n", nameLen - 1, name, ctx->gen.conf->name ); closedir( dir ); return -1; } while ((de = readdir( dir ))) { const char *ent = de->d_name; if (ent[0] == '.' && (!ent[1] || (ent[1] == '.' && !ent[2]))) continue; pl = nfsnprintf( path + pathLen, _POSIX_PATH_MAX - pathLen, "%s", ent ); if (pl == 3 && (!memcmp( ent, "cur", 3 ) || !memcmp( ent, "new", 3 ) || !memcmp( ent, "tmp", 3 ))) continue; pl += pathLen; if (inbox && equals( path, pl, inbox, inboxLen )) { // Inbox nested into Path. if (maildir_list_inbox( ctx, flags, 0 ) < 0) { closedir( dir ); return -1; } } else if (basePath && equals( path, pl, basePath, basePathLen )) { // Path nested into Inbox. if (maildir_list_path( ctx, flags, 0 ) < 0) { closedir( dir ); return -1; } } else { if (style == SUB_LEGACY) { if (*ent == '.') { if (!isBox) continue; ent++; } else { if (isBox) continue; } } if (!nameLen && equals( ent, -1, "INBOX", 5 )) { path[pathLen] = 0; warn( "Maildir warning: ignoring INBOX in %s\n", path ); continue; } nl = nameLen + nfsnprintf( name + nameLen, _POSIX_PATH_MAX - nameLen, "%s", ent ); path[pl++] = '/'; nfsnprintf( path + pl, _POSIX_PATH_MAX - pl, "cur" ); if (!stat( path, &st ) && S_ISDIR(st.st_mode)) add_string_list( &ctx->boxes, name ); path[pl] = 0; name[nl++] = '/'; if (maildir_list_recurse( ctx, isBox + 1, flags, inbox, inboxLen, basePath, basePathLen, path, pl, name, nl ) < 0) { closedir( dir ); return -1; } } } closedir (dir); return 0; } static int maildir_list_inbox( maildir_store_t *ctx, int flags, const char *basePath ) { char path[_POSIX_PATH_MAX], name[_POSIX_PATH_MAX]; if (ctx->listed & LIST_INBOX) return 0; ctx->listed |= LIST_INBOX; add_string_list( &ctx->boxes, "INBOX" ); return maildir_list_recurse( ctx, 1, flags, 0, 0, basePath, basePath ? strlen( basePath ) - 1 : 0, path, nfsnprintf( path, _POSIX_PATH_MAX, "%s/", ((maildir_store_conf_t *)ctx->gen.conf)->inbox ), name, nfsnprintf( name, _POSIX_PATH_MAX, "INBOX/" ) ); } static int maildir_list_path( maildir_store_t *ctx, int flags, const char *inbox ) { char path[_POSIX_PATH_MAX], name[_POSIX_PATH_MAX]; if (ctx->listed & LIST_PATH) return 0; ctx->listed |= LIST_PATH; if (maildir_ensure_path( (maildir_store_conf_t *)ctx->gen.conf ) < 0) return -1; return maildir_list_recurse( ctx, 0, flags, inbox, inbox ? strlen( inbox ) : 0, 0, 0, path, nfsnprintf( path, _POSIX_PATH_MAX, "%s", ctx->gen.conf->path ), name, 0 ); } static void maildir_list_store( store_t *gctx, int flags, void (*cb)( int sts, string_list_t *boxes, void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; maildir_store_conf_t *conf = (maildir_store_conf_t *)gctx->conf; if (conf->sub_style == SUB_MAILDIRPP ? maildir_list_maildirpp( ctx, flags, conf->inbox ) < 0 : ((((flags & LIST_PATH) || ((flags & LIST_PATH_MAYBE) && gctx->conf->path)) && maildir_list_path( ctx, flags, conf->inbox ) < 0) || ((flags & LIST_INBOX) && maildir_list_inbox( ctx, flags, gctx->conf->path ) < 0))) { maildir_invoke_bad_callback( ctx ); cb( DRV_CANCELED, 0, aux ); } else { cb( DRV_OK, ctx->boxes, aux ); } } static const char *subdirs[] = { "cur", "new", "tmp" }; typedef struct { char *base; char *msgid; int size; uint uid; uchar recent; char tuid[TUIDL]; } msg_t; DEFINE_ARRAY_TYPE(msg_t) static void maildir_free_scan( msg_t_array_alloc_t *msglist ) { int i; if (msglist->array.data) { for (i = 0; i < msglist->array.size; i++) free( msglist->array.data[i].base ); free( msglist->array.data ); } } #define _24_HOURS (3600 * 24) static int maildir_clear_tmp( char *buf, int bufsz, int bl ) { DIR *dirp; struct dirent *entry; time_t now; struct stat st; memcpy( buf + bl, "tmp/", 5 ); bl += 4; if (!(dirp = opendir( buf ))) { sys_error( "Maildir error: cannot list %s", buf ); return DRV_BOX_BAD; } time( &now ); while ((entry = readdir( dirp ))) { nfsnprintf( buf + bl, bufsz - bl, "%s", entry->d_name ); if (stat( buf, &st )) { if (errno != ENOENT) sys_error( "Maildir error: cannot access %s", buf ); } else if (S_ISREG(st.st_mode) && now - st.st_ctime >= _24_HOURS) { /* This should happen infrequently enough that it won't be * bothersome to the user to display when it occurs. */ notice( "Maildir notice: removing stale file %s\n", buf ); if (unlink( buf ) && errno != ENOENT) sys_error( "Maildir error: cannot remove %s", buf ); } } closedir( dirp ); return DRV_OK; } static int make_box_dir( char *buf, int bl ) { char *p; if (!mkdir( buf, 0700 ) || errno == EEXIST) return 0; p = memrchr( buf, '/', bl - 1 ); *p = 0; if (make_box_dir( buf, (int)(p - buf) )) return -1; *p = '/'; return mkdir( buf, 0700 ); } static int maildir_validate( const char *box, int create, maildir_store_t *ctx ) { int i, bl, ret; struct stat st; char buf[_POSIX_PATH_MAX]; bl = nfsnprintf( buf, sizeof(buf) - 4, "%s/", box ); if (stat( buf, &st )) { if (errno != ENOENT) { sys_error( "Maildir error: cannot access mailbox '%s'", box ); return DRV_BOX_BAD; } if (!create) return DRV_BOX_BAD; if (make_box_dir( buf, bl )) { sys_error( "Maildir error: cannot create mailbox '%s'", box ); ((maildir_store_conf_t *)ctx->gen.conf)->failed = FAIL_FINAL; maildir_invoke_bad_callback( ctx ); return DRV_CANCELED; } } else if (!S_ISDIR(st.st_mode)) { notdir: error( "Maildir error: '%s' is no valid mailbox\n", box ); return DRV_BOX_BAD; } for (i = 0; i < 3; i++) { memcpy( buf + bl, subdirs[i], 4 ); if (stat( buf, &st )) { /* We always create new/ and tmp/ if they are missing. cur/ is the presence indicator. */ if (!i && !create) return DRV_BOX_BAD; if (mkdir( buf, 0700 )) { sys_error( "Maildir error: cannot create directory %s", buf ); return DRV_BOX_BAD; } ctx->fresh[i] = 1; } else if (!S_ISDIR(st.st_mode)) { goto notdir; } else { if (i == 2) { if ((ret = maildir_clear_tmp( buf, sizeof(buf), bl )) != DRV_OK) return ret; } } } return DRV_OK; } #ifdef USE_DB static void make_key( const char *info_stop, DBT *tkey, char *name ) { char *u = strpbrk( name, info_stop ); tkey->data = name; tkey->size = u ? (size_t)(u - name) : strlen( name ); } #endif /* USE_DB */ static int maildir_store_uidval( maildir_store_t *ctx ) { int n; #ifdef USE_DB int ret; uint uv[2]; #endif char buf[128]; #ifdef USE_DB if (ctx->db) { key.data = (void *)"UIDVALIDITY"; key.size = 11; uv[0] = ctx->uidvalidity; uv[1] = ctx->nuid; value.data = uv; value.size = sizeof(uv); if ((ret = ctx->db->put( ctx->db, 0, &key, &value, 0 ))) { ctx->db->err( ctx->db, ret, "Maildir error: db->put()" ); return DRV_BOX_BAD; } if ((ret = ctx->db->sync( ctx->db, 0 ))) { ctx->db->err( ctx->db, ret, "Maildir error: db->sync()" ); return DRV_BOX_BAD; } } else #endif /* USE_DB */ { n = sprintf( buf, "%u\n%u\n", ctx->uidvalidity, ctx->nuid ); lseek( ctx->uvfd, 0, SEEK_SET ); if (write( ctx->uvfd, buf, n ) != n || ftruncate( ctx->uvfd, n ) || (UseFSync && fdatasync( ctx->uvfd ))) { error( "Maildir error: cannot write UIDVALIDITY.\n" ); return DRV_BOX_BAD; } } conf_wakeup( &ctx->lcktmr, 2 ); return DRV_OK; } static int maildir_init_uidval( maildir_store_t *ctx ) { ctx->uidvalidity = time( 0 ); ctx->nuid = 0; ctx->uvok = 0; #ifdef USE_DB if (ctx->db) { u_int32_t count; ctx->db->truncate( ctx->db, 0, &count, 0 ); } #endif /* USE_DB */ return maildir_store_uidval( ctx ); } static int maildir_init_uidval_new( maildir_store_t *ctx ) { notice( "Maildir notice: no UIDVALIDITY, creating new.\n" ); return maildir_init_uidval( ctx ); } static int maildir_uidval_lock( maildir_store_t *ctx ) { int n; #ifdef USE_DB int ret; struct stat st; #endif char buf[128]; if (pending_wakeup( &ctx->lcktmr )) { /* The unlock timer is active, so we are obviously already locked. */ return DRV_OK; } /* This (theoretically) works over NFS. Let's hope nobody else did the same in the opposite order, as we'd deadlock then. */ #if SEEK_SET != 0 lck.l_whence = SEEK_SET; #endif lck.l_type = F_WRLCK; if (fcntl( ctx->uvfd, F_SETLKW, &lck )) { error( "Maildir error: cannot fcntl lock UIDVALIDITY.\n" ); return DRV_BOX_BAD; } #ifdef USE_DB if (ctx->usedb) { if (fstat( ctx->uvfd, &st )) { sys_error( "Maildir error: cannot fstat UID database" ); return DRV_BOX_BAD; } if (db_create( &ctx->db, 0, 0 )) { fputs( "Maildir error: db_create() failed\n", stderr ); return DRV_BOX_BAD; } if ((ret = (ctx->db->open)( ctx->db, 0, ctx->usedb, 0, DB_HASH, st.st_size ? 0 : DB_CREATE | DB_TRUNCATE, 0 ))) { ctx->db->err( ctx->db, ret, "Maildir error: db->open(%s)", ctx->usedb ); return DRV_BOX_BAD; } key.data = (void *)"UIDVALIDITY"; key.size = 11; if ((ret = ctx->db->get( ctx->db, 0, &key, &value, 0 ))) { if (ret != DB_NOTFOUND) { ctx->db->err( ctx->db, ret, "Maildir error: db->get()" ); return DRV_BOX_BAD; } return maildir_init_uidval_new( ctx ); } ctx->uidvalidity = ((uint *)value.data)[0]; ctx->nuid = ((uint *)value.data)[1]; } else #endif { lseek( ctx->uvfd, 0, SEEK_SET ); if ((n = read( ctx->uvfd, buf, sizeof(buf) - 1 )) <= 0 || (buf[n] = 0, sscanf( buf, "%u\n%u", &ctx->uidvalidity, &ctx->nuid ) != 2)) { #if 1 /* In a generic driver, resetting the UID validity would be the right thing. * But this would mess up the sync state completely. So better bail out and * give the user a chance to fix the mailbox. */ if (n) { error( "Maildir error: cannot read UIDVALIDITY.\n" ); return DRV_BOX_BAD; } #endif return maildir_init_uidval_new( ctx ); } } ctx->uvok = 1; conf_wakeup( &ctx->lcktmr, 2 ); return DRV_OK; } static void maildir_uidval_unlock( maildir_store_t *ctx ) { #ifdef USE_DB if (ctx->db) { ctx->db->close( ctx->db, 0 ); ctx->db = 0; } #endif /* USE_DB */ lck.l_type = F_UNLCK; fcntl( ctx->uvfd, F_SETLK, &lck ); } static void lcktmr_timeout( void *aux ) { maildir_uidval_unlock( (maildir_store_t *)aux ); } static int maildir_obtain_uid( maildir_store_t *ctx, uint *uid ) { int ret; if ((ret = maildir_uidval_lock( ctx )) != DRV_OK) return ret; *uid = ++ctx->nuid; return maildir_store_uidval( ctx ); } #ifdef USE_DB static int maildir_set_uid( maildir_store_t *ctx, const char *name, uint *uid ) { int ret; if ((ret = maildir_uidval_lock( ctx )) != DRV_OK) return ret; *uid = ++ctx->nuid; make_key( ((maildir_store_conf_t *)ctx->gen.conf)->info_stop, &key, (char *)name ); value.data = uid; value.size = sizeof(*uid); if ((ret = ctx->db->put( ctx->db, 0, &key, &value, 0 ))) { ctx->db->err( ctx->db, ret, "Maildir error: db->put()" ); return DRV_BOX_BAD; } return maildir_store_uidval( ctx ); } #endif static int maildir_compare( const void *l, const void *r ) { msg_t *lm = (msg_t *)l, *rm = (msg_t *)r; char *ldot, *rdot, *ldot2, *rdot2, *lseq, *rseq; int ret, llen, rlen; if ((ret = lm->uid - rm->uid)) return ret; /* No UID, so sort by arrival date. We should not do this, but we rely on the suggested unique file name scheme - we have no choice. */ /* The first field are always the seconds. Alphabetical sort should be faster than numeric. */ if (!(ldot = strchr( lm->base, '.' )) || !(rdot = strchr( rm->base, '.' ))) goto stronly; /* Should never happen ... */ llen = ldot - lm->base, rlen = rdot - rm->base; /* The shorter number is smaller. Really. This won't trigger with any mail created after Sep 9 2001 anyway. */ if ((ret = llen - rlen)) return ret; if ((ret = memcmp( lm->base, rm->base, llen ))) return ret; ldot++, rdot++; if ((llen = strtol( ldot, &ldot2, 10 ))) { if (!(rlen = strtol( rdot, &rdot2, 10 ))) goto stronly; /* Comparing apples to oranges ... */ /* Classical PID specs */ if ((ret = llen - rlen)) { retpid: /* Handle PID wraparound. This works only on systems where PIDs are not reused too fast */ if (ret > 20000 || ret < -20000) ret = -ret; return ret; } return (*ldot2 != '_' ? 0 : atoi( ldot2 + 1 )) - (*rdot2 != '_' ? 0 : atoi( rdot2 + 1 )); } if (!(ldot2 = strchr( ldot, '.' )) || !(rdot2 = strchr( rdot, '.' ))) goto stronly; /* Should never happen ... */ llen = ldot2 - ldot, rlen = rdot2 - rdot; if (((lseq = memchr( ldot, '#', llen )) && (rseq = memchr( rdot, '#', rlen ))) || ((lseq = memchr( ldot, 'M', llen )) && (rseq = memchr( rdot, 'M', rlen )))) return atoi( lseq + 1 ) - atoi( rseq + 1 ); if ((lseq = memchr( ldot, 'P', llen )) && (rseq = memchr( rdot, 'P', rlen ))) { if ((ret = atoi( lseq + 1 ) - atoi( rseq + 1 ))) goto retpid; if ((lseq = memchr( ldot, 'Q', llen )) && (rseq = memchr( rdot, 'Q', rlen ))) return atoi( lseq + 1 ) - atoi( rseq + 1 ); } stronly: /* Fall-back, so the sort order is defined at all */ return strcmp( lm->base, rm->base ); } static int maildir_scan( maildir_store_t *ctx, msg_t_array_alloc_t *msglist ) { maildir_store_conf_t *conf = (maildir_store_conf_t *)ctx->gen.conf; DIR *d; FILE *f; struct dirent *e; const char *u, *ru; #ifdef USE_DB DB *tdb; DBC *dbc; #endif /* USE_DB */ msg_t *entry; int i, bl, fnl, ret; uint uid; time_t now, stamps[2]; struct stat st; char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX]; again: ARRAY_INIT( msglist ); ctx->total_msgs = ctx->recent_msgs = 0; if (ctx->uvok || ctx->maxuid == UINT_MAX) { #ifdef USE_DB if (ctx->usedb) { if (db_create( &tdb, 0, 0 )) { fputs( "Maildir error: db_create() failed\n", stderr ); return DRV_BOX_BAD; } if ((tdb->open)( tdb, 0, 0, 0, DB_HASH, DB_CREATE, 0 )) { fputs( "Maildir error: tdb->open() failed\n", stderr ); bork: tdb->close( tdb, 0 ); return DRV_BOX_BAD; } } #endif /* USE_DB */ bl = nfsnprintf( buf, sizeof(buf) - 4, "%s/", ctx->path ); restat: now = time( 0 ); for (i = 0; i < 2; i++) { memcpy( buf + bl, subdirs[i], 4 ); if (stat( buf, &st )) { sys_error( "Maildir error: cannot stat %s", buf ); goto dfail; } if (st.st_mtime == now && !(DFlags & ZERODELAY) && !ctx->fresh[i]) { /* If the modification happened during this second, we wouldn't be able to * tell if there were further modifications during this second. So wait. * This has the nice side effect that we wait for "batches" of changes to * complete. On the downside, it can potentially block indefinitely. */ notice( "Maildir notice: sleeping due to recent directory modification.\n" ); sleep( 1 ); /* FIXME: should make this async */ goto restat; } stamps[i] = st.st_mtime; } for (i = 0; i < 2; i++) { memcpy( buf + bl, subdirs[i], 4 ); if (!(d = opendir( buf ))) { sys_error( "Maildir error: cannot list %s", buf ); rfail: maildir_free_scan( msglist ); dfail: #ifdef USE_DB if (ctx->usedb) tdb->close( tdb, 0 ); #endif /* USE_DB */ return DRV_BOX_BAD; } while ((e = readdir( d ))) { if (*e->d_name == '.') continue; ctx->total_msgs++; ctx->recent_msgs += i; #ifdef USE_DB if (ctx->usedb) { if (maildir_uidval_lock( ctx ) != DRV_OK) goto mbork; make_key( conf->info_stop, &key, e->d_name ); if ((ret = ctx->db->get( ctx->db, 0, &key, &value, 0 ))) { if (ret != DB_NOTFOUND) { ctx->db->err( ctx->db, ret, "Maildir error: db->get()" ); mbork: maildir_free_scan( msglist ); closedir( d ); goto bork; } uid = UINT_MAX; } else { value.size = 0; if ((ret = tdb->put( tdb, 0, &key, &value, 0 ))) { tdb->err( tdb, ret, "Maildir error: tdb->put()" ); goto mbork; } uid = *(uint *)value.data; } } else #endif /* USE_DB */ { uid = (ctx->uvok && (u = strstr( e->d_name, ",U=" ))) ? strtoul( u + 3, NULL, 10 ) : 0; if (!uid) uid = UINT_MAX; } if (uid <= ctx->maxuid) { if (uid < ctx->minuid && !find_uint_array( ctx->excs, uid )) continue; entry = msg_t_array_append( msglist ); entry->base = nfstrdup( e->d_name ); entry->msgid = 0; entry->uid = uid; entry->recent = i; entry->size = 0; entry->tuid[0] = 0; } } closedir( d ); } for (i = 0; i < 2; i++) { memcpy( buf + bl, subdirs[i], 4 ); if (stat( buf, &st )) { sys_error( "Maildir error: cannot re-stat %s", buf ); goto rfail; } if (st.st_mtime != stamps[i]) { /* Somebody messed with the mailbox since we started listing it. */ #ifdef USE_DB if (ctx->usedb) tdb->close( tdb, 0 ); #endif /* USE_DB */ maildir_free_scan( msglist ); goto again; } } #ifdef USE_DB if (ctx->usedb) { if (maildir_uidval_lock( ctx ) != DRV_OK) ; else if ((ret = ctx->db->cursor( ctx->db, 0, &dbc, 0 ))) ctx->db->err( ctx->db, ret, "Maildir error: db->cursor()" ); else { for (;;) { if ((ret = dbc->c_get( dbc, &key, &value, DB_NEXT ))) { if (ret != DB_NOTFOUND) ctx->db->err( ctx->db, ret, "Maildir error: db->c_get()" ); break; } if (!equals( key.data, key.size, "UIDVALIDITY", 11 ) && (ret = tdb->get( tdb, 0, &key, &value, 0 ))) { if (ret != DB_NOTFOUND) { tdb->err( tdb, ret, "Maildir error: tdb->get()" ); break; } if ((ret = dbc->c_del( dbc, 0 ))) { ctx->db->err( ctx->db, ret, "Maildir error: db->c_del()" ); break; } } } dbc->c_close( dbc ); } tdb->close( tdb, 0 ); } #endif /* USE_DB */ qsort( msglist->array.data, msglist->array.size, sizeof(msg_t), maildir_compare ); for (uid = i = 0; i < msglist->array.size; i++) { entry = &msglist->array.data[i]; if (entry->uid != UINT_MAX) { if (uid == entry->uid) { #if 1 /* See comment in maildir_uidval_lock() why this is fatal. */ error( "Maildir error: duplicate UID %u.\n", uid ); maildir_free_scan( msglist ); return DRV_BOX_BAD; #else notice( "Maildir notice: duplicate UID; changing UIDVALIDITY.\n"); if ((ret = maildir_init_uid( ctx )) != DRV_OK) { maildir_free_scan( msglist ); return ret; } maildir_free_scan( msglist ); goto again; #endif } uid = entry->uid; if (uid > ctx->nuid) { /* In principle, we could just warn and top up nuid. However, getting into this * situation might indicate some serious trouble, so let's not make it worse. */ error( "Maildir error: UID %u is beyond highest assigned UID %u.\n", uid, ctx->nuid ); maildir_free_scan( msglist ); return DRV_BOX_BAD; } fnl = 0; #ifdef USE_DB } else if (ctx->usedb) { if ((ret = maildir_set_uid( ctx, entry->base, &uid )) != DRV_OK) { maildir_free_scan( msglist ); return ret; } entry->uid = uid; fnl = 0; #endif /* USE_DB */ } else { if ((ret = maildir_obtain_uid( ctx, &uid )) != DRV_OK) { maildir_free_scan( msglist ); return ret; } entry->uid = uid; if ((u = strstr( entry->base, ",U=" ))) for (ru = u + 3; isdigit( (uchar)*ru ); ru++); else u = ru = strchr( entry->base, conf->info_delimiter ); fnl = (u ? nfsnprintf( buf + bl, sizeof(buf) - bl, "%s/%.*s,U=%u%s", subdirs[entry->recent], (int)(u - entry->base), entry->base, uid, ru ) : nfsnprintf( buf + bl, sizeof(buf) - bl, "%s/%s,U=%u", subdirs[entry->recent], entry->base, uid )) - 4; memcpy( nbuf, buf, bl + 4 ); nfsnprintf( nbuf + bl + 4, sizeof(nbuf) - bl - 4, "%s", entry->base ); if (rename( nbuf, buf )) { if (errno != ENOENT) { sys_error( "Maildir error: cannot rename %s to %s", nbuf, buf ); fail: maildir_free_scan( msglist ); return DRV_BOX_BAD; } retry: maildir_free_scan( msglist ); goto again; } free( entry->base ); entry->base = nfstrndup( buf + bl + 4, fnl ); } int want_size = (uid > ctx->seenuid) ? (ctx->opts & OPEN_NEW_SIZE) : (ctx->opts & OPEN_OLD_SIZE); int want_tuid = ((ctx->opts & OPEN_FIND) && uid >= ctx->newuid); int want_msgid = ((ctx->opts & OPEN_OLD_IDS) && uid <= ctx->seenuid); if (!want_size && !want_tuid && !want_msgid) continue; if (!fnl) nfsnprintf( buf + bl, sizeof(buf) - bl, "%s/%s", subdirs[entry->recent], entry->base ); if (want_size) { if (stat( buf, &st )) { if (errno != ENOENT) { sys_error( "Maildir error: cannot stat %s", buf ); goto fail; } goto retry; } entry->size = st.st_size; } if (want_tuid || want_msgid) { if (!(f = fopen( buf, "r" ))) { if (errno != ENOENT) { sys_error( "Maildir error: cannot open %s", buf ); goto fail; } goto retry; } int off, in_msgid = 0; while ((want_tuid || want_msgid) && fgets( nbuf, sizeof(nbuf), f )) { int bufl = strlen( nbuf ); if (bufl && nbuf[bufl - 1] == '\n') --bufl; if (bufl && nbuf[bufl - 1] == '\r') --bufl; if (!bufl) break; if (want_tuid && starts_with( nbuf, bufl, "X-TUID: ", 8 )) { if (bufl < 8 + TUIDL) { error( "Maildir error: malformed X-TUID header (UID %u)\n", uid ); continue; } memcpy( entry->tuid, nbuf + 8, TUIDL ); want_tuid = 0; in_msgid = 0; continue; } if (want_msgid && starts_with_upper( nbuf, bufl, "MESSAGE-ID:", 11 )) { off = 11; } else if (in_msgid) { if (!isspace( nbuf[0] )) { in_msgid = 0; continue; } off = 1; } else { continue; } while (off < bufl && isspace( nbuf[off] )) off++; if (off == bufl) { in_msgid = 1; continue; } entry->msgid = nfstrndup( nbuf + off, bufl - off ); want_msgid = 0; in_msgid = 0; } fclose( f ); } } ctx->uvok = 1; } return DRV_OK; } static void maildir_init_msg( maildir_store_t *ctx, maildir_message_t *msg, msg_t *entry ) { msg->base = entry->base; entry->base = 0; /* prevent deletion */ msg->gen.msgid = entry->msgid; entry->msgid = 0; /* prevent deletion */ msg->gen.size = entry->size; msg->gen.srec = 0; memcpy( msg->gen.tuid, entry->tuid, TUIDL ); if (entry->recent) msg->gen.status |= M_RECENT; if (ctx->opts & OPEN_FLAGS) { msg->gen.status |= M_FLAGS; msg->gen.flags = maildir_parse_flags( ((maildir_store_conf_t *)ctx->gen.conf)->info_prefix, msg->base ); } else msg->gen.flags = 0; } static void maildir_app_msg( maildir_store_t *ctx, message_t ***msgapp, msg_t *entry ) { maildir_message_t *msg = nfmalloc( sizeof(*msg) ); msg->gen.next = **msgapp; **msgapp = &msg->gen; *msgapp = &msg->gen.next; msg->gen.uid = entry->uid; msg->gen.status = 0; maildir_init_msg( ctx, msg, entry ); } static int maildir_select_box( store_t *gctx, const char *name ) { maildir_store_conf_t *conf = (maildir_store_conf_t *)gctx->conf; maildir_store_t *ctx = (maildir_store_t *)gctx; maildir_cleanup( gctx ); ctx->msgs = 0; ctx->excs.data = 0; ctx->uvfd = -1; #ifdef USE_DB ctx->db = 0; ctx->usedb = 0; #endif /* USE_DB */ ctx->fresh[0] = ctx->fresh[1] = 0; if (starts_with( name, -1, "INBOX", 5 ) && (!name[5] || name[5] == '/')) { if (!name[5]) { ctx->path = nfstrdup( conf->inbox ); ctx->is_inbox = 1; } else { ctx->path = maildir_join_path( conf, 1, name + 5 ); ctx->is_inbox = 0; } } else { if (!(ctx->path = maildir_join_path( conf, 0, name ))) return DRV_CANCELED; ctx->is_inbox = 0; } return ctx->path ? DRV_OK : DRV_BOX_BAD; } static const char * maildir_get_box_path( store_t *gctx ) { return ((maildir_store_t *)gctx)->path; } static void maildir_open_box( store_t *gctx, void (*cb)( int sts, int uidvalidity, void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; int ret; char uvpath[_POSIX_PATH_MAX]; if ((ret = maildir_validate( ctx->path, ctx->is_inbox, ctx )) != DRV_OK) goto bail; nfsnprintf( uvpath, sizeof(uvpath), "%s/.uidvalidity", ctx->path ); #ifndef USE_DB if ((ctx->uvfd = open( uvpath, O_RDWR|O_CREAT, 0600 )) < 0) { sys_error( "Maildir error: cannot write %s", uvpath ); cb( DRV_BOX_BAD, UIDVAL_BAD, aux ); return; } #else ctx->usedb = 0; if ((ctx->uvfd = open( uvpath, O_RDWR, 0600 )) < 0) { nfsnprintf( uvpath, sizeof(uvpath), "%s/.isyncuidmap.db", ctx->path ); if ((ctx->uvfd = open( uvpath, O_RDWR, 0600 )) < 0) { if (((maildir_store_conf_t *)gctx->conf)->alt_map) { if ((ctx->uvfd = open( uvpath, O_RDWR|O_CREAT, 0600 )) >= 0) goto dbok; } else { nfsnprintf( uvpath, sizeof(uvpath), "%s/.uidvalidity", ctx->path ); if ((ctx->uvfd = open( uvpath, O_RDWR|O_CREAT, 0600 )) >= 0) goto fnok; } sys_error( "Maildir error: cannot write %s", uvpath ); cb( DRV_BOX_BAD, UIDVAL_BAD, aux ); return; } else { dbok: ctx->usedb = nfstrdup( uvpath ); } } fnok: #endif /* USE_DB */ ret = maildir_uidval_lock( ctx ); bail: cb( ret, ctx->uidvalidity, aux ); } static int maildir_get_uidnext( store_t *gctx ATTR_UNUSED ) { return 0; } static void maildir_create_box( store_t *gctx, void (*cb)( int sts, void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; cb( maildir_validate( ctx->path, 1, ctx ), aux ); } static int maildir_confirm_box_empty( store_t *gctx ) { maildir_store_t *ctx = (maildir_store_t *)gctx; msg_t_array_alloc_t msglist; ctx->excs.size = ctx->minuid = ctx->maxuid = ctx->newuid = 0; if (maildir_scan( ctx, &msglist ) != DRV_OK) return DRV_BOX_BAD; maildir_free_scan( &msglist ); return ctx->total_msgs ? DRV_BOX_BAD : DRV_OK; } static void maildir_delete_box( store_t *gctx, void (*cb)( int sts, void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; int i, bl, ret = DRV_OK; struct stat st; char buf[_POSIX_PATH_MAX]; bl = nfsnprintf( buf, sizeof(buf) - 4, "%s/", ctx->path ); if (stat( buf, &st )) { if (errno != ENOENT) { sys_error( "Maildir error: cannot access mailbox '%s'", ctx->path ); ret = DRV_BOX_BAD; } } else if (!S_ISDIR(st.st_mode)) { error( "Maildir error: '%s' is no valid mailbox\n", ctx->path ); ret = DRV_BOX_BAD; } else if ((ret = maildir_clear_tmp( buf, sizeof(buf), bl )) == DRV_OK) { nfsnprintf( buf + bl, sizeof(buf) - bl, ".uidvalidity" ); if (unlink( buf ) && errno != ENOENT) goto badrm; #ifdef USE_DB nfsnprintf( buf + bl, sizeof(buf) - bl, ".isyncuidmap.db" ); if (unlink( buf ) && errno != ENOENT) goto badrm; #endif /* We delete cur/ last, as it is the indicator for a present mailbox. * That way an interrupted operation can be resumed. */ for (i = 3; --i >= 0; ) { memcpy( buf + bl, subdirs[i], 4 ); if (rmdir( buf ) && errno != ENOENT) { badrm: sys_error( "Maildir error: cannot remove '%s'", buf ); ret = DRV_BOX_BAD; break; } } } cb( ret, aux ); } static int maildir_finish_delete_box( store_t *gctx ) { maildir_store_t *ctx = (maildir_store_t *)gctx; /* Subfolders are not deleted; the deleted folder is only "stripped of its mailboxness". * Consequently, the rmdir may legitimately fail. This behavior follows the IMAP spec. */ if (rmdir( ctx->path ) && errno != ENOENT && errno != ENOTEMPTY) { sys_error( "Maildir warning: cannot remove '%s'", ctx->path ); return DRV_BOX_BAD; } return DRV_OK; } static int maildir_prepare_load_box( store_t *gctx, int opts ) { maildir_store_t *ctx = (maildir_store_t *)gctx; if (opts & OPEN_SETFLAGS) opts |= OPEN_OLD; if (opts & OPEN_EXPUNGE) opts |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS; ctx->opts = opts; return opts; } static void maildir_load_box( store_t *gctx, uint minuid, uint maxuid, uint newuid, uint seenuid, uint_array_t excs, void (*cb)( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; message_t **msgapp; msg_t_array_alloc_t msglist; int i; ctx->minuid = minuid; ctx->maxuid = maxuid; ctx->newuid = newuid; ctx->seenuid = seenuid; ARRAY_SQUEEZE( &excs ); ctx->excs = excs; if (maildir_scan( ctx, &msglist ) != DRV_OK) { cb( DRV_BOX_BAD, 0, 0, 0, aux ); return; } msgapp = &ctx->msgs; for (i = 0; i < msglist.array.size; i++) maildir_app_msg( ctx, &msgapp, msglist.array.data + i ); maildir_free_scan( &msglist ); cb( DRV_OK, ctx->msgs, ctx->total_msgs, ctx->recent_msgs, aux ); } static int maildir_rescan( maildir_store_t *ctx ) { message_t **msgapp; maildir_message_t *msg; msg_t_array_alloc_t msglist; int i; ctx->fresh[0] = ctx->fresh[1] = 0; if (maildir_scan( ctx, &msglist ) != DRV_OK) return DRV_BOX_BAD; for (msgapp = &ctx->msgs, i = 0; (msg = (maildir_message_t *)*msgapp) || i < msglist.array.size; ) { if (!msg) { #if 0 debug( "adding new message %u\n", msglist.array.data[i].uid ); maildir_app_msg( ctx, &msgapp, msglist.array.data + i ); #else debug( "ignoring new message %u\n", msglist.array.data[i].uid ); #endif i++; } else if (i >= msglist.array.size) { debug( "purging deleted message %u\n", msg->gen.uid ); msg->gen.status = M_DEAD; msgapp = &msg->gen.next; } else if (msglist.array.data[i].uid < msg->gen.uid) { /* this should not happen, actually */ #if 0 debug( "adding new message %u\n", msglist.array.data[i].uid ); maildir_app_msg( ctx, &msgapp, msglist.array.data + i ); #else debug( "ignoring new message %u\n", msglist.array.data[i].uid ); #endif i++; } else if (msglist.array.data[i].uid > msg->gen.uid) { debug( "purging deleted message %u\n", msg->gen.uid ); msg->gen.status = M_DEAD; msgapp = &msg->gen.next; } else { debug( "updating message %u\n", msg->gen.uid ); msg->gen.status &= ~(M_FLAGS|M_RECENT); free( msg->base ); free( msg->gen.msgid ); maildir_init_msg( ctx, msg, msglist.array.data + i ); i++, msgapp = &msg->gen.next; } } maildir_free_scan( &msglist ); return DRV_OK; } static int maildir_again( maildir_store_t *ctx, maildir_message_t *msg, const char *err, const char *fn, const char *fn2 ) { int ret; if (errno != ENOENT) { sys_error( err, fn, fn2 ); return DRV_BOX_BAD; } if ((ret = maildir_rescan( ctx )) != DRV_OK) return ret; return (msg->gen.status & M_DEAD) ? DRV_MSG_BAD : DRV_OK; } static void maildir_fetch_msg( store_t *gctx, message_t *gmsg, msg_data_t *data, void (*cb)( int sts, void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; maildir_message_t *msg = (maildir_message_t *)gmsg; int fd, ret; struct stat st; char buf[_POSIX_PATH_MAX]; for (;;) { nfsnprintf( buf, sizeof(buf), "%s/%s/%s", ctx->path, subdirs[gmsg->status & M_RECENT], msg->base ); if ((fd = open( buf, O_RDONLY )) >= 0) break; if ((ret = maildir_again( ctx, msg, "Cannot open %s", buf, 0 )) != DRV_OK) { cb( ret, aux ); return; } } fstat( fd, &st ); data->len = st.st_size; if (data->date == -1) data->date = st.st_mtime; data->data = nfmalloc( data->len ); if (read( fd, data->data, data->len ) != data->len) { sys_error( "Maildir error: cannot read %s", buf ); close( fd ); cb( DRV_MSG_BAD, aux ); return; } close( fd ); if (!(gmsg->status & M_FLAGS)) data->flags = maildir_parse_flags( ((maildir_store_conf_t *)gctx->conf)->info_prefix, msg->base ); cb( DRV_OK, aux ); } static int maildir_make_flags( char info_delimiter, int flags, char *buf ) { uint i, d; buf[0] = info_delimiter; buf[1] = '2'; buf[2] = ','; for (d = 3, i = 0; i < as(Flags); i++) if (flags & (1 << i)) buf[d++] = Flags[i]; buf[d] = 0; return d; } static void maildir_store_msg( store_t *gctx, msg_data_t *data, int to_trash, void (*cb)( int sts, uint uid, void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; const char *box; int ret, fd, bl; uint uid; char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX], fbuf[NUM_FLAGS + 3], base[128]; bl = nfsnprintf( base, sizeof(base), "%ld.%d_%d.%s", (long)time( 0 ), Pid, ++MaildirCount, Hostname ); if (!to_trash) { #ifdef USE_DB if (ctx->usedb) { if ((ret = maildir_set_uid( ctx, base, &uid )) != DRV_OK) { free( data->data ); cb( ret, 0, aux ); return; } } else #endif /* USE_DB */ { if ((ret = maildir_obtain_uid( ctx, &uid )) != DRV_OK) { free( data->data ); cb( ret, 0, aux ); return; } nfsnprintf( base + bl, sizeof(base) - bl, ",U=%u", uid ); } box = ctx->path; } else { uid = 0; box = ctx->trash; } maildir_make_flags( ((maildir_store_conf_t *)gctx->conf)->info_delimiter, data->flags, fbuf ); nfsnprintf( buf, sizeof(buf), "%s/tmp/%s%s", box, base, fbuf ); if ((fd = open( buf, O_WRONLY|O_CREAT|O_EXCL, 0600 )) < 0) { if (errno != ENOENT || !to_trash) { sys_error( "Maildir error: cannot create %s", buf ); free( data->data ); cb( DRV_BOX_BAD, 0, aux ); return; } if ((ret = maildir_validate( box, 1, ctx )) != DRV_OK) { free( data->data ); cb( ret, 0, aux ); return; } if ((fd = open( buf, O_WRONLY|O_CREAT|O_EXCL, 0600 )) < 0) { sys_error( "Maildir error: cannot create %s", buf ); free( data->data ); cb( DRV_BOX_BAD, 0, aux ); return; } } ret = write( fd, data->data, data->len ); free( data->data ); if (ret != data->len || (UseFSync && (ret = fsync( fd )))) { if (ret < 0) sys_error( "Maildir error: cannot write %s", buf ); else error( "Maildir error: cannot write %s. Disk full?\n", buf ); close( fd ); cb( DRV_BOX_BAD, 0, aux ); return; } if (close( fd ) < 0) { /* Quota exceeded may cause this. */ sys_error( "Maildir error: cannot write %s", buf ); cb( DRV_BOX_BAD, 0, aux ); return; } if (data->date) { /* Set atime and mtime according to INTERNALDATE or mtime of source message */ struct utimbuf utimebuf; utimebuf.actime = utimebuf.modtime = data->date; if (utime( buf, &utimebuf ) < 0) { sys_error( "Maildir error: cannot set times for %s", buf ); cb( DRV_BOX_BAD, 0, aux ); return; } } /* Moving seen messages to cur/ is strictly speaking incorrect, but makes mutt happy. */ nfsnprintf( nbuf, sizeof(nbuf), "%s/%s/%s%s", box, subdirs[!(data->flags & F_SEEN)], base, fbuf ); if (rename( buf, nbuf )) { sys_error( "Maildir error: cannot rename %s to %s", buf, nbuf ); cb( DRV_BOX_BAD, 0, aux ); return; } cb( DRV_OK, uid, aux ); } static void maildir_find_new_msgs( store_t *gctx ATTR_UNUSED, uint newuid ATTR_UNUSED, void (*cb)( int sts, message_t *msgs, void *aux ) ATTR_UNUSED, void *aux ATTR_UNUSED ) { assert( !"maildir_find_new_msgs is not supposed to be called" ); } static void maildir_set_msg_flags( store_t *gctx, message_t *gmsg, uint uid ATTR_UNUSED, int add, int del, void (*cb)( int sts, void *aux ), void *aux ) { maildir_store_conf_t *conf = (maildir_store_conf_t *)gctx->conf; maildir_store_t *ctx = (maildir_store_t *)gctx; maildir_message_t *msg = (maildir_message_t *)gmsg; char *s, *p; uint i; int j, ret, ol, fl, bbl, bl, tl; char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX]; bbl = nfsnprintf( buf, sizeof(buf), "%s/", ctx->path ); memcpy( nbuf, ctx->path, bbl - 1 ); memcpy( nbuf + bbl - 1, "/cur/", 5 ); for (;;) { bl = bbl + nfsnprintf( buf + bbl, sizeof(buf) - bbl, "%s/", subdirs[gmsg->status & M_RECENT] ); ol = strlen( msg->base ); if ((int)sizeof(buf) - bl < ol + 3 + NUM_FLAGS) oob(); memcpy( buf + bl, msg->base, ol + 1 ); memcpy( nbuf + bl, msg->base, ol + 1 ); if ((s = strstr( nbuf + bl, conf->info_prefix ))) { s += 3; fl = ol - (s - (nbuf + bl)); for (i = 0; i < as(Flags); i++) { if ((p = strchr( s, Flags[i] ))) { if (del & (1 << i)) { memmove( p, p + 1, fl - (p - s) ); fl--; } } else if (add & (1 << i)) { for (j = 0; j < fl && Flags[i] > s[j]; j++); fl++; memmove( s + j + 1, s + j, fl - j ); s[j] = Flags[i]; } } tl = ol + 3 + fl; } else { tl = ol + maildir_make_flags( conf->info_delimiter, msg->gen.flags, nbuf + bl + ol ); } if (!rename( buf, nbuf )) break; if ((ret = maildir_again( ctx, msg, "Maildir error: cannot rename %s to %s", buf, nbuf )) != DRV_OK) { cb( ret, aux ); return; } } free( msg->base ); msg->base = nfstrndup( nbuf + bl, tl ); msg->gen.flags |= add; msg->gen.flags &= ~del; gmsg->status &= ~M_RECENT; cb( DRV_OK, aux ); } #ifdef USE_DB static int maildir_purge_msg( maildir_store_t *ctx, const char *name ) { int ret; if ((ret = maildir_uidval_lock( ctx )) != DRV_OK) return ret; make_key( ((maildir_store_conf_t *)ctx->gen.conf)->info_stop, &key, (char *)name ); if ((ret = ctx->db->del( ctx->db, 0, &key, 0 ))) { ctx->db->err( ctx->db, ret, "Maildir error: db->del()" ); return DRV_BOX_BAD; } return DRV_OK; } #endif /* USE_DB */ static void maildir_trash_msg( store_t *gctx, message_t *gmsg, void (*cb)( int sts, void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; maildir_message_t *msg = (maildir_message_t *)gmsg; char *s; int ret; struct stat st; char buf[_POSIX_PATH_MAX], nbuf[_POSIX_PATH_MAX]; for (;;) { nfsnprintf( buf, sizeof(buf), "%s/%s/%s", ctx->path, subdirs[gmsg->status & M_RECENT], msg->base ); s = strstr( msg->base, ((maildir_store_conf_t *)gctx->conf)->info_prefix ); nfsnprintf( nbuf, sizeof(nbuf), "%s/%s/%ld.%d_%d.%s%s", ctx->trash, subdirs[gmsg->status & M_RECENT], (long)time( 0 ), Pid, ++MaildirCount, Hostname, s ? s : "" ); if (!rename( buf, nbuf )) break; if (!stat( buf, &st )) { if ((ret = maildir_validate( ctx->trash, 1, ctx )) != DRV_OK) { cb( ret, aux ); return; } if (!rename( buf, nbuf )) break; if (errno != ENOENT) { sys_error( "Maildir error: cannot move %s to %s", buf, nbuf ); cb( DRV_BOX_BAD, aux ); return; } } if ((ret = maildir_again( ctx, msg, "Maildir error: cannot move %s to %s", buf, nbuf )) != DRV_OK) { cb( ret, aux ); return; } } gmsg->status |= M_DEAD; ctx->total_msgs--; #ifdef USE_DB if (ctx->usedb) { cb( maildir_purge_msg( ctx, msg->base ), aux ); return; } #endif /* USE_DB */ cb( DRV_OK, aux ); } static void maildir_close_box( store_t *gctx, void (*cb)( int sts, void *aux ), void *aux ) { maildir_store_t *ctx = (maildir_store_t *)gctx; message_t *msg; int basel, retry, ret; char buf[_POSIX_PATH_MAX]; for (;;) { retry = 0; basel = nfsnprintf( buf, sizeof(buf), "%s/", ctx->path ); for (msg = ctx->msgs; msg; msg = msg->next) if (!(msg->status & M_DEAD) && (msg->flags & F_DELETED)) { nfsnprintf( buf + basel, sizeof(buf) - basel, "%s/%s", subdirs[msg->status & M_RECENT], ((maildir_message_t *)msg)->base ); if (unlink( buf )) { if (errno == ENOENT) retry = 1; else sys_error( "Maildir error: cannot remove %s", buf ); } else { msg->status |= M_DEAD; ctx->total_msgs--; #ifdef USE_DB if (ctx->db && (ret = maildir_purge_msg( ctx, ((maildir_message_t *)msg)->base )) != DRV_OK) { cb( ret, aux ); return; } #endif /* USE_DB */ } } if (!retry) { cb( DRV_OK, aux ); return; } if ((ret = maildir_rescan( (maildir_store_t *)gctx )) != DRV_OK) { cb( ret, aux ); return; } } } static void maildir_cancel_cmds( store_t *gctx ATTR_UNUSED, void (*cb)( void *aux ), void *aux ) { cb( aux ); } static void maildir_commit_cmds( store_t *gctx ) { (void) gctx; } static int maildir_get_memory_usage( store_t *gctx ATTR_UNUSED ) { return 0; } static int maildir_get_fail_state( store_conf_t *gconf ) { return ((maildir_store_conf_t *)gconf)->failed; } static int maildir_parse_store( conffile_t *cfg, store_conf_t **storep ) { maildir_store_conf_t *store; if (strcasecmp( "MaildirStore", cfg->cmd )) return 0; store = nfcalloc( sizeof(*store) ); store->info_delimiter = FieldDelimiter; store->gen.driver = &maildir_driver; store->gen.name = nfstrdup( cfg->val ); while (getcline( cfg ) && cfg->cmd) if (!strcasecmp( "Inbox", cfg->cmd )) store->inbox = expand_strdup( cfg->val ); else if (!strcasecmp( "Path", cfg->cmd )) store->gen.path = expand_strdup( cfg->val ); #ifdef USE_DB else if (!strcasecmp( "AltMap", cfg->cmd )) store->alt_map = parse_bool( cfg ); #endif /* USE_DB */ else if (!strcasecmp( "InfoDelimiter", cfg->cmd )) { if (strlen( cfg->val ) != 1) { error( "%s:%d: Info delimiter must be exactly one character long\n", cfg->file, cfg->line ); cfg->err = 1; continue; } store->info_delimiter = cfg->val[0]; if (!ispunct( store->info_delimiter )) { error( "%s:%d: Info delimiter must be a punctuation character\n", cfg->file, cfg->line ); cfg->err = 1; continue; } } else if (!strcasecmp( "SubFolders", cfg->cmd )) { if (!strcasecmp( "Verbatim", cfg->val )) { store->sub_style = SUB_VERBATIM; } else if (!strcasecmp( "Maildir++", cfg->val )) { store->sub_style = SUB_MAILDIRPP; } else if (!strcasecmp( "Legacy", cfg->val )) { store->sub_style = SUB_LEGACY; } else { error( "%s:%d: Unrecognized SubFolders style\n", cfg->file, cfg->line ); cfg->err = 1; } } else parse_generic_store( &store->gen, cfg ); if (!store->inbox) store->inbox = expand_strdup( "~/Maildir" ); if (store->sub_style == SUB_MAILDIRPP && store->gen.path) { error( "Maildir store '%s': Setting Path is incompatible with 'SubFolders Maildir++'\n", store->gen.name ); cfg->err = 1; } nfasprintf( &store->info_prefix, "%c2,", store->info_delimiter ); nfasprintf( &store->info_stop, "%c,", store->info_delimiter ); *storep = &store->gen; return 1; } static int maildir_get_caps( store_t *gctx ATTR_UNUSED ) { return 0; /* XXX DRV_CRLF? */ } struct driver maildir_driver = { maildir_get_caps, maildir_parse_store, maildir_cleanup_drv, maildir_alloc_store, maildir_set_bad_callback, maildir_connect_store, maildir_free_store, maildir_free_store, /* _cancel_, but it's the same */ maildir_list_store, maildir_select_box, maildir_get_box_path, maildir_create_box, maildir_open_box, maildir_get_uidnext, maildir_confirm_box_empty, maildir_delete_box, maildir_finish_delete_box, maildir_prepare_load_box, maildir_load_box, maildir_fetch_msg, maildir_store_msg, maildir_find_new_msgs, maildir_set_msg_flags, maildir_trash_msg, maildir_close_box, maildir_cancel_cmds, maildir_commit_cmds, maildir_get_memory_usage, maildir_get_fail_state, }; isync-1.3.0/src/drv_proxy_gen.pl0000755000175000001440000001044713141404045013573 00000000000000#!/usr/bin/perl # # mbsync - mailbox synchronizer # Copyright (C) 2017 Oswald Buddenhagen # # 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, see . # # As a special exception, mbsync may be linked with the OpenSSL library, # despite that library's more restrictive license. # use strict; use warnings; die("Usage: $0 driver.h drv_proxy.c drv_proxy.inc\n") if ($#ARGV != 2); my ($in_header, $in_source, $out_source) = @ARGV; my %templates; my %defines; my %excluded; my %special; open(my $ins, $in_source) or die("Cannot open $in_source: $!\n"); my $template; my $define; my $conts; while (<$ins>) { if ($template) { if (/^\/\/\# END$/) { $templates{$template} = $conts; $template = undef; } else { $conts .= $_; } } elsif ($define) { if (/^\/\/\# END$/) { $defines{$define} = $conts; $define = undef; } else { $conts .= $_; } } else { if (/^\/\/\# TEMPLATE (\w+)$/) { $template = $1; $conts = ""; } elsif (/^\/\/\# DEFINE (\w+)$/) { $define = $1; $conts = ""; } elsif (/^\/\/\# DEFINE (\w+) (.*)$/) { $defines{$1} = $2; } elsif (/^\/\/\# UNDEFINE (\w+)$/) { $defines{$1} = ""; } elsif (/^\/\/\# EXCLUDE (\w+)$/) { $excluded{$1} = 1; } elsif (/^\/\/\# SPECIAL (\w+)$/) { $special{$1} = 1; } } } close($ins); open(my $inh, $in_header) or die("Cannot open $in_header: $!\n"); my $sts = 0; my $cont = ""; while (<$inh>) { if ($sts == 0) { if (/^struct driver \{$/) { $sts = 1; } } elsif ($sts == 1) { if (/^\};$/) { $sts = 0; } else { $cont .= $_; } } } close($inh); $cont =~ s,\n, ,g; $cont =~ s,/\*.*?\*/, ,g; $cont =~ s,\h+, ,g; my @ptypes = map { s,^ ,,r } split(/;/, $cont); pop @ptypes; # last one is empty my @cmd_table; sub make_args($) { $_ = shift; s/(?:^|(?<=, ))(?:const )?\w+ \*?//g; return $_; } sub type_to_format($) { $_ = shift; s/xint /\%\#x/g; s/int /\%d/g; s/const char \*/\%s/g; return $_; } sub make_format($) { $_ = type_to_format(shift); s/, (\%\#?.)(\w+)/, $2=$1/g; return $_; } open(my $outh, ">".$out_source) or die("Cannot create $out_source: $!\n"); for (@ptypes) { /^([\w* ]+)\(\*(\w+)\)\( (.*) \)$/ or die("Cannot parse prototype '$_'\n"); my ($cmd_type, $cmd_name, $cmd_args) = ($1, $2, $3); if (defined($excluded{$cmd_name})) { push @cmd_table, "0"; next; } push @cmd_table, "proxy_$cmd_name"; next if (defined($special{$cmd_name})); my %replace; $replace{'name'} = $cmd_name; $replace{'type'} = $cmd_type; $cmd_args =~ s/^store_t \*ctx// or die("Arguments '$cmd_args' don't start with 'store_t *ctx'\n"); if ($cmd_type eq "void " && $cmd_args =~ s/, void \(\*cb\)\( (.*)void \*aux \), void \*aux$//) { my $cmd_cb_args = $1; $replace{'decl_cb_args'} = $cmd_cb_args; $replace{'pass_cb_args'} = make_args($cmd_cb_args); my $cmd_print_cb_args = $cmd_cb_args =~ s/(.*), $/, $1/r; $replace{'print_pass_cb_args'} = make_args($cmd_print_cb_args); $replace{'print_fmt_cb_args'} = make_format($cmd_print_cb_args); $template = "CALLBACK"; } elsif ($cmd_name =~ /^get_/) { $template = "GETTER"; $replace{'fmt'} = type_to_format($cmd_type); } elsif ($cmd_type eq "void ") { $template = "REGULAR_VOID"; } else { $template = "REGULAR"; $replace{'fmt'} = type_to_format($cmd_type); } $replace{'decl_args'} = $cmd_args; $replace{'print_pass_args'} = $replace{'pass_args'} = make_args($cmd_args); $replace{'print_fmt_args'} = make_format($cmd_args); for (keys %defines) { $replace{$1} = $defines{$_} if (/^${cmd_name}_(.*)$/); } my $text = $templates{$template}; $text =~ s/^\h*\@(\w+)\@\n/$replace{$1} \/\/ ""/smeg; $text =~ s/\@(\w+)\@/$replace{$1} \/\/ ""/eg; print $outh $text."\n"; } print $outh "struct driver proxy_driver = {\n".join("", map { "\t$_,\n" } @cmd_table)."};\n"; close $outh; isync-1.3.0/src/drv_imap.c0000644000175000001440000026146613164125173012333 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2008,2010-2013 Oswald Buddenhagen * Copyright (C) 2004 Theodore Y. Ts'o * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #include "driver.h" #include "socket.h" #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBSASL # include # include #endif #ifdef HAVE_LIBSSL enum { SSL_None, SSL_STARTTLS, SSL_IMAPS }; #endif typedef struct imap_server_conf { struct imap_server_conf *next; char *name; server_conf_t sconf; char *user; char *pass; char *pass_cmd; int max_in_progress; int cap_mask; string_list_t *auth_mechs; #ifdef HAVE_LIBSSL char ssl_type; #endif char failed; } imap_server_conf_t; typedef struct { store_conf_t gen; imap_server_conf_t *server; char delimiter; char use_namespace; } imap_store_conf_t; typedef struct { message_t gen; /* int seq; will be needed when expunges are tracked */ } imap_message_t; #define NIL (void*)0x1 #define LIST (void*)0x2 typedef struct _list { struct _list *next, *child; char *val; int len; } list_t; #define MAX_LIST_DEPTH 5 typedef struct imap_store imap_store_t; typedef struct { list_t *head, **stack[MAX_LIST_DEPTH]; int (*callback)( imap_store_t *ctx, list_t *list, char *cmd ); int level, need_bytes; } parse_list_state_t; typedef struct imap_cmd imap_cmd_t; struct imap_store { store_t gen; const char *label; /* foreign */ const char *prefix; const char *name; int ref_count; uint opts; enum { SST_BAD, SST_HALF, SST_GOOD } state; /* trash folder's existence is not confirmed yet */ enum { TrashUnknown, TrashChecking, TrashKnown } trashnc; uint got_namespace:1; char delimiter[2]; /* hierarchy delimiter */ list_t *ns_personal, *ns_other, *ns_shared; /* NAMESPACE info */ string_list_t *boxes; // _list results char listed; // was _list already run with these flags? // note that the message counts do _not_ reflect stats from msgs, // but mailbox totals. also, don't trust them beyond the initial load. int total_msgs, recent_msgs; uint uidvalidity, uidnext; message_t *msgs; message_t **msgapp; /* FETCH results */ uint caps; /* CAPABILITY results */ string_list_t *auth_mechs; parse_list_state_t parse_list_sts; /* command queue */ int nexttag, num_in_progress; imap_cmd_t *pending, **pending_append; imap_cmd_t *in_progress, **in_progress_append; int buffer_mem; /* memory currently occupied by buffers in the queue */ /* Used during sequential operations like connect */ enum { GreetingPending = 0, GreetingBad, GreetingOk, GreetingPreauth } greeting; int expectBYE; /* LOGOUT is in progress */ int expectEOF; /* received LOGOUT's OK or unsolicited BYE */ int canceling; /* imap_cancel() is in progress */ union { void (*imap_open)( int sts, void *aux ); void (*imap_cancel)( void *aux ); } callbacks; void *callback_aux; #ifdef HAVE_LIBSASL sasl_conn_t *sasl; int sasl_cont; #endif void (*bad_callback)( void *aux ); void *bad_callback_aux; conn_t conn; /* this is BIG, so put it last */ }; struct imap_cmd { struct imap_cmd *next; char *cmd; int tag; struct { /* Will be called on each continuation request until it resets this pointer. * Needs to invoke bad_callback and return -1 on error, otherwise return 0. */ int (*cont)( imap_store_t *ctx, imap_cmd_t *cmd, const char *prompt ); void (*done)( imap_store_t *ctx, imap_cmd_t *cmd, int response ); char *data; int data_len; uint uid; /* to identify fetch responses */ char high_prio; /* if command is queued, put it at the front of the queue. */ char to_trash; /* we are storing to trash, not current. */ char create; /* create the mailbox if we get an error which suggests so. */ char failok; /* Don't complain about NO response. */ char lastuid; /* querying the last UID in the mailbox. */ } param; }; typedef struct { imap_cmd_t gen; void (*callback)( int sts, void *aux ); void *callback_aux; } imap_cmd_simple_t; typedef struct { imap_cmd_simple_t gen; msg_data_t *msg_data; } imap_cmd_fetch_msg_t; typedef struct { imap_cmd_t gen; void (*callback)( int sts, uint uid, void *aux ); void *callback_aux; uint out_uid; } imap_cmd_out_uid_t; typedef struct { imap_cmd_t gen; void (*callback)( int sts, message_t *msgs, void *aux ); void *callback_aux; message_t **out_msgs; uint uid; } imap_cmd_find_new_t; typedef struct { int ref_count; int ret_val; } imap_cmd_refcounted_state_t; typedef struct { imap_cmd_t gen; imap_cmd_refcounted_state_t *state; } imap_cmd_refcounted_t; #define CAP(cap) (ctx->caps & (1 << (cap))) enum CAPABILITY { NOLOGIN = 0, #ifdef HAVE_LIBSASL SASLIR, #endif #ifdef HAVE_LIBSSL STARTTLS, #endif UIDPLUS, LITERALPLUS, MOVE, NAMESPACE, COMPRESS_DEFLATE }; static const char *cap_list[] = { "LOGINDISABLED", #ifdef HAVE_LIBSASL "SASL-IR", #endif #ifdef HAVE_LIBSSL "STARTTLS", #endif "UIDPLUS", "LITERAL+", "MOVE", "NAMESPACE", "COMPRESS=DEFLATE" }; #define RESP_OK 0 #define RESP_NO 1 #define RESP_CANCEL 2 static INLINE void imap_ref( imap_store_t *ctx ) { ++ctx->ref_count; } static int imap_deref( imap_store_t *ctx ); static void imap_invoke_bad_callback( imap_store_t *ctx ); static const char *Flags[] = { "Draft", "Flagged", "Answered", "Seen", "Deleted", }; static imap_cmd_t * new_imap_cmd( int size ) { imap_cmd_t *cmd = nfmalloc( size ); memset( &cmd->param, 0, sizeof(cmd->param) ); return cmd; } #define INIT_IMAP_CMD(type, cmdp, cb, aux) \ cmdp = (type *)new_imap_cmd( sizeof(*cmdp) ); \ cmdp->callback = cb; \ cmdp->callback_aux = aux; #define INIT_IMAP_CMD_X(type, cmdp, cb, aux) \ cmdp = (type *)new_imap_cmd( sizeof(*cmdp) ); \ cmdp->gen.callback = cb; \ cmdp->gen.callback_aux = aux; static void done_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd, int response ) { cmd->param.done( ctx, cmd, response ); if (cmd->param.data) { free( cmd->param.data ); ctx->buffer_mem -= cmd->param.data_len; } free( cmd->cmd ); free( cmd ); } static void send_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd ) { int bufl, litplus, iovcnt = 1; const char *buffmt; conn_iovec_t iov[3]; char buf[1024]; cmd->tag = ++ctx->nexttag; if (!cmd->param.data) { buffmt = "%d %s\r\n"; litplus = 0; } else if ((cmd->param.to_trash && ctx->trashnc == TrashUnknown) || !CAP(LITERALPLUS) || cmd->param.data_len >= 100*1024) { buffmt = "%d %s{%d}\r\n"; litplus = 0; } else { buffmt = "%d %s{%d+}\r\n"; litplus = 1; } bufl = nfsnprintf( buf, sizeof(buf), buffmt, cmd->tag, cmd->cmd, cmd->param.data_len ); if (DFlags & DEBUG_NET) { if (ctx->num_in_progress) printf( "(%d in progress) ", ctx->num_in_progress ); if (starts_with( cmd->cmd, -1, "LOGIN", 5 )) printf( "%s>>> %d LOGIN \n", ctx->label, cmd->tag ); else if (starts_with( cmd->cmd, -1, "AUTHENTICATE PLAIN", 18 )) printf( "%s>>> %d AUTHENTICATE PLAIN \n", ctx->label, cmd->tag ); else printf( "%s>>> %s", ctx->label, buf ); fflush( stdout ); } iov[0].buf = buf; iov[0].len = bufl; iov[0].takeOwn = KeepOwn; if (litplus) { if (DFlags & DEBUG_NET_ALL) { printf( "%s>>>>>>>>>\n", ctx->label ); fwrite( cmd->param.data, cmd->param.data_len, 1, stdout ); printf( "%s>>>>>>>>>\n", ctx->label ); fflush( stdout ); } iov[1].buf = cmd->param.data; iov[1].len = cmd->param.data_len; iov[1].takeOwn = GiveOwn; cmd->param.data = 0; ctx->buffer_mem -= cmd->param.data_len; iov[2].buf = "\r\n"; iov[2].len = 2; iov[2].takeOwn = KeepOwn; iovcnt = 3; } socket_write( &ctx->conn, iov, iovcnt ); if (cmd->param.to_trash && ctx->trashnc == TrashUnknown) ctx->trashnc = TrashChecking; cmd->next = 0; *ctx->in_progress_append = cmd; ctx->in_progress_append = &cmd->next; ctx->num_in_progress++; socket_expect_read( &ctx->conn, 1 ); } static int cmd_sendable( imap_store_t *ctx, imap_cmd_t *cmd ) { if (ctx->conn.write_buf) { /* Don't build up a long queue in the socket, so we can * control when the commands are actually sent. * This allows reliable cancelation of pending commands, * injecting commands in front of other pending commands, * and keeping num_in_progress accurate. */ return 0; } if (ctx->in_progress) { /* If the last command in flight ... */ imap_cmd_t *cmdp = (imap_cmd_t *)((char *)ctx->in_progress_append - offsetof(imap_cmd_t, next)); if (cmdp->param.cont || cmdp->param.data) { /* ... is expected to trigger a continuation request, we need to * wait for that round-trip before sending the next command. */ return 0; } } if (cmd->param.to_trash && ctx->trashnc == TrashChecking) { /* Don't build a queue of MOVE/COPY/APPEND commands that may all fail. */ return 0; } if (ctx->num_in_progress >= ((imap_store_conf_t *)ctx->gen.conf)->server->max_in_progress) { /* Too many commands in flight. */ return 0; } return 1; } static void flush_imap_cmds( imap_store_t *ctx ) { imap_cmd_t *cmd; if ((cmd = ctx->pending) && cmd_sendable( ctx, cmd )) { if (!(ctx->pending = cmd->next)) ctx->pending_append = &ctx->pending; send_imap_cmd( ctx, cmd ); } } static void cancel_pending_imap_cmds( imap_store_t *ctx ) { imap_cmd_t *cmd; while ((cmd = ctx->pending)) { if (!(ctx->pending = cmd->next)) ctx->pending_append = &ctx->pending; done_imap_cmd( ctx, cmd, RESP_CANCEL ); } } static void cancel_sent_imap_cmds( imap_store_t *ctx ) { imap_cmd_t *cmd; socket_expect_read( &ctx->conn, 0 ); while ((cmd = ctx->in_progress)) { ctx->in_progress = cmd->next; /* don't update num_in_progress and in_progress_append - store is dead */ done_imap_cmd( ctx, cmd, RESP_CANCEL ); } } static void submit_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd ) { assert( ctx ); assert( ctx->bad_callback ); assert( cmd ); assert( cmd->param.done ); if ((ctx->pending && !cmd->param.high_prio) || !cmd_sendable( ctx, cmd )) { if (ctx->pending && cmd->param.high_prio) { cmd->next = ctx->pending; ctx->pending = cmd; } else { cmd->next = 0; *ctx->pending_append = cmd; ctx->pending_append = &cmd->next; } } else { send_imap_cmd( ctx, cmd ); } } /* Minimal printf() replacement that supports an %\s format sequence to print backslash-escaped * string literals. Note that this does not automatically add quotes around the printed string, * so it is possible to concatenate multiple segments. */ static char * imap_vprintf( const char *fmt, va_list ap ) { const char *s; char *d, *ed; int maxlen; char c; char buf[1024]; /* Minimal supported command buffer size per IMAP spec. */ d = buf; ed = d + sizeof(buf); s = fmt; for (;;) { c = *fmt; if (!c || c == '%') { int l = fmt - s; if (d + l > ed) oob(); memcpy( d, s, l ); d += l; if (!c) return nfstrndup( buf, d - buf ); maxlen = INT_MAX; c = *++fmt; if (c == '\\') { c = *++fmt; if (c != 's') { fputs( "Fatal: unsupported escaped format specifier. Please report a bug.\n", stderr ); abort(); } s = va_arg( ap, const char * ); while ((c = *s++)) { if (d + 2 > ed) oob(); if (c == '\\' || c == '"') *d++ = '\\'; *d++ = c; } } else { /* \\ cannot be combined with anything else. */ if (c == '.') { c = *++fmt; if (c != '*') { fputs( "Fatal: unsupported string length specification. Please report a bug.\n", stderr ); abort(); } maxlen = va_arg( ap , int ); c = *++fmt; } if (c == 'c') { if (d + 1 > ed) oob(); *d++ = (char)va_arg( ap , int ); } else if (c == 's') { s = va_arg( ap, const char * ); l = strnlen( s, maxlen ); if (d + l > ed) oob(); memcpy( d, s, l ); d += l; } else if (c == 'd') { d += nfsnprintf( d, ed - d, "%d", va_arg( ap , int ) ); } else if (c == 'u') { d += nfsnprintf( d, ed - d, "%u", va_arg( ap , uint ) ); } else { fputs( "Fatal: unsupported format specifier. Please report a bug.\n", stderr ); abort(); } } s = ++fmt; } else { fmt++; } } } static void imap_exec( imap_store_t *ctx, imap_cmd_t *cmdp, void (*done)( imap_store_t *ctx, imap_cmd_t *cmd, int response ), const char *fmt, ... ) { va_list ap; if (!cmdp) cmdp = new_imap_cmd( sizeof(*cmdp) ); cmdp->param.done = done; va_start( ap, fmt ); cmdp->cmd = imap_vprintf( fmt, ap ); va_end( ap ); submit_imap_cmd( ctx, cmdp ); } static void transform_box_response( int *response ) { switch (*response) { case RESP_CANCEL: *response = DRV_CANCELED; break; case RESP_NO: *response = DRV_BOX_BAD; break; default: *response = DRV_OK; break; } } static void imap_done_simple_box( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *cmd, int response ) { imap_cmd_simple_t *cmdp = (imap_cmd_simple_t *)cmd; transform_box_response( &response ); cmdp->callback( response, cmdp->callback_aux ); } static void transform_msg_response( int *response ) { switch (*response) { case RESP_CANCEL: *response = DRV_CANCELED; break; case RESP_NO: *response = DRV_MSG_BAD; break; default: *response = DRV_OK; break; } } static void imap_done_simple_msg( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *cmd, int response ) { imap_cmd_simple_t *cmdp = (imap_cmd_simple_t *)cmd; transform_msg_response( &response ); cmdp->callback( response, cmdp->callback_aux ); } static imap_cmd_refcounted_state_t * imap_refcounted_new_state( int sz ) { imap_cmd_refcounted_state_t *sts = nfmalloc( sz ); sts->ref_count = 1; /* so forced sync does not cause an early exit */ sts->ret_val = DRV_OK; return sts; } #define INIT_REFCOUNTED_STATE(type, sts, cb, aux) \ type *sts = (type *)imap_refcounted_new_state( sizeof(type) ); \ sts->callback = cb; \ sts->callback_aux = aux; static imap_cmd_t * imap_refcounted_new_cmd( imap_cmd_refcounted_state_t *sts ) { imap_cmd_refcounted_t *cmd = (imap_cmd_refcounted_t *)new_imap_cmd( sizeof(*cmd) ); cmd->state = sts; sts->ref_count++; return &cmd->gen; } #define DONE_REFCOUNTED_STATE(sts) \ if (!--sts->gen.ref_count) { \ sts->callback( sts->gen.ret_val, sts->callback_aux ); \ free( sts ); \ } #define DONE_REFCOUNTED_STATE_ARGS(sts, ...) \ if (!--sts->gen.ref_count) { \ sts->callback( sts->gen.ret_val, __VA_ARGS__, sts->callback_aux ); \ free( sts ); \ } static void transform_refcounted_box_response( imap_cmd_refcounted_state_t *sts, int response ) { switch (response) { case RESP_CANCEL: sts->ret_val = DRV_CANCELED; break; case RESP_NO: if (sts->ret_val == DRV_OK) /* Don't override cancelation. */ sts->ret_val = DRV_BOX_BAD; break; } } static void transform_refcounted_msg_response( imap_cmd_refcounted_state_t *sts, int response ) { switch (response) { case RESP_CANCEL: sts->ret_val = DRV_CANCELED; break; case RESP_NO: if (sts->ret_val == DRV_OK) /* Don't override cancelation. */ sts->ret_val = DRV_MSG_BAD; break; } } static const char * imap_strchr( const char *s, char tc ) { for (;; s++) { char c = *s; if (c == '\\') c = *++s; if (!c) return 0; if (c == tc) return s; } } static char * next_arg( char **ps ) { char *ret, *s, *d; char c; assert( ps ); s = *ps; if (!s) return 0; while (isspace( (uchar)*s )) s++; if (!*s) { *ps = 0; return 0; } if (*s == '"') { s++; ret = d = s; while ((c = *s++) != '"') { if (c == '\\') c = *s++; if (!c) { *ps = 0; return 0; } *d++ = c; } *d = 0; } else { ret = s; while ((c = *s)) { if (isspace( (uchar)c )) { *s++ = 0; break; } s++; } } if (!*s) s = 0; *ps = s; return ret; } static int is_opt_atom( list_t *list ) { return list && list->val && list->val != LIST; } static int is_atom( list_t *list ) { return list && list->val && list->val != NIL && list->val != LIST; } static int is_list( list_t *list ) { return list && list->val == LIST; } static void free_list( list_t *list ) { list_t *tmp; for (; list; list = tmp) { tmp = list->next; if (is_list( list )) free_list( list->child ); else if (is_atom( list )) free( list->val ); free( list ); } } enum { LIST_OK, LIST_PARTIAL, LIST_BAD }; static int parse_imap_list( imap_store_t *ctx, char **sp, parse_list_state_t *sts ) { list_t *cur, **curp; char *s = *sp, *d, *p; int n, bytes; char c; assert( sts ); assert( sts->level > 0 ); curp = sts->stack[--sts->level]; bytes = sts->need_bytes; if (bytes >= 0) { sts->need_bytes = -1; if (!bytes) goto getline; cur = (list_t *)((char *)curp - offsetof(list_t, next)); s = cur->val + cur->len - bytes; goto getbytes; } if (!s) return LIST_BAD; for (;;) { while (isspace( (uchar)*s )) s++; if (sts->level && *s == ')') { s++; curp = sts->stack[--sts->level]; goto next; } *curp = cur = nfmalloc( sizeof(*cur) ); cur->val = 0; /* for clean bail */ curp = &cur->next; *curp = 0; /* ditto */ if (*s == '(') { /* sublist */ if (sts->level == MAX_LIST_DEPTH) goto bail; s++; cur->val = LIST; sts->stack[sts->level++] = curp; curp = &cur->child; *curp = 0; /* for clean bail */ goto next2; } else if (ctx && *s == '{') { /* literal */ bytes = cur->len = strtol( s + 1, &s, 10 ); if (*s != '}' || *++s) goto bail; s = cur->val = nfmalloc( cur->len + 1 ); s[cur->len] = 0; getbytes: n = socket_read( &ctx->conn, s, bytes ); if (n < 0) { badeof: error( "IMAP error: unexpected EOF from %s\n", ctx->conn.name ); goto bail; } bytes -= n; if (bytes > 0) goto postpone; if (DFlags & DEBUG_NET_ALL) { printf( "%s=========\n", ctx->label ); fwrite( cur->val, cur->len, 1, stdout ); printf( "%s=========\n", ctx->label ); fflush( stdout ); } getline: if (!(s = socket_read_line( &ctx->conn ))) goto postpone; if (s == (void *)~0) goto badeof; if (DFlags & DEBUG_NET) { printf( "%s%s\n", ctx->label, s ); fflush( stdout ); } } else if (*s == '"') { /* quoted string */ s++; p = d = s; while ((c = *s++) != '"') { if (c == '\\') c = *s++; if (!c) goto bail; *d++ = c; } cur->len = d - p; cur->val = nfstrndup( p, cur->len ); } else { /* atom */ p = s; for (; *s && !isspace( (uchar)*s ); s++) if (sts->level && *s == ')') break; cur->len = s - p; if (equals( p, cur->len, "NIL", 3 )) cur->val = NIL; else cur->val = nfstrndup( p, cur->len ); } next: if (!sts->level) break; next2: if (!*s) goto bail; } *sp = s; return LIST_OK; postpone: if (sts->level < MAX_LIST_DEPTH) { sts->stack[sts->level++] = curp; sts->need_bytes = bytes; return LIST_PARTIAL; } bail: free_list( sts->head ); return LIST_BAD; } static void parse_list_init( parse_list_state_t *sts ) { sts->need_bytes = -1; sts->level = 1; sts->head = 0; sts->stack[0] = &sts->head; } static int parse_list_continue( imap_store_t *ctx, char *s ) { list_t *list; int resp; if ((resp = parse_imap_list( ctx, &s, &ctx->parse_list_sts )) != LIST_PARTIAL) { list = (resp == LIST_BAD) ? 0 : ctx->parse_list_sts.head; ctx->parse_list_sts.head = 0; resp = ctx->parse_list_sts.callback( ctx, list, s ); } return resp; } static int parse_list( imap_store_t *ctx, char *s, int (*cb)( imap_store_t *ctx, list_t *list, char *s ) ) { parse_list_init( &ctx->parse_list_sts ); ctx->parse_list_sts.callback = cb; return parse_list_continue( ctx, s ); } static int parse_namespace_rsp_p2( imap_store_t *, list_t *, char * ); static int parse_namespace_rsp_p3( imap_store_t *, list_t *, char * ); static int parse_namespace_check( list_t *list ) { if (!list) goto bad; if (list->val == NIL) return 0; if (list->val != LIST) goto bad; for (list = list->child; list; list = list->next) { if (list->val != LIST) goto bad; if (!is_atom( list->child )) goto bad; if (!is_opt_atom( list->child->next )) goto bad; /* Namespace response extensions may follow here; we don't care. */ } return 0; bad: error( "IMAP error: malformed NAMESPACE response\n" ); return -1; } static int parse_namespace_rsp( imap_store_t *ctx, list_t *list, char *s ) { if (parse_namespace_check( (ctx->ns_personal = list) )) return LIST_BAD; return parse_list( ctx, s, parse_namespace_rsp_p2 ); } static int parse_namespace_rsp_p2( imap_store_t *ctx, list_t *list, char *s ) { if (parse_namespace_check( (ctx->ns_other = list) )) return LIST_BAD; return parse_list( ctx, s, parse_namespace_rsp_p3 ); } static int parse_namespace_rsp_p3( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) { if (parse_namespace_check( (ctx->ns_shared = list) )) return LIST_BAD; return LIST_OK; } static time_t parse_date( const char *str ) { char *end; time_t date; int hours, mins; struct tm datetime; memset( &datetime, 0, sizeof(datetime) ); if (!(end = strptime( str, "%d-%b-%Y %H:%M:%S ", &datetime ))) return -1; if ((date = timegm( &datetime )) == -1) return -1; if (sscanf( end, "%3d%2d", &hours, &mins ) != 2) return -1; return date - (hours * 60 + mins) * 60; } static int parse_fetch_rsp( imap_store_t *ctx, list_t *list, char *s ATTR_UNUSED ) { list_t *tmp, *flags; char *body = 0, *tuid = 0, *msgid = 0, *ep; imap_message_t *cur; msg_data_t *msgdata; imap_cmd_t *cmdp; int mask = 0, status = 0, size = 0; uint i, uid = 0; time_t date = 0; if (!is_list( list )) { error( "IMAP error: bogus FETCH response\n" ); free_list( list ); return LIST_BAD; } for (tmp = list->child; tmp; tmp = tmp->next) { if (is_atom( tmp )) { if (!strcmp( "UID", tmp->val )) { tmp = tmp->next; if (!is_atom( tmp ) || (uid = strtoul( tmp->val, &ep, 10 ), *ep)) error( "IMAP error: unable to parse UID\n" ); } else if (!strcmp( "FLAGS", tmp->val )) { tmp = tmp->next; if (is_list( tmp )) { for (flags = tmp->child; flags; flags = flags->next) { if (is_atom( flags )) { if (flags->val[0] == '\\') { /* ignore user-defined flags for now */ if (!strcmp( "Recent", flags->val + 1)) { status |= M_RECENT; goto flagok; } for (i = 0; i < as(Flags); i++) if (!strcmp( Flags[i], flags->val + 1 )) { mask |= 1 << i; goto flagok; } if (flags->val[1] == 'X' && flags->val[2] == '-') goto flagok; /* ignore system flag extensions */ error( "IMAP warning: unknown system flag %s\n", flags->val ); } flagok: ; } else error( "IMAP error: unable to parse FLAGS list\n" ); } status |= M_FLAGS; } else error( "IMAP error: unable to parse FLAGS\n" ); } else if (!strcmp( "INTERNALDATE", tmp->val )) { tmp = tmp->next; if (is_atom( tmp )) { if ((date = parse_date( tmp->val )) == -1) error( "IMAP error: unable to parse INTERNALDATE format\n" ); } else error( "IMAP error: unable to parse INTERNALDATE\n" ); } else if (!strcmp( "RFC822.SIZE", tmp->val )) { tmp = tmp->next; if (!is_atom( tmp ) || (size = strtoul( tmp->val, &ep, 10 ), *ep)) error( "IMAP error: unable to parse RFC822.SIZE\n" ); } else if (!strcmp( "BODY[]", tmp->val )) { tmp = tmp->next; if (is_atom( tmp )) { body = tmp->val; tmp->val = 0; /* don't free together with list */ size = tmp->len; } else error( "IMAP error: unable to parse BODY[]\n" ); } else if (!strcmp( "BODY[HEADER.FIELDS", tmp->val )) { tmp = tmp->next; if (is_list( tmp )) { tmp = tmp->next; if (!is_atom( tmp ) || strcmp( tmp->val, "]" )) goto bfail; tmp = tmp->next; if (!is_atom( tmp )) goto bfail; int off, in_msgid = 0; for (char *val = tmp->val, *end; (end = strchr( val, '\n' )); val = end + 1) { int len = (int)(end - val); if (len && end[-1] == '\r') len--; if (!len) break; if (starts_with_upper( val, len, "X-TUID: ", 8 )) { if (len < 8 + TUIDL) { error( "IMAP error: malformed X-TUID header (UID %u)\n", uid ); continue; } tuid = val + 8; in_msgid = 0; continue; } if (starts_with_upper( val, len, "MESSAGE-ID:", 11 )) { off = 11; } else if (in_msgid) { if (!isspace( val[0] )) { in_msgid = 0; continue; } off = 1; } else { continue; } while (off < len && isspace( val[off] )) off++; if (off == len) { in_msgid = 1; continue; } msgid = nfstrndup( val + off, len - off ); in_msgid = 0; } } else { bfail: error( "IMAP error: unable to parse BODY[HEADER.FIELDS ...]\n" ); } } } } if (!uid) { assert( !body && !tuid && !msgid ); // Ignore async flag updates for now. } else if ((cmdp = ctx->in_progress) && cmdp->param.lastuid) { assert( !body && !tuid && !msgid ); // Workaround for server not sending UIDNEXT and/or APPENDUID. ctx->uidnext = uid + 1; } else if (body) { assert( !tuid && !msgid ); for (cmdp = ctx->in_progress; cmdp; cmdp = cmdp->next) if (cmdp->param.uid == uid) goto gotuid; error( "IMAP error: unexpected FETCH response (UID %u)\n", uid ); free_list( list ); return LIST_BAD; gotuid: msgdata = ((imap_cmd_fetch_msg_t *)cmdp)->msg_data; msgdata->data = body; msgdata->len = size; msgdata->date = date; if (status & M_FLAGS) msgdata->flags = mask; } else { /* XXX this will need sorting for out-of-order (multiple queries) */ cur = nfcalloc( sizeof(*cur) ); *ctx->msgapp = &cur->gen; ctx->msgapp = &cur->gen.next; cur->gen.next = 0; cur->gen.uid = uid; cur->gen.flags = mask; cur->gen.status = status; cur->gen.size = size; cur->gen.srec = 0; cur->gen.msgid = msgid; if (tuid) memcpy( cur->gen.tuid, tuid, TUIDL ); else cur->gen.tuid[0] = 0; } free_list( list ); return LIST_OK; } static void parse_capability( imap_store_t *ctx, char *cmd ) { char *arg; uint i; free_string_list( ctx->auth_mechs ); ctx->auth_mechs = 0; ctx->caps = 0x80000000; while ((arg = next_arg( &cmd ))) { if (starts_with( arg, -1, "AUTH=", 5 )) { add_string_list( &ctx->auth_mechs, arg + 5 ); } else { for (i = 0; i < as(cap_list); i++) if (!strcmp( cap_list[i], arg )) ctx->caps |= 1 << i; } } ctx->caps &= ~((imap_store_conf_t *)ctx->gen.conf)->server->cap_mask; if (!CAP(NOLOGIN)) add_string_list( &ctx->auth_mechs, "LOGIN" ); } static int parse_response_code( imap_store_t *ctx, imap_cmd_t *cmd, char *s ) { char *arg, *earg, *p; if (!s || *s != '[') return RESP_OK; /* no response code */ s++; if (!(p = strchr( s, ']' ))) { bad_resp: error( "IMAP error: malformed response code\n" ); return RESP_CANCEL; } *p++ = 0; if (!(arg = next_arg( &s ))) goto bad_resp; if (!strcmp( "UIDVALIDITY", arg )) { if (!(arg = next_arg( &s )) || (ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg)) { error( "IMAP error: malformed UIDVALIDITY status\n" ); return RESP_CANCEL; } } else if (!strcmp( "UIDNEXT", arg )) { if (!(arg = next_arg( &s )) || (ctx->uidnext = strtoul( arg, &earg, 10 ), *earg)) { error( "IMAP error: malformed NEXTUID status\n" ); return RESP_CANCEL; } } else if (!strcmp( "CAPABILITY", arg )) { parse_capability( ctx, s ); } else if (!strcmp( "ALERT", arg )) { /* RFC2060 says that these messages MUST be displayed * to the user */ for (; isspace( (uchar)*p ); p++); error( "*** IMAP ALERT *** %s\n", p ); } else if (cmd && !strcmp( "APPENDUID", arg )) { if (!(arg = next_arg( &s )) || (ctx->uidvalidity = strtoul( arg, &earg, 10 ), *earg) || !(arg = next_arg( &s )) || (((imap_cmd_out_uid_t *)cmd)->out_uid = strtoul( arg, &earg, 10 ), *earg)) { error( "IMAP error: malformed APPENDUID status\n" ); return RESP_CANCEL; } } return RESP_OK; } static int parse_list_rsp_p2( imap_store_t *, list_t *, char * ); static int parse_list_rsp( imap_store_t *ctx, list_t *list, char *cmd ) { char *arg; list_t *lp; if (!is_list( list )) { free_list( list ); bad_list: error( "IMAP error: malformed LIST response\n" ); return LIST_BAD; } for (lp = list->child; lp; lp = lp->next) if (is_atom( lp ) && !strcasecmp( lp->val, "\\NoSelect" )) { free_list( list ); return LIST_OK; } free_list( list ); if (!(arg = next_arg( &cmd ))) goto bad_list; if (!ctx->delimiter[0]) ctx->delimiter[0] = arg[0]; return parse_list( ctx, cmd, parse_list_rsp_p2 ); } static int is_inbox( imap_store_t *ctx, const char *arg, int argl ) { if (!starts_with( arg, argl, "INBOX", 5 )) return 0; if (arg[5] && arg[5] != ctx->delimiter[0]) return 0; return 1; } static int parse_list_rsp_p2( imap_store_t *ctx, list_t *list, char *cmd ATTR_UNUSED ) { string_list_t *narg; char *arg; int argl, l; if (!is_atom( list )) { error( "IMAP error: malformed LIST response\n" ); free_list( list ); return LIST_BAD; } arg = list->val; argl = list->len; if ((l = strlen( ctx->prefix ))) { if (starts_with( arg, argl, ctx->prefix, l )) { arg += l; argl -= l; if (is_inbox( ctx, arg, argl )) { if (!arg[5]) warn( "IMAP warning: ignoring INBOX in %s\n", ctx->prefix ); goto skip; } } else if (!is_inbox( ctx, arg, argl )) { goto skip; } } if (argl >= 5 && !memcmp( arg + argl - 5, ".lock", 5 )) /* workaround broken servers */ goto skip; if (map_name( arg, (char **)&narg, offsetof(string_list_t, string), ctx->delimiter, "/") < 0) { warn( "IMAP warning: ignoring mailbox %s (reserved character '/' in name)\n", arg ); goto skip; } narg->next = ctx->boxes; ctx->boxes = narg; skip: free_list( list ); return LIST_OK; } static int prepare_name( char **buf, const imap_store_t *ctx, const char *prefix, const char *name ) { int pl = strlen( prefix ); switch (map_name( name, buf, pl, "/", ctx->delimiter )) { case -1: error( "IMAP error: mailbox name %s contains server's hierarchy delimiter\n", name ); return -1; case -2: error( "IMAP error: server's hierarchy delimiter not known\n" ); return -1; default: memcpy( *buf, prefix, pl ); return 0; } } static int prepare_box( char **buf, const imap_store_t *ctx ) { const char *name = ctx->name; return prepare_name( buf, ctx, (starts_with( name, -1, "INBOX", 5 ) && (!name[5] || name[5] == '/')) ? "" : ctx->prefix, name ); } static int prepare_trash( char **buf, const imap_store_t *ctx ) { return prepare_name( buf, ctx, ctx->prefix, ctx->gen.conf->trash ); } typedef struct { imap_cmd_t gen; imap_cmd_t *orig_cmd; } imap_cmd_trycreate_t; static void imap_open_store_greeted( imap_store_t * ); static void get_cmd_result_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_socket_read( void *aux ) { imap_store_t *ctx = (imap_store_t *)aux; imap_cmd_t *cmdp, **pcmdp; char *cmd, *arg, *arg1, *p; int resp, resp2, tag; conn_iovec_t iov[2]; for (;;) { if (ctx->parse_list_sts.level) { resp = parse_list_continue( ctx, 0 ); listret: if (resp == LIST_PARTIAL) return; if (resp == LIST_BAD) break; continue; } if (!(cmd = socket_read_line( &ctx->conn ))) return; if (cmd == (void *)~0) { if (!ctx->expectEOF) error( "IMAP error: unexpected EOF from %s\n", ctx->conn.name ); /* A clean shutdown sequence ends with bad_callback as well (see imap_cleanup()). */ break; } if (DFlags & DEBUG_NET) { printf( "%s%s\n", ctx->label, cmd ); fflush( stdout ); } arg = next_arg( &cmd ); if (!arg) { error( "IMAP error: empty response\n" ); break; } if (*arg == '*') { arg = next_arg( &cmd ); if (!arg) { error( "IMAP error: malformed untagged response\n" ); break; } if (ctx->greeting == GreetingPending && !strcmp( "PREAUTH", arg )) { parse_response_code( ctx, 0, cmd ); ctx->greeting = GreetingPreauth; dogreet: imap_ref( ctx ); imap_open_store_greeted( ctx ); if (imap_deref( ctx )) return; } else if (!strcmp( "OK", arg )) { parse_response_code( ctx, 0, cmd ); if (ctx->greeting == GreetingPending) { ctx->greeting = GreetingOk; goto dogreet; } } else if (!strcmp( "BYE", arg )) { if (!ctx->expectBYE) { ctx->greeting = GreetingBad; error( "IMAP error: unexpected BYE response: %s\n", cmd ); /* We just wait for the server to close the connection now. */ ctx->expectEOF = 1; } else { /* We still need to wait for the LOGOUT's tagged OK. */ } } else if (ctx->greeting == GreetingPending) { error( "IMAP error: bogus greeting response %s\n", arg ); break; } else if (!strcmp( "NO", arg )) { warn( "Warning from IMAP server: %s\n", cmd ); } else if (!strcmp( "BAD", arg )) { error( "Error from IMAP server: %s\n", cmd ); } else if (!strcmp( "CAPABILITY", arg )) { parse_capability( ctx, cmd ); } else if (!strcmp( "LIST", arg )) { resp = parse_list( ctx, cmd, parse_list_rsp ); goto listret; } else if (!strcmp( "NAMESPACE", arg )) { resp = parse_list( ctx, cmd, parse_namespace_rsp ); goto listret; } else if ((arg1 = next_arg( &cmd ))) { if (!strcmp( "EXISTS", arg1 )) ctx->total_msgs = atoi( arg ); else if (!strcmp( "RECENT", arg1 )) ctx->recent_msgs = atoi( arg ); else if(!strcmp ( "FETCH", arg1 )) { resp = parse_list( ctx, cmd, parse_fetch_rsp ); goto listret; } } else { error( "IMAP error: unrecognized untagged response '%s'\n", arg ); break; /* this may mean anything, so prefer not to spam the log */ } continue; } else if (!ctx->in_progress) { error( "IMAP error: unexpected reply: %s %s\n", arg, cmd ? cmd : "" ); break; /* this may mean anything, so prefer not to spam the log */ } else if (*arg == '+') { socket_expect_read( &ctx->conn, 0 ); /* There can be any number of commands in flight, but only the last * one can require a continuation, as it enforces a round-trip. */ cmdp = (imap_cmd_t *)((char *)ctx->in_progress_append - offsetof(imap_cmd_t, next)); if (cmdp->param.data) { if (cmdp->param.to_trash) ctx->trashnc = TrashKnown; /* Can't get NO [TRYCREATE] any more. */ if (DFlags & DEBUG_NET_ALL) { printf( "%s>>>>>>>>>\n", ctx->label ); fwrite( cmdp->param.data, cmdp->param.data_len, 1, stdout ); printf( "%s>>>>>>>>>\n", ctx->label ); fflush( stdout ); } iov[0].buf = cmdp->param.data; iov[0].len = cmdp->param.data_len; iov[0].takeOwn = GiveOwn; cmdp->param.data = 0; ctx->buffer_mem -= cmdp->param.data_len; iov[1].buf = "\r\n"; iov[1].len = 2; iov[1].takeOwn = KeepOwn; socket_write( &ctx->conn, iov, 2 ); } else if (cmdp->param.cont) { if (cmdp->param.cont( ctx, cmdp, cmd )) return; } else { error( "IMAP error: unexpected command continuation request\n" ); break; } socket_expect_read( &ctx->conn, 1 ); } else { tag = atoi( arg ); for (pcmdp = &ctx->in_progress; (cmdp = *pcmdp); pcmdp = &cmdp->next) if (cmdp->tag == tag) goto gottag; error( "IMAP error: unexpected tag %s\n", arg ); break; gottag: if (!(*pcmdp = cmdp->next)) ctx->in_progress_append = pcmdp; if (!--ctx->num_in_progress) socket_expect_read( &ctx->conn, 0 ); arg = next_arg( &cmd ); if (!arg) { error( "IMAP error: malformed tagged response\n" ); break; } if (!strcmp( "OK", arg )) { if (cmdp->param.to_trash) ctx->trashnc = TrashKnown; /* Can't get NO [TRYCREATE] any more. */ resp = RESP_OK; } else { if (!strcmp( "NO", arg )) { if (cmdp->param.create && cmd && starts_with( cmd, -1, "[TRYCREATE]", 11 )) { /* APPEND or UID COPY */ imap_cmd_trycreate_t *cmd2 = (imap_cmd_trycreate_t *)new_imap_cmd( sizeof(*cmd2) ); cmd2->orig_cmd = cmdp; cmd2->gen.param.high_prio = 1; p = strchr( cmdp->cmd, '"' ); imap_exec( ctx, &cmd2->gen, get_cmd_result_p2, "CREATE %.*s", imap_strchr( p + 1, '"' ) - p + 1, p ); continue; } resp = RESP_NO; if (cmdp->param.failok) goto doresp; } else /*if (!strcmp( "BAD", arg ))*/ resp = RESP_CANCEL; error( "IMAP command '%s' returned an error: %s %s\n", starts_with( cmdp->cmd, -1, "LOGIN", 5 ) ? "LOGIN " : starts_with( cmdp->cmd, -1, "AUTHENTICATE PLAIN", 18 ) ? "AUTHENTICATE PLAIN " : cmdp->cmd, arg, cmd ? cmd : "" ); } doresp: if ((resp2 = parse_response_code( ctx, cmdp, cmd )) > resp) resp = resp2; imap_ref( ctx ); if (resp == RESP_CANCEL) imap_invoke_bad_callback( ctx ); done_imap_cmd( ctx, cmdp, resp ); if (imap_deref( ctx )) return; if (ctx->canceling && !ctx->in_progress) { ctx->canceling = 0; ctx->callbacks.imap_cancel( ctx->callback_aux ); return; } } flush_imap_cmds( ctx ); } imap_invoke_bad_callback( ctx ); } static void get_cmd_result_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response ) { imap_cmd_trycreate_t *cmdp = (imap_cmd_trycreate_t *)cmd; imap_cmd_t *ocmd = cmdp->orig_cmd; if (response != RESP_OK) { done_imap_cmd( ctx, ocmd, response ); } else { ctx->uidnext = 1; if (ocmd->param.to_trash) ctx->trashnc = TrashKnown; ocmd->param.create = 0; ocmd->param.high_prio = 1; submit_imap_cmd( ctx, ocmd ); } } /******************* imap_cancel_store *******************/ static void imap_cleanup_store( imap_store_t *ctx ) { free_generic_messages( ctx->msgs ); free_string_list( ctx->boxes ); } static void imap_cancel_store( store_t *gctx ) { imap_store_t *ctx = (imap_store_t *)gctx; #ifdef HAVE_LIBSASL sasl_dispose( &ctx->sasl ); #endif socket_close( &ctx->conn ); cancel_sent_imap_cmds( ctx ); cancel_pending_imap_cmds( ctx ); free_list( ctx->ns_personal ); free_list( ctx->ns_other ); free_list( ctx->ns_shared ); free_string_list( ctx->auth_mechs ); imap_cleanup_store( ctx ); imap_deref( ctx ); } static int imap_deref( imap_store_t *ctx ) { if (!--ctx->ref_count) { free( ctx ); return -1; } return 0; } static void imap_set_bad_callback( store_t *gctx, void (*cb)( void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; ctx->bad_callback = cb; ctx->bad_callback_aux = aux; } static void imap_invoke_bad_callback( imap_store_t *ctx ) { ctx->bad_callback( ctx->bad_callback_aux ); } /******************* imap_free_store *******************/ static store_t *unowned; static void imap_cancel_unowned( void *gctx ) { store_t *store, **storep; for (storep = &unowned; (store = *storep); storep = &store->next) if (store == gctx) { *storep = store->next; break; } imap_cancel_store( gctx ); } static void imap_free_store( store_t *gctx ) { imap_store_t *ctx = (imap_store_t *)gctx; free_generic_messages( ctx->msgs ); ctx->msgs = 0; imap_set_bad_callback( gctx, imap_cancel_unowned, gctx ); gctx->next = unowned; unowned = gctx; } /******************* imap_cleanup *******************/ static void imap_cleanup_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_cleanup( void ) { store_t *ctx, *nctx; for (ctx = unowned; ctx; ctx = nctx) { nctx = ctx->next; imap_set_bad_callback( ctx, (void (*)(void *))imap_cancel_store, ctx ); if (((imap_store_t *)ctx)->state != SST_BAD) { ((imap_store_t *)ctx)->expectBYE = 1; imap_exec( (imap_store_t *)ctx, 0, imap_cleanup_p2, "LOGOUT" ); } else { imap_cancel_store( ctx ); } } } static void imap_cleanup_p2( imap_store_t *ctx, imap_cmd_t *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) imap_cancel_store( &ctx->gen ); else if (response == RESP_OK) ctx->expectEOF = 1; } /******************* imap_open_store *******************/ static void imap_open_store_connected( int, void * ); #ifdef HAVE_LIBSSL static void imap_open_store_tlsstarted1( int, void * ); #endif static void imap_open_store_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_open_store_authenticate( imap_store_t * ); #ifdef HAVE_LIBSSL static void imap_open_store_authenticate_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_open_store_tlsstarted2( int, void * ); static void imap_open_store_authenticate_p3( imap_store_t *, imap_cmd_t *, int ); #endif static void imap_open_store_authenticate2( imap_store_t * ); static void imap_open_store_authenticate2_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_open_store_compress( imap_store_t * ); #ifdef HAVE_LIBZ static void imap_open_store_compress_p2( imap_store_t *, imap_cmd_t *, int ); #endif static void imap_open_store_namespace( imap_store_t * ); static void imap_open_store_namespace_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_open_store_namespace2( imap_store_t * ); static void imap_open_store_finalize( imap_store_t * ); #ifdef HAVE_LIBSSL static void imap_open_store_ssl_bail( imap_store_t * ); #endif static void imap_open_store_bail( imap_store_t *, int ); static store_t * imap_alloc_store( store_conf_t *conf, const char *label ) { imap_store_conf_t *cfg = (imap_store_conf_t *)conf; imap_server_conf_t *srvc = cfg->server; imap_store_t *ctx; store_t **ctxp; /* First try to recycle a whole store. */ for (ctxp = &unowned; (ctx = (imap_store_t *)*ctxp); ctxp = &ctx->gen.next) if (ctx->state == SST_GOOD && ctx->gen.conf == conf) { *ctxp = ctx->gen.next; ctx->label = label; return &ctx->gen; } /* Then try to recycle a server connection. */ for (ctxp = &unowned; (ctx = (imap_store_t *)*ctxp); ctxp = &ctx->gen.next) if (ctx->state != SST_BAD && ((imap_store_conf_t *)ctx->gen.conf)->server == srvc) { *ctxp = ctx->gen.next; imap_cleanup_store( ctx ); /* One could ping the server here, but given that the idle timeout * is at least 30 minutes, this sounds pretty pointless. */ ctx->state = SST_HALF; goto gotsrv; } /* Finally, schedule opening a new server connection. */ ctx = nfcalloc( sizeof(*ctx) ); socket_init( &ctx->conn, &srvc->sconf, (void (*)( void * ))imap_invoke_bad_callback, imap_socket_read, (void (*)(void *))flush_imap_cmds, ctx ); ctx->in_progress_append = &ctx->in_progress; ctx->pending_append = &ctx->pending; gotsrv: ctx->gen.driver = &imap_driver; ctx->gen.conf = conf; ctx->label = label; ctx->ref_count = 1; return &ctx->gen; } static void imap_connect_store( store_t *gctx, void (*cb)( int sts, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; if (ctx->state == SST_GOOD) { cb( DRV_OK, aux ); } else { ctx->callbacks.imap_open = cb; ctx->callback_aux = aux; if (ctx->state == SST_HALF) imap_open_store_namespace( ctx ); else socket_connect( &ctx->conn, imap_open_store_connected ); } } static void imap_open_store_connected( int ok, void *aux ) { imap_store_t *ctx = (imap_store_t *)aux; #ifdef HAVE_LIBSSL imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf; imap_server_conf_t *srvc = cfg->server; #endif if (!ok) imap_open_store_bail( ctx, FAIL_WAIT ); #ifdef HAVE_LIBSSL else if (srvc->ssl_type == SSL_IMAPS) socket_start_tls( &ctx->conn, imap_open_store_tlsstarted1 ); #endif else socket_expect_read( &ctx->conn, 1 ); } #ifdef HAVE_LIBSSL static void imap_open_store_tlsstarted1( int ok, void *aux ) { imap_store_t *ctx = (imap_store_t *)aux; if (!ok) imap_open_store_ssl_bail( ctx ); else socket_expect_read( &ctx->conn, 1 ); } #endif static void imap_open_store_greeted( imap_store_t *ctx ) { socket_expect_read( &ctx->conn, 0 ); if (!ctx->caps) imap_exec( ctx, 0, imap_open_store_p2, "CAPABILITY" ); else imap_open_store_authenticate( ctx ); } static void imap_open_store_p2( imap_store_t *ctx, imap_cmd_t *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) imap_open_store_bail( ctx, FAIL_FINAL ); else if (response == RESP_OK) imap_open_store_authenticate( ctx ); } static void imap_open_store_authenticate( imap_store_t *ctx ) { #ifdef HAVE_LIBSSL imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf; imap_server_conf_t *srvc = cfg->server; #endif if (ctx->greeting != GreetingPreauth) { #ifdef HAVE_LIBSSL if (srvc->ssl_type == SSL_STARTTLS) { if (CAP(STARTTLS)) { imap_exec( ctx, 0, imap_open_store_authenticate_p2, "STARTTLS" ); return; } else { error( "IMAP error: SSL support not available\n" ); imap_open_store_bail( ctx, FAIL_FINAL ); return; } } #endif imap_open_store_authenticate2( ctx ); } else { #ifdef HAVE_LIBSSL if (srvc->ssl_type == SSL_STARTTLS) { error( "IMAP error: SSL support not available\n" ); imap_open_store_bail( ctx, FAIL_FINAL ); return; } #endif imap_open_store_compress( ctx ); } } #ifdef HAVE_LIBSSL static void imap_open_store_authenticate_p2( imap_store_t *ctx, imap_cmd_t *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) imap_open_store_bail( ctx, FAIL_FINAL ); else if (response == RESP_OK) socket_start_tls( &ctx->conn, imap_open_store_tlsstarted2 ); } static void imap_open_store_tlsstarted2( int ok, void *aux ) { imap_store_t *ctx = (imap_store_t *)aux; if (!ok) imap_open_store_ssl_bail( ctx ); else imap_exec( ctx, 0, imap_open_store_authenticate_p3, "CAPABILITY" ); } static void imap_open_store_authenticate_p3( imap_store_t *ctx, imap_cmd_t *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) imap_open_store_bail( ctx, FAIL_FINAL ); else if (response == RESP_OK) imap_open_store_authenticate2( ctx ); } #endif static const char * ensure_user( imap_server_conf_t *srvc ) { if (!srvc->user) { error( "Skipping account %s, no user\n", srvc->name ); return 0; } return srvc->user; } static const char * ensure_password( imap_server_conf_t *srvc ) { char *cmd = srvc->pass_cmd; if (cmd) { FILE *fp; int ret; char buffer[80]; if (*cmd == '+') { flushn(); cmd++; } if (!(fp = popen( cmd, "r" ))) { pipeerr: sys_error( "Skipping account %s, password command failed", srvc->name ); return 0; } if (!fgets( buffer, sizeof(buffer), fp )) buffer[0] = 0; if ((ret = pclose( fp )) < 0) goto pipeerr; if (ret) { if (WIFSIGNALED( ret )) error( "Skipping account %s, password command crashed\n", srvc->name ); else error( "Skipping account %s, password command exited with status %d\n", srvc->name, WEXITSTATUS( ret ) ); return 0; } if (!buffer[0]) { error( "Skipping account %s, password command produced no output\n", srvc->name ); return 0; } buffer[strcspn( buffer, "\n" )] = 0; /* Strip trailing newline */ free( srvc->pass ); /* From previous runs */ srvc->pass = nfstrdup( buffer ); } else if (!srvc->pass) { char *pass, prompt[80]; flushn(); sprintf( prompt, "Password (%s): ", srvc->name ); pass = getpass( prompt ); if (!pass) { perror( "getpass" ); exit( 1 ); } if (!*pass) { error( "Skipping account %s, no password\n", srvc->name ); return 0; } /* getpass() returns a pointer to a static buffer. Make a copy for long term storage. */ srvc->pass = nfstrdup( pass ); } return srvc->pass; } #ifdef HAVE_LIBSASL static sasl_callback_t sasl_callbacks[] = { { SASL_CB_USER, NULL, NULL }, { SASL_CB_AUTHNAME, NULL, NULL }, { SASL_CB_PASS, NULL, NULL }, { SASL_CB_LIST_END, NULL, NULL } }; static int process_sasl_interact( sasl_interact_t *interact, imap_server_conf_t *srvc ) { const char *val; for (;; ++interact) { switch (interact->id) { case SASL_CB_LIST_END: return 0; case SASL_CB_USER: case SASL_CB_AUTHNAME: val = ensure_user( srvc ); break; case SASL_CB_PASS: val = ensure_password( srvc ); break; default: error( "Error: Unknown SASL interaction ID\n" ); return -1; } if (!val) return -1; interact->result = val; interact->len = strlen( val ); } } static int process_sasl_step( imap_store_t *ctx, int rc, const char *in, uint in_len, sasl_interact_t *interact, const char **out, uint *out_len ) { imap_server_conf_t *srvc = ((imap_store_conf_t *)ctx->gen.conf)->server; while (rc == SASL_INTERACT) { if (process_sasl_interact( interact, srvc ) < 0) return -1; rc = sasl_client_step( ctx->sasl, in, in_len, &interact, out, out_len ); } if (rc == SASL_CONTINUE) { ctx->sasl_cont = 1; } else if (rc == SASL_OK) { ctx->sasl_cont = 0; } else { error( "Error: %s\n", sasl_errdetail( ctx->sasl ) ); return -1; } return 0; } static int decode_sasl_data( const char *prompt, char **in, uint *in_len ) { if (prompt) { int rc; uint prompt_len = strlen( prompt ); /* We're decoding, the output will be shorter than prompt_len. */ *in = nfmalloc( prompt_len ); rc = sasl_decode64( prompt, prompt_len, *in, prompt_len, in_len ); if (rc != SASL_OK) { free( *in ); error( "Error: SASL(%d): %s\n", rc, sasl_errstring( rc, NULL, NULL ) ); return -1; } } else { *in = NULL; *in_len = 0; } return 0; } static int encode_sasl_data( const char *out, uint out_len, char **enc, uint *enc_len ) { int rc; uint enc_len_max = ((out_len + 2) / 3) * 4 + 1; *enc = nfmalloc( enc_len_max ); rc = sasl_encode64( out, out_len, *enc, enc_len_max, enc_len ); if (rc != SASL_OK) { free( *enc ); error( "Error: SASL(%d): %s\n", rc, sasl_errstring( rc, NULL, NULL ) ); return -1; } return 0; } static int do_sasl_auth( imap_store_t *ctx, imap_cmd_t *cmdp ATTR_UNUSED, const char *prompt ) { int rc, ret, iovcnt = 0; uint in_len, out_len, enc_len; const char *out; char *in, *enc; sasl_interact_t *interact = NULL; conn_iovec_t iov[2]; if (!ctx->sasl_cont) { error( "Error: IMAP wants more steps despite successful SASL authentication.\n" ); goto bail; } if (decode_sasl_data( prompt, &in, &in_len ) < 0) goto bail; rc = sasl_client_step( ctx->sasl, in, in_len, &interact, &out, &out_len ); ret = process_sasl_step( ctx, rc, in, in_len, interact, &out, &out_len ); free( in ); if (ret < 0) goto bail; if (out) { if (encode_sasl_data( out, out_len, &enc, &enc_len ) < 0) goto bail; iov[0].buf = enc; iov[0].len = enc_len; iov[0].takeOwn = GiveOwn; iovcnt = 1; if (DFlags & DEBUG_NET) { printf( "%s>+> %s\n", ctx->label, enc ); fflush( stdout ); } } else { if (DFlags & DEBUG_NET) { printf( "%s>+>\n", ctx->label ); fflush( stdout ); } } iov[iovcnt].buf = "\r\n"; iov[iovcnt].len = 2; iov[iovcnt].takeOwn = KeepOwn; iovcnt++; socket_write( &ctx->conn, iov, iovcnt ); return 0; bail: imap_open_store_bail( ctx, FAIL_FINAL ); return -1; } static void done_sasl_auth( imap_store_t *ctx, imap_cmd_t *cmd ATTR_UNUSED, int response ) { if (response == RESP_OK && ctx->sasl_cont) { sasl_interact_t *interact = NULL; const char *out; uint out_len; int rc = sasl_client_step( ctx->sasl, NULL, 0, &interact, &out, &out_len ); if (process_sasl_step( ctx, rc, NULL, 0, interact, &out, &out_len ) < 0) warn( "Warning: SASL reported failure despite successful IMAP authentication. Ignoring...\n" ); else if (out) warn( "Warning: SASL wants more steps despite successful IMAP authentication. Ignoring...\n" ); } imap_open_store_authenticate2_p2( ctx, NULL, response ); } #endif static void imap_open_store_authenticate2( imap_store_t *ctx ) { imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf; imap_server_conf_t *srvc = cfg->server; string_list_t *mech, *cmech; int auth_login = 0; int skipped_login = 0; #ifdef HAVE_LIBSASL const char *saslavail; char saslmechs[1024], *saslend = saslmechs; #endif info( "Logging in...\n" ); for (mech = srvc->auth_mechs; mech; mech = mech->next) { int any = !strcmp( mech->string, "*" ); for (cmech = ctx->auth_mechs; cmech; cmech = cmech->next) { if (any || !strcasecmp( mech->string, cmech->string )) { if (!strcasecmp( cmech->string, "LOGIN" )) { #ifdef HAVE_LIBSSL if (ctx->conn.ssl || !any) #else if (!any) #endif auth_login = 1; else skipped_login = 1; #ifdef HAVE_LIBSASL } else { int len = strlen( cmech->string ); if (saslend + len + 2 > saslmechs + sizeof(saslmechs)) oob(); *saslend++ = ' '; memcpy( saslend, cmech->string, len + 1 ); saslend += len; #endif } } } } #ifdef HAVE_LIBSASL if (saslend != saslmechs) { int rc; uint out_len = 0; char *enc = NULL; const char *gotmech = NULL, *out = NULL; sasl_interact_t *interact = NULL; imap_cmd_t *cmd; static int sasl_inited; if (!sasl_inited) { rc = sasl_client_init( sasl_callbacks ); if (rc != SASL_OK) { saslbail: error( "Error: SASL(%d): %s\n", rc, sasl_errstring( rc, NULL, NULL ) ); goto bail; } sasl_inited = 1; } rc = sasl_client_new( "imap", srvc->sconf.host, NULL, NULL, NULL, 0, &ctx->sasl ); if (rc != SASL_OK) { if (rc == SASL_NOMECH) goto notsasl; if (!ctx->sasl) goto saslbail; error( "Error: %s\n", sasl_errdetail( ctx->sasl ) ); goto bail; } rc = sasl_client_start( ctx->sasl, saslmechs + 1, &interact, CAP(SASLIR) ? &out : NULL, &out_len, &gotmech ); if (rc == SASL_NOMECH) goto notsasl; if (gotmech) info( "Authenticating with SASL mechanism %s...\n", gotmech ); /* Technically, we are supposed to loop over sasl_client_start(), * but it just calls sasl_client_step() anyway. */ if (process_sasl_step( ctx, rc, NULL, 0, interact, CAP(SASLIR) ? &out : NULL, &out_len ) < 0) goto bail; if (out) { if (!out_len) enc = nfstrdup( "=" ); /* A zero-length initial response is encoded as padding. */ else if (encode_sasl_data( out, out_len, &enc, NULL ) < 0) goto bail; } cmd = new_imap_cmd( sizeof(*cmd) ); cmd->param.cont = do_sasl_auth; imap_exec( ctx, cmd, done_sasl_auth, enc ? "AUTHENTICATE %s %s" : "AUTHENTICATE %s", gotmech, enc ); free( enc ); return; notsasl: if (!ctx->sasl || sasl_listmech( ctx->sasl, NULL, "", "", "", &saslavail, NULL, NULL ) != SASL_OK) saslavail = "(none)"; /* EXTERNAL is always there anyway. */ if (!auth_login) { error( "IMAP error: selected SASL mechanism(s) not available;\n" " selected:%s\n available: %s\n", saslmechs, saslavail ); goto skipnote; } info( "NOT using available SASL mechanism(s): %s\n", saslavail ); sasl_dispose( &ctx->sasl ); } #endif if (auth_login) { if (!ensure_user( srvc ) || !ensure_password( srvc )) goto bail; #ifdef HAVE_LIBSSL if (!ctx->conn.ssl) #endif warn( "*** IMAP Warning *** Password is being sent in the clear\n" ); imap_exec( ctx, 0, imap_open_store_authenticate2_p2, "LOGIN \"%\\s\" \"%\\s\"", srvc->user, srvc->pass ); return; } error( "IMAP error: server supports no acceptable authentication mechanism\n" ); #ifdef HAVE_LIBSASL skipnote: #endif if (skipped_login) error( "Note: not using LOGIN because connection is not encrypted;\n" " use 'AuthMechs LOGIN' explicitly to force it.\n" ); bail: imap_open_store_bail( ctx, FAIL_FINAL ); } static void imap_open_store_authenticate2_p2( imap_store_t *ctx, imap_cmd_t *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) imap_open_store_bail( ctx, FAIL_FINAL ); else if (response == RESP_OK) imap_open_store_compress( ctx ); } static void imap_open_store_compress( imap_store_t *ctx ) { #ifdef HAVE_LIBZ if (CAP(COMPRESS_DEFLATE)) { imap_exec( ctx, 0, imap_open_store_compress_p2, "COMPRESS DEFLATE" ); return; } #endif imap_open_store_namespace( ctx ); } #ifdef HAVE_LIBZ static void imap_open_store_compress_p2( imap_store_t *ctx, imap_cmd_t *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) { /* We already reported an error, but it's not fatal to us. */ imap_open_store_namespace( ctx ); } else if (response == RESP_OK) { socket_start_deflate( &ctx->conn ); imap_open_store_namespace( ctx ); } } #endif static void imap_open_store_namespace( imap_store_t *ctx ) { imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf; ctx->state = SST_HALF; ctx->prefix = cfg->gen.path; ctx->delimiter[0] = cfg->delimiter ? cfg->delimiter : 0; if (((!ctx->prefix && cfg->use_namespace) || !cfg->delimiter) && CAP(NAMESPACE)) { /* get NAMESPACE info */ if (!ctx->got_namespace) imap_exec( ctx, 0, imap_open_store_namespace_p2, "NAMESPACE" ); else imap_open_store_namespace2( ctx ); return; } imap_open_store_finalize( ctx ); } static void imap_open_store_namespace_p2( imap_store_t *ctx, imap_cmd_t *cmd ATTR_UNUSED, int response ) { if (response == RESP_NO) { imap_open_store_bail( ctx, FAIL_FINAL ); } else if (response == RESP_OK) { ctx->got_namespace = 1; imap_open_store_namespace2( ctx ); } } static void imap_open_store_namespace2( imap_store_t *ctx ) { imap_store_conf_t *cfg = (imap_store_conf_t *)ctx->gen.conf; list_t *nsp, *nsp_1st; /* XXX for now assume 1st personal namespace */ if (is_list( (nsp = ctx->ns_personal) ) && is_list( (nsp_1st = nsp->child) )) { list_t *nsp_1st_ns = nsp_1st->child; list_t *nsp_1st_dl = nsp_1st_ns->next; if (!ctx->prefix && cfg->use_namespace) ctx->prefix = nsp_1st_ns->val; if (!ctx->delimiter[0] && is_atom( nsp_1st_dl )) ctx->delimiter[0] = nsp_1st_dl->val[0]; } imap_open_store_finalize( ctx ); } static void imap_open_store_finalize( imap_store_t *ctx ) { ctx->state = SST_GOOD; if (!ctx->prefix) ctx->prefix = ""; ctx->trashnc = TrashUnknown; ctx->callbacks.imap_open( DRV_OK, ctx->callback_aux ); } #ifdef HAVE_LIBSSL static void imap_open_store_ssl_bail( imap_store_t *ctx ) { /* This avoids that we try to send LOGOUT to an unusable socket. */ socket_close( &ctx->conn ); imap_open_store_bail( ctx, FAIL_FINAL ); } #endif static void imap_open_store_bail( imap_store_t *ctx, int failed ) { ((imap_store_conf_t *)ctx->gen.conf)->server->failed = failed; ctx->callbacks.imap_open( DRV_STORE_BAD, ctx->callback_aux ); } /******************* imap_open_box *******************/ static int imap_select_box( store_t *gctx, const char *name ) { imap_store_t *ctx = (imap_store_t *)gctx; free_generic_messages( ctx->msgs ); ctx->msgs = 0; ctx->msgapp = &ctx->msgs; ctx->name = name; return DRV_OK; } static const char * imap_get_box_path( store_t *gctx ATTR_UNUSED ) { return 0; } typedef struct { imap_cmd_t gen; void (*callback)( int sts, int uidvalidity, void *aux ); void *callback_aux; } imap_cmd_open_box_t; static void imap_open_box_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_open_box_p3( imap_store_t *, imap_cmd_t *, int ); static void imap_open_box_p4( imap_store_t *, imap_cmd_open_box_t *, int ); static void imap_open_box( store_t *gctx, void (*cb)( int sts, int uidvalidity, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; imap_cmd_open_box_t *cmd; char *buf; if (prepare_box( &buf, ctx ) < 0) { cb( DRV_BOX_BAD, UIDVAL_BAD, aux ); return; } ctx->uidvalidity = UIDVAL_BAD; ctx->uidnext = 0; INIT_IMAP_CMD(imap_cmd_open_box_t, cmd, cb, aux) cmd->gen.param.failok = 1; imap_exec( ctx, &cmd->gen, imap_open_box_p2, "SELECT \"%\\s\"", buf ); free( buf ); } static void imap_open_box_p2( imap_store_t *ctx, imap_cmd_t *gcmd, int response ) { imap_cmd_open_box_t *cmdp = (imap_cmd_open_box_t *)gcmd; imap_cmd_open_box_t *cmd; if (response != RESP_OK || ctx->uidnext) { imap_open_box_p4( ctx, cmdp, response ); return; } INIT_IMAP_CMD(imap_cmd_open_box_t, cmd, cmdp->callback, cmdp->callback_aux) cmd->gen.param.lastuid = 1; imap_exec( ctx, &cmd->gen, imap_open_box_p3, "UID FETCH *:* (UID)" ); } static void imap_open_box_p3( imap_store_t *ctx, imap_cmd_t *gcmd, int response ) { imap_cmd_open_box_t *cmdp = (imap_cmd_open_box_t *)gcmd; // This will happen if the box is empty. if (!ctx->uidnext) ctx->uidnext = 1; imap_open_box_p4( ctx, cmdp, response ); } static void imap_open_box_p4( imap_store_t *ctx, imap_cmd_open_box_t *cmdp, int response ) { transform_box_response( &response ); cmdp->callback( response, ctx->uidvalidity, cmdp->callback_aux ); } static int imap_get_uidnext( store_t *gctx ) { imap_store_t *ctx = (imap_store_t *)gctx; return ctx->uidnext; } /******************* imap_create_box *******************/ static void imap_create_box( store_t *gctx, void (*cb)( int sts, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; imap_cmd_simple_t *cmd; char *buf; if (prepare_box( &buf, ctx ) < 0) { cb( DRV_BOX_BAD, aux ); return; } INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cb, aux) imap_exec( ctx, &cmd->gen, imap_done_simple_box, "CREATE \"%\\s\"", buf ); free( buf ); } /******************* imap_delete_box *******************/ static int imap_confirm_box_empty( store_t *gctx ) { imap_store_t *ctx = (imap_store_t *)gctx; return ctx->total_msgs ? DRV_BOX_BAD : DRV_OK; } static void imap_delete_box_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_delete_box( store_t *gctx, void (*cb)( int sts, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; imap_cmd_simple_t *cmd; INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cb, aux) imap_exec( ctx, &cmd->gen, imap_delete_box_p2, "CLOSE" ); } static void imap_delete_box_p2( imap_store_t *ctx, imap_cmd_t *gcmd, int response ) { imap_cmd_simple_t *cmdp = (imap_cmd_simple_t *)gcmd; imap_cmd_simple_t *cmd; char *buf; if (response != RESP_OK) { imap_done_simple_box( ctx, &cmdp->gen, response ); return; } if (prepare_box( &buf, ctx ) < 0) { imap_done_simple_box( ctx, &cmdp->gen, RESP_NO ); return; } INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cmdp->callback, cmdp->callback_aux) imap_exec( ctx, &cmd->gen, imap_done_simple_box, "DELETE \"%\\s\"", buf ); free( buf ); } static int imap_finish_delete_box( store_t *gctx ATTR_UNUSED ) { return DRV_OK; } /******************* imap_load_box *******************/ static int imap_prepare_load_box( store_t *gctx, int opts ) { imap_store_t *ctx = (imap_store_t *)gctx; ctx->opts = opts; return opts; } enum { WantSize = 1, WantTuids = 2, WantMsgids = 4 }; typedef struct { int first, last, flags; } imap_range_t; static void imap_set_range( imap_range_t *ranges, int *nranges, int low_flags, int high_flags, int maxlow ) { if (low_flags != high_flags) { for (int r = 0; r < *nranges; r++) { if (ranges[r].first > maxlow) break; /* Range starts above split point; so do all subsequent ranges. */ if (ranges[r].last < maxlow) continue; /* Range ends below split point; try next one. */ if (ranges[r].last != maxlow) { /* Range does not end exactly at split point; need to split. */ memmove( &ranges[r + 1], &ranges[r], ((*nranges)++ - r) * sizeof(*ranges) ); ranges[r].last = maxlow; ranges[r + 1].first = maxlow + 1; } break; } } for (int r = 0; r < *nranges; r++) ranges[r].flags |= (ranges[r].last <= maxlow) ? low_flags : high_flags; } typedef struct { imap_cmd_refcounted_state_t gen; void (*callback)( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ); void *callback_aux; } imap_load_box_state_t; static void imap_submit_load( imap_store_t *, const char *, int, imap_load_box_state_t * ); static void imap_submit_load_p3( imap_store_t *ctx, imap_load_box_state_t * ); static void imap_load_box( store_t *gctx, uint minuid, uint maxuid, uint newuid, uint seenuid, uint_array_t excs, void (*cb)( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; int i, j, bl; char buf[1000]; if (!ctx->total_msgs) { free( excs.data ); cb( DRV_OK, 0, 0, 0, aux ); } else { INIT_REFCOUNTED_STATE(imap_load_box_state_t, sts, cb, aux) for (i = 0; i < excs.size; ) { for (bl = 0; i < excs.size && bl < 960; i++) { if (bl) buf[bl++] = ','; bl += sprintf( buf + bl, "%u", excs.data[i] ); j = i; for (; i + 1 < excs.size && excs.data[i + 1] == excs.data[i] + 1; i++) {} if (i != j) bl += sprintf( buf + bl, ":%u", excs.data[i] ); } imap_submit_load( ctx, buf, shifted_bit( ctx->opts, OPEN_OLD_IDS, WantMsgids ), sts ); } if (maxuid == UINT_MAX) maxuid = ctx->uidnext - 1; if (maxuid >= minuid) { imap_range_t ranges[3]; ranges[0].first = minuid; ranges[0].last = maxuid; ranges[0].flags = 0; int nranges = 1; if (ctx->opts & (OPEN_OLD_SIZE | OPEN_NEW_SIZE)) imap_set_range( ranges, &nranges, shifted_bit( ctx->opts, OPEN_OLD_SIZE, WantSize), shifted_bit( ctx->opts, OPEN_NEW_SIZE, WantSize), seenuid ); if (ctx->opts & OPEN_FIND) imap_set_range( ranges, &nranges, 0, WantTuids, newuid - 1 ); if (ctx->opts & OPEN_OLD_IDS) imap_set_range( ranges, &nranges, WantMsgids, 0, seenuid ); for (int r = 0; r < nranges; r++) { sprintf( buf, "%u:%u", ranges[r].first, ranges[r].last ); imap_submit_load( ctx, buf, ranges[r].flags, sts ); } } free( excs.data ); imap_submit_load_p3( ctx, sts ); } } static void imap_submit_load_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_submit_load( imap_store_t *ctx, const char *buf, int flags, imap_load_box_state_t *sts ) { imap_exec( ctx, imap_refcounted_new_cmd( &sts->gen ), imap_submit_load_p2, "UID FETCH %s (UID%s%s%s%s%s%s%s)", buf, (ctx->opts & OPEN_FLAGS) ? " FLAGS" : "", (flags & WantSize) ? " RFC822.SIZE" : "", (flags & (WantTuids | WantMsgids)) ? " BODY.PEEK[HEADER.FIELDS (" : "", (flags & WantTuids) ? "X-TUID" : "", !(~flags & (WantTuids | WantMsgids)) ? " " : "", (flags & WantMsgids) ? "MESSAGE-ID" : "", (flags & (WantTuids | WantMsgids)) ? ")]" : ""); } static void imap_submit_load_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response ) { imap_load_box_state_t *sts = (imap_load_box_state_t *)((imap_cmd_refcounted_t *)cmd)->state; transform_refcounted_box_response( &sts->gen, response ); imap_submit_load_p3( ctx, sts ); } static void imap_submit_load_p3( imap_store_t *ctx, imap_load_box_state_t *sts ) { DONE_REFCOUNTED_STATE_ARGS(sts, ctx->msgs, ctx->total_msgs, ctx->recent_msgs) } /******************* imap_fetch_msg *******************/ static void imap_fetch_msg_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_fetch_msg( store_t *ctx, message_t *msg, msg_data_t *data, void (*cb)( int sts, void *aux ), void *aux ) { imap_cmd_fetch_msg_t *cmd; INIT_IMAP_CMD_X(imap_cmd_fetch_msg_t, cmd, cb, aux) cmd->gen.gen.param.uid = msg->uid; cmd->msg_data = data; data->data = 0; imap_exec( (imap_store_t *)ctx, &cmd->gen.gen, imap_fetch_msg_p2, "UID FETCH %u (%s%sBODY.PEEK[])", msg->uid, !(msg->status & M_FLAGS) ? "FLAGS " : "", (data->date== -1) ? "INTERNALDATE " : "" ); } static void imap_fetch_msg_p2( imap_store_t *ctx, imap_cmd_t *gcmd, int response ) { imap_cmd_fetch_msg_t *cmd = (imap_cmd_fetch_msg_t *)gcmd; if (response == RESP_OK && !cmd->msg_data->data) { /* The FETCH succeeded, but there is no message with this UID. */ response = RESP_NO; } imap_done_simple_msg( ctx, gcmd, response ); } /******************* imap_set_msg_flags *******************/ static int imap_make_flags( int flags, char *buf ) { const char *s; uint i, d; for (i = d = 0; i < as(Flags); i++) if (flags & (1 << i)) { buf[d++] = ' '; buf[d++] = '\\'; for (s = Flags[i]; *s; s++) buf[d++] = *s; } buf[0] = '('; buf[d++] = ')'; return d; } typedef struct { imap_cmd_refcounted_state_t gen; void (*callback)( int sts, void *aux ); void *callback_aux; } imap_set_msg_flags_state_t; static void imap_set_flags_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_set_flags_p3( imap_set_msg_flags_state_t * ); static void imap_flags_helper( imap_store_t *ctx, uint uid, char what, int flags, imap_set_msg_flags_state_t *sts ) { char buf[256]; buf[imap_make_flags( flags, buf )] = 0; imap_exec( ctx, imap_refcounted_new_cmd( &sts->gen ), imap_set_flags_p2, "UID STORE %u %cFLAGS.SILENT %s", uid, what, buf ); } static void imap_set_msg_flags( store_t *gctx, message_t *msg, uint uid, int add, int del, void (*cb)( int sts, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; if (msg) { uid = msg->uid; add &= ~msg->flags; del &= msg->flags; msg->flags |= add; msg->flags &= ~del; } if (add || del) { INIT_REFCOUNTED_STATE(imap_set_msg_flags_state_t, sts, cb, aux) if (add) imap_flags_helper( ctx, uid, '+', add, sts ); if (del) imap_flags_helper( ctx, uid, '-', del, sts ); imap_set_flags_p3( sts ); } else { cb( DRV_OK, aux ); } } static void imap_set_flags_p2( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *cmd, int response ) { imap_set_msg_flags_state_t *sts = (imap_set_msg_flags_state_t *)((imap_cmd_refcounted_t *)cmd)->state; transform_refcounted_msg_response( &sts->gen, response); imap_set_flags_p3( sts ); } static void imap_set_flags_p3( imap_set_msg_flags_state_t *sts ) { DONE_REFCOUNTED_STATE(sts) } /******************* imap_close_box *******************/ typedef struct { imap_cmd_refcounted_state_t gen; void (*callback)( int sts, void *aux ); void *callback_aux; } imap_expunge_state_t; static void imap_close_box_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_close_box_p3( imap_expunge_state_t * ); static void imap_close_box( store_t *gctx, void (*cb)( int sts, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; if (ctx->gen.conf->trash && CAP(UIDPLUS)) { INIT_REFCOUNTED_STATE(imap_expunge_state_t, sts, cb, aux) message_t *msg, *fmsg, *nmsg; int bl; char buf[1000]; for (msg = ctx->msgs; ; ) { for (bl = 0; msg && bl < 960; msg = msg->next) { if (!(msg->flags & F_DELETED)) continue; if (bl) buf[bl++] = ','; bl += sprintf( buf + bl, "%u", msg->uid ); fmsg = msg; for (; (nmsg = msg->next) && (nmsg->flags & F_DELETED); msg = nmsg) {} if (msg != fmsg) bl += sprintf( buf + bl, ":%u", msg->uid ); } if (!bl) break; imap_exec( ctx, imap_refcounted_new_cmd( &sts->gen ), imap_close_box_p2, "UID EXPUNGE %s", buf ); } imap_close_box_p3( sts ); } else { /* This is inherently racy: it may cause messages which other clients * marked as deleted to be expunged without being trashed. */ imap_cmd_simple_t *cmd; INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cb, aux) imap_exec( ctx, &cmd->gen, imap_done_simple_box, "CLOSE" ); } } static void imap_close_box_p2( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *cmd, int response ) { imap_expunge_state_t *sts = (imap_expunge_state_t *)((imap_cmd_refcounted_t *)cmd)->state; transform_refcounted_box_response( &sts->gen, response ); imap_close_box_p3( sts ); } static void imap_close_box_p3( imap_expunge_state_t *sts ) { DONE_REFCOUNTED_STATE(sts) } /******************* imap_trash_msg *******************/ static void imap_trash_msg( store_t *gctx, message_t *msg, void (*cb)( int sts, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; imap_cmd_simple_t *cmd; char *buf; INIT_IMAP_CMD(imap_cmd_simple_t, cmd, cb, aux) cmd->gen.param.create = 1; cmd->gen.param.to_trash = 1; if (prepare_trash( &buf, ctx ) < 0) { cb( DRV_BOX_BAD, aux ); return; } imap_exec( ctx, &cmd->gen, imap_done_simple_msg, CAP(MOVE) ? "UID MOVE %u \"%\\s\"" : "UID COPY %u \"%\\s\"", msg->uid, buf ); free( buf ); } /******************* imap_store_msg *******************/ static void imap_store_msg_p2( imap_store_t *, imap_cmd_t *, int ); static size_t my_strftime( char *s, size_t max, const char *fmt, const struct tm *tm ) { return strftime( s, max, fmt, tm ); } static void imap_store_msg( store_t *gctx, msg_data_t *data, int to_trash, void (*cb)( int sts, uint uid, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; imap_cmd_out_uid_t *cmd; char *buf; int d; char flagstr[128], datestr[64]; d = 0; if (data->flags) { d = imap_make_flags( data->flags, flagstr ); flagstr[d++] = ' '; } flagstr[d] = 0; INIT_IMAP_CMD(imap_cmd_out_uid_t, cmd, cb, aux) ctx->buffer_mem += data->len; cmd->gen.param.data_len = data->len; cmd->gen.param.data = data->data; cmd->out_uid = 0; if (to_trash) { cmd->gen.param.create = 1; cmd->gen.param.to_trash = 1; if (prepare_trash( &buf, ctx ) < 0) { cb( DRV_BOX_BAD, -1, aux ); return; } } else { if (prepare_box( &buf, ctx ) < 0) { cb( DRV_BOX_BAD, -1, aux ); return; } } if (data->date) { /* configure ensures that %z actually works. */ my_strftime( datestr, sizeof(datestr), "%d-%b-%Y %H:%M:%S %z", localtime( &data->date ) ); imap_exec( ctx, &cmd->gen, imap_store_msg_p2, "APPEND \"%\\s\" %s\"%\\s\" ", buf, flagstr, datestr ); } else { imap_exec( ctx, &cmd->gen, imap_store_msg_p2, "APPEND \"%\\s\" %s", buf, flagstr ); } free( buf ); } static void imap_store_msg_p2( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *cmd, int response ) { imap_cmd_out_uid_t *cmdp = (imap_cmd_out_uid_t *)cmd; transform_msg_response( &response ); cmdp->callback( response, cmdp->out_uid, cmdp->callback_aux ); } /******************* imap_find_new_msgs *******************/ static void imap_find_new_msgs_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_find_new_msgs_p3( imap_store_t *, imap_cmd_t *, int ); static void imap_find_new_msgs_p4( imap_store_t *, imap_cmd_t *, int ); static void imap_find_new_msgs( store_t *gctx, uint newuid, void (*cb)( int sts, message_t *msgs, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; imap_cmd_find_new_t *cmd; INIT_IMAP_CMD(imap_cmd_find_new_t, cmd, cb, aux) cmd->out_msgs = ctx->msgapp; cmd->uid = newuid; // Some servers fail to enumerate recently STOREd messages without syncing first. imap_exec( (imap_store_t *)ctx, &cmd->gen, imap_find_new_msgs_p2, "CHECK" ); } static void imap_find_new_msgs_p2( imap_store_t *ctx, imap_cmd_t *gcmd, int response ) { imap_cmd_find_new_t *cmdp = (imap_cmd_find_new_t *)gcmd; imap_cmd_find_new_t *cmd; if (response != RESP_OK) { imap_done_simple_box( ctx, gcmd, response ); return; } ctx->uidnext = 0; INIT_IMAP_CMD(imap_cmd_find_new_t, cmd, cmdp->callback, cmdp->callback_aux) cmd->out_msgs = cmdp->out_msgs; cmd->uid = cmdp->uid; cmd->gen.param.lastuid = 1; imap_exec( ctx, &cmd->gen, imap_find_new_msgs_p3, "UID FETCH *:* (UID)" ); } static void imap_find_new_msgs_p3( imap_store_t *ctx, imap_cmd_t *gcmd, int response ) { imap_cmd_find_new_t *cmdp = (imap_cmd_find_new_t *)gcmd; imap_cmd_find_new_t *cmd; if (response != RESP_OK || ctx->uidnext <= cmdp->uid) { imap_find_new_msgs_p4( ctx, gcmd, response ); return; } INIT_IMAP_CMD(imap_cmd_find_new_t, cmd, cmdp->callback, cmdp->callback_aux) cmd->out_msgs = cmdp->out_msgs; imap_exec( (imap_store_t *)ctx, &cmd->gen, imap_find_new_msgs_p4, "UID FETCH %u:%u (UID BODY.PEEK[HEADER.FIELDS (X-TUID)])", cmdp->uid, ctx->uidnext - 1 ); } static void imap_find_new_msgs_p4( imap_store_t *ctx ATTR_UNUSED, imap_cmd_t *gcmd, int response ) { imap_cmd_find_new_t *cmdp = (imap_cmd_find_new_t *)gcmd; transform_box_response( &response ); cmdp->callback( response, *cmdp->out_msgs, cmdp->callback_aux ); } /******************* imap_list_store *******************/ typedef struct { imap_cmd_refcounted_state_t gen; void (*callback)( int sts, string_list_t *, void *aux ); void *callback_aux; } imap_list_store_state_t; static void imap_list_store_p2( imap_store_t *, imap_cmd_t *, int ); static void imap_list_store_p3( imap_store_t *, imap_list_store_state_t * ); static void imap_list_store( store_t *gctx, int flags, void (*cb)( int sts, string_list_t *boxes, void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; INIT_REFCOUNTED_STATE(imap_list_store_state_t, sts, cb, aux) // ctx->prefix may be empty, "INBOX.", or something else. // 'flags' may be LIST_INBOX, LIST_PATH (or LIST_PATH_MAYBE), or both. 'listed' // already containing a particular value effectively removes it from 'flags'. // This matrix determines what to query, and what comes out as a side effect. // The lowercase letters indicate unnecessary results; the queries are done // this way to have non-overlapping result sets, so subsequent calls create // no duplicates: // // qry \ pfx | empty | inbox | other // ----------+-------+-------+------- // inbox | p [I] | I [p] | I // both | P [I] | I [P] | I + P // path | P [i] | i [P] | P // int pfx_is_empty = !*ctx->prefix; int pfx_is_inbox = !pfx_is_empty && is_inbox( ctx, ctx->prefix, -1 ); if (((flags & (LIST_PATH | LIST_PATH_MAYBE)) || pfx_is_empty) && !pfx_is_inbox && !(ctx->listed & LIST_PATH)) { ctx->listed |= LIST_PATH; if (pfx_is_empty) ctx->listed |= LIST_INBOX; imap_exec( ctx, imap_refcounted_new_cmd( &sts->gen ), imap_list_store_p2, "LIST \"\" \"%\\s*\"", ctx->prefix ); } if (((flags & LIST_INBOX) || pfx_is_inbox) && !pfx_is_empty && !(ctx->listed & LIST_INBOX)) { ctx->listed |= LIST_INBOX; if (pfx_is_inbox) ctx->listed |= LIST_PATH; imap_exec( ctx, imap_refcounted_new_cmd( &sts->gen ), imap_list_store_p2, "LIST \"\" INBOX*" ); } imap_list_store_p3( ctx, sts ); } static void imap_list_store_p2( imap_store_t *ctx, imap_cmd_t *cmd, int response ) { imap_list_store_state_t *sts = (imap_list_store_state_t *)((imap_cmd_refcounted_t *)cmd)->state; transform_refcounted_box_response( &sts->gen, response ); imap_list_store_p3( ctx, sts ); } static void imap_list_store_p3( imap_store_t *ctx, imap_list_store_state_t *sts ) { DONE_REFCOUNTED_STATE_ARGS(sts, ctx->boxes) } /******************* imap_cancel_cmds *******************/ static void imap_cancel_cmds( store_t *gctx, void (*cb)( void *aux ), void *aux ) { imap_store_t *ctx = (imap_store_t *)gctx; cancel_pending_imap_cmds( ctx ); if (ctx->in_progress) { ctx->canceling = 1; ctx->callbacks.imap_cancel = cb; ctx->callback_aux = aux; } else { cb( aux ); } } /******************* imap_commit_cmds *******************/ static void imap_commit_cmds( store_t *gctx ) { (void)gctx; } /******************* imap_get_memory_usage *******************/ static int imap_get_memory_usage( store_t *gctx ) { imap_store_t *ctx = (imap_store_t *)gctx; return ctx->buffer_mem + ctx->conn.buffer_mem; } /******************* imap_get_fail_state *******************/ static int imap_get_fail_state( store_conf_t *gconf ) { return ((imap_store_conf_t *)gconf)->server->failed; } /******************* imap_parse_store *******************/ imap_server_conf_t *servers, **serverapp = &servers; static int imap_parse_store( conffile_t *cfg, store_conf_t **storep ) { imap_store_conf_t *store; imap_server_conf_t *server, *srv, sserver; const char *type, *name, *arg; unsigned u; int acc_opt = 0; #ifdef HAVE_LIBSSL /* Legacy SSL options */ int require_ssl = -1, use_imaps = -1; int use_sslv3 = -1, use_tlsv1 = -1, use_tlsv11 = -1, use_tlsv12 = -1; #endif /* Legacy SASL option */ int require_cram = -1; if (!strcasecmp( "IMAPAccount", cfg->cmd )) { server = nfcalloc( sizeof(*server) ); server->name = nfstrdup( cfg->val ); *serverapp = server; serverapp = &server->next; store = 0; *storep = 0; } else if (!strcasecmp( "IMAPStore", cfg->cmd )) { store = nfcalloc( sizeof(*store) ); store->gen.driver = &imap_driver; store->gen.name = nfstrdup( cfg->val ); store->use_namespace = 1; *storep = &store->gen; memset( &sserver, 0, sizeof(sserver) ); server = &sserver; } else return 0; server->sconf.timeout = 20; #ifdef HAVE_LIBSSL server->ssl_type = -1; server->sconf.ssl_versions = -1; server->sconf.system_certs = 1; #endif server->max_in_progress = INT_MAX; while (getcline( cfg ) && cfg->cmd) { if (!strcasecmp( "Host", cfg->cmd )) { /* The imap[s]: syntax is just a backwards compat hack. */ arg = cfg->val; #ifdef HAVE_LIBSSL if (starts_with( arg, -1, "imaps:", 6 )) { arg += 6; server->ssl_type = SSL_IMAPS; if (server->sconf.ssl_versions == -1) server->sconf.ssl_versions = SSLv3 | TLSv1 | TLSv1_1 | TLSv1_2; } else #endif if (starts_with( arg, -1, "imap:", 5 )) arg += 5; if (starts_with( arg, -1, "//", 2 )) arg += 2; if (arg != cfg->val) warn( "%s:%d: Notice: URL notation is deprecated; use a plain host name and possibly 'SSLType IMAPS' instead\n", cfg->file, cfg->line ); server->sconf.host = nfstrdup( arg ); } else if (!strcasecmp( "User", cfg->cmd )) server->user = nfstrdup( cfg->val ); else if (!strcasecmp( "Pass", cfg->cmd )) server->pass = nfstrdup( cfg->val ); else if (!strcasecmp( "PassCmd", cfg->cmd )) server->pass_cmd = nfstrdup( cfg->val ); else if (!strcasecmp( "Port", cfg->cmd )) server->sconf.port = parse_int( cfg ); else if (!strcasecmp( "Timeout", cfg->cmd )) server->sconf.timeout = parse_int( cfg ); else if (!strcasecmp( "PipelineDepth", cfg->cmd )) { if ((server->max_in_progress = parse_int( cfg )) < 1) { error( "%s:%d: PipelineDepth must be at least 1\n", cfg->file, cfg->line ); cfg->err = 1; } } else if (!strcasecmp( "DisableExtension", cfg->cmd ) || !strcasecmp( "DisableExtensions", cfg->cmd )) { arg = cfg->val; do { for (u = 0; u < as(cap_list); u++) { if (!strcasecmp( cap_list[u], arg )) { server->cap_mask |= 1 << u; goto gotcap; } } error( "%s:%d: Unrecognized IMAP extension '%s'\n", cfg->file, cfg->line, arg ); cfg->err = 1; gotcap: ; } while ((arg = get_arg( cfg, ARG_OPTIONAL, 0 ))); } #ifdef HAVE_LIBSSL else if (!strcasecmp( "CertificateFile", cfg->cmd )) { server->sconf.cert_file = expand_strdup( cfg->val ); if (access( server->sconf.cert_file, R_OK )) { sys_error( "%s:%d: CertificateFile '%s'", cfg->file, cfg->line, server->sconf.cert_file ); cfg->err = 1; } } else if (!strcasecmp( "SystemCertificates", cfg->cmd )) { server->sconf.system_certs = parse_bool( cfg ); } else if (!strcasecmp( "ClientCertificate", cfg->cmd )) { server->sconf.client_certfile = expand_strdup( cfg->val ); if (access( server->sconf.client_certfile, R_OK )) { sys_error( "%s:%d: ClientCertificate '%s'", cfg->file, cfg->line, server->sconf.client_certfile ); cfg->err = 1; } } else if (!strcasecmp( "ClientKey", cfg->cmd )) { server->sconf.client_keyfile = expand_strdup( cfg->val ); if (access( server->sconf.client_keyfile, R_OK )) { sys_error( "%s:%d: ClientKey '%s'", cfg->file, cfg->line, server->sconf.client_keyfile ); cfg->err = 1; } } else if (!strcasecmp( "SSLType", cfg->cmd )) { if (!strcasecmp( "None", cfg->val )) { server->ssl_type = SSL_None; } else if (!strcasecmp( "STARTTLS", cfg->val )) { server->ssl_type = SSL_STARTTLS; } else if (!strcasecmp( "IMAPS", cfg->val )) { server->ssl_type = SSL_IMAPS; } else { error( "%s:%d: Invalid SSL type\n", cfg->file, cfg->line ); cfg->err = 1; } } else if (!strcasecmp( "SSLVersion", cfg->cmd ) || !strcasecmp( "SSLVersions", cfg->cmd )) { server->sconf.ssl_versions = 0; arg = cfg->val; do { if (!strcasecmp( "SSLv2", arg )) { warn( "Warning: SSLVersion SSLv2 is no longer supported\n" ); } else if (!strcasecmp( "SSLv3", arg )) { server->sconf.ssl_versions |= SSLv3; } else if (!strcasecmp( "TLSv1", arg )) { server->sconf.ssl_versions |= TLSv1; } else if (!strcasecmp( "TLSv1.1", arg )) { server->sconf.ssl_versions |= TLSv1_1; } else if (!strcasecmp( "TLSv1.2", arg )) { server->sconf.ssl_versions |= TLSv1_2; } else { error( "%s:%d: Unrecognized SSL version\n", cfg->file, cfg->line ); cfg->err = 1; } } while ((arg = get_arg( cfg, ARG_OPTIONAL, 0 ))); } else if (!strcasecmp( "RequireSSL", cfg->cmd )) require_ssl = parse_bool( cfg ); else if (!strcasecmp( "UseIMAPS", cfg->cmd )) use_imaps = parse_bool( cfg ); else if (!strcasecmp( "UseSSLv2", cfg->cmd )) warn( "Warning: UseSSLv2 is no longer supported\n" ); else if (!strcasecmp( "UseSSLv3", cfg->cmd )) use_sslv3 = parse_bool( cfg ); else if (!strcasecmp( "UseTLSv1", cfg->cmd )) use_tlsv1 = parse_bool( cfg ); else if (!strcasecmp( "UseTLSv1.1", cfg->cmd )) use_tlsv11 = parse_bool( cfg ); else if (!strcasecmp( "UseTLSv1.2", cfg->cmd )) use_tlsv12 = parse_bool( cfg ); #endif else if (!strcasecmp( "AuthMech", cfg->cmd ) || !strcasecmp( "AuthMechs", cfg->cmd )) { arg = cfg->val; do add_string_list( &server->auth_mechs, arg ); while ((arg = get_arg( cfg, ARG_OPTIONAL, 0 ))); } else if (!strcasecmp( "RequireCRAM", cfg->cmd )) require_cram = parse_bool( cfg ); else if (!strcasecmp( "Tunnel", cfg->cmd )) server->sconf.tunnel = nfstrdup( cfg->val ); else if (store) { if (!strcasecmp( "Account", cfg->cmd )) { for (srv = servers; srv; srv = srv->next) if (srv->name && !strcmp( srv->name, cfg->val )) goto gotsrv; error( "%s:%d: unknown IMAP account '%s'\n", cfg->file, cfg->line, cfg->val ); cfg->err = 1; continue; gotsrv: store->server = srv; } else if (!strcasecmp( "UseNamespace", cfg->cmd )) store->use_namespace = parse_bool( cfg ); else if (!strcasecmp( "Path", cfg->cmd )) store->gen.path = nfstrdup( cfg->val ); else if (!strcasecmp( "PathDelimiter", cfg->cmd )) { if (strlen( cfg->val ) != 1) { error( "%s:%d: Path delimiter must be exactly one character long\n", cfg->file, cfg->line ); cfg->err = 1; continue; } store->delimiter = cfg->val[0]; } else parse_generic_store( &store->gen, cfg ); continue; } else { error( "%s:%d: unknown/misplaced keyword '%s'\n", cfg->file, cfg->line, cfg->cmd ); cfg->err = 1; continue; } acc_opt = 1; } if (store) type = "IMAP store", name = store->gen.name; else type = "IMAP account", name = server->name; if (!store || !store->server) { if (!server->sconf.tunnel && !server->sconf.host) { error( "%s '%s' has neither Tunnel nor Host\n", type, name ); cfg->err = 1; return 1; } if (server->pass && server->pass_cmd) { error( "%s '%s' has both Pass and PassCmd\n", type, name ); cfg->err = 1; return 1; } #ifdef HAVE_LIBSSL if ((use_sslv3 & use_tlsv1 & use_tlsv11 & use_tlsv12) != -1 || use_imaps >= 0 || require_ssl >= 0) { if (server->ssl_type >= 0 || server->sconf.ssl_versions >= 0) { error( "%s '%s': The deprecated UseSSL*, UseTLS*, UseIMAPS, and RequireSSL options are mutually exclusive with SSLType and SSLVersions.\n", type, name ); cfg->err = 1; return 1; } warn( "Notice: %s '%s': UseSSL*, UseTLS*, UseIMAPS, and RequireSSL are deprecated. Use SSLType and SSLVersions instead.\n", type, name ); server->sconf.ssl_versions = (use_sslv3 != 1 ? 0 : SSLv3) | (use_tlsv1 == 0 ? 0 : TLSv1) | (use_tlsv11 != 1 ? 0 : TLSv1_1) | (use_tlsv12 != 1 ? 0 : TLSv1_2); if (use_imaps == 1) { server->ssl_type = SSL_IMAPS; } else if (require_ssl) { server->ssl_type = SSL_STARTTLS; } else if (!server->sconf.ssl_versions) { server->ssl_type = SSL_None; } else { warn( "Notice: %s '%s': 'RequireSSL no' is being ignored\n", type, name ); server->ssl_type = SSL_STARTTLS; } if (server->ssl_type != SSL_None && !server->sconf.ssl_versions) { error( "%s '%s' requires SSL but no SSL versions enabled\n", type, name ); cfg->err = 1; return 1; } } else { if (server->sconf.ssl_versions < 0) server->sconf.ssl_versions = TLSv1 | TLSv1_1 | TLSv1_2; if (server->ssl_type < 0) server->ssl_type = server->sconf.tunnel ? SSL_None : SSL_STARTTLS; } #endif if (require_cram >= 0) { if (server->auth_mechs) { error( "%s '%s': The deprecated RequireCRAM option is mutually exclusive with AuthMech.\n", type, name ); cfg->err = 1; return 1; } warn( "Notice: %s '%s': RequireCRAM is deprecated. Use AuthMech instead.\n", type, name ); if (require_cram) add_string_list(&server->auth_mechs, "CRAM-MD5"); } if (!server->auth_mechs) add_string_list( &server->auth_mechs, "*" ); if (!server->sconf.port) server->sconf.port = #ifdef HAVE_LIBSSL server->ssl_type == SSL_IMAPS ? 993 : #endif 143; } if (store) { if (!store->server) { store->server = nfmalloc( sizeof(sserver) ); memcpy( store->server, &sserver, sizeof(sserver) ); store->server->name = store->gen.name; } else if (acc_opt) { error( "%s '%s' has both Account and account-specific options\n", type, name ); cfg->err = 1; } } return 1; } static int imap_get_caps( store_t *gctx ATTR_UNUSED ) { return DRV_CRLF | DRV_VERBOSE; } struct driver imap_driver = { imap_get_caps, imap_parse_store, imap_cleanup, imap_alloc_store, imap_set_bad_callback, imap_connect_store, imap_free_store, imap_cancel_store, imap_list_store, imap_select_box, imap_get_box_path, imap_create_box, imap_open_box, imap_get_uidnext, imap_confirm_box_empty, imap_delete_box, imap_finish_delete_box, imap_prepare_load_box, imap_load_box, imap_fetch_msg, imap_store_msg, imap_find_new_msgs, imap_set_msg_flags, imap_trash_msg, imap_close_box, imap_cancel_cmds, imap_commit_cmds, imap_get_memory_usage, imap_get_fail_state, }; isync-1.3.0/src/config.h0000644000175000001440000000274313141404045011764 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2010-2012 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #ifndef CONFIG_H #define CONFIG_H #include "common.h" typedef struct { const char *file; FILE *fp; char *buf; int bufl; int line; int err; char *cmd, *val, *rest; } conffile_t; #define ARG_OPTIONAL 0 #define ARG_REQUIRED 1 char *get_arg( conffile_t *cfile, int required, int *comment ); int parse_bool( conffile_t *cfile ); int parse_int( conffile_t *cfile ); int parse_size( conffile_t *cfile ); int getcline( conffile_t *cfile ); int merge_ops( int cops, int ops[] ); int load_config( const char *filename, int pseudo ); #endif isync-1.3.0/src/mdconvert.c0000644000175000001440000001667213007413620012521 00000000000000/* * mdconvert - Maildir UID scheme converter * Copyright (C) 2004 Oswald Buddenhagen * * 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, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define EXE "mdconvert" #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) # define ATTR_NORETURN __attribute__((noreturn)) # define ATTR_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) #else # define ATTR_NORETURN # define ATTR_PRINTFLIKE(fmt,var) #endif static void ATTR_NORETURN oob( void ) { fputs( "Fatal: buffer too small. Please report a bug.\n", stderr ); abort(); } static void ATTR_PRINTFLIKE(1, 2) sys_error( const char *msg, ... ) { va_list va; char buf[1024]; va_start( va, msg ); if ((unsigned)vsnprintf( buf, sizeof(buf), msg, va ) >= sizeof(buf)) oob(); va_end( va ); perror( buf ); } static int ATTR_PRINTFLIKE(3, 4) nfsnprintf( char *buf, int blen, const char *fmt, ... ) { int ret; va_list va; va_start( va, fmt ); if (blen <= 0 || (unsigned)(ret = vsnprintf( buf, blen, fmt, va )) >= (unsigned)blen) oob(); va_end( va ); return ret; } static const char *subdirs[] = { "cur", "new" }; static struct flock lck; static DBT key, value; static int convert( const char *box, int altmap ) { DB *db; DIR *d; struct dirent *e; const char *u, *ru; char *p, *s, *dpath, *spath, *dbpath; int i, n, ret, sfd, dfd, bl, ml, uv[2], uid; struct stat st; char buf[_POSIX_PATH_MAX], buf2[_POSIX_PATH_MAX]; char umpath[_POSIX_PATH_MAX], uvpath[_POSIX_PATH_MAX], tdpath[_POSIX_PATH_MAX]; if (stat( box, &st ) || !S_ISDIR(st.st_mode)) { fprintf( stderr, "'%s' is no Maildir mailbox.\n", box ); return 1; } nfsnprintf( umpath, sizeof(umpath), "%s/.isyncuidmap.db", box ); nfsnprintf( uvpath, sizeof(uvpath), "%s/.uidvalidity", box ); if (altmap) dpath = umpath, spath = uvpath, dbpath = tdpath; else spath = umpath, dpath = uvpath, dbpath = umpath; nfsnprintf( tdpath, sizeof(tdpath), "%s.tmp", dpath ); if ((sfd = open( spath, O_RDWR )) < 0) { if (errno != ENOENT) sys_error( "Cannot open %s", spath ); return 1; } if (fcntl( sfd, F_SETLKW, &lck )) { sys_error( "Cannot lock %s", spath ); goto sbork; } if ((dfd = open( tdpath, O_RDWR|O_CREAT, 0600 )) < 0) { sys_error( "Cannot create %s", tdpath ); goto sbork; } if (db_create( &db, 0, 0 )) { fputs( "Error: db_create() failed\n", stderr ); goto tbork; } if ((ret = (db->open)( db, 0, dbpath, 0, DB_HASH, altmap ? DB_CREATE|DB_TRUNCATE : 0, 0 ))) { db->err( db, ret, "Error: db->open(%s)", dbpath ); dbork: db->close( db, 0 ); tbork: unlink( tdpath ); close( dfd ); sbork: close( sfd ); return 1; } key.data = (void *)"UIDVALIDITY"; key.size = 11; if (altmap) { if ((n = read( sfd, buf, sizeof(buf) - 1 )) <= 0 || (buf[n] = 0, sscanf( buf, "%d\n%d", &uv[0], &uv[1] ) != 2)) { fprintf( stderr, "Error: cannot read UIDVALIDITY of '%s'.\n", box ); goto dbork; } value.data = uv; value.size = sizeof(uv); if ((ret = db->put( db, 0, &key, &value, 0 ))) { db->err( db, ret, "Error: cannot write UIDVALIDITY for '%s'", box ); goto dbork; } } else { if ((ret = db->get( db, 0, &key, &value, 0 ))) { db->err( db, ret, "Error: cannot read UIDVALIDITY of '%s'", box ); goto dbork; } n = sprintf( buf, "%d\n%d\n", ((int *)value.data)[0], ((int *)value.data)[1] ); if (write( dfd, buf, n ) != n) { fprintf( stderr, "Error: cannot write UIDVALIDITY for '%s'.\n", box ); goto dbork; } } again: for (i = 0; i < 2; i++) { bl = nfsnprintf( buf, sizeof(buf), "%s/%s/", box, subdirs[i] ); if (!(d = opendir( buf ))) { sys_error( "Cannot list %s", buf ); goto dbork; } while ((e = readdir( d ))) { if (*e->d_name == '.') continue; nfsnprintf( buf + bl, sizeof(buf) - bl, "%s", e->d_name ); memcpy( buf2, buf, bl ); p = strstr( e->d_name, ",U=" ); if (p) for (u = p, ru = p + 3; isdigit( (unsigned char)*ru ); ru++); else u = ru = strchr( e->d_name, ':' ); if (u) ml = u - e->d_name; else ru = "", ml = sizeof(buf); if (altmap) { if (!p) continue; key.data = e->d_name; key.size = (size_t)(strchr( e->d_name, ',' ) - e->d_name); uid = atoi( p + 3 ); value.data = &uid; value.size = sizeof(uid); if ((ret = db->put( db, 0, &key, &value, 0 ))) { db->err( db, ret, "Error: cannot write UID for '%s'", box ); goto ebork; } nfsnprintf( buf2 + bl, sizeof(buf2) - bl, "%.*s%s", ml, e->d_name, ru ); } else { s = strpbrk( e->d_name, ",:" ); key.data = e->d_name; key.size = s ? (size_t)(s - e->d_name) : strlen( e->d_name ); if ((ret = db->get( db, 0, &key, &value, 0 ))) { if (ret != DB_NOTFOUND) { db->err( db, ret, "Error: cannot read UID for '%s'", box ); goto ebork; } continue; } uid = *(int *)value.data; nfsnprintf( buf2 + bl, sizeof(buf2) - bl, "%.*s,U=%d%s", ml, e->d_name, uid, ru ); } if (rename( buf, buf2 )) { if (errno == ENOENT) { closedir( d ); goto again; } sys_error( "Cannot rename %s to %s", buf, buf2 ); ebork: closedir( d ); goto dbork; } } closedir( d ); } db->close( db, 0 ); close( dfd ); if (rename( tdpath, dpath )) { sys_error( "Cannot rename %s to %s", tdpath, dpath ); close( sfd ); return 1; } if (unlink( spath )) sys_error( "Cannot remove %s", spath ); close( sfd ); return 0; } int main( int argc, char **argv ) { int oint, ret, altmap = 0; for (oint = 1; oint < argc; oint++) { if (!strcmp( argv[oint], "-h" ) || !strcmp( argv[oint], "--help" )) { puts( "Usage: " EXE " [-a] mailbox...\n" " -a, --alt convert to alternative (DB based) UID scheme\n" " -n, --native convert to native (file name based) UID scheme (default)\n" " -h, --help show this help message\n" " -v, --version display version" ); return 0; } else if (!strcmp( argv[oint], "-v" ) || !strcmp( argv[oint], "--version" )) { puts( EXE " " VERSION " - Maildir UID scheme converter" ); return 0; } else if (!strcmp( argv[oint], "-a" ) || !strcmp( argv[oint], "--alt" )) { altmap = 1; } else if (!strcmp( argv[oint], "-n" ) || !strcmp( argv[oint], "--native" )) { altmap = 0; } else if (!strcmp( argv[oint], "--" )) { oint++; break; } else if (argv[oint][0] == '-') { fprintf( stderr, "Unrecognized option '%s'. Try " EXE " -h\n", argv[oint] ); return 1; } else break; } if (oint == argc) { fprintf( stderr, "Mailbox specification missing. Try " EXE " -h\n" ); return 1; } #if SEEK_SET != 0 lck.l_whence = SEEK_SET; #endif #if F_WRLCK != 0 lck.l_type = F_WRLCK; #endif ret = 0; for (; oint < argc; oint++) ret |= convert( argv[oint], altmap ); return ret; } isync-1.3.0/src/main.c0000644000175000001440000006601713164125071011446 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2010-2017 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #include "sync.h" #include #include #include #include #include #include #include #include int DFlags; int JLimit; int UseFSync = 1; #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__CYGWIN__) char FieldDelimiter = ';'; #else char FieldDelimiter = ':'; #endif int Pid; /* for maildir and imap */ char Hostname[256]; /* for maildir */ const char *Home; /* for config */ int BufferLimit = 10 * 1024 * 1024; int chans_total, chans_done; int boxes_total, boxes_done; int new_total[2], new_done[2]; int flags_total[2], flags_done[2]; int trash_total[2], trash_done[2]; static void ATTR_NORETURN version( void ) { puts( PACKAGE " " VERSION ); exit( 0 ); } static void ATTR_NORETURN usage( int code ) { fputs( PACKAGE " " VERSION " - mailbox synchronizer\n" "Copyright (C) 2000-2002 Michael R. Elkins \n" "Copyright (C) 2002-2006,2008,2010-2017 Oswald Buddenhagen \n" "Copyright (C) 2004 Theodore Ts'o \n" "usage:\n" " " EXE " [flags] {{channel[:box,...]|group} ...|-a}\n" " -a, --all operate on all defined channels\n" " -l, --list list mailboxes instead of syncing them\n" " -n, --new propagate new messages\n" " -d, --delete propagate message deletions\n" " -f, --flags propagate message flag changes\n" " -N, --renew propagate previously not propagated new messages\n" " -L, --pull propagate from master to slave\n" " -H, --push propagate from slave to master\n" " -C, --create create mailboxes if nonexistent\n" " -X, --expunge expunge deleted messages\n" " -c, --config CONFIG read an alternate config file (default: ~/." EXE "rc)\n" " -D, --debug debugging modes (see manual)\n" " -V, --verbose display what is happening\n" " -q, --quiet don't display progress counters\n" " -v, --version display version\n" " -h, --help display this help message\n" "\nIf neither --pull nor --push are specified, both are active.\n" "If neither --new, --delete, --flags nor --renew are specified, all are active.\n" "Direction and operation can be concatenated like --pull-new, etc.\n" "--create and --expunge can be suffixed with -master/-slave. Read the man page.\n" "\nSupported mailbox formats are: IMAP4rev1, Maildir\n" "\nCompile time options:\n" #ifdef HAVE_LIBSSL " +HAVE_LIBSSL" #else " -HAVE_LIBSSL" #endif #ifdef HAVE_LIBSASL " +HAVE_LIBSASL" #else " -HAVE_LIBSASL" #endif #ifdef HAVE_LIBZ " +HAVE_LIBZ" #else " -HAVE_LIBZ" #endif #ifdef USE_DB " +USE_DB" #else " -USE_DB" #endif #ifdef HAVE_IPV6 " +HAVE_IPV6\n" #else " -HAVE_IPV6\n" #endif , code ? stderr : stdout ); exit( code ); } static void ATTR_PRINTFLIKE(1, 2) debug( const char *msg, ... ) { va_list va; va_start( va, msg ); vdebug( DEBUG_MAIN, msg, va ); va_end( va ); } #ifdef __linux__ static void crashHandler( int n ) { int dpid; char pbuf[10], pabuf[20]; close( 0 ); open( "/dev/tty", O_RDWR ); dup2( 0, 1 ); dup2( 0, 2 ); error( "*** " EXE " caught signal %d. Starting debugger ...\n", n ); switch ((dpid = fork())) { case -1: perror( "fork()" ); break; case 0: sprintf( pbuf, "%d", Pid ); sprintf( pabuf, "/proc/%d/exe", Pid ); execlp( "gdb", "gdb", pabuf, pbuf, (char *)0 ); perror( "execlp()" ); _exit( 1 ); default: waitpid( dpid, 0, 0 ); break; } exit( 3 ); } #endif void stats( void ) { char buf[3][64]; char *cs; int t, l, ll, cls; static int cols = -1; if (!(DFlags & PROGRESS)) return; if (cols < 0 && (!(cs = getenv( "COLUMNS" )) || !(cols = atoi( cs )))) cols = 80; ll = sprintf( buf[2], "C: %d/%d B: %d/%d", chans_done, chans_total, boxes_done, boxes_total ); cls = (cols - ll - 10) / 2; for (t = 0; t < 2; t++) { l = sprintf( buf[t], "+%d/%d *%d/%d #%d/%d", new_done[t], new_total[t], flags_done[t], flags_total[t], trash_done[t], trash_total[t] ); if (l > cls) buf[t][cls - 1] = '~'; } progress( "\r%s M: %.*s S: %.*s", buf[2], cls, buf[0], cls, buf[1] ); } static int matches( const char *t, const char *p ) { for (;;) { if (!*p) return !*t; if (*p == '*') { p++; do { if (matches( t, p )) return 1; } while (*t++); return 0; } else if (*p == '%') { p++; do { if (*t == '/') return 0; if (matches( t, p )) return 1; } while (*t++); return 0; } else { if (*p != *t) return 0; p++, t++; } } } static int is_inbox( const char *name ) { return starts_with( name, -1, "INBOX", 5 ) && (!name[5] || name[5] == '/'); } static int cmp_box_names( const void *a, const void *b ) { const char *as = *(const char **)a; const char *bs = *(const char **)b; int ai = is_inbox( as ); int bi = is_inbox( bs ); int di = bi - ai; if (di) return di; return strcmp( as, bs ); } static char ** filter_boxes( string_list_t *boxes, const char *prefix, string_list_t *patterns ) { string_list_t *cpat; char **boxarr = 0; const char *ps; int not, fnot, pfxl, num = 0, rnum = 0; pfxl = prefix ? strlen( prefix ) : 0; for (; boxes; boxes = boxes->next) { if (!starts_with( boxes->string, -1, prefix, pfxl )) continue; fnot = 1; for (cpat = patterns; cpat; cpat = cpat->next) { ps = cpat->string; if (*ps == '!') { ps++; not = 1; } else not = 0; if (matches( boxes->string + pfxl, ps )) { fnot = not; break; } } if (!fnot) { if (num + 1 >= rnum) boxarr = nfrealloc( boxarr, (rnum = (rnum + 10) * 2) * sizeof(*boxarr) ); boxarr[num++] = nfstrdup( boxes->string + pfxl ); boxarr[num] = 0; } } qsort( boxarr, num, sizeof(*boxarr), cmp_box_names ); return boxarr; } static void merge_actions( channel_conf_t *chan, int ops[], int have, int mask, int def ) { if (ops[M] & have) { chan->ops[M] &= ~mask; chan->ops[M] |= ops[M] & mask; chan->ops[S] &= ~mask; chan->ops[S] |= ops[S] & mask; } else if (!(chan->ops[M] & have)) { if (global_conf.ops[M] & have) { chan->ops[M] |= global_conf.ops[M] & mask; chan->ops[S] |= global_conf.ops[S] & mask; } else { chan->ops[M] |= def; chan->ops[S] |= def; } } } typedef struct box_ent { struct box_ent *next; char *name; int present[2]; } box_ent_t; typedef struct chan_ent { struct chan_ent *next; channel_conf_t *conf; box_ent_t *boxes; char boxlist; } chan_ent_t; static chan_ent_t * add_channel( chan_ent_t ***chanapp, channel_conf_t *chan, int ops[] ) { chan_ent_t *ce = nfcalloc( sizeof(*ce) ); ce->conf = chan; merge_actions( chan, ops, XOP_HAVE_TYPE, OP_MASK_TYPE, OP_MASK_TYPE ); merge_actions( chan, ops, XOP_HAVE_CREATE, OP_CREATE, 0 ); merge_actions( chan, ops, XOP_HAVE_REMOVE, OP_REMOVE, 0 ); merge_actions( chan, ops, XOP_HAVE_EXPUNGE, OP_EXPUNGE, 0 ); **chanapp = ce; *chanapp = &ce->next; chans_total++; return ce; } static chan_ent_t * add_named_channel( chan_ent_t ***chanapp, char *channame, int ops[] ) { channel_conf_t *chan; chan_ent_t *ce; box_ent_t *boxes = 0, **mboxapp = &boxes, *mbox; char *boxp, *nboxp; int boxl, boxlist = 0; if ((boxp = strchr( channame, ':' ))) *boxp++ = 0; for (chan = channels; chan; chan = chan->next) if (!strcmp( chan->name, channame )) goto gotchan; error( "No channel or group named '%s' defined.\n", channame ); return 0; gotchan: if (boxp) { if (!chan->patterns) { error( "Cannot override mailbox in channel '%s' - no Patterns.\n", channame ); return 0; } boxlist = 1; do { nboxp = strpbrk( boxp, ",\n" ); if (nboxp) { boxl = nboxp - boxp; *nboxp++ = 0; } else { boxl = strlen( boxp ); } mbox = nfmalloc( sizeof(*mbox) ); if (boxl) mbox->name = nfstrndup( boxp, boxl ); else mbox->name = nfstrndup( "INBOX", 5 ); mbox->present[M] = mbox->present[S] = BOX_POSSIBLE; mbox->next = 0; *mboxapp = mbox; mboxapp = &mbox->next; boxes_total++; boxp = nboxp; } while (boxp); } else { if (!chan->patterns) boxes_total++; } ce = add_channel( chanapp, chan, ops ); ce->boxes = boxes; ce->boxlist = boxlist; return ce; } typedef struct { int t[2]; channel_conf_t *chan; driver_t *drv[2]; store_t *ctx[2]; chan_ent_t *chanptr; box_ent_t *boxptr; string_list_t *boxes[2]; char *names[2]; int ret, all, list, state[2]; char done, skip, cben; } main_vars_t; #define AUX &mvars->t[t] #define MVARS(aux) \ int t = *(int *)aux; \ main_vars_t *mvars = (main_vars_t *)(((char *)(&((int *)aux)[-t])) - offsetof(main_vars_t, t)); #define E_START 0 #define E_OPEN 1 #define E_SYNC 2 static void sync_chans( main_vars_t *mvars, int ent ); int main( int argc, char **argv ) { main_vars_t mvars[1]; chan_ent_t *chans = 0, **chanapp = &chans; group_conf_t *group; channel_conf_t *chan; string_list_t *channame; char *config = 0, *opt, *ochar; int oind, cops = 0, op, ops[2] = { 0, 0 }, pseudo = 0; tzset(); gethostname( Hostname, sizeof(Hostname) ); if ((ochar = strchr( Hostname, '.' ))) *ochar = 0; Pid = getpid(); if (!(Home = getenv("HOME"))) { fputs( "Fatal: $HOME not set\n", stderr ); return 1; } arc4_init(); memset( mvars, 0, sizeof(*mvars) ); mvars->t[1] = 1; for (oind = 1, ochar = 0; ; ) { if (!ochar || !*ochar) { if (oind >= argc) break; if (argv[oind][0] != '-') break; if (argv[oind][1] == '-') { opt = argv[oind++] + 2; if (!*opt) break; if (!strcmp( opt, "config" )) { if (oind >= argc) { error( "--config requires an argument.\n" ); return 1; } config = argv[oind++]; } else if (starts_with( opt, -1, "config=", 7 )) config = opt + 7; else if (!strcmp( opt, "all" )) mvars->all = 1; else if (!strcmp( opt, "list" )) mvars->list = 1; else if (!strcmp( opt, "help" )) usage( 0 ); else if (!strcmp( opt, "version" )) version(); else if (!strcmp( opt, "quiet" )) { if (DFlags & QUIET) DFlags |= VERYQUIET; else DFlags |= QUIET; } else if (!strcmp( opt, "verbose" )) { DFlags |= VERBOSE; } else if (starts_with( opt, -1, "debug", 5 )) { opt += 5; if (!*opt) op = VERBOSE | DEBUG_ALL; else if (!strcmp( opt, "-crash" )) op = DEBUG_CRASH; else if (!strcmp( opt, "-driver" )) op = VERBOSE | DEBUG_DRV; else if (!strcmp( opt, "-driver-all" )) op = VERBOSE | DEBUG_DRV | DEBUG_DRV_ALL; else if (!strcmp( opt, "-maildir" )) op = VERBOSE | DEBUG_MAILDIR; else if (!strcmp( opt, "-main" )) op = VERBOSE | DEBUG_MAIN; else if (!strcmp( opt, "-net" )) op = VERBOSE | DEBUG_NET; else if (!strcmp( opt, "-net-all" )) op = VERBOSE | DEBUG_NET | DEBUG_NET_ALL; else if (!strcmp( opt, "-sync" )) op = VERBOSE | DEBUG_SYNC; else goto badopt; DFlags |= op; } else if (!strcmp( opt, "pull" )) cops |= XOP_PULL, ops[M] |= XOP_HAVE_TYPE; else if (!strcmp( opt, "push" )) cops |= XOP_PUSH, ops[M] |= XOP_HAVE_TYPE; else if (starts_with( opt, -1, "create", 6 )) { opt += 6; op = OP_CREATE|XOP_HAVE_CREATE; lcop: if (!*opt) cops |= op; else if (!strcmp( opt, "-master" )) ops[M] |= op; else if (!strcmp( opt, "-slave" )) ops[S] |= op; else goto badopt; ops[M] |= op & (XOP_HAVE_CREATE|XOP_HAVE_REMOVE|XOP_HAVE_EXPUNGE); } else if (starts_with( opt, -1, "remove", 6 )) { opt += 6; op = OP_REMOVE|XOP_HAVE_REMOVE; goto lcop; } else if (starts_with( opt, -1, "expunge", 7 )) { opt += 7; op = OP_EXPUNGE|XOP_HAVE_EXPUNGE; goto lcop; } else if (!strcmp( opt, "no-expunge" )) ops[M] |= XOP_HAVE_EXPUNGE; else if (!strcmp( opt, "no-create" )) ops[M] |= XOP_HAVE_CREATE; else if (!strcmp( opt, "no-remove" )) ops[M] |= XOP_HAVE_REMOVE; else if (!strcmp( opt, "full" )) ops[M] |= XOP_HAVE_TYPE|XOP_PULL|XOP_PUSH; else if (!strcmp( opt, "noop" )) ops[M] |= XOP_HAVE_TYPE; else if (starts_with( opt, -1, "pull", 4 )) { op = XOP_PULL; lcac: opt += 4; if (!*opt) cops |= op; else if (*opt == '-') { opt++; goto rlcac; } else goto badopt; } else if (starts_with( opt, -1, "push", 4 )) { op = XOP_PUSH; goto lcac; } else { op = 0; rlcac: if (!strcmp( opt, "new" )) op |= OP_NEW; else if (!strcmp( opt, "renew" )) op |= OP_RENEW; else if (!strcmp( opt, "delete" )) op |= OP_DELETE; else if (!strcmp( opt, "flags" )) op |= OP_FLAGS; else { badopt: error( "Unknown option '%s'\n", argv[oind - 1] ); return 1; } switch (op & XOP_MASK_DIR) { case XOP_PULL: ops[S] |= op & OP_MASK_TYPE; break; case XOP_PUSH: ops[M] |= op & OP_MASK_TYPE; break; default: cops |= op; break; } ops[M] |= XOP_HAVE_TYPE; } continue; } ochar = argv[oind++] + 1; if (!*ochar) { error( "Invalid option '-'\n" ); return 1; } } switch (*ochar++) { case 'a': mvars->all = 1; break; case 'l': mvars->list = 1; break; case 'c': if (*ochar == 'T') { ochar++; pseudo = 1; } if (oind >= argc) { error( "-c requires an argument.\n" ); return 1; } config = argv[oind++]; break; case 'C': op = OP_CREATE|XOP_HAVE_CREATE; cop: if (*ochar == 'm') ops[M] |= op, ochar++; else if (*ochar == 's') ops[S] |= op, ochar++; else if (*ochar == '-') ochar++; else cops |= op; ops[M] |= op & (XOP_HAVE_CREATE|XOP_HAVE_REMOVE|XOP_HAVE_EXPUNGE); break; case 'R': op = OP_REMOVE|XOP_HAVE_REMOVE; goto cop; case 'X': op = OP_EXPUNGE|XOP_HAVE_EXPUNGE; goto cop; case 'F': cops |= XOP_PULL|XOP_PUSH; FALLTHROUGH case '0': ops[M] |= XOP_HAVE_TYPE; break; case 'n': case 'd': case 'f': case 'N': --ochar; op = 0; cac: for (;; ochar++) { if (*ochar == 'n') op |= OP_NEW; else if (*ochar == 'd') op |= OP_DELETE; else if (*ochar == 'f') op |= OP_FLAGS; else if (*ochar == 'N') op |= OP_RENEW; else break; } if (op & OP_MASK_TYPE) switch (op & XOP_MASK_DIR) { case XOP_PULL: ops[S] |= op & OP_MASK_TYPE; break; case XOP_PUSH: ops[M] |= op & OP_MASK_TYPE; break; default: cops |= op; break; } else cops |= op; ops[M] |= XOP_HAVE_TYPE; break; case 'L': op = XOP_PULL; goto cac; case 'H': op = XOP_PUSH; goto cac; case 'q': if (DFlags & QUIET) DFlags |= VERYQUIET; else DFlags |= QUIET; break; case 'V': DFlags |= VERBOSE; break; case 'D': for (op = 0; *ochar; ochar++) { switch (*ochar) { case 'C': op |= DEBUG_CRASH; break; case 'd': op |= DEBUG_DRV | VERBOSE; break; case 'D': op |= DEBUG_DRV | DEBUG_DRV_ALL | VERBOSE; break; case 'm': op |= DEBUG_MAILDIR | VERBOSE; break; case 'M': op |= DEBUG_MAIN | VERBOSE; break; case 'n': op |= DEBUG_NET | VERBOSE; break; case 'N': op |= DEBUG_NET | DEBUG_NET_ALL | VERBOSE; break; case 's': op |= DEBUG_SYNC | VERBOSE; break; default: error( "Unknown -D flag '%c'\n", *ochar ); return 1; } } if (!op) op = DEBUG_ALL | VERBOSE; DFlags |= op; break; case 'J': DFlags |= KEEPJOURNAL; JLimit = strtol( ochar, &ochar, 10 ); break; case 'Z': DFlags |= ZERODELAY; break; case 'v': version(); case 'h': usage( 0 ); default: error( "Unknown option '-%c'\n", *(ochar - 1) ); return 1; } } if (!(DFlags & (QUIET | DEBUG_ALL)) && isatty( 1 )) DFlags |= PROGRESS; #ifdef __linux__ if (DFlags & DEBUG_CRASH) { signal( SIGSEGV, crashHandler ); signal( SIGBUS, crashHandler ); signal( SIGILL, crashHandler ); } #endif if (merge_ops( cops, ops )) return 1; if (load_config( config, pseudo )) return 1; if (!channels) { fputs( "No channels defined. Try 'man " EXE "'\n", stderr ); return 1; } if (mvars->all) { for (chan = channels; chan; chan = chan->next) { add_channel( &chanapp, chan, ops ); if (!chan->patterns) boxes_total++; } } else { for (; argv[oind]; oind++) { for (group = groups; group; group = group->next) { if (!strcmp( group->name, argv[oind] )) { for (channame = group->channels; channame; channame = channame->next) if (!add_named_channel( &chanapp, channame->string, ops )) mvars->ret = 1; goto gotgrp; } } if (!add_named_channel( &chanapp, argv[oind], ops )) mvars->ret = 1; gotgrp: ; } } if (!chans) { fputs( "No channel specified. Try '" EXE " -h'\n", stderr ); return 1; } mvars->chanptr = chans; if (!mvars->list) stats(); mvars->cben = 1; sync_chans( mvars, E_START ); main_loop(); if (!mvars->list) flushn(); return mvars->ret; } #define ST_FRESH 0 #define ST_CONNECTED 1 #define ST_OPEN 2 #define ST_CANCELING 3 #define ST_CLOSED 4 static void cancel_prep_done( void *aux ) { MVARS(aux) mvars->drv[t]->free_store( mvars->ctx[t] ); mvars->state[t] = ST_CLOSED; sync_chans( mvars, E_OPEN ); } static void store_bad( void *aux ) { MVARS(aux) mvars->drv[t]->cancel_store( mvars->ctx[t] ); mvars->state[t] = ST_CLOSED; mvars->ret = mvars->skip = 1; sync_chans( mvars, E_OPEN ); } static void store_connected( int sts, void *aux ); static void store_listed( int sts, string_list_t *boxes, void *aux ); static int sync_listed_boxes( main_vars_t *mvars, box_ent_t *mbox ); static void done_sync_2_dyn( int sts, void *aux ); static void done_sync( int sts, void *aux ); #define nz(a,b) ((a)?(a):(b)) static void sync_chans( main_vars_t *mvars, int ent ) { box_ent_t *mbox, *nmbox, **mboxapp; char **boxes[2]; const char *labels[2]; int t, mb, sb, cmp; if (!mvars->cben) return; switch (ent) { case E_OPEN: goto opened; case E_SYNC: goto syncone; } do { mvars->chan = mvars->chanptr->conf; info( "Channel %s\n", mvars->chan->name ); mvars->skip = mvars->cben = 0; for (t = 0; t < 2; t++) { int st = mvars->chan->stores[t]->driver->get_fail_state( mvars->chan->stores[t] ); if (st != FAIL_TEMP) { info( "Skipping due to %sfailed %s store %s.\n", (st == FAIL_WAIT) ? "temporarily " : "", str_ms[t], mvars->chan->stores[t]->name ); mvars->skip = 1; } } if (mvars->skip) goto next2; mvars->state[M] = mvars->state[S] = ST_FRESH; if ((DFlags & DEBUG_DRV) || (mvars->chan->stores[M]->driver->get_caps( 0 ) & mvars->chan->stores[S]->driver->get_caps( 0 ) & DRV_VERBOSE)) labels[M] = "M: ", labels[S] = "S: "; else labels[M] = labels[S] = ""; for (t = 0; t < 2; t++) { driver_t *drv = mvars->chan->stores[t]->driver; store_t *ctx = drv->alloc_store( mvars->chan->stores[t], labels[t] ); if (DFlags & DEBUG_DRV) { drv = &proxy_driver; ctx = proxy_alloc_store( ctx, labels[t] ); } mvars->drv[t] = drv; mvars->ctx[t] = ctx; drv->set_bad_callback( ctx, store_bad, AUX ); } for (t = 0; ; t++) { info( "Opening %s store %s...\n", str_ms[t], mvars->chan->stores[t]->name ); mvars->drv[t]->connect_store( mvars->ctx[t], store_connected, AUX ); if (t || mvars->skip) break; } mvars->cben = 1; opened: if (mvars->skip) goto next; if (mvars->state[M] != ST_OPEN || mvars->state[S] != ST_OPEN) return; if (!mvars->chanptr->boxlist && mvars->chan->patterns) { mvars->chanptr->boxlist = 2; boxes[M] = filter_boxes( mvars->boxes[M], mvars->chan->boxes[M], mvars->chan->patterns ); boxes[S] = filter_boxes( mvars->boxes[S], mvars->chan->boxes[S], mvars->chan->patterns ); mboxapp = &mvars->chanptr->boxes; for (mb = sb = 0; ; ) { char *mname = boxes[M] ? boxes[M][mb] : 0; char *sname = boxes[S] ? boxes[S][sb] : 0; if (!mname && !sname) break; mbox = nfmalloc( sizeof(*mbox) ); if (!(cmp = !mname - !sname) && !(cmp = cmp_box_names( &mname, &sname ))) { mbox->name = mname; free( sname ); mbox->present[M] = mbox->present[S] = BOX_PRESENT; mb++; sb++; } else if (cmp < 0) { mbox->name = mname; mbox->present[M] = BOX_PRESENT; mbox->present[S] = (!mb && !strcmp( mbox->name, "INBOX" )) ? BOX_PRESENT : BOX_ABSENT; mb++; } else { mbox->name = sname; mbox->present[M] = (!sb && !strcmp( mbox->name, "INBOX" )) ? BOX_PRESENT : BOX_ABSENT; mbox->present[S] = BOX_PRESENT; sb++; } mbox->next = 0; *mboxapp = mbox; mboxapp = &mbox->next; boxes_total++; } free( boxes[M] ); free( boxes[S] ); if (!mvars->list) stats(); } mvars->boxptr = mvars->chanptr->boxes; if (mvars->list && chans_total > 1) printf( "%s:\n", mvars->chan->name ); syncml: mvars->done = mvars->cben = 0; if (mvars->chanptr->boxlist) { while ((mbox = mvars->boxptr)) { mvars->boxptr = mbox->next; if (sync_listed_boxes( mvars, mbox )) goto syncw; } } else { if (!mvars->list) { int present[] = { BOX_POSSIBLE, BOX_POSSIBLE }; sync_boxes( mvars->ctx, mvars->chan->boxes, present, mvars->chan, done_sync, mvars ); mvars->skip = 1; syncw: mvars->cben = 1; if (!mvars->done) return; syncone: if (!mvars->skip) goto syncml; } else printf( "%s <=> %s\n", nz( mvars->chan->boxes[M], "INBOX" ), nz( mvars->chan->boxes[S], "INBOX" ) ); } next: mvars->cben = 0; for (t = 0; t < 2; t++) { free_string_list( mvars->boxes[t] ); mvars->boxes[t] = 0; if (mvars->state[t] == ST_FRESH) { /* An unconnected store may be only cancelled. */ mvars->state[t] = ST_CLOSED; mvars->drv[t]->cancel_store( mvars->ctx[t] ); } else if (mvars->state[t] == ST_CONNECTED || mvars->state[t] == ST_OPEN) { mvars->state[t] = ST_CANCELING; mvars->drv[t]->cancel_cmds( mvars->ctx[t], cancel_prep_done, AUX ); } } mvars->cben = 1; if (mvars->state[M] != ST_CLOSED || mvars->state[S] != ST_CLOSED) { mvars->skip = 1; return; } if (mvars->chanptr->boxlist == 2) { for (nmbox = mvars->chanptr->boxes; (mbox = nmbox); ) { nmbox = mbox->next; free( mbox->name ); free( mbox ); } mvars->chanptr->boxes = 0; mvars->chanptr->boxlist = 0; } next2: if (!mvars->list) { chans_done++; stats(); } } while ((mvars->chanptr = mvars->chanptr->next)); for (t = 0; t < N_DRIVERS; t++) drivers[t]->cleanup(); } static void store_connected( int sts, void *aux ) { MVARS(aux) string_list_t *cpat; int cflags; switch (sts) { case DRV_CANCELED: return; case DRV_OK: if (!mvars->skip && !mvars->chanptr->boxlist && mvars->chan->patterns) { for (cflags = 0, cpat = mvars->chan->patterns; cpat; cpat = cpat->next) { const char *pat = cpat->string; if (*pat != '!') { char buf[8]; int bufl = snprintf( buf, sizeof(buf), "%s%s", nz( mvars->chan->boxes[t], "" ), pat ); int flags = 0; /* Partial matches like "INB*" or even "*" are not considered, * except implicity when the INBOX lives under Path. */ if (starts_with( buf, bufl, "INBOX", 5 )) { char c = buf[5]; if (!c) { /* User really wants the INBOX. */ flags |= LIST_INBOX; } else if (c == '/') { /* Flattened sub-folders of INBOX actually end up in Path. */ if (mvars->ctx[t]->conf->flat_delim) flags |= LIST_PATH; else flags |= LIST_INBOX; } else if (c == '*' || c == '%') { /* It can be both INBOX and Path, but don't require Path to be configured. */ flags |= LIST_INBOX | LIST_PATH_MAYBE; } else { /* It's definitely not the INBOX. */ flags |= LIST_PATH; } } else { flags |= LIST_PATH; } debug( "pattern '%s' (effective '%s'): %sPath, %sINBOX\n", pat, buf, (flags & LIST_PATH) ? "" : "no ", (flags & LIST_INBOX) ? "" : "no "); cflags |= flags; } } mvars->state[t] = ST_CONNECTED; mvars->drv[t]->list_store( mvars->ctx[t], cflags, store_listed, AUX ); return; } mvars->state[t] = ST_OPEN; break; default: mvars->ret = mvars->skip = 1; mvars->state[t] = ST_OPEN; break; } sync_chans( mvars, E_OPEN ); } static void store_listed( int sts, string_list_t *boxes, void *aux ) { MVARS(aux) string_list_t *box; switch (sts) { case DRV_CANCELED: return; case DRV_OK: for (box = boxes; box; box = box->next) { if (mvars->ctx[t]->conf->flat_delim) { string_list_t *nbox; if (map_name( box->string, (char **)&nbox, offsetof(string_list_t, string), mvars->ctx[t]->conf->flat_delim, "/" ) < 0) { error( "Error: flattened mailbox name '%s' contains canonical hierarchy delimiter\n", box->string ); mvars->ret = mvars->skip = 1; } else { nbox->next = mvars->boxes[t]; mvars->boxes[t] = nbox; } } else { add_string_list( &mvars->boxes[t], box->string ); } } if (mvars->ctx[t]->conf->map_inbox) { debug( "adding mapped inbox to %s: %s\n", str_ms[t], mvars->ctx[t]->conf->map_inbox ); add_string_list( &mvars->boxes[t], mvars->ctx[t]->conf->map_inbox ); } break; default: mvars->ret = mvars->skip = 1; break; } mvars->state[t] = ST_OPEN; sync_chans( mvars, E_OPEN ); } static int sync_listed_boxes( main_vars_t *mvars, box_ent_t *mbox ) { if (mvars->chan->boxes[M] || mvars->chan->boxes[S]) { const char *mpfx = nz( mvars->chan->boxes[M], "" ); const char *spfx = nz( mvars->chan->boxes[S], "" ); if (!mvars->list) { nfasprintf( &mvars->names[M], "%s%s", mpfx, mbox->name ); nfasprintf( &mvars->names[S], "%s%s", spfx, mbox->name ); sync_boxes( mvars->ctx, (const char **)mvars->names, mbox->present, mvars->chan, done_sync_2_dyn, mvars ); return 1; } printf( "%s%s <=> %s%s\n", mpfx, mbox->name, spfx, mbox->name ); } else { if (!mvars->list) { mvars->names[M] = mvars->names[S] = mbox->name; sync_boxes( mvars->ctx, (const char **)mvars->names, mbox->present, mvars->chan, done_sync, mvars ); return 1; } puts( mbox->name ); } return 0; } static void done_sync_2_dyn( int sts, void *aux ) { main_vars_t *mvars = (main_vars_t *)aux; free( mvars->names[M] ); free( mvars->names[S] ); done_sync( sts, aux ); } static void done_sync( int sts, void *aux ) { main_vars_t *mvars = (main_vars_t *)aux; mvars->done = 1; boxes_done++; stats(); if (sts) { mvars->ret = 1; if (sts & (SYNC_BAD(M) | SYNC_BAD(S))) { if (sts & SYNC_BAD(M)) mvars->state[M] = ST_CLOSED; if (sts & SYNC_BAD(S)) mvars->state[S] = ST_CLOSED; mvars->skip = 1; } } sync_chans( mvars, E_SYNC ); } isync-1.3.0/src/driver.c0000644000175000001440000000425213141421437012006 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2010-2012 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #include "driver.h" #include #include driver_t *drivers[N_DRIVERS] = { &maildir_driver, &imap_driver }; void free_generic_messages( message_t *msgs ) { message_t *tmsg; for (; msgs; msgs = tmsg) { tmsg = msgs->next; free( msgs->msgid ); free( msgs ); } } void parse_generic_store( store_conf_t *store, conffile_t *cfg ) { if (!strcasecmp( "Trash", cfg->cmd )) { store->trash = nfstrdup( cfg->val ); } else if (!strcasecmp( "TrashRemoteNew", cfg->cmd )) { store->trash_remote_new = parse_bool( cfg ); } else if (!strcasecmp( "TrashNewOnly", cfg->cmd )) { store->trash_only_new = parse_bool( cfg ); } else if (!strcasecmp( "MaxSize", cfg->cmd )) { store->max_size = parse_size( cfg ); } else if (!strcasecmp( "MapInbox", cfg->cmd )) { store->map_inbox = nfstrdup( cfg->val ); } else if (!strcasecmp( "Flatten", cfg->cmd )) { const char *p; for (p = cfg->val; *p; p++) { if (*p == '/') { error( "%s:%d: flattened hierarchy delimiter cannot contain the canonical delimiter '/'\n", cfg->file, cfg->line ); cfg->err = 1; return; } } store->flat_delim = nfstrdup( cfg->val ); } else { error( "%s:%d: unknown keyword '%s'\n", cfg->file, cfg->line, cfg->cmd ); cfg->err = 1; } } isync-1.3.0/src/mdconvert.10000644000175000001440000000311113007413620012417 00000000000000.ig \" mdconvert - Maildir mailbox UID storage scheme converter \" Copyright (C) 2004 Oswald Buddenhagen \" \" 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, see . .. .TH mdconvert 1 "2004 Mar 27" .. .SH NAME mdconvert - Maildir mailbox UID storage scheme converter .. .SH SYNOPSIS \fBmdconvert\fR [\fIoptions\fR ...] \fImailbox\fR ... .. .SH DESCRIPTION \fBmdconvert\fR converts Maildir mailboxes between the two UID storage schemes supported by \fBmbsync\fR. See \fBmbsync\fR's manual page for details on these schemes. .. .SH OPTIONS .TP \fB-a\fR, \fB--alt\fR Convert to the \fBalternative\fR (Berkeley DB based) UID storage scheme. .TP \fB-n\fR, \fB--native\fR Convert to the \fBnative\fR (file name based) UID storage scheme. This is the default. .TP \fB-h\fR, \fB--help\fR Displays a summary of command line options. .TP \fB-v\fR, \fB--version\fR Displays version information. .. .SH SEE ALSO mbsync(1) .. .SH AUTHOR Written and maintained by Oswald Buddenhagen . isync-1.3.0/src/run-tests.pl0000755000175000001440000004330313141404045012647 00000000000000#! /usr/bin/perl -w # # Copyright (C) 2006,2013 Oswald Buddenhagen # # 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, see . # use warnings; use strict; use Cwd; use File::Path; my $use_vg = $ENV{USE_VALGRIND}; my $mbsync = getcwd()."/mbsync"; -d "tmp" or mkdir "tmp"; chdir "tmp" or die "Cannot enter temp direcory.\n"; sub show($$$); sub test($$$@); ################################################################################ # Format of the test defs: [ master, slave, state ] # master/slave: [ maxuid, { seq, uid, flags }... ] # state: [ MaxPulledUid, MaxExpiredMasterUid, MaxPushedUid, { muid, suid, flags }... ] # generic syncing tests my @x01 = ( [ 9, 1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "F", 7, 7, "FT", 9, 9, "" ], [ 9, 1, 1, "", 2, 2, "F", 3, 3, "F", 4, 4, "", 5, 5, "", 7, 7, "", 8, 8, "", 10, 9, "" ], [ 8, 0, 0, 1, 1, "", 2, 2, "", 3, 3, "", 4, 4, "", 5, 5, "", 6, 6, "", 7, 7, "", 8, 8, "" ], ); my @O01 = ("", "", ""); #show("01", "01", "01"); my @X01 = ( [ 10, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "FT", 7, 7, "FT", 9, 9, "", 10, 10, "" ], [ 10, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 7, 7, "FT", 8, 8, "T", 9, 10, "", 10, 9, "" ], [ 9, 0, 9, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 0, "", 7, 7, "FT", 0, 8, "", 10, 9, "", 9, 10, "" ], ); test("full", \@x01, \@X01, @O01); my @O02 = ("", "", "Expunge Both\n"); #show("01", "02", "02"); my @X02 = ( [ 10, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 9, 9, "", 10, 10, "" ], [ 10, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 9, 10, "", 10, 9, "" ], [ 9, 0, 9, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 10, 9, "", 9, 10, "" ], ); test("full + expunge both", \@x01, \@X02, @O02); my @O03 = ("", "", "Expunge Slave\n"); #show("01", "03", "03"); my @X03 = ( [ 10, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "FT", 7, 7, "FT", 9, 9, "", 10, 10, "" ], [ 10, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 9, 10, "", 10, 9, "" ], [ 9, 0, 9, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 0, "T", 6, 0, "", 7, 0, "T", 10, 9, "", 9, 10, "" ], ); test("full + expunge slave", \@x01, \@X03, @O03); my @O04 = ("", "", "Sync Pull\n"); #show("01", "04", "04"); my @X04 = ( [ 9, 1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "F", 7, 7, "FT", 9, 9, "" ], [ 10, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 7, 7, "FT", 8, 8, "T", 9, 10, "", 10, 9, "" ], [ 9, 0, 0, 1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "", 7, 7, "FT", 0, 8, "", 9, 10, "" ], ); test("pull", \@x01, \@X04, @O04); my @O05 = ("", "", "Sync Flags\n"); #show("01", "05", "05"); my @X05 = ( [ 9, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "F", 7, 7, "FT", 9, 9, "" ], [ 9, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 7, 7, "FT", 8, 8, "", 10, 9, "" ], [ 8, 0, 0, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "", 7, 7, "FT", 8, 8, "" ], ); test("flags", \@x01, \@X05, @O05); my @O06 = ("", "", "Sync Delete\n"); #show("01", "06", "06"); my @X06 = ( [ 9, 1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "FT", 7, 7, "FT", 9, 9, "" ], [ 9, 1, 1, "", 2, 2, "F", 3, 3, "F", 4, 4, "", 5, 5, "", 7, 7, "", 8, 8, "T", 10, 9, "" ], [ 8, 0, 0, 1, 1, "", 2, 2, "", 3, 3, "", 4, 4, "", 5, 5, "", 6, 0, "", 7, 7, "", 0, 8, "" ], ); test("deletions", \@x01, \@X06, @O06); my @O07 = ("", "", "Sync New\n"); #show("01", "07", "07"); my @X07 = ( [ 10, 1, 1, "F", 2, 2, "", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "F", 7, 7, "FT", 9, 9, "", 10, 10, "" ], [ 10, 1, 1, "", 2, 2, "F", 3, 3, "F", 4, 4, "", 5, 5, "", 7, 7, "", 8, 8, "", 9, 10, "", 10, 9, "" ], [ 9, 0, 9, 1, 1, "", 2, 2, "", 3, 3, "", 4, 4, "", 5, 5, "", 6, 6, "", 7, 7, "", 8, 8, "", 10, 9, "", 9, 10, "" ], ); test("new", \@x01, \@X07, @O07); my @O08 = ("", "", "Sync PushFlags PullDelete\n"); #show("01", "08", "08"); my @X08 = ( [ 9, 1, 1, "F", 2, 2, "F", 3, 3, "FS", 4, 4, "", 5, 5, "T", 6, 6, "F", 7, 7, "FT", 9, 9, "" ], [ 9, 1, 1, "", 2, 2, "F", 3, 3, "F", 4, 4, "", 5, 5, "", 7, 7, "", 8, 8, "T", 10, 9, "" ], [ 8, 0, 0, 1, 1, "", 2, 2, "F", 3, 3, "F", 4, 4, "", 5, 5, "", 6, 6, "", 7, 7, "", 0, 8, "" ], ); test("push flags + pull deletions", \@x01, \@X08, @O08); # size restriction tests my @x10 = ( [ 2, 1, 1, "", 2, 2, "*" ], [ 1, 3, 1, "*" ], [ 0, 0, 0, ], ); my @O11 = ("MaxSize 1k\n", "MaxSize 1k\n", ""); #show("10", "11", "11"); my @X11 = ( [ 2, 1, 1, "", 2, 2, "*" ], [ 2, 3, 1, "*", 1, 2, "" ], [ 2, 0, 1, 0, 1, "^", 1, 2, "", 2, 0, "^" ], ); test("max size", \@x10, \@X11, @O11); my @O22 = ("", "MaxSize 1k\n", ""); #show("11", "22", "22"); my @X22 = ( [ 3, 1, 1, "", 2, 2, "*", 3, 3, "*" ], [ 2, 3, 1, "*", 1, 2, "" ], [ 2, 0, 1, 3, 1, "", 1, 2, "", 2, 0, "^" ], ); test("slave max size", \@X11, \@X22, @O22); # expiration tests my @x30 = ( [ 6, 1, 1, "F", 2, 2, "", 3, 3, "S", 4, 4, "", 5, 5, "S", 6, 6, "" ], [ 0, ], [ 0, 0, 0, ], ); my @O31 = ("", "", "MaxMessages 3\n"); #show("30", "31", "31"); my @X31 = ( [ 6, 1, 1, "F", 2, 2, "", 3, 3, "S", 4, 4, "", 5, 5, "S", 6, 6, "" ], [ 5, 1, 1, "F", 2, 2, "", 4, 3, "", 5, 4, "S", 6, 5, "" ], [ 6, 3, 0, 1, 1, "F", 2, 2, "", 4, 3, "", 5, 4, "S", 6, 5, "" ], ); test("max messages", \@x30, \@X31, @O31); my @O32 = ("", "", "MaxMessages 3\nExpireUnread yes\n"); #show("30", "32", "32"); my @X32 = ( [ 6, 1, 1, "F", 2, 2, "", 3, 3, "S", 4, 4, "", 5, 5, "S", 6, 6, "" ], [ 4, 1, 1, "F", 4, 2, "", 5, 3, "S", 6, 4, "" ], [ 6, 3, 0, 1, 1, "F", 4, 2, "", 5, 3, "S", 6, 4, "" ], ); test("max messages vs. unread", \@x30, \@X32, @O32); my @x50 = ( [ 6, 1, 1, "FS", 2, 2, "FS", 3, 3, "S", 4, 4, "", 5, 5, "", 6, 6, "" ], [ 6, 1, 1, "S", 2, 2, "ST", 4, 4, "", 5, 5, "", 6, 6, "" ], [ 6, 3, 0, 1, 1, "FS", 2, 2, "~S", 3, 3, "~S", 4, 4, "", 5, 5, "", 6, 6, "" ], ); my @O51 = ("", "", "MaxMessages 3\nExpunge Both\n"); #show("50", "51", "51"); my @X51 = ( [ 6, 1, 1, "S", 2, 2, "FS", 3, 3, "S", 4, 4, "", 5, 5, "", 6, 6, "" ], [ 6, 2, 2, "FS", 4, 4, "", 5, 5, "", 6, 6, "" ], [ 6, 3, 0, 2, 2, "FS", 4, 4, "", 5, 5, "", 6, 6, "" ], ); test("max messages + expunge", \@x50, \@X51, @O51); ################################################################################ chdir ".."; rmdir "tmp"; print "OK.\n"; exit 0; sub qm($) { shift; s/\\/\\\\/g; s/\"/\\"/g; s/\"/\\"/g; s/\n/\\n/g; return $_; } # $master, $slave, $channel sub writecfg($$$) { open(FILE, ">", ".mbsyncrc") or die "Cannot open .mbsyncrc.\n"; print FILE "FSync no MaildirStore master Path ./ Inbox ./master ".shift()." MaildirStore slave Path ./ Inbox ./slave ".shift()." Channel test Master :master: Slave :slave: SyncState * ".shift(); close FILE; } sub killcfg() { unlink $_ for (glob("*.log")); unlink ".mbsyncrc"; } # $options sub runsync($$) { my ($flags, $file) = @_; my $cmd; if ($use_vg) { $cmd = "valgrind -q --error-exitcode=1 "; } else { $flags .= " -D"; } $cmd .= "$mbsync -Z $flags -c .mbsyncrc test"; open FILE, "$cmd 2>&1 |"; my @out = ; close FILE or push(@out, $! ? "*** error closing mbsync: $!\n" : "*** mbsync exited with signal ".($?&127).", code ".($?>>8)."\n"); if ($file) { open FILE, ">$file" or die("Cannot create $file: $!\n"); print FILE @out; close FILE; } return $?, @out; } # $path sub readbox($) { my $bn = shift; (-d $bn) or die "No mailbox '$bn'.\n"; (-d $bn."/tmp" and -d $bn."/new" and -d $bn."/cur") or die "Invalid mailbox '$bn'.\n"; open(FILE, "<", $bn."/.uidvalidity") or die "Cannot read UID validity of mailbox '$bn'.\n"; my $dummy = ; chomp(my $mu = ); close FILE; my %ms = (); for my $d ("cur", "new") { opendir(DIR, $bn."/".$d) or next; for my $f (grep(!/^\.\.?$/, readdir(DIR))) { my ($uid, $flg, $num); if ($f =~ /^\d+\.\d+_\d+\.[-[:alnum:]]+,U=(\d+):2,(.*)$/) { ($uid, $flg) = ($1, $2); } elsif ($f =~ /^\d+\.\d+_(\d+)\.[-[:alnum:]]+:2,(.*)$/) { ($uid, $flg) = (0, $2); } else { print STDERR "unrecognided file name '$f' in '$bn'.\n"; exit 1; } open(FILE, "<", $bn."/".$d."/".$f) or die "Cannot read message '$f' in '$bn'.\n"; my $sz = 0; while () { /^Subject: (\d+)$/ && ($num = $1); $sz += length($_); } close FILE; if (!defined($num)) { print STDERR "message '$f' in '$bn' has no identifier.\n"; exit 1; } @{ $ms{$num} } = ($uid, $flg.($sz>1000?"*":"")); } } return ($mu, %ms); } # $boxname # Output: # [ maxuid, # serial, uid, "flags", ... ], sub showbox($) { my ($bn) = @_; my ($mu, %ms) = readbox($bn); my @MS = ($mu); for my $num (sort { $a <=> $b } keys %ms) { push @MS, $num, $ms{$num}[0], $ms{$num}[1]; } printbox($bn, @MS); } # $filename # Output: # [ maxuid[M], mmaxxuid, maxuid[S], # uid[M], uid[S], "flags", ... ], sub showstate($) { my ($fn) = @_; if (!open(FILE, "<", $fn)) { print STDERR " Cannot read sync state $fn: $!\n"; return; } chomp(my @ls = ); close FILE; my %hdr; OUTER: while (1) { while (@ls) { $_ = shift(@ls); last OUTER if (!length($_)); if (!/^([^ ]+) (\d+)$/) { print STDERR "Malformed sync state header entry: $_\n"; close FILE; return; } $hdr{$1} = $2; } print STDERR "Unterminated sync state header.\n"; close FILE; return; } my @T = ($hdr{'MaxPulledUid'} // "missing", $hdr{'MaxExpiredMasterUid'} // "0", $hdr{'MaxPushedUid'} // "missing"); for (@ls) { /^(\d+) (\d+) (.*)$/; push @T, $1, $2, $3; } printstate(@T); } # $filename sub showchan($) { my ($fn) = @_; showbox("master"); showbox("slave"); showstate($fn); } # $source_state_name, $target_state_name, $configs_name sub show($$$) { my ($sx, $tx, $sfxn) = @_; my (@sp, @sfx); eval "\@sp = \@x$sx"; eval "\@sfx = \@O$sfxn"; mkchan($sp[0], $sp[1], @{ $sp[2] }); print "my \@x$sx = (\n"; showchan("slave/.mbsyncstate"); print ");\n"; &writecfg(@sfx); runsync("", ""); killcfg(); print "my \@X$tx = (\n"; showchan("slave/.mbsyncstate"); print ");\n"; print "test(\"\", \\\@x$sx, \\\@X$tx, \@O$sfxn);\n\n"; rmtree "slave"; rmtree "master"; } # $boxname, $maxuid, @msgs sub mkbox($$@) { my ($bn, $mu, @ms) = @_; rmtree($bn); (mkdir($bn) and mkdir($bn."/tmp") and mkdir($bn."/new") and mkdir($bn."/cur")) or die "Cannot create mailbox $bn.\n"; open(FILE, ">", $bn."/.uidvalidity") or die "Cannot create UID validity for mailbox $bn.\n"; print FILE "1\n$mu\n"; close FILE; while (@ms) { my ($num, $uid, $flg) = (shift @ms, shift @ms, shift @ms); if ($uid) { $uid = ",U=".$uid; } else { $uid = ""; } my $big = $flg =~ s/\*//; open(FILE, ">", $bn."/".($flg =~ /S/ ? "cur" : "new")."/0.1_".$num.".local".$uid.":2,".$flg) or die "Cannot create message $num in mailbox $bn.\n"; print FILE "From: foo\nTo: bar\nDate: Thu, 1 Jan 1970 00:00:00 +0000\nSubject: $num\n\n".(("A"x50)."\n")x($big*30); close FILE; } } # \@master, \@slave, @syncstate sub mkchan($$@) { my ($m, $s, @t) = @_; &mkbox("master", @{ $m }); &mkbox("slave", @{ $s }); open(FILE, ">", "slave/.mbsyncstate") or die "Cannot create sync state.\n"; print FILE "MasterUidValidity 1\nMaxPulledUid ".shift(@t)."\n". "SlaveUidValidity 1\nMaxExpiredMasterUid ".shift(@t)."\nMaxPushedUid ".shift(@t)."\n\n"; while (@t) { print FILE shift(@t)." ".shift(@t)." ".shift(@t)."\n"; } close FILE; } # $config, $boxname, $maxuid, @msgs sub ckbox($$$@) { my ($bn, $MU, @MS) = @_; my ($mu, %ms) = readbox($bn); if ($mu != $MU) { print STDERR "MAXUID mismatch for '$bn' (got $mu, wanted $MU).\n"; return 1; } while (@MS) { my ($num, $uid, $flg) = (shift @MS, shift @MS, shift @MS); if (!defined $ms{$num}) { print STDERR "No message $bn:$num.\n"; return 1; } if ($ms{$num}[0] ne $uid) { print STDERR "UID mismatch for $bn:$num.\n"; return 1; } if ($ms{$num}[1] ne $flg) { print STDERR "Flag mismatch for $bn:$num.\n"; return 1; } delete $ms{$num}; } if (%ms) { print STDERR "Excess messages in '$bn': ".join(", ", sort({$a <=> $b } keys(%ms))).".\n"; return 1; } return 0; } # $filename, @syncstate sub ckstate($@) { my ($fn, $mmaxuid, $mmaxxuid, $smaxuid, @T) = @_; my %hdr; $hdr{'MasterUidValidity'} = "1"; $hdr{'SlaveUidValidity'} = "1"; $hdr{'MaxPulledUid'} = $mmaxuid; $hdr{'MaxPushedUid'} = $smaxuid; $hdr{'MaxExpiredMasterUid'} = $mmaxxuid if ($mmaxxuid ne 0); open(FILE, "<", $fn) or die "Cannot read sync state $fn.\n"; chomp(my @ls = ); close FILE; OUTER: while (1) { while (@ls) { my $l = shift(@ls); last OUTER if (!length($l)); if ($l !~ /^([^ ]+) (\d+)$/) { print STDERR "Malformed sync state header entry: $l\n"; return 1; } my $want = delete $hdr{$1}; if (!defined($want)) { print STDERR "Unexpected sync state header entry: $1\n"; return 1; } if ($2 != $want) { print STDERR "Sync state header entry $1 mismatch: got $2, wanted $want\n"; return 1; } } print STDERR "Unterminated sync state header.\n"; return 1; } my @ky = keys %hdr; if (@ky) { print STDERR "Keys missing from sync state header: @ky\n"; return 1; } for my $l (@ls) { if (!@T) { print STDERR "Excess sync state entry: '$l'.\n"; return 1; } my $xl = shift(@T)." ".shift(@T)." ".shift(@T); if ($l ne $xl) { print STDERR "Sync state entry mismatch: '$l' instead of '$xl'.\n"; return 1; } } if (@T) { print STDERR "Missing sync state entry: '".shift(@T)." ".shift(@T)." ".shift(@T)."'.\n"; return 1; } return 0; } # $statefile, \@chan_state sub ckchan($$) { my ($F, $cs) = @_; my $rslt = ckstate($F, @{ $$cs[2] }); $rslt |= &ckbox("master", @{ $$cs[0] }); $rslt |= &ckbox("slave", @{ $$cs[1] }); return $rslt; } sub printbox($$@) { my ($bn, $mu, @ms) = @_; print " [ $mu,\n "; my $frst = 1; while (@ms) { if ($frst) { $frst = 0; } else { print ", "; } print shift(@ms).", ".shift(@ms).", \"".shift(@ms)."\""; } print " ],\n"; } # @syncstate sub printstate(@) { my (@t) = @_; print " [ ".shift(@t).", ".shift(@t).", ".shift(@t).",\n "; my $frst = 1; while (@t) { if ($frst) { $frst = 0; } else { print ", "; } print((shift(@t) // "??").", ".(shift(@t) // "??").", \"".(shift(@t) // "??")."\""); } print " ],\n"; } # \@chan_state sub printchan($) { my ($cs) = @_; &printbox("master", @{ $$cs[0] }); &printbox("slave", @{ $$cs[1] }); printstate(@{ $$cs[2] }); } sub readfile($) { my ($file) = @_; open(FILE, $file) or return; my @nj = ; close FILE; return @nj; } # $title, \@source_state, \@target_state, @channel_configs sub test($$$@) { my ($ttl, $sx, $tx, @sfx) = @_; return 0 if (scalar(@ARGV) && !grep { $_ eq $ttl } @ARGV); print "Testing: ".$ttl." ...\n"; &writecfg(@sfx); mkchan($$sx[0], $$sx[1], @{ $$sx[2] }); my ($xc, @ret) = runsync("-J", "1-initial.log"); if ($xc || ckchan("slave/.mbsyncstate.new", $tx)) { print "Input:\n"; printchan($sx); print "Options:\n"; print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ]\n"; if (!$xc) { print "Expected result:\n"; printchan($tx); print "Actual result:\n"; showchan("slave/.mbsyncstate.new"); } print "Debug output:\n"; print @ret; exit 1; } my @nj = readfile("slave/.mbsyncstate.journal"); my ($jxc, @jret) = runsync("-0 --no-expunge", "2-replay.log"); if ($jxc || ckstate("slave/.mbsyncstate", @{ $$tx[2] })) { print "Journal replay failed.\n"; print "Options:\n"; print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ], [ \"-0\", \"--no-expunge\" ]\n"; print "Old State:\n"; printstate(@{ $$sx[2] }); print "Journal:\n".join("", @nj)."\n"; if (!$jxc) { print "Expected New State:\n"; printstate(@{ $$tx[2] }); print "New State:\n"; showstate("slave/.mbsyncstate"); } print "Debug output:\n"; print @jret; exit 1; } my ($ixc, @iret) = runsync("", "3-verify.log"); if ($ixc || ckchan("slave/.mbsyncstate", $tx)) { print "Idempotence verification run failed.\n"; print "Input == Expected result:\n"; printchan($tx); print "Options:\n"; print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ]\n"; if (!$ixc) { print "Actual result:\n"; showchan("slave/.mbsyncstate"); } print "Debug output:\n"; print @iret; exit 1; } rmtree "slave"; rmtree "master"; my $njl = (@nj - 1) * 2; for (my $l = 2; $l < $njl; $l++) { mkchan($$sx[0], $$sx[1], @{ $$sx[2] }); my ($nxc, @nret) = runsync("-J$l", "4-interrupt.log"); if ($nxc != (100 + ($l & 1)) << 8) { print "Interrupting at step $l/$njl failed.\n"; print "Debug output:\n"; print @nret; exit 1; } ($nxc, @nret) = runsync("-J", "5-resume.log"); if ($nxc || ckchan("slave/.mbsyncstate.new", $tx)) { print "Resuming from step $l/$njl failed.\n"; print "Input:\n"; printchan($sx); print "Options:\n"; print " [ ".join(", ", map('"'.qm($_).'"', @sfx))." ]\n"; my @nnj = readfile("slave/.mbsyncstate.journal"); print "Journal:\n".join("", @nnj[0..($l / 2 - 1)])."-------\n".join("", @nnj[($l / 2)..$#nnj])."\n"; print "Full journal:\n".join("", @nj)."\n"; if (!$nxc) { print "Expected result:\n"; printchan($tx); print "Actual result:\n"; showchan("slave/.mbsyncstate"); } print "Debug output:\n"; print @nret; exit 1; } rmtree "slave"; rmtree "master"; } killcfg(); } isync-1.3.0/src/socket.c0000644000175000001440000006200113164125173012002 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2008,2010,2011, 2013 Oswald Buddenhagen * Copyright (C) 2004 Theodore Y. Ts'o * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #include "socket.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_LIBSSL # include # include # include # if OPENSSL_VERSION_NUMBER < 0x10100000L # define X509_OBJECT_get0_X509(o) ((o)->data.x509) # define X509_STORE_get0_objects(o) ((o)->objs) # endif #endif enum { SCK_CONNECTING, #ifdef HAVE_LIBSSL SCK_STARTTLS, #endif SCK_READY, SCK_EOF }; static void socket_fail( conn_t *conn ) { conn->bad_callback( conn->callback_aux ); } #ifdef HAVE_LIBSSL static int ssl_return( const char *func, conn_t *conn, int ret ) { int err; switch ((err = SSL_get_error( conn->ssl, ret ))) { case SSL_ERROR_NONE: return ret; case SSL_ERROR_WANT_WRITE: conf_notifier( &conn->notify, POLLIN, POLLOUT ); FALLTHROUGH case SSL_ERROR_WANT_READ: return 0; case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: if (!(err = ERR_get_error())) { if (ret == 0) { case SSL_ERROR_ZERO_RETURN: /* Callers take the short path out, so signal higher layers from here. */ conn->state = SCK_EOF; conn->read_callback( conn->callback_aux ); return -1; } sys_error( "Socket error: secure %s %s", func, conn->name ); } else { error( "Socket error: secure %s %s: %s\n", func, conn->name, ERR_error_string( err, 0 ) ); } break; default: error( "Socket error: secure %s %s: unhandled SSL error %d\n", func, conn->name, err ); break; } if (conn->state == SCK_STARTTLS) conn->callbacks.starttls( 0, conn->callback_aux ); else socket_fail( conn ); return -1; } /* Some of this code is inspired by / lifted from mutt. */ static int host_matches( const char *host, const char *pattern ) { if (pattern[0] == '*' && pattern[1] == '.') { pattern += 2; if (!(host = strchr( host, '.' ))) return 0; host++; } return *host && *pattern && !strcasecmp( host, pattern ); } static int verify_hostname( X509 *cert, const char *hostname ) { int i, len, found; X509_NAME *subj; STACK_OF(GENERAL_NAME) *subj_alt_names; char cname[1000]; /* try the DNS subjectAltNames */ found = 0; if ((subj_alt_names = X509_get_ext_d2i( cert, NID_subject_alt_name, NULL, NULL ))) { int num_subj_alt_names = sk_GENERAL_NAME_num( subj_alt_names ); for (i = 0; i < num_subj_alt_names; i++) { GENERAL_NAME *subj_alt_name = sk_GENERAL_NAME_value( subj_alt_names, i ); if (subj_alt_name->type == GEN_DNS && strlen( (const char *)subj_alt_name->d.ia5->data ) == (size_t)subj_alt_name->d.ia5->length && host_matches( hostname, (const char *)(subj_alt_name->d.ia5->data) )) { found = 1; break; } } sk_GENERAL_NAME_pop_free( subj_alt_names, GENERAL_NAME_free ); } if (found) return 0; /* try the common name */ if (!(subj = X509_get_subject_name( cert ))) { error( "Error, cannot get certificate subject\n" ); return -1; } if ((len = X509_NAME_get_text_by_NID( subj, NID_commonName, cname, sizeof(cname) )) < 0) { error( "Error, cannot get certificate common name\n" ); return -1; } if (strlen( cname ) == (size_t)len && host_matches( hostname, cname )) return 0; error( "Error, certificate owner does not match hostname %s\n", hostname ); return -1; } static int verify_cert_host( const server_conf_t *conf, conn_t *sock ) { int i; long err; X509 *cert; STACK_OF(X509_OBJECT) *trusted; cert = SSL_get_peer_certificate( sock->ssl ); if (!cert) { error( "Error, no server certificate\n" ); return -1; } trusted = (STACK_OF(X509_OBJECT) *)sock->conf->trusted_certs; for (i = 0; i < sk_X509_OBJECT_num( trusted ); i++) { if (!X509_cmp( cert, X509_OBJECT_get0_X509( sk_X509_OBJECT_value( trusted, i ) ) )) return 0; } err = SSL_get_verify_result( sock->ssl ); if (err != X509_V_OK) { error( "SSL error connecting %s: %s\n", sock->name, X509_verify_cert_error_string( err ) ); return -1; } if (!conf->host) { error( "SSL error connecting %s: Neither host nor matching certificate specified\n", sock->name ); return -1; } return verify_hostname( cert, conf->host ); } static int init_ssl_ctx( const server_conf_t *conf ) { server_conf_t *mconf = (server_conf_t *)conf; int options = 0; if (conf->SSLContext) return conf->ssl_ctx_valid; mconf->SSLContext = SSL_CTX_new( SSLv23_client_method() ); if (!(conf->ssl_versions & SSLv3)) options |= SSL_OP_NO_SSLv3; if (!(conf->ssl_versions & TLSv1)) options |= SSL_OP_NO_TLSv1; #ifdef SSL_OP_NO_TLSv1_1 if (!(conf->ssl_versions & TLSv1_1)) options |= SSL_OP_NO_TLSv1_1; #endif #ifdef SSL_OP_NO_TLSv1_2 if (!(conf->ssl_versions & TLSv1_2)) options |= SSL_OP_NO_TLSv1_2; #endif SSL_CTX_set_options( mconf->SSLContext, options ); if (conf->cert_file && !SSL_CTX_load_verify_locations( mconf->SSLContext, conf->cert_file, 0 )) { error( "Error while loading certificate file '%s': %s\n", conf->cert_file, ERR_error_string( ERR_get_error(), 0 ) ); return 0; } mconf->trusted_certs = (_STACK *)sk_X509_OBJECT_dup( X509_STORE_get0_objects( SSL_CTX_get_cert_store( mconf->SSLContext ) ) ); if (mconf->system_certs && !SSL_CTX_set_default_verify_paths( mconf->SSLContext )) warn( "Warning: Unable to load default certificate files: %s\n", ERR_error_string( ERR_get_error(), 0 ) ); SSL_CTX_set_verify( mconf->SSLContext, SSL_VERIFY_NONE, NULL ); if (conf->client_certfile && !SSL_CTX_use_certificate_chain_file( mconf->SSLContext, conf->client_certfile)) { error( "Error while loading client certificate file '%s': %s\n", conf->client_certfile, ERR_error_string( ERR_get_error(), 0 ) ); return 0; } if (conf->client_keyfile && !SSL_CTX_use_PrivateKey_file( mconf->SSLContext, conf->client_keyfile, SSL_FILETYPE_PEM)) { error( "Error while loading client private key '%s': %s\n", conf->client_keyfile, ERR_error_string( ERR_get_error(), 0 ) ); return 0; } mconf->ssl_ctx_valid = 1; return 1; } static void start_tls_p2( conn_t * ); static void start_tls_p3( conn_t *, int ); static void ssl_fake_cb( void * ); void socket_start_tls( conn_t *conn, void (*cb)( int ok, void *aux ) ) { static int ssl_inited; conn->callbacks.starttls = cb; if (!ssl_inited) { SSL_library_init(); SSL_load_error_strings(); ssl_inited = 1; } if (!init_ssl_ctx( conn->conf )) { start_tls_p3( conn, 0 ); return; } init_wakeup( &conn->ssl_fake, ssl_fake_cb, conn ); conn->ssl = SSL_new( ((server_conf_t *)conn->conf)->SSLContext ); SSL_set_fd( conn->ssl, conn->fd ); SSL_set_mode( conn->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER ); socket_expect_read( conn, 1 ); conn->state = SCK_STARTTLS; start_tls_p2( conn ); } static void start_tls_p2( conn_t *conn ) { if (ssl_return( "connect to", conn, SSL_connect( conn->ssl ) ) > 0) { if (verify_cert_host( conn->conf, conn )) { start_tls_p3( conn, 0 ); } else { info( "Connection is now encrypted\n" ); start_tls_p3( conn, 1 ); } } } static void start_tls_p3( conn_t *conn, int ok ) { socket_expect_read( conn, 0 ); conn->state = SCK_READY; conn->callbacks.starttls( ok, conn->callback_aux ); } #endif /* HAVE_LIBSSL */ #ifdef HAVE_LIBZ static void z_fake_cb( void * ); static const char * z_err_msg( int code, z_streamp strm ) { /* zlib's consistency in populating z_stream->msg is somewhat * less than stellar. zError() is undocumented. */ return strm->msg ? strm->msg : zError( code ); } void socket_start_deflate( conn_t *conn ) { int result; conn->in_z = nfcalloc( sizeof(*conn->in_z) ); result = inflateInit2( conn->in_z, -15 /* Use raw deflate */ ); if (result != Z_OK) { error( "Fatal: Cannot initialize decompression: %s\n", z_err_msg( result, conn->in_z ) ); abort(); } conn->out_z = nfcalloc( sizeof(*conn->out_z) ); result = deflateInit2( conn->out_z, Z_DEFAULT_COMPRESSION, /* Compression level */ Z_DEFLATED, /* Only valid value */ -15, /* Use raw deflate */ 8, /* Default memory usage */ Z_DEFAULT_STRATEGY /* Don't try to do anything fancy */ ); if (result != Z_OK) { error( "Fatal: Cannot initialize compression: %s\n", z_err_msg( result, conn->out_z ) ); abort(); } init_wakeup( &conn->z_fake, z_fake_cb, conn ); } #endif /* HAVE_LIBZ */ static void socket_fd_cb( int, void * ); static void socket_fake_cb( void * ); static void socket_timeout_cb( void * ); static void socket_connect_one( conn_t * ); static void socket_connect_next( conn_t * ); static void socket_connect_failed( conn_t * ); static void socket_connected( conn_t * ); static void socket_connect_bail( conn_t * ); static void socket_open_internal( conn_t *sock, int fd ) { sock->fd = fd; fcntl( fd, F_SETFL, O_NONBLOCK ); init_notifier( &sock->notify, fd, socket_fd_cb, sock ); init_wakeup( &sock->fd_fake, socket_fake_cb, sock ); init_wakeup( &sock->fd_timeout, socket_timeout_cb, sock ); } static void socket_close_internal( conn_t *sock ) { wipe_notifier( &sock->notify ); wipe_wakeup( &sock->fd_fake ); wipe_wakeup( &sock->fd_timeout ); close( sock->fd ); sock->fd = -1; } void socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) ) { const server_conf_t *conf = sock->conf; sock->callbacks.connect = cb; /* open connection to server */ if (conf->tunnel) { int a[2]; nfasprintf( &sock->name, "tunnel '%s'", conf->tunnel ); infon( "Starting %s... ", sock->name ); if (socketpair( PF_UNIX, SOCK_STREAM, 0, a )) { perror( "socketpair" ); exit( 1 ); } if (fork() == 0) { if (dup2( a[0], 0 ) == -1 || dup2( a[0], 1 ) == -1) _exit( 127 ); close( a[0] ); close( a[1] ); execl( "/bin/sh", "sh", "-c", conf->tunnel, (char *)0 ); _exit( 127 ); } close( a[0] ); socket_open_internal( sock, a[1] ); info( "\vok\n" ); socket_connected( sock ); } else { #ifdef HAVE_IPV6 int gaierr; struct addrinfo hints; memset( &hints, 0, sizeof(hints) ); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG; infon( "Resolving %s... ", conf->host ); if ((gaierr = getaddrinfo( conf->host, NULL, &hints, &sock->addrs ))) { error( "Error: Cannot resolve server '%s': %s\n", conf->host, gai_strerror( gaierr ) ); socket_connect_bail( sock ); return; } info( "\vok\n" ); sock->curr_addr = sock->addrs; #else struct hostent *he; infon( "Resolving %s... ", conf->host ); he = gethostbyname( conf->host ); if (!he) { error( "Error: Cannot resolve server '%s': %s\n", conf->host, hstrerror( h_errno ) ); socket_connect_bail( sock ); return; } info( "\vok\n" ); sock->curr_addr = he->h_addr_list; #endif socket_connect_one( sock ); } } static void socket_connect_one( conn_t *sock ) { int s; #ifdef HAVE_IPV6 struct addrinfo *ai; #else struct { struct sockaddr_in ai_addr[1]; } ai[1]; #endif #ifdef HAVE_IPV6 if (!(ai = sock->curr_addr)) { #else if (!*sock->curr_addr) { #endif error( "No working address found for %s\n", sock->conf->host ); socket_connect_bail( sock ); return; } #ifdef HAVE_IPV6 if (ai->ai_family == AF_INET6) { struct sockaddr_in6 *in6 = ((struct sockaddr_in6 *)ai->ai_addr); char sockname[64]; in6->sin6_port = htons( sock->conf->port ); nfasprintf( &sock->name, "%s ([%s]:%hu)", sock->conf->host, inet_ntop( AF_INET6, &in6->sin6_addr, sockname, sizeof(sockname) ), sock->conf->port ); } else #endif { struct sockaddr_in *in = ((struct sockaddr_in *)ai->ai_addr); #ifndef HAVE_IPV6 memset( in, 0, sizeof(*in) ); in->sin_family = AF_INET; in->sin_addr.s_addr = *((int *)*sock->curr_addr); #endif in->sin_port = htons( sock->conf->port ); nfasprintf( &sock->name, "%s (%s:%hu)", sock->conf->host, inet_ntoa( in->sin_addr ), sock->conf->port ); } #ifdef HAVE_IPV6 s = socket( ai->ai_family, SOCK_STREAM, 0 ); #else s = socket( PF_INET, SOCK_STREAM, 0 ); #endif if (s < 0) { socket_connect_next( sock ); return; } socket_open_internal( sock, s ); infon( "Connecting to %s... ", sock->name ); #ifdef HAVE_IPV6 if (connect( s, ai->ai_addr, ai->ai_addrlen )) { #else if (connect( s, ai->ai_addr, sizeof(*ai->ai_addr) )) { #endif if (errno != EINPROGRESS) { socket_connect_failed( sock ); return; } conf_notifier( &sock->notify, 0, POLLOUT ); socket_expect_read( sock, 1 ); sock->state = SCK_CONNECTING; info( "\v\n" ); return; } info( "\vok\n" ); socket_connected( sock ); } static void socket_connect_next( conn_t *conn ) { sys_error( "Cannot connect to %s", conn->name ); free( conn->name ); conn->name = 0; #ifdef HAVE_IPV6 conn->curr_addr = conn->curr_addr->ai_next; #else conn->curr_addr++; #endif socket_connect_one( conn ); } static void socket_connect_failed( conn_t *conn ) { socket_close_internal( conn ); socket_connect_next( conn ); } static void socket_connected( conn_t *conn ) { #ifdef HAVE_IPV6 freeaddrinfo( conn->addrs ); conn->addrs = 0; #endif conf_notifier( &conn->notify, 0, POLLIN ); socket_expect_read( conn, 0 ); conn->state = SCK_READY; conn->callbacks.connect( 1, conn->callback_aux ); } static void socket_cleanup_names( conn_t *conn ) { #ifdef HAVE_IPV6 if (conn->addrs) { freeaddrinfo( conn->addrs ); conn->addrs = 0; } #endif free( conn->name ); conn->name = 0; } static void socket_connect_bail( conn_t *conn ) { socket_cleanup_names( conn ); conn->callbacks.connect( 0, conn->callback_aux ); } static void dispose_chunk( conn_t *conn ); void socket_close( conn_t *sock ) { if (sock->fd >= 0) socket_close_internal( sock ); socket_cleanup_names( sock ); #ifdef HAVE_LIBSSL if (sock->ssl) { SSL_free( sock->ssl ); sock->ssl = 0; wipe_wakeup( &sock->ssl_fake ); } #endif #ifdef HAVE_LIBZ if (sock->in_z) { inflateEnd( sock->in_z ); free( sock->in_z ); sock->in_z = 0; deflateEnd( sock->out_z ); free( sock->out_z ); sock->out_z = 0; wipe_wakeup( &sock->z_fake ); } #endif while (sock->write_buf) dispose_chunk( sock ); free( sock->append_buf ); sock->append_buf = 0; } static int prepare_read( conn_t *sock, char **buf, int *len ) { int n = sock->offset + sock->bytes; if (!(*len = sizeof(sock->buf) - n)) { error( "Socket error: receive buffer full. Probably protocol error.\n" ); socket_fail( sock ); return -1; } *buf = sock->buf + n; return 0; } static int do_read( conn_t *sock, char *buf, int len ) { int n; assert( sock->fd >= 0 ); if (pending_wakeup( &sock->fd_timeout )) conf_wakeup( &sock->fd_timeout, sock->conf->timeout ); #ifdef HAVE_LIBSSL if (sock->ssl) { if ((n = ssl_return( "read from", sock, SSL_read( sock->ssl, buf, len ) )) <= 0) return n; if (n == len && SSL_pending( sock->ssl )) conf_wakeup( &sock->ssl_fake, 0 ); } else #endif { if ((n = read( sock->fd, buf, len )) < 0) { sys_error( "Socket error: read from %s", sock->name ); socket_fail( sock ); } else if (!n) { /* EOF. Callers take the short path out, so signal higher layers from here. */ sock->state = SCK_EOF; sock->read_callback( sock->callback_aux ); } } return n; } #ifdef HAVE_LIBZ static void socket_fill_z( conn_t *sock ) { char *buf; int len, ret; if (prepare_read( sock, &buf, &len ) < 0) return; sock->in_z->avail_out = len; sock->in_z->next_out = (unsigned char *)buf; ret = inflate( sock->in_z, Z_SYNC_FLUSH ); /* Z_BUF_ERROR happens here when the previous call both consumed * all input and exactly filled up the output buffer. */ if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_STREAM_END) { error( "Error decompressing data from %s: %s\n", sock->name, z_err_msg( ret, sock->in_z ) ); socket_fail( sock ); return; } if (!sock->in_z->avail_out) conf_wakeup( &sock->z_fake, 0 ); if ((len = (char *)sock->in_z->next_out - buf)) { sock->bytes += len; sock->read_callback( sock->callback_aux ); } } #endif static void socket_fill( conn_t *sock ) { #ifdef HAVE_LIBZ if (sock->in_z) { int ret; /* The timer will preempt reads until the buffer is empty. */ assert( !sock->in_z->avail_in ); sock->in_z->next_in = (uchar *)sock->z_buf; if ((ret = do_read( sock, sock->z_buf, sizeof(sock->z_buf) )) <= 0) return; sock->in_z->avail_in = ret; socket_fill_z( sock ); } else #endif { char *buf; int len; if (prepare_read( sock, &buf, &len ) < 0) return; if ((len = do_read( sock, buf, len )) <= 0) return; sock->bytes += len; sock->read_callback( sock->callback_aux ); } } void socket_expect_read( conn_t *conn, int expect ) { if (conn->conf->timeout > 0 && expect != pending_wakeup( &conn->fd_timeout )) conf_wakeup( &conn->fd_timeout, expect ? conn->conf->timeout : -1 ); } int socket_read( conn_t *conn, char *buf, int len ) { int n = conn->bytes; if (!n && conn->state == SCK_EOF) return -1; if (n > len) n = len; memcpy( buf, conn->buf + conn->offset, n ); if (!(conn->bytes -= n)) conn->offset = 0; else conn->offset += n; return n; } char * socket_read_line( conn_t *b ) { char *p, *s; int n; s = b->buf + b->offset; p = memchr( s + b->scanoff, '\n', b->bytes - b->scanoff ); if (!p) { b->scanoff = b->bytes; if (b->offset + b->bytes == sizeof(b->buf)) { memmove( b->buf, b->buf + b->offset, b->bytes ); b->offset = 0; } if (b->state == SCK_EOF) return (void *)~0; return 0; } n = p + 1 - s; b->offset += n; b->bytes -= n; b->scanoff = 0; if (p != s && p[-1] == '\r') p--; *p = 0; return s; } static int do_write( conn_t *sock, char *buf, int len ) { int n; assert( sock->fd >= 0 ); #ifdef HAVE_LIBSSL if (sock->ssl) return ssl_return( "write to", sock, SSL_write( sock->ssl, buf, len ) ); #endif n = write( sock->fd, buf, len ); if (n < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK) { sys_error( "Socket error: write to %s", sock->name ); socket_fail( sock ); } else { n = 0; conf_notifier( &sock->notify, POLLIN, POLLOUT ); } } else if (n != len) { conf_notifier( &sock->notify, POLLIN, POLLOUT ); } return n; } static void dispose_chunk( conn_t *conn ) { buff_chunk_t *bc = conn->write_buf; if (!(conn->write_buf = bc->next)) conn->write_buf_append = &conn->write_buf; conn->buffer_mem -= bc->len; free( bc ); } static int do_queued_write( conn_t *conn ) { buff_chunk_t *bc; if (!conn->write_buf) return 0; while ((bc = conn->write_buf)) { int n, len = bc->len - conn->write_offset; if ((n = do_write( conn, bc->data + conn->write_offset, len )) < 0) return -1; if (n != len) { conn->write_offset += n; conn->writing = 1; return 0; } conn->write_offset = 0; dispose_chunk( conn ); } #ifdef HAVE_LIBSSL if (conn->ssl && SSL_pending( conn->ssl )) conf_wakeup( &conn->ssl_fake, 0 ); #endif conn->writing = 0; conn->write_callback( conn->callback_aux ); return -1; } static void do_append( conn_t *conn, buff_chunk_t *bc ) { bc->next = 0; conn->buffer_mem += bc->len; *conn->write_buf_append = bc; conn->write_buf_append = &bc->next; } /* This is big enough to avoid excessive chunking, but is * sufficiently small to keep SSL latency low with a slow uplink. */ #define WRITE_CHUNK_SIZE 1024 static void do_flush( conn_t *conn ) { buff_chunk_t *bc = conn->append_buf; #ifdef HAVE_LIBZ if (conn->out_z) { int buf_avail = conn->append_avail; if (!conn->z_written) return; do { int ret; if (!bc) { buf_avail = WRITE_CHUNK_SIZE; bc = nfmalloc( offsetof(buff_chunk_t, data) + buf_avail ); bc->len = 0; } conn->out_z->next_in = Z_NULL; conn->out_z->avail_in = 0; conn->out_z->next_out = (uchar *)bc->data + bc->len; conn->out_z->avail_out = buf_avail; /* Z_BUF_ERROR cannot happen here, as zlib suppresses the error * both upon increasing the flush level (1st iteration) and upon * a no-op after the output buffer was full (later iterations). */ if ((ret = deflate( conn->out_z, Z_PARTIAL_FLUSH )) != Z_OK) { error( "Fatal: Compression error: %s\n", z_err_msg( ret, conn->out_z ) ); abort(); } bc->len = (char *)conn->out_z->next_out - bc->data; if (bc->len) { do_append( conn, bc ); bc = 0; buf_avail = 0; } else { buf_avail = conn->out_z->avail_out; } } while (!conn->out_z->avail_out); conn->append_buf = bc; conn->append_avail = buf_avail; conn->z_written = 0; } else #endif if (bc) { do_append( conn, bc ); conn->append_buf = 0; #ifdef HAVE_LIBZ conn->append_avail = 0; #endif } } void socket_write( conn_t *conn, conn_iovec_t *iov, int iovcnt ) { int i, buf_avail, len, offset = 0, total = 0; buff_chunk_t *bc; for (i = 0; i < iovcnt; i++) total += iov[i].len; if (total >= WRITE_CHUNK_SIZE) { /* If the new data is too big, queue the pending buffer to avoid latency. */ do_flush( conn ); } bc = conn->append_buf; #ifdef HAVE_LIBZ buf_avail = conn->append_avail; #endif while (total) { if (!bc) { /* We don't do anything special when compressing, as there is no way to * predict a reasonable output buffer size anyway - deflatePending() does * not account for consumed but not yet compressed input, and adding up * the deflateBound()s would be a tad *too* pessimistic. */ buf_avail = total > WRITE_CHUNK_SIZE ? total : WRITE_CHUNK_SIZE; bc = nfmalloc( offsetof(buff_chunk_t, data) + buf_avail ); bc->len = 0; #ifndef HAVE_LIBZ } else { /* A pending buffer will always be of standard size - over-sized * buffers are immediately filled and queued. */ buf_avail = WRITE_CHUNK_SIZE - bc->len; #endif } while (total) { len = iov->len - offset; #ifdef HAVE_LIBZ if (conn->out_z) { int ret; conn->out_z->next_in = (uchar *)iov->buf + offset; conn->out_z->avail_in = len; conn->out_z->next_out = (uchar *)bc->data + bc->len; conn->out_z->avail_out = buf_avail; /* Z_BUF_ERROR is impossible here, as the input buffer always has data, * and the output buffer always has space. */ if ((ret = deflate( conn->out_z, Z_NO_FLUSH )) != Z_OK) { error( "Fatal: Compression error: %s\n", z_err_msg( ret, conn->out_z ) ); abort(); } bc->len = (char *)conn->out_z->next_out - bc->data; buf_avail = conn->out_z->avail_out; len -= conn->out_z->avail_in; conn->z_written = 1; } else #endif { if (len > buf_avail) len = buf_avail; memcpy( bc->data + bc->len, iov->buf + offset, len ); bc->len += len; buf_avail -= len; } offset += len; total -= len; if (offset == iov->len) { if (iov->takeOwn == GiveOwn) free( iov->buf ); iov++; offset = 0; } if (!buf_avail) { do_append( conn, bc ); bc = 0; break; } } } conn->append_buf = bc; #ifdef HAVE_LIBZ conn->append_avail = buf_avail; #endif conf_wakeup( &conn->fd_fake, 0 ); } static void socket_fd_cb( int events, void *aux ) { conn_t *conn = (conn_t *)aux; if ((events & POLLERR) || conn->state == SCK_CONNECTING) { int soerr; socklen_t selen = sizeof(soerr); if (getsockopt( conn->fd, SOL_SOCKET, SO_ERROR, &soerr, &selen )) { perror( "getsockopt" ); exit( 1 ); } errno = soerr; if (conn->state == SCK_CONNECTING) { if (errno) socket_connect_failed( conn ); else socket_connected( conn ); return; } sys_error( "Socket error from %s", conn->name ); socket_fail( conn ); return; } if (events & POLLOUT) conf_notifier( &conn->notify, POLLIN, 0 ); #ifdef HAVE_LIBSSL if (conn->state == SCK_STARTTLS) { start_tls_p2( conn ); return; } if (conn->ssl) { if (do_queued_write( conn ) < 0) return; socket_fill( conn ); return; } #endif if ((events & POLLOUT) && do_queued_write( conn ) < 0) return; if (events & POLLIN) socket_fill( conn ); } static void socket_fake_cb( void *aux ) { conn_t *conn = (conn_t *)aux; /* Ensure that a pending write gets queued. */ do_flush( conn ); /* If no writes are ongoing, start writing now. */ if (!conn->writing) do_queued_write( conn ); } static void socket_timeout_cb( void *aux ) { conn_t *conn = (conn_t *)aux; if (conn->state == SCK_CONNECTING) { errno = ETIMEDOUT; socket_connect_failed( conn ); } else { error( "Socket error on %s: timeout.\n", conn->name ); socket_fail( conn ); } } #ifdef HAVE_LIBZ static void z_fake_cb( void *aux ) { conn_t *conn = (conn_t *)aux; socket_fill_z( conn ); } #endif #ifdef HAVE_LIBSSL static void ssl_fake_cb( void *aux ) { conn_t *conn = (conn_t *)aux; socket_fill( conn ); } #endif isync-1.3.0/src/sync.c0000644000175000001440000020117713164125173011477 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2010-2013 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #include "sync.h" #include #include #include #include #include #include #include #include #include #include #include #include #if !defined(_POSIX_SYNCHRONIZED_IO) || _POSIX_SYNCHRONIZED_IO <= 0 # define fdatasync fsync #endif channel_conf_t global_conf; channel_conf_t *channels; group_conf_t *groups; const char *str_ms[] = { "master", "slave" }, *str_hl[] = { "push", "pull" }; static void ATTR_PRINTFLIKE(1, 2) debug( const char *msg, ... ) { va_list va; va_start( va, msg ); vdebug( DEBUG_SYNC, msg, va ); va_end( va ); } static void ATTR_PRINTFLIKE(1, 2) debugn( const char *msg, ... ) { va_list va; va_start( va, msg ); vdebugn( DEBUG_SYNC, msg, va ); va_end( va ); } void Fclose( FILE *f, int safe ) { if ((safe && (fflush( f ) || (UseFSync && fdatasync( fileno( f ) )))) || fclose( f ) == EOF) { sys_error( "Error: cannot close file" ); exit( 1 ); } } void vFprintf( FILE *f, const char *msg, va_list va ) { int r; r = vfprintf( f, msg, va ); if (r < 0) { sys_error( "Error: cannot write file" ); exit( 1 ); } } void Fprintf( FILE *f, const char *msg, ... ) { va_list va; va_start( va, msg ); vFprintf( f, msg, va ); va_end( va ); } static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' }; static int parse_flags( const char *buf ) { uint flags, i, d; for (flags = i = d = 0; i < as(Flags); i++) if (buf[d] == Flags[i]) { flags |= (1 << i); d++; } return flags; } static int make_flags( int flags, char *buf ) { uint i, d; for (i = d = 0; i < as(Flags); i++) if (flags & (1 << i)) buf[d++] = Flags[i]; buf[d] = 0; return d; } // These is the (mostly) persistent status of the sync record. // Most of these bits are actually mutually exclusive. It is a // bitfield to allow for easy testing for multiple states. #define S_EXPIRE (1<<0) // the entry is being expired (slave message removal scheduled) #define S_EXPIRED (1<<1) // the entry is expired (slave message removal confirmed) #define S_PENDING (1<<2) // the entry is new and awaits propagation (possibly a retry) #define S_SKIPPED (1<<3) // the entry was not propagated (message is too big) #define S_DEAD (1<<7) // ephemeral: the entry was killed and should be ignored // Ephemeral working set. #define W_NEXPIRE (1<<0) // temporary: new expiration state #define W_DELETE (1<<1) // ephemeral: flags propagation is a deletion #define W_DEL(ms) (1<<(2+(ms))) // ephemeral: m/s message would be subject to expunge typedef struct sync_rec { struct sync_rec *next; /* string_list_t *keywords; */ uint uid[2]; message_t *msg[2]; uchar status, wstate, flags, aflags[2], dflags[2]; char tuid[TUIDL]; } sync_rec_t; typedef struct { int t[2]; void (*cb)( int sts, void *aux ), *aux; char *dname, *jname, *nname, *lname, *box_name[2]; FILE *jfp, *nfp; sync_rec_t *srecs, **srecadd; channel_conf_t *chan; store_t *ctx[2]; driver_t *drv[2]; const char *orig_name[2]; message_t *msgs[2], *new_msgs[2]; uint_array_alloc_t trashed_msgs[2]; int state[2], opts[2], ref_count, nsrecs, ret, lfd, existing, replayed; int new_pending[2], flags_pending[2], trash_pending[2]; uint maxuid[2]; // highest UID that was already propagated uint newmaxuid[2]; // highest UID that is currently being propagated uint uidval[2]; // UID validity value uint newuidval[2]; // UID validity obtained from driver uint newuid[2]; // TUID lookup makes sense only for UIDs >= this uint mmaxxuid; // highest expired UID on master } sync_vars_t; static void sync_ref( sync_vars_t *svars ) { ++svars->ref_count; } static void sync_deref( sync_vars_t *svars ); static int check_cancel( sync_vars_t *svars ); #define AUX &svars->t[t] #define INV_AUX &svars->t[1-t] #define DECL_SVARS \ int t; \ sync_vars_t *svars #define INIT_SVARS(aux) \ t = *(int *)aux; \ svars = (sync_vars_t *)(((char *)(&((int *)aux)[-t])) - offsetof(sync_vars_t, t)) #define DECL_INIT_SVARS(aux) \ int t = *(int *)aux; \ sync_vars_t *svars = (sync_vars_t *)(((char *)(&((int *)aux)[-t])) - offsetof(sync_vars_t, t)) /* operation dependencies: select(x): - load(x): select(x) new(M), new(S), flags(M), flags(S): load(M) & load(S) find_new(x): new(x) trash(x): flags(x) close(x): trash(x) & find_new(x) & new(!x) // with expunge cleanup: close(M) & close(S) */ #define ST_LOADED (1<<0) #define ST_FIND_OLD (1<<1) #define ST_SENT_NEW (1<<2) #define ST_FIND_NEW (1<<3) #define ST_FOUND_NEW (1<<4) #define ST_SENT_FLAGS (1<<5) #define ST_SENT_TRASH (1<<6) #define ST_CLOSED (1<<7) #define ST_SENT_CANCEL (1<<8) #define ST_CANCELED (1<<9) #define ST_SELECTED (1<<10) #define ST_DID_EXPUNGE (1<<11) #define ST_CLOSING (1<<12) #define ST_CONFIRMED (1<<13) #define ST_PRESENT (1<<14) #define ST_SENDING_NEW (1<<15) void jFprintf( sync_vars_t *svars, const char *msg, ... ) { va_list va; if (JLimit && !--JLimit) exit( 101 ); va_start( va, msg ); vFprintf( svars->jfp, msg, va ); va_end( va ); if (JLimit && !--JLimit) exit( 100 ); } static void match_tuids( sync_vars_t *svars, int t, message_t *msgs ) { sync_rec_t *srec; message_t *tmsg, *ntmsg = 0; const char *diag; int num_lost = 0; for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; if (!srec->uid[t] && srec->tuid[0]) { debug( " pair(%u,%u): lookup %s, TUID %." stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], str_ms[t], srec->tuid ); for (tmsg = ntmsg; tmsg; tmsg = tmsg->next) { if (tmsg->status & M_DEAD) continue; if (tmsg->tuid[0] && !memcmp( tmsg->tuid, srec->tuid, TUIDL )) { diag = (tmsg == ntmsg) ? "adjacently" : "after gap"; goto mfound; } } for (tmsg = msgs; tmsg != ntmsg; tmsg = tmsg->next) { if (tmsg->status & M_DEAD) continue; if (tmsg->tuid[0] && !memcmp( tmsg->tuid, srec->tuid, TUIDL )) { diag = "after reset"; goto mfound; } } debug( " -> TUID lost\n" ); jFprintf( svars, "& %u %u\n", srec->uid[M], srec->uid[S] ); srec->flags = 0; // Note: status remains S_PENDING. srec->tuid[0] = 0; num_lost++; continue; mfound: debug( " -> new UID %u %s\n", tmsg->uid, diag ); jFprintf( svars, "%c %u %u %u\n", "<>"[t], srec->uid[M], srec->uid[S], tmsg->uid ); tmsg->srec = srec; srec->msg[t] = tmsg; ntmsg = tmsg->next; srec->uid[t] = tmsg->uid; srec->status = 0; srec->tuid[0] = 0; } } if (num_lost) warn( "Warning: lost track of %d %sed message(s)\n", num_lost, str_hl[t] ); } typedef struct copy_vars { void (*cb)( int sts, uint uid, struct copy_vars *vars ); void *aux; sync_rec_t *srec; /* also ->tuid */ message_t *msg; msg_data_t data; } copy_vars_t; static void msg_fetched( int sts, void *aux ); static void copy_msg( copy_vars_t *vars ) { DECL_INIT_SVARS(vars->aux); t ^= 1; vars->data.flags = vars->msg->flags; vars->data.date = svars->chan->use_internal_date ? -1 : 0; svars->drv[t]->fetch_msg( svars->ctx[t], vars->msg, &vars->data, msg_fetched, vars ); } static void msg_stored( int sts, uint uid, void *aux ); static void copy_msg_bytes( char **out_ptr, const char *in_buf, int *in_idx, int in_len, int in_cr, int out_cr ) { char *out = *out_ptr; int idx = *in_idx; if (out_cr != in_cr) { char c; if (out_cr) { for (; idx < in_len; idx++) { if ((c = in_buf[idx]) != '\r') { if (c == '\n') *out++ = '\r'; *out++ = c; } } } else { for (; idx < in_len; idx++) { if ((c = in_buf[idx]) != '\r') *out++ = c; } } } else { memcpy( out, in_buf + idx, in_len - idx ); out += in_len - idx; idx = in_len; } *out_ptr = out; *in_idx = idx; } static int copy_msg_convert( int in_cr, int out_cr, copy_vars_t *vars ) { char *in_buf = vars->data.data; int in_len = vars->data.len; int idx = 0, sbreak = 0, ebreak = 0; int lines = 0, hdr_crs = 0, bdy_crs = 0, app_cr = 0, extra = 0; if (vars->srec) { nloop: ; int start = idx; int line_crs = 0; while (idx < in_len) { char c = in_buf[idx++]; if (c == '\r') { line_crs++; } else if (c == '\n') { if (starts_with_upper( in_buf + start, in_len - start, "X-TUID: ", 8 )) { extra = (sbreak = start) - (ebreak = idx); goto oke; } lines++; hdr_crs += line_crs; if (idx - line_crs - 1 == start) { sbreak = ebreak = start; goto oke; } goto nloop; } } /* invalid message */ free( in_buf ); return 0; oke: app_cr = out_cr && (!in_cr || hdr_crs); extra += 8 + TUIDL + app_cr + 1; } if (out_cr != in_cr) { for (; idx < in_len; idx++) { char c = in_buf[idx]; if (c == '\r') bdy_crs++; else if (c == '\n') lines++; } extra -= hdr_crs + bdy_crs; if (out_cr) extra += lines; } vars->data.len = in_len + extra; char *out_buf = vars->data.data = nfmalloc( vars->data.len ); idx = 0; if (vars->srec) { copy_msg_bytes( &out_buf, in_buf, &idx, sbreak, in_cr, out_cr ); memcpy( out_buf, "X-TUID: ", 8 ); out_buf += 8; memcpy( out_buf, vars->srec->tuid, TUIDL ); out_buf += TUIDL; if (app_cr) *out_buf++ = '\r'; *out_buf++ = '\n'; idx = ebreak; } copy_msg_bytes( &out_buf, in_buf, &idx, in_len, in_cr, out_cr ); free( in_buf ); return 1; } static void msg_fetched( int sts, void *aux ) { copy_vars_t *vars = (copy_vars_t *)aux; DECL_SVARS; int scr, tcr; switch (sts) { case DRV_OK: INIT_SVARS(vars->aux); if (check_cancel( svars )) { free( vars->data.data ); vars->cb( SYNC_CANCELED, 0, vars ); return; } vars->msg->flags = vars->data.flags; scr = (svars->drv[1-t]->get_caps( svars->ctx[1-t] ) / DRV_CRLF) & 1; tcr = (svars->drv[t]->get_caps( svars->ctx[t] ) / DRV_CRLF) & 1; if (vars->srec || scr != tcr) { if (!copy_msg_convert( scr, tcr, vars )) { warn( "Warning: message %u from %s has incomplete header.\n", vars->msg->uid, str_ms[1-t] ); vars->cb( SYNC_NOGOOD, 0, vars ); return; } } svars->drv[t]->store_msg( svars->ctx[t], &vars->data, !vars->srec, msg_stored, vars ); break; case DRV_CANCELED: vars->cb( SYNC_CANCELED, 0, vars ); break; case DRV_MSG_BAD: vars->cb( SYNC_NOGOOD, 0, vars ); break; default: vars->cb( SYNC_FAIL, 0, vars ); break; } } static void msg_stored( int sts, uint uid, void *aux ) { copy_vars_t *vars = (copy_vars_t *)aux; DECL_SVARS; switch (sts) { case DRV_OK: vars->cb( SYNC_OK, uid, vars ); break; case DRV_CANCELED: vars->cb( SYNC_CANCELED, 0, vars ); break; case DRV_MSG_BAD: INIT_SVARS(vars->aux); (void)svars; warn( "Warning: %s refuses to store message %u from %s.\n", str_ms[t], vars->msg->uid, str_ms[1-t] ); vars->cb( SYNC_NOGOOD, 0, vars ); break; default: vars->cb( SYNC_FAIL, 0, vars ); break; } } static void sync_bail( sync_vars_t *svars ); static void sync_bail2( sync_vars_t *svars ); static void sync_bail3( sync_vars_t *svars ); static void cancel_done( void *aux ); static void cancel_sync( sync_vars_t *svars ) { int t; for (t = 0; t < 2; t++) { int other_state = svars->state[1-t]; if (svars->ret & SYNC_BAD(t)) { cancel_done( AUX ); } else if (!(svars->state[t] & ST_SENT_CANCEL)) { /* ignore subsequent failures from in-flight commands */ svars->state[t] |= ST_SENT_CANCEL; svars->drv[t]->cancel_cmds( svars->ctx[t], cancel_done, AUX ); } if (other_state & ST_CANCELED) break; } } static void cancel_done( void *aux ) { DECL_INIT_SVARS(aux); svars->state[t] |= ST_CANCELED; if (svars->state[1-t] & ST_CANCELED) { if (svars->nfp) { Fclose( svars->nfp, 0 ); Fclose( svars->jfp, 0 ); } sync_bail( svars ); } } static void store_bad( void *aux ) { DECL_INIT_SVARS(aux); svars->drv[t]->cancel_store( svars->ctx[t] ); svars->ret |= SYNC_BAD(t); cancel_sync( svars ); } static int check_cancel( sync_vars_t *svars ) { return (svars->state[M] | svars->state[S]) & (ST_SENT_CANCEL | ST_CANCELED); } static int check_ret( int sts, void *aux ) { DECL_SVARS; if (sts == DRV_CANCELED) return 1; INIT_SVARS(aux); if (sts == DRV_BOX_BAD) { svars->ret |= SYNC_FAIL; cancel_sync( svars ); return 1; } return check_cancel( svars ); } #define SVARS_CHECK_RET \ DECL_SVARS; \ if (check_ret( sts, aux )) \ return; \ INIT_SVARS(aux) #define SVARS_CHECK_RET_VARS(type) \ type *vars = (type *)aux; \ DECL_SVARS; \ if (check_ret( sts, vars->aux )) { \ free( vars ); \ return; \ } \ INIT_SVARS(vars->aux) #define SVARS_CHECK_CANCEL_RET \ DECL_SVARS; \ if (sts == SYNC_CANCELED) { \ free( vars ); \ return; \ } \ INIT_SVARS(vars->aux) static char * clean_strdup( const char *s ) { char *cs; int i; cs = nfstrdup( s ); for (i = 0; cs[i]; i++) if (cs[i] == '/') cs[i] = '!'; return cs; } #define JOURNAL_VERSION "3" static int prepare_state( sync_vars_t *svars ) { char *s, *cmname, *csname; channel_conf_t *chan; chan = svars->chan; if (!strcmp( chan->sync_state ? chan->sync_state : global_conf.sync_state, "*" )) { const char *path = svars->drv[S]->get_box_path( svars->ctx[S] ); if (!path) { error( "Error: store '%s' does not support in-box sync state\n", chan->stores[S]->name ); return 0; } nfasprintf( &svars->dname, "%s/." EXE "state", path ); } else { csname = clean_strdup( svars->box_name[S] ); if (chan->sync_state) nfasprintf( &svars->dname, "%s%s", chan->sync_state, csname ); else { char c = FieldDelimiter; cmname = clean_strdup( svars->box_name[M] ); nfasprintf( &svars->dname, "%s%c%s%c%s_%c%s%c%s", global_conf.sync_state, c, chan->stores[M]->name, c, cmname, c, chan->stores[S]->name, c, csname ); free( cmname ); } free( csname ); if (!(s = strrchr( svars->dname, '/' ))) { error( "Error: invalid SyncState location '%s'\n", svars->dname ); return 0; } *s = 0; if (mkdir( svars->dname, 0700 ) && errno != EEXIST) { sys_error( "Error: cannot create SyncState directory '%s'", svars->dname ); return 0; } *s = '/'; } nfasprintf( &svars->jname, "%s.journal", svars->dname ); nfasprintf( &svars->nname, "%s.new", svars->dname ); nfasprintf( &svars->lname, "%s.lock", svars->dname ); return 1; } static int lock_state( sync_vars_t *svars ) { struct flock lck; if (svars->lfd >= 0) return 1; memset( &lck, 0, sizeof(lck) ); #if SEEK_SET != 0 lck.l_whence = SEEK_SET; #endif #if F_WRLCK != 0 lck.l_type = F_WRLCK; #endif if ((svars->lfd = open( svars->lname, O_WRONLY|O_CREAT, 0666 )) < 0) { sys_error( "Error: cannot create lock file %s", svars->lname ); return 0; } if (fcntl( svars->lfd, F_SETLK, &lck )) { error( "Error: channel :%s:%s-:%s:%s is locked\n", svars->chan->stores[M]->name, svars->orig_name[M], svars->chan->stores[S]->name, svars->orig_name[S] ); close( svars->lfd ); svars->lfd = -1; return 0; } return 1; } static void save_state( sync_vars_t *svars ) { sync_rec_t *srec; char fbuf[16]; /* enlarge when support for keywords is added */ Fprintf( svars->nfp, "MasterUidValidity %u\nSlaveUidValidity %u\nMaxPulledUid %u\nMaxPushedUid %u\n", svars->uidval[M], svars->uidval[S], svars->maxuid[M], svars->maxuid[S] ); if (svars->mmaxxuid) Fprintf( svars->nfp, "MaxExpiredMasterUid %u\n", svars->mmaxxuid ); Fprintf( svars->nfp, "\n" ); for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; make_flags( srec->flags, fbuf ); Fprintf( svars->nfp, "%u %u %s%s\n", srec->uid[M], srec->uid[S], (srec->status & S_SKIPPED) ? "^" : (srec->status & S_PENDING) ? "!" : (srec->status & S_EXPIRED) ? "~" : "", fbuf ); } Fclose( svars->nfp, 1 ); Fclose( svars->jfp, 0 ); if (!(DFlags & KEEPJOURNAL)) { /* order is important! */ if (rename( svars->nname, svars->dname )) warn( "Warning: cannot commit sync state %s\n", svars->dname ); else if (unlink( svars->jname )) warn( "Warning: cannot delete journal %s\n", svars->jname ); } } static int load_state( sync_vars_t *svars ) { sync_rec_t *srec, *nsrec; char *s; FILE *jfp; int ll; uint smaxxuid = 0; char c; struct stat st; char fbuf[16]; /* enlarge when support for keywords is added */ char buf[128], buf1[64], buf2[64]; if ((jfp = fopen( svars->dname, "r" ))) { if (!lock_state( svars )) goto jbail; debug( "reading sync state %s ...\n", svars->dname ); int line = 0; while (fgets( buf, sizeof(buf), jfp )) { line++; if (!(ll = strlen( buf )) || buf[ll - 1] != '\n') { error( "Error: incomplete sync state header entry at %s:%d\n", svars->dname, line ); jbail: fclose( jfp ); return 0; } if (ll == 1) goto gothdr; if (line == 1 && isdigit( buf[0] )) { if (sscanf( buf, "%63s %63s", buf1, buf2 ) != 2 || sscanf( buf1, "%u:%u", &svars->uidval[M], &svars->maxuid[M] ) < 2 || sscanf( buf2, "%u:%u:%u", &svars->uidval[S], &smaxxuid, &svars->maxuid[S] ) < 3) { error( "Error: invalid sync state header in %s\n", svars->dname ); goto jbail; } goto gothdr; } uint uid; if (sscanf( buf, "%63s %u", buf1, &uid ) != 2) { error( "Error: malformed sync state header entry at %s:%d\n", svars->dname, line ); goto jbail; } if (!strcmp( buf1, "MasterUidValidity" )) svars->uidval[M] = uid; else if (!strcmp( buf1, "SlaveUidValidity" )) svars->uidval[S] = uid; else if (!strcmp( buf1, "MaxPulledUid" )) svars->maxuid[M] = uid; else if (!strcmp( buf1, "MaxPushedUid" )) svars->maxuid[S] = uid; else if (!strcmp( buf1, "MaxExpiredMasterUid" )) svars->mmaxxuid = uid; else if (!strcmp( buf1, "MaxExpiredSlaveUid" )) // Legacy smaxxuid = uid; else { error( "Error: unrecognized sync state header entry at %s:%d\n", svars->dname, line ); goto jbail; } } error( "Error: unterminated sync state header in %s\n", svars->dname ); goto jbail; gothdr: while (fgets( buf, sizeof(buf), jfp )) { line++; if (!(ll = strlen( buf )) || buf[--ll] != '\n') { error( "Error: incomplete sync state entry at %s:%d\n", svars->dname, line ); goto jbail; } buf[ll] = 0; fbuf[0] = 0; uint t1, t2; if (sscanf( buf, "%u %u %15s", &t1, &t2, fbuf ) < 2) { error( "Error: invalid sync state entry at %s:%d\n", svars->dname, line ); goto jbail; } srec = nfmalloc( sizeof(*srec) ); srec->uid[M] = t1; srec->uid[S] = t2; s = fbuf; if (*s == '^') { s++; srec->status = S_SKIPPED; } else if (*s == '!') { s++; srec->status = S_PENDING; } else if (*s == '~' || *s == 'X' /* Pre-1.3 legacy */) { s++; srec->status = S_EXPIRE | S_EXPIRED; } else if (srec->uid[M] == (uint)-1) { // Pre-1.3 legacy srec->uid[M] = 0; srec->status = S_SKIPPED; } else if (srec->uid[M] == (uint)-2) { srec->uid[M] = 0; srec->status = S_PENDING; } else if (srec->uid[S] == (uint)-1) { srec->uid[S] = 0; srec->status = S_SKIPPED; } else if (srec->uid[S] == (uint)-2) { srec->uid[S] = 0; srec->status = S_PENDING; } else srec->status = 0; srec->wstate = 0; srec->flags = parse_flags( s ); debug( " entry (%u,%u,%u,%s)\n", srec->uid[M], srec->uid[S], srec->flags, (srec->status & S_SKIPPED) ? "SKIP" : (srec->status & S_PENDING) ? "FAIL" : (srec->status & S_EXPIRED) ? "XPIRE" : "" ); srec->msg[M] = srec->msg[S] = 0; srec->tuid[0] = 0; srec->next = 0; *svars->srecadd = srec; svars->srecadd = &srec->next; svars->nsrecs++; } fclose( jfp ); svars->existing = 1; } else { if (errno != ENOENT) { sys_error( "Error: cannot read sync state %s", svars->dname ); return 0; } svars->existing = 0; } // This is legacy support for pre-1.3 sync states. if (smaxxuid) { uint minwuid = UINT_MAX; for (srec = svars->srecs; srec; srec = srec->next) { if ((srec->status & (S_DEAD | S_SKIPPED | S_PENDING)) || !srec->uid[M]) continue; if (srec->status & S_EXPIRED) { if (!srec->uid[S]) { // The expired message was already gone. continue; } // The expired message was not expunged yet, so re-examine it. // This will happen en masse, so just extend the bulk fetch. } else { if (srec->uid[S] && smaxxuid >= srec->uid[S]) { // The non-expired message is in the generally expired range, // so don't make it contribute to the bulk fetch. continue; } // Usual non-expired message. } if (minwuid > srec->uid[M]) minwuid = srec->uid[M]; } svars->mmaxxuid = minwuid - 1; } svars->newmaxuid[M] = svars->maxuid[M]; svars->newmaxuid[S] = svars->maxuid[S]; int line = 0; if ((jfp = fopen( svars->jname, "r" ))) { if (!lock_state( svars )) goto jbail; if (!stat( svars->nname, &st ) && fgets( buf, sizeof(buf), jfp )) { debug( "recovering journal ...\n" ); if (!(ll = strlen( buf )) || buf[--ll] != '\n') { error( "Error: incomplete journal header in %s\n", svars->jname ); goto jbail; } buf[ll] = 0; if (!equals( buf, ll, JOURNAL_VERSION, strlen(JOURNAL_VERSION) )) { error( "Error: incompatible journal version " "(got %s, expected " JOURNAL_VERSION ")\n", buf ); goto jbail; } srec = 0; line = 1; while (fgets( buf, sizeof(buf), jfp )) { line++; if (!(ll = strlen( buf )) || buf[--ll] != '\n') { error( "Error: incomplete journal entry at %s:%d\n", svars->jname, line ); goto jbail; } buf[ll] = 0; int tn; uint t1, t2, t3; if ((c = buf[0]) == '#' ? (tn = 0, (sscanf( buf + 2, "%u %u %n", &t1, &t2, &tn ) < 2) || !tn || (ll - tn != TUIDL + 2)) : c == 'S' || c == '!' ? (sscanf( buf + 2, "%u", &t1 ) != 1) : c == 'F' || c == 'T' || c == '+' || c == '&' || c == '-' || c == '=' || c == '|' ? (sscanf( buf + 2, "%u %u", &t1, &t2 ) != 2) : (sscanf( buf + 2, "%u %u %u", &t1, &t2, &t3 ) != 3)) { error( "Error: malformed journal entry at %s:%d\n", svars->jname, line ); goto jbail; } if (c == 'S') svars->maxuid[t1] = svars->newmaxuid[t1]; else if (c == 'F') svars->newuid[t1] = t2; else if (c == 'T') *uint_array_append( &svars->trashed_msgs[t1] ) = t2; else if (c == '!') svars->mmaxxuid = t1; else if (c == '|') { svars->uidval[M] = t1; svars->uidval[S] = t2; } else if (c == '+') { srec = nfmalloc( sizeof(*srec) ); srec->uid[M] = t1; srec->uid[S] = t2; if (svars->newmaxuid[M] < t1) svars->newmaxuid[M] = t1; if (svars->newmaxuid[S] < t2) svars->newmaxuid[S] = t2; debug( " new entry(%u,%u)\n", t1, t2 ); srec->msg[M] = srec->msg[S] = 0; srec->status = S_PENDING; srec->wstate = 0; srec->flags = 0; srec->tuid[0] = 0; srec->next = 0; *svars->srecadd = srec; svars->srecadd = &srec->next; svars->nsrecs++; } else { for (nsrec = srec; srec; srec = srec->next) if (srec->uid[M] == t1 && srec->uid[S] == t2) goto syncfnd; for (srec = svars->srecs; srec != nsrec; srec = srec->next) if (srec->uid[M] == t1 && srec->uid[S] == t2) goto syncfnd; error( "Error: journal entry at %s:%d refers to non-existing sync state entry\n", svars->jname, line ); goto jbail; syncfnd: debugn( " entry(%u,%u,%u) ", srec->uid[M], srec->uid[S], srec->flags ); switch (c) { case '-': debug( "killed\n" ); srec->status = S_DEAD; break; case '=': debug( "aborted\n" ); svars->mmaxxuid = srec->uid[M]; srec->status = S_DEAD; break; case '#': memcpy( srec->tuid, buf + tn + 2, TUIDL ); debug( "TUID now %." stringify(TUIDL) "s\n", srec->tuid ); break; case '&': debug( "TUID %." stringify(TUIDL) "s lost\n", srec->tuid ); srec->flags = 0; srec->tuid[0] = 0; break; case '<': debug( "master now %u\n", t3 ); srec->uid[M] = t3; srec->status &= ~S_PENDING; srec->tuid[0] = 0; break; case '>': debug( "slave now %u\n", t3 ); srec->uid[S] = t3; srec->status &= ~S_PENDING; srec->tuid[0] = 0; break; case '*': debug( "flags now %u\n", t3 ); srec->flags = t3; break; case '~': debug( "status now %#x\n", t3 ); srec->status = t3; break; default: error( "Error: unrecognized journal entry at %s:%d\n", svars->jname, line ); goto jbail; } } } } fclose( jfp ); } else { if (errno != ENOENT) { sys_error( "Error: cannot read journal %s", svars->jname ); return 0; } } svars->replayed = line; return 1; } static void delete_state( sync_vars_t *svars ) { unlink( svars->nname ); unlink( svars->jname ); if (unlink( svars->dname ) || unlink( svars->lname )) { sys_error( "Error: channel %s: sync state cannot be deleted", svars->chan->name ); svars->ret = SYNC_FAIL; } } static void box_confirmed( int sts, int uidvalidity, void *aux ); static void box_confirmed2( sync_vars_t *svars, int t ); static void box_deleted( int sts, void *aux ); static void box_created( int sts, void *aux ); static void box_opened( int sts, int uidvalidity, void *aux ); static void box_opened2( sync_vars_t *svars, int t ); static void load_box( sync_vars_t *svars, int t, uint minwuid, uint_array_t mexcs ); void sync_boxes( store_t *ctx[], const char *names[], int present[], channel_conf_t *chan, void (*cb)( int sts, void *aux ), void *aux ) { sync_vars_t *svars; int t; svars = nfcalloc( sizeof(*svars) ); svars->t[1] = 1; svars->ref_count = 1; svars->cb = cb; svars->aux = aux; svars->ctx[0] = ctx[0]; svars->ctx[1] = ctx[1]; svars->chan = chan; svars->lfd = -1; svars->uidval[0] = svars->uidval[1] = UIDVAL_BAD; svars->srecadd = &svars->srecs; for (t = 0; t < 2; t++) { svars->orig_name[t] = (!names[t] || (ctx[t]->conf->map_inbox && !strcmp( ctx[t]->conf->map_inbox, names[t] ))) ? "INBOX" : names[t]; if (!ctx[t]->conf->flat_delim) { svars->box_name[t] = nfstrdup( svars->orig_name[t] ); } else if (map_name( svars->orig_name[t], &svars->box_name[t], 0, "/", ctx[t]->conf->flat_delim ) < 0) { error( "Error: canonical mailbox name '%s' contains flattened hierarchy delimiter\n", svars->orig_name[t] ); bail3: svars->ret = SYNC_FAIL; sync_bail3( svars ); return; } svars->drv[t] = ctx[t]->driver; svars->drv[t]->set_bad_callback( ctx[t], store_bad, AUX ); } /* Both boxes must be fully set up at this point, so that error exit paths * don't run into uninitialized variables. */ for (t = 0; t < 2; t++) { switch (svars->drv[t]->select_box( ctx[t], svars->box_name[t] )) { case DRV_CANCELED: store_bad( AUX ); return; case DRV_BOX_BAD: goto bail3; } } if (!prepare_state( svars )) { svars->ret = SYNC_FAIL; sync_bail2( svars ); return; } if (!load_state( svars )) { svars->ret = SYNC_FAIL; sync_bail( svars ); return; } sync_ref( svars ); for (t = 0; ; t++) { info( "Opening %s box %s...\n", str_ms[t], svars->orig_name[t] ); if (present[t] == BOX_ABSENT) box_confirmed2( svars, t ); else svars->drv[t]->open_box( ctx[t], box_confirmed, AUX ); if (t || check_cancel( svars )) break; } sync_deref( svars ); } static void box_confirmed( int sts, int uidvalidity, void *aux ) { DECL_SVARS; if (sts == DRV_CANCELED) return; INIT_SVARS(aux); if (check_cancel( svars )) return; if (sts == DRV_OK) { svars->state[t] |= ST_PRESENT; svars->newuidval[t] = uidvalidity; } box_confirmed2( svars, t ); } static void box_confirmed2( sync_vars_t *svars, int t ) { svars->state[t] |= ST_CONFIRMED; if (!(svars->state[1-t] & ST_CONFIRMED)) return; sync_ref( svars ); for (t = 0; ; t++) { if (!(svars->state[t] & ST_PRESENT)) { if (!(svars->state[1-t] & ST_PRESENT)) { if (!svars->existing) { error( "Error: channel %s: both master %s and slave %s cannot be opened.\n", svars->chan->name, svars->orig_name[M], svars->orig_name[S] ); bail: svars->ret = SYNC_FAIL; } else { /* This can legitimately happen if a deletion propagation was interrupted. * We have no place to record this transaction, so we just assume it. * Of course this bears the danger of clearing the state if both mailboxes * temorarily cannot be opened for some weird reason (while the stores can). */ delete_state( svars ); } done: sync_bail( svars ); break; } if (svars->existing) { if (!(svars->chan->ops[1-t] & OP_REMOVE)) { error( "Error: channel %s: %s %s cannot be opened.\n", svars->chan->name, str_ms[t], svars->orig_name[t] ); goto bail; } if (svars->drv[1-t]->confirm_box_empty( svars->ctx[1-t] ) != DRV_OK) { warn( "Warning: channel %s: %s %s cannot be opened and %s %s not empty.\n", svars->chan->name, str_ms[t], svars->orig_name[t], str_ms[1-t], svars->orig_name[1-t] ); goto done; } info( "Deleting %s %s...\n", str_ms[1-t], svars->orig_name[1-t] ); svars->drv[1-t]->delete_box( svars->ctx[1-t], box_deleted, INV_AUX ); } else { if (!(svars->chan->ops[t] & OP_CREATE)) { box_opened( DRV_BOX_BAD, UIDVAL_BAD, AUX ); } else { info( "Creating %s %s...\n", str_ms[t], svars->orig_name[t] ); svars->drv[t]->create_box( svars->ctx[t], box_created, AUX ); } } } else { box_opened2( svars, t ); } if (t || check_cancel( svars )) break; } sync_deref( svars ); } static void box_deleted( int sts, void *aux ) { DECL_SVARS; if (check_ret( sts, aux )) return; INIT_SVARS(aux); delete_state( svars ); svars->drv[t]->finish_delete_box( svars->ctx[t] ); sync_bail( svars ); } static void box_created( int sts, void *aux ) { DECL_SVARS; if (check_ret( sts, aux )) return; INIT_SVARS(aux); svars->drv[t]->open_box( svars->ctx[t], box_opened, AUX ); } static void box_opened( int sts, int uidvalidity, void *aux ) { DECL_SVARS; if (sts == DRV_CANCELED) return; INIT_SVARS(aux); if (check_cancel( svars )) return; if (sts == DRV_BOX_BAD) { error( "Error: channel %s: %s %s cannot be opened.\n", svars->chan->name, str_ms[t], svars->orig_name[t] ); svars->ret = SYNC_FAIL; sync_bail( svars ); } else { svars->newuidval[t] = uidvalidity; box_opened2( svars, t ); } } static void box_opened2( sync_vars_t *svars, int t ) { store_t *ctx[2]; channel_conf_t *chan; sync_rec_t *srec; uint_array_alloc_t mexcs; uint minwuid; int opts[2], fails; svars->state[t] |= ST_SELECTED; if (!(svars->state[1-t] & ST_SELECTED)) return; ctx[0] = svars->ctx[0]; ctx[1] = svars->ctx[1]; chan = svars->chan; fails = 0; for (t = 0; t < 2; t++) if (svars->uidval[t] != UIDVAL_BAD && svars->uidval[t] != svars->newuidval[t]) fails++; if (fails == 2) { error( "Error: channel %s: UIDVALIDITY of both master and slave changed\n" "(master got %u, expected %u; slave got %u, expected %u).\n", svars->chan->name, svars->newuidval[M], svars->uidval[M], svars->newuidval[S], svars->uidval[S] ); bail: svars->ret = SYNC_FAIL; sync_bail( svars ); return; } if (!lock_state( svars )) goto bail; if (!(svars->nfp = fopen( svars->nname, "w" ))) { sys_error( "Error: cannot create new sync state %s", svars->nname ); goto bail; } if (!(svars->jfp = fopen( svars->jname, "a" ))) { sys_error( "Error: cannot create journal %s", svars->jname ); fclose( svars->nfp ); goto bail; } setlinebuf( svars->jfp ); if (!svars->replayed) jFprintf( svars, JOURNAL_VERSION "\n" ); opts[M] = opts[S] = 0; if (fails) opts[M] = opts[S] = OPEN_OLD|OPEN_OLD_IDS; for (t = 0; t < 2; t++) { if (chan->ops[t] & (OP_DELETE|OP_FLAGS)) { opts[t] |= OPEN_SETFLAGS; opts[1-t] |= OPEN_OLD; if (chan->ops[t] & OP_FLAGS) opts[1-t] |= OPEN_FLAGS; } if (chan->ops[t] & (OP_NEW|OP_RENEW)) { opts[t] |= OPEN_APPEND; if (chan->ops[t] & OP_RENEW) opts[1-t] |= OPEN_OLD; if (chan->ops[t] & OP_NEW) opts[1-t] |= OPEN_NEW; if (chan->ops[t] & OP_EXPUNGE) opts[1-t] |= OPEN_FLAGS; if (chan->stores[t]->max_size != INT_MAX) { if (chan->ops[t] & OP_RENEW) opts[1-t] |= OPEN_OLD_SIZE; if (chan->ops[t] & OP_NEW) opts[1-t] |= OPEN_NEW_SIZE; } } if (chan->ops[t] & OP_EXPUNGE) { opts[t] |= OPEN_EXPUNGE; if (chan->stores[t]->trash) { if (!chan->stores[t]->trash_only_new) opts[t] |= OPEN_OLD; opts[t] |= OPEN_NEW|OPEN_FLAGS; } else if (chan->stores[1-t]->trash && chan->stores[1-t]->trash_remote_new) opts[t] |= OPEN_NEW|OPEN_FLAGS; } } if ((chan->ops[S] & (OP_NEW|OP_RENEW|OP_FLAGS)) && chan->max_messages) opts[S] |= OPEN_OLD|OPEN_NEW|OPEN_FLAGS; if (svars->replayed) for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; if (srec->tuid[0]) { if (!srec->uid[M]) opts[M] |= OPEN_NEW|OPEN_FIND, svars->state[M] |= ST_FIND_OLD; else if (!srec->uid[S]) opts[S] |= OPEN_NEW|OPEN_FIND, svars->state[S] |= ST_FIND_OLD; else warn( "Warning: sync record (%d,%d) has stray TUID. Ignoring.\n", srec->uid[M], srec->uid[S] ); } } svars->opts[M] = svars->drv[M]->prepare_load_box( ctx[M], opts[M] ); svars->opts[S] = svars->drv[S]->prepare_load_box( ctx[S], opts[S] ); ARRAY_INIT( &mexcs ); if (svars->opts[M] & OPEN_OLD) { if (chan->max_messages) { /* When messages have been expired on the slave, the master fetch is split into * two ranges: The bulk fetch which corresponds with the most recent messages, and an * exception list of messages which would have been expired if they weren't important. */ debug( "preparing master selection - max expired master uid is %u\n", svars->mmaxxuid ); /* First, find out the lower bound for the bulk fetch. */ minwuid = svars->mmaxxuid + 1; /* Next, calculate the exception fetch. */ for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; if (!srec->uid[M]) // No message; other state is irrelevant continue; if (minwuid > srec->uid[M] && (!(svars->opts[M] & OPEN_NEW) || svars->maxuid[M] >= srec->uid[M])) { if (!srec->uid[S] && !(srec->status & S_PENDING)) // Only actually paired up messages matter continue; /* The pair is alive, but outside the bulk range. */ *uint_array_append( &mexcs ) = srec->uid[M]; } } sort_uint_array( mexcs.array ); } else { minwuid = 1; } } else { minwuid = UINT_MAX; } sync_ref( svars ); load_box( svars, M, minwuid, mexcs.array ); if (!check_cancel( svars )) load_box( svars, S, (svars->opts[S] & OPEN_OLD) ? 1 : UINT_MAX, (uint_array_t){ 0, 0 } ); sync_deref( svars ); } static int get_seenuid( sync_vars_t *svars, int t ) { uint seenuid = 0; for (sync_rec_t *srec = svars->srecs; srec; srec = srec->next) if (!(srec->status & S_DEAD) && seenuid < srec->uid[t]) seenuid = srec->uid[t]; return seenuid; } static void box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ); static void load_box( sync_vars_t *svars, int t, uint minwuid, uint_array_t mexcs ) { uint maxwuid, seenuid; if (svars->opts[t] & OPEN_NEW) { if (minwuid > svars->maxuid[t] + 1) minwuid = svars->maxuid[t] + 1; maxwuid = UINT_MAX; if (svars->opts[t] & (OPEN_OLD_IDS|OPEN_OLD_SIZE)) seenuid = get_seenuid( svars, t ); else seenuid = 0; } else if (svars->opts[t] & OPEN_OLD) { maxwuid = seenuid = get_seenuid( svars, t ); } else maxwuid = seenuid = 0; if (seenuid < svars->maxuid[t]) { /* We cannot rely on the maxuid, as uni-directional syncing does not update it. * But if it is there, use it to avoid a possible gap in the fetched range. */ seenuid = svars->maxuid[t]; } info( "Loading %s...\n", str_ms[t] ); svars->drv[t]->load_box( svars->ctx[t], minwuid, maxwuid, svars->newuid[t], seenuid, mexcs, box_loaded, AUX ); } typedef struct { void *aux; sync_rec_t *srec; int aflags, dflags; } flag_vars_t; typedef struct { uint uid; sync_rec_t *srec; } sync_rec_map_t; static void flags_set( int sts, void *aux ); static void flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t ); static void msgs_flags_set( sync_vars_t *svars, int t ); static void msg_copied( int sts, uint uid, copy_vars_t *vars ); static void msgs_copied( sync_vars_t *svars, int t ); static void box_loaded( int sts, message_t *msgs, int total_msgs, int recent_msgs, void *aux ) { DECL_SVARS; sync_rec_t *srec; sync_rec_map_t *srecmap; message_t *tmsg; flag_vars_t *fv; int no[2], del[2], alive, todel; int sflags, nflags, aflags, dflags; uint hashsz, idx; if (check_ret( sts, aux )) return; INIT_SVARS(aux); svars->state[t] |= ST_LOADED; svars->msgs[t] = msgs; info( "%s: %d messages, %d recent\n", str_ms[t], total_msgs, recent_msgs ); if (svars->state[t] & ST_FIND_OLD) { debug( "matching previously copied messages on %s\n", str_ms[t] ); match_tuids( svars, t, msgs ); } debug( "matching messages on %s against sync records\n", str_ms[t] ); hashsz = bucketsForSize( svars->nsrecs * 3 ); srecmap = nfcalloc( hashsz * sizeof(*srecmap) ); for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; uint uid = srec->uid[t]; if (!uid) continue; idx = (uint)(uid * 1103515245U) % hashsz; while (srecmap[idx].uid) if (++idx == hashsz) idx = 0; srecmap[idx].uid = uid; srecmap[idx].srec = srec; } for (tmsg = svars->msgs[t]; tmsg; tmsg = tmsg->next) { if (tmsg->srec) /* found by TUID */ continue; uint uid = tmsg->uid; idx = (uint)(uid * 1103515245U) % hashsz; while (srecmap[idx].uid) { if (srecmap[idx].uid == uid) { srec = srecmap[idx].srec; goto found; } if (++idx == hashsz) idx = 0; } continue; found: tmsg->srec = srec; srec->msg[t] = tmsg; } free( srecmap ); if (!(svars->state[1-t] & ST_LOADED)) return; for (t = 0; t < 2; t++) { if (svars->uidval[t] != UIDVAL_BAD && svars->uidval[t] != svars->newuidval[t]) { unsigned need = 0, got = 0; debug( "trying to re-approve uid validity of %s\n", str_ms[t] ); for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; if (!srec->msg[t]) continue; // Message disappeared. need++; // Present paired messages require re-validation. if (!srec->msg[t]->msgid) continue; // Messages without ID are useless for re-validation. if (!srec->msg[1-t]) continue; // Partner disappeared. if (!srec->msg[1-t]->msgid || strcmp( srec->msg[M]->msgid, srec->msg[S]->msgid )) { error( "Error: channel %s, %s %s: UIDVALIDITY genuinely changed (at UID %u).\n", svars->chan->name, str_ms[t], svars->orig_name[t], srec->uid[t] ); uvchg: svars->ret |= SYNC_FAIL; cancel_sync( svars ); return; } got++; } if (got < 20 && got * 5 < need * 4) { // Too few confirmed messages. This is very likely in the drafts folder. // A proper fallback would be fetching more headers (which potentially need // normalization) or the message body (which should be truncated for sanity) // and comparing. error( "Error: channel %s, %s %s: Unable to recover from UIDVALIDITY change\n" "(got %u, expected %u).\n", svars->chan->name, str_ms[t], svars->orig_name[t], svars->newuidval[t], svars->uidval[t] ); goto uvchg; } notice( "Notice: channel %s, %s %s: Recovered from change of UIDVALIDITY.\n", svars->chan->name, str_ms[t], svars->orig_name[t] ); svars->uidval[t] = UIDVAL_BAD; } } if (svars->uidval[M] == UIDVAL_BAD || svars->uidval[S] == UIDVAL_BAD) { svars->uidval[M] = svars->newuidval[M]; svars->uidval[S] = svars->newuidval[S]; jFprintf( svars, "| %u %u\n", svars->uidval[M], svars->uidval[S] ); } info( "Synchronizing...\n" ); debug( "synchronizing old entries\n" ); for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; debug( "pair (%u,%u)\n", srec->uid[M], srec->uid[S] ); assert( !srec->tuid[0] ); // no[] means that a message is known to be not there. no[M] = !srec->msg[M] && (svars->opts[M] & OPEN_OLD); no[S] = !srec->msg[S] && (svars->opts[S] & OPEN_OLD); if (no[M] && no[S]) { // It does not matter whether one side was already known to be missing // (never stored [skipped or failed] or expunged [possibly expired]) - // now both are missing, so the entry is superfluous. debug( " vanished\n" ); srec->status = S_DEAD; jFprintf( svars, "- %u %u\n", srec->uid[M], srec->uid[S] ); } else { // del[] means that a message becomes known to have been expunged. del[M] = no[M] && srec->uid[M]; del[S] = no[S] && srec->uid[S]; for (t = 0; t < 2; t++) { srec->aflags[t] = srec->dflags[t] = 0; if (srec->msg[t] && (srec->msg[t]->flags & F_DELETED)) srec->wstate |= W_DEL(t); if (del[t]) { // The target was newly expunged, so there is nothing to update. // The deletion is propagated in the opposite iteration. } else if (!srec->uid[t]) { // The target was never stored, or was previously expunged, so there // is nothing to update. // Note: the opposite UID must be valid, as otherwise the entry would // have been pruned already. } else if (del[1-t]) { // The source was newly expunged, so possibly propagate the deletion. // The target may be in an unknown state (not fetched). if ((t == M) && (srec->status & (S_EXPIRE|S_EXPIRED))) { /* Don't propagate deletion resulting from expiration. */ debug( " slave expired, orphaning master\n" ); jFprintf( svars, "> %u %u 0\n", srec->uid[M], srec->uid[S] ); srec->uid[S] = 0; } else { if (srec->msg[t] && (srec->msg[t]->status & M_FLAGS) && srec->msg[t]->flags != srec->flags) notice( "Notice: conflicting changes in (%u,%u)\n", srec->uid[M], srec->uid[S] ); if (svars->chan->ops[t] & OP_DELETE) { debug( " %sing delete\n", str_hl[t] ); srec->aflags[t] = F_DELETED; srec->wstate |= W_DELETE; } else { debug( " not %sing delete\n", str_hl[t] ); } } } else if (!srec->msg[1-t]) { // We have no source to work with, because it was never stored, // it was previously expunged, or we did not fetch it. debug( " no %s\n", str_ms[1-t] ); } else { // We have a source. The target may be in an unknown state. if (svars->chan->ops[t] & OP_FLAGS) { sflags = srec->msg[1-t]->flags; if ((t == M) && (srec->status & (S_EXPIRE|S_EXPIRED))) { /* Don't propagate deletion resulting from expiration. */ debug( " slave expiring\n" ); sflags &= ~F_DELETED; } srec->aflags[t] = sflags & ~srec->flags; srec->dflags[t] = ~sflags & srec->flags; if ((DFlags & DEBUG_SYNC) && (srec->aflags[t] || srec->dflags[t])) { char afbuf[16], dfbuf[16]; /* enlarge when support for keywords is added */ make_flags( srec->aflags[t], afbuf ); make_flags( srec->dflags[t], dfbuf ); debug( " %sing flags: +%s -%s\n", str_hl[t], afbuf, dfbuf ); } } } } } } debug( "synchronizing new entries\n" ); for (t = 0; t < 2; t++) { for (tmsg = svars->msgs[1-t]; tmsg; tmsg = tmsg->next) { // If new have no srec, the message is always New. If we have a srec: // - message is paired or expired => ignore // - message was skipped => ReNew // - message was attempted, but is still pending or failed => New // // If messages were previously ignored due to being excessive, they would now // appear to be newer than the messages that got actually synced, so increment // newmaxuid immediately to make sure we always look only at the newest ones. // However, committing it to maxuid must be delayed until all messages were // propagated, to ensure that all pending messages are still loaded next time // in case of interruption - in particular skipping big messages would otherwise // up the limit too early. srec = tmsg->srec; if (srec ? !srec->uid[t] && (((srec->status & S_PENDING) && (svars->chan->ops[t] & OP_NEW)) || ((srec->status & S_SKIPPED) && (svars->chan->ops[t] & OP_RENEW))) : svars->newmaxuid[1-t] < tmsg->uid && (svars->chan->ops[t] & OP_NEW)) { debug( "new message %u on %s\n", tmsg->uid, str_ms[1-t] ); if ((svars->chan->ops[t] & OP_EXPUNGE) && (tmsg->flags & F_DELETED)) { debug( " -> not %sing - would be expunged anyway\n", str_hl[t] ); } else { if (srec) { debug( " -> pair(%u,%u) exists\n", srec->uid[M], srec->uid[S] ); } else { srec = nfmalloc( sizeof(*srec) ); srec->next = 0; *svars->srecadd = srec; svars->srecadd = &srec->next; svars->nsrecs++; srec->status = S_PENDING; srec->wstate = 0; srec->flags = 0; srec->tuid[0] = 0; srec->uid[1-t] = tmsg->uid; srec->uid[t] = 0; srec->msg[1-t] = tmsg; srec->msg[t] = 0; tmsg->srec = srec; if (svars->newmaxuid[1-t] < tmsg->uid) svars->newmaxuid[1-t] = tmsg->uid; jFprintf( svars, "+ %u %u\n", srec->uid[M], srec->uid[S] ); debug( " -> pair(%u,%u) created\n", srec->uid[M], srec->uid[S] ); } if ((tmsg->flags & F_FLAGGED) || tmsg->size <= svars->chan->stores[t]->max_size) { if (tmsg->flags != srec->flags) { srec->flags = tmsg->flags; jFprintf( svars, "* %u %u %u\n", srec->uid[M], srec->uid[S], srec->flags ); debug( " -> updated flags to %u\n", tmsg->flags ); } if (srec->status != S_PENDING) { debug( " -> not too big any more\n" ); srec->status = S_PENDING; jFprintf( svars, "~ %d %d %u\n", srec->uid[M], srec->uid[S], srec->status ); } } else { if (srec->status == S_SKIPPED) { debug( " -> not %sing - still too big\n", str_hl[t] ); } else { debug( " -> not %sing - too big\n", str_hl[t] ); srec->status = S_SKIPPED; jFprintf( svars, "~ %d %d %u\n", srec->uid[M], srec->uid[S], srec->status ); } } } } } } if ((svars->chan->ops[S] & (OP_NEW|OP_RENEW|OP_FLAGS)) && svars->chan->max_messages) { /* Note: When this branch is entered, we have loaded all slave messages. */ /* Expire excess messages. Important (flagged, unread, or unpropagated) messages * older than the first not expired message are not counted towards the total. */ debug( "preparing message expiration\n" ); alive = 0; for (tmsg = svars->msgs[S]; tmsg; tmsg = tmsg->next) { if (tmsg->status & M_DEAD) continue; if ((srec = tmsg->srec) && srec->uid[M] && ((tmsg->flags | srec->aflags[S]) & ~srec->dflags[S] & F_DELETED) && !(srec->status & (S_EXPIRE|S_EXPIRED))) { /* Message was not propagated yet, or is deleted. */ } else { alive++; } } for (tmsg = svars->msgs[M]; tmsg; tmsg = tmsg->next) { if ((srec = tmsg->srec) && (srec->status & S_PENDING) && !(tmsg->flags & F_DELETED)) alive++; } todel = alive - svars->chan->max_messages; debug( "%d alive messages, %d excess - expiring\n", alive, todel ); alive = 0; for (tmsg = svars->msgs[S]; tmsg; tmsg = tmsg->next) { if (tmsg->status & M_DEAD) continue; if (!(srec = tmsg->srec) || !srec->uid[M]) { /* We did not push the message, so it must be kept. */ debug( " message %u unpropagated\n", tmsg->uid ); todel--; } else { nflags = (tmsg->flags | srec->aflags[S]) & ~srec->dflags[S]; if (!(nflags & F_DELETED) || (srec->status & (S_EXPIRE|S_EXPIRED))) { /* The message is not deleted, or is already (being) expired. */ if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) { /* Important messages are always kept. */ debug( " old pair(%u,%u) important\n", srec->uid[M], srec->uid[S] ); todel--; } else if (todel > 0 || ((srec->status & (S_EXPIRE|S_EXPIRED)) == (S_EXPIRE|S_EXPIRED)) || ((srec->status & (S_EXPIRE|S_EXPIRED)) && (tmsg->flags & F_DELETED))) { /* The message is excess or was already (being) expired. */ srec->wstate |= W_NEXPIRE; debug( " old pair(%u,%u) expired\n", srec->uid[M], srec->uid[S] ); if (svars->mmaxxuid < srec->uid[M]) svars->mmaxxuid = srec->uid[M]; todel--; } } } } for (tmsg = svars->msgs[M]; tmsg; tmsg = tmsg->next) { if ((srec = tmsg->srec) && (srec->status & S_PENDING)) { nflags = tmsg->flags; if (!(nflags & F_DELETED)) { if ((nflags & F_FLAGGED) || !((nflags & F_SEEN) || ((void)(todel > 0 && alive++), svars->chan->expire_unread > 0))) { /* Important messages are always fetched. */ debug( " new pair(%u,%u) important\n", srec->uid[M], srec->uid[S] ); todel--; } else if (todel > 0) { /* The message is excess. */ srec->wstate |= W_NEXPIRE; todel--; } } } } debug( "%d excess messages remain\n", todel ); if (svars->chan->expire_unread < 0 && (uint)alive * 2 > svars->chan->max_messages) { error( "%s: %d unread messages in excess of MaxMessages (%d).\n" "Please set ExpireUnread to decide outcome. Skipping mailbox.\n", svars->orig_name[S], alive, svars->chan->max_messages ); svars->ret |= SYNC_FAIL; cancel_sync( svars ); return; } for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; if (!(srec->status & S_PENDING)) { if (!srec->msg[S]) continue; uint nex = (srec->wstate / W_NEXPIRE) & 1; if (nex != ((srec->status / S_EXPIRED) & 1)) { /* The record needs a state change ... */ if (nex != ((srec->status / S_EXPIRE) & 1)) { /* ... and we need to start a transaction. */ debug( " pair(%u,%u): %u (pre)\n", srec->uid[M], srec->uid[S], nex ); srec->status = (srec->status & ~S_EXPIRE) | (nex * S_EXPIRE); jFprintf( svars, "~ %u %u %u\n", srec->uid[M], srec->uid[S], srec->status ); } else { /* ... but the "right" transaction is already pending. */ debug( " pair(%u,%u): %d (pending)\n", srec->uid[M], srec->uid[S], nex ); } } else { /* Note: the "wrong" transaction may be pending here, * e.g.: W_NEXPIRE = 0, S_EXPIRE = 1, S_EXPIRED = 0. */ } } else { if (srec->wstate & W_NEXPIRE) { jFprintf( svars, "= %u %u\n", srec->uid[M], srec->uid[S] ); debug( " pair(%u,%u): 1 (abort)\n", srec->uid[M], srec->uid[S] ); // If we have so many new messages that some of them are instantly expired, // but some are still propagated because they are important, we need to // ensure explicitly that the bulk fetch limit is upped. svars->mmaxxuid = srec->uid[M]; srec->msg[M]->srec = 0; srec->status = S_DEAD; } } } } sync_ref( svars ); debug( "synchronizing flags\n" ); for (srec = svars->srecs; srec; srec = srec->next) { if ((srec->status & S_DEAD) || !srec->uid[M] || !srec->uid[S]) continue; for (t = 0; t < 2; t++) { aflags = srec->aflags[t]; dflags = srec->dflags[t]; if (srec->wstate & W_DELETE) { if (!aflags) { /* This deletion propagation goes the other way round. */ continue; } } else { /* The trigger is an expiration transaction being ongoing ... */ if ((t == S) && ((shifted_bit(srec->status, S_EXPIRE, S_EXPIRED) ^ srec->status) & S_EXPIRED)) { /* ... but the actual action derives from the wanted state. */ if (srec->wstate & W_NEXPIRE) aflags |= F_DELETED; else dflags |= F_DELETED; } } if ((svars->chan->ops[t] & OP_EXPUNGE) && (((srec->msg[t] ? srec->msg[t]->flags : 0) | aflags) & ~dflags & F_DELETED) && (!svars->ctx[t]->conf->trash || svars->ctx[t]->conf->trash_only_new)) { /* If the message is going to be expunged, don't propagate anything but the deletion. */ srec->aflags[t] &= F_DELETED; aflags &= F_DELETED; srec->dflags[t] = dflags = 0; } if (srec->msg[t] && (srec->msg[t]->status & M_FLAGS)) { /* If we know the target message's state, optimize away non-changes. */ aflags &= ~srec->msg[t]->flags; dflags &= srec->msg[t]->flags; } if (aflags | dflags) { flags_total[t]++; stats(); svars->flags_pending[t]++; fv = nfmalloc( sizeof(*fv) ); fv->aux = AUX; fv->srec = srec; fv->aflags = aflags; fv->dflags = dflags; svars->drv[t]->set_msg_flags( svars->ctx[t], srec->msg[t], srec->uid[t], aflags, dflags, flags_set, fv ); if (check_cancel( svars )) goto out; } else flags_set_p2( svars, srec, t ); } } for (t = 0; t < 2; t++) { svars->drv[t]->commit_cmds( svars->ctx[t] ); svars->state[t] |= ST_SENT_FLAGS; msgs_flags_set( svars, t ); if (check_cancel( svars )) goto out; } debug( "propagating new messages\n" ); if (UseFSync) fdatasync( fileno( svars->jfp ) ); for (t = 0; t < 2; t++) { svars->newuid[t] = svars->drv[t]->get_uidnext( svars->ctx[t] ); jFprintf( svars, "F %d %u\n", t, svars->newuid[t] ); svars->new_msgs[t] = svars->msgs[1-t]; msgs_copied( svars, t ); if (check_cancel( svars )) goto out; } out: sync_deref( svars ); } static void msg_copied( int sts, uint uid, copy_vars_t *vars ) { SVARS_CHECK_CANCEL_RET; switch (sts) { case SYNC_OK: if (!uid) { // Stored to a non-UIDPLUS mailbox svars->state[t] |= ST_FIND_NEW; } else { debug( " -> new UID %u on %s\n", uid, str_ms[t] ); jFprintf( svars, "%c %u %u %u\n", "<>"[t], vars->srec->uid[M], vars->srec->uid[S], uid ); vars->srec->uid[t] = uid; vars->srec->status &= ~S_PENDING; vars->srec->tuid[0] = 0; } break; case SYNC_NOGOOD: debug( " -> killing (%u,%u)\n", vars->srec->uid[M], vars->srec->uid[S] ); vars->srec->status = S_DEAD; jFprintf( svars, "- %u %u\n", vars->srec->uid[M], vars->srec->uid[S] ); break; default: cancel_sync( svars ); free( vars ); return; } free( vars ); new_done[t]++; stats(); svars->new_pending[t]--; msgs_copied( svars, t ); } static void msgs_found_new( int sts, message_t *msgs, void *aux ); static void msgs_new_done( sync_vars_t *svars, int t ); static void sync_close( sync_vars_t *svars, int t ); static void msgs_copied( sync_vars_t *svars, int t ) { message_t *tmsg; sync_rec_t *srec; copy_vars_t *cv; if (svars->state[t] & ST_SENDING_NEW) return; sync_ref( svars ); if (!(svars->state[t] & ST_SENT_NEW)) { for (tmsg = svars->new_msgs[t]; tmsg; tmsg = tmsg->next) { if ((srec = tmsg->srec) && (srec->status & S_PENDING)) { if (svars->drv[t]->get_memory_usage( svars->ctx[t] ) >= BufferLimit) { svars->new_msgs[t] = tmsg; goto out; } for (uint i = 0; i < TUIDL; i++) { uchar c = arc4_getbyte() & 0x3f; srec->tuid[i] = c < 26 ? c + 'A' : c < 52 ? c + 'a' - 26 : c < 62 ? c + '0' - 52 : c == 62 ? '+' : '/'; } jFprintf( svars, "# %u %u %." stringify(TUIDL) "s\n", srec->uid[M], srec->uid[S], srec->tuid ); debug( "%sing message %u, TUID %." stringify(TUIDL) "s\n", str_hl[t], tmsg->uid, srec->tuid ); new_total[t]++; stats(); svars->new_pending[t]++; svars->state[t] |= ST_SENDING_NEW; cv = nfmalloc( sizeof(*cv) ); cv->cb = msg_copied; cv->aux = AUX; cv->srec = srec; cv->msg = tmsg; copy_msg( cv ); svars->state[t] &= ~ST_SENDING_NEW; if (check_cancel( svars )) goto out; } } svars->state[t] |= ST_SENT_NEW; } if (svars->new_pending[t]) goto out; if (svars->maxuid[1-t] != svars->newmaxuid[1-t]) { svars->maxuid[1-t] = svars->newmaxuid[1-t]; jFprintf( svars, "S %d\n", 1-t ); } sync_close( svars, 1-t ); if (check_cancel( svars )) goto out; if (svars->state[t] & ST_FIND_NEW) { debug( "finding just copied messages on %s\n", str_ms[t] ); svars->drv[t]->find_new_msgs( svars->ctx[t], svars->newuid[t], msgs_found_new, AUX ); } else { msgs_new_done( svars, t ); } out: sync_deref( svars ); } static void msgs_found_new( int sts, message_t *msgs, void *aux ) { SVARS_CHECK_RET; switch (sts) { case DRV_OK: debug( "matching just copied messages on %s\n", str_ms[t] ); break; default: warn( "Warning: cannot find newly stored messages on %s.\n", str_ms[t] ); break; } match_tuids( svars, t, msgs ); msgs_new_done( svars, t ); } static void msgs_new_done( sync_vars_t *svars, int t ) { svars->state[t] |= ST_FOUND_NEW; sync_close( svars, t ); } static void flags_set( int sts, void *aux ) { SVARS_CHECK_RET_VARS(flag_vars_t); switch (sts) { case DRV_OK: if (vars->aflags & F_DELETED) vars->srec->wstate |= W_DEL(t); else if (vars->dflags & F_DELETED) vars->srec->wstate &= ~W_DEL(t); flags_set_p2( svars, vars->srec, t ); break; } free( vars ); flags_done[t]++; stats(); svars->flags_pending[t]--; msgs_flags_set( svars, t ); } static void flags_set_p2( sync_vars_t *svars, sync_rec_t *srec, int t ) { if (srec->wstate & W_DELETE) { debug( " pair(%u,%u): resetting %s UID\n", srec->uid[M], srec->uid[S], str_ms[1-t] ); jFprintf( svars, "%c %u %u 0\n", "><"[t], srec->uid[M], srec->uid[S] ); srec->uid[1-t] = 0; } else { uint nflags = (srec->flags | srec->aflags[t]) & ~srec->dflags[t]; if (srec->flags != nflags) { debug( " pair(%u,%u): updating flags (%u -> %u; %sed)\n", srec->uid[M], srec->uid[S], srec->flags, nflags, str_hl[t] ); srec->flags = nflags; jFprintf( svars, "* %u %u %u\n", srec->uid[M], srec->uid[S], nflags ); } if (t == S) { uint nex = (srec->wstate / W_NEXPIRE) & 1; if (nex != ((srec->status / S_EXPIRED) & 1)) { debug( " pair(%u,%u): expired %d (commit)\n", srec->uid[M], srec->uid[S], nex ); srec->status = (srec->status & ~S_EXPIRED) | (nex * S_EXPIRED); jFprintf( svars, "~ %u %u %u\n", srec->uid[M], srec->uid[S], srec->status ); } else if (nex != ((srec->status / S_EXPIRE) & 1)) { debug( " pair(%u,%u): expire %d (cancel)\n", srec->uid[M], srec->uid[S], nex ); srec->status = (srec->status & ~S_EXPIRE) | (nex * S_EXPIRE); jFprintf( svars, "~ %u %u %u\n", srec->uid[M], srec->uid[S], srec->status ); } } } } typedef struct { void *aux; message_t *msg; } trash_vars_t; static void msg_trashed( int sts, void *aux ); static void msg_rtrashed( int sts, uint uid, copy_vars_t *vars ); static void msgs_flags_set( sync_vars_t *svars, int t ) { message_t *tmsg; trash_vars_t *tv; copy_vars_t *cv; if (!(svars->state[t] & ST_SENT_FLAGS) || svars->flags_pending[t]) return; sync_ref( svars ); if ((svars->chan->ops[t] & OP_EXPUNGE) && (svars->ctx[t]->conf->trash || (svars->ctx[1-t]->conf->trash && svars->ctx[1-t]->conf->trash_remote_new))) { debug( "trashing in %s\n", str_ms[t] ); for (tmsg = svars->msgs[t]; tmsg; tmsg = tmsg->next) if ((tmsg->flags & F_DELETED) && !find_uint_array( svars->trashed_msgs[t].array, tmsg->uid ) && (t == M || !tmsg->srec || !(tmsg->srec->status & (S_EXPIRE|S_EXPIRED)))) { if (svars->ctx[t]->conf->trash) { if (!svars->ctx[t]->conf->trash_only_new || !tmsg->srec || (tmsg->srec->status & (S_PENDING | S_SKIPPED))) { debug( "%s: trashing message %u\n", str_ms[t], tmsg->uid ); trash_total[t]++; stats(); svars->trash_pending[t]++; tv = nfmalloc( sizeof(*tv) ); tv->aux = AUX; tv->msg = tmsg; svars->drv[t]->trash_msg( svars->ctx[t], tmsg, msg_trashed, tv ); if (check_cancel( svars )) goto out; } else debug( "%s: not trashing message %u - not new\n", str_ms[t], tmsg->uid ); } else { if (!tmsg->srec || (tmsg->srec->status & (S_PENDING | S_SKIPPED))) { if (tmsg->size <= svars->ctx[1-t]->conf->max_size) { debug( "%s: remote trashing message %u\n", str_ms[t], tmsg->uid ); trash_total[t]++; stats(); svars->trash_pending[t]++; cv = nfmalloc( sizeof(*cv) ); cv->cb = msg_rtrashed; cv->aux = INV_AUX; cv->srec = 0; cv->msg = tmsg; copy_msg( cv ); if (check_cancel( svars )) goto out; } else debug( "%s: not remote trashing message %u - too big\n", str_ms[t], tmsg->uid ); } else debug( "%s: not remote trashing message %u - not new\n", str_ms[t], tmsg->uid ); } } } svars->state[t] |= ST_SENT_TRASH; sync_close( svars, t ); out: sync_deref( svars ); } static void msg_trashed( int sts, void *aux ) { trash_vars_t *vars = (trash_vars_t *)aux; DECL_SVARS; if (sts == DRV_MSG_BAD) sts = DRV_BOX_BAD; if (check_ret( sts, vars->aux )) return; INIT_SVARS(vars->aux); debug( " -> trashed %s %u\n", str_ms[t], vars->msg->uid ); jFprintf( svars, "T %d %u\n", t, vars->msg->uid ); free( vars ); trash_done[t]++; stats(); svars->trash_pending[t]--; sync_close( svars, t ); } static void msg_rtrashed( int sts, uint uid ATTR_UNUSED, copy_vars_t *vars ) { SVARS_CHECK_CANCEL_RET; switch (sts) { case SYNC_OK: case SYNC_NOGOOD: /* the message is gone or heavily busted */ break; default: cancel_sync( svars ); free( vars ); return; } t ^= 1; debug( " -> remote trashed %s %u\n", str_ms[t], vars->msg->uid ); jFprintf( svars, "T %d %u\n", t, vars->msg->uid ); free( vars ); trash_done[t]++; stats(); svars->trash_pending[t]--; sync_close( svars, t ); } static void box_closed( int sts, void *aux ); static void box_closed_p2( sync_vars_t *svars, int t ); static void sync_close( sync_vars_t *svars, int t ) { if ((~svars->state[t] & (ST_FOUND_NEW|ST_SENT_TRASH)) || svars->trash_pending[t] || !(svars->state[1-t] & ST_SENT_NEW) || svars->new_pending[1-t]) return; if (svars->state[t] & ST_CLOSING) return; svars->state[t] |= ST_CLOSING; if ((svars->chan->ops[t] & OP_EXPUNGE) /*&& !(svars->state[t] & ST_TRASH_BAD)*/) { debug( "expunging %s\n", str_ms[t] ); svars->drv[t]->close_box( svars->ctx[t], box_closed, AUX ); } else { box_closed_p2( svars, t ); } } static void box_closed( int sts, void *aux ) { SVARS_CHECK_RET; svars->state[t] |= ST_DID_EXPUNGE; box_closed_p2( svars, t ); } static void box_closed_p2( sync_vars_t *svars, int t ) { sync_rec_t *srec; svars->state[t] |= ST_CLOSED; if (!(svars->state[1-t] & ST_CLOSED)) return; // All the journalling done in this function is merely for the autotest - // the operations are idempotent, and we're about to commit the new state // right afterwards anyway. if (((svars->state[M] | svars->state[S]) & ST_DID_EXPUNGE) || svars->chan->max_messages) { debug( "purging obsolete entries\n" ); for (srec = svars->srecs; srec; srec = srec->next) { if (srec->status & S_DEAD) continue; if (!srec->uid[S] || ((srec->wstate & W_DEL(S)) && (svars->state[S] & ST_DID_EXPUNGE))) { if (!srec->uid[M] || ((srec->wstate & W_DEL(M)) && (svars->state[M] & ST_DID_EXPUNGE)) || ((srec->status & S_EXPIRED) && svars->maxuid[M] >= srec->uid[M] && svars->mmaxxuid >= srec->uid[M])) { debug( " -> killing (%u,%u)\n", srec->uid[M], srec->uid[S] ); jFprintf( svars, "- %u %u\n", srec->uid[M], srec->uid[S] ); srec->status = S_DEAD; } else if (srec->uid[S]) { debug( " -> orphaning (%u,[%u])\n", srec->uid[M], srec->uid[S] ); jFprintf( svars, "> %u %u 0\n", srec->uid[M], srec->uid[S] ); srec->uid[S] = 0; } } else if (srec->uid[M] && ((srec->wstate & W_DEL(M)) && (svars->state[M] & ST_DID_EXPUNGE))) { debug( " -> orphaning ([%u],%u)\n", srec->uid[M], srec->uid[S] ); jFprintf( svars, "< %u %u 0\n", srec->uid[M], srec->uid[S] ); srec->uid[M] = 0; } } } // This is just an optimization, so it needs no journaling of intermediate states. // However, doing it before the entry purge would require ensuring that the // exception list includes all relevant messages. debug( "max expired uid on master is now %d\n", svars->mmaxxuid ); jFprintf( svars, "! %d\n", svars->mmaxxuid ); save_state( svars ); sync_bail( svars ); } static void sync_bail( sync_vars_t *svars ) { sync_rec_t *srec, *nsrec; free( svars->trashed_msgs[M].array.data ); free( svars->trashed_msgs[S].array.data ); for (srec = svars->srecs; srec; srec = nsrec) { nsrec = srec->next; free( srec ); } if (svars->lfd >= 0) { unlink( svars->lname ); close( svars->lfd ); } sync_bail2( svars ); } static void sync_bail2( sync_vars_t *svars ) { free( svars->lname ); free( svars->nname ); free( svars->jname ); free( svars->dname ); sync_bail3( svars ); } static void sync_bail3( sync_vars_t *svars ) { free( svars->box_name[M] ); free( svars->box_name[S] ); sync_deref( svars ); } static void sync_deref( sync_vars_t *svars ) { if (!--svars->ref_count) { void (*cb)( int sts, void *aux ) = svars->cb; void *aux = svars->aux; int ret = svars->ret; free( svars ); cb( ret, aux ); } } isync-1.3.0/src/util.c0000644000175000001440000004036113141421437011471 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2011,2012 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #include "common.h" #include #include #include #include #include #include #include static int need_nl; void flushn( void ) { if (need_nl) { putchar( '\n' ); fflush( stdout ); need_nl = 0; } } static void printn( const char *msg, va_list va ) { if (*msg == '\v') msg++; else flushn(); vprintf( msg, va ); fflush( stdout ); } void vdebug( int cat, const char *msg, va_list va ) { if (DFlags & cat) { vprintf( msg, va ); fflush( stdout ); need_nl = 0; } } void vdebugn( int cat, const char *msg, va_list va ) { if (DFlags & cat) { vprintf( msg, va ); fflush( stdout ); need_nl = 1; } } void progress( const char *msg, ... ) { va_list va; va_start( va, msg ); vprintf( msg, va ); va_end( va ); fflush( stdout ); need_nl = 1; } void info( const char *msg, ... ) { va_list va; if (DFlags & VERBOSE) { va_start( va, msg ); printn( msg, va ); va_end( va ); need_nl = 0; } } void infon( const char *msg, ... ) { va_list va; if (DFlags & VERBOSE) { va_start( va, msg ); printn( msg, va ); va_end( va ); need_nl = 1; } } void notice( const char *msg, ... ) { va_list va; if (!(DFlags & QUIET)) { va_start( va, msg ); printn( msg, va ); va_end( va ); need_nl = 0; } } void warn( const char *msg, ... ) { va_list va; if (!(DFlags & VERYQUIET)) { flushn(); va_start( va, msg ); vfprintf( stderr, msg, va ); va_end( va ); } } void error( const char *msg, ... ) { va_list va; flushn(); va_start( va, msg ); vfprintf( stderr, msg, va ); va_end( va ); } void sys_error( const char *msg, ... ) { va_list va; char buf[1024]; flushn(); va_start( va, msg ); if ((uint)vsnprintf( buf, sizeof(buf), msg, va ) >= sizeof(buf)) oob(); va_end( va ); perror( buf ); } void add_string_list_n( string_list_t **list, const char *str, int len ) { string_list_t *elem; elem = nfmalloc( sizeof(*elem) + len ); elem->next = *list; *list = elem; memcpy( elem->string, str, len ); elem->string[len] = 0; } void add_string_list( string_list_t **list, const char *str ) { add_string_list_n( list, str, strlen( str ) ); } void free_string_list( string_list_t *list ) { string_list_t *tlist; for (; list; list = tlist) { tlist = list->next; free( list ); } } #ifndef HAVE_VASPRINTF static int vasprintf( char **strp, const char *fmt, va_list ap ) { int len; char tmp[1024]; if ((len = vsnprintf( tmp, sizeof(tmp), fmt, ap )) < 0 || !(*strp = malloc( len + 1 ))) return -1; if (len >= (int)sizeof(tmp)) vsprintf( *strp, fmt, ap ); else memcpy( *strp, tmp, len + 1 ); return len; } #endif #ifndef HAVE_MEMRCHR void * memrchr( const void *s, int c, size_t n ) { u_char *b = (u_char *)s, *e = b + n; while (--e >= b) if (*e == c) return (void *)e; return 0; } #endif #ifndef HAVE_STRNLEN size_t strnlen( const char *str, size_t maxlen ) { const char *estr = memchr( str, 0, maxlen ); return estr ? (size_t)(estr - str) : maxlen; } #endif int starts_with( const char *str, int strl, const char *cmp, int cmpl ) { if (strl < 0) strl = strnlen( str, cmpl + 1 ); return (strl >= cmpl) && !memcmp( str, cmp, cmpl ); } int starts_with_upper( const char *str, int strl, const char *cmp, int cmpl ) { int i; if (strl < 0) strl = strnlen( str, cmpl + 1 ); if (strl < cmpl) return 0; for (i = 0; i < cmpl; i++) if (str[i] != cmp[i] && toupper( str[i] ) != cmp[i]) return 0; return 1; } int equals( const char *str, int strl, const char *cmp, int cmpl ) { if (strl < 0) strl = strnlen( str, cmpl + 1 ); return (strl == cmpl) && !memcmp( str, cmp, cmpl ); } #ifndef HAVE_TIMEGM /* Converts struct tm to time_t, assuming the data in tm is UTC rather than local timezone. mktime is similar but assumes struct tm, also known as the "broken-down" form of time, is in local time zone. timegm uses mktime to make the conversion understanding that an offset will be introduced by the local time assumption. mktime_from_utc then measures the introduced offset by applying gmtime to the initial result and applying mktime to the resulting "broken-down" form. The difference between the two mktime results is the measured offset which is then subtracted from the initial mktime result to yield a calendar time which is the value returned. tm_isdst in struct tm is set to 0 to force mktime to introduce a consistent offset (the non DST offset) since tm and tm+o might be on opposite sides of a DST change. Some implementations of mktime return -1 for the nonexistent localtime hour at the beginning of DST. In this event, use mktime(tm - 1hr) + 3600. Schematically mktime(tm) --> t+o gmtime(t+o) --> tm+o mktime(tm+o) --> t+2o t+o - (t+2o - t+o) = t Contributed by Roger Beeman , with the help of Mark Baushke and the rest of the Gurus at CISCO. Further improved by Roger with assistance from Edward J. Sabol based on input by Jamie Zawinski. */ static time_t my_mktime( struct tm *t ) { time_t tl = mktime( t ); if (tl == -1) { t->tm_hour--; tl = mktime( t ); if (tl != -1) tl += 3600; } return tl; } time_t timegm( struct tm *t ) { time_t tl, tb; struct tm *tg; if ((tl = my_mktime( t )) == -1) return tl; tg = gmtime( &tl ); tg->tm_isdst = 0; if ((tb = my_mktime( tg )) == -1) return tb; return tl - (tb - tl); } #endif void oob( void ) { fputs( "Fatal: buffer too small. Please report a bug.\n", stderr ); abort(); } int nfsnprintf( char *buf, int blen, const char *fmt, ... ) { int ret; va_list va; va_start( va, fmt ); if (blen <= 0 || (uint)(ret = vsnprintf( buf, blen, fmt, va )) >= (uint)blen) oob(); va_end( va ); return ret; } static void ATTR_NORETURN oom( void ) { fputs( "Fatal: Out of memory\n", stderr ); abort(); } void * nfmalloc( size_t sz ) { void *ret; if (!(ret = malloc( sz ))) oom(); return ret; } void * nfcalloc( size_t sz ) { void *ret; if (!(ret = calloc( sz, 1 ))) oom(); return ret; } void * nfrealloc( void *mem, size_t sz ) { char *ret; if (!(ret = realloc( mem, sz )) && sz) oom(); return ret; } char * nfstrndup( const char *str, size_t nchars ) { char *ret = nfmalloc( nchars + 1 ); memcpy( ret, str, nchars ); ret[nchars] = 0; return ret; } char * nfstrdup( const char *str ) { return nfstrndup( str, strlen( str ) ); } int nfvasprintf( char **str, const char *fmt, va_list va ) { int ret = vasprintf( str, fmt, va ); if (ret < 0) oom(); return ret; } int nfasprintf( char **str, const char *fmt, ... ) { int ret; va_list va; va_start( va, fmt ); ret = nfvasprintf( str, fmt, va ); va_end( va ); return ret; } /* static struct passwd * cur_user( void ) { char *p; struct passwd *pw; uid_t uid; uid = getuid(); if ((!(p = getenv("LOGNAME")) || !(pw = getpwnam( p )) || pw->pw_uid != uid) && (!(p = getenv("USER")) || !(pw = getpwnam( p )) || pw->pw_uid != uid) && !(pw = getpwuid( uid ))) { fputs ("Cannot determinate current user\n", stderr); return 0; } return pw; } */ char * expand_strdup( const char *s ) { struct passwd *pw; const char *p, *q; char *r; if (*s == '~') { s++; if (!*s) { p = 0; q = Home; } else if (*s == '/') { p = s; q = Home; } else { if ((p = strchr( s, '/' ))) { r = nfstrndup( s, (int)(p - s) ); pw = getpwnam( r ); free( r ); } else pw = getpwnam( s ); if (!pw) return 0; q = pw->pw_dir; } nfasprintf( &r, "%s%s", q, p ? p : "" ); return r; } else return nfstrdup( s ); } /* Return value: 0 = ok, -1 = out found in arg, -2 = in found in arg but no out specified */ int map_name( const char *arg, char **result, int reserve, const char *in, const char *out ) { char *p; int i, l, ll, num, inl, outl; l = strlen( arg ); if (!in) { copy: *result = nfmalloc( reserve + l + 1 ); memcpy( *result + reserve, arg, l + 1 ); return 0; } inl = strlen( in ); if (out) { outl = strlen( out ); if (inl == outl && !memcmp( in, out, inl )) goto copy; } for (num = 0, i = 0; i < l; ) { for (ll = 0; ll < inl; ll++) if (arg[i + ll] != in[ll]) goto fout; num++; i += inl; continue; fout: if (out) { for (ll = 0; ll < outl; ll++) if (arg[i + ll] != out[ll]) goto fnexti; return -1; } fnexti: i++; } if (!num) goto copy; if (!out) return -2; *result = nfmalloc( reserve + l + num * (outl - inl) + 1 ); p = *result + reserve; for (i = 0; i < l; ) { for (ll = 0; ll < inl; ll++) if (arg[i + ll] != in[ll]) goto rnexti; #ifdef __GNUC__ # pragma GCC diagnostic push /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42145 */ # pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif memcpy( p, out, outl ); #ifdef __GNUC__ # pragma GCC diagnostic pop #endif p += outl; i += inl; continue; rnexti: *p++ = arg[i++]; } *p = 0; return 0; } static int compare_uints( const void *l, const void *r ) { return *(uint *)l - *(uint *)r; } void sort_uint_array( uint_array_t array ) { qsort( array.data, array.size, sizeof(uint), compare_uints ); } int find_uint_array( uint_array_t array, uint value ) { int bot = 0, top = array.size - 1; while (bot <= top) { int i = (bot + top) / 2; uint elt = array.data[i]; if (elt == value) return 1; if (elt < value) bot = i + 1; else top = i - 1; } return 0; } static struct { uchar i, j, s[256]; } rs; void arc4_init( void ) { int i, fd; uchar j, si, dat[128]; if ((fd = open( "/dev/urandom", O_RDONLY )) < 0 && (fd = open( "/dev/random", O_RDONLY )) < 0) { error( "Fatal: no random number source available.\n" ); exit( 3 ); } if (read( fd, dat, 128 ) != 128) { error( "Fatal: cannot read random number source.\n" ); exit( 3 ); } close( fd ); for (i = 0; i < 256; i++) rs.s[i] = i; for (i = j = 0; i < 256; i++) { si = rs.s[i]; j += si + dat[i & 127]; rs.s[i] = rs.s[j]; rs.s[j] = si; } rs.i = rs.j = 0; for (i = 0; i < 256; i++) arc4_getbyte(); } uchar arc4_getbyte( void ) { uchar si, sj; rs.i++; si = rs.s[rs.i]; rs.j += si; sj = rs.s[rs.j]; rs.s[rs.i] = sj; rs.s[rs.j] = si; return rs.s[(si + sj) & 0xff]; } static const uchar prime_deltas[] = { 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 17, 27, 3, 1, 29, 3, 21, 7, 17, 15, 9, 43, 35, 15, 0, 0, 0, 0, 0 }; int bucketsForSize( int size ) { int base = 4, bits = 2; for (;;) { int prime = base + prime_deltas[bits]; if (prime >= size) return prime; base <<= 1; bits++; } } static void list_prepend( list_head_t *head, list_head_t *to ) { assert( !head->next ); assert( to->next ); assert( to->prev->next == to ); head->next = to; head->prev = to->prev; head->prev->next = head; to->prev = head; } static void list_unlink( list_head_t *head ) { assert( head->next ); assert( head->next->prev == head); assert( head->prev->next == head); head->next->prev = head->prev; head->prev->next = head->next; head->next = head->prev = 0; } static notifier_t *notifiers; static int changed; /* Iterator may be invalid now. */ #ifdef HAVE_SYS_POLL_H static struct pollfd *pollfds; static int npolls, rpolls; #else # ifdef HAVE_SYS_SELECT_H # include # endif #endif void init_notifier( notifier_t *sn, int fd, void (*cb)( int, void * ), void *aux ) { #ifdef HAVE_SYS_POLL_H int idx = npolls++; if (rpolls < npolls) { rpolls = npolls; pollfds = nfrealloc( pollfds, npolls * sizeof(*pollfds) ); } pollfds[idx].fd = fd; pollfds[idx].events = 0; /* POLLERR & POLLHUP implicit */ sn->index = idx; #else sn->fd = fd; sn->events = 0; #endif sn->cb = cb; sn->aux = aux; sn->next = notifiers; notifiers = sn; } void conf_notifier( notifier_t *sn, int and_events, int or_events ) { #ifdef HAVE_SYS_POLL_H int idx = sn->index; pollfds[idx].events = (pollfds[idx].events & and_events) | or_events; #else sn->events = (sn->events & and_events) | or_events; #endif } void wipe_notifier( notifier_t *sn ) { notifier_t **snp; #ifdef HAVE_SYS_POLL_H int idx; #endif for (snp = ¬ifiers; *snp != sn; snp = &(*snp)->next) assert( *snp ); *snp = sn->next; sn->next = 0; changed = 1; #ifdef HAVE_SYS_POLL_H idx = sn->index; memmove( pollfds + idx, pollfds + idx + 1, (--npolls - idx) * sizeof(*pollfds) ); for (sn = notifiers; sn; sn = sn->next) { if (sn->index > idx) sn->index--; } #endif } static time_t get_now( void ) { return time( 0 ); } static list_head_t timers = { &timers, &timers }; void init_wakeup( wakeup_t *tmr, void (*cb)( void * ), void *aux ) { tmr->cb = cb; tmr->aux = aux; tmr->links.next = tmr->links.prev = 0; } void wipe_wakeup( wakeup_t *tmr ) { if (tmr->links.next) list_unlink( &tmr->links ); } void conf_wakeup( wakeup_t *tmr, int to ) { list_head_t *head, *succ; if (to < 0) { if (tmr->links.next) list_unlink( &tmr->links ); } else { time_t timeout = to; if (!to) { /* We always prepend null timers, to cluster related events. */ succ = timers.next; } else { timeout += get_now(); /* We start at the end in the expectation that the newest timer is likely to fire last * (which will be true only if all timeouts are equal, but it's an as good guess as any). */ for (succ = &timers; (head = succ->prev) != &timers; succ = head) { if (head != &tmr->links && timeout > ((wakeup_t *)head)->timeout) break; } assert( head != &tmr->links ); } tmr->timeout = timeout; if (succ != &tmr->links) { if (tmr->links.next) list_unlink( &tmr->links ); list_prepend( &tmr->links, succ ); } } } static void event_wait( void ) { list_head_t *head; notifier_t *sn; int m; #ifdef HAVE_SYS_POLL_H int timeout = -1; if ((head = timers.next) != &timers) { wakeup_t *tmr = (wakeup_t *)head; time_t delta = tmr->timeout; if (!delta || (delta -= get_now()) <= 0) { list_unlink( head ); tmr->cb( tmr->aux ); return; } timeout = (int)delta * 1000; } switch (poll( pollfds, npolls, timeout )) { case 0: return; case -1: perror( "poll() failed in event loop" ); abort(); default: break; } for (sn = notifiers; sn; sn = sn->next) { int n = sn->index; if ((m = pollfds[n].revents)) { assert( !(m & POLLNVAL) ); sn->cb( m | shifted_bit( m, POLLHUP, POLLIN ), sn->aux ); if (changed) { changed = 0; break; } } } #else struct timeval *timeout = 0; struct timeval to_tv; fd_set rfds, wfds, efds; int fd; if ((head = timers.next) != &timers) { wakeup_t *tmr = (wakeup_t *)head; time_t delta = tmr->timeout; if (!delta || (delta -= get_now()) <= 0) { list_unlink( head ); tmr->cb( tmr->aux ); return; } to_tv.tv_sec = delta; to_tv.tv_usec = 0; timeout = &to_tv; } FD_ZERO( &rfds ); FD_ZERO( &wfds ); FD_ZERO( &efds ); m = -1; for (sn = notifiers; sn; sn = sn->next) { fd = sn->fd; if (sn->events & POLLIN) FD_SET( fd, &rfds ); if (sn->events & POLLOUT) FD_SET( fd, &wfds ); FD_SET( fd, &efds ); if (fd > m) m = fd; } switch (select( m + 1, &rfds, &wfds, &efds, timeout )) { case 0: return; case -1: perror( "select() failed in event loop" ); abort(); default: break; } for (sn = notifiers; sn; sn = sn->next) { fd = sn->fd; m = 0; if (FD_ISSET( fd, &rfds )) m |= POLLIN; if (FD_ISSET( fd, &wfds )) m |= POLLOUT; if (FD_ISSET( fd, &efds )) m |= POLLERR; if (m) { sn->cb( m, sn->aux ); if (changed) { changed = 0; break; } } } #endif } void main_loop( void ) { while (notifiers || timers.next != &timers) event_wait(); } isync-1.3.0/src/sync.h0000644000175000001440000000520413141404045011466 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2010-2012 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #ifndef SYNC_H #define SYNC_H #include "driver.h" #define M 0 /* master */ #define S 1 /* slave */ #define OP_NEW (1<<0) #define OP_RENEW (1<<1) #define OP_DELETE (1<<2) #define OP_FLAGS (1<<3) #define OP_MASK_TYPE (OP_NEW|OP_RENEW|OP_DELETE|OP_FLAGS) /* asserted in the target ops */ #define OP_EXPUNGE (1<<4) #define OP_CREATE (1<<5) #define OP_REMOVE (1<<6) #define XOP_PUSH (1<<8) #define XOP_PULL (1<<9) #define XOP_MASK_DIR (XOP_PUSH|XOP_PULL) #define XOP_HAVE_TYPE (1<<10) #define XOP_HAVE_EXPUNGE (1<<11) #define XOP_HAVE_CREATE (1<<12) #define XOP_HAVE_REMOVE (1<<13) typedef struct channel_conf { struct channel_conf *next; const char *name; store_conf_t *stores[2]; const char *boxes[2]; char *sync_state; string_list_t *patterns; int ops[2]; uint max_messages; /* for slave only */ signed char expire_unread; char use_internal_date; } channel_conf_t; typedef struct group_conf { struct group_conf *next; const char *name; string_list_t *channels; } group_conf_t; extern channel_conf_t global_conf; extern channel_conf_t *channels; extern group_conf_t *groups; extern const char *str_ms[2], *str_hl[2]; #define SYNC_OK 0 /* assumed to be 0 */ #define SYNC_FAIL 1 #define SYNC_BAD(ms) (4<<(ms)) #define SYNC_NOGOOD 16 /* internal */ #define SYNC_CANCELED 32 /* internal */ #define BOX_POSSIBLE -1 #define BOX_ABSENT 0 #define BOX_PRESENT 1 /* All passed pointers must stay alive until cb is called. */ void sync_boxes( store_t *ctx[], const char *names[], int present[], channel_conf_t *chan, void (*cb)( int sts, void *aux ), void *aux ); #endif isync-1.3.0/src/config.c0000644000175000001440000003204013141421437011754 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2011 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #include "config.h" #include "sync.h" #include #include #include #include #include #include #include #include #include store_conf_t *stores; char * get_arg( conffile_t *cfile, int required, int *comment ) { char *ret, *p, *t; int escaped, quoted; char c; p = cfile->rest; assert( p ); while ((c = *p) && isspace( (uchar)c )) p++; if (!c || c == '#') { if (comment) *comment = (c == '#'); if (required) { error( "%s:%d: parameter missing\n", cfile->file, cfile->line ); cfile->err = 1; } ret = 0; } else { for (escaped = 0, quoted = 0, ret = t = p; c; c = *p) { p++; if (escaped && c >= 32) { escaped = 0; *t++ = c; } else if (c == '\\') escaped = 1; else if (c == '"') quoted ^= 1; else if (!quoted && isspace( (uchar)c )) break; else *t++ = c; } *t = 0; if (escaped) { error( "%s:%d: unterminated escape sequence\n", cfile->file, cfile->line ); cfile->err = 1; ret = 0; } if (quoted) { error( "%s:%d: missing closing quote\n", cfile->file, cfile->line ); cfile->err = 1; ret = 0; } } cfile->rest = p; return ret; } int parse_bool( conffile_t *cfile ) { if (!strcasecmp( cfile->val, "yes" ) || !strcasecmp( cfile->val, "true" ) || !strcasecmp( cfile->val, "on" ) || !strcmp( cfile->val, "1" )) return 1; if (strcasecmp( cfile->val, "no" ) && strcasecmp( cfile->val, "false" ) && strcasecmp( cfile->val, "off" ) && strcmp( cfile->val, "0" )) { error( "%s:%d: invalid boolean value '%s'\n", cfile->file, cfile->line, cfile->val ); cfile->err = 1; } return 0; } int parse_int( conffile_t *cfile ) { char *p; int ret; ret = strtol( cfile->val, &p, 10 ); if (*p) { error( "%s:%d: invalid integer value '%s'\n", cfile->file, cfile->line, cfile->val ); cfile->err = 1; return 0; } return ret; } int parse_size( conffile_t *cfile ) { char *p; int ret; ret = strtol (cfile->val, &p, 10); if (*p == 'k' || *p == 'K') ret *= 1024, p++; else if (*p == 'm' || *p == 'M') ret *= 1024 * 1024, p++; if (*p == 'b' || *p == 'B') p++; if (*p) { fprintf (stderr, "%s:%d: invalid size '%s'\n", cfile->file, cfile->line, cfile->val); cfile->err = 1; return 0; } return ret; } static const struct { int op; const char *name; } boxOps[] = { { OP_EXPUNGE, "Expunge" }, { OP_CREATE, "Create" }, { OP_REMOVE, "Remove" }, }; static int getopt_helper( conffile_t *cfile, int *cops, channel_conf_t *conf ) { char *arg; uint i; if (!strcasecmp( "Sync", cfile->cmd )) { arg = cfile->val; do if (!strcasecmp( "Push", arg )) *cops |= XOP_PUSH; else if (!strcasecmp( "Pull", arg )) *cops |= XOP_PULL; else if (!strcasecmp( "ReNew", arg )) *cops |= OP_RENEW; else if (!strcasecmp( "New", arg )) *cops |= OP_NEW; else if (!strcasecmp( "Delete", arg )) *cops |= OP_DELETE; else if (!strcasecmp( "Flags", arg )) *cops |= OP_FLAGS; else if (!strcasecmp( "PullReNew", arg )) conf->ops[S] |= OP_RENEW; else if (!strcasecmp( "PullNew", arg )) conf->ops[S] |= OP_NEW; else if (!strcasecmp( "PullDelete", arg )) conf->ops[S] |= OP_DELETE; else if (!strcasecmp( "PullFlags", arg )) conf->ops[S] |= OP_FLAGS; else if (!strcasecmp( "PushReNew", arg )) conf->ops[M] |= OP_RENEW; else if (!strcasecmp( "PushNew", arg )) conf->ops[M] |= OP_NEW; else if (!strcasecmp( "PushDelete", arg )) conf->ops[M] |= OP_DELETE; else if (!strcasecmp( "PushFlags", arg )) conf->ops[M] |= OP_FLAGS; else if (!strcasecmp( "All", arg ) || !strcasecmp( "Full", arg )) *cops |= XOP_PULL|XOP_PUSH; else if (strcasecmp( "None", arg ) && strcasecmp( "Noop", arg )) { error( "%s:%d: invalid Sync arg '%s'\n", cfile->file, cfile->line, arg ); cfile->err = 1; } while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 ))); conf->ops[M] |= XOP_HAVE_TYPE; } else if (!strcasecmp( "SyncState", cfile->cmd )) conf->sync_state = expand_strdup( cfile->val ); else if (!strcasecmp( "CopyArrivalDate", cfile->cmd )) conf->use_internal_date = parse_bool( cfile ); else if (!strcasecmp( "MaxMessages", cfile->cmd )) conf->max_messages = parse_int( cfile ); else if (!strcasecmp( "ExpireUnread", cfile->cmd )) conf->expire_unread = parse_bool( cfile ); else { for (i = 0; i < as(boxOps); i++) { if (!strcasecmp( boxOps[i].name, cfile->cmd )) { int op = boxOps[i].op; arg = cfile->val; do { if (!strcasecmp( "Both", arg )) { *cops |= op; } else if (!strcasecmp( "Master", arg )) { conf->ops[M] |= op; } else if (!strcasecmp( "Slave", arg )) { conf->ops[S] |= op; } else if (strcasecmp( "None", arg )) { error( "%s:%d: invalid %s arg '%s'\n", cfile->file, cfile->line, boxOps[i].name, arg ); cfile->err = 1; } } while ((arg = get_arg( cfile, ARG_OPTIONAL, 0 ))); conf->ops[M] |= op * (XOP_HAVE_EXPUNGE / OP_EXPUNGE); return 1; } } return 0; } return 1; } int getcline( conffile_t *cfile ) { char *arg; int comment; if (cfile->rest && (arg = get_arg( cfile, ARG_OPTIONAL, 0 ))) { error( "%s:%d: excess token '%s'\n", cfile->file, cfile->line, arg ); cfile->err = 1; } while (fgets( cfile->buf, cfile->bufl, cfile->fp )) { cfile->line++; cfile->rest = cfile->buf; if (!(cfile->cmd = get_arg( cfile, ARG_OPTIONAL, &comment ))) { if (comment) continue; return 1; } if (!(cfile->val = get_arg( cfile, ARG_REQUIRED, 0 ))) continue; return 1; } return 0; } /* XXX - this does not detect None conflicts ... */ int merge_ops( int cops, int ops[] ) { int aops, op; uint i; aops = ops[M] | ops[S]; if (ops[M] & XOP_HAVE_TYPE) { if (aops & OP_MASK_TYPE) { if (aops & cops & OP_MASK_TYPE) { cfl: error( "Conflicting Sync args specified.\n" ); return 1; } ops[M] |= cops & OP_MASK_TYPE; ops[S] |= cops & OP_MASK_TYPE; if (cops & XOP_PULL) { if (ops[S] & OP_MASK_TYPE) goto cfl; ops[S] |= OP_MASK_TYPE; } if (cops & XOP_PUSH) { if (ops[M] & OP_MASK_TYPE) goto cfl; ops[M] |= OP_MASK_TYPE; } } else if (cops & (OP_MASK_TYPE|XOP_MASK_DIR)) { if (!(cops & OP_MASK_TYPE)) cops |= OP_MASK_TYPE; else if (!(cops & XOP_MASK_DIR)) cops |= XOP_PULL|XOP_PUSH; if (cops & XOP_PULL) ops[S] |= cops & OP_MASK_TYPE; if (cops & XOP_PUSH) ops[M] |= cops & OP_MASK_TYPE; } } for (i = 0; i < as(boxOps); i++) { op = boxOps[i].op; if (ops[M] & (op * (XOP_HAVE_EXPUNGE / OP_EXPUNGE))) { if (aops & cops & op) { error( "Conflicting %s args specified.\n", boxOps[i].name ); return 1; } ops[M] |= cops & op; ops[S] |= cops & op; } } return 0; } int load_config( const char *where, int pseudo ) { conffile_t cfile; store_conf_t *store, **storeapp = &stores; channel_conf_t *channel, **channelapp = &channels; group_conf_t *group, **groupapp = &groups; string_list_t *chanlist, **chanlistapp; char *arg, *p; int len, cops, gcops, max_size, ms, i; char path[_POSIX_PATH_MAX]; char buf[1024]; if (!where) { assert( !pseudo ); nfsnprintf( path, sizeof(path), "%s/." EXE "rc", Home ); cfile.file = path; } else cfile.file = where; if (!pseudo) info( "Reading configuration file %s\n", cfile.file ); if (!(cfile.fp = fopen( cfile.file, "r" ))) { sys_error( "Cannot open config file '%s'", cfile.file ); return 1; } buf[sizeof(buf) - 1] = 0; cfile.buf = buf; cfile.bufl = sizeof(buf) - 1; cfile.line = 0; cfile.err = 0; cfile.rest = 0; gcops = 0; global_conf.expire_unread = -1; reloop: while (getcline( &cfile )) { if (!cfile.cmd) continue; for (i = 0; i < N_DRIVERS; i++) if (drivers[i]->parse_store( &cfile, &store )) { if (store) { if (!store->max_size) store->max_size = INT_MAX; *storeapp = store; storeapp = &store->next; *storeapp = 0; } goto reloop; } if (!strcasecmp( "Channel", cfile.cmd )) { channel = nfcalloc( sizeof(*channel) ); channel->name = nfstrdup( cfile.val ); channel->max_messages = global_conf.max_messages; channel->expire_unread = global_conf.expire_unread; channel->use_internal_date = global_conf.use_internal_date; cops = 0; max_size = -1; while (getcline( &cfile ) && cfile.cmd) { if (!strcasecmp( "MaxSize", cfile.cmd )) max_size = parse_size( &cfile ); else if (!strcasecmp( "Pattern", cfile.cmd ) || !strcasecmp( "Patterns", cfile.cmd )) { arg = cfile.val; do add_string_list( &channel->patterns, arg ); while ((arg = get_arg( &cfile, ARG_OPTIONAL, 0 ))); } else if (!strcasecmp( "Master", cfile.cmd )) { ms = M; goto linkst; } else if (!strcasecmp( "Slave", cfile.cmd )) { ms = S; linkst: if (*cfile.val != ':' || !(p = strchr( cfile.val + 1, ':' ))) { error( "%s:%d: malformed mailbox spec\n", cfile.file, cfile.line ); cfile.err = 1; continue; } *p = 0; for (store = stores; store; store = store->next) if (!strcmp( store->name, cfile.val + 1 )) { channel->stores[ms] = store; goto stpcom; } error( "%s:%d: unknown store '%s'\n", cfile.file, cfile.line, cfile.val + 1 ); cfile.err = 1; continue; stpcom: if (*++p) channel->boxes[ms] = nfstrdup( p ); } else if (!getopt_helper( &cfile, &cops, channel )) { error( "%s:%d: unknown keyword '%s'\n", cfile.file, cfile.line, cfile.cmd ); cfile.err = 1; } } if (!channel->stores[M]) { error( "channel '%s' refers to no master store\n", channel->name ); cfile.err = 1; } else if (!channel->stores[S]) { error( "channel '%s' refers to no slave store\n", channel->name ); cfile.err = 1; } else if (merge_ops( cops, channel->ops )) cfile.err = 1; else { if (max_size >= 0) { if (!max_size) max_size = INT_MAX; channel->stores[M]->max_size = channel->stores[S]->max_size = max_size; } *channelapp = channel; channelapp = &channel->next; } } else if (!strcasecmp( "Group", cfile.cmd )) { group = nfmalloc( sizeof(*group) ); group->name = nfstrdup( cfile.val ); *groupapp = group; groupapp = &group->next; *groupapp = 0; chanlistapp = &group->channels; *chanlistapp = 0; while ((arg = get_arg( &cfile, ARG_OPTIONAL, 0 ))) { addone: len = strlen( arg ); chanlist = nfmalloc( sizeof(*chanlist) + len ); memcpy( chanlist->string, arg, len + 1 ); *chanlistapp = chanlist; chanlistapp = &chanlist->next; *chanlistapp = 0; } while (getcline( &cfile )) { if (!cfile.cmd) goto reloop; if (!strcasecmp( "Channel", cfile.cmd ) || !strcasecmp( "Channels", cfile.cmd )) { arg = cfile.val; goto addone; } else { error( "%s:%d: unknown keyword '%s'\n", cfile.file, cfile.line, cfile.cmd ); cfile.err = 1; } } break; } else if (!strcasecmp( "FSync", cfile.cmd )) { UseFSync = parse_bool( &cfile ); } else if (!strcasecmp( "FieldDelimiter", cfile.cmd )) { if (strlen( cfile.val ) != 1) { error( "%s:%d: Field delimiter must be exactly one character long\n", cfile.file, cfile.line ); cfile.err = 1; } else { FieldDelimiter = cfile.val[0]; if (!ispunct( FieldDelimiter )) { error( "%s:%d: Field delimiter must be a punctuation character\n", cfile.file, cfile.line ); cfile.err = 1; } } } else if (!strcasecmp( "BufferLimit", cfile.cmd )) { BufferLimit = parse_size( &cfile ); if (BufferLimit <= 0) { error( "%s:%d: BufferLimit must be positive\n", cfile.file, cfile.line ); cfile.err = 1; } } else if (!getopt_helper( &cfile, &gcops, &global_conf )) { error( "%s:%d: unknown section keyword '%s'\n", cfile.file, cfile.line, cfile.cmd ); cfile.err = 1; while (getcline( &cfile )) if (!cfile.cmd) goto reloop; break; } } fclose (cfile.fp); cfile.err |= merge_ops( gcops, global_conf.ops ); if (!global_conf.sync_state) global_conf.sync_state = expand_strdup( "~/." EXE "/" ); if (!cfile.err && pseudo) unlink( where ); return cfile.err; } isync-1.3.0/src/Makefile.in0000644000175000001440000006762413164125572012436 00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 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@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@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 = : EXTRA_PROGRAMS = tst_timers$(EXEEXT) bin_PROGRAMS = mbsync$(EXEEXT) $(am__EXEEXT_1) subdir = src 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) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/autodefs.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @with_mdconvert_TRUE@am__EXEEXT_1 = mdconvert$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \ "$(DESTDIR)$(exampledir)" PROGRAMS = $(bin_PROGRAMS) am_mbsync_OBJECTS = main.$(OBJEXT) sync.$(OBJEXT) config.$(OBJEXT) \ util.$(OBJEXT) socket.$(OBJEXT) driver.$(OBJEXT) \ drv_imap.$(OBJEXT) drv_maildir.$(OBJEXT) drv_proxy.$(OBJEXT) mbsync_OBJECTS = $(am_mbsync_OBJECTS) am__DEPENDENCIES_1 = mbsync_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_mdconvert_OBJECTS = mdconvert.$(OBJEXT) mdconvert_OBJECTS = $(am_mdconvert_OBJECTS) mdconvert_DEPENDENCIES = $(am__DEPENDENCIES_1) am_tst_timers_OBJECTS = tst_timers.$(OBJEXT) util.$(OBJEXT) tst_timers_OBJECTS = $(am_tst_timers_OBJECTS) tst_timers_LDADD = $(LDADD) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(mbsync_SOURCES) $(mdconvert_SOURCES) $(tst_timers_SOURCES) DIST_SOURCES = $(mbsync_SOURCES) $(mdconvert_SOURCES) \ $(tst_timers_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-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 \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac 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 = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 NROFF = nroff MANS = $(man_MANS) DATA = $(example_DATA) HEADERS = $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = compat am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DB_LIBS = @DB_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ SASL_LIBS = @SASL_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOCK_LIBS = @SOCK_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ Z_LIBS = @Z_LIBS@ 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@ 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_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ @with_compat_TRUE@compat_dir = compat SUBDIRS = $(compat_dir) mbsync_SOURCES = main.c sync.c config.c util.c socket.c driver.c drv_imap.c drv_maildir.c drv_proxy.c mbsync_LDADD = $(DB_LIBS) $(SSL_LIBS) $(SOCK_LIBS) $(SASL_LIBS) $(Z_LIBS) noinst_HEADERS = common.h config.h driver.h sync.h socket.h mdconvert_SOURCES = mdconvert.c mdconvert_LDADD = $(DB_LIBS) @with_mdconvert_TRUE@mdconvert_prog = mdconvert @with_mdconvert_TRUE@mdconvert_man = mdconvert.1 tst_timers_SOURCES = tst_timers.c util.c man_MANS = mbsync.1 $(mdconvert_man) exampledir = $(docdir)/examples example_DATA = mbsyncrc.sample EXTRA_DIST = drv_proxy_gen.pl run-tests.pl $(example_DATA) $(man_MANS) CLEANFILES = drv_proxy.inc all: all-recursive .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) mbsync$(EXEEXT): $(mbsync_OBJECTS) $(mbsync_DEPENDENCIES) $(EXTRA_mbsync_DEPENDENCIES) @rm -f mbsync$(EXEEXT) $(AM_V_CCLD)$(LINK) $(mbsync_OBJECTS) $(mbsync_LDADD) $(LIBS) mdconvert$(EXEEXT): $(mdconvert_OBJECTS) $(mdconvert_DEPENDENCIES) $(EXTRA_mdconvert_DEPENDENCIES) @rm -f mdconvert$(EXEEXT) $(AM_V_CCLD)$(LINK) $(mdconvert_OBJECTS) $(mdconvert_LDADD) $(LIBS) tst_timers$(EXEEXT): $(tst_timers_OBJECTS) $(tst_timers_DEPENDENCIES) $(EXTRA_tst_timers_DEPENDENCIES) @rm -f tst_timers$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tst_timers_OBJECTS) $(tst_timers_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/driver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drv_imap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drv_maildir.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/drv_proxy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mdconvert.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sync.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tst_timers.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-exampleDATA: $(example_DATA) @$(NORMAL_INSTALL) @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(exampledir)'"; \ $(MKDIR_P) "$(DESTDIR)$(exampledir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(exampledir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(exampledir)" || exit $$?; \ done uninstall-exampleDATA: @$(NORMAL_UNINSTALL) @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(exampledir)'; $(am__uninstall_files_from_dir) # 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. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ 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; \ ($(am__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" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ 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 || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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 "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$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 \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(PROGRAMS) $(MANS) $(DATA) $(HEADERS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(exampledir)"; 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-exampleDATA install-man install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man1 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-exampleDATA \ uninstall-man uninstall-man: uninstall-man1 .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-binPROGRAMS clean-generic cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-tags distdir dvi dvi-am html html-am info info-am \ install install-am install-binPROGRAMS install-data \ install-data-am install-dvi install-dvi-am install-exampleDATA \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-man1 \ 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-compile mostlyclean-generic pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-exampleDATA uninstall-man \ uninstall-man1 .PRECIOUS: Makefile drv_proxy.$(OBJEXT): drv_proxy.inc drv_proxy.inc: $(srcdir)/driver.h $(srcdir)/drv_proxy.c $(srcdir)/drv_proxy_gen.pl perl $(srcdir)/drv_proxy_gen.pl $(srcdir)/driver.h $(srcdir)/drv_proxy.c drv_proxy.inc # 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: isync-1.3.0/src/mbsyncrc.sample0000644000175000001440000000410113007413620013357 00000000000000# Global configuration section # Values here are used as defaults for any following Channel section that # doesn't specify them. Expunge None Create Both MaildirStore local Path ~/Mail/ Trash Trash IMAPStore work Host work.host.com User tehuser Pass xxxxxxxx # Fetch password from gnome-keyring: #PassCmd "gnome-keyring-query get mail_pw" # Fetch password from .netrc: #PassCmd "sed -n -e 's,^machine work\\.host\\.com login tehuser password \\(.*\\),\\1,p' < $HOME/.netrc" # Fetch password from a gpg-encrypted file: #PassCmd "gpg --quiet --for-your-eyes-only --decrypt $HOME/imappassword.gpg" # Fetch password from pwmd (http://pwmd.sourceforge.net/): #PassCmd "echo -ne 'GET myIsp\\tpassword' | pwmc datafile" # On Mac OS X, run "KeyChain Access" -- File->New Password Item. Fill out form using # "Keychain Item Name" http://IMAPSERVER (note: the "http://" is a hack) # "Account Name" USERNAME # "Password" PASSWORD #PassCmd "/usr/bin/security find-internet-password -w -a USERNAME -s IMAPSERVER ~/Library/Keychains/login.keychain" Channel work Master :work: Slave :local:work Expunge Slave Sync PullNew Push IMAPStore personal Host host.play.com Port 6789 RequireSSL no Channel personal Master :personal: Slave :local:personal Expunge Both MaxMessages 150 MaxSize 200k IMAPStore remote Tunnel "ssh -q host.remote.com /usr/sbin/imapd" Channel remote Master :remote: Slave :local:remote Group boxes Channels work personal remote IMAPStore st1 Host st1.domain.com RequireCRAM yes CertificateFile ~/.st1-certificate.crt IMAPStore st2 Host imap.another-domain.com Path non-standard/ RequireSSL no UseTLSv1 no Channel rst Master :st1:somebox Slave :st2: IMAPAccount server Host imaps:foo.bar.com CertificateFile ~/.server-certificate.crt IMAPStore server Account server MapInbox inbox Trash ~/trash TrashRemoteNew yes MaildirStore mirror Path ~/Maildir/ SubFolders Verbatim Channel o2o Master :server: Slave :mirror: Patterns % Group partial o2o:inbox,sent-mail,foobar # INBOX => server, INBOX.foo => server.foo, etc. Channel inbox Master :server:INBOX Slave :mirror:server Patterns * isync-1.3.0/src/common.h0000644000175000001440000001463313164125071012014 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2010-2012 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #ifndef COMMON_H #define COMMON_H #include #include #include #include #include typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; #define as(ar) (sizeof(ar)/sizeof(ar[0])) #define __stringify(x) #x #define stringify(x) __stringify(x) #define shifted_bit(in, from, to) \ (((uint)(in) / (from > to ? from / to : 1) * (to > from ? to / from : 1)) & to) #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) # define ATTR_UNUSED __attribute__((unused)) # define ATTR_NORETURN __attribute__((noreturn)) # define ATTR_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) # define ATTR_PACKED(ref) __attribute__((packed,aligned(sizeof(ref)))) #else # define ATTR_UNUSED # define ATTR_NORETURN # define ATTR_PRINTFLIKE(fmt,var) # define ATTR_PACKED(ref) #endif #if __GNUC__ >= 7 # define FALLTHROUGH __attribute__((fallthrough)); #else # define FALLTHROUGH #endif #ifdef __GNUC__ # define INLINE __inline__ #else # define INLINE #endif #define EXE "mbsync" /* main.c */ #define DEBUG_CRASH 0x01 #define DEBUG_MAILDIR 0x02 #define DEBUG_NET 0x04 #define DEBUG_NET_ALL 0x08 #define DEBUG_SYNC 0x10 #define DEBUG_MAIN 0x20 #define DEBUG_DRV 0x40 #define DEBUG_DRV_ALL 0x80 #define DEBUG_ALL (0xFF & ~(DEBUG_NET_ALL | DEBUG_DRV_ALL)) #define QUIET 0x100 #define VERYQUIET 0x200 #define PROGRESS 0x400 #define VERBOSE 0x800 #define KEEPJOURNAL 0x1000 #define ZERODELAY 0x2000 extern int DFlags; extern int JLimit; extern int UseFSync; extern char FieldDelimiter; extern int Pid; extern char Hostname[256]; extern const char *Home; extern int BufferLimit; extern int new_total[2], new_done[2]; extern int flags_total[2], flags_done[2]; extern int trash_total[2], trash_done[2]; void stats( void ); /* util.c */ void vdebug( int, const char *, va_list va ); void vdebugn( int, const char *, va_list va ); void ATTR_PRINTFLIKE(1, 2) info( const char *, ... ); void ATTR_PRINTFLIKE(1, 2) infon( const char *, ... ); void ATTR_PRINTFLIKE(1, 2) progress( const char *, ... ); void ATTR_PRINTFLIKE(1, 2) notice( const char *, ... ); void ATTR_PRINTFLIKE(1, 2) warn( const char *, ... ); void ATTR_PRINTFLIKE(1, 2) error( const char *, ... ); void ATTR_PRINTFLIKE(1, 2) sys_error( const char *, ... ); void flushn( void ); typedef struct string_list { struct string_list *next; char string[1]; } ATTR_PACKED(void *) string_list_t; void add_string_list_n( string_list_t **list, const char *str, int len ); void add_string_list( string_list_t **list, const char *str ); void free_string_list( string_list_t *list ); #ifndef HAVE_MEMRCHR void *memrchr( const void *s, int c, size_t n ); #endif #ifndef HAVE_STRNLEN size_t strnlen( const char *str, size_t maxlen ); #endif int starts_with( const char *str, int strl, const char *cmp, int cmpl ); int starts_with_upper( const char *str, int strl, const char *cmp, int cmpl ); int equals( const char *str, int strl, const char *cmp, int cmpl ); #ifndef HAVE_TIMEGM time_t timegm( struct tm *tm ); #endif void *nfmalloc( size_t sz ); void *nfcalloc( size_t sz ); void *nfrealloc( void *mem, size_t sz ); char *nfstrndup( const char *str, size_t nchars ); char *nfstrdup( const char *str ); int nfvasprintf( char **str, const char *fmt, va_list va ); int ATTR_PRINTFLIKE(2, 3) nfasprintf( char **str, const char *fmt, ... ); int ATTR_PRINTFLIKE(3, 4) nfsnprintf( char *buf, int blen, const char *fmt, ... ); void ATTR_NORETURN oob( void ); char *expand_strdup( const char *s ); int map_name( const char *arg, char **result, int reserve, const char *in, const char *out ); #define DEFINE_ARRAY_TYPE(T) \ typedef struct { \ T *data; \ int size; \ } ATTR_PACKED(T *) T##_array_t; \ typedef struct { \ T##_array_t array; \ int alloc; \ } ATTR_PACKED(T *) T##_array_alloc_t; \ static INLINE T *T##_array_append( T##_array_alloc_t *arr ) \ { \ if (arr->array.size == arr->alloc) { \ arr->alloc = arr->alloc * 2 + 100; \ arr->array.data = nfrealloc( arr->array.data, arr->alloc * sizeof(T) ); \ } \ return &arr->array.data[arr->array.size++]; \ } #define ARRAY_INIT(arr) \ do { (arr)->array.data = 0; (arr)->array.size = (arr)->alloc = 0; } while (0) #define ARRAY_SQUEEZE(arr) \ do { \ (arr)->data = nfrealloc( (arr)->data, (arr)->size * sizeof((arr)->data[0]) ); \ } while (0) DEFINE_ARRAY_TYPE(uint) void sort_uint_array( uint_array_t array ); int find_uint_array( const uint_array_t array, uint value ); void arc4_init( void ); uchar arc4_getbyte( void ); int bucketsForSize( int size ); typedef struct list_head { struct list_head *next, *prev; } list_head_t; typedef struct notifier { struct notifier *next; void (*cb)( int what, void *aux ); void *aux; #ifdef HAVE_SYS_POLL_H int index; #else int fd, events; #endif } notifier_t; #ifdef HAVE_SYS_POLL_H # include #else # define POLLIN 1 # define POLLOUT 4 # define POLLERR 8 #endif void init_notifier( notifier_t *sn, int fd, void (*cb)( int, void * ), void *aux ); void conf_notifier( notifier_t *sn, int and_events, int or_events ); void wipe_notifier( notifier_t *sn ); typedef struct { list_head_t links; void (*cb)( void *aux ); void *aux; time_t timeout; } wakeup_t; void init_wakeup( wakeup_t *tmr, void (*cb)( void * ), void *aux ); void conf_wakeup( wakeup_t *tmr, int timeout ); void wipe_wakeup( wakeup_t *tmr ); static INLINE int pending_wakeup( wakeup_t *tmr ) { return tmr->links.next != 0; } void main_loop( void ); #endif isync-1.3.0/src/drv_proxy.c0000644000175000001440000002142713141404045012546 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2017 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #include "driver.h" #include #include typedef struct { store_t gen; const char *label; // foreign int ref_count; driver_t *real_driver; store_t *real_store; void (*bad_callback)( void *aux ); void *bad_callback_aux; } proxy_store_t; static void ATTR_PRINTFLIKE(1, 2) debug( const char *msg, ... ) { va_list va; va_start( va, msg ); vdebug( DEBUG_DRV, msg, va ); va_end( va ); } static void ATTR_PRINTFLIKE(1, 2) debugn( const char *msg, ... ) { va_list va; va_start( va, msg ); vdebugn( DEBUG_DRV, msg, va ); va_end( va ); } static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' }; static char * proxy_make_flags( int flags, char *buf ) { uint i, d; for (d = 0, i = 0; i < as(Flags); i++) if (flags & (1 << i)) buf[d++] = Flags[i]; buf[d] = 0; return buf; } static void proxy_store_deref( proxy_store_t *ctx ) { if (!--ctx->ref_count) free( ctx ); } static int curr_tag; typedef struct { int ref_count; int tag; proxy_store_t *ctx; } gen_cmd_t; static gen_cmd_t * proxy_cmd_new( proxy_store_t *ctx, int sz ) { gen_cmd_t *cmd = nfmalloc( sz ); cmd->ref_count = 2; cmd->tag = ++curr_tag; cmd->ctx = ctx; ctx->ref_count++; return cmd; } static void proxy_cmd_done( gen_cmd_t *cmd ) { if (!--cmd->ref_count) { proxy_store_deref( cmd->ctx ); free( cmd ); } } #if 0 //# TEMPLATE GETTER static @type@proxy_@name@( store_t *gctx ) { proxy_store_t *ctx = (proxy_store_t *)gctx; @type@rv = ctx->real_driver->@name@( ctx->real_store ); debug( "%sCalled @name@, ret=@fmt@\n", ctx->label, rv ); return rv; } //# END //# TEMPLATE REGULAR static @type@proxy_@name@( store_t *gctx@decl_args@ ) { proxy_store_t *ctx = (proxy_store_t *)gctx; @pre_print_args@ debug( "%sEnter @name@@print_fmt_args@\n", ctx->label@print_pass_args@ ); @print_args@ @type@rv = ctx->real_driver->@name@( ctx->real_store@pass_args@ ); debug( "%sLeave @name@, ret=@fmt@\n", ctx->label, rv ); return rv; } //# END //# TEMPLATE REGULAR_VOID static void proxy_@name@( store_t *gctx@decl_args@ ) { proxy_store_t *ctx = (proxy_store_t *)gctx; @pre_print_args@ debug( "%sEnter @name@@print_fmt_args@\n", ctx->label@print_pass_args@ ); @print_args@ ctx->real_driver->@name@( ctx->real_store@pass_args@ ); debug( "%sLeave @name@\n", ctx->label ); @action@ } //# END //# TEMPLATE CALLBACK typedef struct { gen_cmd_t gen; void (*callback)( @decl_cb_args@void *aux ); void *callback_aux; @decl_state@ } @name@_cmd_t; static void proxy_@name@_cb( @decl_cb_args@void *aux ) { @name@_cmd_t *cmd = (@name@_cmd_t *)aux; @pre_print_cb_args@ debug( "%s[% 2d] Callback enter @name@@print_fmt_cb_args@\n", cmd->gen.ctx->label, cmd->gen.tag@print_pass_cb_args@ ); @print_cb_args@ cmd->callback( @pass_cb_args@cmd->callback_aux ); debug( "%s[% 2d] Callback leave @name@\n", cmd->gen.ctx->label, cmd->gen.tag ); proxy_cmd_done( &cmd->gen ); } static void proxy_@name@( store_t *gctx@decl_args@, void (*cb)( @decl_cb_args@void *aux ), void *aux ) { proxy_store_t *ctx = (proxy_store_t *)gctx; @name@_cmd_t *cmd = (@name@_cmd_t *)proxy_cmd_new( ctx, sizeof(@name@_cmd_t) ); cmd->callback = cb; cmd->callback_aux = aux; @assign_state@ @pre_print_args@ debug( "%s[% 2d] Enter @name@@print_fmt_args@\n", ctx->label, cmd->gen.tag@print_pass_args@ ); @print_args@ ctx->real_driver->@name@( ctx->real_store@pass_args@, proxy_@name@_cb, cmd ); debug( "%s[% 2d] Leave @name@\n", ctx->label, cmd->gen.tag ); proxy_cmd_done( &cmd->gen ); } //# END //# UNDEFINE list_store_print_fmt_cb_args //# UNDEFINE list_store_print_pass_cb_args //# DEFINE list_store_print_cb_args if (sts == DRV_OK) { for (string_list_t *box = boxes; box; box = box->next) debug( " %s\n", box->string ); } //# END //# DEFINE load_box_pre_print_args static char ubuf[12]; //# END //# DEFINE load_box_print_fmt_args , [%u,%s] (new >= %u, seen <= %u) //# DEFINE load_box_print_pass_args , minuid, (maxuid == UINT_MAX) ? "inf" : (nfsnprintf( ubuf, sizeof(ubuf), "%u", maxuid ), ubuf), newuid, seenuid //# DEFINE load_box_print_args if (excs.size) { debugn( " excs:" ); for (int t = 0; t < excs.size; t++) debugn( " %d", excs.data[t] ); debug( "\n" ); } //# END //# DEFINE load_box_pre_print_cb_args static char fbuf[as(Flags) + 1]; //# END //# DEFINE load_box_print_fmt_cb_args , sts=%d, total=%d, recent=%d //# DEFINE load_box_print_pass_cb_args , sts, total_msgs, recent_msgs //# DEFINE load_box_print_cb_args if (sts == DRV_OK) { for (message_t *msg = msgs; msg; msg = msg->next) debug( " uid=%5u, flags=%4s, size=%6d, tuid=%." stringify(TUIDL) "s\n", msg->uid, (msg->status & M_FLAGS) ? (proxy_make_flags( msg->flags, fbuf ), fbuf) : "?", msg->size, *msg->tuid ? msg->tuid : "?" ); } //# END //# DEFINE find_new_msgs_print_fmt_cb_args , sts=%d //# DEFINE find_new_msgs_print_pass_cb_args , sts //# DEFINE find_new_msgs_print_cb_args if (sts == DRV_OK) { for (message_t *msg = msgs; msg; msg = msg->next) debug( " uid=%5u, tuid=%." stringify(TUIDL) "s\n", msg->uid, msg->tuid ); } //# END //# DEFINE fetch_msg_decl_state msg_data_t *data; //# END //# DEFINE fetch_msg_assign_state cmd->data = data; //# END //# DEFINE fetch_msg_print_fmt_args , uid=%u, want_flags=%s, want_date=%s //# DEFINE fetch_msg_print_pass_args , msg->uid, !(msg->status & M_FLAGS) ? "yes" : "no", data->date ? "yes" : "no" //# DEFINE fetch_msg_pre_print_cb_args static char fbuf[as(Flags) + 1]; proxy_make_flags( cmd->data->flags, fbuf ); //# END //# DEFINE fetch_msg_print_fmt_cb_args , flags=%s, date=%ld, size=%d //# DEFINE fetch_msg_print_pass_cb_args , fbuf, cmd->data->date, cmd->data->len //# DEFINE fetch_msg_print_cb_args if (sts == DRV_OK && (DFlags & DEBUG_DRV_ALL)) { printf( "%s=========\n", cmd->gen.ctx->label ); fwrite( cmd->data->data, cmd->data->len, 1, stdout ); printf( "%s=========\n", cmd->gen.ctx->label ); fflush( stdout ); } //# END //# DEFINE store_msg_pre_print_args static char fbuf[as(Flags) + 1]; proxy_make_flags( data->flags, fbuf ); //# END //# DEFINE store_msg_print_fmt_args , flags=%s, date=%ld, size=%d, to_trash=%s //# DEFINE store_msg_print_pass_args , fbuf, data->date, data->len, to_trash ? "yes" : "no" //# DEFINE store_msg_print_args if (DFlags & DEBUG_DRV_ALL) { printf( "%s>>>>>>>>>\n", ctx->label ); fwrite( data->data, data->len, 1, stdout ); printf( "%s>>>>>>>>>\n", ctx->label ); fflush( stdout ); } //# END //# DEFINE set_msg_flags_pre_print_args static char fbuf1[as(Flags) + 1], fbuf2[as(Flags) + 1]; proxy_make_flags( add, fbuf1 ); proxy_make_flags( del, fbuf2 ); //# END //# DEFINE set_msg_flags_print_fmt_args , uid=%u, add=%s, del=%s //# DEFINE set_msg_flags_print_pass_args , uid, fbuf1, fbuf2 //# DEFINE trash_msg_print_fmt_args , uid=%u //# DEFINE trash_msg_print_pass_args , msg->uid //# DEFINE free_store_action proxy_store_deref( ctx ); //# END //# DEFINE cancel_store_action proxy_store_deref( ctx ); //# END #endif //# SPECIAL commit_cmds static void proxy_commit_cmds( store_t *gctx ) { // Currently a dummy in all real drivers. (void) gctx; } //# SPECIAL set_bad_callback static void proxy_set_bad_callback( store_t *gctx, void (*cb)( void *aux ), void *aux ) { proxy_store_t *ctx = (proxy_store_t *)gctx; ctx->bad_callback = cb; ctx->bad_callback_aux = aux; } static void proxy_invoke_bad_callback( proxy_store_t *ctx ) { debug( "%sCallback enter bad store\n", ctx->label ); ctx->bad_callback( ctx->bad_callback_aux ); debug( "%sCallback leave bad store\n", ctx->label ); \ } //# EXCLUDE alloc_store store_t * proxy_alloc_store( store_t *real_ctx, const char *label ) { proxy_store_t *ctx; ctx = nfcalloc( sizeof(*ctx) ); ctx->gen.driver = &proxy_driver; ctx->gen.conf = real_ctx->conf; ctx->ref_count = 1; ctx->label = label; ctx->real_driver = real_ctx->driver; ctx->real_store = real_ctx; ctx->real_driver->set_bad_callback( ctx->real_store, (void (*)(void *))proxy_invoke_bad_callback, ctx ); return &ctx->gen; } //# EXCLUDE parse_store //# EXCLUDE cleanup //# EXCLUDE get_fail_state #include "drv_proxy.inc" isync-1.3.0/src/socket.h0000644000175000001440000001050513164125173012011 00000000000000/* * mbsync - mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2006,2010-2012 Oswald Buddenhagen * * 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, see . * * As a special exception, mbsync may be linked with the OpenSSL library, * despite that library's more restrictive license. */ #ifndef SOCKET_H #define SOCKET_H #include "common.h" #ifdef HAVE_LIBZ #include #endif #ifdef HAVE_LIBSSL typedef struct ssl_st SSL; typedef struct ssl_ctx_st SSL_CTX; typedef struct stack_st _STACK; enum { SSLv3 = 2, TLSv1 = 4, TLSv1_1 = 8, TLSv1_2 = 16 }; #endif typedef struct { char *tunnel; char *host; int port; int timeout; #ifdef HAVE_LIBSSL char *cert_file; char *client_certfile; char *client_keyfile; char system_certs; char ssl_versions; /* these are actually variables and are leaked at the end */ char ssl_ctx_valid; _STACK *trusted_certs; SSL_CTX *SSLContext; #endif } server_conf_t; typedef struct buff_chunk { struct buff_chunk *next; int len; char data[1]; } buff_chunk_t; typedef struct { /* connection */ int fd; int state; const server_conf_t *conf; /* needed during connect */ #ifdef HAVE_IPV6 struct addrinfo *addrs, *curr_addr; /* needed during connect */ #else char **curr_addr; /* needed during connect */ #endif char *name; #ifdef HAVE_LIBSSL SSL *ssl; wakeup_t ssl_fake; #endif #ifdef HAVE_LIBZ z_streamp in_z, out_z; wakeup_t z_fake; int z_written; #endif void (*bad_callback)( void *aux ); /* async fail while sending or listening */ void (*read_callback)( void *aux ); /* data available for reading */ void (*write_callback)( void *aux ); /* all *queued* data was sent */ union { void (*connect)( int ok, void *aux ); void (*starttls)( int ok, void *aux ); } callbacks; void *callback_aux; notifier_t notify; wakeup_t fd_fake; wakeup_t fd_timeout; /* writing */ buff_chunk_t *append_buf; /* accumulating buffer */ buff_chunk_t *write_buf, **write_buf_append; /* buffer head & tail */ int writing; #ifdef HAVE_LIBZ int append_avail; /* space left in accumulating buffer */ #endif int write_offset; /* offset into buffer head */ int buffer_mem; /* memory currently occupied by buffers in the queue */ /* reading */ int offset; /* start of filled bytes in buffer */ int bytes; /* number of filled bytes in buffer */ int scanoff; /* offset to continue scanning for newline at, relative to 'offset' */ char buf[100000]; #ifdef HAVE_LIBZ char z_buf[100000]; #endif } conn_t; /* call this before doing anything with the socket */ static INLINE void socket_init( conn_t *conn, const server_conf_t *conf, void (*bad_callback)( void *aux ), void (*read_callback)( void *aux ), void (*write_callback)( void *aux ), void *aux ) { conn->conf = conf; conn->bad_callback = bad_callback; conn->read_callback = read_callback; conn->write_callback = write_callback; conn->callback_aux = aux; conn->fd = -1; conn->name = 0; conn->write_buf_append = &conn->write_buf; } void socket_connect( conn_t *conn, void (*cb)( int ok, void *aux ) ); void socket_start_tls(conn_t *conn, void (*cb)( int ok, void *aux ) ); void socket_start_deflate( conn_t *conn ); void socket_close( conn_t *sock ); void socket_expect_read( conn_t *sock, int expect ); int socket_read( conn_t *sock, char *buf, int len ); /* never waits */ char *socket_read_line( conn_t *sock ); /* don't free return value; never waits */ typedef enum { KeepOwn = 0, GiveOwn } ownership_t; typedef struct { char *buf; int len; ownership_t takeOwn; } conn_iovec_t; void socket_write( conn_t *sock, conn_iovec_t *iov, int iovcnt ); #endif isync-1.3.0/src/compat/0000755000175000001440000000000013164163470011714 500000000000000isync-1.3.0/src/compat/Makefile.am0000644000175000001440000000036613007413620013664 00000000000000bin_PROGRAMS = isync isync_SOURCES = main.c config.c convert.c util.c isync_LDADD = $(DB_LIBS) noinst_HEADERS = isync.h man_MANS = isync.1 exampledir = $(docdir)/examples example_DATA = isyncrc.sample EXTRA_DIST = $(example_DATA) $(man_MANS) isync-1.3.0/src/compat/main.c0000644000175000001440000002462513164125173012733 00000000000000/* * isync - mbsync wrapper: IMAP4 to maildir mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2004 Oswald Buddenhagen * * 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, see . */ #include "isync.h" #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_GETOPT_LONG # include struct option Opts[] = { {"write", 0, NULL, 'w' }, {"writeto", 0, NULL, 'W' }, {"all", 0, NULL, 'a' }, {"list", 0, NULL, 'l'}, {"config", 1, NULL, 'c'}, {"create", 0, NULL, 'C'}, {"create-local", 0, NULL, 'L'}, {"create-remote", 0, NULL, 'R'}, {"delete", 0, NULL, 'd'}, {"expunge", 0, NULL, 'e'}, {"fast", 0, NULL, 'f'}, {"help", 0, NULL, 'h'}, {"remote", 1, NULL, 'r'}, {"folder", 1, NULL, 'F'}, {"maildir", 1, NULL, 'M'}, {"one-to-one", 0, NULL, '1'}, {"inbox", 1, NULL, 'I'}, {"host", 1, NULL, 's'}, {"port", 1, NULL, 'p'}, {"debug", 0, NULL, 'D'}, {"quiet", 0, NULL, 'q'}, {"user", 1, NULL, 'u'}, {"pass", 1, NULL, 'P'}, {"version", 0, NULL, 'v'}, {"verbose", 0, NULL, 'V'}, {0, 0, 0, 0} }; #endif static void ATTR_NORETURN version( void ) { puts( PACKAGE " " VERSION ); exit( 0 ); } static void ATTR_NORETURN usage( int code ) { fputs( PACKAGE " " VERSION " - mbsync wrapper: IMAP4 to maildir synchronizer\n" "Copyright (C) 2000-2002 Michael R. Elkins \n" "Copyright (C) 2002-2006,2008,2010-2012 Oswald Buddenhagen \n" "Copyright (C) 2004 Theodore Ts'o \n" "usage:\n" " " PACKAGE " [ flags ] mailbox [mailbox ...]\n" " " PACKAGE " [ flags ] -a\n" " " PACKAGE " [ flags ] -l\n" " -a, --all synchronize all defined mailboxes\n" " -l, --list list all defined mailboxes and exit\n" " -L, --create-local create local maildir mailbox if nonexistent\n" " -R, --create-remote create remote imap mailbox if nonexistent\n" " -C, --create create both local and remote mailboxes if nonexistent\n" " -d, --delete delete local msgs that don't exist on the server\n" " -e, --expunge expunge deleted messages\n" " -f, --fast only fetch new messages\n" " -r, --remote BOX remote mailbox\n" " -F, --folder DIR remote IMAP folder containing mailboxes\n" " -M, --maildir DIR local directory containing mailboxes\n" " -1, --one-to-one map every IMAP /box to /box\n" " -I, --inbox BOX map IMAP INBOX to /BOX (exception to -1)\n" " -s, --host HOST IMAP server address\n" " -p, --port PORT server IMAP port\n" " -u, --user USER IMAP user name\n" " -P, --pass PASSWORD IMAP password\n" " -c, --config CONFIG read an alternate config file (default: ~/.isyncrc)\n" " -D, --debug print debugging messages\n" " -V, --verbose verbose mode (display network traffic)\n" " -q, --quiet don't display progress info\n" " -v, --version display version\n" " -h, --help display this help message\n\n" "Note that this is a wrapper binary only; the \"real\" isync is named \"mbsync\".\n" "Options to permanently transform your old isync configuration:\n" " -w, --write write permanent mbsync configuration\n" " -W, --writeto FILE write permanent mbsync configuration to FILE\n", code ? stderr : stdout ); exit( code ); } static const char * strrstr( const char *h, const char *n ) { char *p = strstr( h, n ); if (!p) return 0; do { h = p; p = strstr( h + 1, n ); } while (p); return h; } static void add_arg( char ***args, const char *arg ) { int nu = 0; if (*args) for (; (*args)[nu]; nu++); *args = nfrealloc( *args, sizeof(char *) * (nu + 2)); (*args)[nu] = nfstrdup( arg ); (*args)[nu + 1] = 0; } #define OP_FAST (1<<2) #define OP_CREATE_REMOTE (1<<3) #define OP_CREATE_LOCAL (1<<4) int Quiet, Verbose, Debug; config_t global, *boxes; const char *maildir, *xmaildir, *folder, *inbox; int o2o, altmap, delete, expunge; const char *Home; int HomeLen; int main( int argc, char **argv ) { config_t *box, **stor; char *config = 0, *outconfig = 0, **args; int i, pl, fd, mod, all, list, ops, writeout; struct stat st; char path1[_POSIX_PATH_MAX], path2[_POSIX_PATH_MAX]; if (!(Home = getenv("HOME"))) { fputs( "Fatal: $HOME not set\n", stderr ); return 1; } HomeLen = strlen( Home ); /* defaults */ /* XXX the precedence is borked: it's defaults < cmdline < file instead of defaults < file < cmdline */ #ifdef BSD global.user = getenv( "USER" ); #else global.user = getenv( "LOGNAME" ); #endif global.port = 143; global.box = ""; /* implicit INBOX in resulting Master/Slave entries */ global.use_namespace = 1; global.require_ssl = 1; global.use_tlsv1 = 1; folder = ""; maildir = "~"; xmaildir = Home; #define FLAGS "wW:alCLRc:defhp:qu:P:r:F:M:1I:s:vVD" mod = all = list = ops = writeout = Quiet = Verbose = Debug = 0; #ifdef HAVE_GETOPT_LONG while ((i = getopt_long( argc, argv, FLAGS, Opts, NULL )) != -1) #else while ((i = getopt( argc, argv, FLAGS )) != -1) #endif { switch (i) { case 'W': outconfig = optarg; FALLTHROUGH case 'w': writeout = 1; break; case 'l': list = 1; FALLTHROUGH case 'a': all = 1; break; case '1': o2o = 1; mod = 1; break; case 'C': ops |= OP_CREATE_REMOTE|OP_CREATE_LOCAL; break; case 'L': ops |= OP_CREATE_LOCAL; break; case 'R': ops |= OP_CREATE_REMOTE; break; case 'c': config = optarg; break; case 'd': delete = 1; break; case 'e': expunge = 1; break; case 'f': ops |= OP_FAST; break; case 'p': global.port = atoi( optarg ); mod = 1; break; case 'r': global.box = optarg; mod = 1; break; case 'F': folder = optarg; mod = 1; break; case 'M': maildir = optarg; mod = 1; break; case 'I': inbox = optarg; mod = 1; break; case 's': #ifdef HAVE_LIBSSL if (!strncasecmp( "imaps:", optarg, 6 )) { global.use_imaps = 1; global.port = 993; global.use_sslv3 = 1; optarg += 6; } #endif global.host = optarg; mod = 1; break; case 'u': global.user = optarg; mod = 1; break; case 'P': global.pass = optarg; mod = 1; break; case 'D': Debug = 1; break; case 'V': Verbose++; break; case 'q': Quiet++; break; case 'v': version(); case 'h': usage( 0 ); default: usage( 1 ); } } if (!writeout) fputs( "Notice: please run 'isync -w' and start using 'mbsync' directly.\n", stderr ); if (config) { if (*config != '/') { if (!getcwd( path1, sizeof(path1) )) { fprintf( stderr, "Can't obtain working directory\n" ); return 1; } pl = strlen( path1 ); nfsnprintf( path1 + pl, sizeof(path1) - pl, "/%s", config ); config = path1; } } else { nfsnprintf( path1, sizeof(path1), "%s/.isyncrc", Home ); config = path1; } stor = &boxes; load_config( config, &stor ); if (!all && !o2o) for (i = optind; argv[i]; i++) if (!find_box( argv[i] )) { box = nfmalloc( sizeof(config_t) ); memcpy( box, &global, sizeof(config_t) ); box->path = argv[i]; *stor = box; stor = &box->next; mod = 1; } if (writeout) { all = 1; if (mod) fprintf( stderr, "Warning: command line switches that influence the resulting config file\n" "have been supplied.\n" ); } else { if (!argv[optind] && !all) { fprintf( stderr, "No mailbox specified. Try isync -h\n" ); return 1; } } if (all) { if (o2o) { DIR * dir; struct dirent *de; if (!(dir = opendir( xmaildir ))) { sys_error( "Cannot list '%s'", xmaildir ); return 1; } while ((de = readdir( dir ))) { if (*de->d_name == '.') continue; nfsnprintf( path2, sizeof(path2), "%s/%s/cur", xmaildir, de->d_name ); if (stat( path2, &st ) || !S_ISDIR( st.st_mode )) continue; global.path = de->d_name; global.box = (inbox && !strcmp( inbox, global.path )) ? "INBOX" : global.path; convert( &global ); } closedir( dir ); } else for (box = boxes; box; box = box->next) convert( box ); } else { for (i = optind; argv[i]; i++) if (o2o) { global.path = argv[i]; global.box = (inbox && !strcmp( global.path, inbox )) ? "INBOX" : global.path; convert( &global ); } else convert( find_box( argv[i] ) ); } if (writeout) { if (!outconfig) { const char *p = strrchr( config, '/' ); if (!p) p = config; p = strrstr( p, "isync" ); if (!p) nfsnprintf( path2, sizeof(path2), "%s.mbsync", config ); else nfsnprintf( path2, sizeof(path2), "%.*smb%s", p - config, config, p + 1 ); outconfig = path2; } if ((fd = creat( outconfig, 0666 )) < 0) { sys_error( "Error: cannot create config file '%s'", outconfig ); return 1; } } else { strcpy( path2, "/tmp/mbsyncrcXXXXXX" ); if ((fd = mkstemp( path2 )) < 0) { sys_error( "Error: cannot create temporary config file" ); return 1; } } write_config( fd ); if (writeout) return 0; args = 0; add_arg( &args, "mbsync" ); while (--Verbose >= 0) add_arg( &args, "-V" ); if (Debug) add_arg( &args, "-D" ); for (; Quiet; Quiet--) add_arg( &args, "-q" ); add_arg( &args, "-cT" ); add_arg( &args, path2 ); if (ops & OP_FAST) add_arg( &args, "-Ln" ); if (ops & OP_CREATE_REMOTE) add_arg( &args, "-Cm" ); if (ops & OP_CREATE_LOCAL) add_arg( &args, "-Cs" ); if (list) add_arg( &args, "-lC" ); if (o2o) { if (all) add_arg( &args, "o2o" ); else { char buf[1024]; strcpy( buf, "o2o:" ); strcat( buf, argv[optind] ); while (argv[++optind]) { strcat( buf, "," ); strcat( buf, argv[optind] ); } add_arg( &args, buf ); } } else { if (all) add_arg( &args, "-a" ); else for (; argv[optind]; optind++) add_arg( &args, find_box( argv[optind] )->channel_name ); } execvp( args[0], args ); sys_error( "Cannot execute %s", args[0] ); return 1; } isync-1.3.0/src/compat/util.c0000644000175000001440000000731213007413620012747 00000000000000/* * isync - mbsync wrapper: IMAP4 to maildir mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2004 Oswald Buddenhagen * * 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, see . */ #include "isync.h" #include #include #include #include #include #include void sys_error( const char *msg, ... ) { va_list va; char buf[1024]; va_start( va, msg ); if ((unsigned)vsnprintf( buf, sizeof(buf), msg, va ) >= sizeof(buf)) oob(); va_end( va ); perror( buf ); } char * next_arg( char **s ) { char *ret; if (!s || !*s) return 0; while (isspace( (unsigned char) **s )) (*s)++; if (!**s) { *s = 0; return 0; } if (**s == '"') { ++*s; ret = *s; *s = strchr( *s, '"' ); } else { ret = *s; while (**s && !isspace( (unsigned char) **s )) (*s)++; } if (*s) { if (**s) *(*s)++ = 0; if (!**s) *s = 0; } return ret; } #ifndef HAVE_VASPRINTF static int vasprintf( char **strp, const char *fmt, va_list ap ) { int len; char tmp[1024]; if ((len = vsnprintf( tmp, sizeof(tmp), fmt, ap )) < 0 || !(*strp = malloc( len + 1 ))) return -1; if (len >= (int)sizeof(tmp)) vsprintf( *strp, fmt, ap ); else memcpy( *strp, tmp, len + 1 ); return len; } #endif #ifndef HAVE_MEMRCHR void * memrchr( const void *s, int c, size_t n ) { u_char *b = (u_char *)s, *e = b + n; while (--e >= b) if (*e == c) return (void *)e; return 0; } #endif #ifndef HAVE_STRNLEN int strnlen( const char *str, size_t maxlen ) { size_t len; /* It's tempting to use memchr(), but it's allowed to read past the end of the actual string. */ for (len = 0; len < maxlen && str[len]; len++) {} return len; } #endif int starts_with( const char *str, int strl, const char *cmp, int cmpl ) { if (strl < 0) strl = strnlen( str, cmpl + 1 ); return (strl >= cmpl) && !memcmp( str, cmp, cmpl ); } int equals( const char *str, int strl, const char *cmp, int cmpl ) { if (strl < 0) strl = strnlen( str, cmpl + 1 ); return (strl == cmpl) && !memcmp( str, cmp, cmpl ); } void oob( void ) { fputs( "Fatal: buffer too small. Please report a bug.\n", stderr ); abort(); } int nfsnprintf( char *buf, int blen, const char *fmt, ... ) { int ret; va_list va; va_start( va, fmt ); if (blen <= 0 || (unsigned)(ret = vsnprintf( buf, blen, fmt, va )) >= (unsigned)blen) oob(); va_end( va ); return ret; } static void ATTR_NORETURN oom( void ) { fputs( "Fatal: Out of memory\n", stderr ); abort(); } void * nfmalloc( size_t sz ) { void *ret; if (!(ret = malloc( sz ))) oom(); return ret; } void * nfrealloc( void *mem, size_t sz ) { char *ret; if (!(ret = realloc( mem, sz )) && sz) oom(); return ret; } char * nfstrdup( const char *str ) { char *ret; if (!(ret = strdup( str ))) oom(); return ret; } int nfvasprintf( char **str, const char *fmt, va_list va ) { int ret = vasprintf( str, fmt, va ); if (ret < 0) oom(); return ret; } int nfasprintf( char **str, const char *fmt, ... ) { int ret; va_list va; va_start( va, fmt ); ret = nfvasprintf( str, fmt, va ); va_end( va ); return ret; } isync-1.3.0/src/compat/config.c0000644000175000001440000003653513164125173013257 00000000000000/* * isync - mbsync wrapper: IMAP4 to maildir mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2004 Oswald Buddenhagen * * 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, see . */ #include "isync.h" #include #include #include #include #include #include #include #include #include static char * my_strndup( const char *s, size_t nchars ) { char *r = nfmalloc( sizeof(char) * (nchars + 1) ); memcpy( r, s, nchars ); r[nchars] = 0; return r; } char * expand_strdup( const char *s ) { struct passwd *pw; const char *p, *q; char *r; if (*s == '~') { s++; if (!*s) { p = 0; q = Home; } else if (*s == '/') { p = s + 1; q = Home; } else { if ((p = strchr( s, '/' ))) { r = my_strndup( s, (int)(p - s) ); pw = getpwnam( r ); free( r ); p++; } else pw = getpwnam( s ); if (!pw) return 0; q = pw->pw_dir; } nfasprintf( &r, "%s/%s", q, p ? p : "" ); return r; } else if (*s != '/' && xmaildir) { nfasprintf( &r, "%s/%s", xmaildir, s ); return r; } else return nfstrdup( s ); } static int is_true( const char *val ) { return !strcasecmp( val, "yes" ) || !strcasecmp( val, "true" ) || !strcasecmp( val, "on" ) || !strcmp( val, "1" ); } void load_config( const char *path, config_t ***stor ) { config_t **sstor, *cfg; FILE *fp; char *p, *cmd, *val; int line = 0; char buf[1024]; if (!(fp = fopen( path, "r" ))) { if (errno != ENOENT) sys_error( "Cannot read config file '%s'", path ); return; } if (!Quiet && !Debug && !Verbose) printf( "Reading configuration file %s\n", path ); buf[sizeof(buf) - 1] = 0; cfg = &global; while (fgets( buf, sizeof(buf) - 1, fp )) { p = buf; cmd = next_arg( &p ); val = next_arg( &p ); line++; if (!cmd || *cmd == '#') continue; if (!val) { fprintf( stderr, "%s:%d: parameter missing\n", path, line ); continue; } if (!strcasecmp( "Mailbox", cmd )) { if (o2o) break; cfg = **stor = nfmalloc( sizeof(config_t) ); *stor = &cfg->next; memcpy( cfg, &global, sizeof(config_t) ); /* not expanded at this point */ cfg->path = nfstrdup( val ); } else if (!strcasecmp( "OneToOne", cmd )) { if (boxes) { forbid: fprintf( stderr, "%s:%d: keyword '%s' allowed only in global section\n", path, line, cmd ); continue; } o2o = is_true( val ); } else if (!strcasecmp( "Maildir", cmd )) { if (boxes) goto forbid; maildir = nfstrdup( val ); xmaildir = expand_strdup( val ); } else if (!strcasecmp( "Folder", cmd )) { if (boxes) goto forbid; folder = nfstrdup( val ); } else if (!strcasecmp( "Inbox", cmd )) { if (boxes) goto forbid; inbox = nfstrdup( val ); } else if (!strcasecmp( "Host", cmd )) { if (starts_with( val, -1, "imaps:", 6 )) { val += 6; cfg->use_imaps = 1; cfg->port = 993; cfg->use_sslv3 = 1; } cfg->host = nfstrdup( val ); } else if (!strcasecmp( "User", cmd )) cfg->user = nfstrdup( val ); else if (!strcasecmp( "Pass", cmd )) cfg->pass = nfstrdup( val ); else if (!strcasecmp ( "Port", cmd )) cfg->port = atoi( val ); else if (!strcasecmp ( "Box", cmd )) cfg->box = nfstrdup( val ); else if (!strcasecmp ( "Alias", cmd )) { if (!boxes) { fprintf( stderr, "%s:%d: keyword 'Alias' allowed only in mailbox specification\n", path, line ); continue; } cfg->alias = nfstrdup( val ); } else if (!strcasecmp( "MaxSize", cmd )) cfg->max_size = atol( val ); else if (!strcasecmp ( "MaxMessages", cmd )) cfg->max_messages = atol( val ); else if (!strcasecmp ( "UseNamespace", cmd )) cfg->use_namespace = is_true( val ); else if (!strcasecmp ( "CopyDeletedTo", cmd )) cfg->copy_deleted_to = nfstrdup( val ); else if (!strcasecmp ( "Tunnel", cmd )) cfg->tunnel = nfstrdup( val ); else if (!strcasecmp ( "Expunge", cmd )) cfg->expunge = is_true( val ); else if (!strcasecmp( "Delete", cmd )) cfg->delete = is_true( val ); else if (!strcasecmp( "CertificateFile", cmd )) cfg->cert_file = expand_strdup( val ); else if (!strcasecmp( "RequireSSL", cmd )) cfg->require_ssl = is_true( val ); else if (!strcasecmp( "UseSSLv2", cmd )) fprintf( stderr, "Warning: UseSSLv2 is no longer supported\n" ); else if (!strcasecmp( "UseSSLv3", cmd )) cfg->use_sslv3 = is_true( val ); else if (!strcasecmp( "UseTLSv1", cmd )) cfg->use_tlsv1 = is_true( val ); else if (!strcasecmp( "RequireCRAM", cmd )) cfg->require_cram = is_true( val ); else if (buf[0]) fprintf( stderr, "%s:%d: unknown keyword '%s'\n", path, line, cmd ); } fclose( fp ); if (o2o) { if (!global.host && !global.tunnel) { fprintf( stderr, "Neither Host nor Tunnel given to OneToOne. Aborting.\n" ); exit( 1 ); } } else for (sstor = &boxes; (cfg = *sstor); ) { if (!cfg->host && !cfg->tunnel) { fprintf( stderr, "Mailbox '%s' has neither Host nor Tunnel. Skipping.\n", cfg->alias ? cfg->alias : cfg->path ); if (&cfg->next == *stor) *stor = sstor; *sstor = cfg->next; continue; } sstor = &cfg->next; } } static const char * tb( int on ) { return on ? "yes" : "no"; } static const char * quotify( const char *str ) { char *ostr; int i; for (i = 0; str[i]; i++) { if (isspace( str[i] )) { nfasprintf( &ostr, "\"%s\"", str ); return ostr; } } return str; } static void write_imap_server( FILE *fp, config_t *cfg ) { config_t *pbox; char *p, *p2; int hl, a1, a2, a3, a4; char buf[128], ubuf[64]; static int tunnels; /* The old server names determine the derived store names. They are kinda stupid, * but can't be changed, because store names are encoded in state file names. */ if (cfg->tunnel) nfasprintf( (char **)&cfg->old_server_name, "tunnel%d", ++tunnels ); else { if (sscanf( cfg->host, "%d.%d.%d.%d", &a1, &a2, &a3, &a4 ) == 4) hl = nfsnprintf( buf, sizeof(buf), "%s", cfg->host ); else { /* XXX this does not avoid clashes. add port? */ p = strrchr( cfg->host, '.' ); if (!p) hl = nfsnprintf( buf, sizeof(buf), "%s", cfg->host ); else { hl = nfsnprintf( buf, sizeof(buf), "%.*s", p - cfg->host, cfg->host ); p2 = strrchr( buf, '.' ); if (p2) hl = sprintf( buf, "%s", p2 + 1 ); } } if (boxes) /* !o2o */ for (pbox = boxes; pbox != cfg; pbox = pbox->next) if (equals( pbox->old_server_name, -1, buf, hl )) { nfasprintf( (char **)&cfg->old_server_name, "%s-%d", buf, ++pbox->old_servers ); goto gotsrv; } cfg->old_server_name = nfstrdup( buf ); cfg->old_servers = 1; gotsrv: ; } /* The "new" server names determine the names of the accounts themselves. * They are optimized for descriptiveness, e.g. in password prompts. */ if (cfg->user) nfsnprintf( ubuf, sizeof(ubuf), "%s@", cfg->user ); else ubuf[0] = 0; if (!cfg->host) hl = nfsnprintf( buf, sizeof(buf), "%stunnel", ubuf ); else { if (cfg->port != (cfg->use_imaps ? 993 : 143)) hl = nfsnprintf( buf, sizeof(buf), "%s%s_%d", ubuf, cfg->host, cfg->port ); else hl = nfsnprintf( buf, sizeof(buf), "%s%s", ubuf, cfg->host ); } if (boxes) /* !o2o */ for (pbox = boxes; pbox != cfg; pbox = pbox->next) if (equals( pbox->server_name, -1, buf, hl )) { nfasprintf( (char **)&cfg->server_name, "%s-%d", buf, ++pbox->servers ); goto ngotsrv; } cfg->server_name = nfstrdup( buf ); cfg->servers = 1; ngotsrv: ; fprintf( fp, "IMAPAccount %s\n", cfg->server_name ); if (cfg->tunnel) fprintf( fp, "Tunnel \"%s\"\n", cfg->tunnel ); else { if (cfg->use_imaps) fprintf( fp, "Host imaps:%s\n", cfg->host ); else fprintf( fp, "Host %s\n", cfg->host ); fprintf( fp, "Port %d\n", cfg->port ); } if (cfg->user) fprintf( fp, "User %s\n", quotify( cfg->user ) ); if (cfg->pass) fprintf( fp, "Pass %s\n", quotify( cfg->pass ) ); fprintf( fp, "RequireCRAM %s\nRequireSSL %s\n" "UseSSLv3 %s\nUseTLSv1 %s\nUseTLSv1.1 %s\nUseTLSv1.2 %s\n", tb(cfg->require_cram), tb(cfg->require_ssl), tb(cfg->use_sslv3), tb(cfg->use_tlsv1), tb(cfg->use_tlsv1), tb(cfg->use_tlsv1) ); if ((cfg->use_imaps || cfg->use_sslv3 || cfg->use_tlsv1) && cfg->cert_file) fprintf( fp, "CertificateFile %s\n", quotify( cfg->cert_file ) ); fputc( '\n', fp ); } static void write_imap_store( FILE *fp, config_t *cfg ) { if (cfg->stores > 1) nfasprintf( (char **)&cfg->store_name, "%s-%d", cfg->old_server_name, cfg->stores ); else cfg->store_name = cfg->old_server_name; fprintf( fp, "IMAPStore %s\nAccount %s\n", cfg->store_name, cfg->server_name ); if (*folder) fprintf( fp, "Path %s\n", quotify( folder ) ); else fprintf( fp, "UseNamespace %s\n", tb(cfg->use_namespace) ); if (inbox) fprintf( fp, "MapInbox %s\n", quotify( inbox ) ); if (cfg->copy_deleted_to) fprintf( fp, "Trash %s\n", quotify( cfg->copy_deleted_to ) ); fputc( '\n', fp ); } static void write_channel_parm( FILE *fp, config_t *cfg ) { if (cfg->max_size) fprintf( fp, "MaxSize %d\n", cfg->max_size ); if (cfg->max_messages) fprintf( fp, "MaxMessages %d\n", cfg->max_messages ); if (cfg->delete && !global.delete && !delete) fputs( "Sync All\n", fp ); if (cfg->expunge && !global.expunge && !expunge) fputs( "Expunge Both\n", fp ); fputc( '\n', fp ); } static int mstrcmp( const char *s1, const char *s2 ) { if (s1 == s2) return 0; if (!s1 || !s2) return 1; return strcmp( s1, s2 ); } void write_config( int fd ) { FILE *fp; const char *cn, *scn; char *path, *local_box, *local_store; config_t *box, *sbox, *pbox; int pl; if (!(fp = fdopen( fd, "w" ))) { perror( "fdopen" ); return; } fputs( "SyncState *\n", fp ); if (!global.delete && !delete) fputs( "Sync New ReNew Flags\n", fp ); if (global.expunge || expunge) fputs( "Expunge Both\n", fp ); fputc( '\n', fp ); if (o2o) { write_imap_server( fp, &global ); write_imap_store( fp, &global ); fprintf( fp, "MaildirStore local\nPath %s/\n", quotify( maildir ) ); if (!inbox) { /* just in case listing actually produces an INBOX ... */ nfasprintf( (char **)&inbox, "%s/INBOX", maildir ); fprintf( fp, "Inbox %s\n", quotify( inbox ) ); } if (altmap > 0) fputs( "AltMap yes\n", fp ); fprintf( fp, "\nChannel o2o\nMaster :%s:\nSlave :local:\nPattern %%\n", global.store_name ); write_channel_parm( fp, &global ); } else { for (box = boxes; box; box = box->next) { for (pbox = boxes; pbox != box; pbox = pbox->next) { if (box->tunnel) { if (mstrcmp( pbox->tunnel, box->tunnel )) continue; } else { if (mstrcmp( pbox->host, box->host ) || pbox->use_imaps != box->use_imaps || pbox->port != box->port) continue; } if (mstrcmp( pbox->user, box->user ) || mstrcmp( pbox->pass, box->pass )) /* nonsense */ continue; if ((box->use_imaps || box->use_sslv3 || box->use_tlsv1) && mstrcmp( pbox->cert_file, box->cert_file )) /* nonsense */ continue; if (pbox->use_imaps != box->use_imaps || pbox->use_sslv3 != box->use_sslv3 || pbox->use_tlsv1 != box->use_tlsv1) continue; box->server_name = pbox->server_name; for (sbox = boxes; sbox != box; sbox = sbox->next) { if (sbox->server_name != box->server_name || mstrcmp( sbox->copy_deleted_to, box->copy_deleted_to ) || (!*folder && sbox->use_namespace != box->use_namespace)) continue; box->store_name = sbox->store_name; goto gotall; } box->stores = ++pbox->stores; goto gotsrv; } write_imap_server( fp, box ); box->stores = 1; gotsrv: write_imap_store( fp, box ); gotall: path = expand_strdup( box->path ); if (starts_with( path, -1, Home, HomeLen ) && path[HomeLen] == '/') nfasprintf( &path, "~%s", path + HomeLen ); local_store = local_box = strrchr( path, '/' ) + 1; pl = local_store - path; /* try to re-use existing store */ for (pbox = boxes; pbox != box; pbox = pbox->next) if (pbox->local_store_path && equals( pbox->local_store_path, -1, path, pl )) goto gotstor; box->local_store_path = my_strndup( path, pl ); /* derive a suitable name */ if (!strcmp( box->local_store_path, "/var/mail/" ) || !strcmp( box->local_store_path, "/var/spool/mail/" )) { local_store = nfstrdup( "spool" ); } else if (!strcmp( box->local_store_path, "~/" )) { local_store = nfstrdup( "home" ); } else { local_store = memrchr( box->local_store_path, '/', pl - 1 ); if (local_store) { local_store = my_strndup( local_store + 1, pl - 2 - (local_store - box->local_store_path) ); for (pl = 0; local_store[pl]; pl++) local_store[pl] = tolower( local_store[pl] ); } else { local_store = nfstrdup( "local" ); } } /* avoid name clashes with imap stores */ for (pbox = boxes; pbox != box; pbox = pbox->next) if (!strcmp( pbox->store_name, local_store )) { nfasprintf( &local_store, "local_%s", local_store ); goto gotsdup; } gotsdup: /* avoid name clashes with other local stores */ for (pbox = boxes; pbox != box; pbox = pbox->next) if (pbox->local_store_name && !strcmp( pbox->local_store_name, local_store )) { nfasprintf( (char **)&box->local_store_name, "%s-%d", local_store, ++pbox->local_stores ); goto gotdup; } box->local_store_name = local_store; box->local_stores = 1; gotdup: fprintf( fp, "MaildirStore %s\nPath %s\n", box->local_store_name, quotify( box->local_store_path ) ); if (altmap > 0) fputs( "AltMap yes\n", fp ); fputc( '\n', fp ); pbox = box; gotstor: if (box->alias) cn = box->alias; else { cn = strrchr( box->path, '/' ); if (cn) cn++; else cn = box->path; } for (sbox = boxes; sbox != box; sbox = sbox->next) { if (sbox->alias) scn = sbox->alias; else { scn = strrchr( sbox->path, '/' ); if (scn) scn++; else scn = sbox->path; } if (mstrcmp( cn, scn )) continue; nfasprintf( (char **)&box->channel_name, "%s-%d", cn, ++sbox->channels ); goto gotchan; } box->channels = 1; box->channel_name = cn; gotchan: fprintf( fp, "Channel %s\nMaster :%s:%s\nSlave :%s:%s\n", box->channel_name, box->store_name, quotify( box->box ), pbox->local_store_name, quotify( local_box ) ); write_channel_parm( fp, box ); } } fclose( fp ); } config_t * find_box( const char *s ) { config_t *p; char *t; if (starts_with( s, -1, Home, HomeLen ) && s[HomeLen] == '/') s += HomeLen + 1; for (p = boxes; p; p = p->next) { if (!strcmp( s, p->path ) || (p->alias && !strcmp( s, p->alias ))) return p; /* check to see if the full pathname was specified on the * command line. */ t = expand_strdup( p->path ); if (!strcmp( s, t )) { free( t ); return p; } free( t ); } return 0; } isync-1.3.0/src/compat/Makefile.in0000644000175000001440000005270313164125572013711 00000000000000# Makefile.in generated by automake 1.15.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2017 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@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@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 = : bin_PROGRAMS = isync$(EXEEXT) subdir = src/compat 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) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/autodefs.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \ "$(DESTDIR)$(exampledir)" PROGRAMS = $(bin_PROGRAMS) am_isync_OBJECTS = main.$(OBJEXT) config.$(OBJEXT) convert.$(OBJEXT) \ util.$(OBJEXT) isync_OBJECTS = $(am_isync_OBJECTS) am__DEPENDENCIES_1 = isync_DEPENDENCIES = $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(isync_SOURCES) DIST_SOURCES = $(isync_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac 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 = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } man1dir = $(mandir)/man1 NROFF = nroff MANS = $(man_MANS) DATA = $(example_DATA) HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DB_LIBS = @DB_LIBS@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LTLIBOBJS = @LTLIBOBJS@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MKDIR_P = @MKDIR_P@ OBJEXT = @OBJEXT@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ SASL_LIBS = @SASL_LIBS@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SOCK_LIBS = @SOCK_LIBS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ Z_LIBS = @Z_LIBS@ 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@ 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_alias = @build_alias@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host_alias = @host_alias@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ isync_SOURCES = main.c config.c convert.c util.c isync_LDADD = $(DB_LIBS) noinst_HEADERS = isync.h man_MANS = isync.1 exampledir = $(docdir)/examples example_DATA = isyncrc.sample EXTRA_DIST = $(example_DATA) $(man_MANS) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/compat/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --gnu src/compat/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) isync$(EXEEXT): $(isync_OBJECTS) $(isync_DEPENDENCIES) $(EXTRA_isync_DEPENDENCIES) @rm -f isync$(EXEEXT) $(AM_V_CCLD)$(LINK) $(isync_OBJECTS) $(isync_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/config.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/convert.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-exampleDATA: $(example_DATA) @$(NORMAL_INSTALL) @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(exampledir)'"; \ $(MKDIR_P) "$(DESTDIR)$(exampledir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(exampledir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(exampledir)" || exit $$?; \ done uninstall-exampleDATA: @$(NORMAL_UNINSTALL) @list='$(example_DATA)'; test -n "$(exampledir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(exampledir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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 "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$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 $(PROGRAMS) $(MANS) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(exampledir)"; 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: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-binPROGRAMS clean-generic 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 html-am: info: info-am info-am: install-data-am: install-exampleDATA install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am 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 pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-exampleDATA \ uninstall-man uninstall-man: uninstall-man1 .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \ clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic distclean-tags \ distdir dvi dvi-am html html-am info info-am install \ install-am install-binPROGRAMS install-data install-data-am \ install-dvi install-dvi-am install-exampleDATA install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man1 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 pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-binPROGRAMS uninstall-exampleDATA \ uninstall-man uninstall-man1 .PRECIOUS: Makefile # 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: isync-1.3.0/src/compat/isync.10000644000175000001440000002715313164124474013054 00000000000000.ig \" isync - mbsync wrapper: IMAP4 to Maildir mailbox synchronizer \" Copyright (C) 2000-2002 Michael R. Elkins \" Copyright (C) 2002-2004 Oswald Buddenhagen \" \" 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, see . \" .. .TH isync 1 "2010 Feb 7" .. .SH NAME isync - synchronize IMAP4 and Maildir mailboxes .. .SH SYNOPSIS \fBisync\fR [\fIoptions\fR ...] {\fImailbox\fR ...|\fI-a\fR|\fI-l\fR} .. .SH DESCRIPTION \fBisync\fR is a command line application which synchronizes local Maildir mailboxes with remote IMAP4 mailboxes, suitable for use in IMAP-disconnected mode. Multiple copies of the remote IMAP4 mailboxes can be maintained, and all flags are synchronized. .br \fBisync\fR is only a wrapper binary around \fBmbsync\fR to simplify upgrades. It will automatically migrate the UID mapping from previous versions of \fBisync\fR (even before 0.8) to the new format, and transparently call \fBmbsync\fR. If you were using \fBisync\fR version 0.8 or 0.9.x you might want to use \fBmdconvert\fR to convert the mailboxes to the more efficient \fBnative\fR UID storage scheme after migrating them. .br \fBisync\fR is deprecated. Please use the \fB-w\fR option to permanently migrate the configuration and start using \fBmbsync\fR directly. .. .SH OPTIONS .TP \fB-c\fR, \fB--config\fR \fIfile\fR Read configuration from \fIfile\fR. By default, the configuration is read from ~/.isyncrc if it exists. .TP \fB-1\fR, \fB--one-to-one\fR Instead of using the mailbox specifications in ~/.isyncrc, isync will pick up all mailboxes from the local directory and remote folder and map them 1:1 onto each other according to their names. .TP \fB-I\fR, \fB--inbox\fR \fImailbox\fR Exception to the 1:1 mapping created by -1: the special IMAP mailbox \fIINBOX\fR is mapped to the local \fImailbox\fR (relative to the maildir). .TP \fB-a\fR, \fB--all\fR Synchronize all mailboxes (either specified in ~/.isyncrc or determined by the 1:1 mapping). .TP \fB-l\fR, \fB--list\fR Don't synchronize anything, but list all mailboxes and exit. .TP \fB-L\fR, \fB--create-local\fR Automatically create the local Maildir mailbox if it doesn't already exist. .TP \fB-R\fR, \fB--create-remote\fR Automatically create the remote IMAP mailbox if it doesn't already exist. .TP \fB-C\fR, \fB--create\fR Automatically create any mailboxes if they don't already exist. This is simply a combination of -L and -R. .TP \fB-d\fR, \fB--delete\fR Causes \fBisync\fR to propagate message deletions. By default, \fIdead\fR messages are \fBnot\fR deleted. .TP \fB-e\fR, \fB--expunge\fR Causes \fBisync\fR to permanently remove all messages marked for deletion. By default, \fIdeleted\fR messages are \fBnot\fR expunged. .TP \fB-f\fR, \fB--fast\fR Only fetch new messages existing on the server into the local mailbox. Message deletions and flag changes will not be propagated. .TP \fB-h\fR, \fB--help\fR Displays a summary of command line options .TP \fB-p\fR, \fB--port\fR \fIport\fR Specifies the port on the IMAP server to connect to (default: 143 for imap, 993 for imaps) .TP \fB-q\fR, \fB--quiet\fR Suppress informational messages. If specified twice, suppress warning messages as well. .TP \fB-r\fR, \fB--remote\fR \fIbox\fR Specifies the name of the remote IMAP mailbox to synchronize with (Default: INBOX) .TP \fB-s\fR, \fB--host\fR [\fBimaps:\fR]\fIhost\fR Specifies the hostname of the IMAP server .TP \fB-u\fR, \fB--user\fR \fIuser\fR Specifies the login name to access the IMAP server (default: $USER) .TP \fB-P\fR, \fB--pass\fR \fIpassword\fR Specifies the password to access the IMAP server (prompted for by default) .TP \fB-M\fR, \fB--maildir\fR \fIdir\fR Specifies the location for your local mailboxes. .TP \fB-F\fR, \fB--folder\fR \fIfolder\fR/ Specifies the location for your remote mailboxes. .TP \fB-v\fR, \fB--version\fR Displays \fBisync\fR version information. .TP \fB-V\fR, \fB--verbose\fR Enables \fIverbose\fR mode, which displays the IMAP4 network traffic. .TP \fB-D\fR, \fB--debug\fR Enable printing of \fIdebug\fR messages. .TP \fB-w\fR, \fB--write\fR Don't run \fBmbsync\fR, but instead write a permanent config file for it. The UID mappings of all configured mailboxes will be migrated. Note that most command line options that would affect an actual sync operation will be incorporated into the new config file as well; exceptions are --fast and --create[-remote|-local]. The name of the new config file is determined by replacing the last occurrence of "isync" with "mbsync", or appending ".mbsync" if "isync" was not found. .TP \fB-W\fR, \fB--writeto\fR \fIfile\fR Like \fB-w\fR, but use the specified name for the new config file. .. .SH CONFIGURATION \fBisync\fR by default reads \fI~/.isyncrc\fR to load configuration data. Each non-empty line of the configuration file that does not start with a hash mark consists of a command. The following commands are understood: .TP \fBMailbox\fR \fIpath\fR Defines a local Maildir mailbox. All configuration commands following this line, up until the next \fIMailbox\fR command, apply to this mailbox only. .. .TP \fBHost\fR [\fBimaps:\fR]\fIname\fR Defines the DNS name or IP address of the IMAP server. If the hostname is prefixed with \fBimaps:\fR the connection is assumed to be a SSL connection to port 993 (though you can change this by placing a \fBPort\fR command \fBafter\fR the \fBHost\fR command). Note that modern servers support SSL on the default port 143. \fBisync\fR will always attempt to use SSL if available. .. .TP \fBPort\fR \fIport\fR Defines the TCP port number of the IMAP server (Default: 143 for imap, 993 for imaps) .. .TP \fBBox\fR \fImailbox\fR Defines the name of the remote IMAP mailbox associated with the local Maildir mailbox (Default: INBOX) .. .TP \fBUser\fR \fIusername\fR Defines the login name on the IMAP server (Default: current user) .. .TP \fBPass\fR \fIpassword\fR Defines the password for \fIusername\fR on the IMAP server. Note that this option is \fBNOT\fR required. If no password is specified in the configuration file, \fBisync\fR will prompt you for it. .. .TP \fBAlias\fR \fIstring\fR Defines an alias for the mailbox which can be used as a shortcut on the command line. .. .TP \fBCopyDeletedTo\fR \fImailbox\fR Specifies the remote IMAP mailbox to copy deleted messages to prior to expunging (Default: none). .. .TP \fBDelete\fR \fIyes\fR|\fIno\fR Specifies whether message deletions are propagated. (Default: no). \fBNOTE:\fR The \fI-d\fR command line option overrides this setting when set to \fIno\fR. .. .TP \fBExpunge\fR \fIyes\fR|\fIno\fR Specifies whether deleted messages are expunged. (Default: no). \fBNOTE:\fR The \fI-e\fR command line option overrides this setting when set to \fIno\fR. .. .TP \fBMailDir\fR \fIdirectory\fR Specifies the location of your local mailboxes if a relative path is specified in a \fIMailbox\fR command (Default: \fI~\fR). \fBNOTE:\fR This directive is allowed only in the \fIglobal\fR section (see below). .. .TP \fBFolder\fR \fIdirectory\fR/ Specifies the location of your IMAP mailboxes specified in \fIBox\fR commands (Default: \fI""\fR). \fBNOTE:\fR You \fBmust\fR append the hierarchy delimiter (usually a slash) to this specification. \fBNOTE 2:\fR This directive is allowed only in the \fIglobal\fR section (see below). .. .TP \fBMaxMessages\fR \fIcount\fR Sets the number of messages \fBisync\fR should keep in the local copy of a mailbox. This is useful for mailboxes where you keep a complete archive on the server, but want to mirror only the last messages (for instance, for mailing lists). The messages that were the first to arrive in the mailbox (independently of the actual date of the message) will be deleted first. Messages that are flagged (marked as important) and unread messages will not be automatically deleted. If \fIcount\fR is 0, the maximum number of messages is \fBunlimited\fR. (Default: 0) .. .TP \fBMaxSize\fR \fIbytes\fR Messages larger than that many bytes will not be transferred over the wire. This is useful for weeding out messages with large attachments. If \fIbytes\fR is 0, the maximum file size is \fBunlimited\fR. (Default: 0) .. .TP \fBTunnel\fR \fIcommand\fR Specify a command to run to establish a connection rather than opening a TCP socket. This allows you to run an IMAP session over an SSH tunnel, for example. .TP \fBUseNamespace\fR \fIyes\fR|\fIno\fR Selects whether the server's first "personal" NAMESPACE should be prefixed to mailbox names. Disabling this makes sense for some broken IMAP servers. This option is meaningless if a \fIFolder\fR was specified. (Default: \fIyes\fR) .. .TP \fBRequireCRAM\fR \fIyes\fR|\fIno\fR If set to \fIyes\fR, \fBisync\fR will abort the connection if no CRAM-MD5 authentication is possible. (Default: \fIno\fR) .. .TP \fBRequireSSL\fR \fIyes\fR|\fIno\fR \fBisync\fR will abort the connection if a TLS/SSL session cannot be established with the IMAP server. (Default: \fIyes\fR) .. .TP \fBCertificateFile\fR \fIpath\fR File containing additional X.509 certificates used to verify server identities. Directly matched peer certificates are always trusted, regardless of validity. .br Note that the system's default certificate store is always used and should not be specified here. .. .TP \fBUseSSLv2\fR \fIyes\fR|\fIno\fR Should \fBisync\fR use SSLv2 for communication with the IMAP server over SSL? (Default: \fIno\fR) .. .TP \fBUseSSLv3\fR \fIyes\fR|\fIno\fR Should \fBisync\fR use SSLv3 for communication with the IMAP server over SSL? (Default: \fIyes\fR if the imaps port is used, otherwise \fIno\fR) .. .TP \fBUseTLSv1\fR \fIyes\fR|\fIno\fR Should \fBisync\fR use TLSv1.x for communication with the IMAP server over SSL? (Default: \fIyes\fR) .. .TP \fBOneToOne\fR \fBisync\fR will ignore any \fIMailbox\fR specifications and instead pick up all mailboxes from the local \fIMailDir\fR and remote \fIFolder\fR and map them 1:1 onto each other according to their names. \fBNOTE:\fR This directive is allowed only in the \fIglobal\fR section (see below). .. .TP \fBInbox\fR \fImailbox\fR Exception to the OneToOne mapping: the special IMAP mailbox \fIINBOX\fR is mapped to the local \fImailbox\fR (relative to the \fIMailDir\fR). \fBNOTE:\fR This directive is only meaningful in the \fIglobal\fR section (see below). .. .P Configuration commands that appear prior to the first \fBMailbox\fR command are considered to be \fIglobal\fR options which are used as defaults when those specific options are not specifically set for a defined Mailbox. For example, if you use the same login name for several IMAP servers, you can put a \fBUser\fR command before the first \fBMailbox\fR command, and then leave out the \fBUser\fR command in the sections for each mailbox. \fBisync\fR will then use the global value by default. .. .SH FILES .TP .B ~/.isyncrc Default configuration file .. .SH BUGS The configuration file takes precedence over command line options. .br Use -c /dev/null to work around. .P See the \fBINHERENT PROBLEMS\fR section in the \fBmbsync\fR man page, too. .. .SH SEE ALSO mbsync(1), mdconvert(1), mutt(1), maildir(5) .P Up to date information on \fBisync\fR can be found at http://isync.sf.net/ .. .SH AUTHORS Originally written by Michael R. Elkins, currently maintained by Oswald Buddenhagen. isync-1.3.0/src/compat/isyncrc.sample0000644000175000001440000000222313007413620014477 00000000000000# Global configuration section # Values here are used as defaults for any following Mailbox section that # doesn't specify it. # SSL server certificate file CertificateFile ~/.isync.certs # by default, expunge deleted messages (same as -e on command line) Expunge yes # by default delete messages in the local mailbox which no longer exist # on the server Delete yes # copy deleted messages to the IMAP "Trash" folder CopyDeletedTo "Trash" # my default username, if different from the local username User me #Port 143 #Box INBOX # don't download messages larger than 200K bytes MaxSize 200000 ### ### work mailbox ### Mailbox /home/me/Mail/work Host work.host.com Pass xxxxxxxx # define a shortcut so I can just use "isync work" from the command line Alias work # don't auto expunge messages in this box (overridden by -e on command line) Expunge no ### ### personal mailbox ### Mailbox /home/me/Mail/personal Host host.play.com # use a non-default port for this connection Port 6789 Alias personal ### ### Remote mailbox over a SSH tunnel ### Mailbox /home/me/Mail/remote Host host.remote.com Tunnel "ssh -q host.remote.com /usr/sbin/imapd" Alias remote isync-1.3.0/src/compat/convert.c0000644000175000001440000001441213007413620013451 00000000000000/* * isync - mbsync wrapper: IMAP4 to maildir mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2004 Oswald Buddenhagen * * 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, see . */ #include "isync.h" #include #include #include #include #include #include #include #include #include #include static const char *subdirs[] = { "cur", "new", "tmp" }; static const char Flags[] = { 'D', 'F', 'R', 'S', 'T' }; static int parse_info( const char *s ) { unsigned i; int flags; flags = 0; if (s && *(s + 1) == '2' && *(s + 2) == ',') for (s += 3, i = 0; i < as(Flags); i++) if (strchr( s, Flags[i] )) flags |= (1 << i); return flags; } typedef struct { int uid, flags; } msg_t; static int compare_uids( const void *l, const void *r ) { return ((msg_t *)l)->uid - ((msg_t *)r)->uid; } static DBT key, value; static struct flock lck; void convert( config_t *box ) { DIR *d; struct dirent *e; char *s, *p, *mboxdir; FILE *fp; msg_t *msgs; DB *db; int i, ret, fd, uidval, maxuid, uid, rmsgs, nmsgs, uv[2]; unsigned u; struct stat sb; char buf[_POSIX_PATH_MAX], diumname[_POSIX_PATH_MAX], uvname[_POSIX_PATH_MAX], sname[_POSIX_PATH_MAX], iuvname[_POSIX_PATH_MAX], imuname[_POSIX_PATH_MAX], ilname[_POSIX_PATH_MAX], iumname[_POSIX_PATH_MAX]; mboxdir = expand_strdup( box->path ); nfsnprintf( iuvname, sizeof(iuvname), "%s/isyncuidvalidity", mboxdir ); nfsnprintf( diumname, sizeof(iumname), "%s/.isyncuidmap.db", mboxdir ); nfsnprintf( uvname, sizeof(uvname), "%s/.uidvalidity", mboxdir ); if (stat( iuvname, &sb )) { if (!stat( diumname, &sb )) altmap++; else if (!stat( uvname, &sb )) altmap--; err1: free( mboxdir ); return; } for (i = 0; i < 3; i++) { nfsnprintf( buf, sizeof(buf), "%s/%s", mboxdir, subdirs[i] ); if (stat( buf, &sb )) { sys_error( "ERROR: cannot access %s", buf ); fprintf( stderr, "ERROR: '%s' does not appear to be a valid maildir style mailbox\n", mboxdir ); goto err1; } } nfsnprintf( iumname, sizeof(iumname), "%s/isyncuidmap.db", mboxdir ); nfsnprintf( imuname, sizeof(imuname), "%s/isyncmaxuid", mboxdir ); nfsnprintf( ilname, sizeof(ilname), "%s/isynclock", mboxdir ); nfsnprintf( sname, sizeof(sname), "%s/.mbsyncstate", mboxdir ); if ((fd = open( ilname, O_WRONLY|O_CREAT, 0600 )) < 0) { sys_error( "Cannot create %s", ilname ); goto err1; } #if SEEK_SET != 0 lck.l_whence = SEEK_SET; #endif #if F_WRLCK != 0 lck.l_type = F_WRLCK; #endif if (fcntl( fd, F_SETLKW, &lck )) { sys_error( "Cannot lock %s", ilname ); err2: close( fd ); goto err1; } if (!(fp = fopen( iuvname, "r" ))) { sys_error( "Cannot open %s", iuvname ); goto err2; } if (fscanf( fp, "%d", &uidval ) != 1) { sys_error( "Cannot read %s", iuvname ); err3: fclose( fp ); goto err2; } fclose( fp ); if (!(fp = fopen( imuname, "r" ))) { sys_error( "Cannot open %s", imuname ); goto err2; } if (fscanf( fp, "%d", &maxuid ) != 1) { sys_error( "Cannot read %s", imuname ); goto err3; } fclose( fp ); if (!stat( iumname, &sb )) { if (db_create( &db, 0, 0 )) { fputs( "dbcreate failed\n", stderr ); goto err2; } if ((db->open)( db, 0, iumname, 0, DB_HASH, 0, 0 )) { fputs( "cannot open db\n", stderr ); db->close( db, 0 ); goto err2; } altmap++; } else { db = 0; altmap--; } msgs = 0; rmsgs = 0; nmsgs = 0; for (i = 0; i < 2; i++) { nfsnprintf( buf, sizeof(buf), "%s/%s/", mboxdir, subdirs[i] ); if (!(d = opendir( buf ))) { sys_error( "Cannot list %s", buf ); err4: free( msgs ); if (db) db->close( db, 0 ); goto err2; } while ((e = readdir( d ))) { if (*e->d_name == '.') continue; s = strchr( e->d_name, ':' ); if (db) { key.data = e->d_name; key.size = s ? (size_t)(s - e->d_name) : strlen( e->d_name ); if ((ret = db->get( db, 0, &key, &value, 0 ))) { if (ret != DB_NOTFOUND) db->err( db, ret, "Maildir error: db->get()" ); continue; } uid = *(int *)value.data; } else if ((p = strstr( e->d_name, ",U=" ))) uid = atoi( p + 3 ); else continue; if (nmsgs == rmsgs) { rmsgs = rmsgs * 2 + 100; msgs = nfrealloc( msgs, rmsgs * sizeof(msg_t) ); } msgs[nmsgs].uid = uid; msgs[nmsgs++].flags = parse_info( s ); } closedir( d ); } qsort( msgs, nmsgs, sizeof(msg_t), compare_uids ); if (!(fp = fopen( sname, "w" ))) { sys_error( "Cannot create %s", sname ); goto err4; } if (box->max_messages) { if (!nmsgs) i = maxuid; else { i = nmsgs - box->max_messages; if (i < 0) i = 0; i = msgs[i].uid - 1; } } else i = 0; fprintf( fp, "%d:%d %d:%d:%d\n", uidval, maxuid, uidval, i, maxuid ); for (i = 0; i < nmsgs; i++) { fprintf( fp, "%d %d ", msgs[i].uid, msgs[i].uid ); for (u = 0; u < as(Flags); u++) if (msgs[i].flags & (1 << u)) fputc( Flags[u], fp ); fputc( '\n', fp ); } fclose( fp ); if (db) { key.data = (void *)"UIDVALIDITY"; key.size = 11; uv[0] = uidval; uv[1] = maxuid; value.data = uv; value.size = sizeof(uv); if ((ret = db->put( db, 0, &key, &value, 0 ))) { db->err( db, ret, "Maildir error: db->put()" ); goto err4; } db->close( db, 0 ); if (rename( iumname, diumname )) { sys_error( "Cannot rename %s to %s", iumname, diumname ); goto err4; } } else { if (!(fp = fopen( uvname, "w" ))) { sys_error( "Cannot create %s", uvname ); goto err4; } fprintf( fp, "%d\n%d\n", uidval, maxuid ); fclose( fp ); } unlink( iuvname ); unlink( imuname ); close( fd ); unlink( ilname ); free( msgs ); free( mboxdir ); return; } isync-1.3.0/src/compat/isync.h0000644000175000001440000000620413164125173013132 00000000000000/* * isync - mbsync wrapper: IMAP4 to maildir mailbox synchronizer * Copyright (C) 2000-2002 Michael R. Elkins * Copyright (C) 2002-2004 Oswald Buddenhagen * * 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, see . */ #include #include #include #define as(ar) (sizeof(ar)/sizeof(ar[0])) #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) # define ATTR_UNUSED __attribute__((unused)) # define ATTR_NORETURN __attribute__((noreturn)) # define ATTR_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) #else # define ATTR_UNUSED # define ATTR_NORETURN # define ATTR_PRINTFLIKE(fmt,var) #endif #if __GNUC__ >= 7 # define FALLTHROUGH __attribute__((fallthrough)); #else # define FALLTHROUGH #endif typedef struct config { struct config *next; const char *server_name; const char *old_server_name; int servers; int old_servers; char *host; int port; char *user; char *pass; char *tunnel; unsigned int require_cram:1; unsigned int require_ssl:1; unsigned int use_imaps:1; unsigned int use_sslv3:1; unsigned int use_tlsv1:1; char *cert_file; const char *store_name; int stores; const char *local_store_name; const char *local_store_path; int local_stores; char *copy_deleted_to; unsigned int use_namespace:1; const char *channel_name; int channels; const char *alias; const char *box; const char *path; /* path relative to .maildir, or absolute path */ int max_size; unsigned int max_messages; unsigned int expunge:1; unsigned int delete:1; } config_t; extern int Quiet, Verbose, Debug; extern const char *Home; extern int HomeLen; extern config_t global, *boxes; extern const char *maildir, *xmaildir, *folder, *inbox; extern int o2o, altmap, delete, expunge; /* config.c */ void load_config( const char *, config_t *** ); void write_config( int ); char *expand_strdup( const char * ); config_t *find_box( const char * ); /* convert.c */ void convert( config_t * ); /* util.c */ char *next_arg( char ** ); void *nfmalloc( size_t sz ); void *nfrealloc( void *mem, size_t sz ); char *nfstrdup( const char *str ); int nfvasprintf( char **str, const char *fmt, va_list va ); int nfasprintf( char **str, const char *fmt, ... ); int nfsnprintf( char *buf, int blen, const char *fmt, ... ); void sys_error( const char *, ... ); void ATTR_NORETURN oob( void ); #ifndef HAVE_MEMRCHR void *memrchr( const void *s, int c, size_t n ); #endif int starts_with( const char *str, int strl, const char *cmp, int cmpl ); int equals( const char *str, int strl, const char *cmp, int cmpl ); isync-1.3.0/install-sh0000755000175000001440000003546313164125572011602 00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2014-09-12.12; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # 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. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) # $RANDOM is not portable (e.g. dash); use it when possible to # lower collision chance tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 # As "mkdir -p" follows symlinks and we work in /tmp possibly; so # create the $tmpdir first (and fail if unsuccessful) to make sure # that nobody tries to guess the $tmpdir name. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # 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 $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: isync-1.3.0/isync.spec.in0000644000175000001440000000166013007413620012162 00000000000000Summary: Utility to synchronize IMAP mailboxes with local maildir folders Name: isync Version: @VERSION@ Release: 1 License: GPL Group: Applications/Internet Source: @PACKAGE@-@VERSION@.tar.gz URL: http://@PACKAGE@.sf.net/ Packager: Oswald Buddenhagen BuildRoot: /var/tmp/%{name}-buildroot %description isync is a command line utility which synchronizes mailboxes; currently Maildir and IMAP4 mailboxes are supported. New messages, message deletions and flag changes can be propagated both ways. It is useful for working in disconnected mode, such as on a laptop or with a non-permanent internet collection (dIMAP). %prep %setup %build %configure %install rm -rf $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install rm -rf $RPM_BUILD_ROOT%{_docdir}/%{name} %clean rm -rf $RPM_BUILD_ROOT %files %doc AUTHORS COPYING NEWS README TODO ChangeLog src/mbsyncrc.sample src/compat/isyncrc.sample %{_bindir}/* %{_mandir}/man1/* isync-1.3.0/ChangeLog0000644000175000001440000056315313164163467011357 000000000000002017-10-01 12:59 Oswald Buddenhagen * Makefile.am: adjust dist-hook to syntax change in .gitignore don't try to delete files in / ... amends 46e792c3d. 2017-10-01 08:44 Oswald Buddenhagen * Makefile.am, mbsync-get-cert: rename get-cert => mbsync-get-cert to avoid undue namespace pollution. inspired by debian. 2017-04-09 08:40 Oswald Buddenhagen * src/sync.c: make sync records with stray TUID non-fatal while the situation indicates an internal error, it is harmless in itself. also, printing some more information may help identify the problem. 2017-08-11 07:20 Oswald Buddenhagen * src/: compat/config.c, compat/isync.h, compat/main.c, drv_imap.c, mbsync.1, socket.c, socket.h: prune SSL 2 support OpenSSL actually did that a while ago already, so this was dead code. 2017-10-01 08:40 Oswald Buddenhagen * src/drv_maildir.c: another fix for -Wimplicit-fallthrough (new on master) 2017-09-23 10:52 Oswald Buddenhagen * Makefile.am: update debian packaging 2017-09-23 10:32 Alessandro Ghedini * src/drv_imap.c: Fix spelling of error messages 2017-10-01 08:04 Oswald Buddenhagen * src/: common.h, compat/isync.h, compat/main.c, main.c, socket.c: fixes for -Wimplicit-fallthrough 2017-10-01 06:15 Oswald Buddenhagen * configure.ac: bump version 2017-08-19 11:22 Helmut Grohne * configure.ac: use autoconf's built-in pkg-config support for OpenSSL the hand-crafted suppport did not work with cross-builds. 2017-08-11 06:50 Oswald Buddenhagen * src/: compat/config.c, compat/isync.1, drv_imap.c, mbsync.1: enable TLS 1.1 and 1.2 by default there is no reason not to, and debian even disabled 1.0 globally, because it's (theoretically) too insecure in some contexts (BEAST attack). in the compat wrapper, the UseTLSv1 option has been re-interpreted as v1.x, to avoid adding new options. 2017-08-05 18:28 Oswald Buddenhagen * configure.ac: bump version 2017-08-05 18:24 Oswald Buddenhagen * src/mbsync.1: mention the need for renaming Maildir files upon move mu4e config line offered by Ben Maughan . 2017-07-30 16:37 Oswald Buddenhagen * src/socket.c: fix spurious decompression errors while that's just bad api, inflate() can return Z_BUF_ERROR during normal operation. contrary to the zpipe example and what the documentation implies, deflate() actually isn't that braindead. add respective comments. REFMAIL: CALA3aExMjtRL0tAmgUANpDTnn-_HJ0sYkOEXWzoO6DVaiNFUHQ@mail.gmail.com 2017-07-30 11:47 Oswald Buddenhagen * src/socket.c: improve zlib error reporting zlib is not exactly thorough about always populating z_stream->msg, so fall back to the error code if necessary. 2017-06-21 07:33 Patrick Steinhardt * src/socket.c: socket: use next addrinfo if opening socket fails The `socket_connect_one` function previously did an `exit(1)` when encountering any errors with opening the socket. This would break connecting to a host where multiple possible addrinfos are returned, where the leading addrinfos are in fact impossible to connect to. E.g. with a kernel configured without support for IPv6, the `getaddrinfo` call may still return a hint containing an IPv6 address alongside another hint with an IPv4 address. Creating the socket with the IPv6 address, which will cause an error, lead us to exiting early without even trying remaining hints. While one can argue that the user should have compiled without HAVE_IPV6 or used an appropriate DNS configuration, we can do better by simply skipping over the current addrinfo causing an error. To do so, we split out a new function `socket_connect_next`, which selects the next available address info and subsequently calls `socket_connect_one` again. When no hints remain, `sock_connect_one` will error out at that point. 2017-05-14 07:42 Oswald Buddenhagen * Makefile.am: fix 'make log' with non-default git config format.pretty suggested by Aaron Jensen . REFMAIL: CAHyO48z0DcoFPC8rCNAL38oxVQtZNKifVd-NEF3sp1EfR-GgxQ@mail.gmail.com 2017-05-14 07:37 Oswald Buddenhagen * src/drv_maildir.c: fix build without BDB amends 83ebe902. REFMAIL: CAHyO48z0DcoFPC8rCNAL38oxVQtZNKifVd-NEF3sp1EfR-GgxQ@mail.gmail.com 2017-03-21 19:05 Oswald Buddenhagen * src/: common.h, driver.h, drv_imap.c, drv_maildir.c, drv_proxy.c, sync.c, util.c: make UIDs unsigned complies with the IMAP spec, thus removing the (not really) arbitrary limitation to INT_MAX for UIDs. 2017-04-02 15:21 Oswald Buddenhagen * src/sync.c: delay assignment of TUID when propagating messages go back to assigning TUIDs only right before actually propagating them. this avoids spurious "TUID lost" warnings. 2017-03-11 12:20 Oswald Buddenhagen * src/: driver.h, drv_imap.c, run-tests.pl, sync.c: move away from magic UIDs in the sync state the only legitimate "deviant" UID is zero, meaning "no message". this can be futher qualified by additional flags in the sync record, rather than using magic values for the UID. in fact, the zero UID (so far meaning only "expunged") was already optionally qualifed with "expired". as a side effect, driver->store_msg() now returns 0 instead of -2 for unknown UIDs. this was a hack to avoid translating the value later on, but it made the api horrible, and now it's superflous in the first place. 2017-04-01 15:02 Oswald Buddenhagen * src/sync.c: split off ephemeral sync record state to a separate member this allows us to simplify logging of expiration, as we now can just log the entire persistent state instead of fiddling with bits. 2017-03-19 10:53 Oswald Buddenhagen * src/: common.h, main.c, run-tests.pl, sync.c: autotest: implement much more thorough resumption verification the test will now make a test run for every journaled step, both right before and right after the logging. 2017-03-29 11:43 Oswald Buddenhagen * src/run-tests.pl: autotest: pre-assign all UIDs of the test messages this ensures stable results when the boxes are used with different OPEN_FLAGS (which will happen in a subsequent commit), at the negligible cost of removing the implicit test of the maildir driver's ability to enumerate new messages. 2017-04-02 12:57 Oswald Buddenhagen * src/: .gitignore, Makefile.am, common.h, driver.h, drv_imap.c, drv_maildir.c, drv_proxy.c, drv_proxy_gen.pl, main.c, mbsync.1, sync.c: introduce driver call debugging do that by wrapping the actual stores into proxies. the proxy driver's code is auto-generated from function templates, some parameters, and the declarations of the driver functions themselves. attempts to do it with CPP macros turned out to be a nightmare. 2017-03-24 18:24 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, sync.c: let driver_t::openbox_box() return the UID validity ... and make 'uidvalidity' private to the drivers. 2017-01-29 14:39 Oswald Buddenhagen * src/: driver.h, sync.c: use a #define for invalid UIDVALIDITY 2017-03-24 17:43 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, sync.c: introduce get_uidnext() driver callback ... and make 'uidnext' private to the imap driver. 2017-03-26 16:44 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, sync.c: let driver_t::find_new_msgs() return the list of messages consistently with driver_t::load_box(). 2017-03-24 17:09 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, sync.c: let driver_t::load_box() return the list of messages ... and make 'msgs', 'count', and 'recent' private to the drivers. 2017-03-24 16:44 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, main.c: let driver_t::list_store() return the list of boxes ... and make 'boxes' and 'listed' private to the drivers. 2017-03-24 16:00 Oswald Buddenhagen * src/drv_imap.c: factor out transform_refcounted_msg_response() the missing cross of transform_refcounted_box_response() and transform_msg_response(). 2017-03-24 15:56 Oswald Buddenhagen * src/drv_imap.c: make struct imap_cmd_refcounted_state "abstract" take the callback out of it, so it can be individualized. so far, this only increases code size ... 2017-03-24 14:29 Oswald Buddenhagen * src/main.c: don't mess with the driver's mailbox list from outside the api specifies that the list remains owned by the driver, so poking around in it is ugly and risky. 2017-03-24 13:18 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, sync.c: make driver_t::prepare_load_box() return the final options ... and make 'opts' private to the drivers. 2017-03-24 13:06 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, sync.c: introduce get_box_path() driver callback ... and make 'path' private to the maildir driver. 2017-03-21 18:27 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, main.c, sync.c: make set_bad_callback() a proper driver_t entry ... and make the pointers private to the drivers. 2017-03-19 12:50 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, drv_proxy.c, main.c, sync.c: provide a proper getter callback for driver capabilities that way driver_t contains only callbacks. 2017-03-19 12:46 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, main.c, sync.c: prepend "get_" to getters in driver_t this makes it callbacks consistently start with a verb. 2017-04-02 12:04 Oswald Buddenhagen * src/: run-tests.pl, sync.c: rewrite tracking of highest expired UID so far, we tracked the slave side, and calculated the master side on the fly. that complicated things unnecessarily. 2017-03-10 16:40 Oswald Buddenhagen * src/sync.c: streamline syncing of old entries the order of the conditionals was purely historical (pre 4ec56f8cf, anno 2005) and hard to follow, as were the comments. 2017-01-29 14:00 Oswald Buddenhagen * src/sync.c: sort uid exception list in a smarter place do it closer to where it is populated. that way the debug output is sorted, and we don't sort the list if it's known to be empty. 2017-01-28 18:19 Oswald Buddenhagen * src/drv_imap.c: add fallbacks for determining UIDNEXT if the server sends no UIDNEXT, do an initial FETCH to query the UID of the last message. same if the server sends no APPENDUID. this allows us to remove the arbitrary limitation of the UID range to INT_MAX, at the cost of additional round-trips. 2017-03-21 17:46 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, main.c: fix repeated listing of same Store with different flags multiple Channels can call driver_t::list_store() with different LIST_* flags. assuming the flags are actually taken into consideration, using a single boolean 'listed' flag to track whether the Store still needs to be listed obviously wouldn't cut it - if INBOX does not live right under Path and the Channels used entirely disjoint Patterns (say, * and INBOX*), the second Channel in a single run (probably a Group) would fail to match anything. to fix this, make store_t::listed more granular. this also requires moving its handling back into the drivers (thus reverting c66afdc0), because the actually performed queries and their possible implicit results are driver-specific. note that this slightly pessimizes some cases - e.g., an IMAP Store with Path "" will now list the entire namespace even if there is only one Channel with Pattern "INBOX*" (because a hypothetical Pattern "*" would also include INBOX*, and the queries are kept disjoint to avoid the need for de-duplication). this isn't expected to be a problem, as listing mailboxes is generally cheap. 2017-03-21 14:12 Oswald Buddenhagen * src/drv_maildir.c: factor out listing Maildir++ Stores Maildir++ is sufficiently different from the other SubFolder styles to justify a separate function; the resulting code duplication is minimal, but the separated functions are a lot clearer. 2017-03-21 13:39 Oswald Buddenhagen * src/drv_maildir.c: fix exclusion of bogus "INBOX.*" folders in Maildir++ this also adds code which avoids that the message about excluding the mailbox is printed multiple times - this could happen with Maildir++, as the hierarchy is flattened. amends 0f24ca31b. 2017-03-19 19:21 Oswald Buddenhagen * src/drv_maildir.c: make "Patterns *" match INBOX* in Maildir++ Stores this also has the side effect that we won't fail to include INBOX itself when Inbox is nested under Path when using other SubFolder styles (regression introduced with Maildir++ support in 0f24ca31b). REFMAIL: 1489492069.2148187.910409864.7727F9FC@webmail.messagingengine.com 2017-03-19 17:08 Oswald Buddenhagen * src/main.c: make help screen print some more compile time options 2017-03-04 11:47 Oswald Buddenhagen * src/drv_imap.c: de-obfuscate cmd_sendable() split the monster conditional and add comments. 2017-03-30 17:39 Oswald Buddenhagen * src/: drv_imap.c, run-tests.pl: add comments 2017-03-30 18:04 Oswald Buddenhagen * src/sync.c: fix sync resumption with aborted entries we need a separate log entry type which does proper mmaxxuid tracking. while moving code around, this also removes a redundant debug statement. amends b1842617. 2017-03-30 17:57 Oswald Buddenhagen * src/sync.c: remove nonsensical statement from journal replay of aborted entries at this stage, entries cannot possibly have messages assigned to them, so trying to unlink them makes no sense. amends b1842617. 2017-03-30 17:48 Oswald Buddenhagen * src/sync.c: fix sync resumption with re-newed messages the UID of the entries needs to be bumped from -1 to -2, as otherwise the resumed run would see a TUID in a sync entry which may not have one. 2017-03-30 17:44 Oswald Buddenhagen * src/sync.c: don't emit redundant flag updates for re-newed messages 2017-03-19 10:35 Oswald Buddenhagen * src/sync.c: fix maxuid tracking newmaxuid represents the highest UID for which a sync entry was created, while maxuid represents the end of the range which is guaranteed to have been propagated. that means that the former needs to be instantly incremented (and logged), while the latter must not be touched until the entire new message sync completes. this matters particularly in the case of resuming an interrupted run, where sync entry creation must resume exactly where it left off, while loading the box must use the old limit to ensure that all messages are available for actual propagation. 2017-03-31 10:39 Oswald Buddenhagen * src/sync.c: de-duplicate journal replay somewhat we've been using indices to separate master/slave state for a long time, so there is no point in using pairs of matching brackets to signify the side in the journal. instead, use somewhat descriptive letters (S[een], F[ind], T[rashed]) and the index itself. 2017-04-02 13:42 Oswald Buddenhagen * src/: common.h, config.h, drv_imap.c, drv_maildir.c, socket.h, tst_timers.c: use typedefs for structs more makes the code more compact (and consistent, as typedefs were already used in some places). 2017-04-02 13:24 Oswald Buddenhagen * src/sync.c: factor out jFprintf() 2017-03-29 13:14 Oswald Buddenhagen * src/sync.c: fix signedness of 'nex' variables they are derived from srec->status, which is unsigned. for not understood reasons, the compiler complains only after extending status to a full unsigned int. on the way, localize the declarations. 2017-04-02 10:03 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c: don't use strncpy() to copy TUIDs latest since 77acc268, the code prior to these statements ensures that the full length is available, so just use memcpy(). the code for comparing TUIDs uses memcmp() anyway. 2017-03-26 19:06 Oswald Buddenhagen * src/run-tests.pl: autotest: improve valgrind integration introduce recognition of $USE_VALGRIND to run all mbsync invocations through valgrind. this also removes the seemingly purposeless --log-fd=3 indirection. 2017-03-29 14:31 Oswald Buddenhagen * src/run-tests.pl: autotest: write logs to files they can get long, and having actual files also helps with diffing. 2017-03-29 14:24 Oswald Buddenhagen * src/run-tests.pl: autotest: factor out readfile() function 2017-03-14 13:52 Oswald Buddenhagen * src/run-tests.pl: autotest: de-duplicate error reporting paths 2017-03-14 13:44 Oswald Buddenhagen * src/run-tests.pl: autotest: print consistent information for journal replay failures 2017-03-14 13:20 Oswald Buddenhagen * src/run-tests.pl: autotest: don't print expected result if the mbsync run itself fails there isn't an actual result to compare with anyway. 2017-03-31 11:16 Oswald Buddenhagen * src/run-tests.pl: autotest: de-duplicate: use print*() in show*() this actually adds some (minimal) transformation overhead, but it makes the relationship clearer. 2017-03-14 14:01 Oswald Buddenhagen * src/run-tests.pl: autotest: determine path of mbsync prior to chdir() that allows tmp/ to be a symlink to a ramdisk. 2017-03-14 10:10 Oswald Buddenhagen * src/run-tests.pl: autotest: use warnings 2017-03-14 10:09 Oswald Buddenhagen * src/run-tests.pl: autotest: remove stray close() call from printstate() 2017-03-11 12:27 Oswald Buddenhagen * src/sync.c: don't populate sync record map with invalid UIDs this would obviously just bloat the hash with nonsense, slowing down the actual lookup later. 2017-02-15 10:45 Oswald Buddenhagen * src/run-tests.pl: fix mislabeling of test 2017-01-28 17:26 Oswald Buddenhagen * src/drv_imap.c: make -DN print also the sent data 2017-02-15 16:25 Oswald Buddenhagen * src/drv_imap.c: don't arbitrarily limit UIDs to a billion, part 2 imap_find_new_msgs() had the same fixed limit as imap_load_box(). amends 815822d8. 2016-12-18 19:50 Oswald Buddenhagen * README, src/driver.c, src/driver.h, src/drv_imap.c, src/drv_maildir.c, src/mbsync.1, src/sync.c: implement Message-Id based UIDVALIDITY recovery 2016-12-18 20:22 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, sync.c: don't fetch message size unless necessary when syncing flags but not re-newing non-fetched messages, there is no need to query the message size for all messages, as the old ones are queried only for their flags. 2016-11-06 16:26 Oswald Buddenhagen * src/drv_maildir.c: some reshuffling in maildir_scan() for clarity 2016-12-18 20:24 Oswald Buddenhagen * src/drv_imap.c: make fetching of partial UID ranges more flexible instead of a single hard-coded branch, use a generic method to split ranges as needed. this is of course entirely over-engineered as of now, but subsequent commits will make good use of it. 2016-11-05 17:33 Oswald Buddenhagen * src/sync.c: factor out app_cr 2016-11-05 17:33 Oswald Buddenhagen * src/sync.c: factor out copy_msg_convert() 2016-11-05 17:32 Oswald Buddenhagen * src/sync.c: factor out copy_msg_bytes() 2016-12-29 13:34 Oswald Buddenhagen * src/: common.h, drv_imap.c: make more use of strnlen() includes adding the so far superfluous prototype for the replacemnt to common.h. 2016-12-29 14:08 Oswald Buddenhagen * src/util.c: make use of memchr() in strnlen() replacement after all turns out the comment advising against it was bogus - unlike for memcmp(), the standard does indeed prescribe that the memchr() implementation may not read past the first occurrence of the searched char. 2016-12-29 14:06 Oswald Buddenhagen * src/util.c: adjust return type of strnlen() replacement it doesn't really matter, but it's nicer to stay consistent with the official prototype. 2016-12-29 13:10 Oswald Buddenhagen * src/: driver.h, sync.c: standardize on 'int' for message sizes that's what the sources already assumed anyway. size_t is total overkill, as No Email Ever (TM) will exceed 2GiB. this also fixes a harmless format string warning in 32 bit builds. 2016-11-13 21:20 Oswald Buddenhagen * src/sync.c: print actually read TUID in debug message 2016-11-13 21:19 Oswald Buddenhagen * src/sync.c: null-terminate lines read from state file & journal makes the subsequent code less convoluted. 2016-11-06 16:23 Oswald Buddenhagen * src/common.h: mark string_list_t as packed otherwise we'll regularly over-allocate due to the struct's stride. 2016-12-18 20:52 Oswald Buddenhagen * src/: common.h, sync.c, util.c: make more use of shifted_bit() technically, this introduces a redundant AND, but the compiler is smart enough to prove that (((A & M) ^ B) & M) == ((A ^ B) & M). 2016-11-06 16:22 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c: make more use of nfstrndup() 2016-11-12 13:15 Oswald Buddenhagen * src/mbsync.1: document some additional uses for PipelineDepth 2016-12-11 11:09 Oswald Buddenhagen * src/util.c: silence bogus [-Wmaybe-uninitialized] with -O0/-O1/-Os 2016-12-04 10:23 Oswald Buddenhagen * src/drv_imap.c: accept NAMESPACE responses without hierarchy delimiter RFC2342 states that the delimiter may be NIL, which some servers apparently actually make use of. REFMAIL: CAM0xXk_FQ83CPrd37iQCMKtc1B2P8=u-r5jX0n2WE5Y+3483nQ@mail.gmail.com 2016-12-04 10:14 Oswald Buddenhagen * src/drv_imap.c: validate NAMESPACE response earlier ... and don't silently fail later on. 2016-12-03 18:18 Oswald Buddenhagen * src/drv_imap.c: inform user if LOGIN was skipped because of missing SSL 'AuthMechs *' technically includes LOGIN, so it is a bit unintuitive when it's still not used. 2016-12-03 19:00 Oswald Buddenhagen * src/drv_imap.c: make * not match LOGIN even in non-SSL builds this is consistent with the plain text transmission warning below. 2016-12-03 19:58 Oswald Buddenhagen * src/drv_imap.c: be more helpful when no SASL mechanisms are available 2016-12-03 19:58 Oswald Buddenhagen * src/drv_imap.c: fix LOGIN in SASL builds if AuthMechs includes more than just LOGIN and the server announces any AUTH= mechanism, we try SASL. but that can still fail to find any suitable authentication mechanism, and we must not error out in that case if we are supposed to fall back to LOGIN. 2016-12-03 13:32 Oswald Buddenhagen * src/drv_imap.c: fix LOGIN in non-SASL builds specifically, if AuthMechs included more than just LOGIN (which would be the case for '*') and the server announced any AUTH= mechanism, we'd immediately error out upon seeing it, thus failing to actually try LOGIN. 2016-11-20 10:47 Oswald Buddenhagen * src/drv_imap.c: don't arbitrarily limit UIDs to a billion the number was chosen to make queries more comprehensible when the server sends no UIDNEXT, but it appears that such insanely large UIDs actually show up in the wild. so send 32-bit INT_MAX instead. note that this is again making an assumption: that no server uses unsigned ints for UIDs. but we can't sent UINT_MAX, as that would break with servers which use signed ints. also, *we* use signed ints (which is actually a clear violation of the spec). it would be possible to special-case the range [1,inf] to 1:*, thus entirely removing arbitrary limits. however, when the range doesn't start at 1, we may actually get a single message instead of none due to the imap uid range limits being unordered. this gets really nasty when we need to issue multiple queries, as we may list the same message twice. a reliable way around this would be issuing a separate query to find the actual value of UID '*', to make up for the server not sending UIDNEXT in the first place. this would obviously imply an additional round-trip per mailbox ... 2016-11-04 20:23 Oswald Buddenhagen * src/sync.c: wrap message trashing into simple transactions trashing many messages at once inevitably overtaxes m$ exchange, and the connection breaks. without any progress tracking, it would restart from scratch each time, which would lead to a) it never finishing and b) many copies of the messages in the trash. full transactions as we do for "proper" syncing would be over the top, as it's not *that* bad if some messages get duplicated in the trash. so we record only the messages for which trashing completed, thus allowing some overlap between the attempts. 2016-11-05 17:16 Oswald Buddenhagen * src/sync.c: use a temporary for sanity 2016-11-04 20:09 Oswald Buddenhagen * src/: common.h, drv_imap.c, drv_maildir.c, sync.c, util.c: pre-sort exception list passed to driver->load_box() ... and use that to optimize the maildir driver somewhat. 2016-11-04 20:48 Oswald Buddenhagen * configure.ac, src/common.h, src/driver.h, src/drv_imap.c, src/drv_maildir.c, src/sync.c, src/util.c: abstract growable arrays somewhat ... and sneak in a C99 requirement on the way. just because. 2016-11-04 15:21 Oswald Buddenhagen * src/: drv_maildir.c, mbsync.1: fix SubFolders style Maildir++ turns out i misread the spec in a subtle way: while all other folders are physically nested under INBOX, the IMAP view puts them at the same (root) level. to get them shown as subfolders of INBOX, they need to have _two_ leading dots. this also implies that the Maildir++ mode has no use for a Path, so reject attempts to specify one. 2016-07-24 09:58 Oswald Buddenhagen * src/socket.c: fix build with openssl 1.1 they finally made their structs opaque, and provided proper getters. 2016-07-24 09:58 Oswald Buddenhagen * src/socket.c: prune obsolete #include hmac.h was needed only for the cram-md5 implementation. 2016-05-21 11:08 Oswald Buddenhagen * src/socket.c: fix server certificate validation error reporting use the right function to decode the error code. found by Andrés Ramírez . 2015-11-08 11:19 Oswald Buddenhagen * .gitignore, src/.gitignore, src/compat/.gitignore: improve .gitignore files - add missing entries - remove redundant entries which are inherited from parent dirs - mark dirctories as such - anchor specific files 2015-11-06 07:29 Oswald Buddenhagen * src/: compat/isync.1, compat/isyncrc.sample, mbsyncrc.sample: fix CertificateFile docs & samples the mbsync manual says explicitly that the system's default certificate store should *not* be specified. however, the isync manual talked about CA certificates, which is (and always was) exactly wrong. also adjust both .sample rc files. 2015-09-27 10:13 Oswald Buddenhagen * src/socket.c: don't crash when dns lookup fails (ipv6 path) we call socket_connect_bail() when getaddrinfo() failed, so it must deal with no addrinfo being there yet. 2015-09-27 09:47 Oswald Buddenhagen * src/drv_maildir.c: remove legacy (bsd-style) locking flock() may be implemented via fcntl(), which may cause the process to deadlock itself when trying to apply both types of locks. this is the case even on linux when the file lives on NFS. it's unlikely that anything except mbsync would try to access the .uidvalidity files anyway, so there is no point in trying to be compatible with anything else ... REFMAIL: uddy4g589ym.fsf@eismej-u14.spgear.lab.emc.com 2015-09-06 20:56 Oswald Buddenhagen * src/drv_imap.c: don't attempt to issue LOGOUT on bad stores amends 9d22641b. 2015-09-06 19:02 Oswald Buddenhagen * src/socket.c: de-duplicate cleanup of name-related data in error paths "name" being both the ipv6 dns info and our own socket label. sort-of amends 9d22641b. 2015-09-07 10:23 Oswald Buddenhagen * README, src/mbsync.1: mention safety of concurrent access; wording improvements 2015-09-01 12:21 Oswald Buddenhagen * src/: common.h, drv_imap.c, sync.c, util.c: tolerate case changes in X-TUID header name it is legal for an email system to simply change the case of rfc2822 headers, and at least one imap server apparently does just that. this would lead to us not finding our own header, which is obviously not helpful. REFMAIL: CA+fD2U3hJEszmvwBsXEpTsaWgJ2Dh373mCESM3M0kg3ZwAYjaw@mail.gmail.com 2015-08-08 17:45 Anton Khirnov * src/: drv_imap.c, mbsync.1, socket.c, socket.h: add support for sending a TLS client certificate 2015-07-18 16:17 Oswald Buddenhagen * configure.ac: fix configure for static libdb, libnsl, and libsocket the right variable to put libraries into is LIBS, not LDFLAGS. REFMAIL: CAABPU68s3uy0Gv-vfAGzeNn0s5Ow--+p+y8W7xE7US_7iXpdjw@mail.gmail.com 2015-05-24 16:20 Oswald Buddenhagen * README: mention m$ exchange MOVE workaround in compat section 2015-05-24 16:20 Oswald Buddenhagen * README: list more deps (sasl and zlib) 2015-05-24 16:20 Oswald Buddenhagen * README: less technical info no point in listing IMAP extensions in the README 2015-05-23 09:06 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, main.c: make it possible to specifiy Pattern INBOX* with no Path defined that pattern may very well expand to INBOXNOT, which would naturally live under Path, so we need to look into the Path. of course, this actually makes sense only if there *is* a Path, and complaining about it being absent is backwards. 2015-05-23 08:47 Oswald Buddenhagen * src/drv_imap.c: remove support for multi-char imap path delimiters again the idea that this is even possible was based on an incomplete reading of the imap spec. however, the infrastructure for supporting multi-char delimiters as such is retained, as the Flatten option can be used with them. 2015-05-24 09:37 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, main.c, socket.c: make server connection a cancellable operation this entails splitting drv->open_store() into alloc_store() and connect_store(). 2015-05-17 14:28 Oswald Buddenhagen * src/drv_maildir.c: validate Path earlier we cannot know whether it will be needed later, but we can validate it if it's set. 2015-05-17 10:06 Oswald Buddenhagen * src/: main.c, sync.h: prune dead SYNC_FAIL_ALL define 2015-05-17 15:07 Oswald Buddenhagen * src/drv_imap.c: don't make bogus attempts at enabling compression recycling server connections skips everything up to setting up the prefix (Path/NAMESPACE). "everything" should obviously include enabling compression, as that must be done at most once per connection. 2015-05-09 16:00 Oswald Buddenhagen * configure.ac: bump version 2015-05-09 15:44 Oswald Buddenhagen * src/drv_imap.c: rename misnamed functions concerning sending imap commands cmd_submittable() => cmd_sendable() cancel_submitted_imap_cmds() => cancel_sent_imap_cmds() the sequence is exec -> submit -> send. 2015-05-09 17:18 Oswald Buddenhagen * src/: drv_imap.c, socket.c, socket.h: ensure direct exit after calling back any structures may be invalid after callback invocation. this has the side effect that the socket write callback now returns void, like all other callbacks do. 2015-05-09 17:17 Oswald Buddenhagen * src/: drv_imap.c, socket.c, socket.h: fix socket_write() recursion the synchronous writing to the socket would have typically invoked the write callback, which would flush further commands, thus recursing. we take the easy way out and make it fully asynchronous, i.e., no data is sent before (re-)entering the event loop. this also has the effect that socket_write() cannot fail any more, and any errors will be reported asynchronously. this is consistent with socket_read(), and produces cleaner code. this introduces a marginal performance regression: the maildir driver is synchronous, so all messages (which fit into memory) will be read before any data is sent. this is not considered relevant. 2015-05-09 15:12 Oswald Buddenhagen * src/drv_imap.c: fix #ifdefs around AuthMech & RequireCRAM these options don't depend on HAVE_LIBSSL. 2015-05-09 15:06 Oswald Buddenhagen * src/drv_imap.c: mask AUTHENTICATE PLAIN commands in error output as well amends bd0f3af5. 2015-05-02 16:59 Felix Janda * configure.ac: Add configure option for zlib 2015-05-08 08:20 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1: add DisableExtension option to work around (server) bugs 2015-05-01 17:16 Oswald Buddenhagen * src/: drv_maildir.c, mbsync.1, mbsyncrc.sample, sync.c: support verbatim and real Maildir++ subfolder naming styles the legacy style is a poorly executed attempt at Maildir++, so introduce the latter for the sake of completeness. but most users will probably just want to use subfolders without any additional dots. 2015-05-01 15:29 Oswald Buddenhagen * src/drv_maildir.c: make maildir_list_recurse() recursion less convoluted move the unconditional addition of INBOX out ouf the function. this makes it possible to move the folder check and addition to the listing before the recursion, which seems clearer. 2015-05-01 11:19 Oswald Buddenhagen * src/drv_maildir.c: pass a maildir_store_conf_t to maildir_validate_path() casting early on makes the code clearer. 2015-05-01 18:19 Oswald Buddenhagen * src/main.c: make flags in pattern debugging non-cumulative 2015-05-01 16:39 Oswald Buddenhagen * src/mbsync.1: use \fB and \fI consistently, take 2 \fB means literal, while \fI means placeholder, value for placeholder, or emphasis. 2015-05-01 09:55 Oswald Buddenhagen * README, configure.ac: fix consistent misspelling of Berkeley 2015-05-01 09:48 Oswald Buddenhagen * README, configure.ac: the minimum required bdb version is in fact 4.1 this is the one that introduced the transaction argument to db->open(). 2015-05-01 09:45 Oswald Buddenhagen * configure.ac: make the bdb check actually check for a linkable library it only checked whether the header is compilable. amends e1d0ea8a1. 2015-04-26 18:54 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, main.c: make skipping of failed stores more thorough in the case of imap stores, the failure is bound to the server config, not just the store config. that means that the storage of the failure state needs to be private to the driver, accessible only through a function. 2015-04-06 14:49 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1, socket.c, socket.h: add socket timeout handling 2015-04-26 16:15 Oswald Buddenhagen * src/util.c: remove caching of current time it's too hard to reliably predict when invalidation will be necessary. 2015-04-26 16:34 Oswald Buddenhagen * src/util.c: don't get system time when dealing with null timers they fire immediately regardless of wall time, so we can save some pointless syscalls. 2015-04-26 10:07 Oswald Buddenhagen * src/main.c: fix -DN not implying -Dn 2015-04-18 09:46 Oswald Buddenhagen * src/drv_maildir.c: make it possible to nest maildir Path under Inbox simply make the code symmetrical to the inverse case. note that the result will be sort of awkward, as the folders under Path (and thus the subfolders of Inbox) don't start with a dot, while the subfolders of these folders do. this needs to be addressed separately. 2015-04-18 09:42 Oswald Buddenhagen * src/drv_maildir.c: make handling of Inbox-in-Path nesting less obfuscated when we run into Inbox while listing Path, check whether Inbox is being listed anyway, and just skip it if so, instead of listing it right away and resetting LIST_INBOX (and thus having a calling order dependency). 2015-04-18 08:54 Oswald Buddenhagen * src/drv_imap.c: don't list IMAP Path under INBOX twice if NAMESPACE is "INBOX.", listing INBOX recursively will already include it. REFMAIL: 1890363108.1020695.1428757117731.JavaMail.yahoo@mail.yahoo.com 2015-04-13 07:17 Oswald Buddenhagen * src/drv_maildir.c: fix uninitialized variable warning the returned UID is not used when trashing messages, but we still shouldn't just return an undefined value. 2015-04-11 18:06 Reimar Döffinger * README, configure.ac, src/Makefile.am, src/compat/Makefile.am, src/drv_maildir.c: Make Berkley DB an optional dependency. It doesn't seem necessary for any of the basic functionality. Signed-off-by: Reimar Döffinger 2015-04-09 08:05 Oswald Buddenhagen * src/drv_imap.c: fix SASL, take 2 USER (the authorization identity) specifies whom to act for. AUTHNAME (the authentication identity) specifies who is acting (and thus whose PASS is being used). USER is derived from AUTHNAME if omitted, but apparently the GSS-API module automatically adds the REALM, which is not helpful. it appears to be common to set both USER and AUTHNAME to the same value, so let's just do it as well. REFMAIL: 20150407194807.GA1714@leeloo.kyriasis.com 2015-04-03 20:38 Dmitrij D. Czarkoff * src/drv_maildir.c: fix crash in maildir_set_msg_flags() memcpy(3)'s behavior is undefined when source and destination addresses overlap, and it actually crashed on OpenBSD. use memmove() instead. 2015-04-03 12:03 Oswald Buddenhagen * Makefile.am: add cov-scan target 2015-04-03 11:24 Oswald Buddenhagen * configure.ac: bump version 2015-03-30 12:52 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1: don't insert unnecessary linebreaks upon PassCmd invocation the PassCmd will be typically non-interactive (or it will use a gui password agent), so starting a new line just makes the progress counter uglier. so make it configurable and default to no line break. 2015-03-30 12:27 Oswald Buddenhagen * src/main.c: fix crash when no mailboxes match Patterns filter_boxes() just returns a null pointer in this case. REFMAIL: 20150330121211.GA10315@venus.fritz.box 2015-03-30 10:59 Oswald Buddenhagen * src/drv_imap.c: fix SASL PLAIN for User != $USER REFMAIL: 87d29mysnx.fsf@ericabrahamsen.net 2015-03-26 17:09 Oswald Buddenhagen * src/: common.h, main.c, mbsync.1: add debugging for main() so far, that's mostly mailbox listing 2015-03-23 07:42 Oswald Buddenhagen * src/: common.h, drv_imap.c, drv_maildir.c, main.c, mbsync.1, sync.c, util.c: revamp console output options - the old meaning of -V[V] was moved to -D{n|N}, as these are really debugging options. - don't print the info messages by default; this can be re-enabled with the -V switch, and is implied by most debug options (it was really kind of stupid that verbose/debug operation disabled these). - the sync algo/state debugging can be separately enabled with -Ds now. 2015-03-28 16:26 Oswald Buddenhagen * src/: common.h, drv_imap.c, main.c, mbsync.1, sync.c: make progress counters global which means they are now cumulative, and include channels and boxes. 2015-03-28 16:51 Oswald Buddenhagen * src/main.c: pre-calculate channel and box lists (as far as possible) ... instead of determining them on the fly, because - it enables early display of totals (to be used soon) - it enables re-use of the data (to be used at some point) - the code is less cryptic note that we leak the data created in main(), consistently with other configuration-related data. 2015-03-26 16:28 Oswald Buddenhagen * src/main.c: don't claim that INBOX is absent even if it was not listed IMAP defines that INBOX is always present. 2015-03-26 16:27 Oswald Buddenhagen * src/main.c: rework Pattern application instead of creating three lists of mailboxes (common, master, slave) and deriving the mailbox presence from the list being processed, create a single joined list which contains the presence information. additionally, the list is sorted alphabetically (with INBOX first), which is neater. 2015-03-26 16:16 Oswald Buddenhagen * src/: common.h, util.c: static my_strndup() => extern nfstrndup() 2015-03-26 13:28 Oswald Buddenhagen * src/drv_maildir.c: make sure that INBOX always exists makes the Maildir driver consistent with IMAP. 2015-03-23 19:16 Oswald Buddenhagen * src/drv_imap.c: don't refuse to strip Path just because it's INBOX/ no ambiguity can result from this, so there is no reason to treat sub-folders of INBOX differently from any other namespace. 2015-03-23 17:05 Oswald Buddenhagen * src/drv_imap.c: mask AUTHENTICATE PLAIN commands in debug output they are almost as bad as LOGIN. 2015-03-22 12:30 Oswald Buddenhagen * src/drv_imap.c: remove double "Logging in ..." when using legacy LOGIN 2015-03-23 18:00 Oswald Buddenhagen * src/main.c: fix out-of-Path INBOX never being matched by Patterns "(null)I" really doesn't cut it. amends cf0f32f8. 2015-03-22 10:44 Oswald Buddenhagen * src/mbsyncrc.sample: escape backslashes in PassCmd examples the config parser strips one level of backslash escapes. 2015-03-21 11:18 Oswald Buddenhagen * src/drv_imap.c: fix bogus "unexpected command continuation request" it helps if the code actually does what the comment above it claims. clarify it a bit, so i don't get stupid ideas again. This reverts commit cf6a7b4d182d2fe82f7371af9e5a857818f3d02d. 2015-03-07 16:46 Oswald Buddenhagen * src/drv_imap.c: fix chaining of COMPRESS invocation it was bound to the use of NAMESPACE, which made no sense at all. 2015-02-15 17:13 Oswald Buddenhagen * src/: common.h, config.c, driver.h, drv_imap.c, drv_maildir.c, main.c, mbsync.1, socket.c, socket.h, sync.c: soft-limit peak memory usage propagating many messages from a fast store (typically maildir or a local IMAP server) to a slow asynchronous store could cause gigabytes of data being buffered. avoid this by throttling fetches if the target context reports memory usage above a configurable limit. REFMAIL: 9737edb14457c71af4ed156c1be0ae59@mpcjanssen.nl 2015-02-15 11:48 Oswald Buddenhagen * src/config.c: complain about excess values supplied to options 2015-02-15 11:19 Oswald Buddenhagen * src/socket.c: handle clean SSL connection shutdowns some servers actually bother to close down the SSL connection before closing the socket. this fixes the spurious "unhandled SSL error 6" messages. REFMAIL: 20150120114805.GA17586@leeloo.kyriasis.com 2015-02-15 11:15 Oswald Buddenhagen * src/: drv_imap.c, socket.c, socket.h: refactor socket EOF handling handling EOF already at the socket level isn't a very good idea - it breaks the abstraction, and makes implementing sane semantics hard. 2015-02-14 13:03 Oswald Buddenhagen * src/socket.c: fix crash on shutdown of compressed connection the callback may destroy the socket, so it is very unwise to use it for buffering the return value. use a temporary instead. 2015-02-14 12:30 Oswald Buddenhagen * src/socket.c: handle clean shutdown of zlib stream the server can actually close the zlib stream before closing the socket, so we need to accept it. we don't do anything beyond that - the actual EOF will be signaled by the socket, and if the server (erroneously) sends more data, zlib will tell us about it. REFMAIL: 1423048708-975-1-git-send-email-alex.bennee@linaro.org 2015-02-15 10:39 Oswald Buddenhagen * src/socket.c: don't try to flush if there is nothing to flush zlib reports Z_BUF_ERROR when a flush is attempted without any activity since the previous flush (if any). while this is harmless as such, discerning the condition from genuine errors would be much harder than avoiding the pointless flush in the first place. REFMAIL: eb5681612f17be777bc8d138d31dd6d6@mpcjanssen.nl 2015-02-15 10:38 Oswald Buddenhagen * src/: common.h, drv_maildir.c: introduce and use pending_wakeup() so we don't need to peek into internal data structures. 2015-01-03 23:39 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, main.c: deal sensibly with permanent errors don't retry dead Stores for every Channel. this also introduces a state for transient errors (specifically, connect failures), but this is currently unused. 2015-01-01 18:25 Oswald Buddenhagen * src/drv_maildir.c: unify .isyncuidmap.db handling with that of .uidvalidity that is, open the database on demand when locking and close it again when unlocking. 2015-01-01 18:18 Oswald Buddenhagen * src/drv_maildir.c: refactor maildir_set_uid() and maildir_store_uidval() the latter now handles both the db and the plaintext file, so the former can make use of it. 2015-01-01 17:00 Oswald Buddenhagen * src/drv_maildir.c: rename some *uid*() => *uidval*() to better reflect their function 2015-01-01 15:49 Oswald Buddenhagen * src/drv_maildir.c: lock .uidvalidity on demand a maildir re-scan doesn't need to lock it if it doesn't need to allocate any new uids. 2015-01-01 12:24 Oswald Buddenhagen * src/drv_maildir.c: delay unlocking of .uidvalidity it's wasteful to re-lock all the time. instead, unlock in the background after 1-2 seconds of inactivity. 2014-12-29 01:08 Oswald Buddenhagen * src/: config.c, driver.h, drv_imap.c, drv_maildir.c, main.c, mbsync.1, sync.c, sync.h: add support for propagating folder deletions 2015-01-17 14:27 Oswald Buddenhagen * src/drv_maildir.c: don't make intermediate directories proper maildirs "phantom" mailboxes waste time on syncing. furthermore, mutt's mailbox navigator provides no means to enter subfolders of maildirs. 2014-12-29 01:01 Oswald Buddenhagen * src/drv_maildir.c: deal sensibly with incomplete maildir directories a directory is no mailbox unless it contains a cur/ subdir. but if that one is present, create new/ and tmp/ if they are missing. this makes it possible to resume interrupted maildir creations. 2014-12-29 01:00 Oswald Buddenhagen * src/drv_maildir.c: factor out maildir_clear_tmp() 2014-12-30 14:16 Oswald Buddenhagen * src/: main.c, sync.c, sync.h: supplement open_box() with box existence information from list_store() there is no point in trying to open a non-existing box before trying to create it. 2014-12-29 00:42 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, sync.c: split create_box() off from open_box() this allows us to do something else than creating missing boxes depending on circumstances. hypothetically, that is. 2015-01-03 22:16 Oswald Buddenhagen * src/sync.c: open the mailboxes after loading the sync state this allows us to react differently to a box'es absence depending on the state. hypothetically, so far. 2014-12-27 22:50 Oswald Buddenhagen * src/sync.c: lock sync state lazily don't try to lock it until we actually read or write it. the idea is to not fail with SyncState * if we tried to load the state before selecting a non-existing mailbox. this is ok, because if the mailbox is missing, we obviously have no sync state pertaining to it, either. as a side effect, this allows simplifying an error path. 2014-12-27 22:39 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, main.c, sync.c: split off open_box() from select_box() aka prepare_paths() reloaded. we'll need it in a moment. 2014-12-27 22:13 Oswald Buddenhagen * src/sync.c: factor out {prepare,lock,save,load}_state() 2014-12-14 16:03 Oswald Buddenhagen * src/config.c: de-duplicate handling of box operation (create & expunge) options loops work just fine ... 2014-12-27 21:13 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, main.c, sync.c: make some driver function names more descriptive 2014-12-14 11:36 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, sync.c: rename driver::prepare_opts() => prepare_load() ... and move it to the right place in the structure and fix the doc to not claim that it is called before select(). 2014-12-13 17:29 Oswald Buddenhagen * src/drv_imap.c: disable use of LITERAL+ for payloads > 100k when LITERAL+ is used, the server has no chance for early rejection of messages. this means that the client can upload megabytes for nothing. so simply don't use LITERAL+ for big messages. of course this adds server roundtrips, but that's tough luck. the limit could be arguably higher than 100k (or even configurable). i set it to ~2 sec with my fairly average DSL line. 2014-12-13 17:01 Oswald Buddenhagen * src/: drv_imap.c, socket.c, socket.h: fix handling of unsolicited BYE responses they can come in at any time, after which we must expect the connection to be closed (and not complain about it). 2014-12-13 16:57 Oswald Buddenhagen * src/drv_imap.c: fix treatment of untagged NO and BAD responses they aren't possible greeting responses. however, they are warning resp. error reports from the server, so print them accordingly. 2014-12-13 11:09 Oswald Buddenhagen * configure.ac, src/Makefile.am, src/drv_imap.c, src/socket.c, src/socket.h: added support for IMAP DEFLATE initial patch by Jesse Weaver , but mostly rewritten by me. 2014-11-08 14:42 Oswald Buddenhagen * src/: socket.c, socket.h: make socket writing buffered the primary objective is reducing the number of small SSL packets (which are always padded), but fewer syscalls in the non-SSL case should be good as well. 2014-10-26 20:10 Oswald Buddenhagen * src/: drv_imap.c, socket.c, socket.h: vectorize socket_write() the objective is making the buffer code aware of the total size of a write in advance. this commit doesn't take advantage of that yet. 2014-11-30 18:51 Oswald Buddenhagen * src/: common.h, util.c: remove support for faking notifications with the existence of timers, this is now superfluous. 2014-11-30 18:44 Oswald Buddenhagen * src/: socket.c, socket.h: use null timer instead of faking a socket notification 2014-11-30 17:41 Oswald Buddenhagen * src/: Makefile.am, common.h, tst_timers.c, util.c: add timers to mainloop they are called "wakeups", though, as timer_t already exists in time.h. 2014-11-29 18:15 Oswald Buddenhagen * src/: common.h, socket.c, socket.h, util.c: change socket notifier design instead of keeping the structures in an opaque array (which was a shadow of the struct pollfd array if poll() was supported), make them directly addressable. this has the advantage that notifier-altering operations (mostly en-/disabling) don't need to look up the structure by file handle each time. on the downside, data locality in the main loop is worse. neither of these have any real effect on performance. note that the structures are not allocated separately, but embedded into the the parent structure (like sockets already were). 2014-12-07 11:51 Oswald Buddenhagen * src/socket.c: factor out socket_open_internal() 2014-12-07 12:19 Oswald Buddenhagen * src/: common.h, config.c, driver.h, drv_imap.c, drv_maildir.c, sync.c, sync.h, util.c: introduce uchar, ushort & uint typedefs 2015-01-11 13:18 Oswald Buddenhagen * Makefile.am: skip merges during ChangeLog generation 2015-01-11 13:29 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, sync.c: fix UID assignment with some non-UIDPLUS servers the seznam.cz IMAP server seems very eager to send UIDNEXT responses despite not supporting UIDPLUS. this doesn't appear to be a particularly sensible combination, but it's valid nonetheless. however, that means that we need to save the UIDNEXT value before we start storing messages, lest imap_find_new_msgs() will simply overlook them. we do that outside the driver, in an already present field - this actually makes the main path more consistent with the journal recovery path. analysis by Tomas Tintera . REFMAIL: 20141220215032.GA10115@kyvadlo.trosos.seznam.cz 2015-01-02 11:38 Oswald Buddenhagen * src/sync.c: fix conditional for early failure in cancel_done() 2015-01-02 10:29 Oswald Buddenhagen * src/main.c: don't leave 2nd store in limbo if opening 1st store fails synchronously we can't leave the store FRESH, as otherwise the error handling code will assume it is still being opened and will return to the main loop. depending on the config this would cause an immediate termination or an indefinite wait. 2014-10-26 21:03 Oswald Buddenhagen * src/drv_imap.c: remove stray CRLF from AUTHENTICATE continuations this re-introduces 6741bc94 (just a bit differently), thus effectively reverting fbfcfea5. i suppose this extra CRLF is needed by a broken CRAM-MD5 implementation of some server, which is why it was there in the original implementation as well. however, it breaks more pedantic non-broken servers. if somebody complains, we'll need to add a much more sophisticated hack. 2014-10-26 19:17 Oswald Buddenhagen * src/socket.h: cleanup dead cram() prototype 2014-12-29 01:16 Oswald Buddenhagen * src/drv_imap.c: fix more memcmp() abuse amends 1217193fb and 4f383a807. 2014-11-08 12:50 Oswald Buddenhagen * src/: socket.c, socket.h: fix acceptance of trusted SSL certs we should make no assumptions about the layout of OpenSSL's certificate store, in particular when they are wrong. so copy the interesting part instead of "deep-linking" into it. this code is uglier than it should be, but OpenSSL's extensive use of macros to manage data types would force us to include the ssl headers into our headers otherwise, which would be even uglier. REFMAIL: <545442CC.9020400@nodivisions.com> 2014-10-25 15:30 Oswald Buddenhagen * README, src/common.h, src/config.c, src/drv_maildir.c, src/main.c, src/mbsync.1, src/sync.c: introduce FieldDelimiter and InfoDelimiter options ... for windows fs compatibility. the maildir-specific InfoDelimiter inherits the global FieldDelimiter (which affects SyncState), based on the assumption that if the sync state is on a windows FS, the mailboxes certainly will be as well, while the inverse is not necessarily true (when running on unix, anyway). REFMAIL: 2014-10-25 13:06 Oswald Buddenhagen * src/: driver.h, sync.c: move orig_name out of store_t it's state specific to the synchronizer. 2014-07-27 16:41 Oswald Buddenhagen * src/: drv_imap.c, socket.c: nuke home-grown CRAM-MD5 support it was obsoleted by SASL support. i deem the additional dependency acceptable when one wants the feature. 2014-07-27 16:41 Oswald Buddenhagen * README, configure.ac, src/Makefile.am, src/drv_imap.c, src/mbsync.1: add SASL support patch initially by Jack Stone , cleaned up by Jan Synacek , ... and then almost completely rewritten by me. ^^ 2014-07-27 17:29 Oswald Buddenhagen * src/drv_imap.c: factor out ensure_user() and ensure_password() 2014-07-12 19:02 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1: rework authentication mechanism configuration RequireCRAM (another fairly stupid "use if available" option) is now deprecated. instead, the AuthMech option can be used to give a precise list of acceptable authentication mechanisms (which is currently "a bit" short). in particular, this allows *not* using CRAM-MD5 even if it's available. 2014-07-27 13:42 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1, socket.c, socket.h: make it possible to disable usage of system cert store 2014-07-27 16:10 Oswald Buddenhagen * src/: mbsync.1, socket.c: require Host if SSL is used despite Tunnel 2014-07-27 13:12 Oswald Buddenhagen * src/: socket.c, socket.h: make SSL certificate verification less arcane instead of using a callback which messes with the certificate chain verification, simply let OpenSSL ignore errors during that phase and check the result only afterwards. 2014-07-12 18:35 Oswald Buddenhagen * src/: config.c, config.h, drv_imap.c, mbsync.1, socket.c, socket.h: re-design SSL/TLS configuration the combinations of the various options made quite a mess. additionally, 'RequireSSL no' is inherently insecure - "use SSL if available" is plain stupid. the old options are still accepted, but will elicit a warning. 2014-07-06 08:06 Oswald Buddenhagen * src/: drv_imap.c, socket.c, socket.h: move use_imaps out of server_conf_t it doesn't belong there - it's a property of imap_server_conf_t. the port setup is now done while reading the config. this makes socket.[hc] imap-agnostic. 2014-07-12 11:50 Oswald Buddenhagen * src/compat/: isync.1, main.c: deprecate the compat wrapper after a decade, it's about time to phase it out. 2014-07-05 14:37 Oswald Buddenhagen * configure.ac: bump version 2014-10-04 16:26 Oswald Buddenhagen * src/: driver.h, drv_imap.c, drv_maildir.c, sync.c: fix memory management of current mailbox name it was a stupid idea to store the pointer to a variable we need to dispose in a structure which has its own lifetime. 2014-10-04 15:07 Oswald Buddenhagen * configure.ac, src/common.h, src/compat/config.c, src/compat/isync.h, src/compat/util.c, src/drv_imap.c, src/drv_maildir.c, src/main.c, src/sync.c, src/util.c: stop abusing memcmp() memcmp() is unfortunately not guaranteed to read forward byte-by-byte, which means that the clever use as a strncmp() without the pointless strlen()s is not permitted, and can actually misbehave with SSE-optimized string functions. so implement proper equals() and starts_with() functions. as a bonus, the calls are less cryptic. 2014-10-04 11:12 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1: permit IMAP Stores with explicitly empty Path this is useful if the server sends an unhelpful NAMESPACE like "INBOX." (which precludes clean use of Patterns with the real INBOX). 2014-10-04 13:43 Oswald Buddenhagen * src/drv_imap.c: don't attempt to filter LIST response if there is no Path we won't filter anything in that case anyway. 2014-10-04 10:16 Oswald Buddenhagen * src/: config.c, drv_imap.c, drv_maildir.c: permit Maildir Stores without a Path it is perfectly reasonable to have a Store which has only an Inbox. 2014-10-04 13:37 Oswald Buddenhagen * src/drv_imap.c: use resolved Path for initial filtering of LIST response otherwise we'd ignore NAMESPACE, and funny things could happen. 2014-10-04 15:30 Oswald Buddenhagen * src/drv_imap.c: consider unexpected structure of NAMESPACE fatal 2014-10-04 09:43 Oswald Buddenhagen * src/drv_maildir.c: ignore INBOX only in Path itself, not its subfolders a box foo/INBOX cannot be mistaken for the INBOX, so there is no point in filtering these out. 2014-07-12 12:07 Oswald Buddenhagen * src/mbsync.1: use \fB and \fI consistently notably, the docu for the Sync option had it mixed up in the description. 2014-07-05 21:11 Oswald Buddenhagen * src/drv_imap.c: complain about RequireSSL with no SSL versions enabled 2014-07-05 21:10 Oswald Buddenhagen * src/drv_imap.c: actually use STARTTLS if only TLSv1.1 or TLSv1.2 is enabled 2014-07-05 21:03 Oswald Buddenhagen * src/drv_imap.c: clarify error message about missing connection details 2014-07-05 21:02 Oswald Buddenhagen * src/drv_imap.c: make store/account error messages less redundant this will become more relevant when more are added. 2014-07-05 20:53 Oswald Buddenhagen * src/mbsync.1: clarify effect of Tunnel on Host and Port 2014-07-05 20:52 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1: don't ignore RequireSSL for PREAUTHenticated connections such connections don't support STARTTLS. that is reasonable, as whatever makes the connection preauthenticated (typically a Tunnel used to launch imapd via a shell login) must already rely on the connection's security. consequently, we would not try to use STARTTLS with such connections. unfortunately, we'd also skip the RequireSSL check as a side effect. this means that a rogue server (via a MITM attack) could simply offer a preauthenticated connection to make us not use SSL, and thus bypass server authentication. as a result, we could send potentially sensitive data to the attacker: - with Patterns used, we would send a LIST command which reveals the remote Path setting. this isn't very useful to an attacker. also, IMAP Accounts usually rely on the server-provided NAMESPACE to start with. - with Create enabled for the remote Store, we would upload messages from newly appeared local folders. this isn't a very likely situation, unless the attacker manages to convince the victim to move/copy interesting mails to a new folder right before the attack. - with Expunge enabled for the local Store, previously synchronized folders would be wiped. however, this would require the attacker to know the correct UIDVALIDITY of each remote folder, which would require incredible luck or convincing the victim to disclose them. the first mismatch would likely tip off the victim. in practice, someone with the level of technical and social engineering skills required for this attack would very likely find more attractive attack vectors. therefore, i don't consider this a particularly serious issue. configurations with UseIMAPS enabled or using a secure Tunnel were not affected to start with. a side effect of this fix is that most users of Tunnel will now need to explicitly set RequireSSL to false. an alternative approach would be defaulting all SSL-related settings to off when Tunnel is used. this would be too invasive for a patch release, but i'll consider it for 1.2. see also CVE-2014-2567 for the Trojita MUA. 2014-07-05 20:54 Oswald Buddenhagen * .gitignore: ignore coverity state directory 2014-07-02 06:47 Oswald Buddenhagen * src/sync.c: initialize store_t::name the field is marked foreign (for the drivers), so a recycled store may contain an old pointer in it. that would make our error path crash. REFMAIL: CAF_KswU7aBS7unnK+rdZy1PG_8SZUAW=tcg75HixDLLE0w3Lhw@mail.gmail.com 2014-07-02 06:40 Oswald Buddenhagen * src/sync.c: actually print the faulty mailbox name, not some garbage REFMAIL: CAF_KswU7aBS7unnK+rdZy1PG_8SZUAW=tcg75HixDLLE0w3Lhw@mail.gmail.com 2014-06-28 12:27 Oswald Buddenhagen * configure.ac: bump version 2014-06-28 09:58 Oswald Buddenhagen * src/drv_maildir.c: detect inconsistent state of highest assigned UID the highest assigned UID must always be at least as high as the highest actually found UID, as otherwise we'd hand out duplicate UIDs at some point. also, getting into such a state in the first place indicates some potentially serious trouble, or at least external interference (e.g., moving/copying a message from another folder without giving it a pristine filename). REFMAIL: 20140626211831.GA11590@sie.protva.ru 2014-06-28 09:04 Oswald Buddenhagen * src/drv_imap.c: zero-terminate imap literals now that we properly support literals for strings, we must expect that the consumer code will use them as strings. amends fc77feacc. discovered by Armands Liepins REFMAIL: CAF_KswXoxdm7KXnWW4b_1odf=XsE4qRqRN4AsecwcPF1d+dSTA@mail.gmail.com 2014-04-13 15:07 Oswald Buddenhagen * src/mbsync.1: don't lie about the default of User unlike the isync wrapper, mbsync does not have a default for the IMAP user. the remote user seldomly matches the local one, so "forwarding" it is more confusing than helpful. CCMAIL: 744389@bugs.debian.org 2014-04-12 17:02 Oswald Buddenhagen * src/drv_maildir.c: don't forget to reset message counts when skipping scan amends b6949c64d2. CCMAIL: 744259@bugs.debian.org 2014-04-12 17:00 Oswald Buddenhagen * src/drv_maildir.c: remove apparently pointless resetting of recent message count past this point, it's not used for anything anyway. 2014-04-12 16:59 Oswald Buddenhagen * src/compat/convert.c: error-check renaming of uid mapping database for pedantry. found by coverity. 2014-04-12 16:34 Oswald Buddenhagen * src/compat/convert.c: error-check reading of old uidvalidity and maxuid files found by coverity. 2014-04-12 16:31 Oswald Buddenhagen * src/sync.c: error-check committing of sync state a failure here is rather unlikely, but let's be pedantic. a failure is not fatal (we'll just enter the journal replay path next time), so only print warnings. found by coverity. 2014-04-12 16:30 Oswald Buddenhagen * src/sync.c: better error messages for sync state and journal related errors we can make perfectly good use of errno here. 2014-04-12 16:28 Oswald Buddenhagen * src/sync.c: remove pointless/counterproductive "Disk full?" error message suffixes the affected functions will set errno to ENOSPC when necessary. 2014-04-12 14:56 Oswald Buddenhagen * src/compat/config.c: fix "inverse copy&pasto" in account labeling code the code was copied and the original adjusted ... but not quite completely. this means that clashing server names never really worked since - not that i would have expected this to be a particularly common configuration to start with. :D also added comments explaining why there are two implementations of the same thing. amends aea4be19e3 (anno 2006). found by coverity. 2014-04-12 14:06 Oswald Buddenhagen * src/config.c: assert !where implying !pseudo to help poor coverity. 2014-04-12 13:28 Oswald Buddenhagen * src/sync.c: don't crash in message expiration debug print we would try to print the uids from the non-existing srec of unpaired messages while preparing expiration. this would happen only if a) MaxMessages was configured and b) new messages appeared on the slave but we were not pushing, so it's a bit of a corner case. found by coverity. 2014-04-12 13:16 Oswald Buddenhagen * src/main.c: fix segfault on passing --{create,expunge}-{master,slave} stupid copy&pasto. found by coverity. 2014-04-12 13:02 Oswald Buddenhagen * src/drv_imap.c: don't crash on malformed response code this would happen in the absurd corner case that the response code is properly terminated with a closing bracket, but the atom itself is an unterminated double-quoted string. NOT found by coverity. 2014-04-12 12:58 Oswald Buddenhagen * src/drv_imap.c: don't crash on truncated LIST response found by coverity. 2014-04-12 11:08 Oswald Buddenhagen * src/compat/main.c: remove pointless pointer assignment 2014-04-12 11:03 Oswald Buddenhagen * src/: drv_maildir.c, mdconvert.c: fix hypothetical buffer overflows if something managed to make the maildir .uidvalidity files big enough (possible only by appending garbage or scrambling them alltogether), we would overflow the read buffer by one when appending the terminating null. this is not expected to have any real-world impact. found by coverity. 2014-04-12 10:46 Oswald Buddenhagen * src/: drv_maildir.c, mdconvert.c: close a bunch of fd leaks in error paths found by coverity. 2014-03-19 09:27 Oswald Buddenhagen * src/util.c: actually use prime numbers for all hash bucket sizes for some reason lost in history, the prime_deltas were actually wrong, leading to using composite numbers. the right sequence is available at http://oeis.org/A092131. 2014-03-19 09:09 Oswald Buddenhagen * src/config.c: fix zero MaxSize override in Channels REFMAIL: CA+Tk8fzb9i9LrC_k4G978c5XR5urNz_s0fpOn_-6EsdrBnEzSQ@mail.gmail.com 2014-03-10 10:57 Oswald Buddenhagen * src/compat/: config.c, isync.h, util.c: rework maildir store mapping the trivial approach of having "home" and "root" stores produced ugly results, and totally failed with the introduction of nested folder handling. instead, create a store per local directory, just as one would manually. CCMAIL: 737708@bugs.debian.org 2014-03-10 10:57 Oswald Buddenhagen * src/compat/config.c: don't needlessly quote strings 2014-03-10 10:54 Oswald Buddenhagen * src/compat/main.c: don't needlessly spell out INBOX 2014-03-09 15:38 Oswald Buddenhagen * src/compat/config.c: write Sync and Expunge to global section if applicable makes for leaner Channel sections. note: the global delete and expunge variables exist so the command line can override the config file despite the otherwise backwards behavior. 2014-03-09 14:56 Oswald Buddenhagen * src/compat/config.c: don't bother checking impossible condition the config readear already verified that at least host or tunnel are set. 2014-02-08 12:21 Oswald Buddenhagen * src/drv_imap.c: fix crash on store without prior fetch with non-UIDPLUS servers we'd never initialize the message list append pointer, so imap_find_new_msgs()'s FETCH would go awry. REFMAIL: <20140207101719.GB17125@mac.home> 2014-02-02 11:24 Oswald Buddenhagen * src/socket.c: remove pointless use of AI_V4MAPPED flag this flag is ineffective if ai_family is not explicitly AF_INET6. on top of that, attempting to use it breaks on FreeBSD. 2014-01-25 12:19 Oswald Buddenhagen * src/mbsync.1: fix typos 2014-01-25 10:34 Oswald Buddenhagen * src/drv_imap.c: don't error out if we don't get an X-TUID header the BODY[] item in the FETCH response corresponds to what we requested, and its presence doesn't imply that it actually contains anything useful - new messages may appear in the mailbox in addition to those we stored ourselves, and these will obviously have no TUID. 2014-01-02 19:50 Oswald Buddenhagen * configure.ac, src/common.h, src/drv_imap.c, src/util.c: make date parsing portable, take 2 the global timezone variable is glibc-specific. so use timegm() instead of mktime() for the conversion. as that is specific to the BSDs and glibc, provide a fallback. amends 62a6099. 2014-01-02 18:36 Oswald Buddenhagen * src/: drv_maildir.c, sync.c: fix _POSIX_SYNCHRONIZED_IO usage it can be -1 for unsupported, or 0 for runtime detection (which we don't do). 2014-01-02 20:08 Oswald Buddenhagen * configure.ac: bump version 2013-12-08 21:29 Oswald Buddenhagen * README, src/mbsyncrc.sample: pre-release doc updates 2013-12-14 11:37 Oswald Buddenhagen * src/mbsync.1: elaborate on expunging and trashing 2013-12-13 18:07 Oswald Buddenhagen * src/mbsync.1: clarify wording in MapInbox doc 2013-12-15 11:46 Oswald Buddenhagen * src/drv_imap.c: avoid array underflow in IMAP LIST .lock workaround suggested by Mark Wielaard . fwiw, the workaround really is still necessary with panda imap ... 2013-12-13 14:36 Oswald Buddenhagen * src/sync.c: MaxMessages: ignore entries with no master while calculating bulk fetch 2013-12-11 15:29 Oswald Buddenhagen * src/sync.c: adjust comments to new reality 2013-12-11 15:25 Oswald Buddenhagen * src/sync.c: ensure sequencing of message propagation and store closing by putting the message propagation last, d3f634702 uncovered a long-standing problem: we might have closed the source store before all messages were propagated from it. 2013-12-11 15:13 Oswald Buddenhagen * src/sync.c: fix error paths wrt sync drivers, take 3 msgs_copied() was not checked at all, and msgs_flags_set() was doing it wrong (sync_close() was not checked). instead of trying to fix/extend the msgs_flags_set() model (ref-counting and cancelation checking in lower-level functions, and return values to propagate the status), place the refs/derefs around higher-level scopes and do the checking only there. this is effectively simpler, and does away with some obscure macros. 2013-12-11 13:30 Oswald Buddenhagen * src/drv_imap.c: don't use UID EXPUNGE unless trashing a simple CLOSE is way more efficient, so use it if no adverse effects can come from it. 2013-12-08 19:46 Oswald Buddenhagen * .gitignore, configure.ac, src/Makefile.am, src/common.h, src/compat/isync.h, src/config.c, src/config.h, src/driver.c, src/driver.h, src/drv_imap.c, src/drv_maildir.c, src/main.c, src/mdconvert.c, src/socket.c, src/socket.h, src/sync.c, src/sync.h, src/util.c: reshuffle sources a bit split header and move some code to more logical places. 2013-12-08 15:37 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, main.c: tag verbose output when channel links two verbose stores otherwise it's pure guesswork to assign the output to particular stores. 2013-12-08 15:32 Oswald Buddenhagen * src/: drv_imap.c, socket.c: move verbose socket logging out of socket driver the way it's used, it's more of a high-level function. 2013-12-08 14:49 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, main.c: remove own_store() function from driver model the drivers which support it can abstract it inside open_store() just fine. 2013-12-08 14:11 Oswald Buddenhagen * src/drv_imap.c: make use of IMAP MOVE extension the Maildir driver is always exposing behavior equivalent to this - it's more efficient. 2013-12-08 09:48 Oswald Buddenhagen * src/drv_maildir.c: don't check for INBOX more than necessary 2013-12-08 09:44 Oswald Buddenhagen * src/drv_maildir.c: fix listing of nested maildir mailboxes 2013-12-08 08:49 Oswald Buddenhagen * src/: main.c, mbsync.1, mbsyncrc.sample: allow prefixes to Patterns this makes it possible to "rename" a "namespace" while syncing. 2013-12-08 08:51 Oswald Buddenhagen * src/main.c: less spaghetti 2013-12-07 16:24 Oswald Buddenhagen * src/main.c: factor out sync_listed_boxes() 2013-12-07 15:41 Oswald Buddenhagen * src/: main.c, mbsync.1: refuse box list overrides if Channel has no Patterns as the named boxes are the same on both sides, they logically make sense only when the channel is in that mode anyway, which is the case when using patterns. 2013-12-07 15:11 Oswald Buddenhagen * src/: isync.h, main.c, util.c: treat manually specified box list the same as one coming from Patterns 2013-12-01 16:57 Oswald Buddenhagen * src/socket.c: make host resolution error messages more useful in non-ipv6 builds 2013-12-01 16:45 Oswald Buddenhagen * src/drv_maildir.c: avoid useless delay after creating maildir box we would see the recent timestamp of the creation and conclude that something is going on, so we'd wait. this is obviously nonsense. as we know that a freshly created mailbox is empty, simply skip the message scan alltogether. 2013-11-02 20:42 Oswald Buddenhagen * src/: config.c, drv_maildir.c, isync.h, mbsync.1, run-tests.pl, sync.c: reduce FSync option to a boolean there is no use for Thorough mode any more, so simplify the configuration. 2013-11-02 20:41 Oswald Buddenhagen * src/sync.c: don't fsync after logging every TUID as we now don't actually start propagating new messages until all TUIDs have been generated, it's sufficient to sync just once. this makes it a cheap operation, so we can do it at SYNC_NORMAL level already. 2013-11-24 19:26 Oswald Buddenhagen * src/: config.c, isync.h, mbsync.1, run-tests.pl, sync.c: add ExpireUnread option 2013-11-24 18:39 Oswald Buddenhagen * src/: config.c, mbsync.1: make it possible to specify CopyArrivalDate and MaxMessages globally sneaky change on the side: the wording of the man page is changed from "outside any section" to "before any section" to get global options. this is not entirely true ... the previously existing options behave as before, while the two newcomers actually affect subsequent channels. 2013-11-24 18:32 Oswald Buddenhagen * src/: config.c, isync.h, main.c, sync.c: replace global_* with a channel_conf_t instance this makes the (growing) list of getopt_helper()'s parameters manageable. the few wasted bytes are worth it. 2013-11-24 18:55 Oswald Buddenhagen * src/: drv_imap.c, isync.h, main.c: do not unnecessarily use bitfields they don't save much (if any) space in our usage, while they make the machine code more bloated and slow. 2013-11-24 17:26 Oswald Buddenhagen * src/sync.c: move handling of new messages after that of old ones i.e., move it back. whatever the original reason was, it's now gone. this order is way more natural, which allows us to remove the osrecadd and S_DONE hacks. 2013-11-04 08:54 Oswald Buddenhagen * src/run-tests.pl: verify idempotence of all sync operations 2013-11-30 12:03 Oswald Buddenhagen * src/: run-tests.pl, sync.c: make MaxMessages work for new mails as well this helps enormously on the first sync of a 100k message box with a limit of 1k messages. it also happens to make the syncing idempotent. in a few conditionals we now explicitly test for max_messages being enabled, not smaxxuid != 0, as after the initial fetch with no important messages smaxxuid is zero, but we still have to skip over 99k messages in the above case. 2013-11-23 14:55 Oswald Buddenhagen * src/sync.c: delay propagation of new messages previous sequence: examine & propagate new => examine old => propagate old new sequence: examine new => examine old => propagate new => propagate old this alone does not buy us much ... 2013-11-02 18:33 Oswald Buddenhagen * src/sync.c: make message propagation recording less magic assign the sync record to the source message asap, and later on rely on a more explicit condition than not doing so. 2013-11-02 19:47 Oswald Buddenhagen * src/sync.c: log maxuid bumping less aggressively we can bump the internal variable whereever convenient, but we cannot log it until we know that all messages were copied, as otherwise we could miss some new messages after an interruption. with the new approach, interruption would merely cause some additonal traffic. 2013-11-17 16:36 Oswald Buddenhagen * src/sync.c: document message expiration transactions 2013-11-24 14:58 Oswald Buddenhagen * src/sync.c: propagate deletions with other flag changes less code duplication, more logical order of issued driver commands (especially after the next commit), and the "side effect" of letting the message expiration code see those deletions if they are asynchronous. 2013-11-17 10:23 Oswald Buddenhagen * src/sync.c: don't delay loading master even if messages were expired the delay optimized the corner case of previously important but now expired messages on the slave disappearing, either through an external expunge or after a journal replay. no point in pessimizing the common case. 2013-11-17 08:06 Oswald Buddenhagen * src/: run-tests.pl, sync.c: remove cleanup of expired entries during setup of master load the removed code would only ever trigger if a) we were after a journal replay or b) something external expunged the expired messages - both are corner cases not worth the extra code. however, this means that the syncing code further down now needs to take care of these zombies. in the end, the normal cleanup will take care of all expired entries, new and old. 2013-11-24 18:50 Oswald Buddenhagen * src/sync.c: micro-optimization/-clarification: swap condition order 2013-11-23 11:01 Oswald Buddenhagen * src/sync.c: make message counting in expiration code less confusing 2013-11-10 18:57 Oswald Buddenhagen * src/sync.c: count unread messages like flagged messages when expiring that is, don't count them towards the total only below the cut-off point. making them extend the working set even though they are inside it is counterintuitive. 2013-11-09 10:25 Oswald Buddenhagen * src/sync.c: use post-sync "seen" flag to determine expirability otherwise it wouldn't be idempotent. 2013-11-08 11:05 Oswald Buddenhagen * src/: compat/isync.1, sync.c: don't protect recent messages from MaxMessages while maildir has a clearly defined meaning of "recent" and for example mutt handles it graciously, IMAP's definition is fubared to the point that some servers (for example gmail) simply refuse to support it. for symmetry reasons it is best to pretend that it doesn't exist at all. it doesn't seem too useful anyway (the user can simply mark the messages as read to allow pruning). and last but not least, the man page of mbsync says nothing about "recent", only "unread". unlike the isync man page, though. 2013-11-23 11:22 Oswald Buddenhagen * src/sync.c: always get slave flags when we are expiring even if we are not propagating new messages, the appearance of new messages on the slave can lead to expiring older messages. for that, we need to know their importance, and thus flags. the alternative would be not doing an expiration run when not fetching new messages, but that would mean more conditionals all over the place. as the decision is somewhat arbitrary, just do the simpler thing. 2013-11-16 16:59 Oswald Buddenhagen * src/sync.c: do not trash expired messages we are not actually deleting them, so there is no point in saving them in the trash. 2013-11-16 12:25 Oswald Buddenhagen * src/: run-tests.pl, sync.c: make sync state header format less obscure the header is not space-critical, so use proper name-value pairs. this has the additional advantage that subsequent format changes can be done much easier. 2013-11-16 12:21 Oswald Buddenhagen * src/run-tests.pl: make state loading in showstate() similar to ckstate() 2013-11-09 12:06 Oswald Buddenhagen * src/run-tests.pl: take configs out of target state defs cleaner and less duplication 2013-11-16 12:41 Oswald Buddenhagen * src/run-tests.pl: more precise failure reporting 2013-11-03 19:17 Oswald Buddenhagen * src/run-tests.pl: make it possible to run only selected tests 2013-11-09 10:42 Oswald Buddenhagen * src/sync.c: set srec->msg[] when finding messages by tuid otherwise we would propagate phantom deletions. this affected only sync runs after an interruption while storing messages, so it went (mostly?) unnoticed. 2013-11-09 10:41 Oswald Buddenhagen * src/sync.c: remove pointless assignment we already know that tmsg->srec is null at this point. 2013-11-02 22:32 Oswald Buddenhagen * src/sync.c: assert no stray TUIDs 2013-11-30 14:07 Oswald Buddenhagen * src/drv_imap.c: initialize struct tm strptime() does not initialize at least tm_isdst, which leads to an uninited value reference in mktime(). 2013-11-09 13:35 Oswald Buddenhagen * src/: drv_imap.c, main.c: make use of strptime() portable it does not (officially) support the %z conversion, so re-implement that part by hand. 2013-11-09 12:53 Oswald Buddenhagen * src/drv_imap.c: fix compilation with older gcc versions the warning suppression pragma within function scope is apparently a new thing. as i don't want to disable the check for the entire function (even if this currently would make no difference), just use a wrapper function to suppress the format string check. 2013-11-09 12:50 Oswald Buddenhagen * configure.ac: fix strftime() %z conversion specifier check only glibc does something sane with gmtime()+strftime(). on bsd (incl. mac os), strftime() can be used only with localtime(). 2013-11-06 07:40 Oswald Buddenhagen * .gitignore: ignore automake's "compile" script 2013-11-06 07:37 Oswald Buddenhagen * autogen.sh: use autoreconf instead of calling separate tools this has been the correct way since a long time. Pointed-out-by: Felipe Contreras 2013-11-02 19:06 Oswald Buddenhagen * src/: isync.h, main.c, run-tests.pl, sync.c: add/fix comments and improve debug messages 2013-11-02 19:02 Oswald Buddenhagen * src/sync.c: simplify condition ... and document the cases. 2013-11-02 18:39 Oswald Buddenhagen * src/sync.c: micro-optimization/-clarification 2013-10-26 09:44 Oswald Buddenhagen * src/sync.c: move initializations for clarity 2013-05-20 16:54 Oswald Buddenhagen * src/sync.c: MaxMessages: make condition exactly symmetrical to condition below 2013-05-20 16:53 Oswald Buddenhagen * src/sync.c: rewrite condition for readability and consistency 2013-11-02 14:04 Oswald Buddenhagen * src/sync.c: remove assumption about value of M constant 2013-11-02 11:57 Oswald Buddenhagen * src/sync.c: fix enum abuse amends 9c86ec344. S_FIND was for the sync record status field. it has no business in the sync vars status fields. its value coincided with ST_SELECTED, which luckily only means that we always tried to match up TUIDs even if there was nothing to do. the need for TUID matching arises in two mostly independent circumstances, so add two separate flags ST_FIND_{OLD,NEW}. 2013-11-03 19:20 Oswald Buddenhagen * src/run-tests.pl: create unseen messages in /new/ seen messages still go to /cur/. this is consistent with the actual maildir driver. 2013-11-03 11:59 Oswald Buddenhagen * src/run-tests.pl: be a bit more verbose 2013-11-03 11:59 Oswald Buddenhagen * src/run-tests.pl: properly handle unexpected exit while replaying journal 2013-11-03 11:49 Oswald Buddenhagen * src/run-tests.pl: ensure that the journal replay pass really does nothing 2013-11-02 15:43 Oswald Buddenhagen * src/run-tests.pl: sort messages by serial number instead of UID in box dumper the input data is sorted that way, so it's easier to compare. 2013-11-02 14:42 Oswald Buddenhagen * src/run-tests.pl: fix error message in sync state dumper 2013-09-25 15:13 Oswald Buddenhagen * src/drv_imap.c: deal with messages disappearing between being listed and fetched 2013-09-25 18:56 Oswald Buddenhagen * src/: config.c, mbsync.1: support backslash-escaping in the config file note that no attempt is made at making this work in the compat wrapper. 2013-09-25 18:55 Oswald Buddenhagen * src/drv_imap.c: support backslashes and quotes in quoted IMAP strings the RFCs require it - well hidden in the BNF at the bottom. patch somewhat inspired by "guns" . 2013-09-25 16:53 Oswald Buddenhagen * src/drv_imap.c: make next_arg() more readable & efficient 2013-09-01 15:35 Oswald Buddenhagen * configure.ac, src/isync.h, src/socket.c: IPv6 support inspired by a patch by "Todd T. Fries" . 2013-09-01 14:32 Oswald Buddenhagen * src/: isync.h, socket.c: support multi-homed servers 2013-08-03 13:10 Oswald Buddenhagen * src/: config.c, drv_imap.c, isync.h, main.c, mbsync.1, sync.c, util.c: support multi-character path separators this applies to both the IMAP PathDelimiter (which is needed by Lotus Domino), as well as the Flatten-ed separators. 2013-07-27 16:46 Oswald Buddenhagen * src/drv_imap.c: CHECK before FETCH after STORE m$ exchange does not seem to update the index in time otherwise. 2013-07-28 13:55 Oswald Buddenhagen * configure.ac, src/config.c, src/drv_imap.c, src/drv_maildir.c, src/isync.h, src/mbsync.1, src/sync.c: added sync support for the arrival date of messages initial patch by Marc Hoersken 2013-07-27 18:17 Oswald Buddenhagen * src/sync.c: warn if we cannot find some messages by TUID 2013-07-27 16:44 Oswald Buddenhagen * src/: drv_maildir.c, sync.c: make better use of ATTR_UNUSED 2013-07-27 13:35 Oswald Buddenhagen * src/drv_imap.c: be somewhat stricter about the LIST response syntax the first token *must* be a list. 2013-07-27 13:32 Oswald Buddenhagen * src/drv_imap.c: allow the mailbox names in LIST responses to be literals Lotus Domino seems to send them like that. 2013-07-27 12:31 Oswald Buddenhagen * src/drv_imap.c: make parse_list() callback based this allows us to parse IMAP literals ({}) in every list. 2013-07-27 08:37 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1, mbsyncrc.sample: add PassCmd option to query IMAP password dynamically inspired by patches by Aurélien Francillon , Martin Stenberg and sbfnk@users.sf.net. 2013-05-09 16:51 Oswald Buddenhagen * src/sync.c: don't unnecessarily use continue 2013-05-11 08:12 Oswald Buddenhagen * src/: config.c, sync.c: use INT_MAX instead of zero for "no size limit" this simplifies the actual conditions 2013-04-20 14:57 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, mbsync.1, socket.c, sync.c: update copyrights 2013-04-13 17:05 Oswald Buddenhagen * src/mbsync.1: man page fixups 2013-04-13 17:05 Oswald Buddenhagen * src/: main.c, mbsync.1: don't let wildcards match INBOX, unless it lives under Path it's counter-intuitive to have '*' match the (always present) INBOX when the rest of the mailboxes lives in a different namespace. 2013-04-13 17:25 Oswald Buddenhagen * src/drv_maildir.c: always list INBOX when asked for it it's there even if it's not there. says IMAP. no need to contradict. 2013-04-01 10:20 Oswald Buddenhagen * src/drv_maildir.c: split maildir_list_part() the boolean argument switched two entirely separate functions. 2013-04-01 10:30 Oswald Buddenhagen * src/drv_maildir.c: remove some temporaries in maildir_list_part() 2013-04-13 08:47 Oswald Buddenhagen * src/socket.c: fix CRAM-MD5 authentication the decoded challenge may be padded, so we really need to use strlen() rather than just the decoded length. 2013-04-13 08:50 Oswald Buddenhagen * src/socket.c: more consistency in char signedness 2013-04-07 15:20 Felipe Contreras * src/drv_maildir.c: maildir: fix trash path double-free It should be freed at the very end. Signed-off-by: Felipe Contreras 2013-04-07 14:53 Felipe Contreras * configure.ac: Fix build with recent autoconf and modernize configure.ac configure.ac:2: warning: macro 'AM_CONFIG_HEADERS' not found in library configure.ac:7: error: 'AM_PROG_CC_STDC': this macro is obsolete. You should simply use the 'AC_PROG_CC' macro instead. Also, your code should no longer depend upon 'am_cv_prog_cc_stdc', but upon 'ac_cv_prog_cc_stdc'. configure.ac:3: warning: AM_INIT_AUTOMAKE: two- and three-arguments Signed-off-by: Felipe Contreras 2013-04-07 10:42 Felipe Contreras * configure.ac: Rename configure.in to the modern equivalent Fixes: aclocal: warning: autoconf input should be named 'configure.ac', not 'configure.in' Signed-off-by: Felipe Contreras 2013-04-07 14:54 Oswald Buddenhagen * src/mbsync.1: discourage use of MapInbox 2013-03-30 09:10 Oswald Buddenhagen * src/drv_imap.c: don't try to fetch status of minus one message this would happen if we were trying to find newly pushed messages, but none actually arrived. as imap's ranges are not ordered, this would actually fetch one message. 2013-03-30 15:27 Oswald Buddenhagen * src/: run-tests.pl, sync.c: don't record newuid in the sync state this value is only ever used to find just pushed messages by TUID, so we can simply use the UIDNEXT value from before we started pushing - and of course, we need to record that in the journal. it makes no sense to log the new value after completing a search, as there won't be a next search before we push the next messages. 2013-03-30 08:38 Oswald Buddenhagen * src/sync.c: rename sync_vars_t::uidnext => newuid & fix comment the purpose of this variable is to hold the UIDNEXT value from before we started pushing new messages, i.e., the minimal uid we can expect them to have. 2013-03-30 13:14 Oswald Buddenhagen * src/: config.c, mbsync.1, util.c: make paths relative to CWD, after all the test suite actually relies on it. it would be possible to adjust it, but there is not much reason to make paths relative to HOME (as we support convenient tilde expansion). so use the least invasive approach, which is simply the old behavior. adjust the documentation accordingly. This reverts commit da5ce5d8f42a15a2842d6d14043452f1a7892a0a. 2013-03-29 17:22 Oswald Buddenhagen * src/socket.c: improve socket error reporting always use getsockopt() to query the meaning of POLLERR, rather than reporting "Unidentified socket error". this is unlikely to have any effect when using select(), as that one pretty much never signals exceptional conditions. 2013-03-29 16:51 Oswald Buddenhagen * src/socket.c: factor out socket_connect_failed() 2013-03-29 17:11 Oswald Buddenhagen * src/socket.c: improve socket connect() error reporting with poll() turns out that poll() may (and on linux does) signal POLLERR on connection failure. this is unlike select(), which is specified to signal write readiness in every case. consequently, check whether we are connecting before checking for POLLERR. 2013-03-29 15:00 Oswald Buddenhagen * src/: isync.h, main.c: introduce -DC option to only install a crash handler 2013-03-24 13:46 Oswald Buddenhagen * configure.in: don't claim that we are looking for exactly bdb 4.2 2013-03-24 12:09 Oswald Buddenhagen * src/mbsync.1: match flag names in man page "Full" is an alias for "All", but let's stick to one. 2013-03-24 10:10 Oswald Buddenhagen * src/: config.c, util.c: make path expansion match docu: paths are relative to ~ the current behavior of being relative to the current directory sort of makes no sense, and contradicts the docu. 2013-03-24 10:10 Oswald Buddenhagen * src/compat/: isync.1, main.c: disable SSLv2 by default in the wrapper as well 2013-03-23 14:07 Oswald Buddenhagen * src/drv_maildir.c: downcast time_t to long for printing time_t may be long long. to keep the sprintf format strings simple, just downcast - this is not going to be a problem for the next 30 years, and until then long will be 64-bit everywhere anyway. suggested 3.5 years ago by Antoine Reilles . 2013-03-23 08:59 Oswald Buddenhagen * src/drv_imap.c: fix cram-md5 authentication we need to send a newline after the response for imap to grok it. 2013-03-23 09:34 Oswald Buddenhagen * src/drv_imap.c: fix crashes in imap_open_store() error paths it's not a good idea to invoke imap_open_store_bail() twice, either ... 2013-03-17 13:32 Oswald Buddenhagen * src/socket.c: fix crash in ssl connection error path not a good idea to invoke the callback twice ... 2013-03-17 11:41 Oswald Buddenhagen * src/: isync.h, mbsync.1, socket.c: rewrite SSL certificate verification. again. leave all the hard work to OpenSSL. this has several consequences: - certificate chain validation actually works instead of throwing around error 20 - the interactive approval is gone. i don't expect it to be useful anyway, as mbsync is mostly a batch tool - the code is much shorter 2013-02-21 07:02 Oswald Buddenhagen * README: language fix 2013-02-21 07:01 Oswald Buddenhagen * README: make build instructions more explicit 2013-02-03 16:34 Oswald Buddenhagen * src/socket.c: fix CVE-2013-0289: add SSL subject verification we did not check a valid certificate's subject at all so far. this is no problem if the certificate file contains only exactly the wanted host's certificate - before revision 04fdf7d1 (dec 2000, < v0.4), this was even enforced (more or less - if the peer cert had been signed directly by a root cert, it would be accepted as well). however, when the file contains root certificates (like the system-wide certificate file typically does), any host with a valid certificate could pretend to be the wanted host. 2013-02-03 16:47 Oswald Buddenhagen * src/: drv_imap.c, isync.h, mbsync.1, socket.c: add support for (disabling) TLS v1.1 and v1.2 2012-10-16 07:27 Oswald Buddenhagen * src/drv_imap.c: more error checking of IMAP responses REFMAIL: CA+Tk8fyu-6bwXq=ee2BgcKK_13m9S0RS+-0DhM=_jFqSKCH8aw@mail.gmail.com 2012-09-22 15:48 Oswald Buddenhagen * src/: drv_imap.c, socket.c, util.c: flush stdout more to make sure it is timely written and not interleaved with stderr even when when redirected. 2012-09-22 15:35 Oswald Buddenhagen * src/sync.c: fix TrashRemoteNew copy direction 2012-09-16 11:03 Oswald Buddenhagen * src/main.c: consider hierarchy delimiter flattening when deciding what to list flattened sub-folders of INBOX actually end up in Path, so list that instead. REFMAIL: 6c0ecbff0d025387020281c5d2f5e6e8@smallsys.org 2012-09-16 10:34 Oswald Buddenhagen * src/main.c: try harder to list all necessary boxes the pattern "INB*" may or may not refer to something in the INBOX. even just "*" may. so list both the INBOX and the Path in case of uncertainty. 2012-09-15 13:15 Oswald Buddenhagen * src/: config.c, drv_maildir.c, isync.h, mbsync.1, run-tests.pl, sync.c: add option to control amount of fsync()ing 2012-09-15 12:38 Oswald Buddenhagen * src/sync.c: avoid that a system crash can cause messages to be propagated twice fdatasync() the journal after creating the pair record and recording the TUID, but before the message propagation actually starts. all other writes to the journal are not flushed, as they will at worst cause some unnecessary network traffic without visible effect. 2012-09-15 12:15 Oswald Buddenhagen * src/drv_maildir.c: avoid that a system crash can lose mails this fixes two possible failure scenarios: - if the journal is committed but the mails are not, the missing files would be erroneously interpreted as deletions which would be propagated - less seriously, if the mail files' meta data was committed but the file contents were not, we would end up with empty files, which would have to be re-fetched "behind mbsync's back" (just deleting the files would not work - see above) 2012-09-15 11:25 Oswald Buddenhagen * src/sync.c: avoid that a system crash can clobber the sync state file make sure that the new state is committed to disk before overwriting the old version - by default meta data is committed first, so we may end up with no valid state at all otherwise. 2012-09-15 09:57 Oswald Buddenhagen * src/compat/config.c: quote mailbox names written to config file 2012-09-15 09:49 Oswald Buddenhagen * src/config.c: make more config file errors fatal we really shouldn't just synchronize despite config parsing errors. 2012-09-15 09:46 Oswald Buddenhagen * src/: config.c, drv_imap.c, drv_maildir.c, isync.h: store config error status in conffile_t object this makes passing it around more straight-forward 2012-09-15 09:24 Oswald Buddenhagen * src/: config.c, drv_imap.c, isync.h, util.c: make config parser a bit more careful about quotes the parsing is more shell-like now: - quoted and unquoted parts can be mixed in one argument - the hashmark can be meaningfully quoted 2012-09-09 10:18 Oswald Buddenhagen * src/drv_maildir.c: call fdatasync() after updating .uidvalidity files they must be flushed before the file system meta data, as otherwise we may end up with duplicate UIDs after a system crash. 2012-09-02 15:35 Ben Kibbey * src/socket.c: Fix certificate verification. The connection state wasn't getting updated. 2012-08-26 13:17 Oswald Buddenhagen * README, src/compat/isync.1, src/mbsync.1: pre-release doc updates 2011-04-10 17:25 Oswald Buddenhagen * src/: compat/main.c, config.c, drv_imap.c, drv_maildir.c, isync.h, main.c, sync.c, util.c: update copyrights make the wrapper's help string also mention copyrights pertaining only to the actual syncer, as this is the only string many people will ever see. 2011-04-10 17:34 Oswald Buddenhagen * src/: compat/config.c, compat/convert.c, compat/isync.1, compat/isync.h, compat/main.c, compat/util.c, config.c, drv_imap.c, drv_maildir.c, isync.h, main.c, mbsync.1, mdconvert.1, mdconvert.c, run-tests.pl, socket.c, sync.c, util.c: replace FSF address with something more ... contemporary 2012-08-26 14:29 Oswald Buddenhagen * src/: Makefile.am, compat/Makefile.am: install the config examples to docdir 2012-08-26 14:16 Oswald Buddenhagen * Makefile.am: update debian packaging 2012-08-26 13:02 Oswald Buddenhagen * Makefile.am, isync.spec.in: fix rpm packaging 2012-08-26 11:36 Oswald Buddenhagen * src/: isync.h, sync.c, util.c: use a hash table for message => sync record lookup this removes the pathological O( * ) case at the cost of being a bit more cpu-intensive (but O()) for old messages. 2012-08-25 18:30 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1: make use of UID EXPUNGE 2012-08-18 11:58 Oswald Buddenhagen * src/: config.c, isync.h, main.c, mbsync.1, sync.c: introduce ability to flatten the hierarchy of Stores 2012-08-11 16:34 Oswald Buddenhagen * configure.in, src/drv_imap.c, src/drv_maildir.c, src/isync.h, src/main.c, src/mbsync.1, src/util.c: add support for hierarchical mailboxes 2012-08-11 15:11 Oswald Buddenhagen * src/drv_maildir.c: calculate trash box path already in maildir_open_store() this gives us some cleaner code paths later on, as we can treat the trash box like a regular mailbox. 2012-08-11 15:05 Oswald Buddenhagen * src/drv_maildir.c: ensure that mailbox creation in maildir_store() is limited to trashing other mailboxes would have been maildir_select()ed already. 2011-06-13 10:13 Oswald Buddenhagen * src/drv_imap.c: refactor: imap_select2_p2 => imap_refcounted_done_box soon, we'll use it for something different, too 2012-08-25 13:34 Oswald Buddenhagen * src/sync.c: don't crash when select() on master fails synchronously svars->drv[S] would not be initialized yet, so cancel_sync() would crash. 2012-08-18 10:48 Oswald Buddenhagen * src/: isync.h, main.c, sync.c: fix error handling of invalid SyncState * when we find that the store is incompatible with in-store sync state, we want to fail the whole channel. however, we must not claim that the store died, otherwise it won't be disposed of properly. 2011-06-02 17:21 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c: reject qualified mailboxes with the magic name INBOX otherwise we couldn't tell them apart from the real INBOX after stripping away the Path. 2011-07-25 07:25 Oswald Buddenhagen * src/: drv_maildir.c, mdconvert.c: suppress bdb complaints about unknown file format pass DB_TRUNCATE when creating databases. otherwise bdb will complain about the empty file we pass it (we have to create it upfront to implement our locking). 2011-06-02 10:43 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1: Revert "fix UIDNEXT handling" in fact, UIDNEXT (and UIDVALIDITY) null is *not* allowed (see RFC3501 section 9). them popping up nonetheless was a dovecot bug (which would also confuse dovecot itself). having it in as a workaround was no good either, as quite some other code in mbsync assumes that UIDs are not null. This reverts commit e1fa867 and most of 39006d7. -REFMAIL: 4CA62BA1.4020104@lemma.co.uk 2012-08-25 13:29 Oswald Buddenhagen * src/: drv_maildir.c, isync.h, main.c, run-tests.pl: deal with concurrent maildir modifications during listing files may be renamed (due to new -> cur transition or flag changes), which may lead to two effects if ignored: - we see both the old and the new name, so we report a spurious duplicate UID - we see neither name, so we report a spurious deletion as countermeasure, record and compare directory modification times. upon mismatch, we just start over - as usual. 2011-05-03 07:42 Oswald Buddenhagen * src/drv_maildir.c: make maildir uidvalidity change fatal it's best to give the user a chance to fix it rather than completely messing up the syncstate by re-enumerating the UIDs. 2011-05-22 15:53 Oswald Buddenhagen * src/drv_maildir.c: cleanup maildir error paths don't try to unlock and close databases and files - this will happen a moment later anyway, through cancelation or re-selection. ironically, this plugs a memory leak, because an open main database is used as a signal to close a temporary db in maildir_scan(). 2011-05-22 15:23 Oswald Buddenhagen * src/drv_maildir.c: fix potential double free the store may be discarded before we reach maildir_select() again, which will leave us with a dangling pointer. 2011-05-22 15:22 Oswald Buddenhagen * src/drv_maildir.c: plug memory leak in maildir_store_msg() upon failure to acquire UID 2011-04-10 11:06 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, run-tests.pl, sync.c: employ alternative scheme to finding messages by TUID instead of SEARCHing every single message (which is slow and happens to be unreliabe with M$ Exchange 2010), just FETCH the new messages from the mailbox - the ones we just appended will be amongst them. 2011-04-03 09:29 Oswald Buddenhagen * src/sync.c: clearer debug msg 2011-04-11 08:46 Oswald Buddenhagen * src/: isync.h, mdconvert.c: use ATTR_PRINTFALIKE 2012-09-01 15:21 Oswald Buddenhagen * src/: socket.c, sync.c, util.c: fix line wrapping before info messages unless an info message is explictly marked as a continuation, it must terminate any pending line (typically the progress information) first. debug output is not affected, as it is mutually exclusive with info output, and no debug lines are left unterminated outside clear scopes. 2011-06-02 08:14 Oswald Buddenhagen * src/: isync.h, main.c, util.c: remove Ontty flag i can't figure out why i added it in the first place. it doesn't seem to make any sense ... 2011-04-11 08:45 Oswald Buddenhagen * src/: isync.h, sync.c, util.c: centralize flushing of unfinished debug lines 2011-04-10 13:32 Oswald Buddenhagen * src/: compat/config.c, compat/convert.c, compat/isync.h, compat/main.c, compat/util.c, config.c, drv_imap.c, drv_maildir.c, isync.h, mdconvert.c, socket.c, sync.c, util.c: unify error reporting - introduce sys_error() and use it instead of perror() and error(strerror()) in all expected error conditions - perror() is used only for "something's really wrong with the system" kind of errors - file names, etc. are quoted if they are not validated yet, so e.g. an empty string becomes immediately obvious - improve and unify language - add missing newlines 2011-03-27 18:39 Oswald Buddenhagen * src/drv_maildir.c: don't complain about disappearing temp files some other process might be cleaning up concurrently ... 2011-03-27 15:50 Oswald Buddenhagen * src/isync.h: enlarge receive buffer considerably the tiny buffer makes no sense in the face of huge payloads and now additionally masses of replies from pipelined commands. 2011-03-13 14:03 Oswald Buddenhagen * configure.in, src/drv_imap.c, src/mdconvert.c: compile with -ansi -pedantic on gcc greatly helps portability ... 2012-09-01 19:14 Oswald Buddenhagen * configure.in, src/compat/isync.h, src/compat/main.c, src/isync.h: define _GNU_SOURCE on the command line that way it is already set in configure and can thus be used by tests. 2011-03-20 17:23 Oswald Buddenhagen * src/drv_imap.c: centralize imap_cmd_refcounted_state refcount decrementing no else branches remain, so the if() can be put into imap_refcounted_done() 2011-03-12 15:16 Oswald Buddenhagen * src/drv_imap.c: get rid of redundant literal_pending state flag 2012-08-25 16:26 Oswald Buddenhagen * configure.in, src/drv_imap.c, src/isync.h, src/mbsync.1, src/socket.c: fully asynchronous IMAP operation - asynchronous sockets using an event loop - connect & starttls have completion callback parameters - callbacks for notification about filled input buffer and emptied output buffer - unsent imap command queue - used when - socket output buffer is non-empty - number of commands in flight exceeds limit - last sent command requires round-trip - command has a dependency on completion of previous command - trashnc is tri-state so only a single "scout" trash APPEND/COPY is sent at first. a possibly resulting CREATE is injected in front of the remaining trash commands, so they can succeed (or be cancel()d if it fails). - queue's presence necessitates imap_cancel implementation 2011-03-13 13:29 Oswald Buddenhagen * configure.in, src/isync.h, src/main.c, src/util.c: add simple mainloop implementation not used so far 2011-03-19 18:40 Oswald Buddenhagen * src/socket.c: move responsibility for closing sockets on error to user the only user being imap and the first thing in imap_cancel_store() being a call to socket_close(), this code was pretty pointless anyway. 2011-03-27 14:50 Oswald Buddenhagen * src/: drv_imap.c, isync.h, socket.c: make socket read/write error reporting callback-based the functions still have synchronous return codes as well - this enables early error returns without having to resort to refcounting. 2011-04-03 16:47 Oswald Buddenhagen * src/: drv_imap.c, isync.h, socket.c: decouple the filling of the read buffer from consuming it this prepares the code for being called from a callback. notably, this makes the imap list parser have a "soft stack", so the recursion can be suspended at any time. 2011-03-27 10:34 Oswald Buddenhagen * src/drv_imap.c: centralize imap_cmd disposal 2011-03-13 13:12 Oswald Buddenhagen * src/: drv_imap.c, isync.h, socket.c: make socket_write() capable of taking ownership of the buffer that way the user code doesn't have to free it any more. 2011-03-13 12:40 Oswald Buddenhagen * src/: drv_imap.c, socket.c: change socket_write() return code semantics instead of returning a write()-like result, return only a binary status code - write errors are handled internally anyway, so user code doesn't have to check the write length. 2011-03-27 14:58 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1: make IMAP pipeline depth configurable currently, this affects only "clustered" message listings and flag stores. 2011-03-19 21:12 Oswald Buddenhagen * src/drv_imap.c: cancel submitted commands when canceling store we already have some minimal asynchronicity, so there might be commands in flight when a fatal error comes in. 2011-01-23 13:06 Oswald Buddenhagen * src/: drv_imap.c, isync.h, socket.c: Socket_t + buffer_t => conn_t remove the layering, in favor of a "buffered connection" abstraction. 2011-04-10 11:28 Oswald Buddenhagen * src/socket.c: security fix: failure to load the certificate file is *not* OK ... 2011-01-23 12:43 Oswald Buddenhagen * src/: Makefile.am, drv_imap.c, isync.h, socket.c: move socket code to a separate file this makes the layering more obvious 2011-03-13 11:06 Oswald Buddenhagen * src/drv_imap.c: move greeting response handling into get_cmd_result() the primary purpose of this is getting rid of the "free-standing" buffer_gets() call. 2011-04-03 16:21 Oswald Buddenhagen * src/: drv_imap.c, isync.h, sync.c: docs - insert "separator comments" between driver entry points - document driver API - document sync_vars_t parts that are stored in the sync state header 2011-04-03 16:15 Oswald Buddenhagen * src/drv_imap.c: make imap_exec() result reporting callback-based this makes the IMAP command submission interface asynchronous. the functions still have synchronous return codes as well - this enables clean error return paths. only when we invoke callbacks we resort to refcounting. as a "side effect", properly sequence commands after CREATE resulting from [TRYCREATE]. 2011-07-24 18:27 Oswald Buddenhagen * src/sync.c: rely on the maildir's existence with "SyncState *" now that we open the box first, we know that it will exist at this point. 2011-07-24 18:26 Oswald Buddenhagen * src/drv_maildir.c: validate maildirs more strictly now that "SyncState *" won't create fake mailboxes any more, we can make a full validity check again. 2011-07-23 14:06 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, sync.c: split out drv->load() from drv->select() 2011-07-23 14:13 Oswald Buddenhagen * src/drv_maildir.c: make creation of trash folder independent from -C option the trash is not a box which is synced, but a "byproduct" of manipulating synced boxes, so it makes no sense to bind it to the same option. 2012-07-29 23:07 Oswald Buddenhagen * src/drv_imap.c: minor cleanup: use ctx->gen instead of gctx for consistency 2012-07-29 21:15 Oswald Buddenhagen * src/sync.c: make callbacks return early when canceling even after driver->cancel() the store may complete commands successfully. return early in this case, so we don't attempt to continue syncing. 2012-07-29 21:14 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, sync.c: fix error paths wrt sync drivers, take 2 synchronous error codes which are passed through callbacks aren't a particularly good idea, after all: latest when the callback does stuff which does not concern the caller, the return code becomes ambiguous. instead, protect the sync_vars object with a refcount when invoking driver functions from loops, as the callbacks they call could invalidate the object and we would have no way of knowing that the loop should be aborted prematurely. the upcoming async imap driver will also need a refcount to protect the cancelation marker of the imap socket dispatcher loop. 2011-04-03 14:29 Oswald Buddenhagen * src/sync.c: don't call cancel() repeatedly on a store erroring command replies will trickle in even after canceling 2012-07-15 10:55 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, main.c, sync.c: replace DRV_STORE_BAD with a separate bad_callback() that way we don't have to piggy-back (possibly asynchronous) fatal errors to particular commands. internally, the drivers still use synchronous return values as well, so they don't try to access the invalidated store after calling back. 2012-07-22 15:46 Oswald Buddenhagen * src/sync.c: don't access free'd memory in cancel_sync() as it happens, the 1st round *may* trash svars - if we get the cancelation request after the slave store has already died. 2012-07-22 15:32 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, sync.c: make drv->cancel()'s callback have no status code this function is not going to actually execute any commands, so it makes no sense for the callback to have a status code. 2012-06-17 12:52 Oswald Buddenhagen * src/sync.c: don't decode aux pointer on DRV_CANCELED the aux data was already free()d by the error callback by the time we get this status code. 2011-03-20 12:45 Oswald Buddenhagen * src/drv_imap.c: always use return value from get_cmd_result() once we have callback-based error reporting, this will ensure that we don't operate on invalidated data structures. 2010-12-05 15:49 Oswald Buddenhagen * src/drv_imap.c: make response code parse failure of untagged OK/NO/BYE/BAD non-fatal as such, it does not disrupt the data stream 2012-07-15 10:50 Oswald Buddenhagen * src/main.c: de-duplicate code a bit 2010-12-15 18:01 Oswald Buddenhagen * src/drv_imap.c: remove redundant use_ssl variables just use the presence of an SSL object as an indicator. if something goes wrong during the ssl handshake or certificate validation, the socket must be immediately closed anyway. 2010-11-20 22:48 Oswald Buddenhagen * src/isync.h: DRV_SERVER_BAD is and will probably stay unused => trash 2010-11-20 09:17 Oswald Buddenhagen * src/drv_imap.c: after [TRYCREATE], just resend the same command instead of cloning it 2011-03-20 15:27 Oswald Buddenhagen * src/drv_imap.c: use return values from correct set in get_cmd_result() DRV_OK == RESP_OK, so this worked by accident 2010-11-15 09:38 Oswald Buddenhagen * src/drv_imap.c: do away with the dreaded rcaps hack don't pretend that the server has no literal+ for the time of the first relevant command's synchronous execution. instead, enable the lower layer to do the processing by telling it for which commands trashnc ("trash's existence not confirmed") is relevant. 2010-11-15 09:30 Oswald Buddenhagen * src/drv_imap.c: purge imap_store_t::currentnc vestiges we always actually open the mailbox before appending to it, so we obviously know that it exists - that's why the code was already commented out. changing this assumption would significantly complicate matters for little gain, so let's just assume it won't happen. consequently, also don't set param.create when appending to regular mailboxes. 2011-06-13 10:02 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, main.c: move setting of ctx->listed outside the drivers it's essentially an external state flag 2011-04-10 07:58 Oswald Buddenhagen * src/sync.c: de-duplicate error paths makes the code more compact. yay for gotos. 2011-07-23 10:49 Oswald Buddenhagen * src/drv_maildir.c: check return value from close() after write() otherwise we may lose data when quota is exceeded or nfs is in a bad mood. 2012-07-07 15:19 Oswald Buddenhagen * src/: compat/convert.c, drv_imap.c, drv_maildir.c, sync.c: fix a bunch of warnings 2011-03-27 10:06 Oswald Buddenhagen * src/: compat/main.c, drv_imap.c, main.c: avoid preprocessor warnings on missing features: #if => #ifdef 2011-03-12 15:20 Oswald Buddenhagen * src/drv_imap.c: less bizarre code we know that there is only one command in progress, so there is no need to employ tricks to access the last command. 2011-01-23 12:35 Oswald Buddenhagen * src/drv_imap.c: make cram() sane - don't silently fail in release mode (expression with side effects inside assert()) - save some redundand strlen()s by not throwing away known lengths - reorganize the code for legibility 2010-11-20 22:04 Oswald Buddenhagen * src/sync.c: don't compare find_old_done with find_new_total this didn't have any effect as no async drivers currently exist. 2010-12-19 22:33 Oswald Buddenhagen * src/main.c: don't hang if store cannot be opened asynchronously 2011-03-06 22:04 Oswald Buddenhagen * src/drv_imap.c: don't leak SSL objects 2011-03-27 09:01 Oswald Buddenhagen * src/sync.c: add CR after TUID during LF => CRLF conversion 2011-03-27 08:52 Oswald Buddenhagen * src/sync.c: fix (another) out-of-bounds access in CRLF conversion if the header contained no CRs but the body (or the post-TUID part of the header) did, the TUID insertion would add an excess CR, thus overflowing the buffer by one byte. 2010-11-14 16:23 Oswald Buddenhagen * src/mbsync.1: document some breakage 2010-11-14 15:44 Oswald Buddenhagen * src/: compat/convert.c, drv_imap.c, drv_maildir.c: turns out, free(NULL) is just fine ... 2010-10-03 12:31 Oswald Buddenhagen * src/drv_imap.c: fix UIDNEXT handling UIDNEXT *can* be legally zero, so deal with it. -REFMAIL: 4CA62BA1.4020104@lemma.co.uk 2010-10-03 09:53 Oswald Buddenhagen * src/drv_imap.c: don't hang after failed start_tls() we'd send a LOGOUT command in plain text while the server was already expecting an encrypted command, which would typically lead to waiting for more data and thus an indefinite hang. so close the socket immediately instead of letting the normal shutdown path take care of it. inspired by a patch by Steven Flintham. -REFMAIL: 4C9AB98E.3000400@lemma.co.uk 2010-09-26 13:26 Oswald Buddenhagen * src/drv_imap.c: remove useless message don't complain about missing greeting response - we already complained about an unexpected EOF anyway. 2010-04-05 11:15 Oswald Buddenhagen * src/drv_imap.c: assert valid file handles i've seen error logs of the type SSL_write: Bad file descriptor and i simply can't nail it, so go for some more drastic measures. 2010-04-05 11:08 Oswald Buddenhagen * src/drv_imap.c: formatting 2010-04-05 11:08 Oswald Buddenhagen * src/drv_imap.c: beautify error messages don't print the error number - we print the error string anyway, so it adds no value. add some whitespace to the messages as well. 2010-04-05 11:06 Oswald Buddenhagen * src/drv_imap.c: fix uninitialized variable read this is basically a security fix for nonsensical configurations: if the specified CertificateFile did not contain any certificates, we *might* have accepted an arbitrary server certificate. 2010-02-28 21:23 Oswald Buddenhagen * src/: compat/isync.1, mbsync.1: remove mail addresses from man pages apparently, some people don't see the "maintained by" bits, so make them look harder for explicit contact information (to be found in AUTHORS). 2010-02-07 20:20 Oswald Buddenhagen * src/drv_imap.c: fix compile with SSL on Mac OS X patch by Remko Tronçon BUG: 2126899 2010-02-07 16:36 Oswald Buddenhagen * src/compat/: isync.1, main.c: add -P option to isync wrapper not really a backwards compat option, but whatever ... based on a patch submitted long ago by "nobody". BUG: 1433532 2010-02-07 21:13 Oswald Buddenhagen * isync.spec.in: fix rpm spec file -REFMAIL: 20090122213325.GA11572@crow.ths.tcoek12.org 2010-02-07 21:12 Oswald Buddenhagen * Makefile.am: (new?) automake already sets docdir correctly for us 2010-02-07 11:24 Oswald Buddenhagen * .gitignore, Makefile.am, src/.gitignore, src/compat/.gitignore: cvsignore => gitignore 2010-02-07 11:23 Oswald Buddenhagen * Makefile.am, autogen.sh: adjust ChangeLog generation to git now that log generation is cheap, don't store it in the SCM any more. 2010-02-06 18:38 Oswald Buddenhagen * Makefile.am: fix "make distcheck" this makes the deb-clean target shadow build safe 2010-02-06 09:40 Oswald Buddenhagen * src/: compat/main.c, drv_imap.c, isync.h, main.c: add extra verbose mode which dumps the message contents i needed that to debug the line ending issues. maybe it will find other uses as well ... 2010-02-06 09:34 Oswald Buddenhagen * src/: drv_maildir.c, isync.h, sync.c: fix line ending conversion logic imap may very well store messages with LF line endings. only RFC2822 requires CRLF. consequently, preserve the line endings as much as possible unless the mailbox format does not support it (this would be the case for unix mbox - i actually have no idea about maildir). 2010-02-06 09:32 Oswald Buddenhagen * src/sync.c: some more error reporting relating malformed messages 2008-08-31 20:14 Oswald Buddenhagen * src/drv_imap.c: refactoring. main part is killing struct imap_cmd_cb as such. issue_imap_cmd is split into new_imap_cmd and submit_imap_cmd, so the command can be parametrized after it was instanciated. 2008-08-23 07:54 Oswald Buddenhagen * src/: drv_imap.c, sync.c: deal with UIDVALIDITY of 0 properly. -REF: 20080822094543.GA3528@ugly.local 2008-04-13 09:56 Oswald Buddenhagen * src/drv_imap.c: give the implicitly created imap account config the name of the store. 2008-04-13 09:51 Oswald Buddenhagen * src/drv_imap.c: make ssl certificate handling much more useful: - system-wide ca certs are auto-loaded - private certs are accepted even if they are self-signed 2008-04-12 08:58 Oswald Buddenhagen * src/drv_imap.c: - accept unset CertificateFile - print the certificate's fingerprint - make the certificate acceptance prompt much less scary 2008-04-12 08:13 Oswald Buddenhagen * src/drv_imap.c: ignore system flag extensions (\X-...) 2008-03-16 09:09 Oswald Buddenhagen * README: minor updates 2008-02-23 14:18 Oswald Buddenhagen * src/compat/config.c: compat wrapper: don't crash if neither host nor tunnel are specified. fixes: CCMAIL: 449006@bugs.debian.org 2008-02-23 09:37 Oswald Buddenhagen * src/compat/config.c: quote user name in generated config. fixes: CCMAIL: 456775@bugs.debian.org 2008-02-23 09:18 Oswald Buddenhagen * src/main.c: don't overlook 2nd and later single-letter options in last argument. reported by fedora -REF: <1197916586.13945.120.camel@localhost.localdomain> 2008-02-23 09:01 Oswald Buddenhagen * src/: compat/convert.c, drv_maildir.c, mdconvert.c: put pointers to bdb open() into parentheses, so they won't be macro-expanded as libc open. patch by fedora -REF: <1197916586.13945.120.camel@localhost.localdomain> 2008-02-23 08:53 Oswald Buddenhagen * AUTHORS: reshuffle for "contact priority's" sake 2007-09-22 08:45 Oswald Buddenhagen * src/drv_imap.c: don't use #ifdef inside htons() arguments - it can be a macro. -REF: CCMAIL: Scott Gifford 2007-04-04 17:03 Oswald Buddenhagen * Makefile.am: forward port (finally ...): add target for creating signed package 2007-04-04 16:19 Oswald Buddenhagen * src/main.c: #ifdef __linux__ for the crash handler. it compiles on other platforms, but the functionality is bound to linux' /proc structure. 2007-02-10 15:37 Oswald Buddenhagen * src/drv_imap.c: fix crash due to uninited var when parsing IMAPServer. Thanks to CCMAIL: Antoine Reilles REF: <20070118182534.GA22288@arcelot.loria.fr> 2006-12-09 10:39 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, sync.c: fix error paths wrt sync drivers 2006-12-09 10:38 Oswald Buddenhagen * src/run-tests.pl: handle abnormal program exit during regtest 2006-12-04 17:47 Oswald Buddenhagen * src/main.c: initialize mvars->t[1] to 1. helps enormously ... :} 2006-11-18 13:17 Oswald Buddenhagen * src/drv_maildir.c: reverse-map to INBOX when encountered during listing. usually this will be a no-op (when putting INBOX in Path, people generally call it INBOX), but better safe than sorry. 2006-11-09 17:57 Oswald Buddenhagen * src/compat/main.c: make compat wrapper default to current user for imap login 2006-11-01 06:19 Oswald Buddenhagen * src/compat/config.c: put INBOX in Maildir 2006-10-24 17:37 Oswald Buddenhagen * src/drv_maildir.c: don't crash on truncating database. seems to affect only some bdb versions (e.g., 4.2). 2006-08-10 07:01 Oswald Buddenhagen * src/sync.c: fix bug in newline conversion causing buffer overflows. this leads to segfaults and has some security impact. 2006-08-10 06:33 Oswald Buddenhagen * src/drv_imap.c: memmove for overlapping mem copies. 2006-07-31 05:30 Oswald Buddenhagen * src/drv_maildir.c: glibc seems to be *really* fucked up. 2006-07-29 11:52 Oswald Buddenhagen * src/: drv_maildir.c, mdconvert.c: work around glibc bug: printf("%.*s", INT_MAX, s) tries to allocate 2G. 2006-06-05 11:59 Oswald Buddenhagen * src/compat/config.c: enable the old account naming scheme to deal with duplicated ip addresses. this is not incompatible - previously, it would just create garbage. 2006-06-05 11:55 Oswald Buddenhagen * src/compat/: config.c, isync.h: create more descriptive account names, so password prompts look sane. the channel names follow the old scheme, though - they are used to compose sync state file names, and i don't feel like writing a migrator for this. 2006-05-28 16:03 Oswald Buddenhagen * src/drv_imap.c: don't crash in imap driver when Host is not specified. 2006-05-28 16:02 Oswald Buddenhagen * src/mbsync.1: be *slightly* more explicit about which options Tunnel makes superfluous. 2006-05-28 15:43 Oswald Buddenhagen * src/: drv_imap.c, mbsync.1: un-document "Host imaps:[...]" syntax and introduce new option UseIMAPS instead. apply ted's patch to support UseIMAPS in conjunction with Tunnel. document that SSLv2 is No Good (TM). 2006-05-28 13:38 Oswald Buddenhagen * src/drv_imap.c: move assigning default port to the place of use 2006-05-27 12:44 Oswald Buddenhagen * src/drv_maildir.c: add comment 2006-05-27 12:43 Oswald Buddenhagen * src/sync.c: seen messages are eligible for expiration even if they are recent in the mailbox. 2006-03-21 20:05 Oswald Buddenhagen * src/main.c: no/empty mailbox name means INBOX 2006-03-21 20:03 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, main.c, sync.c, util.c: make the driver model, sync_chans() and sync_boxes() fully async. async drivers to follow ... 2006-03-21 17:50 Oswald Buddenhagen * src/sync.c: unscrew lf=>crlf conversion and tuid insertion 2006-03-21 17:40 Oswald Buddenhagen * src/sync.c: ok, mismerging and not running the reg-tests is lame. unscrew expunging again. 2006-03-21 16:03 Oswald Buddenhagen * src/sync.c: don't enter trash loop if not trashing at all. also, move expunge message where it belongs. not adding info("trashing"), as it will be replaced in a moment anyway. 2006-03-21 15:53 Oswald Buddenhagen * src/: main.c, sync.c: async merge: aggregate most variables of main() & sync_boxes() in main_vars_t resp. sync_vars_t. also some minor var renames, whitespace, comments. 2006-03-21 10:38 Oswald Buddenhagen * src/main.c: split box list preparation from "consumption". 2006-03-21 10:30 Oswald Buddenhagen * src/: isync.h, main.c, sync.c: info() about opening of stores 2006-03-20 20:39 Oswald Buddenhagen * src/drv_imap.c: do not repeatedly get namespace from server. 2006-03-20 20:34 Oswald Buddenhagen * src/drv_imap.c: handle socket() failure and correctly report gethostbyname() failure. 2006-03-20 20:16 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, main.c, sync.c, util.c: update copyrights 2006-03-20 19:38 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, main.c: move whole responsibility for recycling open stores/server connections to the drivers. 2006-03-20 19:27 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, main.c: keep the result of driver->list() and a flag whether it is valid in the store. 2006-03-20 18:36 Oswald Buddenhagen * src/: config.c, isync.h: aggregate all (two ...) drivers in an array instead of naming them in each (one ...) location explicitly. 2006-03-20 17:21 Oswald Buddenhagen * src/drv_imap.c: whitespace and code verbosity 2006-03-20 15:01 Oswald Buddenhagen * src/drv_imap.c: merge imap_t into imap_store_t - there is really no point in having them separated. 2006-03-19 11:29 Oswald Buddenhagen * src/: config.c, drv_imap.c, drv_maildir.c, isync.h, main.c, sync.c, util.c: "fprintf( stderr," => "error(". new functions debugn() and infon() for messages with missing newline; warn() and error() act upon this. 2006-03-19 10:44 Oswald Buddenhagen * src/drv_imap.c: make config parsing more robust against bogus input and report errors more clearly. 2006-02-12 11:42 Oswald Buddenhagen * src/sync.c: factor out box selection from sync_boxes to avoid code dupe 2006-02-11 20:28 Oswald Buddenhagen * src/sync.c: lock the sync state open the journal before opening the master. this is a bit ugly for the "SyncState *" case, as we have to create a directory without making it a maildir right away. however, this makes the code quite a bit simpler to understand and simpler to parallelize. 2006-02-11 20:14 Oswald Buddenhagen * src/drv_maildir.c: don't barf at directories with none of {tmp,new,cur}/ and turn them into maildirs instead. see next commit. 2006-02-11 20:02 Oswald Buddenhagen * src/sync.c: don't commit state file when a fatal error occurs 2006-02-11 19:52 Oswald Buddenhagen * src/sync.c: unbelieveable, but close() can actually fail 2006-02-11 19:48 Oswald Buddenhagen * src/run-tests.pl: add copyright + license 2006-02-09 17:44 Oswald Buddenhagen * acinclude.m4, get-cert, src/compat/config.c, src/compat/convert.c, src/compat/isync.1, src/compat/isync.h, src/compat/main.c, src/compat/util.c, src/config.c, src/drv_imap.c, src/drv_maildir.c, src/isync.h, src/main.c, src/mbsync.1, src/mdconvert.1, src/mdconvert.c, src/sync.c, src/util.c: update fsf's postal address. i think it's sort of useless nowadays anyway, but heck ... 2006-02-05 17:42 Oswald Buddenhagen * src/mbsync.1: typos 2006-02-05 17:39 Oswald Buddenhagen * configure.in: bump version. no, i'm not releasing yet ... :) 2006-02-05 17:38 Oswald Buddenhagen * src/Makefile.am: include run-tests.pl in distribution 2006-02-03 23:43 Oswald Buddenhagen * src/sync.c: and now don't clobber the mails ... 2006-02-03 21:33 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, sync.c, util.c: wrap message storing into transactions. nice side effect: drivers don't need to deal with line end conversion any move. 2006-02-02 17:03 Oswald Buddenhagen * src/: isync.h, sync.c: major overhaul of flag change propagation and MaxMessages handling: - wrap message (un)expirations into transactions - no redundand flag propagations in conjunction with expirations - better prepared for the upcoming async operation 2006-02-02 13:48 Oswald Buddenhagen * src/main.c: crash handler that launches gdb. activated when started with -D option. simplifies debugging crashes during the reg-tests. 2006-02-02 11:23 Oswald Buddenhagen * src/sync.c: less cluttered debug output 2006-02-02 11:12 Oswald Buddenhagen * src/sync.c: cosmetics: move around variable declarations and remove obsolete comment 2006-02-02 11:07 Oswald Buddenhagen * src/sync.c: versioned journal. the commands and their meanings change all the time, so better handle that case. ps: yes, i think not upgrading mbsync between interrupting and resuming a run is a reasonable requirement. 2006-02-02 10:44 Oswald Buddenhagen * src/sync.c: make the sync entry search in the journal replay wrap around at the end of the list. the "always forward" assumption is violated in some cases. 2006-02-02 10:25 Oswald Buddenhagen * src/run-tests.pl: much improved journal replay testing. some clenup. 2006-02-02 10:04 Oswald Buddenhagen * src/: run-tests.pl, sync.c: orphan/kill all affected entries after expunge 2006-01-31 13:57 Oswald Buddenhagen * Makefile.am: deal with branches in "make log" 2006-01-30 13:49 Oswald Buddenhagen * src/: isync.h, sync.c: M_EXPIRED -> M_EXPIRE 2006-01-30 13:11 Oswald Buddenhagen * src/sync.c: sanitize S_DEL 2006-01-30 13:01 Oswald Buddenhagen * src/sync.c: remove superfluous temporary rflags from sync_boxes 2006-01-30 11:12 Oswald Buddenhagen * src/: isync.h, sync.c: now that messages know their sync records, M_SYNCES is superfluous. 2006-01-30 10:26 Oswald Buddenhagen * src/: isync.h, sync.c: establish bi-directional mapping between mails and sync records. use it to merge the --renew case into the --new case. 2006-01-30 09:33 Oswald Buddenhagen * src/sync.c: declaring ex[M] instead of ex[2] is, indeed, no good. long live watchpoints. 2006-01-29 18:40 Oswald Buddenhagen * src/compat/main.c: whoops - 'isync -w' would write .mbsyncrc to a wrong directory 2006-01-29 15:52 Oswald Buddenhagen * src/sync.c: move fetching new messages in front of syncing old entries. this alone does not buy us a whole lot ... 2006-01-29 15:48 Oswald Buddenhagen * src/run-tests.pl: test for journalling and journal replay. 2006-01-29 15:46 Oswald Buddenhagen * src/: isync.h, main.c, sync.c: undocumented flag -J to skip committing the new sync state. 2006-01-29 14:46 Oswald Buddenhagen * src/: drv_imap.c, isync.h, main.c, sync.c, util.c: merge Quiet, Verbose & Debug into DFlags 2006-01-29 11:49 Oswald Buddenhagen * src/: isync.h, sync.c: M_NOT_SYNCED => M_SYNCED. now that sync records know their messages, it is simpler to track the positive case. 2006-01-29 11:35 Oswald Buddenhagen * src/sync.c: move driver options composition below journal replay - it might make additional actions necessary (it doesn't, yet). 2006-01-29 11:22 Oswald Buddenhagen * src/: drv_imap.c, drv_maildir.c, isync.h, sync.c: split driver->prepare into ->prepare_opts and ->prepare_paths 2006-01-25 06:35 Oswald Buddenhagen * src/drv_imap.c: #include limits.h (for INT_MAX) REF: 2006-01-13 16:10 Oswald Buddenhagen * src/sync.c: less confusing uid ranges in debug 2006-01-12 06:36 Oswald Buddenhagen * configure.in, src/drv_imap.c: solaris 10 fix: use sys/filio.h for FIONREAD. untested. REF: <20060111215014.GA601@49.180.97-84.rev.gaoland.net> 2006-01-08 19:25 Oswald Buddenhagen * src/run-tests.pl: adjust to: omit flags other than "deleted" when expunging target. 2006-01-03 09:28 Oswald Buddenhagen * src/run-tests.pl: collect stderr as well. 2005-12-29 13:08 Oswald Buddenhagen * src/sync.c: don't record we synced flags if we didn't. 2005-12-28 20:45 Oswald Buddenhagen * src/util.c: have to flush debug as well ... 2005-12-28 20:05 Oswald Buddenhagen * src/sync.c: of course F_DELETED will have been added to expired slave messages, so don't complain about it. 2005-12-28 19:17 Oswald Buddenhagen * src/sync.c: put message references into the sync records. match up the uids after opening the boxes instead of "sort-of-on-demand" - this is much simpler. match from messages to sync records, not the other way round - makes the debug output shorter, as the separate dump_box() is gone now. 2005-12-28 19:10 Oswald Buddenhagen * src/sync.c: "reformat" S_EXP_S setting logic for understandability. 2005-12-28 11:07 Oswald Buddenhagen * src/main.c: whoops 2005-12-28 10:02 Oswald Buddenhagen * src/: config.c, isync.h, main.c, sync.c: - instead of having {m,s}foo, we have foo[2] now, so we can do everything with loops instead of symmetric function calls - added some const 2005-12-27 17:44 Oswald Buddenhagen * src/run-tests.pl: show debug output on error. 2005-12-27 17:31 Oswald Buddenhagen * src/run-tests.pl: make the error case output more useful by dumping the entire data set. 2005-12-26 16:02 Oswald Buddenhagen * src/run-tests.pl: fix error message 2005-12-26 16:02 Oswald Buddenhagen * src/run-tests.pl: add expiration tests 2005-12-26 16:01 Oswald Buddenhagen * src/run-tests.pl: add MaxSize tests 2005-12-26 16:00 Oswald Buddenhagen * src/run-tests.pl: when dumping mailboxes, sort by uid 1st. 2005-12-26 15:58 Oswald Buddenhagen * src/run-tests.pl: detect excess messages after sync 2005-12-26 15:57 Oswald Buddenhagen * src/run-tests.pl: sync state reader: - grok negative uids - more robust 2005-12-26 15:54 Oswald Buddenhagen * src/run-tests.pl: don't eat array lead-in on empty arrays 2005-12-26 15:02 Oswald Buddenhagen * src/sync.c: why would somebody manipulate an expired message? right, he wouldn't: he would either expunge the mailbox or configure his MUA to hide trashed messages. consequently don't sync expired message flags, let alone interpret them in a special way. one special feature remains, though: if a non-expunged expired message is flagged on the master, it will be unexpired on the slave. i'm not sure whether i should remove or document this feature. 2005-12-26 14:55 Oswald Buddenhagen * src/sync.c: message tweaks 2005-12-23 10:22 Oswald Buddenhagen * src/run-tests.pl: more logical order 2005-12-22 18:06 Oswald Buddenhagen * src/: .cvsignore, run-tests.pl: add some regression testing. 2005-12-22 14:59 Oswald Buddenhagen * src/sync.c: fix sync entries not being purged due to c&p error. 2005-12-21 13:04 Oswald Buddenhagen * src/drv_maildir.c: less confusing error message on invalid mailbox. 2005-12-18 14:10 Oswald Buddenhagen * src/config.c: it's beyond me what this memset was supposed to do ... 2005-12-18 13:41 Oswald Buddenhagen * src/: config.c, main.c: trailing whitespace 2005-12-17 13:47 Oswald Buddenhagen * src/drv_imap.c: revert 1.8 - what was i smoking?! the CREATE argument is already quoted; we just extracted it from the previous command. 2005-09-29 21:07 Oswald Buddenhagen * src/drv_maildir.c: make flag changes unset "new" status - unless a ghost is acting in the background, a flag change indicates that the message was at least noticed. 2005-09-29 21:05 Oswald Buddenhagen * src/sync.c: don't call the driver's set_flags() if the flags did not change at all. 2005-09-21 16:14 Oswald Buddenhagen * src/drv_imap.c: 64-bit cleanness 2005-03-28 10:43 Oswald Buddenhagen * src/drv_imap.c: quote CREATE argument 2005-03-28 10:26 Oswald Buddenhagen * configure.in: bump version 2005-03-28 10:26 Oswald Buddenhagen * src/drv_maildir.c: fix inverted condition leading to endless loop when message is changed while isync is running. 2004-11-13 09:19 Oswald Buddenhagen * src/sync.c: cope with out-of-disk-space halfways gracefully (that is, don't clobber the sync state including the journal, but exit immediately). 2004-10-17 16:31 Oswald Buddenhagen * AUTHORS: sf.net -> sourceforge.net. otherwise the list-post is different from the actual address, which makes mutt add two to addresses on list-reply ... 2004-10-17 15:34 Oswald Buddenhagen * src/drv_imap.c: ignore user-defined flags (for now). also, split off the backslash from the "core" flag names. 2004-10-17 09:00 Oswald Buddenhagen * src/drv_imap.c: fix segfault due to wrong pointer being passed to parse_response_code. inspired by Raimar Döffinger 2004-10-17 08:30 Oswald Buddenhagen * src/drv_imap.c: remove spurious crlf during cram auth. not sure that this instance of socket_write should be (re)moved, but as long as the .cont callback is used only for this ... investigation & patch by Mike Delaney. 2004-09-24 08:45 Oswald Buddenhagen * Makefile.am: install supplementary doc files. REF: 38C5E3CF30C73C4984F41AE8786C852AB739@khyron.ads.cs.umass.edu 2004-09-20 11:31 Oswald Buddenhagen * src/drv_maildir.c: use legacy flock() only on linux. at least on OS X flock aliases to fcntl. 2004-09-20 11:28 Oswald Buddenhagen * src/: compat/main.c, drv_imap.c, isync.h, util.c: stdarg.h at the right places 2004-09-15 09:33 Oswald Buddenhagen * README: update c-client compatibility 2004-09-15 09:06 Oswald Buddenhagen * src/drv_maildir.c: when storing \seen messages, don't set the \recent flag on them. could well be that this is incorrect, but some mailers need it that way. when trashing messages, preserve their \recent status as well. 2004-09-15 08:44 Oswald Buddenhagen * configure.in: whoops, wrong define 2004-09-08 16:40 Oswald Buddenhagen * configure.in: don't encode maturity in version number 2004-09-08 16:38 Oswald Buddenhagen * Makefile.am: optimize rpms for i686 2004-09-08 16:28 Oswald Buddenhagen * configure.in: sanitize the OpenSSL detection 2004-09-08 16:14 Oswald Buddenhagen * src/drv_imap.c: stddef.h for offsetof 2004-09-08 14:52 Oswald Buddenhagen * src/drv_maildir.c: first check _both_ bounds, then compare ... 2004-09-07 11:59 Oswald Buddenhagen * src/sync.c: print name of mailbox being opened. 2004-08-13 11:03 Oswald Buddenhagen * src/drv_imap.c: fix -C for imap mailboxes: - SELECT does not return [TRYCREATE] - fix bit field truncation 2004-06-17 13:44 Oswald Buddenhagen * configure.in: A{C,S}_HELP_STRING aliasing tricks. 2004-05-23 16:39 Oswald Buddenhagen * src/drv_maildir.c: store new UIDVALIDITY immediately after initializing it 2004-04-27 20:23 Oswald Buddenhagen * src/compat/main.c: old -l is new -l -C 2004-04-26 14:48 Oswald Buddenhagen * src/compat/: config.c, isync.h, main.c: full support for absolute paths in Mailboxes 2004-04-26 14:09 Oswald Buddenhagen * src/compat/config.c: strip $HOME and ~ from Mailbox paths 2004-03-29 22:32 Oswald Buddenhagen * src/: compat/util.c, util.c: fix return values of asprintf replacement. 2004-03-29 06:52 Oswald Buddenhagen * src/compat/: config.c, isync.1, isync.h, main.c: unscrew --delete by merging it into the config file. merge --expunge as well for symmetry. 2004-03-27 16:07 Oswald Buddenhagen * .cvsignore, Makefile.am, README, configure.in, isync.spec.in, src/.cvsignore, src/Makefile.am, src/compat/.cvsignore, src/compat/Makefile.am, src/compat/config.c, src/compat/convert.c, src/compat/isync.1, src/compat/isync.h, src/compat/isyncrc.sample, src/compat/main.c, src/compat/util.c, src/config.c, src/cram.c, src/dotlock.c, src/dotlock.h, src/drv_imap.c, src/drv_maildir.c, src/imap.c, src/isync.h, src/list.c, src/maildir.c, src/main.c, src/mbsync.1, src/mbsyncrc.sample, src/mdconvert.1, src/mdconvert.c, src/sync.c, src/util.c: The Big Rewrite. too many change to list them all. as opposed to earlier threats, BerkDB was not entirely dropped; i suppose the isync 0.7 -> 0.8 change had a reason, so i added an alternative UID storage scheme. note that BDB 4.0 is not sufficient, as the db->open function changed in an incompatible way ... i updated the debian packaging except for a changelog entry. note that i removed the upgrade blurb, as upstream now has a smooth upgrade path down to at least isync 0.4. 2004-03-26 16:34 Oswald Buddenhagen * get-cert: excessively secure temp file creation. more user friendliness. 2004-02-07 15:36 Oswald Buddenhagen * src/dotlock.c: portability: don't rely on struct flock layout 2004-02-01 16:44 Oswald Buddenhagen * .cvsignore: shht 2004-02-01 16:27 Oswald Buddenhagen * src/: main.c, sync.c: once again: (slightly) better output. make maildir flag setting failure non-fatal. maildir sucks ... 2004-01-31 01:01 Oswald Buddenhagen * src/: imap.c, isync.h: more sophisticated CAPABILITY handling. also, don't issue the command if the initial response already had it in the status code. 2004-01-30 23:39 Oswald Buddenhagen * src/imap.c: don't ask for NAMESPACE if Folder was specified 2004-01-30 23:35 Oswald Buddenhagen * src/: imap.c, isync.h: following the "screw murphy" principle and commiting untested patch: obey LOGINDISABLED 2004-01-27 21:01 Oswald Buddenhagen * src/imap.c: PREAUTH cannot come out of the blue 2004-01-27 20:58 Oswald Buddenhagen * src/imap.c: cleanup around parse_fetch 2004-01-27 20:50 Oswald Buddenhagen * src/: imap.c, isync.h, main.c: make Tag int, move it to imap.c 2004-01-27 00:11 Nicolas Boullis * acinclude.m4, configure.in: Add a --disable-maintainer-mode option to configure. 2004-01-20 01:55 Oswald Buddenhagen * src/imap.c: don't use STARTTLS for PREAUTH connections. uw-imap doesn't seem to like it, and it does not make too much sense anyway - i think - state converse opinions now. 2004-01-20 01:27 Oswald Buddenhagen * Makefile.am: exclude ChangeLog (do'h), NEWS and TODO when creating ChangeLog. exclude debian/ as well, based on the fact that it already has a detailed log - is that ok with everybody? 2004-01-18 02:22 Oswald Buddenhagen * isync.1, src/imap.c, src/isync.h, src/maildir.c, src/main.c, src/sync.c: another message output cleanup, still not perfect (info messages will be interleaved with progress dots). support specifying -q twice to suppress warnings as well. 2004-01-17 11:38 Oswald Buddenhagen * isync.1: document mua interaction 2004-01-16 10:11 Oswald Buddenhagen * AUTHORS: credit where credit is due. are the comments satisfactory for everybody? 2004-01-15 03:51 Theodore Ts'o * get-cert: Script that can be used to extract the server's certificate from an IMAP server. 2004-01-15 02:23 Oswald Buddenhagen * configure.in: remove useless define and more verbose error message. 2004-01-13 03:56 Theodore Ts'o * configure.in: Use a more sophisticated test for the existence of libdb that works for berk_db 4.0. 2004-01-12 01:49 Oswald Buddenhagen * configure.in: bah, forgot to remove debian/Makefile.in from AC_OUTPUT. :} kde's overly sophisticated build system does that automatically ... 2004-01-12 01:24 Theodore Ts'o * src/: imap.c, isync.h, main.c: Optimized isync by not fetching the sizes of messages if they are unneeded (i.e., if MaxSize is not specified in the config file). Patch and idea originally from Nicolas Boullis , modified/polished by Theodore Ts'o per comments by Oswald Buddenhagen. 2004-01-12 00:52 Oswald Buddenhagen * configure.in, src/isync.h, src/maildir.c, src/sync.c: sync uid database after every message. this is accompanied by a dbm -> db4 migration. patch by theodore, with some final polishing by me. 2004-01-12 00:38 Oswald Buddenhagen * Makefile.am: use ../CVSROOT/accounts for UID mapping in ChangeLog. 2004-01-12 00:36 Oswald Buddenhagen * AUTHORS: be more explicit about contact address 2004-01-11 12:38 Oswald Buddenhagen * .cvsignore: new stuff 2004-01-11 12:35 Oswald Buddenhagen * Makefile.am: getting rid of Makefile.am in debian/ - it seems to be non-standard and is a pita to maintain anyway. instead, make distdir and distclean depend on a partial debian-clean. 2004-01-11 11:53 Oswald Buddenhagen * autogen.sh: don't call configure 2004-01-09 20:43 Oswald Buddenhagen * src/main.c: ignore anything that does not look remotely like a maildir when collecting mailboxes for OneToOne. 2003-12-07 15:37 Oswald Buddenhagen * isyncrc.sample: add sample CertificateFile 2003-12-07 15:36 Oswald Buddenhagen * src/imap.c: add trailing space to password prompt 2003-12-07 15:34 Oswald Buddenhagen * src/main.c: make imaps: on the command line adjust the port and ssl options as well 2003-12-07 15:09 Oswald Buddenhagen * configure.in: bump version 2003-12-02 02:53 Oswald Buddenhagen * src/imap.c: echo the mailbox the password is for 2003-11-11 03:02 Oswald Buddenhagen * AUTHORS: be more explicit about maintainership, as people don't seem to get it. 2003-09-02 12:06 Oswald Buddenhagen * isync.1: minor additions 2003-07-02 17:18 Oswald Buddenhagen * src/imap.c: fix crash when syncing multiple mailboxes over a Tunnel 2003-05-14 13:42 Oswald Buddenhagen * isync.1: minor 2003-05-07 00:06 Oswald Buddenhagen * .cvsignore, Makefile.am, autogen.sh, configure.in, src/config.c, src/cram.c, src/dotlock.c, src/imap.c, src/isync.h, src/list.c, src/maildir.c, src/main.c, src/sync.c: - make it work without SSL - switch from -Ds in Makefile to config.h - small header cleaup 2003-05-07 00:04 Oswald Buddenhagen * isync.spec.in: make it actually work 2003-05-06 02:17 Oswald Buddenhagen * Makefile.am: minors 2003-05-06 02:15 Oswald Buddenhagen * README: i'm bored :) 2003-05-05 17:58 Oswald Buddenhagen * src/: config.c, isync.h, main.c: don't free any config strings - who cares for a few bytes? this fixes some crashes at exit. 2003-05-05 17:17 Oswald Buddenhagen * Makefile.am: switch ChangeLog generation to cvs2cl 2003-05-05 13:43 Oswald Buddenhagen * isync.1: minor fixes 2003-05-05 13:41 Oswald Buddenhagen * configure.in: cleanup 2003-05-05 13:24 Oswald Buddenhagen * src/main.c: accumulate status over multiple mailboxes, i.e., don't abort after first failure 2003-05-05 12:54 Oswald Buddenhagen * src/imap.c: fix imaps: 2003-02-27 18:43 Oswald Buddenhagen * src/sync.c: ignore \Recent, as it is voided by the syncronization run itself. 2002-12-28 15:31 Oswald Buddenhagen * src/: config.c, cram.c, imap.c, isync.h, list.c, maildir.c, main.c, sync.c: - update copyrights. 2003 didn't begin yet, but who cares? :) 2002-12-28 04:14 Oswald Buddenhagen * isync.1: - fixed typo - updated maintainer and location 2002-12-28 04:12 Oswald Buddenhagen * src/: maildir.c, sync.c: - update isyncmaxuid properly 2002-12-28 04:04 Oswald Buddenhagen * src/config.c: - fixed two crashes 2002-12-28 04:02 Oswald Buddenhagen * src/imap.c: - handle bogus search responses more gracefully 2002-12-28 04:00 Oswald Buddenhagen * src/imap.c: - workaround imap server bug: lock files are no mailboxes 2002-12-28 03:58 Oswald Buddenhagen * src/: imap.c, sync.c: - improve console output 2002-12-28 03:11 Oswald Buddenhagen * .cvsignore: - ssht! 2002-12-28 03:05 Oswald Buddenhagen * .cvsignore, AUTHORS, Makefile.am, README, autogen.sh, configure.in, isync.spec.in, src/.cvsignore, src/Makefile.am, src/config.c, src/cram.c, src/dotlock.c, src/dotlock.h, src/imap.c, src/isync.h, src/list.c, src/maildir.c, src/main.c, src/sync.c: - took over maintenance - moved to sourceforge - reorganized cvs structure 2002-10-30 02:31 Michael Elkins * config.c, cram.c, dotlock.c, dotlock.h, imap.c, isync.1, isync.h, list.c, maildir.c, main.c, sync.c: Updated the copyright notice to allow an exception for linking with OpenSSL, which has a non-GPL compatible license. 2002-10-30 02:23 Michael Elkins * .cvsignore, config.c, imap.c, isync.1, isync.h, maildir.c, main.c, sync.c: Bunch 'o patches from Oswald Buddenhagen: i implemented some cool stuff (tm). first, the long missing "create server-side missing mailboxes". -C now creates both local and remote boxes; -L and -R create only local/remote. second, i implemented a 1:1 remote:local folder mapping (-1) with an optional INBOX exception (inbox/-I). the remote folder is specified with the folder keyword (or -F switch) and takes precedence over the namespace setting. the local directory with the mailboxes can now be specified on the command line, too (-M). another patch: - made the -1 switch settable permanently (OneToOne). after all, you usually define your mailbox layout once forever. removed -A, as it is semantically -a modified by -1. - cleaned up message output a bit. still, the quiet variable should be used throughout the program. at best, create some generic output function, which obeys a global verbosity level variable. - optimized + cleaned up configuration parser slightly - minor cleanups add an (almost) unique id to every uploaded message and search for it right after. i thought about using the message-id, but a) it is not guaranteed to be unique in a mailbox (imagine you edit a mail and store the dupe in the same box) and b) some mails (e.g., postponed) don't even have one. a downside of the current implementation is, that this id-header remains in the mailbox, but given that it wastes only 27 bytes per mail and removing it would mean several roundtrips more, this seems acceptable. i changed the line-counting loop to use a mmapped file instead of reading it in chunks, as it makes things simpler and is probably even faster for big mails. the amount of goto statements in my code may be scary, but c is simply lacking a multi-level break statement. :) this is the "shut up" patch. :) it makes the -q option consequent, so to say. additionally it adds an -l option which gathers all defined/found mailboxes and just outputs the list. don't ask what i need it for. ;) 2002-10-30 02:01 Michael Elkins * maildir.c: fixed missing closedir() call (Joey Hess) 2002-06-27 03:55 Michael Elkins * imap.c: explicitly set global.pass to NULL when getpass() returns an empty string. 2002-06-27 03:51 Michael Elkins * imap.c: Oswald Buddenhagen * fix imap_open() brokeness with PREAUTH (missed hunk from previous patch) 2002-06-22 17:06 Michael Elkins * dotlock.c, imap.c: fixed errors introduced by ME when hand-applying Oswald Nuddenhagen's patch. 2002-06-22 01:21 Michael Elkins * autogen.sh, dotlock.c, imap.c, isync.h, main.c: Patch from Oswald Buddenhagen - move prompt for password to imap_open() - don't ask for global password in PREAUTH state - use socketpair() to create one full-duplex fd in tunnel mode instead of two half-duplex pipes - don't set lck.l_pid in fcntl() call (its read-only) - use F_SETLK instead of F_SETLKW to avoid infinite waiting - use "$@" in autogen.sh to get proper word expansion 2002-06-21 00:26 Michael Elkins * configure.in, isync.h: Fixed to compile under FreeBSD 4.6-RELEASE. Must include ndbm.h rather than db.h. 2002-06-20 23:33 Michael Elkins * Makefile.am, dotlock.c, dotlock.h, maildir.c: remove debian/files move dotlocking code to dotlock.c. dotlocking code fixed to ignore whether or not the lockfile exists on open(). we only care about whether fcntl() was able to lock it. 2002-06-19 02:31 Michael Elkins * sync.c: Don't bother uploaded messages marked deleted when we are going to expunge. 2002-06-19 01:11 Michael Elkins * AUTHORS, imap.c, maildir.c: fixed unused var warning in imap_open() locking cleanups from Oswald Buddenhagen * don't need to stat the lockfile since it will always be size 0 * only remove lockfile when we actually succeeded in locking 2002-06-19 00:44 Michael Elkins * Makefile.am: Debian package cleanups from Oswald Buddenhagen 2002-06-18 06:37 Michael Elkins * README, isync.1, isync.h, maildir.c, main.c, sync.c: updated URL for project fixed segmentation fault caused by double free() when an error occurred during the IMAP transmission. fixed bug where isync could not handle a 0 value UIDVALIDITY 2002-04-19 19:43 Michael Elkins * config.c, configure.in, imap.c, isync.1, isync.h, isyncrc.sample, main.c: PREAUTH support from Oswald Buddenhagen Added Tunnel directive to allow the user to specify a shell command to run to set up an IMAP connection in place of a TCP socket (eg., to run over an SSH session). 2002-01-28 19:39 Michael Elkins * isync.spec.in: post 0.8 release commit 2002-01-28 19:34 Michael Elkins * configure.in: check for dbm_open() in libc and libdb 2002-01-17 19:33 Michael Elkins * sync.c: don't bother renaming the message file if we are about to unlink() it 2002-01-16 22:23 Michael Elkins * AUTHORS, Makefile.am, sync.c: remove tilde backup files for distclean fixed indentation added full name to AUTHORS reformated NEWS blurb for 0.8 2002-01-16 22:13 Michael Elkins * maildir.c, sync.c: sync_mailbox() did not update the msg struct when flags were changed, causing the expunge command to fail remove bogus strfcpy() line 2002-01-16 21:51 Michael Elkins * Makefile.am, configure.in: added debian build files dist target so that people can use them to build their own .deb packages without having to use CVS 2002-01-16 21:43 Michael Elkins * isync.1, maildir.c, sync.c: added debian build files fixed indentation added bug note to manpage about db file format not being architecture independent 2002-01-16 21:22 Michael Elkins * maildir.c, sync.c: remove the uid from the db when a message is deleted from the maildir optimize db fetch/store to not copy the base filename 2002-01-16 19:47 Michael Elkins * config.c, configure.in, cram.c, imap.c, isync.1, isync.h, list.c, maildir.c, main.c, sync.c: updated year in copyright notice the uid for each message in the maildir is now stored in a dbm database rather than the filename. this change was necessary because isync became confused if you copied a message to another folder, in which case the uid was invalid. as a result of the above change, isync now acquires a mutex on the mailbox to protect the dbm database from concurrent access. main() was reworked to continue gracefully when an error is encountered, and to always call maildir_close() so that the lock can be disabled, and the database closed. 2001-11-20 18:28 Michael Elkins * Makefile.am, isync.spec.in: post 0.7-release commit 2001-11-20 18:06 Michael Elkins * Makefile.am, isync.1, isync.h, maildir.c, main.c: added --create/-C command line option to force creation of the local maildir-style mailbox if nonexistent debug.h was not included in isync_SOURCES in Makefile.am 2001-11-19 19:41 Michael Elkins * Makefile.am, config.c, configure.in, isync.h, list.c, main.c: added memory debugging code fixed memory leak in free_list() free memory associated with global settings on exit 2001-11-16 21:23 Michael Elkins * cram.c, imap.c, isync.h, sync.c: remove c++ style comments use %lu and cast off_t to unsigned long in printf() 2001-11-15 23:59 Michael Elkins * config.c, isync.1, isync.h, main.c, sync.c: Added MaxMessages patch from Eivind Eklund . config_defaults() can just use memcpy() instead of assigning each struct member individually. config_defaults() can be declared static 2001-11-14 17:40 Michael Elkins * config.c, configure.in: move strndup() code into config.c for less complexity change AC_REPLACE_FUNC(strndup) to AC_CHECK_FUNCS(strndup) sed expression checking for gcc-3.0 should be quoted beccause it fails under Solaris 2.7 2001-11-13 00:36 Michael Elkins * config.c, sync.c: strndup() could return a non-NULL terminated string size_t should be printed with %lu when expending tildes (~), an extra slash was inserted after the user's home directory 2001-11-12 23:03 Michael Elkins * isync.h, maildir.c, main.c: merge maildir_sync() and maildir_close(). the maxuid in a maildir still needs to be updated in --fast mode, and the sync code already checks to see if any changes were made to the mailbox. 2001-11-09 00:35 Michael Elkins * README: add FreeBSD to the list of tested platforms 2001-11-09 00:23 Michael Elkins * config.c, configure.in, imap.c, maildir.c: update version to 0.7 detect short write in write_strip() fix compilation warnings with gcc-2.95.4 2001-10-31 19:50 Michael Elkins * configure.in, imap.c, isync.h, main.c, sync.c: set compiler warnings for gcc-3.0 as well display message with count of uploaded messages --quiet now supresses warnings in sync_mailbox() fixed compiler warnings with -Wshadow 2001-10-31 06:06 Michael Elkins * isync.1: post 0.6 commit 2001-10-30 22:57 Michael Elkins * README, configure.in: add strndup replacement function for systems which lack it 2001-10-03 17:10 Michael Elkins * Makefile.am, maildir.c: fixed broken code in maildir_clean_tmp() 2001-10-03 16:48 Michael Elkins * maildir.c: added code to clean the tmp directory in a maildir to comply with maildir(5) 2001-10-03 06:32 Michael Elkins * config.c: forgot to add code to parse the `Delete' option 2001-10-03 06:18 Michael Elkins * main.c: forgot conditional #if HAVE_LIBSSL around setting of .use_imaps in main() from command line arguments 2001-10-03 06:15 Michael Elkins * main.c: update Copyright printed by --help add compile time option list to --help output 2001-10-03 05:42 Michael Elkins * config.c, isync.1, isync.h, isyncrc.sample, main.c, sync.c: added `Delete' configuration option to force -d option sync_mailbox() didn't consider MaxSize == 0 to mean "unlimited". load_config() needs to print a newline in its error messages since next_arg() kills the newline of the line that was read out of the config file. 2001-10-03 00:01 Michael Elkins * imap.c, sync.c: fixed maildir message filenames to comply with the maildir(5) specification. fixed write_strip() and imap_fetch_message() to check the return code of write() and fsync() to comply with maildir(5) spec. 2001-10-02 23:43 Michael Elkins * main.c: the `Expunge' config directive didn't work since only the -e command line argument was consulted. 2001-10-02 22:46 Michael Elkins * config.c, imap.c, isync.h: we should issue a CAPABILITY even if we aren't going to use ssl/tls so that cram-md5 auth still works. 2001-07-18 18:56 Michael Elkins * config.c: find_box() should attempt to expand all filenames if none of the other methods found a match. 2001-07-18 18:49 Michael Elkins * config.c, isync.h, maildir.c: fixed to not expand filenames until they are used inside of maildir_open(), so that aliases are not required for simple filenames. [re: http://bugs.debian.org/102255] 2001-06-22 23:30 Michael Elkins * main.c: --host option didn't check for imaps: prefix 2001-06-21 20:45 Michael Elkins * main.c: fixed core when specifying multiple mailboxes on the command line 2001-06-18 21:38 Michael Elkins * configure.in, imap.c, isync.1: handle untagged responses in imap_fetch_message() so that it doesn't bomb out if new mail arrives while in the process of downloading noted in BUGS section of man page that if new mail arrives after the initial message list has been retrieved from the IMAP server, that new mail will not be fetched until the next invocation of isync. 2001-06-18 17:49 Michael Elkins * config.c, imap.c, isync.h, main.c: isync should continue to process additional mailboxes even if there is an error with a previous mailbox. added -a (--all) flag to synchronize all mailboxes defined in ~/.isyncrc 2001-02-28 01:02 Michael Elkins * config.c, imap.c: fixed compiler warnings under Solaris 2.7 2001-02-19 18:44 Michael Elkins * cram.c, imap.c, maildir.c: rfc2595 compliance patch from Daniel Resare - CAPABILITY should be reissued after starting TLS since the previous call was not protected 2001-02-14 20:46 Michael Elkins * config.c, imap.c, isync.1, main.c, sync.c: patch from Daniel Resare : 1 giving a path to a nonexistant rc-file with the -c argument dumps core The patch adds a check to ensure that the given rc-file is accessible 2 the error messages given from failed openssl calls are bogus The handles the error from SSL_connect () correctly. The bug is understndable since the error handling in openssl is quite obfuscated. Good news is that the documentation manapges has been greatly updated in the latest version (0.9.6). See in particular err(3), ERR_get_error(3) and SSL_get_error(3). Please note that possible SSL_ERROR_SSL type errors from SSL_read() and SSL_write() is not handled. This should also be fixed. 3 connecting using the STARTTLS command with an imap server that is configured only to accept the TLSv1 protocol gives an error because isync sends an SSLv2 Hello message for backwards compability. (This is the case with the uw-imap 2000 that ships with redhat-7.0) I've read RFC2595 several times to see if it says something about compability SSL2/SSL3 hello messages but can't find anything. IMHO the correct thing to do is change the default to not use SSL2/3 compability hello when using the STARTTLS command but use it if the imaps port is used. The patch implements this change 4 repeated calls to SSL_CTX_set_options overwrites the old settings (the values needs to be ORed together) fixed in the patch patch from me@mutt.org: \Recent messages were put in the cur/ directory instead of new/ give error message when the LOGIN command fails 2001-02-01 23:35 Michael Elkins * imap.c: patch from Daniel Resare - don't initialize ssl support if none of use_sslv* is enabled 2001-01-26 20:21 Michael Elkins * imap.c, isync.h: include for off_t patch from "lorenzo martignoni" - fixed uploading of message to IMAP server 2001-01-24 07:09 Michael Elkins * config.c, cram.c, imap.c, isync.1, list.c, maildir.c, main.c, sync.c: fixed cram compilation error under bsd updated man page 2001-01-16 19:45 Michael Elkins * config.c, imap.c, isync.1, isync.h, main.c: added support for tilde (~) expansion in the `Mailbox' and `CertificateFile' configuration directives added `Maildir' configuration command to specify the default location of the user's mailboxes. If a relative path is used in a `Mailbox' command, this path is used as a prefix. 2001-01-11 10:21 Michael Elkins * configure.in, imap.c, isync.h: set imap->prefix to be the namespace prefix update version to 0.5 fixed compilation warnings in imap.c 2001-01-11 10:13 Michael Elkins * Makefile.am, config.c, imap.c, isync.1, isync.h, isyncrc.sample, main.c, sync.c: broke config code into config.c added support for uploading local messages with no UID to the IMAP server added Expunge configuration option added CopyDeletedTo configuration option 2001-01-09 20:09 Michael Elkins * maildir.c, sync.c: always put changed messages in the cur/ subdirectory since they are no longer new. don't set \Seen implicitly for messages in the cur/ folder. Require the S flag on the message since Mutt will move Old (unread, but not recent) messges into cur/. 2001-01-08 09:45 Michael Elkins * Makefile.am, main.c: patch from Hugo Haas -c was not specified in the getopt*() calls set global password to the one the user inputs and use that as the default for remaining mailboxes 2001-01-05 21:20 Michael Elkins * configure.in: added --with-ssl-dir to specify an alternate installation of OpenSSL 2000-12-31 22:39 Michael Elkins * isync.spec.in: pre 0.4 commit. updated rpm spec file 2000-12-31 22:37 Michael Elkins * sync.c: display how many messages were fetched from the server 2000-12-31 22:17 Michael Elkins * imap.c: fixed compilation error with no libssl support ("lorenzo martignoni" ) 2000-12-28 18:44 Michael Elkins * main.c: fixed config parser to accept arbitrary whitespace 2000-12-27 21:16 Michael Elkins * imap.c: use imap_close to terminate a connection in imap_open() 2000-12-27 21:14 Michael Elkins * imap.c, isync.1, isync.h, maildir.c, main.c: allow leading whitespace in config files now possible to sync multiple mailboxes by specifying multiple aliases on the command line. IMAP connections are reused if possible. don't initialize ssl unless we are going to use it. 2000-12-23 21:57 Michael Elkins * imap.c, isync.h: don't use NAMESPACE unless the server supports it 2000-12-23 00:02 Michael Elkins * Makefile.am, README, cram.c, imap.c, isync.h: added CRAM-MD5 authentication support. parse server capability string to determine if STARTTLS is available 2000-12-22 21:22 Michael Elkins * README, imap.c, isync.1, isync.h, main.c: isync-brokenservers.diff (Jeremy Katz ) adds support for disabling NAMESPACE, and disable various flavors of TLS/SSL for use with some broken IMAP servers. 2000-12-22 19:30 Michael Elkins * imap.c, sync.c: prompt user if they wish to continue if the server's X.509 certificate can't be verified. sync_mailbox should consider uid == 0 to be "unknown" 2000-12-22 15:48 Michael Elkins * main.c, sync.c: fixed sync_mailbox() to correctly write new messages to the local maildir box (Thomas Roessler ) 2000-12-22 15:24 Michael Elkins * main.c: set default MaxSize to 0 (unlimited) invert test for password being set after getpass() call (Magnus Jonsson ) 2000-12-22 07:14 Michael Elkins * configure.in, imap.c, isync.1, isync.h, isyncrc.sample, maildir.c, main.c, sync.c: added MaxSize configuration variable fixed --fast to work robustly without relying on the \Recent flag in messages 2000-12-21 23:10 Michael Elkins * imap.c, isync.h, maildir.c, sync.c: RFC822.PEEK is obsolete in RFC2060. Use BODY.PEEK[] instead, which does the same thing keep track of the uidvalidity so isync can detect if the mailbox on the server has changed since the last sync. 2000-12-21 20:56 Michael Elkins * Makefile.am, isync.spec.in: added support for building RPMS 2000-12-21 19:49 Michael Elkins * Makefile.am, isync.1: added target for creating html version of the man page documented the imaps: prefix to the Host command 2000-12-21 19:11 Michael Elkins * imap.c, sync.c: can't assume flag order when fetching a message. just search for the first `{' to find the message size. 2000-12-21 18:16 Michael Elkins * isync.1, sync.c: added BUGS section to manpage detailing the fact that we break the maildir(5) spec by parsing the filename change message delivery to use the method described in maildir(5) 2000-12-21 17:51 Michael Elkins * configure.in, main.c, sync.c: use getpass() to get the user's password unlink the temp file if we are unable to fetch a new message from the server. update version to 0.3 2000-12-21 11:14 Michael Elkins * isync.1: fixed typo in man page for --verbose option 2000-12-21 10:24 Michael Elkins * Makefile.am, README, imap.c, isync.h, list.c: added generic IMAP list parser and rewrote imap_exec() to handle arbitrary data instead of hardcoded 2000-12-21 06:51 Michael Elkins * Makefile.am, README, configure.in, main.c: fixes to compile cleanly under Solaris 2.7 2000-12-21 06:27 Michael Elkins * configure.in, imap.c, isync.1, isync.h, main.c: added OpenSSL support 2000-12-21 00:35 Michael Elkins * configure.in, main.c: config options were not case insensitive 2000-12-21 00:30 Michael Elkins * imap.c, isync.h, maildir.c, main.c, sync.c: don't fetch deleted messages when expunging display number of messages that are to be deleted flags for \Recent messages were not properly fetched local messages with updated flags were not corrected renamed 2000-12-20 22:28 Michael Elkins * Makefile.am: updated ChangeLog added log: rule in Makefile.am 2000-12-20 22:10 Michael Elkins * autogen.sh: added autogen.sh to regenerate the build environment 2000-12-20 22:00 Michael Elkins * COPYING: added missing files 2000-12-20 21:41 Michael Elkins * AUTHORS, Makefile.am, README, configure.in, imap.c, isync.1, isync.h, isyncrc.sample, maildir.c, main.c, sync.c: initial import isync-1.3.0/depcomp0000755000175000001440000005601713164125572011151 00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2016-01-11.22; # UTC # Copyright (C) 1999-2017 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, see . # 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 outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} 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" # Avoid interferences from the environment. gccflag= dashmflag= # 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 cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc 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. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## 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). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - 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 -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # 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. ## 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. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -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 -ne 0; then 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 ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # 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 ;; 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. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then 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" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; 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. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # 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 ;; #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 "X$1" != 'X--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|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | 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 "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi 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. -arch) eat=yes ;; -*|$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" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | 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 "X$1" != 'X--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 -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [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. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # 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 ;; 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-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: isync-1.3.0/isync.spec0000644000175000001440000000164013164141647011566 00000000000000Summary: Utility to synchronize IMAP mailboxes with local maildir folders Name: isync Version: 1.3.0 Release: 1 License: GPL Group: Applications/Internet Source: isync-1.3.0.tar.gz URL: http://isync.sf.net/ Packager: Oswald Buddenhagen BuildRoot: /var/tmp/%{name}-buildroot %description isync is a command line utility which synchronizes mailboxes; currently Maildir and IMAP4 mailboxes are supported. New messages, message deletions and flag changes can be propagated both ways. It is useful for working in disconnected mode, such as on a laptop or with a non-permanent internet collection (dIMAP). %prep %setup %build %configure %install rm -rf $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install rm -rf $RPM_BUILD_ROOT%{_docdir}/%{name} %clean rm -rf $RPM_BUILD_ROOT %files %doc AUTHORS COPYING NEWS README TODO ChangeLog src/mbsyncrc.sample src/compat/isyncrc.sample %{_bindir}/* %{_mandir}/man1/* isync-1.3.0/aclocal.m40000644000175000001440000014630413164125570011431 00000000000000# generated automatically by aclocal 1.15.1 -*- Autoconf -*- # Copyright (C) 1996-2017 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_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. 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'.])]) dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- dnl serial 11 (pkg-config-0.29) dnl dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR # Copyright (C) 2002-2017 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.15' 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.15.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 AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.15.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2017 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], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2017 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_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$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 m4_define([_AM_COND_VALUE_$1], [$2])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-2017 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. # 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", "OBJC", "OBJCXX", "UPC", or "GJC". # 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 m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" 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". rm -rf conftest.dir 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 am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) 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 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # 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. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; 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 ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj 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 $am__obj 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], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2017 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_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf 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"` # 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'`; 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"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2017 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 macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # 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.65])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], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) 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], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [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]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). 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])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # 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-2017 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 if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2017 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. # 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])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2017 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_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .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 # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2017 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_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 is modern enough. # If it is, 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 if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2017 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_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], [m4_foreach_w([_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])]) # Copyright (C) 1999-2017 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_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_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 AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2017 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_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2017 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_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # 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 ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file 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 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 if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done 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]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2017 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_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2017 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-2017 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]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2017 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_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. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} 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]) isync-1.3.0/NEWS0000644000175000001440000001175513164125503010265 00000000000000[1.3.0] Network timeout handling has been added. Support for proper Maildir++ and a Maildir sub-folder naming style without extra dots have been added. Support for TLS client certificates was added. Support for recovering from baseless UID validity changes was added. The get-cert script was renamed to mbsync-get-cert. [1.2.0] The 'isync' compatibility wrapper is now deprecated. An IMAP Path/NAMESPACE rooted in INBOX won't be handled specially any more. This means that some Patterns may need adjustment. The default output is a lot less verbose now. The meanings of the -V and -D options changed significantly. The SSL/TLS configuration has been re-designed. SSL is now explicitly enabled or disabled - "use SSL if available" is gone. Notice: Tunnels are assumed to be secure and thus default to no SSL. Support for SASL (flexible authentication) has been added. Support for Windows file systems has been added. Support for compressed data transfer has been added. Folder deletions can be propagated now. [1.1.0] Support for hierarchical mailboxes in Patterns. Full support for IMAP pipelining (streaming, parallelization) added. This is considerably faster especially with high-latency networks. Faster and hopefully more reliable support for IMAP servers without the UIDPLUS extension (e.g., M$ Exchange). More automatic handling of SSL certificates. IPv6 support. IMAP password query can be scripted. Message arrival dates can be propagated. Data safety in case of system crashes was improved. MaxMessages was made vastly more useful. [1.0.0] Essentially a rewrite. Synchronization state storage concept, configuration and command line changed entirely. But you needn't to worry about the upgrade, as a fully automated migration path is provided, even for users of isync 0.7 and below. Still, you should re-read the manual to be able to take full advantage of the new features: The supported mailbox types can be freely paired. A possible application of this is using a local IMAP server to access mailboxes that are not natively supported yet. Message deletions (expunges) are now propagated both ways, so there is no need for using mutt with maildir_trash any more. Additional trash options added. `OneToOne' replaced by something more flexible. Partial support for IMAP pipelining (streaming, parallelization) added. Makes flag change propagation much faster - this affects every message that becomes Seen/Read. [0.9] Added Tunnel directive to allow the user to specify a shell command to run to set up an IMAP connection in place of a TCP socket (eg., to run over an SSH session). Added PREAUTH support (useful mostly in conjunction with Tunnel). Messages marked deleted are not uploaded when we are going to expunge. Locally generated messages are not re-fetched after uploading even if the UIDPLUS extension is not supported by the server. Added `OneToOne' configuration option: ignore any Mailbox specifications and instead pick up all mailboxes from the local MailDir and remote Folder and map them 1:1 onto each other according to their names. -C now creates both local and remote boxes; -L and -R create only local/remote. --quiet is now really quiet. [0.8] !!! IMPORTANT !!! In order to fix the problem where messages copied from one mailbox to another were not uploaded to the new mailbox, the way Isync stores the UID for each message needed to be changed. As a result, you _MUST_ delete all the messages in the local maildir box before using this version. Otherwise it will upload every message to the server thinking its a new mail. [0.7] Added `MaxMessages' configuration option to allow tracking of only the most recently added message in the local mailbox. Added --create (-C) command line option to force creation of the local maildir-style mailbox if it doesn't already exist. [0.6] Added `Delete' configuration option to correspond to the -d command line option. Added -a (--all) command line option to synchronize all mailboxes. [0.5] Updated SSL support. Added CRAM authentication support. Added MailDir configuration option to specify the default location of local mailboxes when relative paths are used. Added support for uploading local messages to the IMAP server. Added CopyDeletedTo configuration option to cause isync to move deleted messages to a particular mailbox on the server when they are expunged. [0.4] Added MaxSize configuration option to limit downloading of new messages from the server to less than some threshold. More robust --fast option works without using \Recent flags, so the previous problem with multiple accesses killing these flags is no longer a problem. RFC2060 obsoleted RFC822.PEEK, use BODY.PEEK[] instead which does the same job. Don't need to request UID in a FETCH when doing UID FETCH (RFC2060 states that its automatically returned). [0.3] Fixed to clean up temp maildir files when the fetch of a new message failed. Fixed to not assume order of the flags returned by "UID FETCH" Added support for building RPMs. [0.2] SSL support added. [0.1] Initial release. isync-1.3.0/autodefs.h.in0000644000175000001440000000460213164125571012154 00000000000000/* autodefs.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if you have the `getaddrinfo' function. */ #undef HAVE_GETADDRINFO /* Define to 1 if you have the `getopt_long' function. */ #undef HAVE_GETOPT_LONG /* Define to 1 if you have the `inet_ntop' function. */ #undef HAVE_INET_NTOP /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* if your libc has IPv6 support */ #undef HAVE_IPV6 /* if you have the SASL libraries */ #undef HAVE_LIBSASL /* if you have the OpenSSL libraries */ #undef HAVE_LIBSSL /* if you have the zlib library */ #undef HAVE_LIBZ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memrchr' function. */ #undef HAVE_MEMRCHR /* 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 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 `strnlen' function. */ #undef HAVE_STRNLEN /* Define to 1 if you have the header file. */ #undef HAVE_SYS_POLL_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_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_TYPES_H /* Define to 1 if you have the `timegm' function. */ #undef HAVE_TIMEGM /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vasprintf' function. */ #undef HAVE_VASPRINTF /* 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 home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* if Berkeley DB should be used */ #undef USE_DB /* Version number of package */ #undef VERSION isync-1.3.0/missing0000755000175000001440000001533013164125572011164 00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2014 Free Software Foundation, Inc. # Originally written 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, see . # 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 case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: isync-1.3.0/INSTALL0000644000175000001440000003661413164125572010626 00000000000000Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell command './configure && make && make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the 'README' file for instructions specific to this package. Some packages provide this 'INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The 'configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a 'Makefile' in each directory of the package. It may also create one or more '.h' files containing system-dependent definitions. Finally, it creates a shell script 'config.status' that you can run in the future to recreate the current configuration, and a file 'config.log' containing compiler output (useful mainly for debugging 'configure'). It can also use an optional file (typically called 'config.cache' and enabled with '--cache-file=config.cache' or simply '-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how 'configure' could check whether to do them, and mail diffs or instructions to the address given in the 'README' so they can be considered for the next release. If you are using the cache, and at some point 'config.cache' contains results you don't want to keep, you may remove or edit it. The file 'configure.ac' (or 'configure.in') is used to create 'configure' by a program called 'autoconf'. You need 'configure.ac' if you want to change it or regenerate 'configure' using a newer version of 'autoconf'. The simplest way to compile this package is: 1. 'cd' to the directory containing the package's source code and type './configure' to configure the package for your system. Running 'configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type 'make' to compile the package. 3. Optionally, type 'make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type 'make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the 'make install' phase executed with root privileges. 5. Optionally, type 'make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior 'make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing 'make clean'. To also remove the files that 'configure' created (so you can compile the package for a different kind of computer), type 'make distclean'. There is also a 'make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type 'make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide 'make distcheck', which can by used by developers to test that all other targets like 'make install' and 'make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the 'configure' script does not know about. Run './configure --help' for details on some of the pertinent environment variables. You can give 'configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU 'make'. 'cd' to the directory where you want the object files and executables to go and run the 'configure' script. 'configure' automatically checks for the source code in the directory that 'configure' is in and in '..'. This is known as a "VPATH" build. With a non-GNU 'make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use 'make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple '-arch' options to the compiler but only a single '-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the 'lipo' tool if you have problems. Installation Names ================== By default, 'make install' installs the package's commands under '/usr/local/bin', include files under '/usr/local/include', etc. You can specify an installation prefix other than '/usr/local' by giving 'configure' the option '--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option '--exec-prefix=PREFIX' to 'configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like '--bindir=DIR' to specify different values for particular kinds of files. Run 'configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of '${prefix}', so that specifying just '--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to 'configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the 'make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, 'make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of '${prefix}'. Any directories that were specified during 'configure', but not in terms of '${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the 'DESTDIR' variable. For example, 'make install DESTDIR=/alternate/directory' will prepend '/alternate/directory' before all installation names. The approach of 'DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of '${prefix}' at 'configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving 'configure' the option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. Some packages pay attention to '--enable-FEATURE' options to 'configure', where FEATURE indicates an optional part of the package. They may also pay attention to '--with-PACKAGE' options, where PACKAGE is something like 'gnu-as' or 'x' (for the X Window System). The 'README' should mention any '--enable-' and '--with-' options that the package recognizes. For packages that use the X Window System, 'configure' can usually find the X include and library files automatically, but if it doesn't, you can use the 'configure' options '--x-includes=DIR' and '--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of 'make' will be. For these packages, running './configure --enable-silent-rules' sets the default to minimal output, which can be overridden with 'make V=1'; while running './configure --disable-silent-rules' sets the default to verbose, which can be overridden with 'make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX 'make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as 'configure' are involved. Use GNU 'make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its '' header file. The option '-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put '/usr/ucb' early in your 'PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in '/usr/bin'. So, if you need '/usr/ucb' in your 'PATH', put it _after_ '/usr/bin'. On Haiku, software installed for all users goes in '/boot/common', not '/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features 'configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, 'configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the '--build=TYPE' option. TYPE can either be a short name for the system type, such as 'sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file 'config.sub' for the possible values of each field. If 'config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option '--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with '--host=TYPE'. Sharing Defaults ================ If you want to set default values for 'configure' scripts to share, you can create a site shell script called 'config.site' that gives default values for variables like 'CC', 'cache_file', and 'prefix'. 'configure' looks for 'PREFIX/share/config.site' if it exists, then 'PREFIX/etc/config.site' if it exists. Or, you can set the 'CONFIG_SITE' environment variable to the location of the site script. A warning: not all 'configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to 'configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the 'configure' command line, using 'VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified 'gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash 'configure' Invocation ====================== 'configure' recognizes the following options to control how it operates. '--help' '-h' Print a summary of all of the options to 'configure', and exit. '--help=short' '--help=recursive' Print a summary of the options unique to this package's 'configure', and exit. The 'short' variant lists options used only in the top level, while the 'recursive' variant lists options also present in any nested packages. '--version' '-V' Print the version of Autoconf used to generate the 'configure' script, and exit. '--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally 'config.cache'. FILE defaults to '/dev/null' to disable caching. '--config-cache' '-C' Alias for '--cache-file=config.cache'. '--quiet' '--silent' '-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to '/dev/null' (any error messages will still be shown). '--srcdir=DIR' Look for the package's source code in directory DIR. Usually 'configure' can determine that directory automatically. '--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. '--no-create' '-n' Run the configure checks, but stop before creating any output files. 'configure' also accepts some other, not widely useful, options. Run 'configure --help' for more details. isync-1.3.0/TODO0000644000175000001440000001007713164160477010263 00000000000000f{,data}sync() usage could be optimized by batching the calls. make SSL (connect) timeouts produce a bit more than "Unidentified socket error". automatically resume upon transient errors, e.g. "connection reset by peer" or timeout after some data was already transmitted. possibly also try to handle Exchange's "glitches" somehow. add support for IMAP UTF-7 (for internationalized mailbox names). uidvalidity lock timeout handling would be a good idea. should complain when multiple Channels match the same folders. propagate folder deletions even when the folders are non-empty. - verify that "most" of the folders in the Channel are still there. - refuse to delete unpropagated messages when trashing on the remote side. - refuse to delete master if it has unpropagated messages. symmetry? add message expiration based on arrival date (message date would be too unreliable). MaxAge; probably mutually exclusive to MaxMessages. add alternative treatments of expired messages. ExpiredMessageMode: Prune (delete messages like now), Keep (just don't sync) and Archive (move to separate folder - ArchiveSuffix, default .archive). add support for event notification callbacks. it would be also possible to report more differentiated exit codes, but that seems too limiting in the general case. make it possible to have different mailbox names for Master and Slave in Patterns. - use master:slave for the pattern - for quoting, use more colons: the longest sequence of colons is the separator - this makes Groups mostly useless, as they are mostly a workaround for this function being missing so far - this is needed for move detection, which would work only within one Channel normalize INBOX capitalization received from IMAP, to avoid anomalies. kill the concept of an INBOX, it is a relic from single-channel operation. if somebody needs it, he can have two stores with different Paths. the path can name a single (in-)box (curr. broken with maildir). an empty box name actually means empty, so the IMAP mailbox should use INBOX for Path (can't make that the default, as it would mess up the NAMESPACE). add regexp-based mailbox path rewriting to the drivers. user would provide expressions for both directions. every transformation would be immediately verified with the inverse transform. PathDelimiter and Flatten would become special cases of this. add daemon mode. primary goal: keep imap password in memory. also: idling mode. parallel fetching of multiple mailboxes. TLS session resumption becomes interesting then as well. imap_set_flags(): group commands for efficiency, don't call back until imap_commit(). add streaming from fetching to storing. handle custom flags (keywords). make use of IMAP CONDSTORE extension (rfc4551; CHANGEDSINCE FETCH Modifier); make use of IMAP QRESYNC extension (rfc5162) to avoid SEARCH to find vanished messages. use MULTIAPPEND and FETCH with multiple messages. create dummies describing MIME structure of messages bigger than MaxSize. flagging the dummy would fetch the real message. possibly remove --renew. note that all interaction needs to happen on the slave side probably. don't SELECT boxes unless really needed; in particular not for appending, and in write-only mode not before changes are made. problem: UIDVALIDITY change detection is delayed, significantly complicating matters. some error messages are unhelpful in non-verbose mode due to missing context. possibly use ^[[1m to highlight error messages. consider alternative approach to trashing: instead of the current trash-before- expunge done by mbsync, let MUAs do the trashing (as modern ones typically do). mbsync wouldn't do any trashing by itself, but should track the moves for optimization. additionally, there should be a mode to move trashed messages to the remote store. TrashMode Internal|External, AbsorbRemoteTrash. a yet different approach to trashing is treating the trash like a normal mailbox. however, this implies a huge working set. consider optional use of messages-id (and X-GM-MSGID): - detection of message moves between folders - recovery from loss of sync state, migration from other tools isync-1.3.0/README0000644000175000001440000000447513141401733010444 00000000000000 _ (_)___ _ _ _ __ ___ | / __| | | | '_ \ / __| | \__ \ |_| | | | | (__ |_|___/\__, |_| |_|\___| |___/ isync/mbsync - free (GPL) mailbox synchronization program http://isync.sf.net/ See AUTHORS for contact information. ``mbsync'' is a command line application which synchronizes mailboxes; currently Maildir and IMAP4 mailboxes are supported. New messages, message deletions and flag changes can be propagated both ways. ``mbsync'' is suitable for use in IMAP-disconnected mode. Synchronization is based on unique message identifiers (UIDs), so no identification conflicts can occur (unlike with some other mail synchronizers). Synchronization state is kept in one local text file per mailbox pair; these files are protected against concurrent ``mbsync'' processes. Mailboxes can be safely modified while ``mbsync'' operates. Multiple replicas of each mailbox can be maintained. isync is the project name, while mbsync is the current executable name; this change was necessary because of massive changes in the user interface. An isync executable still exists; it is a compatibility wrapper around mbsync. * Features * Fine-grained selection of synchronization operations to perform * Synchronizes single mailboxes or entire mailbox collections * Partial mirrors possible: keep only the latest messages locally * Trash functionality: backup messages before removing them * IMAP features: * Supports TLS/SSL via imaps: (port 993) and STARTTLS * Supports SASL for authentication * Pipelining for maximum speed * Compatibility isync should work fairly well with any IMAP4 compliant server; servers that support the UIDPLUS and LITERAL+ extensions are most efficient. Courier 1.4.3 is known to be buggy, version 1.7.3 works fine. M$ Exchange (2013 at least) needs DisableExtension MOVE to be compatible with the Trash functionality. * Platforms At some point, ``isync'' has successfully run on: Linux, Solaris 2.7, OpenBSD 2.8, FreeBSD 4.3. * Requirements Berkeley DB 4.1+ (optional) OpenSSL for TLS/SSL support (optional) Cyrus SASL (optional) zlib (optional) * Installation ./autogen.sh (only when building from git) ./configure make sudo make install * Help Please see the man page for complete documentation.