tags 448470 + patch
thanks

This problem is solved by getting portmap to write a pidfile, making
sure the correct process is checked by the start script instead of a
random one with the portmap name.  This is the same patch as the one
submitted for bug #468665.

--- portmap-6.0.orig/portmap.c
+++ portmap-6.0/portmap.c
@@ -98,6 +98,8 @@

 #include <stdlib.h>
 #include <pwd.h>
+#include <stdarg.h>
+#include <sys/stat.h>

 #ifndef LOG_PERROR
 #define LOG_PERROR 0
@@ -169,6 +171,126 @@
        int priv;
 };

+#ifndef PIDFILE
+#  define PIDFILE "/var/run/portmap.pid"
+#endif
+
+/*
+ * Copied from the atd source
+ */
+static int
+lock_fd(int fd)
+{
+    struct flock lock;
+
+    lock.l_type = F_WRLCK;
+    lock.l_whence = SEEK_SET;
+    lock.l_start = 0;
+    lock.l_len = 0;
+
+    return fcntl(fd, F_SETLK, &lock);
+}
+
+void
+perr(const char *fmt,...)
+{
+    char buf[1024];
+    va_list args;
+
+    va_start(args, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, args);
+    va_end(args);
+
+    if (debugging) {
+       perror(buf);
+    } else
+       syslog(LOG_ERR, "%s: %m", buf);
+
+    exit(EXIT_FAILURE);
+}
+
+void
+pabort(const char *fmt,...)
+{
+    char buf[1024];
+    va_list args;
+
+    va_start(args, fmt);
+    vsnprintf(buf, sizeof(buf), fmt, args);
+    va_end(args);
+
+    if (debugging) {
+       fprintf(stderr, "%s\n", buf);
+    } else
+       syslog(LOG_ERR, "%s", buf);
+
+    exit(EXIT_FAILURE);
+}
+
+FILE *
+save_pidfile(void) {
+    pid_t pid;
+    int fd;
+    FILE *fp;
+    fd = open(PIDFILE, O_RDWR | O_CREAT | O_EXCL,
+             S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+
+    if (fd == -1) {
+
+       if (errno != EEXIST)
+           perr("Cannot open " PIDFILE);
+
+       if ((fd = open(PIDFILE, O_RDWR)) < 0)
+           perr("Cannot open " PIDFILE);
+
+       fp = fdopen(fd, "rw");
+       if (fp == NULL) {
+           perr("Cannot open " PIDFILE " for reading");
+       }
+       pid = -1;
+       if ((fscanf(fp, "%d", &pid) != 1) || (pid == getpid())
+           || (lock_fd(fileno(fp)) == 0)) {
+           int rc;
+
+           syslog(LOG_NOTICE, "Removing stale lockfile for pid %d", pid);
+
+           rc = unlink(PIDFILE);
+
+           if (rc == -1) {
+               perr("Cannot unlink " PIDFILE);
+           }
+       } else {
+           pabort("Another atd already running with pid %d", pid);
+       }
+       fclose(fp);
+
+       unlink(PIDFILE);
+       fd = open(PIDFILE, O_RDWR | O_CREAT | O_EXCL,
+                 S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+
+
+       if (fd == -1)
+           perr("Cannot open " PIDFILE " the second time round");
+
+    }
+
+    if (lock_fd(fd) == -1)
+       perr("Cannot lock " PIDFILE);
+
+    fp = fdopen(fd, "w");
+    if (fp == NULL)
+       perr("Special weirdness: fdopen failed");
+
+    fprintf(fp, "%d\n", getpid());
+
+    /* We do NOT close fd, since we want to keep the lock. However, we don't
+     * want to keep the file descriptor in case of an exec().
+     */
+    fflush(fp);
+    fcntl(fd, F_SETFD, (long) 1);
+    return fp;
+}
+
 int
 main(int argc, char **argv)
 {
@@ -252,6 +374,8 @@
                exit(1);
        }

+       save_pidfile();
+
 #ifdef LOG_DAEMON
        openlog("portmap", LOG_PID|LOG_NDELAY | ( foreground ? LOG_PERROR : 0),
            FACILITY);



-- 
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]

Reply via email to