summaryrefslogtreecommitdiffstats
path: root/lib/libutil
diff options
context:
space:
mode:
authorbri <bri@openbsd.org>1997-11-09 00:29:02 +0000
committerbri <bri@openbsd.org>1997-11-09 00:29:02 +0000
commitc280f579c91ef05f227b22eac4160545864eb658 (patch)
tree092c56da469fba769d355bee0a95afc619523274 /lib/libutil
parentSort idle processes by total CPU usage, not cpticks since cpticks (diff)
downloadwireguard-openbsd-c280f579c91ef05f227b22eac4160545864eb658.tar.xz
wireguard-openbsd-c280f579c91ef05f227b22eac4160545864eb658.zip
Introduce uu_lock(), uu_unlock() and uu_lockerr()
into libutil. Obtained from: FreeBSD Reviewed by: Theo
Diffstat (limited to 'lib/libutil')
-rw-r--r--lib/libutil/Makefile10
-rw-r--r--lib/libutil/shlib_version2
-rw-r--r--lib/libutil/util.h14
-rw-r--r--lib/libutil/uucplock.3160
-rw-r--r--lib/libutil/uucplock.c211
5 files changed, 392 insertions, 5 deletions
diff --git a/lib/libutil/Makefile b/lib/libutil/Makefile
index 4f6c215bc7c..ca526ded95f 100644
--- a/lib/libutil/Makefile
+++ b/lib/libutil/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.14 1997/06/17 10:10:41 niklas Exp $
+# $OpenBSD: Makefile,v 1.15 1997/11/09 00:29:13 bri Exp $
# $NetBSD: Makefile,v 1.8 1996/05/16 07:03:28 thorpej Exp $
LIB= util
@@ -6,11 +6,12 @@ CFLAGS+=-DLIBC_SCCS
HDRS= util.h scsi.h
SRCS= getmaxpartitions.c getrawpartition.c login.c login_tty.c logout.c \
- logwtmp.c opendev.c passwd.c pty.c readlabel.c scsi.c login_fbtab.c
+ logwtmp.c opendev.c passwd.c pty.c readlabel.c scsi.c login_fbtab.c \
+ uucplock.c
# XXX need login_fbtab.3
MAN= getmaxpartitions.3 getrawpartition.3 login.3 opendev.3 openpty.3 \
- pw_init.3 pw_lock.3 readlabelfs.3 scsi.3 pw_getconf.3
+ pw_init.3 pw_lock.3 readlabelfs.3 scsi.3 pw_getconf.3 uucplock.3
MLINKS+=login.3 logout.3
MLINKS+=login.3 logwtmp.3
@@ -36,6 +37,9 @@ MLINKS+=scsi.3 SCSIREQ_ERROR.3
MLINKS+=scsi.3 scsi_open.3
MLINKS+=scsi.3 scsi_debug.3
MLINKS+=scsi.3 scsi_debug_output.3
+MLINKS+=uucplock.3 uu_lock.3
+MLINKS+=uucplock.3 uu_unlock.3
+MLINKS+=uucplock.3 uu_lockerr.3
includes:
@cd ${.CURDIR}; for i in $(HDRS); do \
diff --git a/lib/libutil/shlib_version b/lib/libutil/shlib_version
index d9961ea9fef..890c57389b5 100644
--- a/lib/libutil/shlib_version
+++ b/lib/libutil/shlib_version
@@ -1,2 +1,2 @@
major=4
-minor=0
+minor=1
diff --git a/lib/libutil/util.h b/lib/libutil/util.h
index acadd530050..9fd98e23862 100644
--- a/lib/libutil/util.h
+++ b/lib/libutil/util.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.h,v 1.6 1997/06/17 10:10:43 niklas Exp $ */
+/* $OpenBSD: util.h,v 1.7 1997/11/09 00:29:14 bri Exp $ */
/* $NetBSD: util.h,v 1.2 1996/05/16 07:00:22 thorpej Exp $ */
/*-
@@ -76,6 +76,18 @@ int getmaxpartitions __P((void));
int getrawpartition __P((void));
void login_fbtab __P((char *, uid_t, gid_t));
char *readlabelfs __P((char *, int));
+const char *uu_lockerr __P((int _uu_lockresult));
+int uu_lock __P((const char *_ttyname));
+int uu_unlock __P((const char *_ttyname));
__END_DECLS
+#define UU_LOCK_INUSE (1)
+#define UU_LOCK_OK (0)
+#define UU_LOCK_OPEN_ERR (-1)
+#define UU_LOCK_READ_ERR (-2)
+#define UU_LOCK_CREAT_ERR (-3)
+#define UU_LOCK_WRITE_ERR (-4)
+#define UU_LOCK_LINK_ERR (-5)
+#define UU_LOCK_TRY_ERR (-6)
+
#endif /* !_UTIL_H_ */
diff --git a/lib/libutil/uucplock.3 b/lib/libutil/uucplock.3
new file mode 100644
index 00000000000..40eeab60847
--- /dev/null
+++ b/lib/libutil/uucplock.3
@@ -0,0 +1,160 @@
+.\"
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $Id: uucplock.3,v 1.1 1997/11/09 00:29:14 bri Exp $
+.\" "
+.Dd March 30, 1997
+.Os
+.Dt uucplock 3
+.Sh NAME
+.Nm uu_lock ,
+.Nm uu_unlock ,
+.Nm uu_lockerr
+.Nd acquire and release control of a serial device
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <libutil.h>
+.Ft int
+.Fn uu_lock "const char *ttyname"
+.Ft int
+.Fn uu_unlock "const char *ttyname"
+.Ft const char *
+.Fn uu_lockerr "int uu_lockresult"
+.Pp
+Link with
+.Va -lutil
+on the
+.Xr cc 1
+command line.
+.Sh DESCRIPTION
+The
+.Fn uu_lock
+function attempts to create a lock file called
+.Pa /var/spool/lock/LCK..
+with a suffix given by the passed
+.Fa ttyname .
+If the file already exists, it is expected to contain the process
+id of the locking program.
+.Pp
+If the file does not already exist, or the owning process given by
+the process id found in the lock file is no longer running,
+.Fn uu_lock
+will write its own process id into the file and return success.
+.Pp
+.Fn uu_unlock
+removes the lockfile created by
+.Fn uu_lock
+for the given
+.Fa ttyname .
+Care should be taken that
+.Fn uu_lock
+was successful before calling
+.Fn uu_unlock .
+.Pp
+.Fn uu_lockerr
+returns an error string representing the error
+.Fa uu_lockresult ,
+as returned from
+.Fn uu_lock .
+.Sh RETURN VALUES
+.Fn uu_unlock
+returns 0 on success and -1 on failure.
+.Pp
+.Fn uu_lock
+may return any of the following values:
+.Pp
+.Dv UU_LOCK_INUSE:
+The lock is in use by another process.
+.Pp
+.Dv UU_LOCK_OK:
+The lock was successfully created.
+.Pp
+.Dv UU_LOCK_OPEN_ERR:
+The lock file could not be opened via
+.Xr open 2 .
+.Pp
+.Dv UU_LOCK_READ_ERR:
+The lock file could not be read via
+.Xr read 2 .
+.Pp
+.Dv UU_LOCK_CREAT_ERR:
+Can't create temporary lock file via
+.Xr creat 2 .
+.Pp
+.Dv UU_LOCK_WRITE_ERR:
+The current process id could not be written to the lock file via a call to
+.Xr write 2 .
+.Pp
+.Dv UU_LOCK_LINK_ERR:
+Can't link temporary lock file via
+.Xr link 2 .
+.Pp
+.Dv UU_LOCK_TRY_ERR:
+Locking attempts are failed after 5 tries.
+.Pp
+If a value of
+.Dv UU_LOCK_OK
+is passed to
+.Fn uu_lockerr ,
+an empty string is returned.
+Otherwise, a string specifying
+the reason for failure is returned.
+.Fn uu_lockerr
+uses the current value of
+.Va errno
+to determine the exact error. Care should be made not to allow
+.Va errno
+to be changed between calls to
+.Fn uu_lock
+and
+.Fn uu_lockerr .
+.Sh ERRORS
+If
+.Fn uu_lock
+returns one of the four error values above, the global value
+.Va errno
+can be used to determine the cause. Refer to the respective manual pages
+for further details.
+.Pp
+.Fn uu_unlock
+will set the global variable
+.Va errno
+to reflect the reason that the lock file could not be removed.
+Refer to the description of
+.Xr unlink 2
+for further details.
+.Sh SEE ALSO
+.Xr lseek 2 ,
+.Xr open 2 ,
+.Xr read 2 ,
+.Xr write 2
+.Sh BUGS
+It is possible that a stale lock is not recognised as such if a new
+processes is assigned the same processes id as the program that left
+the stale lock.
+.Pp
+The calling process must have write permissions to the
+.Pa /var/spool/lock
+directory. There is no mechanism in place to ensure that the
+permissions of this directory are the same as those of the
+serial devices that might be locked.
diff --git a/lib/libutil/uucplock.c b/lib/libutil/uucplock.c
new file mode 100644
index 00000000000..5f879df8290
--- /dev/null
+++ b/lib/libutil/uucplock.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: uucplock.c,v 1.1 1997/11/09 00:29:15 bri Exp $
+ *
+ */
+
+#ifndef lint
+static const char sccsid[] = "@(#)uucplock.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <paths.h>
+#include <string.h>
+#include "util.h"
+
+#define MAXTRIES 5
+
+#define LOCKTMP "LCKTMP..%d"
+#define LOCKFMT "LCK..%s"
+
+#define GORET(level, val) { err = errno; uuerr = (val); \
+ goto __CONCAT(ret, level); }
+
+/* Forward declarations */
+static int put_pid __P((int fd, pid_t pid));
+static pid_t get_pid __P((int fd,int *err));
+
+/*
+ * uucp style locking routines
+ */
+
+int
+uu_lock(ttyname)
+ const char *ttyname;
+{
+ int fd, tmpfd, i;
+ pid_t pid;
+ char lckname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN],
+ lcktmpname[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
+ int err, uuerr;
+
+ pid = getpid();
+ (void)snprintf(lcktmpname, sizeof(lcktmpname), _PATH_UUCPLOCK LOCKTMP,
+ pid);
+ (void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT,
+ ttyname);
+ if ((tmpfd = creat(lcktmpname, 0664)) < 0)
+ GORET(0, UU_LOCK_CREAT_ERR);
+
+ for (i = 0; i < MAXTRIES; i++) {
+ if (link (lcktmpname, lckname) < 0) {
+ if (errno != EEXIST)
+ GORET(1, UU_LOCK_LINK_ERR);
+ /*
+ * file is already locked
+ * check to see if the process holding the lock
+ * still exists
+ */
+ if ((fd = open(lckname, O_RDONLY)) < 0)
+ GORET(1, UU_LOCK_OPEN_ERR);
+
+ if ((pid = get_pid (fd, &err)) == -1)
+ GORET(2, UU_LOCK_READ_ERR);
+
+ close(fd);
+
+ if (kill(pid, 0) == 0 || errno != ESRCH)
+ GORET(1, UU_LOCK_INUSE);
+ /*
+ * The process that locked the file isn't running, so
+ * we'll lock it ourselves
+ */
+ (void)unlink(lckname);
+ } else {
+ if (!put_pid (tmpfd, pid))
+ GORET(3, UU_LOCK_WRITE_ERR);
+ break;
+ }
+ }
+ GORET(1, (i >= MAXTRIES) ? UU_LOCK_TRY_ERR : UU_LOCK_OK);
+
+ret3:
+ (void)unlink(lckname);
+ goto ret1;
+ret2:
+ (void)close(fd);
+ret1:
+ (void)close(tmpfd);
+ (void)unlink(lcktmpname);
+ret0:
+ errno = err;
+ return uuerr;
+}
+
+int
+uu_unlock(ttyname)
+ const char *ttyname;
+{
+ char tbuf[sizeof(_PATH_UUCPLOCK) + MAXNAMLEN];
+
+ (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, ttyname);
+ return unlink(tbuf);
+}
+
+const char *
+uu_lockerr(uu_lockresult)
+ int uu_lockresult;
+{
+ static char errbuf[128];
+ char *fmt;
+
+ switch (uu_lockresult) {
+ case UU_LOCK_INUSE:
+ return "device in use";
+ case UU_LOCK_OK:
+ return "";
+ case UU_LOCK_OPEN_ERR:
+ fmt = "open error: %s";
+ break;
+ case UU_LOCK_READ_ERR:
+ fmt = "read error: %s";
+ break;
+ case UU_LOCK_CREAT_ERR:
+ fmt = "creat error: %s";
+ break;
+ case UU_LOCK_WRITE_ERR:
+ fmt = "write error: %s";
+ break;
+ case UU_LOCK_LINK_ERR:
+ fmt = "link error: %s";
+ break;
+ case UU_LOCK_TRY_ERR:
+ fmt = "too many tries: %s";
+ break;
+ default:
+ fmt = "undefined error: %s";
+ break;
+ }
+
+ (void)snprintf(errbuf, sizeof(errbuf), fmt, strerror(errno));
+ return errbuf;
+}
+
+static int
+put_pid(fd, pid)
+ int fd;
+ pid_t pid;
+{
+ char buf[32];
+ int len;
+
+ len = sprintf (buf, "%10d\n", pid);
+ return write (fd, buf, len) == len && ftruncate(fd, len);
+}
+
+static pid_t
+get_pid(fd, err)
+ int fd;
+ int *err;
+{
+ int bytes_read;
+ char buf[32];
+ pid_t pid;
+
+ bytes_read = read (fd, buf, sizeof (buf) - 1);
+ if (bytes_read > 0) {
+ buf[bytes_read] = '\0';
+ pid = strtoul (buf, (char **) NULL, 10);
+ } else {
+ pid = -1;
+ *err = bytes_read ? errno : EINVAL;
+ }
+ return pid;
+}