aboutsummaryrefslogtreecommitdiffstats
path: root/todo.html
Commit message (Expand)AuthorAgeFilesLines
* Link the two TODO documents to each other.Matthias Andree2009-05-241-0/+3
* Clean out obsolete items.Matthias Andree2006-03-031-15/+0
* Move TODO into todo.html.Matthias Andree2005-07-031-47/+52
* Make this conformant XHTML.Matthias Andree2005-07-031-2/+2
* Fix patch for Sunil Shetye's POP3 tweaks.Eric S. Raymond2004-01-131-2/+25
* Close a Debian bug.Eric S. Raymond2003-10-101-2/+13
* First round ofmlong-delayed bug fixes.Eric S. Raymond2003-07-171-2/+4
* Documentation updates.Eric S. Raymond2003-02-281-2/+11
* IDLE implementation.Eric S. Raymond2003-02-281-10/+2
* Fix a minor bug reported by Matthias Andree.Eric S. Raymond2002-09-171-31/+2
* XML headers everywhere.Eric S. Raymond2002-07-301-2/+3
* XML conversionEric S. Raymond2002-07-281-93/+108
* Cleanup.Eric S. Raymond2002-07-281-6/+6
* Cleanup.Eric S. Raymond2002-07-281-7/+8
* Added a bug note.Eric S. Raymond2002-03-091-2/+27
* Initial version of ESMTP AUTH.Eric S. Raymond2002-03-091-7/+2
* Note a new bug.Eric S. Raymond2001-12-141-2/+8
* License cleanup.Eric S. Raymond2001-09-301-10/+2
* Eliminate a bug.Eric S. Raymond2001-09-241-5/+2
* Added TODO about license com[patibility.Eric S. Raymond2001-09-221-2/+10
* Ready to ship.Eric S. Raymond2001-08-101-2/+6
* Updated buglist.Eric S. Raymond2001-07-311-38/+21
* Note Paul Howarth's error.Eric S. Raymond2001-07-061-2/+19
* Resady to ship.Eric S. Raymond2001-05-301-2/+5
* SSL certification handling.Eric S. Raymond2001-05-141-5/+3
* Version bump.Eric S. Raymond2001-02-191-3/+3
* Initial revisionEric S. Raymond2001-02-111-0/+74
} /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/**
 * \file lock.c cross-platform concurrency locking for fetchmail
 *
 * For license terms, see the file COPYING in this directory.
 */
#include "config.h"

#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h> /* strcat() */
#endif
#if defined(STDC_HEADERS)
#include <stdlib.h>
#endif
#if defined(HAVE_UNISTD_H)
#include <unistd.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <signal.h>

#include "fetchmail.h"
#include "i18n.h"
#include "lock.h"

static char *lockfile;		/** name of lockfile */
static int lock_acquired;	/** flag if have we acquired a lock */

void fm_lock_setup(struct runctl *ctl)
/* set up the global lockfile name */
{
    /* set up to do lock protocol */
    const char *const FETCHMAIL_PIDFILE="fetchmail.pid";

    /* command-line option override */
    if (ctl->pidfile) {
	lockfile = xstrdup(ctl->pidfile);
	return;
    }

    /* defaults */
    if (getuid() == ROOT_UID) {
	lockfile = (char *)xmalloc(strlen(PID_DIR)
		+ strlen(FETCHMAIL_PIDFILE) + 2); /* 2: "/" and NUL */
	strcpy(lockfile, PID_DIR);
	strcat(lockfile, "/");
	strcat(lockfile, FETCHMAIL_PIDFILE);
    } else {
	lockfile = (char *)xmalloc(strlen(fmhome)
		+ strlen(FETCHMAIL_PIDFILE) + 3); /* 3: "/", "." and NUL */
	strcpy(lockfile, fmhome);
	strcat(lockfile, "/");
	if (fmhome == home)
	   strcat(lockfile, ".");
	strcat(lockfile, FETCHMAIL_PIDFILE);
    }
}

