aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnulib.modules4
-rw-r--r--src/Makefile.am1
-rw-r--r--src/config.c8
-rw-r--r--src/directive.c4
-rw-r--r--src/diskio.c6
-rw-r--r--src/exec.c2
-rw-r--r--src/getopt.m42
-rw-r--r--src/job.c45
-rw-r--r--src/lock.c239
-rw-r--r--src/net.c14
-rw-r--r--src/pidfile.c10
-rw-r--r--src/process.c25
-rw-r--r--src/triplet.c4
-rw-r--r--src/wydawca.c50
-rw-r--r--src/wydawca.h27
-rw-r--r--tests/etc/wydawca.rcin2
16 files changed, 391 insertions, 52 deletions
diff --git a/gnulib.modules b/gnulib.modules
index 1c56638..3dbc445 100644
--- a/gnulib.modules
+++ b/gnulib.modules
@@ -12,7 +12,9 @@ mkdtemp
save-cwd
backupfile
strerror
+sysexits
vasprintf
inttostr
strftime
-version-etc \ No newline at end of file
+version-etc
+xgethostname
diff --git a/src/Makefile.am b/src/Makefile.am
index 903b754..fcfdb78 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,6 +26,7 @@ wydawca_SOURCES=\
gpg.c\
interval.c\
job.c\
+ lock.c\
meta.c\
method.c\
net.c\
diff --git a/src/config.c b/src/config.c
index facfcbc..bab1ed3 100644
--- a/src/config.c
+++ b/src/config.c
@@ -1237,6 +1237,14 @@ static struct gconf_keyword wydawca_kw[] = {
gconf_type_string, &wakeup_interval, 0, cb_interval },
{ "pidfile", N_("file"), N_("Set pid file name"),
gconf_type_string, &pidfile },
+
+ { "locking", NULL, N_("Enable or disable locking"),
+ gconf_type_bool, &enable_locking },
+ { "lockdir", N_("dir"), N_("Set directory for lock files"),
+ gconf_type_string, &lockdir },
+ { "lock-expire-time", N_("interval"), N_("Define lock expiration interval"),
+ gconf_type_string, &lock_expire_time, 0, cb_interval },
+
{ "listen", N_("socket"), N_("Listen on this address"),
gconf_type_sockaddr, &listen_sockaddr, },
{ "mailer", N_("url"), N_("Set mailer URL"),
diff --git a/src/directive.c b/src/directive.c
index 37ce241..ccea1ef 100644
--- a/src/directive.c
+++ b/src/directive.c
@@ -337,9 +337,9 @@ process_directives (struct file_triplet *trp, const struct spool *spool)
break;
case filename_dir:
- wydawca_uid (0);
+ wydawca_set_uid (0);
rc = verify_detached_signature (trp, spool);
- wydawca_uid (TRIPLET_UID (trp));
+ wydawca_set_uid (TRIPLET_UID (trp));
if (rc == 0)
{
if (move_file (trp, spool, file_dist, relative_dir)
diff --git a/src/diskio.c b/src/diskio.c
index ccff5c2..c068e49 100644
--- a/src/diskio.c
+++ b/src/diskio.c
@@ -124,9 +124,9 @@ create_directory (const char *base, const char *name, uid_t uid, gid_t gid)
if (!dry_run_mode)
{
int rc;
- wydawca_uid (0);
+ wydawca_set_uid (0);
rc = create_hierarchy (dir, baselen, uid, gid);
- wydawca_uid (uid);
+ wydawca_set_uid (uid);
if (rc)
{
free (dir);
@@ -647,7 +647,7 @@ dir_symlink_file (struct file_triplet *trp, const struct spool *spool,
{
logmsg (LOG_EMERG, _("cannot restore current directory: %s"),
strerror (errno));
- exit (1);
+ exit (EX_SOFTWARE);
}
free (src);
diff --git a/src/exec.c b/src/exec.c
index eb4c8c4..7293ca1 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -49,7 +49,7 @@ start_prog (int argc, const char **argv, pid_t *ppid)
execvp (argv[0], (char**) argv);
logmsg (LOG_CRIT, _("cannot run %s: %s"), argv[0], strerror (errno));
- exit (1);
+ exit (EX_UNAVAILABLE);
case -1:
logmsg (LOG_CRIT, _("cannot run `%s': fork failed: %s"),
diff --git a/src/getopt.m4 b/src/getopt.m4
index 83cc45f..2cd9a0f 100644
--- a/src/getopt.m4
+++ b/src/getopt.m4
@@ -179,7 +179,7 @@ ifelse([<$#>],3,opterr = 0;)
switch (c)
{
default:
- ifelse([<$#>],3,$3,[<exit(1)>]);
+ ifelse([<$#>],3,$3,[<exit (EX_USAGE)>]);
undivert(4)
}
diff --git a/src/job.c b/src/job.c
index 545d270..2c177cb 100644
--- a/src/job.c
+++ b/src/job.c
@@ -38,6 +38,15 @@ size_t jobcnt;
static struct spool fake_spool = { "all spools" };
+static int wakeup;
+
+RETSIGTYPE
+queue_signal (int sig)
+{
+ wakeup = 1;
+ signal (sig, queue_signal);
+}
+
struct job *
job_locate (const struct spool *spool, uid_t uid)
{
@@ -59,21 +68,23 @@ job_active_count ()
return count;
}
-void
+int
wydawca_scanner (struct job *job)
{
+ int rc;
initstats();
timer_start ("wydawca");
if (job->spool == &fake_spool)
- scan_all_spools (1, &job->uid);
+ rc = scan_all_spools (1, &job->uid);
else
{
spool_create_timers ();
- scan_spool (job->spool, 1, &job->uid);
+ rc = scan_spool (job->spool, 1, &job->uid);
}
timer_stop ("wydawca");
mail_finish ();
logstats ();
+ return rc;
}
int
@@ -92,15 +103,17 @@ job_start (struct job *job)
if (single_process)
{
- wydawca_scanner (job);
- return 0;
+ if (wydawca_scanner (job))
+ job->state = STATE_QUEUED;
+ else
+ job->state = STATE_FINISHED;
+ wakeup = 1;
}
pid = fork ();
if (pid == 0)
{
- wydawca_scanner (job);
- exit (0);
+ exit (wydawca_scanner (job) ? WYDAWCA_EX_AGAIN : 0);
}
else if (pid == -1)
{
@@ -235,15 +248,6 @@ print_status (struct job *job, int expect_term)
job->pid, job->spool->tag, pw->pw_name);
}
-static int wakeup;
-
-RETSIGTYPE
-queue_signal (int sig)
-{
- wakeup = 1;
- signal (sig, queue_signal);
-}
-
void
job_queue_runner ()
{
@@ -278,7 +282,14 @@ job_queue_runner ()
{
print_status (job, 0);
if ((job->state &= ~STATE_FINISHED) == 0)
- job_remove (job);
+ {
+ if (WIFEXITED (job->exit_status)
+ && WEXITSTATUS (job->exit_status) == WYDAWCA_EX_AGAIN)
+ /* Re-queue the job */
+ job->state = STATE_QUEUED;
+ else
+ job_remove (job);
+ }
}
if (job->state == STATE_QUEUED)
if (job_start (job))
diff --git a/src/lock.c b/src/lock.c
new file mode 100644
index 0000000..d94731c
--- /dev/null
+++ b/src/lock.c
@@ -0,0 +1,239 @@
+/* wydawca - automatic release submission daemon
+ Copyright (C) 2007, 2009 Sergey Poznyakoff
+
+ Wydawca is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ Wydawca 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 wydawca. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "wydawca.h"
+#include "c-ctype.h"
+#include "xgethostname.h"
+
+int enable_locking = 1;
+char *lockdir;
+time_t lock_expire_time;
+
+#define LOCKFILE_MODE 0644
+
+static int
+stat_check (const char *file, int fd, int links)
+{
+ struct stat fn_stat;
+ struct stat fd_stat;
+ int err = 0;
+ int localfd = -1;
+
+ if (fd == -1)
+ {
+ localfd = open (file, O_RDONLY);
+
+ if (localfd == -1)
+ return errno;
+ fd = localfd;
+ }
+
+ /* We should always be able to stat a valid fd, so this
+ is an error condition. */
+ if (lstat (file, &fn_stat) || fstat (fd, &fd_stat))
+ err = errno;
+ else
+ {
+ /* If the link and stat don't report the same info, or the
+ file is a symlink, fail the locking. */
+#define CHK(X) if(X) err = EINVAL
+
+ CHK (!S_ISREG (fn_stat.st_mode));
+ CHK (!S_ISREG (fd_stat.st_mode));
+ CHK (fn_stat.st_nlink != links);
+ CHK (fn_stat.st_dev != fd_stat.st_dev);
+ CHK (fn_stat.st_ino != fd_stat.st_ino);
+ CHK (fn_stat.st_mode != fd_stat.st_mode);
+ CHK (fn_stat.st_nlink != fd_stat.st_nlink);
+ CHK (fn_stat.st_uid != fd_stat.st_uid);
+ CHK (fn_stat.st_gid != fd_stat.st_gid);
+ CHK (fn_stat.st_rdev != fd_stat.st_rdev);
+
+#undef CHK
+ }
+ if (localfd != -1)
+ close (localfd);
+
+ return err;
+}
+
+int
+_lock_internal (const char *file, const char *fname)
+{
+ int err = 0;
+ int fd;
+ FILE *fp;
+
+ fd = open (fname, O_WRONLY | O_CREAT | O_EXCL, LOCKFILE_MODE);
+ if (fd == -1)
+ {
+ if (errno == EEXIST)
+ return LOCK_RETRY;
+ else
+ {
+ logmsg (LOG_ERR, _("cannot create lock file %s: %s"),
+ fname, strerror (errno));
+ return LOCK_FAILURE;
+ }
+ }
+ close (fd);
+
+ /* Try to link to the lockfile. */
+ if (link (fname, file) == -1)
+ {
+ unlink (fname);
+ if (errno == EEXIST)
+ return LOCK_RETRY;
+ else
+ {
+ logmsg (LOG_ERR, _("cannot create lock file %s: %s"),
+ file, strerror (errno));
+ return LOCK_FAILURE;
+ }
+ }
+
+ if ((fd = open (file, O_RDWR)) == -1)
+ {
+ unlink (fname);
+ logmsg (LOG_ERR, _("cannot open lock file %s: %s"),
+ fname, strerror (errno));
+ return LOCK_FAILURE;
+ }
+
+ err = stat_check (fname, fd, 2);
+ if (err)
+ {
+ unlink (fname);
+ logmsg (LOG_ERR, _("lock file check failed: %s"), strerror (errno));
+ return (err == EINVAL) ? LOCK_INVALID : LOCK_FAILURE;
+ }
+
+ unlink (fname);
+
+ fp = fdopen (fd, "w");
+ fprintf (fp, "%lu", (unsigned long) getpid ());
+ fclose (fp);
+
+ return 0;
+}
+
+static void
+expire_stale_lock (const char *file)
+{
+ int stale = 0;
+ char buf[80];
+ int fd;
+ int len;
+
+ fd = open (file, O_RDONLY);
+ if (fd == -1)
+ return;
+
+ len = read (fd, buf, sizeof (buf) - 1);
+ if (len > 0)
+ {
+ pid_t pid;
+
+ buf[len] = 0;
+ pid = strtoul (buf, NULL, 10);
+ if (pid > 0)
+ {
+ /* Process is gone so we try to remove the lock. */
+ if (kill (pid, 0) == -1)
+ stale = 1;
+ }
+ else
+ stale = 1; /* Corrupted file, remove the lock. */
+ }
+
+ if (!stale)
+ {
+ struct stat stbuf;
+ fstat (fd, &stbuf);
+ /* The lock has expired. */
+ if ((time (NULL) - stbuf.st_mtime) > lock_expire_time)
+ stale = 1;
+ }
+
+ close (fd);
+ if (stale)
+ unlink (file);
+}
+
+int
+wydawca_lock (const char *lockname)
+{
+ char *tempname = NULL;
+ int rc;
+
+ if (!enable_locking)
+ return 0;
+ expire_stale_lock (lockname);
+
+ /* build the NFS hitching-post to the lock file */
+ asprintf (&tempname, "%s.%lu.%lu.%s",
+ lockname,
+ (unsigned long) getpid (),
+ (unsigned long) time (NULL), xgethostname ());
+ if (!tempname)
+ return LOCK_FAILURE;
+ rc = _lock_internal (lockname, tempname);
+ free (tempname);
+ return rc;
+}
+
+void
+wydawca_unlock (const char *lockfile)
+{
+ if (enable_locking)
+ unlink (lockfile);
+}
+
+static char *
+fix_tagname (const char *tag)
+{
+ char *tagname = xstrdup (tag);
+ char *p;
+
+ for (p = tagname; *p; p++)
+ if (!c_isalnum (*p) && *p != '_' && *p != '-')
+ *p = '_';
+ return tagname;
+}
+
+char *
+wydawca_lockname (const char *tag)
+{
+ char *lockname = NULL;
+ char *tagname = fix_tagname (tag);
+ asprintf (&lockname, "%s/LCK.%s", lockdir, tagname);
+ if (!lockname)
+ xalloc_die ();
+ free (tagname);
+ return lockname;
+}
+
+void
+wydawca_lock_init ()
+{
+ if (enable_locking)
+ {
+ if (!lockdir)
+ lockdir = xstrdup (LOCALSTATEDIR "/lock/" PACKAGE);
+ if (create_hierarchy (lockdir, 0, getuid (), getgid ()))
+ exit (EX_OSFILE);
+ }
+}
diff --git a/src/net.c b/src/net.c
index 03f9a5a..3874827 100644
--- a/src/net.c
+++ b/src/net.c
@@ -24,7 +24,7 @@ open_listener ()
if (listen_sockaddr.sa == NULL)
{
logmsg (LOG_CRIT, _("listener address is not configured"));
- exit (1);
+ exit (EX_CONFIG);
}
fd = socket (listen_sockaddr.sa->sa_family, SOCK_STREAM, 0);
@@ -32,7 +32,7 @@ open_listener ()
{
logmsg (LOG_CRIT, _("cannot create socket: %s"),
strerror(errno));
- exit (1);
+ exit (EX_OSERR);
}
if (listen_sockaddr.sa->sa_family == AF_UNIX)
{
@@ -44,7 +44,7 @@ open_listener ()
{
logmsg (LOG_CRIT, _("%s: cannot stat socket: %s"),
s_un->sun_path, strerror (errno));
- exit (1);
+ exit (errno == EACCES ? EX_NOPERM : EX_OSERR);
}
}
else
@@ -54,7 +54,7 @@ open_listener ()
{
logmsg (LOG_CRIT, _("%s: not a socket"),
s_un->sun_path, strerror (errno));
- exit (1);
+ exit (EX_OSFILE);
}
unlink (s_un->sun_path);
}
@@ -71,13 +71,13 @@ open_listener ()
logmsg (LOG_CRIT, _("cannot bind to local address: %s"),
strerror (errno));
close (fd);
- exit (1);
+ exit (EX_OSERR);
}
if (listen (fd, 8) == -1)
{
logmsg (LOG_CRIT, "listen: %s", strerror (errno));
close (fd);
- exit (1);
+ exit (EX_OSERR);
}
return fd;
@@ -155,7 +155,7 @@ handle_connection (FILE *fp)
free (buf);
}
-static int reconfigure;
+int reconfigure;
static int terminate;
RETSIGTYPE
diff --git a/src/pidfile.c b/src/pidfile.c
index 484cabd..6da84f1 100644
--- a/src/pidfile.c
+++ b/src/pidfile.c
@@ -38,7 +38,7 @@ check_pidfile ()
{
logmsg (LOG_ERR, _("malformed pidfile %s"), pidfile);
if (!force_startup)
- exit (1);
+ exit (EX_UNAVAILABLE);
}
else
{
@@ -50,7 +50,7 @@ check_pidfile ()
_("cannot verify if PID %lu is running: %s"),
pid, strerror (errno));
if (!force_startup)
- exit (1);
+ exit (EX_UNAVAILABLE);
}
}
else if (!force_startup)
@@ -58,7 +58,7 @@ check_pidfile ()
logmsg (LOG_ERR,
_("another wydawca instance may be running (PID %lu)"),
pid);
- exit (1);
+ exit (EX_UNAVAILABLE);
}
}
logmsg (LOG_NOTICE, _("replacing pidfile %s (PID %lu)"),
@@ -69,7 +69,7 @@ check_pidfile ()
{
logmsg (LOG_ERR, _("cannot open pidfile %s: %s"), pidfile,
strerror (errno));
- exit (1);
+ exit (EX_UNAVAILABLE);
}
else
{
@@ -79,7 +79,7 @@ check_pidfile ()
logmsg (LOG_ERR,
_("cannot open pidfile %s for writing: %s"),
pidfile, strerror (errno));
- exit (1);
+ exit (EX_UNAVAILABLE);
}
}
fprintf (fp, "%lu\n", getpid ());
diff --git a/src/process.c b/src/process.c
index 1a6b01d..d04121c 100644
--- a/src/process.c
+++ b/src/process.c
@@ -137,7 +137,7 @@ match_uid_p (uid_t uid, int uc, uid_t *uv)
/* Scan upload directory from the DPAIR and register all files found
there, forming triplets when possible */
void
-scan_spool (const struct spool *spool, int uc, uid_t *uv)
+scan_spool_unlocked (const struct spool *spool, int uc, uid_t *uv)
{
DIR *dir;
struct dirent *ent;
@@ -225,6 +225,20 @@ scan_spool (const struct spool *spool, int uc, uid_t *uv)
timer_stop ("spool");
}
+int
+scan_spool (const struct spool *spool, int uc, uid_t *uv)
+{
+ char *lockfile = wydawca_lockname (spool->tag);
+ int rc = wydawca_lock (lockfile);
+ if (rc == LOCK_OK)
+ {
+ scan_spool_unlocked (spool, uc, uv);
+ wydawca_unlock (lockfile);
+ }
+ free (lockfile);
+ return rc;
+}
+
static void
close_methods (struct spool *spool)
{
@@ -234,19 +248,22 @@ close_methods (struct spool *spool)
}
/* Scan all configured update directories */
-void
+int
scan_all_spools (int uidc, uid_t *uidv)
{
struct spool_list *sp;
-
+ int rc = 0;
+
timer_start ("wydawca");
for (sp = spool_list; sp; sp = sp->next)
if (enabled_spool_p (&sp->spool))
- scan_spool (&sp->spool, uidc, uidv);
+ if (scan_spool (&sp->spool, uidc, uidv))
+ rc++;
for (sp = spool_list; sp; sp = sp->next)
close_methods (&sp->spool);
timer_stop ("wydawca");
+ return rc;
}
void
diff --git a/src/triplet.c b/src/triplet.c
index 717fd2a..285c831 100644
--- a/src/triplet.c
+++ b/src/triplet.c
@@ -199,10 +199,10 @@ triplet_processor (void *data, void *proc_data)
case triplet_complete:
if (debug_level)
logmsg (LOG_DEBUG, _("processing triplet `%s'"), trp->name);
- if (wydawca_uid (TRIPLET_UID (trp)) == 0)
+ if (wydawca_set_uid (TRIPLET_UID (trp)) == 0)
{
process_directives (trp, spool);
- wydawca_uid (0);
+ wydawca_set_uid (0);
}
return true;
diff --git a/src/wydawca.c b/src/wydawca.c
index f9818ed..b121959 100644
--- a/src/wydawca.c
+++ b/src/wydawca.c
@@ -255,7 +255,7 @@ collect_uids (int argc, char **argv)
if (*p)
{
logmsg (LOG_ERR, _("no such user: %s"), argv[i]);
- exit (1);
+ exit (EX_NOUSER);
}
uidv[i] = n;
}
@@ -266,7 +266,7 @@ collect_uids (int argc, char **argv)
int
-wydawca_uid (uid_t uid)
+wydawca_set_uid (uid_t uid)
{
int rc;
@@ -287,7 +287,32 @@ wydawca_uid (uid_t uid)
return rc;
}
+int
+wydawca_set_gid (gid_t gid)
+{
+ int rc;
+
+ if (getuid () != 0)
+ return 0;
+#if defined(HAVE_SETREGID)
+ rc = setregid (0, gid);
+#elif defined(HAVE_SETRESGID)
+ rc = setresgid (-1, gid, -1);
+#elif defined(HAVE_SETEGID)
+ rc = setegid (gid);
+#else
+# error "No way to reset user privileges?"
+#endif
+ if (rc < 0)
+ logmsg (LOG_ERR, _("cannot switch to GID %d: %s (r=%d, e=%d)"),
+ gid, strerror (errno), getgid (), getegid ());
+ return rc;
+}
+
+char **x_argv;
+extern int reconfigure;
+
void
wydawca_daemon ()
{
@@ -296,7 +321,7 @@ wydawca_daemon ()
if (!foreground && daemon (0, 0))
{
logmsg (LOG_ERR, "%s", strerror (errno));
- exit (1);
+ exit (EX_OSERR);
}
wydawca_listener ();
@@ -312,6 +337,7 @@ main (int argc, char **argv)
mu_register_all_mailer_formats ();
config_init ();
+ x_argv = argv;
parse_options (argc, argv);
argv += optind;
@@ -321,9 +347,10 @@ main (int argc, char **argv)
collect_uids (argc, argv);
if (preprocess_only)
- exit (gconf_preproc_run (conffile, gconf_preprocessor));
+ exit (gconf_preproc_run (conffile, gconf_preprocessor) ? EX_CONFIG : 0);
- gconf_parse (conffile);
+ if (gconf_parse (conffile))
+ exit (EX_CONFIG);
if (lint_mode)
exit (0);
@@ -346,7 +373,8 @@ main (int argc, char **argv)
}
mail_init ();
-
+ wydawca_lock_init ();
+
logmsg (LOG_NOTICE, _("wydawca (%s) started"), PACKAGE_STRING);
if (!daemon_mode)
@@ -361,5 +389,15 @@ main (int argc, char **argv)
mail_finish ();
+ if (reconfigure)
+ {
+ int i;
+ wydawca_set_uid (0);
+ for (i = getdtablesize (); i > 2; i--)
+ close (i);
+ remove_pidfile ();
+ execv (x_argv[0], x_argv);
+ }
+
exit (0);
}
diff --git a/src/wydawca.h b/src/wydawca.h
index 6384738..f093504 100644
--- a/src/wydawca.h
+++ b/src/wydawca.h
@@ -40,6 +40,7 @@
#include <arpa/inet.h>
#include <fcntl.h>
#include <time.h>
+#include <sysexits.h>
#include <mailutils/types.h>
#include <mailutils/url.h>
@@ -63,6 +64,8 @@
#define SP(s) ((s) ? (s) : "NONE")
+#define WYDAWCA_EX_AGAIN 1
+
/* The range of directive versions we accept (major * 100 + minor) */
#define MIN_DIRECTIVE_VERSION 101
#define MAX_DIRECTIVE_VERSION 101
@@ -319,6 +322,10 @@ extern char *admin_stat_message;
extern char *pidfile;
extern int force_startup;
+extern char *lockdir;
+extern time_t lock_expire_time;
+extern int enable_locking;
+
extern int daemon_mode;
extern time_t wakeup_interval;
extern int foreground;
@@ -364,8 +371,9 @@ enum exec_result wydawca_exec (int argc, const char **argv, int *retcode);
/* Directory scanning and registering */
-void scan_spool (const struct spool *spool, int uc, uid_t *uv);
-void scan_all_spools (int, uid_t *);
+int scan_spool (const struct spool *spool, int uc, uid_t *uv);
+int scan_all_spools (int, uid_t *);
+void spool_create_timers (void);
void register_spool (struct spool *spool);
struct spool *wydawca_find_spool (const char *name);
@@ -420,7 +428,7 @@ int process_directives (struct file_triplet *trp,
int enabled_spool_p (const struct spool *spool);
-int wydawca_uid (uid_t uid);
+int wydawca_set_uid (uid_t uid);
int parse_time_interval (const char *str, time_t *pint, const char **endp);
@@ -504,7 +512,20 @@ void job_queue_runner (void);
/* profile.c */
void check_pidfile (void);
+void remove_pidfile (void);
/* net.c */
void wydawca_listener (void);
+
+
+#define LOCK_OK 0
+#define LOCK_CONFLICT 1
+#define LOCK_RETRY 2
+#define LOCK_INVALID 3
+#define LOCK_FAILURE 4
+
+char *wydawca_lockname (const char *tag);
+int wydawca_lock (const char *lockname);
+void wydawca_unlock (const char *lockname);
+void wydawca_lock_init (void);
diff --git a/tests/etc/wydawca.rcin b/tests/etc/wydawca.rcin
index 36ef7a2..bc6aaa4 100644
--- a/tests/etc/wydawca.rcin
+++ b/tests/etc/wydawca.rcin
@@ -18,6 +18,8 @@ statistics all;
umask 022;
+locking no;
+
access-method project-owner {
type builtin;
query "${project}";

Return to:

Send suggestions and report system problems to the System administrator.