jaromail

a commandline tool to easily and privately handle your e-mail
git clone git://parazyd.org/jaromail.git
Log | Files | Refs | Submodules | README

commit e78d55188900c78b110900d6e0c8ee7ee9ce18b1
parent 4253b833e3c9467a4c8688505313d52ff34ca3d4
Author: Jaromil <jaromil@dyne.org>
Date:   Wed, 10 Apr 2013 12:23:19 +0200

fixes for compilation on osx 10.8 with latest xcode

Diffstat:
Mbuild/build-osx.sh | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mbuild/clang-static-osx.sh | 6+++---
Dsrc/mutt-1.5.21/mutt_dotlock.c | 758-------------------------------------------------------------------------------
3 files changed, 115 insertions(+), 793 deletions(-)

diff --git a/build/build-osx.sh b/build/build-osx.sh @@ -15,17 +15,23 @@ builddir=`pwd` #cc="${builddir}/cc-static.zsh" -cc="${builddir}/clang-static-osx.sh" +#cc="gcc-4.7" +#cpp="cpp-4.7" +cc="llvm-gcc" +cpp="llvm-cpp-4.2" +# ${builddir}/clang-static-osx.sh" #cflags="-arch x86_64 -arch i386 -O2" - -cflags=(-I/opt/local/include -I/usr/include) -cflags+=(-arch x86_64) -cflags+=(-arch i386) +OSX_SDK=10.7 +cflags=(-I/usr/local/include -I/usr/include) +cflags+=(-I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${OSX_SDK}.sdk/usr/include) +# cflags+=(-arch x86_64) +# cflags+=(-arch i386) cflags+=(-O2) -ldflags="-L/opt/local/lib -L/usr/lib" +ldflags=(-L/usr/local/lib -L/usr/lib) +ldflags+=(-L/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX${OSX_SDK}.sdk/usr/lib) target=all @@ -67,11 +73,64 @@ copydeps() { done # 1st cp $1 build/osx/`basename $1`.bin + chmod +w build/osx/`basename $1`.bin + strip build/osx/`basename $1`.bin + for d in `cat $tmp | sort | uniq`; do + if ! [ -r build/osx/dylib/`basename $d` ]; then + cp $d build/osx/dylib/ + print " `basename $d`" + fi + done + + # create a wrapper + cat <<EOF > build/osx/`basename $1` +#!/usr/bin/env zsh +test -r \$HOME/Mail/jaro/bin/jaro && PDIR=\$HOME/Mail/jaro +test -r jaro/bin/jaro && PDIR="\`pwd\`/jaro" +test \$JAROMAIL && PDIR=\$JAROMAIL +DYLD_LIBRARY_PATH=\$PDIR/bin/dylib:\$DYLD_LIBRARY_PATH \\ +\$PDIR/bin/`basename $1`.bin \${=@} +EOF + chmod +x build/osx/`basename $1` + +} + + +copydeps_brew() { + # copy a binary and all dependencies until 3rd level + print "`basename $1`" + + tmp="/tmp/build_`basename $1`"; + rm -f $tmp; touch $tmp + + libs=`otool -L $1 | awk ' + /^\// {next} /\/usr\/local/ {print $1}'` + + for p1 in ${(f)libs}; do + echo "$p1" >> $tmp + # second pass + libs2=`otool -L $p1 | awk ' + /^\// {next} /\/usr\/local/ {print $1}'` + + for p2 in ${(f)libs2}; do + echo "$p2" >> $tmp + # third pass + libs3=`otool -L $p2 | awk ' + /^\// {next} /\/usr\/local/ {print $1}'` + + for p3 in ${(f)libs3}; do + echo "$p3" >> $tmp + done # 3rd + done # 2nd + done # 1st + + cp $1 build/osx/`basename $1`.bin + chmod +w build/osx/`basename $1`.bin strip build/osx/`basename $1`.bin for d in `cat $tmp | sort | uniq`; do if ! [ -r build/osx/dylib/`basename $d` ]; then cp $d build/osx/dylib/ - print "`basename $d`" + print " `basename $d`" fi done @@ -88,6 +147,8 @@ EOF } + + print "Building Jaro Mail binary stash for Apple/OSX" if ! [ -r /opt/local/bin/port ]; then @@ -111,8 +172,8 @@ fi # build our own address parser pushd src print "Address parser" - $cc -c fetchaddr.c helpers.c rfc2047.c rfc822.c; \ - $cc -o fetchaddr fetchaddr.o helpers.o rfc2047.o rfc822.o; + $cc ${=cflags} -c fetchaddr.c helpers.c rfc2047.c rfc822.c + $cc -o fetchaddr fetchaddr.o helpers.o rfc2047.o rfc822.o ${=ldflags}; popd } @@ -121,9 +182,10 @@ fi # build mairix pushd src/mairix print "Search engine and date parser" - CC="$cc" LD=/usr/bin/ld CPP=/usr/bin/cpp \ - ./configure --disable-gzip-mbox --disable-bzip-mbox \ - > /dev/null ; make 2>&1 > /dev/null + CFLAGS="${=cflags} ${=ldflags} -L/usr/local/opt/bison/lib" \ + CFLAGS="$CFLAGS -L/usr/local/opt/flex/lib -I/usr/local/opt/flex/include" \ + CC="$cc" LD=ld CPP="$cpp" \ + ./configure --disable-gzip-mbox --disable-bzip-mbox ; make popd } @@ -131,8 +193,8 @@ fi test "$target" = "all" } && { # build our own fetchdate pushd src - $cc -I mairix -c fetchdate.c - $cc -DHAS_STDINT_H -DHAS_INTTYPES_H \ + $cc ${=cflags} ${=ldflags} -I mairix -c fetchdate.c + $cc ${=cflags} ${=ldflags} -DHAS_STDINT_H -DHAS_INTTYPES_H \ -o fetchdate fetchdate.o \ mairix/datescan.o mairix/db.o mairix/dotlock.o \ mairix/expandstr.o mairix/glob.o mairix/md5.o \ @@ -148,8 +210,8 @@ fi test "$target" = "all" } && { # build our own dotlock pushd src - $cc -c dotlock.c - $cc -o dotlock dotlock.o + $cc ${=cflags} -c dotlock.c + $cc ${=ldflags} -o dotlock dotlock.o popd } @@ -171,20 +233,35 @@ fi echo "Compiling Mutt (MUA)" pushd src/mutt-1.5.21 - CC=clang CFLAGS="$cflags" CPPFLAGS="-I/opt/local/include" LDFLAGS="$ldflags" ./configure \ + CC="$gcc" CPP="$cpp" CFLAGS="${=cflags} -I/usr/local/Cellar/gettext/0.18.2/include" \ + CPPFLAGS="${=cflags}" LDFLAGS="${=ldflags} -L/usr/local/Cellar/gettext/0.18.2/lib" ./configure \ --with-ssl --with-gnutls --enable-imap --disable-debug \ --with-slang --disable-gpgme \ --enable-hcache --with-regex --with-tokyocabinet \ - --with-mixmaster=${root}/src/mixmaster --enable-pgp \ - > /dev/null - make mutt > /dev/null - { test $? = 0 } && { - mv mutt mutt-jaro - mv mutt_dotlock dotlock-mutt - } + --with-mixmaster=${root}/src/mixmaster --enable-pgp + make keymap_defs.h + make reldate.h + CFLAGS="-I/usr/local/Cellar/gettext/0.18.2/include" make hcversion.h + make mutt + make pgpewrap + { test $? = 0 } && { mv mutt mutt-jaro } popd } +# build our own lynx (no ssl) +{ test "$target" = "lynx" } || { + test "$target" = "all" } && { + echo "Compiling Lynx (html 2 txt)" + pushd src/lynx2-8-7 + CC="$gcc" CPP="$cpp" CFLAGS="${=cflags} -I/usr/local/Cellar/gettext/0.18.2/include" \ + CPPFLAGS="${=cflags}" LDFLAGS="${=ldflags} -L/usr/local/Cellar/gettext/0.18.2/lib" ./configure \ + --disable-trace --enable-nls --with-screen=slang --enable-widec --enable-default-colors \ + --disable-file-upload --disable-persistent-cookie --with-bzlib --with-zlib \ + --disable-finger --disable-gopher --disable-news --disable-ftp --disable-dired \ + --enable-cjk --enable-japanese-utf8 --enable-charset-selection + make + popd +} # CFLAGS="${=cflags}" \ @@ -201,17 +278,20 @@ fi # cp src/msmtp/src/msmtp build/osx/ cp -v src/dotlock build/osx/ copydeps ${root}/src/mutt-1.5.21/mutt-jaro - copydeps ${root}/src/mutt-1.5.21/dotlock-mutt copydeps ${root}/src/mutt-1.5.21/pgpewrap - copydeps /opt/local/bin/gfind - copydeps /opt/local/bin/msmtp - copydeps /opt/local/bin/gpg + copydeps_brew /usr/local/bin/gfind + copydeps_brew /usr/local/bin/msmtp + copydeps_brew /usr/local/bin/gpg mv build/osx/gpg build/osx/gpg-jaro - copydeps /opt/local/bin/pinentry - copydeps /opt/local/bin/abook - copydeps /opt/local/bin/lynx + copydeps_brew /usr/local/bin/pinentry + copydeps_brew /usr/local/bin/abook + copydeps ${root}/src/lynx2-8-7/lynx + cp ${root}/src/lynx2-8-7/lynx.cfg build/osx/lynx.cfg + copydeps /opt/local/bin/fetchmail - copydeps /opt/local/bin/procmail + + # system wide + rm build/osx/dylib/libiconv.2.dylib } diff --git a/build/clang-static-osx.sh b/build/clang-static-osx.sh @@ -24,14 +24,14 @@ # configuration variables -cc=clang -libdir="/opt/local/lib" +cc=gcc +libdir="/usr/local/lib" typeset -a arguments typeset -a cflags cflags+=(-arch x86_64) -cflags+=(-arch i386) +# cflags+=(-arch i386) ########################## diff --git a/src/mutt-1.5.21/mutt_dotlock.c b/src/mutt-1.5.21/mutt_dotlock.c @@ -1,758 +0,0 @@ -/* - * Copyright (C) 1996-2000 Michael R. Elkins <me@mutt.org> - * Copyright (C) 1998-2001,2007 Thomas Roessler <roessler@does-not-exist.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* - * This module either be compiled into Mutt, or it can be - * built as a separate program. For building it - * separately, define the DL_STANDALONE preprocessor - * macro. - */ - -#if HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <unistd.h> -#include <dirent.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <sys/utsname.h> -#include <errno.h> -#include <time.h> -#include <fcntl.h> -#include <limits.h> - -#ifndef _POSIX_PATH_MAX -#include <limits.h> -#endif - -#include "dotlock.h" - -#ifdef HAVE_GETOPT_H -#include <getopt.h> -#endif - -#ifdef DL_STANDALONE -# include "reldate.h" -#endif - -#define MAXLINKS 1024 /* maximum link depth */ - -#ifdef DL_STANDALONE - -# define LONG_STRING 1024 -# define MAXLOCKATTEMPT 5 - -# define strfcpy(A,B,C) strncpy (A,B,C), *(A+(C)-1)=0 - -# ifdef USE_SETGID - -# ifdef HAVE_SETEGID -# define SETEGID setegid -# else -# define SETEGID setgid -# endif -# ifndef S_ISLNK -# define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK ? 1 : 0) -# endif - -# endif - -# ifndef HAVE_SNPRINTF -extern int snprintf (char *, size_t, const char *, ...); -# endif - -#else /* DL_STANDALONE */ - -# ifdef USE_SETGID -# error Do not try to compile dotlock as a mutt module when requiring egid switching! -# endif - -# include "mutt.h" -# include "mx.h" - -#endif /* DL_STANDALONE */ - -static int DotlockFlags; -static int Retry = MAXLOCKATTEMPT; - -#ifdef DL_STANDALONE -static char *Hostname; -#endif - -#ifdef USE_SETGID -static gid_t UserGid; -static gid_t MailGid; -#endif - -static int dotlock_deference_symlink (char *, size_t, const char *); -static int dotlock_prepare (char *, size_t, const char *, int fd); -static int dotlock_check_stats (struct stat *, struct stat *); -static int dotlock_dispatch (const char *, int fd); - -#ifdef DL_STANDALONE -static int dotlock_init_privs (void); -static void usage (const char *); -#endif - -static void dotlock_expand_link (char *, const char *, const char *); -static void BEGIN_PRIVILEGED (void); -static void END_PRIVILEGED (void); - -/* These functions work on the current directory. - * Invoke dotlock_prepare () before and check their - * return value. - */ - -static int dotlock_try (void); -static int dotlock_unlock (const char *); -static int dotlock_unlink (const char *); -static int dotlock_lock (const char *); - - -#ifdef DL_STANDALONE - -#define check_flags(a) if (a & DL_FL_ACTIONS) usage (argv[0]) - -int main (int argc, char **argv) -{ - int i; - char *p; - struct utsname utsname; - - /* first, drop privileges */ - - if (dotlock_init_privs () == -1) - return DL_EX_ERROR; - - - /* determine the system's host name */ - - uname (&utsname); - if (!(Hostname = strdup (utsname.nodename))) /* __MEM_CHECKED__ */ - return DL_EX_ERROR; - if ((p = strchr (Hostname, '.'))) - *p = '\0'; - - - /* parse the command line options. */ - DotlockFlags = 0; - - while ((i = getopt (argc, argv, "dtfupr:")) != EOF) - { - switch (i) - { - /* actions, mutually exclusive */ - case 't': check_flags (DotlockFlags); DotlockFlags |= DL_FL_TRY; break; - case 'd': check_flags (DotlockFlags); DotlockFlags |= DL_FL_UNLINK; break; - case 'u': check_flags (DotlockFlags); DotlockFlags |= DL_FL_UNLOCK; break; - - /* other flags */ - case 'f': DotlockFlags |= DL_FL_FORCE; break; - case 'p': DotlockFlags |= DL_FL_USEPRIV; break; - case 'r': DotlockFlags |= DL_FL_RETRY; Retry = atoi (optarg); break; - - default: usage (argv[0]); - } - } - - if (optind == argc || Retry < 0) - usage (argv[0]); - - return dotlock_dispatch (argv[optind], -1); -} - - -/* - * Determine our effective group ID, and drop - * privileges. - * - * Return value: - * - * 0 - everything went fine - * -1 - we couldn't drop privileges. - * - */ - - -static int -dotlock_init_privs (void) -{ - -# ifdef USE_SETGID - - UserGid = getgid (); - MailGid = getegid (); - - if (SETEGID (UserGid) != 0) - return -1; - -# endif - - return 0; -} - - -#else /* DL_STANDALONE */ - -/* - * This function is intended to be invoked from within - * mutt instead of mx.c's invoke_dotlock (). - */ - -int dotlock_invoke (const char *path, int fd, int flags, int retry) -{ - int currdir; - int r; - - DotlockFlags = flags; - - if ((currdir = open (".", O_RDONLY)) == -1) - return DL_EX_ERROR; - - if (!(DotlockFlags & DL_FL_RETRY) || retry) - Retry = MAXLOCKATTEMPT; - else - Retry = 0; - - r = dotlock_dispatch (path, fd); - - fchdir (currdir); - close (currdir); - - return r; -} - -#endif /* DL_STANDALONE */ - - -static int dotlock_dispatch (const char *f, int fd) -{ - char realpath[_POSIX_PATH_MAX]; - - /* If dotlock_prepare () succeeds [return value == 0], - * realpath contains the basename of f, and we have - * successfully changed our working directory to - * `dirname $f`. Additionally, f has been opened for - * reading to verify that the user has at least read - * permissions on that file. - * - * For a more detailed explanation of all this, see the - * lengthy comment below. - */ - - if (dotlock_prepare (realpath, sizeof (realpath), f, fd) != 0) - return DL_EX_ERROR; - - /* Actually perform the locking operation. */ - - if (DotlockFlags & DL_FL_TRY) - return dotlock_try (); - else if (DotlockFlags & DL_FL_UNLOCK) - return dotlock_unlock (realpath); - else if (DotlockFlags & DL_FL_UNLINK) - return dotlock_unlink (realpath); - else /* lock */ - return dotlock_lock (realpath); -} - - -/* - * Get privileges - * - * This function re-acquires the privileges we may have - * if the user told us to do so by giving the "-p" - * command line option. - * - * BEGIN_PRIVILEGES () won't return if an error occurs. - * - */ - -static void -BEGIN_PRIVILEGED (void) -{ -#ifdef USE_SETGID - if (DotlockFlags & DL_FL_USEPRIV) - { - if (SETEGID (MailGid) != 0) - { - /* perror ("setegid"); */ - exit (DL_EX_ERROR); - } - } -#endif -} - -/* - * Drop privileges - * - * This function drops the group privileges we may have. - * - * END_PRIVILEGED () won't return if an error occurs. - * - */ - -static void -END_PRIVILEGED (void) -{ -#ifdef USE_SETGID - if (DotlockFlags & DL_FL_USEPRIV) - { - if (SETEGID (UserGid) != 0) - { - /* perror ("setegid"); */ - exit (DL_EX_ERROR); - } - } -#endif -} - -#ifdef DL_STANDALONE - -/* - * Usage information. - * - * This function doesn't return. - * - */ - -static void -usage (const char *av0) -{ - fprintf (stderr, "dotlock [Mutt %s (%s)]\n", VERSION, ReleaseDate); - fprintf (stderr, "usage: %s [-t|-f|-u|-d] [-p] [-r <retries>] file\n", - av0); - - fputs ("\noptions:" - "\n -t\t\ttry" - "\n -f\t\tforce" - "\n -u\t\tunlock" - "\n -d\t\tunlink" - "\n -p\t\tprivileged" -#ifndef USE_SETGID - " (ignored)" -#endif - "\n -r <retries>\tRetry locking" - "\n", stderr); - - exit (DL_EX_ERROR); -} - -#endif - -/* - * Access checking: Let's avoid to lock other users' mail - * spool files if we aren't permitted to read them. - * - * Some simple-minded access (2) checking isn't sufficient - * here: The problem is that the user may give us a - * deeply nested path to a file which has the same name - * as the file he wants to lock, but different - * permissions, say, e.g. - * /tmp/lots/of/subdirs/var/spool/mail/root. - * - * He may then try to replace /tmp/lots/of/subdirs by a - * symbolic link to / after we have invoked access () to - * check the file's permissions. The lockfile we'd - * create or remove would then actually be - * /var/spool/mail/root. - * - * To avoid this attack, we proceed as follows: - * - * - First, follow symbolic links a la - * dotlock_deference_symlink (). - * - * - get the result's dirname. - * - * - chdir to this directory. If you can't, bail out. - * - * - try to open the file in question, only using its - * basename. If you can't, bail out. - * - * - fstat that file and compare the result to a - * subsequent lstat (only using the basename). If - * the comparison fails, bail out. - * - * dotlock_prepare () is invoked from main () directly - * after the command line parsing has been done. - * - * Return values: - * - * 0 - Evereything's fine. The program's new current - * directory is the contains the file to be locked. - * The string pointed to by bn contains the name of - * the file to be locked. - * - * -1 - Something failed. Don't continue. - * - * tlr, Jul 15 1998 - */ - -static int -dotlock_check_stats (struct stat *fsb, struct stat *lsb) -{ - /* S_ISLNK (fsb->st_mode) should actually be impossible, - * but we may have mixed up the parameters somewhere. - * play safe. - */ - - if (S_ISLNK (lsb->st_mode) || S_ISLNK (fsb->st_mode)) - return -1; - - if ((lsb->st_dev != fsb->st_dev) || - (lsb->st_ino != fsb->st_ino) || - (lsb->st_mode != fsb->st_mode) || - (lsb->st_nlink != fsb->st_nlink) || - (lsb->st_uid != fsb->st_uid) || - (lsb->st_gid != fsb->st_gid) || - (lsb->st_rdev != fsb->st_rdev) || - (lsb->st_size != fsb->st_size)) - { - /* something's fishy */ - return -1; - } - - return 0; -} - -static int -dotlock_prepare (char *bn, size_t l, const char *f, int _fd) -{ - struct stat fsb, lsb; - char realpath[_POSIX_PATH_MAX]; - char *basename, *dirname; - char *p; - int fd; - int r; - - if (dotlock_deference_symlink (realpath, sizeof (realpath), f) == -1) - return -1; - - if ((p = strrchr (realpath, '/'))) - { - *p = '\0'; - basename = p + 1; - dirname = realpath; - } - else - { - basename = realpath; - dirname = "."; - } - - if (strlen (basename) + 1 > l) - return -1; - - strfcpy (bn, basename, l); - - if (chdir (dirname) == -1) - return -1; - - if (_fd != -1) - fd = _fd; - else if ((fd = open (basename, O_RDONLY)) == -1) - return -1; - - r = fstat (fd, &fsb); - - if (_fd == -1) - close (fd); - - if (r == -1) - return -1; - - if (lstat (basename, &lsb) == -1) - return -1; - - if (dotlock_check_stats (&fsb, &lsb) == -1) - return -1; - - return 0; -} - -/* - * Expand a symbolic link. - * - * This function expects newpath to have space for - * at least _POSIX_PATH_MAX characters. - * - */ - -static void -dotlock_expand_link (char *newpath, const char *path, const char *link) -{ - const char *lb = NULL; - size_t len; - - /* link is full path */ - if (*link == '/') - { - strfcpy (newpath, link, _POSIX_PATH_MAX); - return; - } - - if ((lb = strrchr (path, '/')) == NULL) - { - /* no path in link */ - strfcpy (newpath, link, _POSIX_PATH_MAX); - return; - } - - len = lb - path + 1; - memcpy (newpath, path, len); - strfcpy (newpath + len, link, _POSIX_PATH_MAX - len); -} - - -/* - * Deference a chain of symbolic links - * - * The final path is written to d. - * - */ - -static int -dotlock_deference_symlink (char *d, size_t l, const char *path) -{ - struct stat sb; - char realpath[_POSIX_PATH_MAX]; - const char *pathptr = path; - int count = 0; - - while (count++ < MAXLINKS) - { - if (lstat (pathptr, &sb) == -1) - { - /* perror (pathptr); */ - return -1; - } - - if (S_ISLNK (sb.st_mode)) - { - char linkfile[_POSIX_PATH_MAX]; - char linkpath[_POSIX_PATH_MAX]; - int len; - - if ((len = readlink (pathptr, linkfile, sizeof (linkfile) - 1)) == -1) - { - /* perror (pathptr); */ - return -1; - } - - linkfile[len] = '\0'; - dotlock_expand_link (linkpath, pathptr, linkfile); - strfcpy (realpath, linkpath, sizeof (realpath)); - pathptr = realpath; - } - else - break; - } - - strfcpy (d, pathptr, l); - return 0; -} - -/* - * Dotlock a file. - * - * realpath is assumed _not_ to be an absolute path to - * the file we are about to lock. Invoke - * dotlock_prepare () before using this function! - * - */ - -#define HARDMAXATTEMPTS 10 - -static int -dotlock_lock (const char *realpath) -{ - char lockfile[_POSIX_PATH_MAX + LONG_STRING]; - char nfslockfile[_POSIX_PATH_MAX + LONG_STRING]; - size_t prev_size = 0; - int fd; - int count = 0; - int hard_count = 0; - struct stat sb; - time_t t; - - snprintf (nfslockfile, sizeof (nfslockfile), "%s.%s.%d", - realpath, Hostname, (int) getpid ()); - snprintf (lockfile, sizeof (lockfile), "%s.lock", realpath); - - - BEGIN_PRIVILEGED (); - - unlink (nfslockfile); - - while ((fd = open (nfslockfile, O_WRONLY | O_EXCL | O_CREAT, 0)) < 0) - { - END_PRIVILEGED (); - - - if (errno != EAGAIN) - { - /* perror ("cannot open NFS lock file"); */ - return DL_EX_ERROR; - } - - - BEGIN_PRIVILEGED (); - } - - END_PRIVILEGED (); - - - close (fd); - - while (hard_count++ < HARDMAXATTEMPTS) - { - - BEGIN_PRIVILEGED (); - link (nfslockfile, lockfile); - END_PRIVILEGED (); - - if (stat (nfslockfile, &sb) != 0) - { - /* perror ("stat"); */ - return DL_EX_ERROR; - } - - if (sb.st_nlink == 2) - break; - - if (count == 0) - prev_size = sb.st_size; - - if (prev_size == sb.st_size && ++count > Retry) - { - if (DotlockFlags & DL_FL_FORCE) - { - BEGIN_PRIVILEGED (); - unlink (lockfile); - END_PRIVILEGED (); - - count = 0; - continue; - } - else - { - BEGIN_PRIVILEGED (); - unlink (nfslockfile); - END_PRIVILEGED (); - return DL_EX_EXIST; - } - } - - prev_size = sb.st_size; - - /* don't trust sleep (3) as it may be interrupted - * by users sending signals. - */ - - t = time (NULL); - do { - sleep (1); - } while (time (NULL) == t); - } - - BEGIN_PRIVILEGED (); - unlink (nfslockfile); - END_PRIVILEGED (); - - return DL_EX_OK; -} - - -/* - * Unlock a file. - * - * The same comment as for dotlock_lock () applies here. - * - */ - -static int -dotlock_unlock (const char *realpath) -{ - char lockfile[_POSIX_PATH_MAX + LONG_STRING]; - int i; - - snprintf (lockfile, sizeof (lockfile), "%s.lock", - realpath); - - BEGIN_PRIVILEGED (); - i = unlink (lockfile); - END_PRIVILEGED (); - - if (i == -1) - return DL_EX_ERROR; - - return DL_EX_OK; -} - -/* remove an empty file */ - -static int -dotlock_unlink (const char *realpath) -{ - struct stat lsb; - int i = -1; - - if (dotlock_lock (realpath) != DL_EX_OK) - return DL_EX_ERROR; - - if ((i = lstat (realpath, &lsb)) == 0 && lsb.st_size == 0) - unlink (realpath); - - dotlock_unlock (realpath); - - return (i == 0) ? DL_EX_OK : DL_EX_ERROR; -} - - -/* - * Check if a file can be locked at all. - * - * The same comment as for dotlock_lock () applies here. - * - */ - -static int -dotlock_try (void) -{ -#ifdef USE_SETGID - struct stat sb; -#endif - - if (access (".", W_OK) == 0) - return DL_EX_OK; - -#ifdef USE_SETGID - if (stat (".", &sb) == 0) - { - if ((sb.st_mode & S_IWGRP) == S_IWGRP && sb.st_gid == MailGid) - return DL_EX_NEED_PRIVS; - } -#endif - - return DL_EX_IMPOSSIBLE; -}