static void unlockit(void)
/* must-do actions for exit (but we can't count on being able to do malloc) */
{
    if (lockfile && lock_acquired)
	unlink(lockfile);
}

void fm_lock_dispose(void)
/* arrange for a lock to be removed on process exit */
{
#ifdef HAVE_ATEXIT
    atexit(unlockit);
#endif
}

int fm_lock_state(void)
{
    int		pid, st;
    FILE	*lockfp;
    int		bkgd = FALSE;

    if ((lockfp = fopen(lockfile, "r")) != NULL)
    {
	int args = fscanf(lockfp, "%d %d", &pid, &st);
	bkgd = (args == 2);

	if (ferror(lockfp)) {
	    fprintf(stderr, GT_("fetchmail: error reading lockfile \"%s\": %s\n"),
		    lockfile, strerror(errno));
	    fclose(lockfp); /* not checking should be safe, file mode was "r" */
	    exit(PS_EXCLUDE);
	}
	fclose(lockfp); /* not checking should be safe, file mode was "r" */

	if (args == EOF || args == 0 || kill(pid, 0) == -1) {
	    /* ^ could not read PID  || process does not exist */
	    /* => lockfile is stale, unlink it */
	    pid = 0;
	    fprintf(stderr,GT_("fetchmail: removing stale lockfile\n"));
	    if (unlink(lockfile)) {
	       if (errno != ENOENT) {
		   perror(lockfile);
		   /* we complain but we don't exit; it might be
		    * writable for us, but in a directory we cannot
		    * write to. This means we can write the new PID to
		    * the file. Truncate to be safe in case the PID is
		    * recycled by another process later.
		    * \bug we should use fcntl() style locks or
		    * something else instead in a future release. */
		   if (truncate(lockfile, (off_t)0)) {
		       /* but if we cannot truncate the file either,
			* assume that we cannot write to it later,
			* complain and quit. */
		       perror(lockfile);
		       exit(PS_EXCLUDE);
		   }
	       }
	    }
	}
    } else {
	pid = 0;
	if (errno != ENOENT) {
	    fprintf(stderr, GT_("fetchmail: error opening lockfile \"%s\": %s\n"),
		    lockfile, strerror(errno));
	    exit(PS_EXCLUDE);
	}
    }

    return(bkgd ? -pid : pid);
}

void fm_lock_assert(void)
/* assert that we already possess a lock */
{
    lock_acquired = TRUE;
}

void fm_lock_or_die(void)
/* get a lock on a given host or exit */
{
    int fd;
    char	tmpbuf[50];

    if (!lock_acquired) {
	int e = 0;

	if ((fd = open(lockfile, O_WRONLY|O_CREAT|O_EXCL, 0666)) != -1) {
	    ssize_t wr;

	    snprintf(tmpbuf, sizeof(tmpbuf), "%ld\n", (long)getpid());
	    wr = write(fd, tmpbuf, strlen(tmpbuf));
	    if (wr == -1 || (size_t)wr != strlen(tmpbuf))
	        e = 1;
	    if (run.poll_interval)
	    {
		snprintf(tmpbuf, sizeof(tmpbuf), "%d\n", run.poll_interval);
		wr = write(fd, tmpbuf, strlen(tmpbuf));
		if (wr == -1 || (size_t)wr != strlen(tmpbuf))
		    e = 1;
	    }
	    if (fsync(fd)) e = 1;
	    if (close(fd)) e = 1;
	} else {
	    e = 1;
	}
	if (e == 0) {
	    lock_acquired = TRUE;
	} else {
	    perror(lockfile);
	    fprintf(stderr, GT_("fetchmail: lock creation failed.\n"));
	    exit(PS_EXCLUDE);
	}
    }
}

void fm_lock_release(void)
/* release a lock on a given host */
{
    unlink(lockfile);
}
/* lock.c ends here */