You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bforce/source/bforce/u_plock.c

204 lines
3.8 KiB
C

/*
* binkleyforce -- unix FTN mailer project
*
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
*
* 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.
*
* $Id$
*/
#include "includes.h"
#include "confread.h"
#include "logger.h"
#include "util.h"
#include "outbound.h"
pid_t plock_read(const char *lockname)
{
FILE *fp = NULL;
pid_t pid = 0;
ASSERT(lockname != NULL);
if( (fp = file_open(lockname, "rt")) )
{
if( fscanf(fp, "%d", &pid) != 1 )
pid = 0;
file_close(fp);
}
DEB((D_OUTBOUND, "plock_read: file \"%s\", PID = %d", lockname, pid));
return pid;
}
pid_t plock_write(const char *lockname)
{
int fd, rc = PLOCK_OK;
char buf[32];
ASSERT(lockname != NULL);
if( (fd = open(lockname, O_CREAT | O_RDWR, 0644)) < 0 )
/* Don't log any errors, really we can have
* no outbound directory for this address */
return PLOCK_ERROR;
chmod(lockname, 0644);
sprintf(buf, "%10d\n", (int)getpid());
if( write(fd, (char *)buf, strlen(buf)) != strlen(buf) )
{
logerr("can't write PID to the lock file \"%s\"", lockname);
rc = PLOCK_ERROR;
}
close(fd);
if( rc != PLOCK_OK )
unlink(lockname);
return rc;
}
/*
* Return codes:
* PLOCK_OK
* PLOCK_EXIST
* PLOCK_ERROR
* PLOCK_OURBSY
*/
int plock_check(const char *lockname)
{
pid_t pid = 0;
struct stat st;
ASSERT(lockname != NULL);
if( stat(lockname, &st) && errno == ENOENT )
return PLOCK_OK;
if( (pid = plock_read(lockname)) == 0 )
return (errno == ENOENT) ? PLOCK_OK : PLOCK_ERROR;
if( pid == getpid() )
return PLOCK_OURLOCK; /* Should we unlink it? */
if( kill(pid, 0) == -1 && errno == ESRCH )
{
/*
* That process no longer exists,
* try to remove lock file
*/
log("remove stale lock file \"%s\", PID %d",
lockname, (int)pid);
if( !unlink(lockname) )
return PLOCK_OK;
else
{
logerr("cannot remove lock file");
return PLOCK_ERROR;
}
}
return PLOCK_EXIST; /* locking process still lives */
}
int plock_link(const char *lockname, const char *tmpname)
{
int rc;
ASSERT(lockname != NULL && tmpname != NULL);
if( !link(tmpname, lockname) )
{
unlink(tmpname);
return PLOCK_OK;
}
/* Can't create link */
if( errno == EEXIST )
{
if( (rc = plock_check(lockname)) != PLOCK_OK )
{
if( rc == PLOCK_OURLOCK )
rc = PLOCK_OK;
}
else if( link(tmpname, lockname) )
{
logerr("cannot link lock \"%s\" to \"%s\"", tmpname, lockname);
rc = PLOCK_ERROR;
} else
rc = PLOCK_OK;
}
else
{
logerr("cannot link lock \"%s\" to \"%s\"", tmpname, lockname);
rc = PLOCK_ERROR;
}
if( unlink(tmpname) == -1 && errno != ENOENT )
logerr("cannot remove lock file \"%s\"", tmpname);
return rc;
}
int plock_create(const char *lockname)
{
int rc;
char *tmpname, *p;
ASSERT(lockname != NULL);
tmpname = xstrcpy(lockname);
if( (p = strrchr(tmpname, DIRSEPCHR)) && p != tmpname )
*++p = '\0';
else
{
free(tmpname);
return PLOCK_ERROR;
}
tmpname = xstrcat(tmpname, "bforce-XXXXXX");
if( (p = mktemp(tmpname)) == NULL )
{
logerr("can't generate unique file name from \"%s\"", tmpname);
free(tmpname);
return PLOCK_ERROR;
}
if( (rc = plock_write(p)) == PLOCK_OK )
rc = plock_link(lockname, p);
DEB((D_OUTBOUND, "out_bsy_createfile: createlink(\"%s\", \"%s\"), rc = %d",
lockname, p, rc));
free(tmpname);
return rc;
}
int plock_remove(const char *lockname)
{
pid_t pid = 0;
ASSERT(lockname != NULL);
DEB((D_OUTBOUND, "out_bsy_unlinkfile: want unlink \"%s\"", lockname));
if( (pid = plock_read(lockname)) == 0 )
return 1;
if( pid == getpid() && unlink(lockname) == -1 )
return 1;
return 0;
}