libutil: Various updates from FreeBSD, esp. pid_* functions
authorJohn Marino <draco@marino.st>
Sun, 9 Feb 2014 14:21:13 +0000 (15:21 +0100)
committerJohn Marino <draco@marino.st>
Sun, 9 Feb 2014 19:07:22 +0000 (20:07 +0100)
It appears that libutil.so is another Frankenstein monster where half
of it came from FreeBSD and later it was updated with NetBSD functions.
Like libm, this causes problems with syncing later.

In order to update the daemon program, the set of pidfile_* functions
had to be brought in from FreeBSD.  While doing that, I synced with
FreeBSD as much as possible.  The expand number function was added
as well as a dedicated pw_util man page.

Specifically ignored were FreeBSD functionality involving kinfo and kld.
The login functions are essentially incompatible as the FreeBSD ones
require syscntls, so I left the NetBSD versions alone.  The various
humanize functions that only exist on DragonFly were also left untouched.

Collateral damage included:
  sbin/devd/devd.[ch][ch]       (partial sync)
  usr.sbin/authpf/authpf.c      (partial sync)
  usr.sbin/apmd/apmd.c
  usr.sbin/battd/battd.c
  usr.sbin/bthcid/bthcid.c
  usr.sbin/pflogd/pflogd.c
  usr.sbin/rwhod/rwhod.c
  usr.sbin/syslogd/             (full sync)
  usr.sbin/sysvipcd/sysvipcd.c

65 files changed:
lib/libutil/Makefile
lib/libutil/_secure_path.3
lib/libutil/_secure_path.c
lib/libutil/auth.c
lib/libutil/dehumanize_number.c
lib/libutil/expand_number.3 [new file with mode: 0644]
lib/libutil/expand_number.c [new file with mode: 0644]
lib/libutil/flopen.3
lib/libutil/flopen.c
lib/libutil/fparseln.3
lib/libutil/fparseln.c
lib/libutil/gr_util.c
lib/libutil/hexdump.3
lib/libutil/hexdump.c
lib/libutil/humanize_number.3
lib/libutil/humanize_number.c
lib/libutil/humanize_unsigned.c
lib/libutil/libutil.h
lib/libutil/login.c
lib/libutil/login.conf.5
lib/libutil/login_auth.3
lib/libutil/login_auth.c
lib/libutil/login_cap.3
lib/libutil/login_cap.c
lib/libutil/login_cap.h
lib/libutil/login_class.c
lib/libutil/login_crypt.c
lib/libutil/login_ok.3
lib/libutil/login_ok.c
lib/libutil/login_times.3
lib/libutil/login_times.c
lib/libutil/login_tty.3
lib/libutil/login_tty.c
lib/libutil/logout.c
lib/libutil/logwtmp.c
lib/libutil/pidfile.3
lib/libutil/pidfile.c
lib/libutil/property.3
lib/libutil/property.c
lib/libutil/pty.3
lib/libutil/pty.c
lib/libutil/pw_util.3 [new file with mode: 0644]
lib/libutil/pw_util.c
lib/libutil/realhostname.3
lib/libutil/realhostname.c
lib/libutil/realhostname_sa.3
lib/libutil/stub.c
lib/libutil/trimdomain.3
lib/libutil/trimdomain.c
lib/libutil/uucplock.3
lib/libutil/uucplock.c
sbin/devd/devd.cc
sbin/devd/devd.hh
usr.sbin/apmd/apmd.c
usr.sbin/authpf/authpf.c
usr.sbin/battd/battd.c
usr.sbin/bthcid/bthcid.c
usr.sbin/pflogd/pflogd.c
usr.sbin/rwhod/rwhod.c
usr.sbin/syslogd/Makefile
usr.sbin/syslogd/pathnames.h
usr.sbin/syslogd/syslog.conf.5
usr.sbin/syslogd/syslogd.8
usr.sbin/syslogd/syslogd.c
usr.sbin/sysvipcd/sysvipcd.c

index 3d6dcdb..4fa15db 100644 (file)
@@ -1,5 +1,5 @@
 #      @(#)Makefile    8.1 (Berkeley) 6/4/93
-#      $FreeBSD: src/lib/libutil/Makefile,v 1.33.2.4 2001/04/25 10:04:42 ru Exp $
+#      $FreeBSD: head/lib/libutil/Makefile 242381 2012-10-30 22:18:08Z bapt $
 
 LIB=   util
 SHLIB_MAJOR= 4
@@ -12,7 +12,7 @@ SRCS= flopen.c login.c login_tty.c logout.c logwtmp.c logwtmpx.c pty.c \
        realhostname.c fparseln.c stub.c pidfile.c trimdomain.c \
        dehumanize_number.c humanize_number.c humanize_unsigned.c pw_util.c \
        efun.c getmntopts.c
-SRCS+= gr_util.c hexdump.c
+SRCS+= gr_util.c hexdump.c expand_number.c
 
 INCS=  libutil.h login_cap.h
 INCSLINKS=libutil.h ${INCLUDEDIR}/util.h
@@ -29,6 +29,7 @@ MAN+= flopen.3 login.3 loginx.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 \
        efun.3 getmntopts.3
 MAN+=  login.conf.5 auth.conf.5
 MAN+=  hexdump.3
+MAN+=  pw_util.3
 
 MLINKS+=auth.3 auth_getval.3
 MLINKS+=efun.3 ecalloc.3 efun.3 emalloc.3 efun.3 erealloc.3 efun.3 esetfunc.3 \
@@ -57,5 +58,18 @@ MLINKS+=property.3 property_find.3
 MLINKS+=pty.3 openpty.3 pty.3 forkpty.3
 MLINKS+=uucplock.3 uu_lock.3 uucplock.3 uu_lock_txfr.3 \
        uucplock.3 uu_unlock.3 uucplock.3 uu_lockerr.3
+MLINKS+=pw_util.3 pw_copy.3 \
+       pw_util.3 pw_dup.3 \
+       pw_util.3 pw_edit.3 \
+       pw_util.3 pw_equal.3 \
+       pw_util.3 pw_fini.3 \
+       pw_util.3 pw_init.3 \
+       pw_util.3 pw_make.3 \
+       pw_util.3 pw_make_v7.3 \
+       pw_util.3 pw_mkdb.3 \
+       pw_util.3 pw_lock.3 \
+       pw_util.3 pw_scan.3 \
+       pw_util.3 pw_tempname.3 \
+       pw_util.3 pw_tmp.3
 
 .include <bsd.lib.mk>
index 18a2977..e9db2c0 100644 (file)
@@ -17,7 +17,7 @@
 .\" 5. Modifications may be freely made to this file providing the above
 .\"    conditions are met.
 .\"
-.\" $FreeBSD: src/lib/libutil/_secure_path.3,v 1.7.2.4 2002/03/19 01:49:54 dd Exp $
+.\" $FreeBSD: head/lib/libutil/_secure_path.3 206622 2010-04-14 19:08:06Z uqs $
 .\"
 .Dd May 2, 1997
 .Dt _SECURE_PATH 3
@@ -58,8 +58,9 @@ gid, if gid is not -1.
 This function returns zero if the file exists and may be
 considered secure, -2 if the file does not exist, and
 -1 otherwise to indicate a security failure.
+The
 .Xr syslog 3
-is used to log any failure of this function, including the
+function is used to log any failure of this function, including the
 reason, at LOG_ERR priority.
 .Sh SEE ALSO
 .Xr lstat 2 ,
index 0a811c8..576aff2 100644 (file)
@@ -18,8 +18,7 @@
  * 5. Modifications may be freely made to this file providing the above
  *    conditions are met.
  *
- * $FreeBSD: src/lib/libutil/_secure_path.c,v 1.5 1999/08/28 00:05:42 peter Exp $
- * $DragonFly: src/lib/libutil/_secure_path.c,v 1.4 2008/10/29 22:03:12 swildner Exp $
+ * $FreeBSD: head/lib/libutil/_secure_path.c 139012 2004-12-18 12:31:12Z ru $
  */
 
 
 #include <sys/stat.h>
 
 #include <errno.h>
+#include <libutil.h>
 #include <syslog.h>
 
-#include "libutil.h"
-
 /*
  * Check for common security problems on a given path
  * It must be:
  * 1. A regular file, and exists
- * 2. Owned and writaable only by root (or given owner)
+ * 2. Owned and writable only by root (or given owner)
  * 3. Group ownership is given group or is non-group writable
  *
  * Returns:    -2 if file does not exist,
index 80206c8..c763b38 100644 (file)
@@ -29,7 +29,6 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/lib/libutil/auth.c,v 1.3.6.1 2001/03/05 06:29:52 kris Exp $
- * $DragonFly: src/lib/libutil/auth.c,v 1.3 2005/03/04 04:31:11 cpressey Exp $
  *
  */
 
@@ -39,8 +38,7 @@
 #include <paths.h>
 #include <syslog.h>
 #include <unistd.h>
-
-#include "libutil.h"
+#include <libutil.h>
 
 static properties P;
 
index da80fbf..1905c0a 100644 (file)
@@ -36,8 +36,7 @@
 #include <string.h>
 #include <errno.h>
 #include <limits.h>
-
-#include "libutil.h"
+#include <libutil.h>
 
 /*
  * Converts the number given in 'str', which may be given in a humanized
diff --git a/lib/libutil/expand_number.3 b/lib/libutil/expand_number.3
new file mode 100644 (file)
index 0000000..895e372
--- /dev/null
@@ -0,0 +1,87 @@
+.\" Copyright (c) 2007 Eric Anderson <anderson@FreeBSD.org>
+.\" Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+.\" 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 AUTHORS 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 AUTHORS 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.
+.\"
+.\" $FreeBSD: head/lib/libutil/expand_number.3 258026 2013-11-12 00:56:22Z eadler $
+.\"
+.Dd August 15, 2010
+.Dt EXPAND_NUMBER 3
+.Os
+.Sh NAME
+.Nm expand_number
+.Nd format a number from human readable form
+.Sh LIBRARY
+.Lb libutil
+.Sh SYNOPSIS
+.In libutil.h
+.Ft int
+.Fo expand_number
+.Fa "const char *buf" "uint64_t *num"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn expand_number
+function unformats the
+.Fa buf
+string and stores a unsigned 64-bit quantity at address pointed out by the
+.Fa num
+argument.
+.Pp
+The
+.Fn expand_number
+function
+is case-insensitive and
+follows the SI power of two convention.
+.Pp
+The prefixes are:
+.Bl -column "Prefix" "Description" "1000000000000000000" -offset indent
+.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier"
+.It Li K Ta No kilo Ta 1024
+.It Li M Ta No mega Ta 1048576
+.It Li G Ta No giga Ta 1073741824
+.It Li T Ta No tera Ta 1099511627776
+.It Li P Ta No peta Ta 1125899906842624
+.It Li E Ta No exa  Ta 1152921504606846976
+.El
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+The
+.Fn expand_number
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The given string contains no digits.
+.It Bq Er EINVAL
+An unrecognized prefix was given.
+.It Bq Er ERANGE
+Result doesn't fit into 64 bits.
+.El
+.Sh SEE ALSO
+.Xr humanize_number 3
+.Sh HISTORY
+The
+.Fn expand_number
+function first appeared in
+.Fx 6.3 .
diff --git a/lib/libutil/expand_number.c b/lib/libutil/expand_number.c
new file mode 100644 (file)
index 0000000..fc099f7
--- /dev/null
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 2007 Eric Anderson <anderson@FreeBSD.org>
+ * Copyright (c) 2007 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+ * 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 AUTHORS 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 AUTHORS 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.
+ *
+ * $FreeBSD: head/lib/libutil/expand_number.c 255069 2013-08-30 11:21:52Z pluknet $
+ */
+
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <libutil.h>
+#include <stdint.h>
+
+int
+expand_number(const char *buf, uint64_t *num)
+{
+       char *endptr;
+       uintmax_t umaxval;
+       uint64_t number;
+       unsigned shift;
+       int serrno;
+
+       serrno = errno;
+       errno = 0;
+       umaxval = strtoumax(buf, &endptr, 0);
+       if (umaxval > UINT64_MAX)
+               errno = ERANGE;
+       if (errno != 0)
+               return (-1);
+       errno = serrno;
+       number = umaxval;
+
+       switch (tolower((unsigned char)*endptr)) {
+       case 'e':
+               shift = 60;
+               break;
+       case 'p':
+               shift = 50;
+               break;
+       case 't':
+               shift = 40;
+               break;
+       case 'g':
+               shift = 30;
+               break;
+       case 'm':
+               shift = 20;
+               break;
+       case 'k':
+               shift = 10;
+               break;
+       case 'b':
+       case '\0': /* No unit. */
+               *num = number;
+               return (0);
+       default:
+               /* Unrecognized unit. */
+               errno = EINVAL;
+               return (-1);
+       }
+
+       if ((number << shift) >> shift != number) {
+               /* Overflow */
+               errno = ERANGE;
+               return (-1);
+       }
+       *num = number << shift;
+       return (0);
+}
index 41c5139..c3d97e8 100644 (file)
@@ -23,9 +23,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/lib/libutil/flopen.3,v 1.7 2008/10/20 18:02:16 des Exp $
+.\" $FreeBSD: head/lib/libutil/flopen.3 229784 2012-01-07 16:13:56Z uqs $
 .\"
-.Dd December 27, 2008
+.Dd June 6, 2009
 .Dt FLOPEN 3
 .Os
 .Sh NAME
@@ -46,13 +46,12 @@ The
 function opens or creates a file and acquires an exclusive lock on it.
 It is essentially equivalent with calling
 .Fn open
-with the same parameters followed by an
-.Fn fcntl
-.Dv F_SETLK
-or
-.Dv F_SETLKW
-operation with lock type
-.Dv F_WRLCK ,
+with the same parameters followed by
+.Fn flock
+with an
+.Va operation
+argument of
+.Dv LOCK_EX ,
 except that
 .Fn flopen
 will attempt to detect and handle races that may occur between opening
@@ -70,7 +69,7 @@ and the file is already locked,
 will fail and set
 .Va errno
 to
-.Er EWOULDBLOCK .
+.Dv EWOULDBLOCK .
 .Pp
 As with
 .Fn open ,
@@ -87,18 +86,13 @@ returns a valid file descriptor.
 Otherwise, it returns -1, and sets
 .Va errno
 as described in
-.Xr fcntl 2
+.Xr flock 2
 and
 .Xr open 2 .
 .Sh SEE ALSO
 .Xr errno 2 ,
-.Xr fcntl 2 ,
+.Xr flock 2 ,
 .Xr open 2
-.Sh HISTORY
-The
-.Fn flopen
-function first appeared in
-.Fx 6.3 .
 .Sh AUTHORS
 .An -nosplit
 The
index 0564489..b3ef6dc 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libutil/flopen.c,v 1.11 2008/10/20 18:11:30 des Exp $
+ * $FreeBSD: head/lib/libutil/flopen.c 193591 2009-06-06 18:47:03Z des $
  */
 
 #include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
 #include <stdarg.h>
-#include <string.h>
 #include <unistd.h>
-
+#include <fcntl.h>
 #include <libutil.h>
 
 int
 flopen(const char *path, int flags, ...)
 {
        int fd, operation, serrno, trunc;
-       struct flock lock;
        struct stat sb, fsb;
        mode_t mode;
 
@@ -58,10 +55,9 @@ flopen(const char *path, int flags, ...)
                va_end(ap);
        }
 
-       memset(&lock, 0, sizeof lock);
-       lock.l_type = ((flags & O_ACCMODE) == O_RDONLY) ? F_RDLCK : F_WRLCK;
-       lock.l_whence = SEEK_SET;
-       operation = (flags & O_NONBLOCK) ? F_SETLK : F_SETLKW;
+        operation = LOCK_EX;
+        if (flags & O_NONBLOCK)
+                operation |= LOCK_NB;
 
        trunc = (flags & O_TRUNC);
        flags &= ~O_TRUNC;
@@ -70,35 +66,35 @@ flopen(const char *path, int flags, ...)
                if ((fd = open(path, flags, mode)) == -1)
                        /* non-existent or no access */
                        return (-1);
-               if (fcntl(fd, operation, &lock) == -1) {
+               if (flock(fd, operation) == -1) {
                        /* unsupported or interrupted */
                        serrno = errno;
-                       close(fd);
+                       (void)close(fd);
                        errno = serrno;
                        return (-1);
                }
                if (stat(path, &sb) == -1) {
                        /* disappeared from under our feet */
-                       close(fd);
+                       (void)close(fd);
                        continue;
                }
                if (fstat(fd, &fsb) == -1) {
                        /* can't happen [tm] */
                        serrno = errno;
-                       close(fd);
+                       (void)close(fd);
                        errno = serrno;
                        return (-1);
                }
                if (sb.st_dev != fsb.st_dev ||
                    sb.st_ino != fsb.st_ino) {
                        /* changed under our feet */
-                       close(fd);
+                       (void)close(fd);
                        continue;
                }
                if (trunc && ftruncate(fd, 0) != 0) {
                        /* can't happen [tm] */
                        serrno = errno;
-                       close(fd);
+                       (void)close(fd);
                        errno = serrno;
                        return (-1);
                }
index a0c1b62..a634722 100644 (file)
@@ -1,6 +1,5 @@
 .\"    $NetBSD: fparseln.3,v 1.7 1999/07/02 15:49:12 simonb Exp $
-.\" $FreeBSD: src/lib/libutil/fparseln.3,v 1.5.2.4 2001/12/17 10:08:32 ru Exp $
-.\" $DragonFly: src/lib/libutil/fparseln.3,v 1.3 2006/03/26 22:56:56 swildner Exp $
+.\" $FreeBSD: head/lib/libutil/fparseln.3 140081 2005-01-11 20:50:51Z ru $
 .\"
 .\" Copyright (c) 1997 Christos Zoulas.  All rights reserved.
 .\"
@@ -38,7 +37,6 @@
 .Sh LIBRARY
 .Lb libutil
 .Sh SYNOPSIS
-.In sys/types.h
 .In stdio.h
 .In libutil.h
 .Ft "char *"
@@ -124,6 +122,7 @@ Remove escape preceding any other character.
 .It Dv FPARSELN_UNESCALL
 All of the above.
 .El
+.Pp
 .El
 .Sh RETURN VALUES
 Upon successful completion a pointer to the parsed line is returned;
@@ -154,4 +153,6 @@ if it runs out of memory.
 The
 .Fn fparseln
 function first appeared in
-.Nx 1.4 .
+.Nx 1.4
+and
+.Fx 4.0 .
index 238c08f..183f2ec 100644 (file)
@@ -1,6 +1,4 @@
 /*     $NetBSD: fparseln.c,v 1.9 1999/09/20 04:48:06 lukem Exp $       */
-/* $FreeBSD: src/lib/libutil/fparseln.c,v 1.2 1999/12/29 17:50:33 peter Exp $ */
-/* $DragonFly: src/lib/libutil/fparseln.c,v 1.6 2005/03/16 06:35:48 cpressey Exp $ */
 
 /*
  * Copyright (c) 1997 Christos Zoulas.  All rights reserved.
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libutil/fparseln.c,v 1.2 1999/12/29 17:50:33 peter Exp $
+ * $FreeBSD: head/lib/libutil/fparseln.c 121193 2003-10-18 10:04:16Z markm $
  */
 
 #include <sys/types.h>
-
 #include <assert.h>
 #include <errno.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
+#include <stdlib.h>
+#include <libutil.h>
 
-#include "libutil.h"
-
-static int isescaped (const char *, const char *, int);
+static int isescaped(const char *, const char *, int);
 
 /* isescaped():
  *     Return true if the character in *p that belongs to a string
@@ -55,8 +51,10 @@ isescaped(const char *sp, const char *p, int esc)
        const char     *cp;
        size_t          ne;
 
+#if 0
        _DIAGASSERT(sp != NULL);
        _DIAGASSERT(p != NULL);
+#endif
 
        /* No escape character */
        if (esc == '\0')
@@ -87,7 +85,9 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
        int     cnt;
        char    esc, con, nl, com;
 
+#if 0
        _DIAGASSERT(fp != NULL);
+#endif
 
        len = 0;
        buf = NULL;
@@ -192,7 +192,7 @@ fparseln(FILE *fp, size_t *size, size_t *lineno, const char str[3], int flags)
 #ifdef TEST
 
 int
-main(int argc, char **argv)
+main(int argc, char *argv[])
 {
        char   *ptr;
        size_t  size, line;
index 4d035d6..7b89302 100644 (file)
@@ -22,6 +22,8 @@
  * 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.
+ *
+ * $FreeBSD: head/lib/libutil/gr_util.c 248102 2013-03-09 13:30:06Z db $
  */
 
 #include <sys/param.h>
 #include <string.h>
 #include <unistd.h>
 
-struct group_storage {
-       struct group     gr;
-       char            *members[];
-};
-
 static int lockfd = -1;
 static char group_dir[PATH_MAX];
 static char group_file[PATH_MAX];
 static char tempname[PATH_MAX];
 static int initialized;
-
-static const char group_line_format[] = "%s:%s:%ju:";
+static size_t grmemlen(const struct group *, const char *, int *);
+static struct group *grcopy(const struct group *gr, char *mem, const char *, int ndx);
 
 /*
  * Initialize statics
@@ -103,10 +100,8 @@ gr_lock(void)
        for (;;) {
                struct stat st;
 
-               lockfd = open(group_file, O_RDONLY, 0);
-               if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
-                       err(1, "%s", group_file);
-               if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) {
+               lockfd = flopen(group_file, O_RDONLY|O_NONBLOCK|O_CLOEXEC, 0);
+               if (lockfd == -1) {
                        if (errno == EWOULDBLOCK) {
                                errx(1, "the group file is busy");
                        } else {
@@ -315,11 +310,14 @@ gr_copy(int ffd, int tfd, const struct group *gr, struct group *old_gr)
 int
 gr_mkdb(void)
 {
+       if (chmod(tempname, 0644) != 0)
+               return (-1);
+
        return (rename(tempname, group_file));
 }
 
 /*
- * Clean up. Preserver errno for the caller's convenience.
+ * Clean up. Preserves errno for the caller's convenience.
  */
 void
 gr_fini(void)
@@ -347,7 +345,6 @@ gr_equal(const struct group *gr1, const struct group *gr2)
 {
        int gr1_ndx;
        int gr2_ndx;
-       bool found;
 
        /* Check that the non-member information is the same. */
        if (gr1->gr_name == NULL || gr2->gr_name == NULL) {
@@ -363,28 +360,30 @@ gr_equal(const struct group *gr1, const struct group *gr2)
        if (gr1->gr_gid != gr2->gr_gid)
                return (false);
 
-       /* Check all members in both groups. */
-       if (gr1->gr_mem == NULL || gr2->gr_mem == NULL) {
-               if (gr1->gr_mem != gr2->gr_mem)
+       /* Check all members in both groups.
+        * getgrnam can return gr_mem with a pointer to NULL.
+        * gr_dup and gr_add strip out this superfluous NULL, setting
+        * gr_mem to NULL for no members.
+       */
+       if (gr1->gr_mem != NULL && gr2->gr_mem != NULL) {
+               int i;
+
+               for (i = 0; gr1->gr_mem[i] != NULL; i++) {
+                       if (strcmp(gr1->gr_mem[i], gr2->gr_mem[i]) != 0)
                        return (false);
-       } else {
-               for (found = false, gr1_ndx = 0; gr1->gr_mem[gr1_ndx] != NULL;
-                   gr1_ndx++) {
-                       for (gr2_ndx = 0; gr2->gr_mem[gr2_ndx] != NULL;
-                           gr2_ndx++)
-                               if (strcmp(gr1->gr_mem[gr1_ndx],
-                                   gr2->gr_mem[gr2_ndx]) == 0) {
-                                       found = true;
-                                       break;
                                }
-                       if (!found)
-                               return (false);
                }
-
-               /* Check that group2 does not have more members than group1. */
-               if (gr2->gr_mem[gr1_ndx] != NULL)
+       /* Count number of members in both structs */
+       gr2_ndx = 0;
+       if (gr2->gr_mem != NULL)
+               for(; gr2->gr_mem[gr2_ndx] != NULL; gr2_ndx++)
+                       /* empty */;
+       gr1_ndx = 0;
+       if (gr1->gr_mem != NULL)
+               for(; gr1->gr_mem[gr1_ndx] != NULL; gr1_ndx++)
+                       /* empty */;
+       if (gr1_ndx != gr2_ndx)
                        return (false);
-       }
 
        return (true);
 }
@@ -395,7 +394,10 @@ gr_equal(const struct group *gr1, const struct group *gr2)
 char *
 gr_make(const struct group *gr)
 {
+       const char *group_line_format = "%s:%s:%ju:";
+       const char *sep;
        char *line;
+       char *p;
        size_t line_size;
        int ndx;
 
@@ -410,15 +412,17 @@ gr_make(const struct group *gr)
        }
 
        /* Create the group line and fill it. */
-       if ((line = malloc(line_size)) == NULL)
+       if ((line = p = malloc(line_size)) == NULL)
                return (NULL);
-       snprintf(line, line_size, group_line_format, gr->gr_name, gr->gr_passwd,
+       p += sprintf(p, group_line_format, gr->gr_name, gr->gr_passwd,
            (uintmax_t)gr->gr_gid);
-       if (gr->gr_mem != NULL)
+       if (gr->gr_mem != NULL) {
+               sep = "";
                for (ndx = 0; gr->gr_mem[ndx] != NULL; ndx++) {
-                       strcat(line, gr->gr_mem[ndx]);
-                       if (gr->gr_mem[ndx + 1] != NULL)
-                               strcat(line, ",");
+                       p = stpcpy(p, sep);
+                       p = stpcpy(p, gr->gr_mem[ndx]);
+                       sep = ",";
+               }
                }
 
        return (line);
@@ -430,48 +434,129 @@ gr_make(const struct group *gr)
 struct group *
 gr_dup(const struct group *gr)
 {
-       char *dst;
+       return (gr_add(gr, NULL));
+}
+/*
+ * Add a new member name to a struct group.
+ */
+struct group *
+gr_add(const struct group *gr, const char *newmember)
+{
+       char *mem;
        size_t len;
-       struct group_storage *gs;
-       int ndx;
        int num_mem;
 
+       num_mem = 0;
+       len = grmemlen(gr, newmember, &num_mem);
+       /* Create new group and copy old group into it. */
+       if ((mem = malloc(len)) == NULL)
+               return (NULL);
+       return (grcopy(gr, mem, newmember, num_mem));
+}
+
+/* It is safer to walk the pointers given at gr_mem since there is no
+ * guarantee the gr_mem + strings are contiguous in the given struct group
+ * but compactify the new group into the following form.
+ *
+ * The new struct is laid out like this in memory. The example given is
+ * for a group with two members only.
+ *
+ * {
+ * (char *name)
+ * (char *passwd)
+ * (int gid)
+ * (gr_mem * newgrp + sizeof(struct group) + sizeof(**)) points to gr_mem area
+ * gr_mem area
+ * (member1 *)
+ * (member2 *)
+ * (NULL)
+ * (name string)
+ * (passwd string)
+ * (member1 string)
+ * (member2 string)
+ * }
+ */
+/*
+ * Copy the contents of a group plus given name to a preallocated group struct
+ */
+static struct group *
+grcopy(const struct group *gr, char *dst, const char *name, int ndx)
+{
+       int i;
+       struct group *newgr;
+
+       newgr = (struct group *)(void *)dst;    /* avoid alignment warning */
+       dst += sizeof(*newgr);
+       if (ndx != 0) {
+               newgr->gr_mem = (char **)(void *)(dst); /* avoid alignment warning */
+               dst += (ndx + 1) * sizeof(*newgr->gr_mem);
+       } else
+               newgr->gr_mem = NULL;
+       if (gr->gr_name != NULL) {
+               newgr->gr_name = dst;
+               dst = stpcpy(dst, gr->gr_name) + 1;
+       } else
+               newgr->gr_name = NULL;
+       if (gr->gr_passwd != NULL) {
+               newgr->gr_passwd = dst;
+               dst = stpcpy(dst, gr->gr_passwd) + 1;
+       } else
+               newgr->gr_passwd = NULL;
+       newgr->gr_gid = gr->gr_gid;
+       i = 0;
+       /* Original group struct might have a NULL gr_mem */
+       if (gr->gr_mem != NULL) {
+               for (; gr->gr_mem[i] != NULL; i++) {
+                       newgr->gr_mem[i] = dst;
+                       dst = stpcpy(dst, gr->gr_mem[i]) + 1;
+               }
+       }
+       /* If name is not NULL, newgr->gr_mem is known to be not NULL */
+       if (name != NULL) {
+               newgr->gr_mem[i++] = dst;
+               dst = stpcpy(dst, name) + 1;
+       }
+       /* if newgr->gr_mem is not NULL add NULL marker */
+       if (newgr->gr_mem != NULL)
+               newgr->gr_mem[i] = NULL;
+
+       return (newgr);
+}
+
+/*
+ *  Calculate length of a struct group + given name
+ */
+static size_t
+grmemlen(const struct group *gr, const char *name, int *num_mem)
+{
+       size_t len;
+       int i;
+
+       if (gr == NULL)
+               return (0);
        /* Calculate size of the group. */
-       len = sizeof(*gs);
+       len = sizeof(*gr);
        if (gr->gr_name != NULL)
                len += strlen(gr->gr_name) + 1;
        if (gr->gr_passwd != NULL)
                len += strlen(gr->gr_passwd) + 1;
+       i = 0;
        if (gr->gr_mem != NULL) {
-               for (num_mem = 0; gr->gr_mem[num_mem] != NULL; num_mem++)
-                       len += strlen(gr->gr_mem[num_mem]) + 1;
-               len += (num_mem + 1) * sizeof(*gr->gr_mem);
-       } else
-               num_mem = -1;
-
-       /* Create new group and copy old group into it. */
-       if ((gs = calloc(1, len)) == NULL)
-               return (NULL);
-       dst = (char *)&gs->members[num_mem + 1];
-       if (gr->gr_name != NULL) {
-               gs->gr.gr_name = dst;
-               dst = stpcpy(gs->gr.gr_name, gr->gr_name) + 1;
+               for (; gr->gr_mem[i] != NULL; i++) {
+                       len += strlen(gr->gr_mem[i]) + 1;
+                       len += sizeof(*gr->gr_mem);
        }
-       if (gr->gr_passwd != NULL) {
-               gs->gr.gr_passwd = dst;
-               dst = stpcpy(gs->gr.gr_passwd, gr->gr_passwd) + 1;
        }
-       gs->gr.gr_gid = gr->gr_gid;
-       if (gr->gr_mem != NULL) {
-               gs->gr.gr_mem = gs->members;
-               for (ndx = 0; ndx < num_mem; ndx++) {
-                       gs->gr.gr_mem[ndx] = dst;
-                       dst = stpcpy(gs->gr.gr_mem[ndx], gr->gr_mem[ndx]) + 1;
+       if (name != NULL) {
+               i++;
+               len += strlen(name) + 1;
+               len += sizeof(*gr->gr_mem);
                }
-               gs->gr.gr_mem[ndx] = NULL;
-       }
-
-       return (&gs->gr);
+       /* Allow for NULL pointer */
+       if (i != 0)
+               len += sizeof(*gr->gr_mem);
+       *num_mem = i;
+       return(len);
 }
 
 /*
index 8eb3508..9f74d72 100644 (file)
@@ -26,7 +26,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: head/lib/libutil/hexdump.3 206622 2010-04-14 19:08:06Z uqs $
 .\"
 .Dd November 3, 2012
 .Dt HEXDUMP 3
index f81930d..50f2b9e 100644 (file)
@@ -32,6 +32,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)subr_prf.c  8.3 (Berkeley) 1/21/94
+ * $FreeBSD: head/lib/libutil/hexdump.c 180161 2008-07-01 22:30:57Z jhb $
  */
 
 #include <sys/types.h>
index 04abe0a..999d586 100644 (file)
@@ -1,6 +1,5 @@
-.\"    $NetBSD: humanize_number.3,v 1.5 2005/04/11 12:19:16 wiz Exp $
-.\" $FreeBSD: src/lib/libutil/humanize_number.3,v 1.12 2007/09/28 15:31:44 obrien Exp $
-.\" $DragonFly: src/lib/libutil/humanize_number.3,v 1.4 2008/09/14 20:04:59 swildner Exp $
+.\"    $NetBSD: humanize_number.3,v 1.4 2003/04/16 13:34:37 wiz Exp $
+.\" $FreeBSD: head/lib/libutil/humanize_number.3 256130 2013-10-07 22:22:57Z jmg $
 .\"
 .\" Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
 .\" All rights reserved.
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd September 14, 2008
+.Dd October 7, 2013
 .Dt HUMANIZE_NUMBER 3
 .Os
 .Sh NAME
-.Nm dehumanize_number ,
 .Nm humanize_number
-.Nd format a number into a human readable form and vice versa
+.Nd format a number into a human readable form
 .Sh LIBRARY
 .Lb libutil
 .Sh SYNOPSIS
-.In sys/types.h
 .In libutil.h
 .Ft int
-.Fn dehumanize_number "const char *str" "int64_t *result"
-.Ft int
 .Fo humanize_number
 .Fa "char *buf" "size_t len" "int64_t number" "const char *suffix"
 .Fa "int scale" "int flags"
 .Sh DESCRIPTION
 The
 .Fn humanize_number
-function formats the signed 64 bit quantity given in
+function formats the signed 64-bit quantity given in
 .Fa number
 into
-.Fa buffer .
+.Fa buf .
 A space and then
 .Fa suffix
 is appended to the end.
 The buffer pointed to by
-.Fa buffer
+.Fa buf
 must be at least
 .Fa len
 bytes long.
@@ -67,23 +62,30 @@ bytes long.
 If the formatted number (including
 .Fa suffix )
 would be too long to fit into
-.Fa buffer ,
+.Fa buf ,
 then divide
 .Fa number
 by 1024 until it will.
 In this case, prefix
 .Fa suffix
-with the appropriate SI designator.
+with the appropriate designator.
 The
 .Fn humanize_number
-function
-follows the traditional computer science conventions rather than the proposed
-SI power of two convention.
+function follows the traditional computer science conventions by
+default, rather than the IEE/IEC (and now also SI) power of two
+convention or the power of ten notion.
+This behaviour however can be altered by specifying the
+.Dv HN_DIVISOR_1000
+and
+.Dv HN_IEC_PREFIXES
+flags.
 .Pp
-The prefixes are:
+The traditional
+.Pq default
+prefixes are:
 .Bl -column "Prefix" "Description" "1000000000000000000" -offset indent
 .It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier" Ta Sy "Multiplier 1000x"
-.It Li k Ta No kilo Ta 1024 Ta 1000
+.It Li (note) Ta No kilo Ta 1024 Ta 1000
 .It Li M Ta No mega Ta 1048576 Ta 1000000
 .It Li G Ta No giga Ta 1073741824 Ta 1000000000
 .It Li T Ta No tera Ta 1099511627776 Ta 1000000000000
@@ -91,15 +93,34 @@ The prefixes are:
 .It Li E Ta No exa Ta 1152921504606846976 Ta 1000000000000000000
 .El
 .Pp
+Note:
+An uppercase K indicates a power of two, a lowercase k a power of ten.
+.Pp
+The IEE/IEC (and now also SI) power of two prefixes are:
+.Bl -column "Prefix" "Description" "1000000000000000000" -offset indent
+.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier"
+.It Li Ki Ta No kibi Ta 1024
+.It Li Mi Ta No mebi Ta 1048576
+.It Li Gi Ta No gibi Ta 1073741824
+.It Li Ti Ta No tebi Ta 1099511627776
+.It Li Pi Ta No pebi Ta 1125899906842624
+.It Li Ei Ta No exbi Ta 1152921504606846976
+.El
+.Pp
 The
 .Fa len
 argument must be at least 4 plus the length of
 .Fa suffix ,
 in order to ensure a useful result is generated into
-.Fa buffer .
+.Fa buf .
 To use a specific prefix, specify this as
 .Fa scale
-(multiplier = 1024 ^ scale).
+.Po multiplier = 1024 ^ scale;
+when
+.Dv HN_DIVISOR_1000
+is specified,
+multiplier = 1000 ^ scale
+.Pc .
 This cannot be combined with any of the
 .Fa scale
 flags below.
@@ -119,7 +140,7 @@ The following flags may be passed in
 .Fa flags :
 .Bl -tag -width ".Dv HN_DIVISOR_1000" -offset indent
 .It Dv HN_DECIMAL
-If the final result is less than 10, display it using one digit.
+If the final result is less than 10, display it using one decimal place.
 .It Dv HN_NOSPACE
 Do not put a space between
 .Fa number
@@ -132,50 +153,42 @@ Use
 Divide
 .Fa number
 with 1000 instead of 1024.
+.It Dv HN_IEC_PREFIXES
+Use the IEE/IEC notion of prefixes (Ki, Mi, Gi...).
+This flag has no effect when
+.Dv HN_DIVISOR_1000
+is also specified.
 .El
-.Pp
-The
-.Fn dehumanize_number
-function parses the string representing an integral value given in
-.Fa str
-and stores the numerical value in the integer pointed to by
-.Fa result .
-The provided string may hold one of the suffixes, which will be interpreted
-and used to scale up its accompanying numerical value.
 .Sh RETURN VALUES
-The
-.Fn humanize_number
-function returns the number of characters stored in
-.Fa buffer
+Upon success, the
+.Nm
+function returns the number of characters that would have been stored in
+.Fa buf
 (excluding the terminating
 .Dv NUL )
-upon success, or \-1 upon failure.
+if
+.Fa buf
+was large enough, or \-1 upon failure.
+Even upon failure, the contents of
+.Fa buf
+may be modified.
 If
 .Dv HN_GETSCALE
 is specified, the prefix index number will be returned instead.
-.Pp
-The
-.Fn dehumanize_number
-function returns 0 if the string was parsed correctly.
-A \-1 is returned to indicate failure and an error code is stored in
-.Va errno .
-.Sh ERRORS
+.Sh SEE ALSO
+.Xr expand_number 3
+.Sh STANDARDS
 The
-.Fn dehumanize_number
-function will fail and no number will be stored in
-.Fa result
-if:
-.Bl -tag -width Er
-.It Bq Er EINVAL
-The string in
-.Fa str
-was empty or carried an unknown suffix.
-.It Bq Er ERANGE
-The string in
-.Fa str
-represented a number that does not fit in
-.Fa result .
-.El
+.Dv HN_DIVISOR_1000
+and
+.Dv HN_IEC_PREFIXES
+flags
+conform to
+.Tn ISO/IEC
+Std\~80000-13:2008
+and
+.Tn IEEE
+Std\~1541-2002.
 .Sh HISTORY
 The
 .Fn humanize_number
@@ -183,8 +196,7 @@ function first appeared in
 .Nx 2.0
 and then in
 .Fx 5.3 .
-.Pp
 The
-.Fn dehumanize_number
-function first appeared in
-.Nx 5.0 .
+.Dv HN_IEC_PREFIXES
+flag was introduced in
+.Fx 9.0 .
index 8ea1041..a2f0830 100644 (file)
@@ -1,8 +1,8 @@
 /*     $NetBSD: humanize_number.c,v 1.14 2008/04/28 20:22:59 martin Exp $      */
-/* $DragonFly: src/lib/libutil/humanize_number.c,v 1.3 2008/08/04 19:09:26 swildner Exp $ */
 
 /*
  * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
+ * Copyright 2013 John-Mark Gurney <jmg@FreeBSD.org>
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -30,7 +30,7 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libutil/humanize_number.c,v 1.3 2008/03/08 21:55:59 antoine Exp $
+ * $FreeBSD: head/lib/libutil/humanize_number.c 256130 2013-10-07 22:22:57Z jmg $
  */
 
 #include <sys/types.h>
 #include <stdlib.h>
 #include <string.h>
 #include <locale.h>
+#include <libutil.h>
 
-#include "libutil.h"
+static const int maxscale = 7;
 
 int
-humanize_number(char *buf, size_t len, int64_t bytes,
+humanize_number(char *buf, size_t len, int64_t quotient,
     const char *suffix, int scale, int flags)
 {
        const char *prefixes, *sep;
-       int     b, i, r, maxscale, s1, s2, sign;
+       int     i, r, remainder, s1, s2, sign;
+       int     divisordeccut;
        int64_t divisor, max;
        size_t  baselen;
 
-       assert(buf != NULL);
-       assert(suffix != NULL);
-       assert(scale >= 0);
+       /* Since so many callers don't check -1, NUL terminate the buffer */
+       if (len > 0)
+               buf[0] = '\0';
+
+       /* validate args */
+       if (buf == NULL || suffix == NULL)
+               return (-1);
+       if (scale < 0)
+               return (-1);
+       else if (scale >= maxscale &&
+           ((scale & ~(HN_AUTOSCALE|HN_GETSCALE)) != 0))
+               return (-1);
+       if ((flags & HN_DIVISOR_1000) && (flags & HN_IEC_PREFIXES))
+               return (-1);
+
+       /* setup parameters */
+       remainder = 0;
 
+       if (flags & HN_IEC_PREFIXES) {
+               baselen = 2;
+               /*
+                * Use the prefixes for power of two recommended by
+                * the International Electrotechnical Commission
+                * (IEC) in IEC 80000-3 (i.e. Ki, Mi, Gi...).
+                *
+                * HN_IEC_PREFIXES implies a divisor of 1024 here
+                * (use of HN_DIVISOR_1000 would have triggered
+                * an assertion earlier).
+                */
+               divisor = 1024;
+               divisordeccut = 973;    /* ceil(.95 * 1024) */
+               if (flags & HN_B)
+                       prefixes = "B\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+               else
+                       prefixes = "\0\0\0Ki\0Mi\0Gi\0Ti\0Pi\0Ei";
+       } else {
+               baselen = 1;
        if (flags & HN_DIVISOR_1000) {
-               /* SI for decimal multiplies */
                divisor = 1000;
+                       divisordeccut = 950;
                if (flags & HN_B)
-                       prefixes = "B\0k\0M\0G\0T\0P\0E";
+                               prefixes = "B\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
                else
-                       prefixes = "\0\0k\0M\0G\0T\0P\0E";
+                               prefixes = "\0\0\0k\0\0M\0\0G\0\0T\0\0P\0\0E";
        } else {
-               /*
-                * binary multiplies
-                * XXX IEC 60027-2 recommends Ki, Mi, Gi...
-                */
                divisor = 1024;
+                       divisordeccut = 973;    /* ceil(.95 * 1024) */
                if (flags & HN_B)
-                       prefixes = "B\0K\0M\0G\0T\0P\0E";
+                               prefixes = "B\0\0K\0\0M\0\0G\0\0T\0\0P\0\0E";
                else
-                       prefixes = "\0\0K\0M\0G\0T\0P\0E";
+                               prefixes = "\0\0\0K\0\0M\0\0G\0\0T\0\0P\0\0E";
+               }
        }
 
-#define        SCALE2PREFIX(scale)     (&prefixes[(scale) << 1])
-       maxscale = 7;
+#define        SCALE2PREFIX(scale)     (&prefixes[(scale) * 3])
 
-       if (scale >= maxscale &&
-           (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
-               return (-1);
-
-       if (buf == NULL || suffix == NULL)
-               return (-1);
-
-       if (len > 0)
-               buf[0] = '\0';
-       if (bytes < 0) {
+       if (quotient < 0) {
                sign = -1;
-               bytes *= -100;
-               baselen = 3;            /* sign, digit, prefix */
+               quotient = -quotient;
+               baselen += 2;           /* sign, digit */
        } else {
                sign = 1;
-               bytes *= 100;
-               baselen = 2;            /* digit, prefix */
+               baselen += 1;           /* digit */
        }
        if (flags & HN_NOSPACE)
                sep = "";
@@ -110,7 +132,7 @@ humanize_number(char *buf, size_t len, int64_t bytes,
 
        if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
                /* See if there is additional columns can be used. */
-               for (max = 100, i = len - baselen; i-- > 0;)
+               for (max = 1, i = len - baselen; i-- > 0;)
                        max *= 10;
 
                /*
@@ -118,29 +140,38 @@ humanize_number(char *buf, size_t len, int64_t bytes,
                 * If there will be an overflow by the rounding below,
                 * divide once more.
                 */
-               for (i = 0; bytes >= max - 50 && i < maxscale; i++)
-                       bytes /= divisor;
+               for (i = 0;
+                   (quotient >= max || (quotient == max - 1 &&
+                   remainder >= divisordeccut)) && i < maxscale; i++) {
+                       remainder = quotient % divisor;
+                       quotient /= divisor;
+               }
 
                if (scale & HN_GETSCALE)
                        return (i);
-       } else
-               for (i = 0; i < scale && i < maxscale; i++)
-                       bytes /= divisor;
+       } else {
+               for (i = 0; i < scale && i < maxscale; i++) {
+                       remainder = quotient % divisor;
+                       quotient /= divisor;
+               }
+       }
 
        /* If a value <= 9.9 after rounding and ... */
-       if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
-               /* baselen + \0 + .N */
-               if (len < baselen + 1 + 2)
-                       return (-1);
-               b = ((int)bytes + 5) / 10;
-               s1 = b / 10;
-               s2 = b % 10;
+       /*
+        * XXX - should we make sure there is enough space for the decimal
+        * place and if not, don't do HN_DECIMAL?
+        */
+       if (((quotient == 9 && remainder < divisordeccut) || quotient < 9) &&
+           i > 0 && flags & HN_DECIMAL) {
+               s1 = (int)quotient + ((remainder * 10 + divisor / 2) /
+                   divisor / 10);
+               s2 = ((remainder * 10 + divisor / 2) / divisor) % 10;
                r = snprintf(buf, len, "%d%s%d%s%s%s",
                    sign * s1, localeconv()->decimal_point, s2,
                    sep, SCALE2PREFIX(i), suffix);
        } else
                r = snprintf(buf, len, "%" PRId64 "%s%s%s",
-                   sign * ((bytes + 50) / 100),
+                   sign * (quotient + (remainder + divisor / 2) / divisor),
                    sep, SCALE2PREFIX(i), suffix);
 
        return (r);
index cc788fc..17e75a1 100644 (file)
@@ -31,8 +31,7 @@
 
 #include <stdio.h>
 #include <string.h>
-
-#include "libutil.h"
+#include <libutil.h>
 
 /*
  * snprintf() `bytes' into `buf', reformatting it so that the number,
index ad74a26..bbf1904 100644 (file)
@@ -33,7 +33,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: head/lib/libutil/libutil.h 247919 2013-03-07 19:00:00Z db $
  */
 
 #ifndef _LIBUTIL_H_
@@ -58,6 +58,7 @@ typedef struct _property {
 
 /* Avoid pulling in all the include files for no need. */
 struct in_addr;
+struct pidfh;
 struct sockaddr;
 struct termios;
 struct winsize;
@@ -65,7 +66,7 @@ struct utmp;
 struct utmpx;
 
 __BEGIN_DECLS
-int    flopen(const char *, int, ...);
+char   *auth_getval(const char *_name);
 void   login(struct utmp *);
 void   loginx(const struct utmpx *);
 int    login_tty(int);
@@ -74,11 +75,14 @@ int logoutx(const char *, int, int);
 void   logwtmp(const char *, const char *, const char *);
 void   logwtmpx(const char *, const char *, const char *, int, int);
 void   trimdomain(char *, int);
-int    openpty(int *, int *, char *, struct termios *, struct winsize *);
-int    forkpty(int *, char *, struct termios *, struct winsize *);
+int    expand_number(const char *_buf, uint64_t *_num);
+int    flopen(const char *_path, int _flags, ...);
+int    forkpty(int *_amaster, char *_name,
+           struct termios *_termp, struct winsize *_winp);
 int    dehumanize_number(const char *, int64_t *);
 void   hexdump(const void *_ptr, int _length, const char *_hdr, int _flags);
-int    humanize_number(char *, size_t, int64_t, const char *, int, int);
+int    humanize_number(char *_buf, size_t _len, int64_t _number,
+           const char *_suffix, int _scale, int _flags);
 int    humanize_unsigned(char *buf, size_t len, uint64_t bytes,
                                        const char *suffix, int divisor);
 int    format_bytes(char *buf, size_t len, uint64_t bytes);
@@ -87,11 +91,18 @@ int uu_lock(const char *);
 int    uu_unlock(const char *);
 int    uu_lock_txfr(const char *, pid_t);
 int    _secure_path(const char *, uid_t, gid_t);
-int    pidfile(const char *);
-properties properties_read(int fd);
-void   properties_free(properties);
-char   *property_find(properties, const char *);
-char   *auth_getval(const char *);
+int    openpty(int *_amaster, int *_aslave, char *_name,
+           struct termios *_termp, struct winsize *_winp);
+int    pidfile_close(struct pidfh *_pfh);
+int    pidfile_fileno(const struct pidfh *_pfh);
+struct pidfh *
+       pidfile_open(const char *_path, mode_t _mode, pid_t *_pidptr);
+int    pidfile_remove(struct pidfh *_pfh);
+int    pidfile_write(struct pidfh *_pfh);
+void   properties_free(properties _list);
+char   *property_find(properties _list, const char *_name);
+properties
+       properties_read(int fd);
 int    realhostname(char *, size_t, const struct in_addr *);
 int    realhostname_sa(char *, size_t, struct sockaddr *, int);
 #ifdef _STDIO_H_       /* avoid adding new includes */
@@ -108,6 +119,7 @@ int pw_equal(const struct passwd *_pw1, const struct passwd *_pw2);
 void   pw_fini(void);
 int    pw_init(const char *_dir, const char *_master);
 char   *pw_make(const struct passwd *_pw);
+char   *pw_make_v7(const struct passwd *_pw);
 int    pw_mkdb(const char *_user);
 int    pw_lock(void);
 struct passwd *
@@ -122,6 +134,8 @@ int         gr_copy(int __ffd, int _tfd, const struct group *_gr,
            struct group *_old_gr);
 struct group *
        gr_dup(const struct group *_gr);
+struct group *
+       gr_add(const struct group *_gr, const char *_newmember);
 int    gr_equal(const struct group *_gr1, const struct group *_gr2);
 void   gr_fini(void);
 int    gr_init(const char *_dir, const char *_master);
index 3c743a6..3b65e63 100644 (file)
@@ -28,7 +28,6 @@
  *
  * @(#)login.c 8.1 (Berkeley) 6/4/93
  * $FreeBSD: src/lib/libutil/login.c,v 1.6 1999/08/28 00:05:45 peter Exp $
- * $DragonFly: src/lib/libutil/login.c,v 1.6 2007/12/30 13:44:33 matthias Exp $
  */
 
 #include <sys/types.h>
@@ -37,8 +36,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <utmp.h>
-
-#include "libutil.h"
+#include <libutil.h>
 
 void
 login(struct utmp *ut)
index 1babffd..a303d00 100644 (file)
@@ -17,7 +17,7 @@
 .\" 5. Modifications may be freely made to this file providing the above
 .\"    conditions are met.
 .\"
-.\" $FreeBSD: src/lib/libutil/login.conf.5,v 1.22.2.18 2003/05/10 23:30:54 murray Exp $
+.\" $FreeBSD: head/lib/libutil/login.conf.5 257205 2013-10-27 04:59:18Z eadler $
 .\"
 .Dd January 21, 2012
 .Dt LOGIN.CONF 5
@@ -39,6 +39,8 @@ It is used by various programs in the system to set up a user's login
 environment and to enforce policy, accounting and administrative restrictions.
 It also provides the means by which users are able to be
 authenticated to the system and the types of authentication available.
+Attributes in addition to the ones described here are available with
+third-party packages.
 .Pp
 A special record "default" in the system user class capability database
 .Pa /etc/login.conf
@@ -48,9 +50,7 @@ non-root user without a valid login class in
 A user with a uid of 0 without a valid login class will use the record
 "root" if it exists, or "default" if not.
 .Pp
-In
-.Dx ,
-users may individually create a file called
+Users may individually create a file called
 .Pa .login_conf
 in their home directory using the same format, consisting of a single
 entry with a record id of "me".
@@ -72,6 +72,28 @@ All names but the last should be in lower case and contain no blanks;
 the last name may contain upper case characters and blanks for
 readability.
 .Pp
+Note that since a colon
+.Pq Ql :\&
+is used to separate capability entries, a
+.Ql \ec
+escape sequence must be used to embed a literal colon in the
+value or name of a capability.
+.Pp
+The default
+.Pa /etc/login.conf
+shipped with
+.Fx
+is an out of the box configuration.
+Whenever changes to this, or
+the user's
+.Pa ~/.login_conf ,
+file are made, the modifications will not be picked up until
+.Xr cap_mkdb 1
+is used to compile the file into a database.
+This database file will have a
+.Pa .db
+extension and is accessed through
+.Xr cgetent 3 .
 See
 .Xr getcap 3
 for a more in-depth description of the format of a capability database.
@@ -103,11 +125,12 @@ home directories etc.)
 A numeric value, either decimal (default), hexadecimal (with leading 0x),
 or octal (with a leading 0).
 With a numeric type, only one numeric value is allowed.
-Numeric types may also be specified in string format (ie. the capability
+Numeric types may also be specified in string format (i.e., the capability
 tag being delimited from the value by '=' instead of '#').
 Whichever method is used, then all records in the database must use the
 same method to allow values to be correctly overridden in interpolated
 records.
+A numeric value may be infinite.
 .It size
 A number which expresses a size.
 The default interpretation of a value is the number of bytes, but a
@@ -126,6 +149,7 @@ represents terabytes.
 .El
 A size value is a numeric quantity and case of the suffix is not significant.
 Concatenated values are added together.
+A size value may be infinite.
 .It time
 A period of time, by default in seconds.
 A prefix may specify a different unit:
@@ -146,26 +170,34 @@ the number of seconds.
 Concatenated values are added together.
 For example, 2 hours and 40 minutes may be written either as
 9600s, 160m or 2h40m.
+A time value may be infinite.
 .El
 .Pp
+.Dq infinity ,
+.Dq inf ,
+.Dq unlimited ,
+.Dq unlimit,
+and -1
+are considered infinite values.
+.Pp
 The usual convention to interpolate capability entries using the special
 .Em tc=value
 notation may be used.
 .Sh RESOURCE LIMITS
 .Bl -column coredumpsize indent indent
-.It Sy Name Ta Sy Type Ta Sy Notes Ta Sy Description
-.It coredumpsize       size            Maximum coredump size limit.
-.It cputime    time            CPU usage limit.
-.It datasize   size            Maximum data size limit.
-.It filesize   size            Maximum file size limit.
-.It maxproc    number          Maximum number of processes.
-.It memorylocked       size            Maximum locked in core memory size limit.
-.It memoryuse  size            Maximum of core memory use size limit.
-.It openfiles  number          Maximum number of open files per process.
-.It sbsize     size            Maximum permitted socketbuffer size.
-.It vmemoryuse size            Maximum permitted total VM usage per process.
-.It stacksize  size            Maximum stack size limit.
-.It posixlocks size            Maximum number of POSIX-type advisory-mode locks.
+.It Sy "Name   Type    Notes   Description"
+.It "coredumpsize      size            Maximum coredump size limit."
+.It "cputime   time            CPU usage limit."
+.It "datasize  size            Maximum data size limit."
+.It "filesize  size            Maximum file size limit."
+.It "maxproc   number          Maximum number of processes."
+.It "memorylocked      size            Maximum locked in core memory size limit."
+.It "memoryuse size            Maximum of core memory use size limit."
+.It "openfiles number          Maximum number of open files per process."
+.It "sbsize    size            Maximum permitted socketbuffer size."
+.It "vmemoryuse        size            Maximum permitted total VM usage per process."
+.It "stacksize size            Maximum stack size limit."
+.It "posixlocks        size            Maximum number of POSIX-type advisory-mode locks."
 .El
 .Pp
 These resource limit entries actually specify both the maximum
@@ -177,41 +209,42 @@ The maximum and current limits may be specified individually by appending a
 -max or -cur to the capability name.
 .Sh ENVIRONMENT
 .Bl -column ignorenologin indent xbinxxusrxbin
-.It Sy Name Ta Sy Type Ta Sy Notes Ta Sy Description
-.It charset    string          Set $MM_CHARSET environment variable to the specified
+.It Sy "Name   Type    Notes   Description"
+.It "charset   string          Set $MM_CHARSET environment variable to the specified"
 value.
-.It hushlogin  bool    false   Same as having a ~/.hushlogin file.
-.It ignorenologin      bool    false   Login not prevented by nologin.
-.It lang       string          Set $LANG environment variable to the specified value.
-.It manpath    path            Default search path for manpages.
-.It nologin    file            If the file exists it will be displayed and
+.It "hushlogin bool    false   Same as having a ~/.hushlogin file."
+.It "ignorenologin     bool    false   Login not prevented by nologin."
+.It "lang      string          Set $LANG environment variable to the specified value."
+.It "manpath   path            Default search path for manpages."
+.It "nocheckmail       bool    false   Display mail status at login."
+.It "nologin   file            If the file exists it will be displayed and"
 the login session will be terminated.
-.It path       path    /bin /usr/bin   Default search path.
-.It priority   number          Initial priority (nice) level.
-.It requirehome        bool    false   Require a valid home directory to login.
-.It setenv     list            A comma-separated list of environment variables and
+.It "path      path    /bin /usr/bin   Default search path."
+.It "priority  number          Initial priority (nice) level."
+.It "requirehome       bool    false   Require a valid home directory to login."
+.It "setenv    list            A comma-separated list of environment variables and"
 values to which they are to be set.
-.It shell      prog            Session shell to execute rather than the
+.It "shell     prog            Session shell to execute rather than the"
 shell specified in the passwd file.
 The SHELL environment variable will
 contain the shell specified in the password file.
-.It term       string          Default terminal type if not able to determine
+.It "term      string          Default terminal type if not able to determine"
 from other means.
-.It timezone   string          Default value of $TZ environment variable.
-.It umask      number  022     Initial umask. Should always have a leading 0 to
+.It "timezone  string          Default value of $TZ environment variable."
+.It "umask     number  022     Initial umask. Should always have a leading 0 to"
 ensure octal interpretation.
-.It welcome    file    /etc/motd       File containing welcome message.
+.It "welcome   file    /etc/motd       File containing welcome message."
 .El
 .Sh AUTHENTICATION
 .Bl -column minpasswordlen indent indent
-.It Sy Name Ta Sy Type Ta Sy Notes Ta Sy Description
-.\" .It approve        program         Program to approve login.
-.It copyright  file            File containing additional copyright information
-.It host.allow list            List of remote host wildcards from which users in
+.It Sy "Name   Type    Notes   Description"
+.\" .It "approve       program         Program to approve login.
+.It "copyright file            File containing additional copyright information"
+.It "host.allow        list            List of remote host wildcards from which users in"
 the class may access.
-.It host.deny  list            List of remote host wildcards from which users
+.It "host.deny list            List of remote host wildcards from which users"
 in the class may not access.
-.It login_prompt       string          The login prompt given by
+.It "login_prompt      string          The login prompt given by"
 .Xr login 1
 .It minpasswordlen     number  6       The minimum length a local password
 may be.
@@ -221,27 +254,27 @@ will warn the user if an all lower case password is entered.
 .It login-backoff      number  3       The number of login attempts
 allowed before the backoff delay is inserted after each subsequent
 attempt.
-.It login-retries      number  10      The number of login attempts
+.It "login-retries     number  10      The number of login attempts"
 allowed before the login fails.
-.It passwd_format      string  sha512  The encryption format that new or
+.It "passwd_format     string  sha512  The encryption format that new or"
 changed passwords will use.
-Valid values include "des", "md5", "blf", "sha256" and "sha512".
-See
-.Xr crypt 3 .
+Valid values include "des", "md5", "blf", "sha256" and "sha512"; see
+.Xr crypt 3
+for details.
 NIS clients using a
 .No non- Ns Dx Ns / Ns Fx
 NIS server should probably use "des".
-.It passwd_prompt      string          The password prompt presented by
+.It "passwd_prompt     string          The password prompt presented by"
 .Xr login 1
-.It times.allow        list            List of time periods during which
+.It "times.allow       list            List of time periods during which"
 logins are allowed.
-.It times.deny list            List of time periods during which logins are
+.It "times.deny        list            List of time periods during which logins are"
 disallowed.
-.It ttys.allow list            List of ttys and ttygroups which users
+.It "ttys.allow        list            List of ttys and ttygroups which users"
 in the class may use for access.
-.It ttys.deny  list            List of ttys and ttygroups which users
+.It "ttys.deny list            List of ttys and ttygroups which users"
 in the class may not use for access.
-.\".It widepasswords   bool    false   Use the wide password format. The wide password
+.\".It "widepasswords  bool    false   Use the wide password format. The wide password
 .\" format allows up to 128 significant characters in the password.
 .El
 .Pp
@@ -331,33 +364,33 @@ If both lists are given and are non-empty, the user is restricted to those
 devices allowed by ttys.allow that are not available by ttys.deny.
 .Sh ACCOUNTING LIMITS
 .Bl -column host.accounted indent indent
-.It Sy Name Ta Sy Type Ta Sy Notes Ta Sy Description
-.It accounted  bool    false   Enable session time accounting for all users
+.It Sy "Name   Type    Notes   Description"
+.It "accounted bool    false   Enable session time accounting for all users"
 in this class.
-.It autodelete time            Time after expiry when account is auto-deleted.
-.It bootfull   bool    false   Enable 'boot only if ttygroup is full' strategy
+.It "autodelete        time            Time after expiry when account is auto-deleted."
+.It "bootfull  bool    false   Enable 'boot only if ttygroup is full' strategy"
 when terminating sessions.
-.It daytime    time            Maximum login time per day.
-.It expireperiod       time            Time for expiry allocation.
-.It graceexpire        time            Grace days for expired account.
-.It gracetime  time            Additional grace login time allowed.
-.It host.accounted     list            List of remote host wildcards from which
+.It "daytime   time            Maximum login time per day."
+.It "expireperiod      time            Time for expiry allocation."
+.It "graceexpire       time            Grace days for expired account."
+.It "gracetime time            Additional grace login time allowed."
+.It "host.accounted    list            List of remote host wildcards from which"
 login sessions will be accounted.
-.It host.exempt        list            List of remote host wildcards from which
+.It "host.exempt       list            List of remote host wildcards from which"
 login session accounting is exempted.
 .It idletime   time            Maximum idle time before logout (unused).
 .It monthtime  time            Maximum login time per month.
 .It passwordtime       time            Used by
 .Xr passwd 1
 to set next password expiry date.
-.It refreshtime        time            New time allowed on account refresh.
-.It refreshperiod      str             How often account time is refreshed.
-.It sessiontime        time            Maximum login time per session.
-.It sessionlimit       number          Maximum number of concurrent
+.It "refreshtime       time            New time allowed on account refresh."
+.It "refreshperiod     str             How often account time is refreshed."
+.It "sessiontime       time            Maximum login time per session."
+.It "sessionlimit      number          Maximum number of concurrent"
 login sessions on ttys in any group.
-.It ttys.accounted     list            List of ttys and ttygroups for which
+.It "ttys.accounted    list            List of ttys and ttygroups for which"
 login accounting is active.
-.It ttys.exempt        list            List of ttys and ttygroups for which login accounting
+.It "ttys.exempt       list            List of ttys and ttygroups for which login accounting"
 is exempt.
 .It warnexpire time            Advance notice for pending account expiry.
 .It warnpassword       time            Advance notice for pending password expiry.
index 9cc28f9..e4383b9 100644 (file)
@@ -17,7 +17,7 @@
 .\" 5. Modifications may be freely made to this file providing the above
 .\"    conditions are met.
 .\"
-.\" $FreeBSD: src/lib/libutil/login_auth.3,v 1.9.2.4 2001/12/17 10:08:32 ru Exp $
+.\" $FreeBSD: head/lib/libutil/login_auth.3 206622 2010-04-14 19:08:06Z uqs $
 .\"
 .Dd December 29, 1996
 .Dt LOGIN_AUTH 3
index 74df3e7..8f9813a 100644 (file)
  *
  * Low-level routines relating to the user capabilities database
  *
- * $FreeBSD: src/lib/libutil/login_auth.c,v 1.11 1999/08/28 00:05:45 peter Exp $
- * $DragonFly: src/lib/libutil/login_auth.c,v 1.3 2005/03/04 04:31:11 cpressey Exp $
+ * $FreeBSD: head/lib/libutil/login_auth.c 255007 2013-08-28 21:10:37Z jilles $
  */
 
 #include <sys/types.h>
 
 #include <fcntl.h>
+#include <login_cap.h>
 #include <paths.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
-#include "login_cap.h"
-
 
 /*
  * auth_checknologin()
@@ -52,7 +50,7 @@
 void
 auth_checknologin(login_cap_t *lc)
 {
-  char *file;
+  const char *file;
 
   /* Do we ignore a nologin file? */
   if (login_getcapbool(lc, "ignorenologin", 0))
@@ -85,7 +83,7 @@ auth_cat(const char *file)
   int fd, count;
   char buf[BUFSIZ];
 
-  if ((fd = open(file, O_RDONLY)) < 0)
+  if ((fd = open(file, O_RDONLY | O_CLOEXEC)) < 0)
     return 0;
   while ((count = read(fd, buf, sizeof(buf))) > 0)
     (void)write(fileno(stdout), buf, count);
index a840790..4a9d5dd 100644 (file)
@@ -17,9 +17,9 @@
 .\" 5. Modifications may be freely made to this file providing the above
 .\"    conditions are met.
 .\"
-.\" $FreeBSD: src/lib/libutil/login_cap.3,v 1.17.2.8 2002/12/29 16:35:36 schweikh Exp $
+.\" $FreeBSD: head/lib/libutil/login_cap.3 233648 2012-03-29 05:02:12Z eadler $
 .\"
-.Dd December 27, 1996
+.Dd June 14, 2007
 .Dt LOGIN_CAP 3
 .Os
 .Sh NAME
 .Fn login_getpwclass "const struct passwd *pwd"
 .Ft login_cap_t *
 .Fn login_getuserclass "const struct passwd *pwd"
-.Ft char *
-.Fn login_getcapstr "login_cap_t *lc" "const char *cap" "char *def" "char *error"
-.Ft char **
+.Ft "const char *"
+.Fn login_getcapstr "login_cap_t *lc" "const char *cap" "const char *def" "const char *error"
+.Ft "const char **"
 .Fn login_getcaplist "login_cap_t *lc" "const char *cap" "const char *chars"
-.Ft char *
-.Fn login_getpath "login_cap_t *lc" "const char *cap" "char *error"
+.Ft "const char *"
+.Fn login_getpath "login_cap_t *lc" "const char *cap" "const char *error"
 .Ft rlim_t
 .Fn login_getcaptime "login_cap_t *lc" "const char *cap" "rlim_t def" "rlim_t error"
 .Ft rlim_t
@@ -66,8 +66,8 @@
 .Fn login_getcapsize "login_cap_t *lc" "const char *cap" "rlim_t def" "rlim_t error"
 .Ft int
 .Fn login_getcapbool "login_cap_t *lc" "const char *cap" "int def"
-.Ft char *
-.Fn login_getstyle "login_cap_t *lc" "char *style" "const char *auth"
+.Ft "const char *"
+.Fn login_getstyle "login_cap_t *lc" "const char *style" "const char *auth"
 .Ft const char *
 .Fn login_setcryptfmt "login_cap_t *lc" "const char *def" "const char *error"
 .Sh DESCRIPTION
@@ -85,8 +85,11 @@ consist of colon
 .Ql \&:
 separated fields, the first field in each record being one or more
 identifiers for the record (which must be unique for the entire database),
-each separated by a '|', and may optionally include a description as
-the last 'name'.
+each separated by a
+.Ql | ,
+and may optionally include a description as
+the last
+.Sq name .
 Remaining fields in the record consist of keyword/data pairs.
 Long lines may be continued with a backslash within empty entries,
 with the second and subsequent lines optionally indented for readability.
@@ -95,9 +98,13 @@ This is similar to the format used in
 except that keywords are not limited to two significant characters,
 and are usually longer for improved readability.
 As with termcap entries, multiple records can be linked together
-(one record including another) using a field containing tc=<recordid>.
-The result is that the entire record referenced by <recordid> replaces
-the tc= field at the point at which it occurs.
+(one record including another) using a field containing
+.Ql tc= Ns Va <recordid> .
+The result is that the entire record referenced by
+.Va <recordid>
+replaces the
+.Va tc=
+field at the point at which it occurs.
 See
 .Xr getcap 3
 for further details on the format and use of a capabilities database.
@@ -105,7 +112,9 @@ for further details on the format and use of a capabilities database.
 The
 .Nm login_cap
 interface provides a convenient means of retrieving login class
-records with all tc= references expanded.
+records with all
+.Va tc=
+references expanded.
 A program will typically call one of
 .Fn login_getclass ,
 .Fn login_getpwclass ,
@@ -114,14 +123,18 @@ or
 .Fn login_getclassbyname
 according to its requirements.
 Each of these functions returns a login capabilities structure,
-.Ft login_cap_t ,
+.Vt login_cap_t ,
 which may subsequently be used to interrogate the database for
 specific values using the rest of the API.
-Once the login_cap_t is of no further use, the
+Once the
+.Vt login_cap_t
+is of no further use, the
 .Fn login_close
 function should be called to free all resources used.
 .Pp
-The structure of login_cap_t is defined in
+The structure of
+.Vt login_cap_t
+is defined in
 .In login_cap.h ,
 as:
 .Bd -literal -offset indent
@@ -133,106 +146,165 @@ typedef struct {
 .Ed
 .Pp
 The
-.Ar lc_class
+.Fa lc_class
 member contains a pointer to the name of the login class
 retrieved.
 This may not necessarily be the same as the one requested,
 either directly via
 .Fn login_getclassbyname ,
-indirectly via a user's login record using
+or indirectly via a user's login record using
 .Fn login_getpwclass ,
 by class name using
-.Fn login_getclass ,
-or
-.Fn login_getuserclass .
+.Fn login_getclass .
 If the referenced user has no login class specified in
 .Pa /etc/master.passwd ,
-the class name is NULL or an empty string.
+the class name is
+.Dv NULL
+or an empty string.
 If the class
 specified does not exist in the database, each of these
-functions will search for a record with an id of "default",
+functions will search for a record with an id of
+.Ql default ,
 with that name returned in the
-.Ar lc_class
+.Fa lc_class
 field.
 In addition, if the referenced user has a UID of 0 (normally,
-"root", although the user name is not considered) then
+.Ql root ,
+although the user name is not considered) then
 .Fn login_getpwclass
-will search for a record with an id of "root" before it searches
-for the record with the id of "default".
+will search for a record with an id of
+.Ql root
+before it searches
+for the record with the id of
+.Ql default .
 .Pp
 The
-.Ar lc_cap
+.Fa lc_cap
 field is used internally by the library to contain the
 expanded login capabilities record.
 Programs with unusual requirements may wish to use this
 with the lower-level
-.Xr getcap 3
+.Fn getcap
 style functions to access the record directly.
 .Pp
 The
-.Ar lc_style
+.Fa lc_style
 field is set by the
 .Fn login_getstyle
 function to the authorisation style, according to the requirements
 of the program handling a login itself.
 .Pp
-As noted above, the
-.Fn login_get*class
-functions return a login_cap_t object which is used to access
-the matching or default record in the capabilities database.
+The
 .Fn login_getclassbyname
-accepts two arguments: the first one is the record identifier of the
-record to be retrieved, the second is an optional directory name.
-If the first
-.Ar name
-argument is NULL, an empty string, or a class that does not exist
-in the supplemental or system login class database, then the system
-.Em default
-record is returned instead.
-If the second
-.Ar dir
-parameter is NULL, then only the system login class database is
-used, but when not NULL, the named directory is searched for
-a login database file called ".login_conf", and capability records
-contained within it may override the system defaults.
-This scheme allows users to override some login settings from
-those in the system login class database by creating class records
-for their own private class with a record id of `me'.
-In the context of a
-.Em login ,
-it should be noted that some options cannot by overridden by
-users for two reasons; many options, such as resource settings
-and default process priorities, require root privileges
-in order to take effect, and other fields in the user's file are
-not be consulted at all during the early phases of login for
-security or administrative reasons.
-See
-.Xr login.conf 5
-for more information on which settings a user is able to override.
-Typically, these are limited purely to the user's default login
-environment which might otherwise have been overridden in shell
-startup scripts in any case.
-The user's
+function is the basic means to get a
+.Vt login_cap_t
+object.
+It accepts two arguments: the first one,
+.Fa name ,
+is the record identifier of the
+record to be retrieved; the second,
+.Fa pwd ,
+is an optional pointer to a
+.Vt passwd
+structure.
+First of all, its arguments are used by the function
+to choose between system and user modes of operation.
+When in system mode, only the system login class database is used.
+When in user mode, the supplemental login class database in the
+user's home directory is allowed to override settings from the system
+database in a limited way as noted below.
+To minimize security implications, user mode is entered by
+.Fn login_getclassbyname
+if and only if
+.Fa name
+is
+.Dv LOGIN_MECLASS
+.Pq Ql me
+and
+.Fa pwd
+is not
+.Dv NULL .
+Otherwise system mode is chosen.
+.Pp
+In system mode, any record in the system database
+.Pa /etc/login.conf
+can be accessed,
+and a fallback to the default record is provided as follows.
+If
+.Fa name
+is
+.Dv NULL ,
+an empty string, or a class that does not exist
+in the login class database, then the
+.Dv LOGIN_DEFCLASS
+record
+.Pq Ql default
+is returned instead.
+.Pp
+In user mode, only the
+.Dv LOGIN_MECLASS
+record
+.Pq Ql me
+is accessed and no fallback to the
+.Ql default
+record is provided.
+The directory specified by
+.Fa pwd->pw_dir
+is searched for
+a login database file called
+.Pa .login_conf ,
+and only the
+.Ql me
+capability record
+contained within it may override the system record with the same name
+while other records are ignored.
+Using this scheme, an application can explicitly
+allow users to override a selected subset of login settings.
+To do so, the application should obtain two
+.Vt login_cap_t
+objects, one in user mode and the other in system mode,
+and then query the user object before the
+system object for login parameters that are allowed to
+be overridden by the user.
+For example, the user's
 .Pa .login_conf
-merely provides a convenient way for a user to set up their preferred
-login environment before the shell is invoked on login.
+can provide a convenient way for a user to set up their preferred
+login environment before the shell is invoked on login if supported by
+.Xr login 1 .
 .Pp
-If the specified record is NULL, empty or does not exist, and the
-system has no "default" record available to fall back to, there is a
+Note that access to the
+.Pa /etc/login.conf
+and
+.Pa .login_conf
+files will only be performed subject to the security checks documented in
+.Xr _secure_path 3
+for the uids 0 and
+.Fa pwd->pw_uid
+respectively.
+.Pp
+If the specified record is
+.Dv NULL ,
+empty or does not exist, and the
+system has no
+.Ql default
+record available to fall back to, there is a
 memory allocation error or for some reason
 .Xr cgetent 3
 is unable to access the login capabilities database, this function
-returns NULL.
+returns
+.Dv NULL .
 .Pp
 The functions
-.Fn login_getpwclass ,
-.Fn login_getclass
+.Fn login_getclass ,
+.Fn login_getpwclass
 and
 .Fn login_getuserclass
 retrieve the applicable login class record for the user's passwd
 entry or class name by calling
 .Fn login_getclassbyname .
-On failure, NULL is returned.
+On failure,
+.Dv NULL
+is returned.
 The difference between these functions is that
 .Fn login_getuserclass
 includes the user's overriding
@@ -245,22 +317,42 @@ restrict lookup only to the system login class database in
 .Pa /etc/login.conf .
 As explained earlier,
 .Fn login_getpwclass
-only differs from
+differs from
 .Fn login_getclass
-in that it allows the default class for user 'root' as "root"
+in that it allows the default class for a super-user as
+.Ql root
 if none has been specified in the password database.
-Otherwise, if the passwd pointer is NULL, or the user record
-has no login class, then the system "default" entry is retrieved.
+Otherwise, if the passwd pointer is
+.Dv NULL ,
+or the user record
+has no login class, then the system
+.Ql default
+entry is retrieved.
+Essentially,
+.Fn login_getclass name
+is equivalent to
+.Fn login_getclassbyname name NULL
+and
+.Fn login_getuserclass pwd
+to
+.Fn login_getclassbyname LOGIN_MECLASS pwd .
 .Pp
-Once a program no longer wishes to use a login_cap_t object,
+Once a program no longer wishes to use a
+.Vt login_cap_t
+object,
 .Fn login_close
 may be called to free all resources used by the login class.
+The
 .Fn login_close
-may be passed a NULL pointer with no harmful side-effects.
+function may be passed a
+.Dv NULL
+pointer with no harmful side-effects.
 .Pp
 The remaining functions may be used to retrieve individual
 capability records.
-Each function takes a login_cap_t object as its first parameter,
+Each function takes a
+.Vt login_cap_t
+object as its first parameter,
 a capability tag as the second, and remaining parameters being
 default and error values that are returned if the capability is
 not found.
@@ -281,21 +373,22 @@ Memory allocated during retrieval or processing of capability
 tags is automatically reused by subsequent calls to functions
 in this group, or deallocated on calling
 .Fn login_close .
-.Bl -tag -width ".Fn login_setcryptfmt"
+.Bl -tag -width "login_getcaplist()"
 .It Fn login_getcapstr
 This function returns a simple string capability.
 If the string is not found, then the value in
-.Ar def
+.Fa def
 is returned as the default value, or if an error
 occurs, the value in the
-.Ar error
+.Fa error
 parameter is returned.
 .It Fn login_getcaplist
 This function returns the value corresponding to the named
-capability tag as a list of values in a NULL terminated
-array.
+capability tag as a list of values in a
+.Dv NULL
+terminated array.
 Within the login class database, some tags are of type
-.Em list ,
+.Vt list ,
 which consist of one or more comma- or space separated
 values.
 Usually, this function is not called directly from an
@@ -303,57 +396,91 @@ application, but is used indirectly via
 .Fn login_getstyle .
 .It Fn login_getpath
 This function returns a list of directories separated by colons
-.Ql &: .
+.Ql \&: .
 Capability tags for which this function is called consist of a list of
 directories separated by spaces.
 .It Fn login_getcaptime
 This function returns a
-.Em time value
+.Vt time value
 associated with a particular capability tag with the value expressed
 in seconds (the default), minutes, hours, days, weeks or (365 day)
 years or any combination of these.
-A suffix determines the units used: S for seconds, M for minutes,
-H for hours, D for days, W for weeks and Y for 365 day years.
+A suffix determines the units used:
+.Ql S
+for seconds,
+.Ql M
+for minutes,
+.Ql H
+for hours,
+.Ql D
+for days,
+.Ql W
+for weeks and
+.Ql Y
+for 365 day years.
 Case of the units suffix is ignored.
 .Pp
 Time values are normally used for setting resource, accounting and
 session limits.
 If supported by the operating system and compiler (which is true of
-.Dx ) ,
-the value returned is a quad (long long), of type
-.Em rlim_t .
-A value "inf" or "infinity" may be used to express an infinite
-value, in which case RLIM_INFINITY is returned.
+.Fx ) ,
+the value returned is a
+.Vt quad
+.Pq Vt long long ,
+of type
+.Vt rlim_t .
+A value
+.Ql inf
+or
+.Ql infinity
+may be used to express an infinite
+value, in which case
+.Dv RLIM_INFINITY
+is returned.
 .It Fn login_getcapnum
 This function returns a numeric value for a tag, expressed either as
-tag=<value> or the standard
+.Ql tag=<value>
+or the standard
 .Fn cgetnum
-format tag#<value>.
+format
+.Ql tag#<value> .
 The first format should be used in preference to the second, the
 second format is provided for compatibility and consistency with the
 .Xr getcap 3
 database format where numeric types use the
 .Ql \&#
 as the delimiter for numeric values.
-If in the first format, then the value given may be "inf" or
-"infinity" which results in a return value of RLIM_INFINITY.
+If in the first format, then the value given may be
+.Ql inf
+or
+.Ql infinity
+which results in a return value of
+.Dv RLIM_INFINITY .
 If the given capability tag cannot be found, the
-.Ar def
+.Fa def
 parameter is returned, and if an error occurs, the
-.Ar error
+.Fa error
 parameter is returned.
 .It Fn login_getcapsize
 .Fn login_getcapsize
 returns a value representing a size (typically, file or memory)
 which may be expressed as bytes (the default), 512 byte blocks,
 kilobytes, megabytes, gigabytes, and on systems that support the
-.Ar long long
+.Vt long long
 type, terabytes.
 The suffix used determines the units, and multiple values and
-units may be used in combination (e.g. 1m500k = 1.5 megabytes).
-A value with no suffix is interpreted as bytes,  B as 512-byte
-blocks, K as kilobytes, M as megabytes, G as gigabytes and T as
-terabytes.
+units may be used in combination (e.g.\& 1m500k = 1.5 megabytes).
+A value with no suffix is interpreted as bytes,
+.Ql B
+as 512-byte blocks,
+.Ql K
+as kilobytes,
+.Ql M
+as megabytes,
+.Ql G
+as gigabytes and
+.Ql T
+as terabytes.
 Case is ignored.
 The error value is returned if there is a login capabilities database
 error, if an invalid suffix is used, or if a numeric value cannot be
@@ -361,33 +488,61 @@ interpreted.
 .It Fn login_getcapbool
 This function returns a boolean value tied to a particular flag.
 It returns 0 if the given capability tag is not present or is
-negated by the presence of a "tag@" (See
+negated by the presence of a
+.Ql tag@
+(see
 .Xr getcap 3
 for more information on boolean flags), and returns 1 if the tag
 is found.
 .It Fn login_getstyle
 This function is used by the login authorisation system to determine
 the style of login available in a particular case.
-The function accepts three parameters, the login_cap entry itself and
-two optional parameters, and authorisation type 'auth' and 'style', and
+The function accepts three parameters, the
+.Fa lc
+entry itself and
+two optional parameters, and authorisation type
+.Fa auth
+and
+.Fa style ,
+and
 applies these to determine the authorisation style that best suites
 these rules.
 .Bl -bullet
 .It
-If 'auth' is neither NULL nor an empty string, look for a tag of type
-"auth-<auth>" in the capability record.
-If not present, then look for the default tag "auth=".
+If
+.Fa auth
+is neither
+.Dv NULL
+nor an empty string, look for a tag of type
+.Ql auth- Ns Fa <auth>
+in the capability record.
+If not present, then look for the default tag
+.Va auth= .
 .It
 If no valid authorisation list was found from the previous step, then
-default to "passwd" as the authorisation list.
+default to
+.Ql passwd
+as the authorisation list.
 .It
-If 'style' is not NULL or empty, look for it in the list of authorisation
-methods found from the pprevious step.
-If 'style' is NULL or an empty string, then default to "passwd"
+If
+.Fa style
+is not
+.Dv NULL
+or empty, look for it in the list of authorisation
+methods found from the previous step.
+If
+.Fa style
+is
+.Dv NULL
+or an empty string, then default to
+.Ql passwd
 authorisation.
 .It
-If 'style' is found in the chosen list of authorisation methods, then
-return that, otherwise return NULL.
+If
+.Fa style
+is found in the chosen list of authorisation methods, then
+return that, otherwise return
+.Dv NULL .
 .El
 .Pp
 This scheme allows the administrator to determine the types of
@@ -404,7 +559,7 @@ The
 function is used to set the
 .Xr crypt 3
 format using the
-.Ql passwd_format
+.Va passwd_format
 configuration entry.
 If no entry is found,
 .Fa def
@@ -416,6 +571,7 @@ on the specifier fails,
 is returned to indicate this.
 .El
 .Sh SEE ALSO
+.Xr login 1 ,
 .Xr crypt 3 ,
 .Xr getcap 3 ,
 .Xr login_class 3 ,
index 4bc609f..5903fc0 100644 (file)
  *
  * Low-level routines relating to the user capabilities database
  *
- * $FreeBSD: src/lib/libutil/login_cap.c,v 1.17.2.4 2001/10/21 19:42:13 ache Exp $
- * $DragonFly: src/lib/libutil/login_cap.c,v 1.4 2008/10/29 22:03:12 swildner Exp $
+ * $FreeBSD: head/lib/libutil/login_cap.c 255007 2013-08-28 21:10:37Z jilles $
  */
 
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/param.h>
-
 #include <errno.h>
 #include <fcntl.h>
+#include <libutil.h>
+#include <login_cap.h>
 #include <pwd.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -43,9 +43,6 @@
 #include <syslog.h>
 #include <unistd.h>
 
-#include "libutil.h"
-#include "login_cap.h"
-
 /*
  * allocstr()
  * Manage a single static pointer for handling a local char* buffer,
@@ -61,10 +58,12 @@ static int lc_object_count = 0;
 static size_t internal_stringsz = 0;
 static char * internal_string = NULL;
 static size_t internal_arraysz = 0;
-static char ** internal_array = NULL;
+static const char ** internal_array = NULL;
+
+static char path_login_conf[] = _PATH_LOGIN_CONF;
 
 static char *
-allocstr(char *str)
+allocstr(const char *str)
 {
     char    *p;
 
@@ -79,10 +78,10 @@ allocstr(char *str)
 }
 
 
-static char **
+static const char **
 allocarray(size_t sz)
 {
-    char    **p;
+    static const char    **p;
 
     if (sz <= internal_arraysz)
        p = internal_array;
@@ -102,25 +101,26 @@ allocarray(size_t sz)
  * Free using freearraystr()
  */
 
-static char **
-arrayize(char *str, const char *chars, int *size)
+static const char **
+arrayize(const char *str, const char *chars, int *size)
 {
     int            i;
     char    *ptr;
-    char    **res = NULL;
+    const char *cptr;
+    const char **res = NULL;
 
     /* count the sub-strings */
-    for (i = 0, ptr = str; *ptr; i++) {
-       int count = strcspn(ptr, chars);
-       ptr += count;
-       if (*ptr)
-           ++ptr;
+    for (i = 0, cptr = str; *cptr; i++) {
+       int count = strcspn(cptr, chars);
+       cptr += count;
+       if (*cptr)
+           ++cptr;
     }
 
     /* alloc the array */
     if ((ptr = allocstr(str)) != NULL) {
        if ((res = allocarray(++i)) == NULL)
-           free(str);
+           free((void *)(uintptr_t)(const void *)str);
        else {
            /* now split the string */
            i = 0;
@@ -170,12 +170,16 @@ login_close(login_cap_t * lc)
 
 
 /*
- * login_getclassbyname() get the login class by its name.
+ * login_getclassbyname()
+ * Get the login class by its name.
  * If the name given is NULL or empty, the default class
- * LOGIN_DEFCLASS (ie. "default") is fetched. If the
- * 'dir' argument contains a non-NULL non-empty string,
- * then the file _FILE_LOGIN_CONF is picked up from that
- * directory instead of the system login database.
+ * LOGIN_DEFCLASS (i.e., "default") is fetched.
+ * If the name given is LOGIN_MECLASS and
+ * 'pwd' argument is non-NULL and contains an non-NULL
+ * dir entry, then the file _FILE_LOGIN_CONF is picked
+ * up from that directory and used before the system
+ * login database. In that case the system login database
+ * is looked up using LOGIN_MECLASS, too, which is a bug.
  * Return a filled-out login_cap_t structure, including
  * class name, and the capability record buffer.
  */
@@ -212,12 +216,14 @@ login_getclassbyname(char const *name, const struct passwd *pwd)
 
        if (dir && snprintf(userpath, MAXPATHLEN, "%s/%s", dir,
                            _FILE_LOGIN_CONF) < MAXPATHLEN) {
-           login_dbarray[i] = userpath;
            if (_secure_path(userpath, pwd->pw_uid, pwd->pw_gid) != -1)
-               i++;            /* only use 'secure' data */
+               login_dbarray[i++] = userpath;
        }
-       if (_secure_path(_PATH_LOGIN_CONF, 0, 0) != -1)
-           login_dbarray[i++] = _PATH_LOGIN_CONF;
+       /*
+        * XXX: Why to add the system database if the class is `me'?
+        */
+       if (_secure_path(path_login_conf, 0, 0) != -1)
+           login_dbarray[i++] = path_login_conf;
        login_dbarray[i] = NULL;
 
        memset(lc, 0, sizeof(login_cap_t));
@@ -226,13 +232,13 @@ login_getclassbyname(char const *name, const struct passwd *pwd)
        if (name == NULL || *name == '\0')
            name = LOGIN_DEFCLASS;
 
-       switch (cgetent(&lc->lc_cap, login_dbarray, (char*)name)) {
+       switch (cgetent(&lc->lc_cap, login_dbarray, name)) {
        case -1:                /* Failed, entry does not exist */
            if (me)
                break;  /* Don't retry default on 'me' */
            if (i == 0)
                r = -1;
-           else if ((r = open(login_dbarray[0], O_RDONLY)) >= 0)
+           else if ((r = open(login_dbarray[0], O_RDONLY | O_CLOEXEC)) >= 0)
                close(r);
            /*
             * If there's at least one login class database,
@@ -244,9 +250,9 @@ login_getclassbyname(char const *name, const struct passwd *pwd)
            /* fall-back to default class */
            name = LOGIN_DEFCLASS;
            msg = "%s: no default/fallback class '%s'";
-           if (cgetent(&lc->lc_cap, login_dbarray, (char*)name) != 0 && r >= 0)
+           if (cgetent(&lc->lc_cap, login_dbarray, name) != 0 && r >= 0)
                break;
-           /* Fallthru - just return system defaults */
+           /* FALLTHROUGH - just return system defaults */
        case 0:         /* success! */
            if ((lc->lc_class = strdup(name)) != NULL) {
                if (dir) {
@@ -300,12 +306,13 @@ login_getclass(const char *cls)
 
 
 /*
- * login_getclass()
+ * login_getpwclass()
  * Get the login class for a given password entry from
  * the system (only) login class database.
  * If the password entry's class field is not set, or
  * the class specified does not exist, then use the
- * default of LOGIN_DEFCLASS (ie. "default").
+ * default of LOGIN_DEFCLASS (i.e., "default") for an unprivileged
+ * user or that of LOGIN_DEFROOTCLASS (i.e., "root") for a super-user.
  * Return a filled-out login_cap_t structure, including
  * class name, and the capability record buffer.
  */
@@ -320,14 +327,18 @@ login_getpwclass(const struct passwd *pwd)
        if (cls == NULL || *cls == '\0')
            cls = (pwd->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS;
     }
+    /*
+     * XXX: pwd should be unused by login_getclassbyname() unless cls is `me',
+     *      so NULL can be passed instead of pwd for more safety.
+     */
     return login_getclassbyname(cls, pwd);
 }
 
 
 /*
  * login_getuserclass()
- * Get the login class for a given password entry, allowing user
- * overrides via ~/.login_conf.
+ * Get the `me' login class, allowing user overrides via ~/.login_conf.
+ * Note that user overrides are allowed only in the `me' class.
  */
 
 login_cap_t *
@@ -337,16 +348,15 @@ login_getuserclass(const struct passwd *pwd)
 }
 
 
-
 /*
  * login_getcapstr()
  * Given a login_cap entry, and a capability name, return the
- * value defined for that capability, a defualt if not found, or
+ * value defined for that capability, a default if not found, or
  * an error string on error.
  */
 
-char *
-login_getcapstr(login_cap_t *lc, const char *cap, char *def, char *error)
+const char *
+login_getcapstr(login_cap_t *lc, const char *cap, const char *def, const char *error)
 {
     char    *res;
     int            ret;
@@ -354,7 +364,7 @@ login_getcapstr(login_cap_t *lc, const char *cap, char *def, char *error)
     if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0')
        return def;
 
-    if ((ret = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+    if ((ret = cgetstr(lc->lc_cap, cap, &res)) == -1)
        return def;
     return (ret >= 0) ? res : error;
 }
@@ -367,14 +377,14 @@ login_getcapstr(login_cap_t *lc, const char *cap, char *def, char *error)
  * strings.
  */
 
-char **
+const char **
 login_getcaplist(login_cap_t *lc, const char *cap, const char *chars)
 {
-    char    *lstring;
+    const char *lstring;
 
     if (chars == NULL)
        chars = ", \t";
-    if ((lstring = login_getcapstr(lc, (char*)cap, NULL, NULL)) != NULL)
+    if ((lstring = login_getcapstr(lc, cap, NULL, NULL)) != NULL)
        return arrayize(lstring, chars, NULL);
     return NULL;
 }
@@ -388,23 +398,23 @@ login_getcaplist(login_cap_t *lc, const char *cap, const char *chars)
  * If there is an error of any kind, return <error>.
  */
 
-char *
-login_getpath(login_cap_t *lc, const char *cap, char * error)
+const char *
+login_getpath(login_cap_t *lc, const char *cap, const char *error)
 {
-    char    *str;
-
-    if ((str = login_getcapstr(lc, (char*)cap, NULL, NULL)) == NULL)
-       str = error;
-    else {
-       char *ptr = str;
+    const char *str;
+    char *ptr;
+    int count;
 
+    str = login_getcapstr(lc, cap, NULL, NULL);
+    if (str == NULL)
+       return error;
+    ptr = __DECONST(char *, str); /* XXXX Yes, very dodgy */
        while (*ptr) {
-           int count = strcspn(ptr, ", \t");
+       count = strcspn(ptr, ", \t");
            ptr += count;
            if (*ptr)
                *ptr++ = ':';
        }
-    }
     return str;
 }
 
@@ -537,7 +547,7 @@ login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
      * If there's an error, return <error>.
      */
 
-    if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+    if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1)
        return def;
     else if (r < 0) {
        errno = ERANGE;
@@ -624,10 +634,10 @@ login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
     /*
      * For BSDI compatibility, try for the tag=<val> first
      */
-    if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1) {
+    if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) {
        long    lval;
        /* string capability not present, so try for tag#<val> as numeric */
-       if ((r = cgetnum(lc->lc_cap, (char *)cap, &lval)) == -1)
+       if ((r = cgetnum(lc->lc_cap, cap, &lval)) == -1)
            return def; /* Not there, so return default */
        else if (r >= 0)
            return (rlim_t)lval;
@@ -673,7 +683,7 @@ login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error)
     if (lc == NULL || lc->lc_cap == NULL)
        return def;
 
-    if ((r = cgetstr(lc->lc_cap, (char *)cap, &res)) == -1)
+    if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1)
        return def;
     else if (r < 0) {
        errno = ERANGE;
@@ -741,7 +751,7 @@ login_getcapbool(login_cap_t *lc, const char *cap, int def)
 {
     if (lc == NULL || lc->lc_cap == NULL)
        return def;
-    return (cgetcap(lc->lc_cap, (char *)cap, ':') != NULL);
+    return (cgetcap(lc->lc_cap, cap, ':') != NULL);
 }
 
 
@@ -765,15 +775,15 @@ login_getcapbool(login_cap_t *lc, const char *cap, int def)
  *     login_getstyle(lc, "skey", "network");
  */
 
-char *
-login_getstyle(login_cap_t *lc, char *style, const char *auth)
+const char *
+login_getstyle(login_cap_t *lc, const char *style, const char *auth)
 {
     int            i;
-    char    **authtypes = NULL;
+    const char **authtypes = NULL;
     char    *auths= NULL;
     char    realauth[64];
 
-    static char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL };
+    static const char *defauthtypes[] = { LOGIN_DEFSTYLE, NULL };
 
     if (auth != NULL && *auth != '\0') {
        if (snprintf(realauth, sizeof realauth, "auth-%s", auth) < (int)sizeof(realauth))
index 61366bb..a625e9d 100644 (file)
@@ -22,8 +22,7 @@
  * Low-level routines relating to the user capabilities database
  *
  *     Was login_cap.h,v 1.9 1997/05/07 20:00:01 eivind Exp
- * $FreeBSD: src/lib/libutil/login_cap.h,v 1.3.2.1 2000/09/20 11:19:54 green Exp $
- * $DragonFly: src/lib/libutil/login_cap.h,v 1.5 2008/10/29 22:03:12 swildner Exp $
+ * $FreeBSD: head/lib/libutil/login_cap.h 219304 2011-03-05 12:40:35Z trasz $
  */
 
 #ifndef _LOGIN_CAP_H_
 #define LOGIN_SETUMASK         0x0020          /* set umask, obviously */
 #define LOGIN_SETUSER          0x0040          /* set user (via setuid) */
 #define LOGIN_SETENV           0x0080          /* set user environment */
-#define        LOGIN_SETALL            0x00ff          /* set everything */
+#define LOGIN_SETMAC           0x0100          /* set user default MAC label */
+#define LOGIN_SETCPUMASK       0x0200          /* set user cpumask */
+#define LOGIN_SETLOGINCLASS    0x0400          /* set login class in the kernel */
+#define LOGIN_SETALL           0x07ff          /* set everything */
 
 #define BI_AUTH                "authorize"             /* accepted authentication */
 #define BI_REJECT      "reject"                /* rejected authentication */
@@ -97,63 +99,67 @@ typedef struct login_time {
 __BEGIN_DECLS
 struct passwd;
 
-void login_close (login_cap_t *);
-login_cap_t *login_getclassbyname (const char *, const struct passwd *);
-login_cap_t *login_getclass (const char *);
-login_cap_t *login_getpwclass (const struct passwd *);
-login_cap_t *login_getuserclass (const struct passwd *);
-
-char *login_getcapstr (login_cap_t*, const char *, char *, char *);
-char **login_getcaplist (login_cap_t *, const char *, const char *);
-char *login_getstyle (login_cap_t *, char *, const char *);
-rlim_t login_getcaptime (login_cap_t *, const char *, rlim_t, rlim_t);
-rlim_t login_getcapnum (login_cap_t *, const char *, rlim_t, rlim_t);
-rlim_t login_getcapsize (login_cap_t *, const char *, rlim_t, rlim_t);
-char *login_getpath (login_cap_t *, const char *, char *);
-int login_getcapbool (login_cap_t *, const char *, int);
-const char *login_setcryptfmt (login_cap_t *, const char *, const char *);
-
-int setclasscontext (const char*, unsigned int);
-int setusercontext (login_cap_t*, const struct passwd*, uid_t, unsigned int);
-void setclassresources (login_cap_t *);
-int setclassenvironment (login_cap_t *, const struct passwd *, int);
+void login_close(login_cap_t *);
+login_cap_t *login_getclassbyname(const char *, const struct passwd *);
+login_cap_t *login_getclass(const char *);
+login_cap_t *login_getpwclass(const struct passwd *);
+login_cap_t *login_getuserclass(const struct passwd *);
+
+const char *login_getcapstr(login_cap_t *, const char *, const char *,
+    const char *);
+const char **login_getcaplist(login_cap_t *, const char *, const char *);
+const char *login_getstyle(login_cap_t *, const char *, const char *);
+rlim_t login_getcaptime(login_cap_t *, const char *, rlim_t, rlim_t);
+rlim_t login_getcapnum(login_cap_t *, const char *, rlim_t, rlim_t);
+rlim_t login_getcapsize(login_cap_t *, const char *, rlim_t, rlim_t);
+const char *login_getpath(login_cap_t *, const char *, const char *);
+int login_getcapbool(login_cap_t *, const char *, int);
+const char *login_setcryptfmt(login_cap_t *, const char *, const char *);
+
+int setclasscontext(const char *, unsigned int);
+int setusercontext(login_cap_t *, const struct passwd *, uid_t, unsigned int);
+void setclassresources(login_cap_t *);
+void setclassenvironment(login_cap_t *, const struct passwd *, int);
 
 /* Most of these functions are deprecated */
-int auth_approve (login_cap_t*, const char*, const char*);
-int auth_check (const char *, const char *, const char *, const char *, int *);
-void auth_env (void);
-char *auth_mkvalue (const char *n);
-int auth_response (const char *, const char *, const char *, const char *, int *, const char *, const char *);
-void auth_rmfiles (void);
-int auth_scan (int);
-int auth_script (const char*, ...);
-int auth_script_data (const char *, int, const char *, ...);
-char *auth_valud (const char *);
-int auth_setopt (const char *, const char *);
-void auth_clropts (void);
-
-void auth_checknologin (login_cap_t*);
-int auth_cat (const char*);
-
-int auth_ttyok (login_cap_t*, const char *);
-int auth_hostok (login_cap_t*, const char *, char const *);
-int auth_timeok (login_cap_t*, time_t);
+int auth_approve(login_cap_t *, const char *, const char *);
+int auth_check(const char *, const char *, const char *, const char *, int *);
+void auth_env(void);
+char *auth_mkvalue(const char *);
+int auth_response(const char *, const char *, const char *, const char *, int *,
+    const char *, const char *);
+void auth_rmfiles(void);
+int auth_scan(int);
+int auth_script(const char *, ...);
+int auth_script_data(const char *, int, const char *, ...);
+char *auth_valud(const char *);
+int auth_setopt(const char *, const char *);
+void auth_clropts(void);
+
+void auth_checknologin(login_cap_t *);
+int auth_cat(const char *);
+
+int auth_ttyok(login_cap_t *, const char *);
+int auth_hostok(login_cap_t *, const char *, char const *);
+int auth_timeok(login_cap_t *, time_t);
 
 struct tm;
 
-login_time_t parse_lt (const char *);
+login_time_t parse_lt(const char *);
 int in_lt(const login_time_t *, time_t *);
-int in_ltm (const login_time_t *, struct tm *, time_t *);
-int in_ltms (const login_time_t *, struct tm *, time_t *);
+int in_ltm(const login_time_t *, struct tm *, time_t *);
+int in_ltms(const login_time_t *, struct tm *, time_t *);
 int in_lts(const login_time_t *, time_t *);
 
 /* helper functions */
 
-int login_strinlist (char **, char const *, int);
-int login_str2inlist (char **, const char *, const char *, int);
-login_time_t * login_timelist (login_cap_t *, char const *, int *, login_time_t **);
-int login_ttyok (login_cap_t *, const char *, const char *, const char *);
-int login_hostok (login_cap_t *, const char *, const char *, const char *, const char *);
+int login_strinlist(const char **, char const *, int);
+int login_str2inlist(const char **, const char *, const char *, int);
+login_time_t * login_timelist(login_cap_t *, char const *, int *,
+    login_time_t **);
+int login_ttyok(login_cap_t *, const char *, const char *, const char *);
+int login_hostok(login_cap_t *, const char *, const char *, const char *,
+    const char *);
 
 __END_DECLS
 
index cf576a7..5df17ef 100644 (file)
  *
  * High-level routines relating to use of the user capabilities database
  *
- * $FreeBSD: src/lib/libutil/login_class.c,v 1.14.2.3 2002/08/06 07:07:52 ache Exp $
- * $DragonFly: src/lib/libutil/login_class.c,v 1.5 2006/01/12 13:43:10 corecode Exp $
+ * $FreeBSD: head/lib/libutil/login_class.c 256850 2013-10-21 16:46:12Z kib $
  */
 
 #include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/rtprio.h>
+#include <sys/stat.h>
+#include <sys/time.h>
 
+#include <ctype.h>
+#include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <login_cap.h>
 #include <paths.h>
 #include <pwd.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <syslog.h>
 #include <unistd.h>
 
-#include "login_cap.h"
-
 
 static struct login_res {
     const char *what;
@@ -105,7 +106,7 @@ setclassresources(login_cap_t *lc)
            rmax = (*lr->who)(lc, lr->what, rmax, rmax);
            rlim.rlim_cur = (*lr->who)(lc, name_cur, rcur, rcur);
            rlim.rlim_max = (*lr->who)(lc, name_max, rmax, rmax);
-    
+
            if (setrlimit(lr->why, &rlim) == -1)
                syslog(LOG_WARNING, "set class '%s' resource limit %s: %m", lc->lc_class, lr->what);
        }
@@ -133,7 +134,7 @@ static struct login_vars {
 };
 
 static char *
-substvar(char * var, const struct passwd * pwd, int hlen, int pch, int nlen)
+substvar(const char * var, const struct passwd * pwd, int hlen, int pch, int nlen)
 {
     char    *np = NULL;
 
@@ -141,14 +142,13 @@ substvar(char * var, const struct passwd * pwd, int hlen, int pch, int nlen)
        int     tildes = 0;
        int     dollas = 0;
        char    *p;
+       const char *q;
 
        if (pwd != NULL) {
-           /* Count the number of ~'s in var to substitute */
-           for (p = var; (p = strchr(p, '~')) != NULL; p++)
-               ++tildes;
-           /* Count the number of $'s in var to substitute */
-           for (p = var; (p = strchr(p, '$')) != NULL; p++)
-               ++dollas;
+           for (q = var; *q != '\0'; ++q) {
+               tildes += (*q == '~');
+               dollas += (*q == '$');
+           }
        }
 
        np = malloc(strlen(var) + (dollas * nlen)
@@ -186,11 +186,11 @@ substvar(char * var, const struct passwd * pwd, int hlen, int pch, int nlen)
        }
     }
 
-    return np;
+    return (np);
 }
 
 
-int
+void
 setclassenvironment(login_cap_t *lc, const struct passwd * pwd, int paths)
 {
     struct login_vars  *vars = paths ? pathvars : envars;
@@ -202,23 +202,16 @@ setclassenvironment(login_cap_t *lc, const struct passwd * pwd, int paths)
        ++pch;
 
     while (vars->tag != NULL) {
-       char * var = paths ? login_getpath(lc, vars->tag, NULL)
+       const char * var = paths ? login_getpath(lc, vars->tag, NULL)
                           : login_getcapstr(lc, vars->tag, NULL, NULL);
 
        char * np  = substvar(var, pwd, hlen, pch, nlen);
 
        if (np != NULL) {
-           if (setenv(vars->var, np, vars->overwrite) == -1) {
-               syslog(LOG_ERR, "setclassenvironment: %m");
-               free(np);
-               return -1;
-           }
+           setenv(vars->var, np, vars->overwrite);
            free(np);
        } else if (vars->def != NULL) {
-           if (setenv(vars->var, vars->def, 0) == -1) {
-               syslog(LOG_ERR, "setclassenvironment: %m");
-               return -1;
-           }
+           setenv(vars->var, vars->def, 0);
        }
        ++vars;
     }
@@ -228,7 +221,7 @@ setclassenvironment(login_cap_t *lc, const struct passwd * pwd, int paths)
      * which the admin and/or user may set an arbitrary set of env vars.
      */
     if (!paths) {
-       char    **set_env = login_getcaplist(lc, "setenv", ",");
+       const char      **set_env = login_getcaplist(lc, "setenv", ",");
 
        if (set_env != NULL) {
            while (*set_env != NULL) {
@@ -239,10 +232,7 @@ setclassenvironment(login_cap_t *lc, const struct passwd * pwd, int paths)
 
                    *p++ = '\0';
                    if ((np = substvar(p, pwd, hlen, pch, nlen)) != NULL) {
-                       if (setenv(*set_env, np, 1) == -1) {
-                           free(np);
-                           return -1;
-                       }
+                       setenv(*set_env, np, 1);
                        free(np);
                    }
                }
@@ -250,10 +240,10 @@ setclassenvironment(login_cap_t *lc, const struct passwd * pwd, int paths)
            }
        }
     }
-    return 0;
 }
 
 
+
 /*
  * setclasscontext()
  *
@@ -278,20 +268,19 @@ setclasscontext(const char *classname, unsigned int flags)
 
     rc = lc ? setusercontext(lc, NULL, 0, flags) : -1;
     login_close(lc);
-    return rc;
+    return (rc);
 }
 
 
 
 /*
- * Private functionw which takes care of processing
+ * Private function which takes care of processing
  */
 
 static mode_t
 setlogincontext(login_cap_t *lc, const struct passwd *pwd,
-               mode_t mymask, unsigned long flags, int *errcode)
+               mode_t mymask, unsigned long flags)
 {
-    *errcode = 0;
     if (lc) {
        /* Set resources */
        if (flags & LOGIN_SETRESOURCES)
@@ -300,17 +289,13 @@ setlogincontext(login_cap_t *lc, const struct passwd *pwd,
        if (flags & LOGIN_SETUMASK)
            mymask = (mode_t)login_getcapnum(lc, "umask", mymask, mymask);
        /* Set paths */
-       if (flags & LOGIN_SETPATH) {
-           if (setclassenvironment(lc, pwd, 1) == -1)
-               *errcode = -1;
-       }
+       if (flags & LOGIN_SETPATH)
+           setclassenvironment(lc, pwd, 1);
        /* Set environment */
-       if (flags & LOGIN_SETENV) {
-           if (setclassenvironment(lc, pwd, 0) == -1)
-               *errcode = -1;
-       }
+       if (flags & LOGIN_SETENV)
+           setclassenvironment(lc, pwd, 0);
     }
-    return mymask;
+    return (mymask);
 }
 
 
@@ -335,10 +320,7 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in
     quad_t     p;
     mode_t     mymask;
     login_cap_t *llc = NULL;
-#ifndef __NETBSD_SYSCALLS
     struct rtprio rtp;
-#endif
-    int                errcode;
 
     if (lc == NULL) {
        if (pwd != NULL && (lc = login_getpwclass(pwd)) != NULL)
@@ -356,25 +338,26 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in
     if (flags & LOGIN_SETPRIORITY) {
        p = login_getcapnum(lc, "priority", LOGIN_DEFPRI, LOGIN_DEFPRI);
 
-       if(p > PRIO_MAX) {
-#ifndef __NETBSD_SYSCALLS
+       if (p > PRIO_MAX) {
            rtp.type = RTP_PRIO_IDLE;
            rtp.prio = p - PRIO_MAX - 1;
-           if(rtprio(RTP_SET, 0, &rtp))
-               syslog(LOG_WARNING, "rtprio (%s): %m",
+           p = (rtp.prio > RTP_PRIO_MAX) ? 31 : p;
+           if (rtprio(RTP_SET, 0, &rtp))
+               syslog(LOG_WARNING, "rtprio '%s' (%s): %m",
+                   pwd ? pwd->pw_name : "-",
                    lc ? lc->lc_class : LOGIN_DEFCLASS);
-#endif
-       } else if(p < PRIO_MIN) {
-#ifndef __NETBSD_SYSCALLS
+       } else if (p < PRIO_MIN) {
            rtp.type = RTP_PRIO_REALTIME;
            rtp.prio = abs(p - PRIO_MIN + RTP_PRIO_MAX);
-           if(rtprio(RTP_SET, 0, &rtp))
-               syslog(LOG_WARNING, "rtprio (%s): %m",
+           p = (rtp.prio > RTP_PRIO_MAX) ? 1 : p;
+           if (rtprio(RTP_SET, 0, &rtp))
+               syslog(LOG_WARNING, "rtprio '%s' (%s): %m",
+                   pwd ? pwd->pw_name : "-",
                    lc ? lc->lc_class : LOGIN_DEFCLASS);
-#endif
        } else {
            if (setpriority(PRIO_PROCESS, 0, (int)p) != 0)
-               syslog(LOG_WARNING, "setpriority (%s): %m",
+               syslog(LOG_WARNING, "setpriority '%s' (%s): %m",
+                   pwd ? pwd->pw_name : "-",
                    lc ? lc->lc_class : LOGIN_DEFCLASS);
        }
     }
@@ -384,13 +367,13 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in
        if (setgid(pwd->pw_gid) != 0) {
            syslog(LOG_ERR, "setgid(%lu): %m", (u_long)pwd->pw_gid);
            login_close(llc);
-           return -1;
+           return (-1);
        }
        if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) {
            syslog(LOG_ERR, "initgroups(%s,%lu): %m", pwd->pw_name,
                   (u_long)pwd->pw_gid);
            login_close(llc);
-           return -1;
+           return (-1);
        }
     }
 
@@ -398,32 +381,24 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in
     if ((flags & LOGIN_SETLOGIN) && setlogin(pwd->pw_name) != 0) {
        syslog(LOG_ERR, "setlogin(%s): %m", pwd->pw_name);
        login_close(llc);
-       return -1;
+       return (-1);
     }
 
     mymask = (flags & LOGIN_SETUMASK) ? umask(LOGIN_DEFUMASK) : 0;
-    mymask = setlogincontext(lc, pwd, mymask, flags, &errcode);
-    if (errcode == -1) {
-       login_close(llc);
-       return -1;
-    }
+    mymask = setlogincontext(lc, pwd, mymask, flags);
     login_close(llc);
 
     /* This needs to be done after anything that needs root privs */
     if ((flags & LOGIN_SETUSER) && setuid(uid) != 0) {
        syslog(LOG_ERR, "setuid(%lu): %m", (u_long)uid);
-       return -1;      /* Paranoia again */
+       return (-1);    /* Paranoia again */
     }
 
     /*
      * Now, we repeat some of the above for the user's private entries
      */
-    if ((lc = login_getuserclass(pwd)) != NULL) {
-       mymask = setlogincontext(lc, pwd, mymask, flags, &errcode);
-       if (errcode == -1) {
-           login_close(lc);
-           return -1;
-       }
+    if (getuid() == uid && (lc = login_getuserclass(pwd)) != NULL) {
+       mymask = setlogincontext(lc, pwd, mymask, flags);
        login_close(lc);
     }
 
@@ -431,6 +406,5 @@ setusercontext(login_cap_t *lc, const struct passwd *pwd, uid_t uid, unsigned in
     if (flags & LOGIN_SETUMASK)
        umask(mymask);
 
-    return 0;
+    return (0);
 }
-
index 2a47883..600e560 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libutil/login_crypt.c,v 1.2.2.2 2000/10/27 01:50:31 green Exp $
- * $DragonFly: src/lib/libutil/login_crypt.c,v 1.3 2005/03/04 04:31:11 cpressey Exp $
+ * $FreeBSD: head/lib/libutil/login_crypt.c 94202 2002-04-08 11:04:56Z ru $
  */
 
 #include <sys/types.h>
 
+#include <login_cap.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
-#include "login_cap.h"
-
 const char *
 login_setcryptfmt(login_cap_t *lc, const char *def, const char *error) {
        const char *cipher;
 
-       cipher = login_getcapstr(lc, "passwd_format", (char *)def, NULL);
+       cipher = login_getcapstr(lc, "passwd_format", def, NULL);
        if (getenv("CRYPT_DEBUG") != NULL)
                fprintf(stderr, "login_setcryptfmt: "
                    "passwd_format = %s\n", cipher);
index c9691ce..8e24c2f 100644 (file)
@@ -17,7 +17,7 @@
 .\" 5. Modifications may be freely made to this file providing the above
 .\"    conditions are met.
 .\"
-.\" $FreeBSD: src/lib/libutil/login_ok.3,v 1.7.2.4 2001/12/17 10:08:32 ru Exp $
+.\" $FreeBSD: head/lib/libutil/login_ok.3 206622 2010-04-14 19:08:06Z uqs $
 .\"
 .Dd January 2, 1997
 .Dt LOGIN_OK 3
@@ -44,8 +44,9 @@ This set of functions checks to see if login is allowed based on login
 class capability entries in the login database,
 .Xr login.conf 5 .
 .Pp
+The
 .Fn auth_ttyok
-checks to see if the named tty is available to users of a specific
+function checks to see if the named tty is available to users of a specific
 class, and is either in the
 .Em ttys.allow
 access list, and not in
@@ -55,7 +56,7 @@ access list.
 An empty
 .Em ttys.allow
 list (or if no such capability exists for
-the give login class) logins via any tty device are allowed unless
+the given login class) logins via any tty device are allowed unless
 the
 .Em ttys.deny
 list exists and is non-empty, and the device or its
@@ -63,7 +64,7 @@ tty group (see
 .Xr ttys 5 )
 is not in the list.
 Access to ttys may be allowed or restricted specifically by tty device
-name, a device name which includes a wildcard (e.g. ttyD* or cuaD*),
+name, a device name which includes a wildcard (e.g.\& ttyD* or cuaD*),
 or may name a ttygroup, when group=<name> tags have been assigned in
 .Pa /etc/ttys .
 Matching of ttys and ttygroups is case sensitive.
@@ -73,8 +74,9 @@ or empty string as the
 .Ar tty
 parameter causes the function to return a non-zero value.
 .Pp
+The
 .Fn auth_hostok
-checks for any host restrictions for remote logins.
+function checks for any host restrictions for remote logins.
 The function checks on both a host name and IP address (given in its
 text form, typically n.n.n.n) against the
 .Em host.allow
@@ -88,7 +90,7 @@ The
 function is used for matching, and the matching on hostnames is case
 insensitive.
 Note that this function expects that the hostname is fully expanded
-(i.e. the local domain name added if necessary) and the IP address
+(i.e., the local domain name added if necessary) and the IP address
 is in its canonical form.
 No hostname or address lookups are attempted.
 .Pp
index 6f41be8..b0637ef 100644 (file)
  *
  * Support allow/deny lists in login class capabilities
  *
- * $FreeBSD: src/lib/libutil/login_ok.c,v 1.7.2.1 2001/01/10 21:01:30 ghelmer Exp $
- * $DragonFly: src/lib/libutil/login_ok.c,v 1.3 2005/03/04 04:31:11 cpressey Exp $
+ * $FreeBSD: head/lib/libutil/login_ok.c 154414 2006-01-16 00:28:11Z rwatson $
  */
 
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/param.h>
-
 #include <errno.h>
 #include <fnmatch.h>
+#include <login_cap.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ttyent.h>
 #include <unistd.h>
 
-#include "login_cap.h"
 
 /* -- support functions -- */
 
@@ -49,7 +47,7 @@
  */
 
 int
-login_strinlist(char **list, char const *str, int flags)
+login_strinlist(const char **list, char const *str, int flags)
 {
     int rc = 0;
 
@@ -69,7 +67,7 @@ login_strinlist(char **list, char const *str, int flags)
  */
 
 int
-login_str2inlist(char **ttlst, const char *str1, const char *str2, int flags)
+login_str2inlist(const char **ttlst, const char *str1, const char *str2, int flags)
 {
     int            rc = 0;
 
@@ -83,7 +81,7 @@ login_str2inlist(char **ttlst, const char *str1, const char *str2, int flags)
 
 /*
  * login_timelist()
- * This function is intentinoally public - reused by TAS.
+ * This function is intentionally public - reused by TAS.
  * Returns an allocated list of time periods given an array
  * of time periods in ascii form.
  */
@@ -94,7 +92,7 @@ login_timelist(login_cap_t *lc, char const *cap, int *ltno,
 {
     int                        j = 0;
     struct login_time  *lt = NULL;
-    char               **tl;
+    const char         **tl;
 
     if ((tl = login_getcaplist(lc, cap, NULL)) != NULL) {
 
@@ -134,7 +132,7 @@ login_ttyok(login_cap_t *lc, const char *tty, const char *allowcap,
     if (lc != NULL && tty != NULL && *tty != '\0') {
        struct ttyent   *te;
        char            *grp;
-       char            **ttl;
+       const char      **ttl;
 
        te = getttynam(tty);  /* Need group name */
        grp = te ? te->ty_group : NULL;
@@ -182,7 +180,7 @@ login_hostok(login_cap_t *lc, const char *host, const char *ip,
 
     if (lc != NULL &&
        ((host != NULL && *host != '\0') || (ip != NULL && *ip != '\0'))) {
-       char    **hl;
+       const char **hl;
 
        hl = login_getcaplist(lc, allowcap, NULL);
        if (hl != NULL && !login_str2inlist(hl, host, ip, FNM_CASEFOLD))
index 5b78f91..2c4a5a5 100644 (file)
@@ -17,9 +17,9 @@
 .\" 5. Modifications may be freely made to this file providing the above
 .\"    conditions are met.
 .\"
-.\" $FreeBSD: src/lib/libutil/login_times.3,v 1.16 2008/10/20 17:17:58 des Exp $
+.\" $FreeBSD: head/lib/libutil/login_times.3 206622 2010-04-14 19:08:06Z uqs $
 .\"
-.Dd October 29, 2008
+.Dd October 20, 2008
 .Dt LOGIN_TIMES 3
 .Os
 .Sh NAME
index e90fce2..f0e8ae7 100644 (file)
  *
  * Login period parsing and comparison functions.
  *
- * $FreeBSD: src/lib/libutil/login_times.c,v 1.7 1999/08/28 00:05:48 peter Exp $
- * $DragonFly: src/lib/libutil/login_times.c,v 1.3 2005/03/04 04:31:11 cpressey Exp $
+ * $FreeBSD: head/lib/libutil/login_times.c 252376 2013-06-29 15:52:48Z kientzle $
  */
 
 #include <sys/types.h>
-
 #include <ctype.h>
+#include <login_cap.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 
-#include "login_cap.h"
-
 static struct
 {
     const char *dw;
@@ -56,12 +53,12 @@ parse_time(char * ptr, u_short * t)
 
     *t = (u_short)((val / 100) * 60 + (val % 100));
 
-    return ptr;
+    return (ptr);
 }
 
 
 login_time_t
-parse_lt(const char * str)
+parse_lt(const char *str)
 {
     login_time_t    t;
 
@@ -74,10 +71,10 @@ parse_lt(const char * str)
        char            buf[64];
 
        /* Make local copy and force lowercase to simplify parsing */
-       p = strncpy(buf, str, sizeof buf);
-       buf[sizeof buf - 1] = '\0';
+       strlcpy(buf, str, sizeof buf);
        for (i = 0; buf[i]; i++)
            buf[i] = (char)tolower(buf[i]);
+       p = buf;
 
        while (isalpha(*p)) {
 
@@ -98,18 +95,18 @@ parse_lt(const char * str)
        else
            m.lt_start = 0;
        if (*p == '-')
-           p = parse_time(++p, &m.lt_end);
+           p = parse_time(p + 1, &m.lt_end);
        else
            m.lt_end = 1440;
 
        t = m;
     }
-    return t;
+    return (t);
 }
 
 
 int
-in_ltm(const login_time_t * ltm, struct tm * tt, time_t * ends)
+in_ltm(const login_time_t *ltm, struct tm *tt, time_t *ends)
 {
     int            rc = 0;
 
@@ -132,32 +129,33 @@ in_ltm(const login_time_t * ltm, struct tm * tt, time_t * ends)
            }
        }
     }
-    return rc;
+    return (rc);
 }
 
 
 int
-in_lt(const login_time_t * ltm, time_t * t)
+in_lt(const login_time_t *ltm, time_t *t)
 {
-    return in_ltm(ltm, localtime(t), t);
+
+    return (in_ltm(ltm, localtime(t), t));
 }
 
 int
-in_ltms(const login_time_t * ltm, struct tm * tm, time_t * t)
+in_ltms(const login_time_t *ltm, struct tm *tm, time_t *t)
 {
     int            i = 0;
 
     while (i < LC_MAXTIMES && ltm[i].lt_dow != LTM_NONE) {
        if (in_ltm(ltm + i, tm, t))
-           return i;
+           return (i);
        i++;
     }
-    return -1;
+    return (-1);
 }
 
 int
-in_lts(const login_time_t * ltm, time_t * t)
+in_lts(const login_time_t *ltm, time_t *t)
 {
-    return in_ltms(ltm, localtime(t), t);
-}
 
+    return (in_ltms(ltm, localtime(t), t));
+}
index 7f40086..4d5767b 100644 (file)
@@ -23,8 +23,8 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/lib/libutil/login_tty.3,v 1.5.2.3 2001/12/17 10:08:32 ru Exp $
-.\"
+.\" $FreeBSD: head/lib/libutil/login_tty.3 206622 2010-04-14 19:08:06Z uqs $
+.\" "
 .Dd December 29, 1996
 .Dt LOGIN_TTY 3
 .Os
 .Sh DESCRIPTION
 The function
 .Fn login_tty
-prepares a terminal for a new login session.  The file descriptor
+prepares a terminal for a new login session.
+The file descriptor
 .Ar fd
 passed to
 .Fn login_tty
-must be opened for reading and writing on a terminal device.  It will be
+must be opened for reading and writing on a terminal device.
+It will be
 made the controlling terminal for the calling process, after allocating
 a new session with
 .Xr setsid 2 .
 This terminal device will also be made the standard input, standard output,
 and standard error output of the calling process.
 .Sh RETURN VALUES
-.Fn Login_tty
-returns -1 if it could not make the device referenced by
+The
+.Fn login_tty
+function returns -1 if it could not make the device referenced by
 .Ar fd
 the controlling terminal of the calling process, and 0 otherwise.
 .Sh SEE ALSO
index 6f973f2..90f37c5 100644 (file)
  *
  * @(#)login_tty.c     8.1 (Berkeley) 6/4/93
  * $FreeBSD: src/lib/libutil/login_tty.c,v 1.6 1999/08/28 00:05:49 peter Exp $
- * $DragonFly: src/lib/libutil/login_tty.c,v 1.5 2007/12/30 13:44:33 matthias Exp $
  */
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
 
+#include <libutil.h>
 #include <stdlib.h>
 #include <unistd.h>
 
-#include "libutil.h"
-
 int
 login_tty(int fd)
 {
index 3fe2388..9667cbc 100644 (file)
@@ -28,7 +28,6 @@
  *
  * @(#)logout.c        8.1 (Berkeley) 6/4/93
  * $FreeBSD: src/lib/libutil/logout.c,v 1.6.2.2 2000/09/20 09:54:16 jkh Exp $
- * $DragonFly: src/lib/libutil/logout.c,v 1.5 2007/12/30 13:44:33 matthias Exp $
  */
 
 #include <sys/types.h>
@@ -39,8 +38,7 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <string.h>
-
-#include "libutil.h"
+#include <libutil.h>
 
 typedef struct utmp UTMP;
 
index 79ea1e1..a26237f 100644 (file)
@@ -41,8 +41,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <utmp.h>
-
-#include "libutil.h"
+#include <libutil.h>
 
 /* wrapper for KAME-special getnameinfo() */
 #ifndef NI_WITHSCOPEID
index 48e7116..8d70ebd 100644 (file)
@@ -1,12 +1,6 @@
-.\"    $NetBSD: pidfile.3,v 1.8 2002/10/01 19:36:30 wiz Exp $
-.\"    $DragonFly: src/lib/libutil/pidfile.3,v 1.2 2005/05/22 17:48:57 liamfoy Exp $
-.\"
-.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
+.\" Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
 .\" All rights reserved.
 .\"
-.\" This code is derived from software contributed to The NetBSD Foundation
-.\" by Jason R. Thorpe.
-.\"
 .\" Redistribution and use in source and binary forms, with or without
 .\" modification, are permitted provided that the following conditions
 .\" are met:
 .\" 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 NetBSD
-.\"        Foundation, Inc. and its contributors.
-.\" 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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.
+.\"
+.\" $FreeBSD: head/lib/libutil/pidfile.3 231193 2012-02-08 08:49:30Z pjd $
 .\"
-.Dd June 5, 1999
+.Dd February 8, 2012
 .Dt PIDFILE 3
 .Os
 .Sh NAME
-.Nm pidfile
-.Nd write a daemon pid file
+.Nm pidfile_open ,
+.Nm pidfile_write ,
+.Nm pidfile_close ,
+.Nm pidfile_remove
+.Nd "library for PID files handling"
 .Sh LIBRARY
 .Lb libutil
 .Sh SYNOPSIS
-.In sys/types.h
 .In libutil.h
+.Ft "struct pidfh *"
+.Fn pidfile_open "const char *path" "mode_t mode" "pid_t *pidptr"
+.Ft int
+.Fn pidfile_write "struct pidfh *pfh"
 .Ft int
-.Fn pidfile "const char *basename"
+.Fn pidfile_close "struct pidfh *pfh"
+.Ft int
+.Fn pidfile_remove "struct pidfh *pfh"
+.Ft int
+.Fn pidfile_fileno "struct pidfh *pfh"
 .Sh DESCRIPTION
-.Fn pidfile
-writes a file containing the process ID of the program to the
-.Pa /var/run
-directory.
-The file name has the form
-.Pa /var/run/basename.pid .
+The
+.Nm pidfile
+family of functions allows daemons to handle PID files.
+It uses
+.Xr flopen 3
+to lock a pidfile and detect already running daemons.
+.Pp
+The
+.Fn pidfile_open
+function opens (or creates) a file specified by the
+.Fa path
+argument and locks it.
+If
+.Fa pidptr
+argument is not
+.Dv NULL
+and file can not be locked, the function will use it to store a PID of an
+already running daemon or
+.Li -1
+in case daemon did not write its PID yet.
+The function does not write process' PID into the file here, so it can be
+used before
+.Fn fork Ns ing
+and exit with a proper error message when needed.
 If the
-.Ar basename
-argument is NULL,
-.Nm
-will determine the program name and use that instead.
+.Fa path
+argument is
+.Dv NULL ,
+.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid
+file will be used.
+The
+.Fn pidfile_open
+function sets the O_CLOEXEC close-on-exec flag when opening the pidfile.
+.Pp
+The
+.Fn pidfile_write
+function writes process' PID into a previously opened file.
+The file is truncated before write, so calling the
+.Fn pidfile_write
+function multiple times is supported.
+.Pp
+The
+.Fn pidfile_close
+function closes a pidfile.
+It should be used after daemon
+.Fn fork Ns s
+to start a child process.
 .Pp
-The pid file can be used as a quick reference if
-the process needs to be sent a signal.
-When the program exits, the pid file will be removed automatically, unless
-the program receives a fatal signal.
+The
+.Fn pidfile_remove
+function closes and removes a pidfile.
 .Pp
-Note that only the first invocation of
-.Nm
-causes a pid file to be written; subsequent invocations have no effect
-unless a new
-.Ar basename
-is supplied.
-If called with a new
-.Ar basename ,
-.Fn pidfile
-will remove the old pid file and write the new one.
+The
+.Fn pidfile_fileno
+function returns the file descriptor for the open pidfile.
 .Sh RETURN VALUES
-.Fn pidfile
-returns 0 on success and -1 on failure.
+The
+.Fn pidfile_open
+function returns a valid pointer to a
+.Vt pidfh
+structure on success, or
+.Dv NULL
+if an error occurs.
+If an error occurs,
+.Va errno
+will be set.
+.Pp
+.Rv -std pidfile_write pidfile_close pidfile_remove
+.Pp
+The
+.Fn pidfile_fileno
+function returns the low-level file descriptor.
+It returns
+.Li -1
+and sets
+.Va errno
+if a NULL
+.Vt pidfh
+is specified, or if the pidfile is no longer open.
+.Sh EXAMPLES
+The following example shows in which order these functions should be used.
+Note that it is safe to pass
+.Dv NULL
+to
+.Fn pidfile_write ,
+.Fn pidfile_remove ,
+.Fn pidfile_close
+and
+.Fn pidfile_fileno
+functions.
+.Bd -literal
+struct pidfh *pfh;
+pid_t otherpid, childpid;
+
+pfh = pidfile_open("/var/run/daemon.pid", 0600, &otherpid);
+if (pfh == NULL) {
+       if (errno == EEXIST) {
+               errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
+                   (intmax_t)otherpid);
+       }
+       /* If we cannot create pidfile from other reasons, only warn. */
+       warn("Cannot open or create pidfile");
+       /*
+        * Eventhough pfh is NULL we can continue, as the other pidfile_*
+        * function can handle such situation by doing nothing except setting
+        * errno to EDOOFUS.
+        */
+}
+
+if (daemon(0, 0) == -1) {
+       warn("Cannot daemonize");
+       pidfile_remove(pfh);
+       exit(EXIT_FAILURE);
+}
+
+pidfile_write(pfh);
+
+for (;;) {
+       /* Do work. */
+       childpid = fork();
+       switch (childpid) {
+       case -1:
+               syslog(LOG_ERR, "Cannot fork(): %s.", strerror(errno));
+               break;
+       case 0:
+               pidfile_close(pfh);
+               /* Do child work. */
+               break;
+       default:
+               syslog(LOG_INFO, "Child %jd started.", (intmax_t)childpid);
+               break;
+       }
+}
+
+pidfile_remove(pfh);
+exit(EXIT_SUCCESS);
+.Ed
+.Sh ERRORS
+The
+.Fn pidfile_open
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EEXIST
+Some process already holds the lock on the given pidfile, meaning that a
+daemon is already running.
+If
+.Fa pidptr
+argument is not
+.Dv NULL
+the function will use it to store a PID of an already running daemon or
+.Li -1
+in case daemon did not write its PID yet.
+.It Bq Er ENAMETOOLONG
+Specified pidfile's name is too long.
+.It Bq Er EINVAL
+Some process already holds the lock on the given pidfile, but PID read
+from there is invalid.
+.El
+.Pp
+The
+.Fn pidfile_open
+function may also fail and set
+.Va errno
+for any errors specified for the
+.Xr fstat 2 ,
+.Xr open 2 ,
+and
+.Xr read 2
+calls.
+.Pp
+The
+.Fn pidfile_write
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EDOOFUS
+Improper function use.
+Probably called before
+.Fn pidfile_open .
+.El
+.Pp
+The
+.Fn pidfile_write
+function may also fail and set
+.Va errno
+for any errors specified for the
+.Xr fstat 2 ,
+.Xr ftruncate 2 ,
+and
+.Xr write 2
+calls.
+.Pp
+The
+.Fn pidfile_close
+function may fail and set
+.Va errno
+for any errors specified for the
+.Xr close 2
+and
+.Xr fstat 2
+calls.
+.Pp
+The
+.Fn pidfile_remove
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EDOOFUS
+Improper function use.
+Probably called not from the process which made
+.Fn pidfile_write .
+.El
+.Pp
+The
+.Fn pidfile_remove
+function may also fail and set
+.Va errno
+for any errors specified for the
+.Xr close 2 ,
+.Xr fstat 2 ,
+.Xr write 2 ,
+and
+.Xr unlink 2
+system calls and the
+.Xr flopen 3
+library function.
+.Pp
+The
+.Fn pidfile_fileno
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EDOOFUS
+Improper function use.
+Probably called not from the process which used
+.Fn pidfile_open .
+.El
 .Sh SEE ALSO
-.Xr atexit 3
-.Sh HISTORY
-The
-.Nm
-function call appeared in
-.Nx 1.5 .
-.Sh BUGS
-.Fn pidfile
-uses
-.Xr atexit 3
-to ensure the pidfile is unlinked at program exit.
-However, programs that use the
-.Xr _exit 2
-function (for example, in signal handlers)
-will not trigger this behaviour.
+.Xr open 2 ,
+.Xr daemon 3 ,
+.Xr flopen 3
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm pidfile
+functionality is based on ideas from
+.An John-Mark Gurney Aq Mt jmg@FreeBSD.org .
+.Pp
+The code and manual page was written by
+.An Pawel Jakub Dawidek Aq Mt pjd@FreeBSD.org .
index 4d7a507..29e8597 100644 (file)
@@ -1,13 +1,7 @@
-/*     $NetBSD: pidfile.c,v 1.6 2001/10/20 09:20:28 taca Exp $ */
-/*     $DragonFly: src/lib/libutil/pidfile.c,v 1.2 2005/03/04 04:31:11 cpressey Exp $ */
-
 /*-
- * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
  * All rights reserved.
  *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Jason R. Thorpe and Matthias Scheler.
- *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 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 NetBSD
- *        Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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.
+ *
+ * $FreeBSD: head/lib/libutil/pidfile.c 255007 2013-08-28 21:10:37Z jilles $
  */
 
 #include <sys/param.h>
+#include <sys/stat.h>
 
-#include <paths.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <err.h>
+#include <errno.h>
+#include <libutil.h>
 
-#include "libutil.h"
+struct pidfh {
+       int     pf_fd;
+       char    pf_path[MAXPATHLEN + 1];
+       dev_t   pf_dev;
+       ino_t   pf_ino;
+};
 
-static int   pidfile_atexit_done;
-static pid_t pidfile_pid;
-static char *pidfile_basename;
-static char *pidfile_path;
+static int _pidfile_remove(struct pidfh *pfh, int freeit);
 
-static void pidfile_cleanup(void);
+static int
+pidfile_verify(const struct pidfh *pfh)
+{
+       struct stat sb;
 
-int
-pidfile(const char *basename)
+       if (pfh == NULL || pfh->pf_fd == -1)
+               return (EDOOFUS);
+       /*
+        * Check remembered descriptor.
+        */
+       if (fstat(pfh->pf_fd, &sb) == -1)
+               return (errno);
+       if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino)
+               return (EDOOFUS);
+       return (0);
+}
+
+static int
+pidfile_read(const char *path, pid_t *pidptr)
 {
-       FILE *f;
+       char buf[16], *endptr;
+       int error, fd, i;
+
+       fd = open(path, O_RDONLY | O_CLOEXEC);
+       if (fd == -1)
+               return (errno);
+
+       i = read(fd, buf, sizeof(buf) - 1);
+       error = errno;  /* Remember errno in case close() wants to change it. */
+       close(fd);
+       if (i == -1)
+               return (error);
+       else if (i == 0)
+               return (EAGAIN);
+       buf[i] = '\0';
+
+       *pidptr = strtol(buf, &endptr, 10);
+       if (endptr != &buf[i])
+               return (EINVAL);
+
+       return (0);
+}
+
+struct pidfh *
+pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
+{
+       struct pidfh *pfh;
+       struct stat sb;
+       int error, fd, len, count;
+       struct timespec rqtp;
+
+       pfh = malloc(sizeof(*pfh));
+       if (pfh == NULL)
+               return (NULL);
+
+       if (path == NULL)
+               len = snprintf(pfh->pf_path, sizeof(pfh->pf_path),
+                   "/var/run/%s.pid", getprogname());
+       else
+               len = snprintf(pfh->pf_path, sizeof(pfh->pf_path),
+                   "%s", path);
+       if (len >= (int)sizeof(pfh->pf_path)) {
+               free(pfh);
+               errno = ENAMETOOLONG;
+               return (NULL);
+       }
 
        /*
-        * Register handler which will remove the pidfile later.
+        * Open the PID file and obtain exclusive lock.
+        * We truncate PID file here only to remove old PID immediatelly,
+        * PID file will be truncated again in pidfile_write(), so
+        * pidfile_write() can be called multiple times.
         */
-       if (!pidfile_atexit_done) {
-               if (atexit(pidfile_cleanup) < 0)
-                       return -1;
-               pidfile_atexit_done = 1;
+       fd = flopen(pfh->pf_path,
+           O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NONBLOCK, mode);
+       if (fd == -1) {
+               if (errno == EWOULDBLOCK) {
+                       if (pidptr == NULL) {
+                               errno = EEXIST;
+                       } else {
+                               count = 20;
+                               rqtp.tv_sec = 0;
+                               rqtp.tv_nsec = 5000000;
+                               for (;;) {
+                                       errno = pidfile_read(pfh->pf_path,
+                                           pidptr);
+                                       if (errno != EAGAIN || --count == 0)
+                                               break;
+                                       nanosleep(&rqtp, 0);
+                               }
+                               if (errno == EAGAIN)
+                                       *pidptr = -1;
+                               if (errno == 0 || errno == EAGAIN)
+                                       errno = EEXIST;
+                       }
+               }
+               free(pfh);
+               return (NULL);
        }
 
-       if (basename == NULL)
-               basename = getprogname();
+       /*
+        * Remember file information, so in pidfile_write() we are sure we write
+        * to the proper descriptor.
+        */
+       if (fstat(fd, &sb) == -1) {
+               error = errno;
+               unlink(pfh->pf_path);
+               close(fd);
+               free(pfh);
+               errno = error;
+               return (NULL);
+       }
+
+       pfh->pf_fd = fd;
+       pfh->pf_dev = sb.st_dev;
+       pfh->pf_ino = sb.st_ino;
+
+       return (pfh);
+}
+
+int
+pidfile_write(struct pidfh *pfh)
+{
+       char pidstr[16];
+       int error, fd;
 
        /*
-        * If pidfile has already been created for the supplied basename
-        * we don't need to create a pidfile again.
+        * Check remembered descriptor, so we don't overwrite some other
+        * file if pidfile was closed and descriptor reused.
         */
-       if (pidfile_path != NULL) {
-               if (strcmp(pidfile_basename, basename) == 0)
-                       return 0;
+       errno = pidfile_verify(pfh);
+       if (errno != 0) {
                /*
-                * Remove existing pidfile if it was created by this process.
+                * Don't close descriptor, because we are not sure if it's ours.
                 */
-               pidfile_cleanup();
+               return (-1);
+       }
+       fd = pfh->pf_fd;
+
+       /*
+        * Truncate PID file, so multiple calls of pidfile_write() are allowed.
+        */
+       if (ftruncate(fd, 0) == -1) {
+               error = errno;
+               _pidfile_remove(pfh, 0);
+               errno = error;
+               return (-1);
+       }
+
+       snprintf(pidstr, sizeof(pidstr), "%u", getpid());
+       if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
+               error = errno;
+               _pidfile_remove(pfh, 0);
+               errno = error;
+               return (-1);
+       }
+
+       return (0);
+}
+
+int
+pidfile_close(struct pidfh *pfh)
+{
+       int error;
 
-               free(pidfile_path);
-               pidfile_path = NULL;
-               free(pidfile_basename);
-               pidfile_basename = NULL;
+       error = pidfile_verify(pfh);
+       if (error != 0) {
+               errno = error;
+               return (-1);
        }
 
-       pidfile_pid = getpid();
+       if (close(pfh->pf_fd) == -1)
+               error = errno;
+       free(pfh);
+       if (error != 0) {
+               errno = error;
+               return (-1);
+       }
+       return (0);
+}
 
-       pidfile_basename = strdup(basename);
-       if (pidfile_basename == NULL)
-               return -1;
+static int
+_pidfile_remove(struct pidfh *pfh, int freeit)
+{
+       int error;
 
-       /* _PATH_VARRUN includes trailing / */
-       asprintf(&pidfile_path, "%s%s.pid", _PATH_VARRUN, basename);
-       if (pidfile_path == NULL) {
-               free(pidfile_basename);
-               pidfile_basename = NULL;
-               return -1;
+       error = pidfile_verify(pfh);
+       if (error != 0) {
+               errno = error;
+               return (-1);
        }
 
-       if ((f = fopen(pidfile_path, "w")) == NULL) {
-               free(pidfile_path);
-               pidfile_path = NULL;
-               free(pidfile_basename);
-               pidfile_basename = NULL;
-               return -1;
+       if (unlink(pfh->pf_path) == -1)
+               error = errno;
+       if (close(pfh->pf_fd) == -1) {
+               if (error == 0)
+                       error = errno;
+       }
+       if (freeit)
+               free(pfh);
+       else
+               pfh->pf_fd = -1;
+       if (error != 0) {
+               errno = error;
+               return (-1);
        }
+       return (0);
+}
 
-       fprintf(f, "%d\n", pidfile_pid);
-       fclose(f);
-       return 0;
+int
+pidfile_remove(struct pidfh *pfh)
+{
+
+       return (_pidfile_remove(pfh, 1));
 }
 
-static void
-pidfile_cleanup(void)
+int
+pidfile_fileno(const struct pidfh *pfh)
 {
-       /* Only remove the pidfile if it was created by this process. */
-       if ((pidfile_path != NULL) && (pidfile_pid == getpid()))
-               unlink(pidfile_path);
+
+       if (pfh == NULL || pfh->pf_fd == -1) {
+               errno = EDOOFUS;
+               return (-1);
+       }
+       return (pfh->pf_fd);
 }
index 397ac1d..23b5190 100644 (file)
@@ -23,8 +23,8 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/lib/libutil/property.3,v 1.8.2.7 2001/12/17 10:08:32 ru Exp $
-.\"
+.\" $FreeBSD: head/lib/libutil/property.3 236965 2012-06-12 17:02:53Z des $
+.\" "
 .Dd October 7, 1998
 .Dt PROPERTIES 3
 .Os
@@ -36,7 +36,6 @@
 .Sh LIBRARY
 .Lb libutil
 .Sh SYNOPSIS
-.In sys/types.h
 .In libutil.h
 .Ft properties
 .Fn properties_read "int fd"
@@ -63,15 +62,18 @@ and returns the head of a new property list, assuming that the
 file's contents have been parsed properly, or NULL in case
 of error.
 .Pp
+The
 .Fn property_find
-Returns the associated value string for the property named
+function returns the associated value string for the property named
 .Fa name
-if found, otherwise NULL.  The value returned may be up to
+if found, otherwise NULL.
+The value returned may be up to
 .Dv PROPERTY_MAX_VALUE
 bytes in length.
 .Pp
+The
 .Fn properties_free
-is used to free the structure returned by
+function is used to free the structure returned by
 .Fn properties_read
 when it is no longer needed.
 .Sh FILE FORMAT
@@ -82,12 +84,12 @@ where
 is an alphanumeric string (and any punctuation not including the `=' character)
 and
 .Fa value
-is an arbitrary string of text terminated by a newline character.  If newlines
+is an arbitrary string of text terminated by a newline character.
+If newlines
 are desired, the entire value should be enclosed in { } (curly-bracket)
-characters.  Any line beginning with a # or ; character is assumed to
+characters.
+Any line beginning with a # or ; character is assumed to
 be a comment and will be ignored.
-.Sh SEE ALSO
-.Xr auth_getval 3
 .Sh AUTHORS
 .An Jordan Hubbard
 .Sh BUGS
index 1b8ae96..28f6490 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libutil/property.c,v 1.5.6.1 2000/11/22 03:49:49 murray Exp $
- * $DragonFly: src/lib/libutil/property.c,v 1.3 2005/03/04 04:31:11 cpressey Exp $
- *
+ * $FreeBSD: head/lib/libutil/property.c 152886 2005-11-28 16:30:16Z jhb $
  */
 
 #include <sys/types.h>
-
 #include <ctype.h>
 #include <err.h>
-#include <stdlib.h>
+#include <libutil.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
-#include "libutil.h"
-
 static properties
 property_alloc(char *name, char *value)
 {
     properties n;
 
-    n = (properties)malloc(sizeof(struct _property));
+    if ((n = (properties)malloc(sizeof(struct _property))) == NULL)
+       return (NULL);
     n->next = NULL;
-    n->name = name ? strdup(name) : NULL;
-    n->value = value ? strdup(value) : NULL;
-    return n;
+    if (name != NULL) {
+       if ((n->name = strdup(name)) == NULL) {
+           free(n);
+           return (NULL);
+       }
+    } else
+       n->name = NULL;
+    if (value != NULL) {
+       if ((n->value = strdup(value)) == NULL) {
+           free(n->name);
+           free(n);
+           return (NULL);
+       }
+    } else
+       n->value = NULL;
+    return (n);
 }
 
 properties
@@ -64,41 +74,51 @@ properties_read(int fd)
     char hold_v[PROPERTY_MAX_VALUE + 1];
     char buf[BUFSIZ * 4];
     int bp, n, v, max;
-    enum { LOOK, COMMENT, NAME, VALUE, MVALUE, COMMIT, FILL, STOP } state;
+    enum { LOOK, COMMENT, NAME, VALUE, MVALUE, COMMIT, FILL, STOP } state, last_state;
     int ch = 0, blevel = 0;
 
     n = v = bp = max = 0;
     head = ptr = NULL;
-    state = LOOK;
+    state = last_state = LOOK;
     while (state != STOP) {
        if (state != COMMIT) {
-           if (bp == max)
+           if (bp == max) {
+               last_state = state;
                state = FILL;
-           else
+           else
                ch = buf[bp++];
        }
        switch(state) {
        case FILL:
-           if ((max = read(fd, buf, sizeof buf)) <= 0) {
-               state = STOP;
-               break;
+           if ((max = read(fd, buf, sizeof buf)) < 0) {
+               properties_free(head);
+               return (NULL);
            }
-           else {
-               state = LOOK;
+           if (max == 0) {
+               state = STOP;
+           } else {
+               /*
+                * Restore the state from before the fill (which will be
+                * initialised to LOOK for the first FILL). This ensures that
+                * if we were part-way through eg., a VALUE state, when the
+                * buffer ran out, that the previous operation will be allowed
+                * to complete.
+                */
+               state = last_state;
                ch = buf[0];
-               bp = 1;
+               bp = 0;
            }
-           /* Fall through deliberately since we already have a character and state == LOOK */
+           continue;
 
        case LOOK:
-           if (isspace(ch))
+           if (isspace((unsigned char)ch))
                continue;
            /* Allow shell or lisp style comments */
            else if (ch == '#' || ch == ';') {
                state = COMMENT;
                continue;
            }
-           else if (isalnum(ch) || ch == '_') {
+           else if (isalnum((unsigned char)ch) || ch == '_') {
                if (n >= PROPERTY_MAX_NAME) {
                    n = 0;
                    state = COMMENT;
@@ -124,7 +144,7 @@ properties_read(int fd)
                v = n = 0;
                state = COMMIT;
            }
-           else if (isspace(ch))
+           else if (isspace((unsigned char)ch))
                continue;
            else if (ch == '=') {
                hold_n[n] = '\0';
@@ -141,7 +161,7 @@ properties_read(int fd)
                v = n = 0;
                state = COMMIT;
            } 
-           else if (v == 0 && isspace(ch))
+           else if (v == 0 && isspace((unsigned char)ch))
                continue;
            else if (ch == '{') {
                state = MVALUE;
@@ -183,10 +203,14 @@ properties_read(int fd)
            break;
 
        case COMMIT:
-           if (!head)
-               head = ptr = property_alloc(hold_n, hold_v);
-           else {
-               ptr->next = property_alloc(hold_n, hold_v);
+           if (head == NULL) {
+               if ((head = ptr = property_alloc(hold_n, hold_v)) == NULL)
+                   return (NULL);
+           } else {
+               if ((ptr->next = property_alloc(hold_n, hold_v)) == NULL) {
+                   properties_free(head);
+                   return (NULL);
+               }
                ptr = ptr->next;
            }
            state = LOOK;
@@ -198,20 +222,23 @@ properties_read(int fd)
            break;
        }
     }
-    return head;
+    if (head == NULL && (head = property_alloc(NULL, NULL)) == NULL)
+       return (NULL);
+
+    return (head);
 }
 
 char *
 property_find(properties list, const char *name)
 {
-    if (!list || !name || !name[0])
-       return NULL;
-    while (list) {
-       if (!strcmp(list->name, name))
-           return list->value;
+    if (list == NULL || name == NULL || !name[0])
+       return (NULL);
+    while (list != NULL) {
+       if (list->name != NULL && strcmp(list->name, name) == 0)
+           return (list->value);
        list = list->next;
     }
-    return NULL;
+    return (NULL);
 }
 
 void
index 165975c..f5a66c8 100644 (file)
@@ -23,8 +23,8 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/lib/libutil/pty.3,v 1.8.2.3 2001/12/17 10:08:32 ru Exp $
-.\"
+.\" $FreeBSD: head/lib/libutil/pty.3 206622 2010-04-14 19:08:06Z uqs $
+.\" "
 .Dd December 29, 1996
 .Dt PTY 3
 .Os
@@ -48,13 +48,13 @@ The function
 .Fn openpty
 attempts to obtain the next available pseudo-terminal from the system (see
 .Xr pty 4 ) .
-If it successfully finds one, it subsequently tries to change the
+If it successfully finds one, it subsequently changes the
 ownership of the slave device to the real UID of the current process,
 the group membership to the group
 .Dq tty
 (if such a group exists in the system), the access permissions for
-reading and writing by the owner, and for writing by the group, and to
-invalidate any current use of the line by calling
+reading and writing by the owner, and for writing by the group, and
+invalidates any current use of the line by calling
 .Xr revoke 2 .
 .Pp
 If the argument
@@ -62,7 +62,8 @@ If the argument
 is not
 .Dv NULL ,
 .Fn openpty
-copies the pathname of the slave pty to this area.  The caller is
+copies the pathname of the slave pty to this area.
+The caller is
 responsible for allocating the required space in this array.
 .Pp
 If the arguments
@@ -82,15 +83,20 @@ and
 .Fa aslave ,
 respectively.
 .Pp
-.Fn Forkpty
-first calls
+The
+.Fn forkpty
+function first calls
 .Fn openpty
-to obtain the next available pseudo-terminal from the system.  Upon success,
-it forks off a new process.  In the child process, it closes the descriptor
+to obtain the next available pseudo-terminal from the system.
+Upon success,
+it forks off a new process.
+In the child process, it closes the descriptor
 for the master side of the pty, and calls
 .Xr login_tty 3
-for the slave pty.  In the parent process, it closes the descriptor for the
-slave side of the pty.  The arguments
+for the slave pty.
+In the parent process, it closes the descriptor for the
+slave side of the pty.
+The arguments
 .Fa amaster ,
 .Fa name ,
 .Fa termp ,
@@ -99,19 +105,28 @@ and
 have the same meaning as described for
 .Fn openpty .
 .Sh RETURN VALUES
-.Fn Openpty
-returns 0 on success, or -1 on failure.
+The
+.Fn openpty
+function returns 0 on success, or -1 on failure.
 .Pp
-.Fn Forkpty
-returns -1 on failure, 0 in the slave process, and the process ID of the
-slave process in the parent process.
+The
+.Fn forkpty
+function returns -1 on failure, 0 in the slave process, and the process ID of
+the slave process in the parent process.
 .Sh ERRORS
-On failure,
+The
 .Fn openpty
-will set the global variable
-.Va errno
-to
-.Er ENOENT .
+function may fail and set the global variable
+.Dv errno
+for any of the errors specified for the
+.Xr grantpt 3 ,
+.Xr posix_openpt 3 ,
+.Xr ptsname 3 ,
+and
+.Xr unlockpt 3
+functions and the
+.Xr revoke 2
+system call.
 .Pp
 In addition to this,
 .Fn forkpty
@@ -128,13 +143,3 @@ may set it to any value as described for
 .Xr pty 4 ,
 .Xr termios 4 ,
 .Xr group 5
-.Sh BUGS
-The calling process must have an effective UID of super-user in order
-to perform all the intended actions.  No notification will occur if
-.Fn openpty
-or
-.Fn forkpty
-failed to proceed with one of the described steps, as long as they could
-at least allocate the pty at all (and create the new process in the case
-of
-.Fn forkpty ) .
index d90f775..885dd5d 100644 (file)
@@ -27,7 +27,7 @@
  * SUCH DAMAGE.
  *
  * @(#)pty.c   8.3 (Berkeley) 5/16/94
- * $FreeBSD: src/lib/libutil/pty.c,v 1.10 1999/08/28 00:05:51 peter Exp $
+ * $FreeBSD: head/lib/libutil/pty.c 184634 2008-11-04 13:50:50Z des $
  */
 
 #include <sys/types.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <grp.h>
+#include <libutil.h>
 #include <stdlib.h>
 #include <string.h>
 #include <termios.h>
 #include <unistd.h>
 
-#include "libutil.h"
-
 int
 openpty(int *amaster, int *aslave, char *name, struct termios *termp,
        struct winsize *winp)
 {
-       char line[] = "/dev/ptyXX";
-       const char *cp1, *cp2;
-       int master, slave, ttygid;
-       struct group *gr;
-       const char *slave_name;
-
-       if ((gr = getgrnam("tty")) != NULL)
-               ttygid = gr->gr_gid;
-       else
-               ttygid = -1;
+       const char *slavename;
+       int master, slave;
 
        master = posix_openpt(O_RDWR|O_NOCTTY);
        if (master == -1)
-               goto fallback;
+               return (-1);
 
-       if (grantpt(master) != 0) {
-               close(master);
-               goto fallback;
-       }
+       if (grantpt(master) == -1)
+               goto bad;
 
-       if (unlockpt(master) != 0) {
-               close(master);
-               goto fallback;
-       }
+       if (unlockpt(master) == -1)
+               goto bad;
 
-       slave_name = ptsname(master);
-       if (slave_name == NULL) {
-               close(master);
-               goto fallback;
-       }
+       slavename = ptsname(master);
+       if (slavename == NULL)
+               goto bad;
 
-       slave = open(slave_name, O_RDWR);
-       if (slave == -1) {
-               close(master);
-               goto fallback;
-       }
+       slave = open(slavename, O_RDWR);
+       if (slave == -1)
+               goto bad;
 
        *amaster = master;
        *aslave = slave;
 
        if (name)
-               strcpy(name, slave_name);
+               strcpy(name, slavename);
        if (termp)
                tcsetattr(slave, TCSAFLUSH, termp);
        if (winp)
@@ -97,38 +80,7 @@ openpty(int *amaster, int *aslave, char *name, struct termios *termp,
 
        return (0);
 
-fallback:
-       for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
-               line[8] = *cp1;
-               for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
-                       line[5] = 'p';
-                       line[9] = *cp2;
-                       if ((master = open(line, O_RDWR, 0)) == -1) {
-                               if (errno == ENOENT)
-                                       return (-1);    /* out of ptys */
-                       } else {
-                               line[5] = 't';
-                               (void) chown(line, getuid(), ttygid);
-                               (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
-                               (void) revoke(line);
-                               if ((slave = open(line, O_RDWR, 0)) != -1) {
-                                       *amaster = master;
-                                       *aslave = slave;
-                                       if (name)
-                                               strcpy(name, line);
-                                       if (termp)
-                                               (void) tcsetattr(slave,
-                                                       TCSAFLUSH, termp);
-                                       if (winp)
-                                               (void) ioctl(slave, TIOCSWINSZ,
-                                                       (char *)winp);
-                                       return (0);
-                               }
-                               (void) close(master);
-                       }
-               }
-       }
-       errno = ENOENT; /* out of ptys */
+bad:   close(master);
        return (-1);
 }
 
diff --git a/lib/libutil/pw_util.3 b/lib/libutil/pw_util.3
new file mode 100644 (file)
index 0000000..1655c9b
--- /dev/null
@@ -0,0 +1,286 @@
+.\" Copyright (c) 2012 Baptiste Daroussin <bapt@FreeBSD.org>
+.\" 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 AUTHORS 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 AUTHORS 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.
+.\"
+.\" $FreeBSD: head/lib/libutil/pw_util.3 242503 2012-11-03 00:30:22Z bapt $
+.\"
+.Dd October 30, 2012
+.Dt PW_UTIL 3
+.Os
+.Sh NAME
+.Nm pw_copy ,
+.Nm pw_dup ,
+.Nm pw_edit ,
+.Nm pw_equal ,
+.Nm pw_fini ,
+.Nm pw_init ,
+.Nm pw_make ,
+.Nm pw_make_v7 ,
+.Nm pw_mkdb ,
+.Nm pw_lock ,
+.Nm pw_scan ,
+.Nm pw_tempname ,
+.Nm pw_tmp
+.Nd "functions for passwd file handling"
+.Sh LIBRARY
+.Lb libutil
+.Sh SYNOPSIS
+.In pwd.h
+.In libutil.h
+.Ft int
+.Fn pw_copy "int ffd" "int tfd" "const struct passwd *pw" "const struct passwd *oldpw"
+.Ft "struct passwd *"
+.Fn pw_dup "const struct passwd *pw"
+.Ft int
+.Fn pw_edit "int nosetuid"
+.Ft int
+.Fn pw_equal "const struct passwd *pw1" "const struct passwd pw2"
+.Ft void
+.Fn pw_fini "void"
+.Ft int
+.Fn pw_init "const char *dir" const char *master"
+.Ft "char *"
+.Fn pw_make "const struct passwd *pw"
+.Ft "char *"
+.Fn pw_make_v7 "const struct passwd *pw"
+.Ft int
+.Fn pw_mkdb "const char *user"
+.Ft int
+.Fn pw_lock "void"
+.Ft "struct passwd *"
+.Fn pw_scan "const char *line" "int flags"
+.Ft "const char *"
+.Fn pw_tempname "void"
+.Ft int
+.Fn pw_tmp "int mfd"
+.Sh DESCRIPTION
+The
+.Fn pw_copy
+function reads a password file from
+.Vt ffd
+and writes it back out to
+.Vt tfd
+possibly with modifications:
+.Bl -dash
+.It
+If
+.Fa pw
+is
+.Dv NULL
+and
+.Fa oldpw
+is not
+.Dv NULL ,
+then the record represented by
+.Fa oldpw
+will not be copied (corresponding to user deletion).
+.It
+If
+.Fa pw
+and
+.Fa oldpw
+are not
+.Dv NULL
+then the record corresponding to
+.Fa pw
+will be replaced by the record corresponding to
+.Fa oldpw .
+.It
+If
+.Vt pw
+is set and
+.Vt oldpw
+is
+.Dv NULL
+then the record corresponding to
+.Vt pw
+will be appended (corresponding to user addition).
+.El
+.Pp
+The
+.Fn pw_copy
+function returns -1 in case of failure otherwise 0.
+.Pp
+The
+.Fn pw_dup
+function duplicates the
+.Vt struct passwd
+pointed to by
+.Fa pw
+and returns a pointer to the copy, or
+.Dv NULL
+in case of failure.
+The new
+.Vt struct passwd
+is allocated with
+.Xr malloc 3 ,
+and it is the caller's responsibility to free it with
+.Xr free 3 .
+.Pp
+The
+.Fn pw_edit
+function invokes the command specified by the
+.Ev EDITOR
+environment variable (or
+.Pa /usr/bin/vi
+if
+.Ev EDITOR
+is not defined)
+on a temporary copy of the master password file created by
+.Fn pw_tmp .
+If the file was modified,
+.Fn pw_edit
+installs it and regenerates the password database.
+The
+.Fn pw_edit
+function returns -1 in case of failure, 0 if the file was not modified,
+and a non-zero positive number if the file was modified and successfully
+installed.
+.Pp
+The
+.Fn pw_equal
+function compares two
+.Vt struct passwd
+and returns 0 if they are equal.
+.Pp
+The
+.Fn pw_fini
+function destroy the temporary file created by
+.Fn pw_tmp
+if any,
+kills any running instance of
+.Ev EDITOR
+executed by
+.Fn pw_edit
+if any,
+and closes the lock created by
+.Fn pw_lock
+if any.
+.Pp
+The
+.Fn pw_init
+initialize the static variable representing the path a password file.
+.Fa dir
+is the directory where the password file is located.
+If set to
+.Dv NULL ,
+it will default to
+.Pa /etc .
+.Fa master
+is the name of the password file.
+If set to
+.Dv NULL?
+it will default to
+.Pa master.passwd
+.Pp
+The
+.Fn pw_make
+function creates a properly formatted
+.Bx
+.Xr passwd 5
+line from a
+.Vt struct passwd ,
+and returns a pointer to the resulting string.
+The string is allocated with
+.Xr malloc 3 ,
+and it is the caller's responsibility to free it with
+.Xr free 3 .
+.Pp
+The
+.Fn pw_make_v7
+function creates a properly formatted
+.Ux V7
+.Xr passwd 5
+line from a
+.Vt struct passwd ,
+and returns a pointer to the resulting string.
+The string is allocated with
+.Xr malloc 3 ,
+and it is the caller's responsibility to free it with
+.Xr free 3 .
+.Pp
+The
+.Fn pw_mkdb
+function regenerates the password database by running
+.Xr pw_mkdb 8 .
+If
+.Fa user
+only the record corresponding to that user will be updated.
+The
+.Fn pw_mkdb
+function returns 0 in case of success and -1 in case of failure.
+.Pp
+The
+.Fn pw_lock
+function locks the master password file.
+It returns 0 in case of success and -1 in case of failure.
+.Pp
+The
+.Fn pw_scan
+function is a wrapper around the internal libc function
+.Fn __pw_scan .
+It scans the master password file for a line corresponding to the
+.Fa line
+provided and return a
+.Vt struct passwd
+if it matched an existing record.
+In case of failure, it returns
+.Dv NULL .
+Otherwise, it returns a pointer to a
+.Vt struct passwd
+containing the matching record.
+The
+.Vt struct passwd
+is allocated with
+.Xr malloc 3 ,
+and it is the caller's responsibility to free it with
+.Xr free 3 .
+.Pp
+The
+.Fn pw_tempname
+function returns the temporary name of the masterfile created via
+.Fn pw_tmp .
+.Pp
+The
+.Fn pw_tmp
+creates and opens a presumably safe temporary password file.
+If
+.Fa mfd
+is a file descriptor to an open password file, it will be read and
+written back to the temporary password file.
+Otherwise if should be set -1.
+The
+.Fn pw_tmp
+returns an open file descriptor to the temporary password file or -1 in case of
+failure.
+.Sh AUTHORS
+Portions of this software were developed for the
+.Fx
+Project by ThinkSec AS and Network Associates Laboratories, the
+Security Research Division of Network Associates, Inc.\& under
+DARPA/SPAWAR contract N66001-01-C-8035
+.Pq Dq CBOSS ,
+as part of the DARPA CHATS research program.
+.Pp
+This manual page was written by
+.An Baptiste Daroussin Aq bapt@FreeBSD.org .
index 5c4a7f6..1d4df24 100644 (file)
@@ -34,8 +34,7 @@
  * SUCH DAMAGE.
  *
  * @(#)pw_util.c       8.3 (Berkeley) 4/2/94
- * $FreeBSD: src/lib/libutil/pw_util.c,v 1.38 2007/01/09 01:02:05 imp Exp $
- * $DragonFly: src/lib/libutil/pw_util.c,v 1.2 2007/12/30 13:44:33 matthias Exp $
+ * $FreeBSD: head/lib/libutil/pw_util.c 244744 2012-12-27 20:24:44Z bapt $
  */
 
 /*
@@ -62,7 +61,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-
 #include <libutil.h>
 
 static pid_t editpid = -1;
@@ -175,11 +173,8 @@ pw_lock(void)
        for (;;) {
                struct stat st;
 
-               lockfd = open(masterpasswd, O_RDONLY, 0);
-               if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
-                       err(1, "%s", masterpasswd);
-               /* XXX vulnerable to race conditions */
-               if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) {
+               lockfd = flopen(masterpasswd, O_RDONLY|O_NONBLOCK|O_CLOEXEC, 0);
+               if (lockfd == -1) {
                        if (errno == EWOULDBLOCK) {
                                errx(1, "the password db file is busy");
                        } else {
@@ -258,11 +253,11 @@ pw_mkdb(const char *user)
                /* child */
                if (user == NULL)
                        execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
-                           "-d", passwd_dir, tempname, NULL);
+                           "-d", passwd_dir, tempname, (char *)NULL);
                else
                        execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p",
                            "-d", passwd_dir, "-u", user, tempname,
-                           NULL);
+                           (char *)NULL);
                _exit(1);
                /* NOTREACHED */
        default:
@@ -285,7 +280,7 @@ int
 pw_edit(int notsetuid)
 {
        struct sigaction sa, sa_int, sa_quit;
-       sigset_t oldsigset, sigset;
+       sigset_t oldsigset, nsigset;
        struct stat st1, st2;
        const char *editor;
        int pstat;
@@ -299,9 +294,9 @@ pw_edit(int notsetuid)
        sa.sa_flags = 0;
        sigaction(SIGINT, &sa, &sa_int);
        sigaction(SIGQUIT, &sa, &sa_quit);
-       sigemptyset(&sigset);
-       sigaddset(&sigset, SIGCHLD);
-       sigprocmask(SIG_BLOCK, &sigset, &oldsigset);
+       sigemptyset(&nsigset);
+       sigaddset(&nsigset, SIGCHLD);
+       sigprocmask(SIG_BLOCK, &nsigset, &oldsigset);
        switch ((editpid = fork())) {
        case -1:
                return (-1);
@@ -310,11 +305,11 @@ pw_edit(int notsetuid)
                sigaction(SIGQUIT, &sa_quit, NULL);
                sigprocmask(SIG_SETMASK, &oldsigset, NULL);
                if (notsetuid) {
-                       setgid(getgid());
-                       setuid(getuid());
+                       (void)setgid(getgid());
+                       (void)setuid(getuid());
                }
                errno = 0;
-               execlp(editor, basename(editor), tempname, NULL);
+               execlp(editor, basename(editor), tempname, (char *)NULL);
                _exit(errno);
        default:
                /* parent */
@@ -343,7 +338,8 @@ pw_edit(int notsetuid)
        sigprocmask(SIG_SETMASK, &oldsigset, NULL);
        if (stat(tempname, &st2) == -1)
                return (-1);
-       return (st1.st_mtime != st2.st_mtime);
+       return (st1.st_mtim.tv_sec != st2.st_mtim.tv_sec ||
+           st1.st_mtim.tv_nsec != st2.st_mtim.tv_nsec);
 }
 
 /*
@@ -402,26 +398,55 @@ pw_make(const struct passwd *pw)
            pw->pw_passwd, (uintmax_t)pw->pw_uid, (uintmax_t)pw->pw_gid,
            pw->pw_class, (uintmax_t)pw->pw_change, (uintmax_t)pw->pw_expire,
            pw->pw_gecos, pw->pw_dir, pw->pw_shell);
-       return line;
+       return (line);
 }
 
 /*
- * Copy password file from one descriptor to another, replacing or adding
- * a single record on the way.
+ * Make a passwd line (in v7 format) out of a struct passwd
+ */
+char *
+pw_make_v7(const struct passwd *pw)
+{
+       char *line;
+
+       asprintf(&line, "%s:*:%ju:%ju:%s:%s:%s", pw->pw_name,
+           (uintmax_t)pw->pw_uid, (uintmax_t)pw->pw_gid,
+           pw->pw_gecos, pw->pw_dir, pw->pw_shell);
+       return (line);
+}
+
+/*
+ * Copy password file from one descriptor to another, replacing, deleting
+ * or adding a single record on the way.
  */
 int
 pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
 {
        char buf[8192], *end, *line, *p, *q, *r, t;
        struct passwd *fpw;
+       const struct passwd *spw;
        size_t len;
        int eof, readlen;
 
+       if (old_pw == NULL && pw == NULL)
+                       return (-1);
+
+       spw = old_pw;
+       /* deleting a user */
+       if (pw == NULL) {
+               line = NULL;
+       } else {
        if ((line = pw_make(pw)) == NULL)
                return (-1);
+       }
+
+       /* adding a user */
+       if (spw == NULL)
+               spw = pw;
 
        eof = 0;
-       q = end = buf;
+       len = 0;
+       p = q = end = buf;
        for (;;) {
                /* find the end of the current line */
                for (p = q; q < end && *q != '\0'; ++q)
@@ -455,7 +480,7 @@ pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
                        if (len < (ssize_t)sizeof(buf)) {
                                eof = 1;
                                if (len > 0 && buf[len - 1] != '\n')
-                                       *end++ = '\n';
+                                       ++len, *end++ = '\n';
                        }
                        continue;
                }
@@ -484,7 +509,7 @@ pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
                 */
 
                *q = t;
-               if (fpw == NULL || strcmp(fpw->pw_name, pw->pw_name) != 0) {
+               if (fpw == NULL || strcmp(fpw->pw_name, spw->pw_name) != 0) {
                        /* nope */
                        if (fpw != NULL)
                                free(fpw);
@@ -501,11 +526,15 @@ pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
                }
                free(fpw);
 
-               /* it is, replace it */
+               /* it is, replace or remove it */
+               if (line != NULL) {
                len = strlen(line);
                if (write(tfd, line, len) != (int)len)
                        goto err;
-
+               } else {
+                       /* when removed, avoid the \n */
+                       q++;
+               }
                /* we're done, just copy the rest over */
                for (;;) {
                        if (write(tfd, q, end - q) != end - q)
@@ -523,15 +552,21 @@ pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
                goto done;
        }
 
-       /* if we got here, we have a new entry */
+       /* if we got here, we didn't find the old entry */
+       if (line == NULL) {
+               errno = ENOENT;
+               goto err;
+       }
        len = strlen(line);
        if ((size_t)write(tfd, line, len) != len ||
            write(tfd, "\n", 1) != 1)
                goto err;
  done:
+       if (line != NULL)
        free(line);
        return (0);
  err:
+       if (line != NULL)
        free(line);
        return (-1);
 }
@@ -552,43 +587,50 @@ pw_tempname(void)
 struct passwd *
 pw_dup(const struct passwd *pw)
 {
+       char *dst;
        struct passwd *npw;
        ssize_t len;
 
-       len = sizeof(*npw) +
-           (pw->pw_name ? strlen(pw->pw_name) + 1 : 0) +
-           (pw->pw_passwd ? strlen(pw->pw_passwd) + 1 : 0) +
-           (pw->pw_class ? strlen(pw->pw_class) + 1 : 0) +
-           (pw->pw_gecos ? strlen(pw->pw_gecos) + 1 : 0) +
-           (pw->pw_dir ? strlen(pw->pw_dir) + 1 : 0) +
-           (pw->pw_shell ? strlen(pw->pw_shell) + 1 : 0);
+       len = sizeof(*npw);
+       if (pw->pw_name != NULL)
+               len += strlen(pw->pw_name) + 1;
+       if (pw->pw_passwd != NULL)
+               len += strlen(pw->pw_passwd) + 1;
+       if (pw->pw_class != NULL)
+               len += strlen(pw->pw_class) + 1;
+       if (pw->pw_gecos != NULL)
+               len += strlen(pw->pw_gecos) + 1;
+       if (pw->pw_dir != NULL)
+               len += strlen(pw->pw_dir) + 1;
+       if (pw->pw_shell != NULL)
+               len += strlen(pw->pw_shell) + 1;
        if ((npw = malloc((size_t)len)) == NULL)
                return (NULL);
        memcpy(npw, pw, sizeof(*npw));
-       len = sizeof(*npw);
-       if (pw->pw_name) {
-               npw->pw_name = ((char *)npw) + len;
-               len += sprintf(npw->pw_name, "%s", pw->pw_name) + 1;
+       dst = (char *)npw + sizeof(*npw);
+       if (pw->pw_name != NULL) {
+               npw->pw_name = dst;
+               dst = stpcpy(npw->pw_name, pw->pw_name) + 1;
        }
-       if (pw->pw_passwd) {
-               npw->pw_passwd = ((char *)npw) + len;
-               len += sprintf(npw->pw_passwd, "%s", pw->pw_passwd) + 1;
+       if (pw->pw_passwd != NULL) {
+               npw->pw_passwd = dst;
+               dst = stpcpy(npw->pw_passwd, pw->pw_passwd) + 1;
        }
-       if (pw->pw_class) {
-               npw->pw_class = ((char *)npw) + len;
-               len += sprintf(npw->pw_class, "%s", pw->pw_class) + 1;
+       if (pw->pw_class != NULL) {
+               npw->pw_class = dst;
+               dst = stpcpy(npw->pw_class, pw->pw_class) + 1;
        }
-       if (pw->pw_gecos) {
-               npw->pw_gecos = ((char *)npw) + len;
-               len += sprintf(npw->pw_gecos, "%s", pw->pw_gecos) + 1;
+       if (pw->pw_gecos != NULL) {
+               npw->pw_gecos = dst;
+               dst = stpcpy(npw->pw_gecos, pw->pw_gecos) + 1;
        }
-       if (pw->pw_dir) {
-               npw->pw_dir = ((char *)npw) + len;
-               len += sprintf(npw->pw_dir, "%s", pw->pw_dir) + 1;
+       if (pw->pw_dir != NULL) {
+               npw->pw_dir = dst;
+               dst = stpcpy(npw->pw_dir, pw->pw_dir) + 1;
        }
-       if (pw->pw_shell) {
-               npw->pw_shell = ((char *)npw) + len;
-               len += sprintf(npw->pw_shell, "%s", pw->pw_shell) + 1;
+       if (pw->pw_shell != NULL) {
+               npw->pw_shell = dst;
+               dst = stpcpy(npw->pw_shell, pw->pw_shell) + 1;
        }
        return (npw);
 }
index 6cfeb68..e8e92d0 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/lib/libutil/realhostname.3,v 1.4.2.2 2001/12/17 10:08:32 ru Exp $
+.\" $FreeBSD: head/lib/libutil/realhostname.3 230234 2012-01-16 21:25:41Z ghelmer $
 .\"
 .Dd April 6, 1999
 .Dt REALHOSTNAME 3
@@ -33,8 +33,6 @@
 .Sh LIBRARY
 .Lb libutil
 .Sh SYNOPSIS
-.In sys/types.h
-.In netinet/in.h
 .In libutil.h
 .Ft int
 .Fn realhostname "char *host" "size_t hsize" "const struct in_addr *ip"
@@ -43,7 +41,8 @@ The function
 .Fn realhostname
 converts
 .Ar ip
-to the corresponding host name.  This is done by resolving
+to the corresponding host name.
+This is done by resolving
 .Ar ip
 to a host name and then ensuring that the host name resolves
 back to
@@ -54,7 +53,7 @@ must point to a buffer of at least
 .Ar hsize
 bytes, and will always be written to by this function.
 .Pp
-If the name resolution doesn't work both ways or if the host name is longer
+If the name resolution does not work both ways or if the host name is longer
 than
 .Ar hsize
 bytes,
@@ -71,8 +70,9 @@ bytes long,
 .Ar host
 will not be NUL terminated.
 .Sh RETURN VALUES
+The
 .Fn realhostname
-will return one of the following constants which are defined in
+function will return one of the following constants which are defined in
 .In libutil.h :
 .Bl -tag -width XXX -offset XXX
 .It Li HOSTNAME_FOUND
index c86ffb5..04b8a50 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libutil/realhostname.c,v 1.6.2.6 2002/06/29 18:26:37 ume Exp $
- * $DragonFly: src/lib/libutil/realhostname.c,v 1.2 2003/06/17 04:26:52 dillon Exp $
+ * $FreeBSD: head/lib/libutil/realhostname.c 185277 2008-11-25 02:15:09Z avatar $
  */
 
 #include <sys/param.h>
-
 #include <sys/socket.h>
+
 #include <netdb.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
 #include <stdio.h>
 #include <string.h>
-
-#include "libutil.h"
-
-/* wrapper for KAME-special getnameinfo() */
-#ifndef NI_WITHSCOPEID
-#define        NI_WITHSCOPEID  0
-#endif
+#include <libutil.h>
 
 struct sockinet {
        u_char  si_len;
@@ -58,7 +51,7 @@ realhostname(char *host, size_t hsize, const struct in_addr *ip)
        struct hostent *hp;
 
        result = HOSTNAME_INVALIDADDR;
-       hp = gethostbyaddr(ip, sizeof(*ip), AF_INET);
+       hp = gethostbyaddr((const char *)ip, sizeof(*ip), AF_INET);
 
        if (hp != NULL) {
                strlcpy(trimmed, hp->h_name, sizeof(trimmed));
@@ -66,8 +59,7 @@ realhostname(char *host, size_t hsize, const struct in_addr *ip)
                if (strlen(trimmed) <= hsize) {
                        char lookup[MAXHOSTNAMELEN];
 
-                       strncpy(lookup, hp->h_name, sizeof(lookup) - 1);
-                       lookup[sizeof(lookup) - 1] = '\0';
+                       strlcpy(lookup, hp->h_name, sizeof(lookup));
                        hp = gethostbyname(lookup);
                        if (hp == NULL)
                                result = HOSTNAME_INVALIDNAME;
@@ -89,12 +81,26 @@ realhostname(char *host, size_t hsize, const struct in_addr *ip)
        return result;
 }
 
+/*
+ * struct sockaddr has very lax alignment requirements, since all its
+ * members are char or equivalent.  This is a problem when trying to
+ * dereference a struct sockaddr_in6 * that was passed in as a struct
+ * sockaddr *.  Although we know (or trust) that the passed-in struct was
+ * properly aligned, the compiler doesn't, and (rightly) complains.  These
+ * macros perform the cast in a way that the compiler will accept.
+ */
+#define SOCKADDR_IN6(p) ((struct sockaddr_in6 *)(void *)(p))
+#define SOCKADDR_IN(p) ((struct sockaddr_in *)(void *)(p))
+#define SOCKINET(p) ((struct sockinet *)(void *)(p))
+
 int
 realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen)
 {
        int result, error;
        char buf[NI_MAXHOST];
-       struct sockaddr_in sin;
+#ifdef INET6
+       struct sockaddr_in lsin;
+#endif
 
        result = HOSTNAME_INVALIDADDR;
 
@@ -102,24 +108,24 @@ realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen)
        /* IPv4 mapped IPv6 addr consideraton, specified in rfc2373. */
        if (addr->sa_family == AF_INET6 &&
            addrlen == sizeof(struct sockaddr_in6) &&
-           IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)addr)->sin6_addr)) {
+           IN6_IS_ADDR_V4MAPPED(&SOCKADDR_IN6(addr)->sin6_addr)) {
                struct sockaddr_in6 *sin6;
 
-               sin6 = (struct sockaddr_in6 *)addr;
+               sin6 = SOCKADDR_IN6(addr);
 
-               memset(&sin, 0, sizeof(sin));
-               sin.sin_len = sizeof(struct sockaddr_in);
-               sin.sin_family = AF_INET;
-               sin.sin_port = sin6->sin6_port;
-               memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
+               memset(&lsin, 0, sizeof(lsin));
+               lsin.sin_len = sizeof(struct sockaddr_in);
+               lsin.sin_family = AF_INET;
+               lsin.sin_port = sin6->sin6_port;
+               memcpy(&lsin.sin_addr, &sin6->sin6_addr.s6_addr[12],
                       sizeof(struct in_addr));
-               addr = (struct sockaddr *)&sin;
-               addrlen = sin.sin_len;
+               addr = (struct sockaddr *)&lsin;
+               addrlen = lsin.sin_len;
        }
 #endif
 
        error = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
-                           NI_WITHSCOPEID | NI_NAMEREQD);
+                           NI_NAMEREQD);
        if (error == 0) {
                struct addrinfo hints, *res, *ores;
                struct sockaddr *sa;
@@ -148,15 +154,16 @@ realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen)
                        }
                        if (sa->sa_len == addrlen &&
                            sa->sa_family == addr->sa_family) {
-                               ((struct sockinet *)sa)->si_port = ((struct sockinet *)addr)->si_port;
+                               SOCKINET(sa)->si_port = SOCKINET(addr)->si_port;
 #ifdef INET6
                                /*
                                 * XXX: sin6_socpe_id may not been
                                 * filled by DNS
                                 */
                                if (sa->sa_family == AF_INET6 &&
-                                   ((struct sockaddr_in6 *)sa)->sin6_scope_id == 0)
-                                       ((struct sockaddr_in6 *)sa)->sin6_scope_id = ((struct sockaddr_in6 *)addr)->sin6_scope_id;
+                                   SOCKADDR_IN6(sa)->sin6_scope_id == 0)
+                                       SOCKADDR_IN6(sa)->sin6_scope_id =
+                                           SOCKADDR_IN6(addr)->sin6_scope_id;
 #endif
                                if (!memcmp(sa, addr, sa->sa_len)) {
                                        result = HOSTNAME_FOUND;
@@ -181,7 +188,7 @@ realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen)
        } else {
     numeric:
                if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
-                               NI_NUMERICHOST|NI_WITHSCOPEID) == 0)
+                               NI_NUMERICHOST) == 0)
                        strncpy(host, buf, hsize);
        }
 
index 3726163..c359ea4 100644 (file)
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/lib/libutil/realhostname_sa.3,v 1.2.2.3 2001/12/17 10:08:32 ru Exp $
+.\" $FreeBSD: head/lib/libutil/realhostname_sa.3 213573 2010-10-08 12:40:16Z uqs $
 .\"
 .Dd January 11, 2000
 .Dt REALHOSTNAME_SA 3
 .Os
 .Sh NAME
 .Nm realhostname_sa
-.Nd "convert an struct sockaddr to the real host name"
+.Nd "convert a"
+.Vt "struct sockaddr"
+to the real host name
 .Sh LIBRARY
 .Lb libutil
 .Sh SYNOPSIS
@@ -70,7 +72,8 @@ The function
 .Fn realhostname_sa
 converts
 .Ar addr
-to the corresponding host name.  This is done by resolving
+to the corresponding host name.
+This is done by resolving
 .Ar addr
 to a host name and then ensuring that the host name resolves
 back to
@@ -81,7 +84,7 @@ must point to a buffer of at least
 .Ar hsize
 bytes, and will always be written to by this function.
 .Pp
-If the name resolution doesn't work both ways or if the host name is longer
+If the name resolution does not work both ways or if the host name is longer
 than
 .Ar hsize
 bytes,
@@ -98,8 +101,9 @@ bytes long,
 .Ar host
 will not be NUL terminated.
 .Sh RETURN VALUES
+The
 .Fn realhostname_sa
-will return one of the following constants which are defined in
+function will return one of the following constants which are defined in
 .In libutil.h :
 .Bl -tag -width XXX -offset XXX
 .It Li HOSTNAME_FOUND
index b3271d9..77406ab 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libutil/stub.c,v 1.1.2.1 2000/10/27 01:50:31 green Exp $
- * $DragonFly: src/lib/libutil/stub.c,v 1.3 2008/10/29 22:03:12 swildner Exp $
+ * $FreeBSD: head/lib/libutil/stub.c 121193 2003-10-18 10:04:16Z markm $
  */
 
 #include <stdio.h>
@@ -36,6 +35,7 @@
  */
 
 #pragma weak crypt_set_format
+/* ARGSUSED */
 int
 crypt_set_format(const char *f __unused) {
 
index b6628c1..ecbca21 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/lib/libutil/trimdomain.3,v 1.3.2.3 2001/12/17 10:08:32 ru Exp $
+.\" $FreeBSD: head/lib/libutil/trimdomain.3 206622 2010-04-14 19:08:06Z uqs $
 .\"
 .Dd April 7, 1999
 .Dt TRIMDOMAIN 3
@@ -44,14 +44,17 @@ removes the current domain name from the passed
 .Ar fullhost
 name by writing a
 .Dv NUL
-character over the first period of the passed name.  The current domain
+character over the first period of the passed name.
+The current domain
 name is determined by calling
 .Xr gethostname 3
-and removing everything up to the first period.  The name is determined
+and removing everything up to the first period.
+The name is determined
 the first time this function is called and is cached for future use.
 .Pp
+The
 .Fn trimdomain
-will only trim the domain name if the passed
+function will only trim the domain name if the passed
 .Ar fullname
 ends with the current domain name and if the length of the resulting host
 name does not exceed
@@ -75,7 +78,8 @@ numbers to the end of the base host name and resulting in
 .Ar host : nn Op . Ar nn .
 .Sm on
 .Sh RETURN VALUES
+The
 .Fn trimdomain
-does not return a value.
+function does not return a value.
 .Sh SEE ALSO
 .Xr gethostname 3
index db08ea3..937fd76 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/*-
  * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
  *   Based on original work by Atsushi Murai <amurai@FreeBSD.org>
  * All rights reserved.
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: /repoman/r/ncvs/src/lib/libutil/trimdomain.c,v 1.5 2003/10/18 10:04:16 markm Exp $
+ * $FreeBSD: head/lib/libutil/trimdomain.c 150955 2005-10-05 04:42:20Z brooks $
  */
 
 #include <sys/param.h>
 
+#include <libutil.h>
 #include <string.h>
 #include <unistd.h>
 
-#include "libutil.h"
-
 static int     isDISP(const char *);
 
 /*-
@@ -74,18 +73,16 @@ trimdomain(char *fullhost, int hostsize)
 
        s = fullhost;
        end = s + hostsize + 1;
-       for (; (s = memchr(s, '.', (size_t)(end - s))) != NULL; s++) {
+       if ((s = memchr(s, '.', (size_t)(end - s))) != NULL) {
                if (strncasecmp(s + 1, domain, dlen) == 0) {
                        if (s[dlen + 1] == '\0') {
                                /* Found -- lose the domain. */
                                *s = '\0';
-                               break;
                        } else if (s[dlen + 1] == ':' &&
                            isDISP(s + dlen + 2) &&
                            (len = strlen(s + dlen + 1)) < (size_t)(end - s)) {
                                /* Found -- shuffle the DISPLAY back. */
                                memmove(s, s + dlen + 1, len + 1);
-                               break;
                        }
                }
        }
index 743bd5a..324befa 100644 (file)
@@ -23,8 +23,8 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/lib/libutil/uucplock.3,v 1.13.2.4 2001/12/17 10:08:32 ru Exp $
-.\"
+.\" $FreeBSD: head/lib/libutil/uucplock.3 206622 2010-04-14 19:08:06Z uqs $
+.\" "
 .Dd March 30, 1997
 .Dt UUCPLOCK 3
 .Os
@@ -103,7 +103,7 @@ The lock file could not be read via
 .Xr read 2 .
 .Pp
 .Dv UU_LOCK_CREAT_ERR :
-Can't create temporary lock file via
+Cannot create temporary lock file via
 .Xr creat 2 .
 .Pp
 .Dv UU_LOCK_WRITE_ERR :
@@ -111,7 +111,7 @@ 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
+Cannot link temporary lock file via
 .Xr link 2 .
 .Pp
 .Dv UU_LOCK_TRY_ERR :
@@ -127,7 +127,8 @@ 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
+to determine the exact error.
+Care should be made not to allow
 .Va errno
 to be changed between calls to
 .Fn uu_lock
@@ -138,7 +139,8 @@ and
 may return any of the following values:
 .Pp
 .Dv UU_LOCK_OK :
-The transfer was successful.  The specified process now holds the device
+The transfer was successful.
+The specified process now holds the device
 lock.
 .Pp
 .Dv UU_LOCK_OWNER_ERR :
@@ -152,7 +154,8 @@ If
 .Fn uu_lock
 returns one of the error values above, the global value
 .Va errno
-can be used to determine the cause.  Refer to the respective manual pages
+can be used to determine the cause.
+Refer to the respective manual pages
 for further details.
 .Pp
 .Fn uu_unlock
@@ -174,6 +177,7 @@ 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
+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.
index 47d158c..9a96e9b 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/lib/libutil/uucplock.c,v 1.12.2.1 2000/10/09 20:20:52 brian Exp $
- * $DragonFly: src/lib/libutil/uucplock.c,v 1.6 2007/12/30 13:44:33 matthias Exp $
+ * $FreeBSD: head/lib/libutil/uucplock.c 255007 2013-08-28 21:10:37Z jilles $
  *
  * @(#)uucplock.c      8.1 (Berkeley) 6/6/93
  */
 
 #include <sys/types.h>
 #include <sys/file.h>
-
 #include <dirent.h>
-#include <errno.h>
 #include <limits.h>
+#include <errno.h>
 #include <paths.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-
-#include "libutil.h"
+#include <libutil.h>
 
 #define MAXTRIES 5
 
@@ -68,8 +65,8 @@ uu_lock(const char *tty_name)
 {
        int fd, tmpfd, i;
        pid_t pid, pid_old;
-       char lckname[PATH_MAX],
-            lcktmpname[PATH_MAX];
+       char lckname[sizeof(_PATH_UUCPLOCK) + NAME_MAX],
+            lcktmpname[sizeof(_PATH_UUCPLOCK) + NAME_MAX];
        int err, uuerr;
 
        pid = getpid();
@@ -77,7 +74,8 @@ uu_lock(const char *tty_name)
                        pid);
        (void)snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT,
                        tty_name);
-       if ((tmpfd = creat(lcktmpname, 0664)) < 0)
+       if ((tmpfd = open(lcktmpname, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC,
+           0664)) < 0)
                GORET(0, UU_LOCK_CREAT_ERR);
 
        for (i = 0; i < MAXTRIES; i++) {
@@ -89,7 +87,7 @@ uu_lock(const char *tty_name)
                         * check to see if the process holding the lock
                         * still exists
                         */
-                       if ((fd = open(lckname, O_RDONLY)) < 0)
+                       if ((fd = open(lckname, O_RDONLY | O_CLOEXEC)) < 0)
                                GORET(1, UU_LOCK_OPEN_ERR);
 
                        if ((pid_old = get_pid (fd, &err)) == -1)
@@ -129,16 +127,16 @@ int
 uu_lock_txfr(const char *tty_name, pid_t pid)
 {
        int fd, err;
-       char lckname[PATH_MAX];
+       char lckname[sizeof(_PATH_UUCPLOCK) + NAME_MAX];
 
        snprintf(lckname, sizeof(lckname), _PATH_UUCPLOCK LOCKFMT, tty_name);
 
-       if ((fd = open(lckname, O_RDWR)) < 0)
+       if ((fd = open(lckname, O_RDWR | O_CLOEXEC)) < 0)
                return UU_LOCK_OWNER_ERR;
        if (get_pid(fd, &err) != getpid())
                err = UU_LOCK_OWNER_ERR;
        else {
-               lseek(fd, 0, SEEK_SET);
+               lseek(fd, (off_t)0, SEEK_SET);
                err = put_pid(fd, pid) ? 0 : UU_LOCK_WRITE_ERR;
        }
        close(fd);
@@ -149,7 +147,7 @@ uu_lock_txfr(const char *tty_name, pid_t pid)
 int
 uu_unlock(const char *tty_name)
 {
-       char tbuf[PATH_MAX];
+       char tbuf[sizeof(_PATH_UUCPLOCK) + NAME_MAX];
 
        (void)snprintf(tbuf, sizeof(tbuf), _PATH_UUCPLOCK LOCKFMT, tty_name);
        return unlink(tbuf);
@@ -203,7 +201,7 @@ put_pid(int fd, pid_t pid)
        int len;
 
        len = sprintf (buf, "%10d\n", (int)pid);
-       return write (fd, buf, len) == len;
+       return write (fd, buf, (size_t)len) == len;
 }
 
 static pid_t
@@ -216,7 +214,7 @@ get_pid(int fd, int *err)
        bytes_read = read (fd, buf, sizeof (buf) - 1);
        if (bytes_read > 0) {
                buf[bytes_read] = '\0';
-               pid = strtol (buf, NULL, 10);
+               pid = (pid_t)strtol (buf, (char **) NULL, 10);
        } else {
                pid = -1;
                *err = bytes_read ? errno : EINVAL;
index 304541a..d61dd2f 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sbin/devd/devd.cc,v 1.33 2006/09/17 22:49:26 ru Exp $
- * $DragonFly: src/sbin/devd/devd.cc,v 1.1 2008/10/03 00:26:21 hasso Exp $
+
  */
 
 /*
@@ -80,6 +80,7 @@ static const char nomatch = '?';
 static const char attach = '+';
 static const char detach = '-';
 
+static struct pidfh *pfh;
 int Dflag;
 int dflag;
 int nflag;
@@ -154,18 +155,18 @@ action::~action()
 bool
 action::do_action(config &c)
 {
-       string s = c.expand_string(_cmd);
+       string s = c.expand_string(_cmd.c_str());
        if (Dflag)
                fprintf(stderr, "Executing '%s'\n", s.c_str());
        ::system(s.c_str());
        return (true);
 }
 
-match::match(config &c, const char *var, const char *re)
-       : _var(var), _re("^")
+match::match(config &c, const char *var, const char *re) :
+       _inv(re[0] == '!'),
+       _var(var),
+       _re(c.expand_string(_inv ? re + 1 : re, "^", "$"))
 {
-       _re.append(c.expand_string(string(re)));
-       _re.append("$");
        regcomp(&_regex, _re.c_str(), REG_EXTENDED | REG_NOSUB | REG_ICASE);
 }
 
@@ -180,12 +181,21 @@ match::do_match(config &c)
        const string &value = c.get_variable(_var);
        bool retval;
 
+       /*
+        * This function gets called WAY too often to justify calling syslog()
+        * each time, even at LOG_DEBUG.  Because if syslogd isn't running, it
+        * can consume excessive amounts of systime inside of connect().  Only
+        * log when we're in -d mode.
+        */
        if (Dflag)
                fprintf(stderr, "Testing %s=%s against %s\n", _var.c_str(),
                    value.c_str(), _re.c_str());
 
        retval = (regexec(&_regex, value.c_str(), 0, NULL, 0) == 0);
-       return retval;
+       if (_inv == 1)
+               retval = (retval == 0) ? 1 : 0;
+
+       return (retval);
 }
 
 #include <sys/sockio.h>
@@ -256,7 +266,7 @@ media::do_match(config &c)
                close(s);
        }
 
-       return retval;
+       return (retval);
 }
 
 const string var_list::bogus = "_$_$_$_$_B_O_G_U_S_$_$_$_$_";
@@ -282,6 +292,12 @@ var_list::is_set(const string &var) const
 void
 var_list::set_variable(const string &var, const string &val)
 {
+       /*
+        * This function gets called WAY too often to justify calling syslog()
+        * each time, even at LOG_DEBUG.  Because if syslogd isn't running, it
+        * can consume excessive amounts of systime inside of connect().  Only
+        * log when we're in -d mode.
+        */
        if (Dflag)
                fprintf(stderr, "setting %s=%s\n", var.c_str(), val.c_str());
        _vars[var] = val;
@@ -333,6 +349,7 @@ config::parse_files_in_dir(const char *dirname)
                        parse_one_file(path);
                }
        }
+       closedir(dirp);
 }
 
 class epv_greater {
@@ -366,8 +383,37 @@ config::parse(void)
 void
 config::open_pidfile()
 {
-       if (pidfile(NULL))
-               errx(1, "devd already running");
+       pid_t otherpid;
+
+       if (_pidfile.empty())
+               return;
+       pfh = pidfile_open(_pidfile.c_str(), 0600, &otherpid);
+       if (pfh == NULL) {
+               if (errno == EEXIST)
+                       errx(1, "devd already running, pid: %d", (int)otherpid);
+               warn("cannot open pid file");
+       }
+}
+
+void
+config::write_pidfile()
+{
+
+       pidfile_write(pfh);
+}
+
+void
+config::close_pidfile()
+{
+
+       pidfile_close(pfh);
+}
+
+void
+config::remove_pidfile()
+{
+
+       pidfile_remove(pfh);
 }
 
 void
@@ -459,7 +505,7 @@ void
 config::expand_one(const char *&src, string &dst)
 {
        int count;
-       string buffer, varstr;
+       string buffer;
 
        src++;
        // $$ -> $
@@ -496,25 +542,37 @@ config::expand_one(const char *&src, string &dst)
        do {
                buffer += *src++;
        } while (is_id_char(*src));
-       buffer.append("", 1);
-       varstr = get_variable(buffer.c_str());
-       dst.append(varstr);
+       dst.append(get_variable(buffer));
 }
 
 const string
-config::expand_string(const string &s)
+config::expand_string(const char *src, const char *prepend, const char *append)
 {
-       const char *src;
+       const char *var_at;
        string dst;
 
-       src = s.c_str();
-       while (*src) {
-               if (*src == '$')
+       /*
+        * 128 bytes is enough for 2427 of 2438 expansions that happen
+        * while parsing config files, as tested on 2013-01-30.
+        */
+       dst.reserve(128);
+
+       if (prepend != NULL)
+               dst = prepend;
+
+       for (;;) {
+               var_at = strchr(src, '$');
+               if (var_at == NULL) {
+                       dst.append(src);
+                       break;
+               }
+               dst.append(src, var_at - src);
+               src = var_at;
                        expand_one(src, dst);
-               else
-                       dst.append(src++, 1);
        }
-       dst.append("", 1);
+
+       if (append != NULL)
+               dst.append(append);
 
        return (dst);
 }
@@ -608,7 +666,7 @@ config::find_and_execute(char type)
 
 }
 
-\f
+
 static void
 process_event(char *buffer)
 {
@@ -632,9 +690,13 @@ process_event(char *buffer)
                if (sp == NULL)
                        return; /* Can't happen? */
                *sp++ = '\0';
+               while (isspace(*sp))
+                       sp++;
                if (strncmp(sp, "at ", 3) == 0)
                        sp += 3;
                sp = cfg.set_vars(sp);
+               while (isspace(*sp))
+                       sp++;
                if (strncmp(sp, "on ", 3) == 0)
                        cfg.set_variable("bus", sp + 3);
                break;
@@ -645,9 +707,13 @@ process_event(char *buffer)
                        return; /* Can't happen? */
                *sp++ = '\0';
                cfg.set_variable("device-name", buffer);
+               while (isspace(*sp))
+                       sp++;
                if (strncmp(sp, "at ", 3) == 0)
                        sp += 3;
                sp = cfg.set_vars(sp);
+               while (isspace(*sp))
+                       sp++;
                if (strncmp(sp, "on ", 3) == 0)
                        cfg.set_variable("bus", sp + 3);
                break;
@@ -739,8 +805,10 @@ event_loop(void)
                        if (rv == 0) {
                                if (Dflag)
                                        fprintf(stderr, "Calling daemon\n");
-                               daemon(0, 0);
+                               cfg.remove_pidfile();
                                cfg.open_pidfile();
+                               daemon(0, 0);
+                               cfg.write_pidfile();
                                once++;
                        }
                }
@@ -774,7 +842,7 @@ event_loop(void)
        }
        close(fd);
 }
-\f
+
 /*
  * functions that the parser uses.
  */
@@ -859,7 +927,7 @@ set_variable(const char *var, const char *val)
        free(const_cast<char *>(val));
 }
 
-\f
+
 
 static void
 gensighand(int)
@@ -921,10 +989,9 @@ main(int argc, char **argv)
 
        cfg.parse();
        if (!dflag && nflag) {
-               if (Dflag)
-                       fprintf(stderr, "Calling daemon\n");
-               daemon(0, 0);
                cfg.open_pidfile();
+               daemon(0, 0);
+               cfg.write_pidfile();
        }
        signal(SIGPIPE, SIG_IGN);
        signal(SIGHUP, gensighand);
index c2d52fc..f32e7b3 100644 (file)
@@ -23,8 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sbin/devd/devd.hh,v 1.5 2007/12/21 01:00:04 imp Exp $
- * $DragonFly: src/sbin/devd/devd.hh,v 1.1 2008/10/03 00:26:21 hasso Exp $
+ * $FreeBSD: head/sbin/devd/devd.hh 247760 2013-03-04 02:21:24Z eadler $
  */
 
 #ifndef DEVD_HH
@@ -91,6 +90,7 @@ public:
        virtual bool do_match(config &);
        virtual bool do_action(config &) { return true; }
 private:
+       bool _inv;
        std::string _var;
        std::string _re;
        regex_t _regex;
@@ -144,7 +144,7 @@ private:
 class config
 {
 public:
-       config() : _pidfile("") { push_var_table(); }
+       config() { push_var_table(); }
        virtual ~config() { reset(); }
        void add_attach(int, event_proc *);
        void add_detach(int, event_proc *);
@@ -154,6 +154,7 @@ public:
        void set_pidfile(const char *);
        void reset();
        void parse();
+       void close_pidfile();
        void open_pidfile();
        void write_pidfile();
        void remove_pidfile();
@@ -161,7 +162,8 @@ public:
        void pop_var_table();
        void set_variable(const char *var, const char *val);
        const std::string &get_variable(const std::string &var);
-       const std::string expand_string(const std::string &var);
+       const std::string expand_string(const char * var, 
+           const char * prepend = NULL, const char * append = NULL);
        char *set_vars(char *);
        void find_and_execute(char);
 protected:
index 7f9edce..4af0a5b 100644 (file)
@@ -624,6 +624,7 @@ main(int ac, char* av[])
        int     daemonize = 1;
        char    *prog;
        int     logopt = LOG_NDELAY | LOG_PID;
+       struct pidfh *pfh = NULL;
 
        while ((ch = getopt(ac, av, "df:v")) != -1) {
                switch (ch) {
@@ -642,6 +643,7 @@ main(int ac, char* av[])
                }
        }
 
+       pfh = pidfile_open(NULL, 600, NULL);
        if (daemonize)
                daemon(0, 0);
 
@@ -671,7 +673,7 @@ main(int ac, char* av[])
        }
 
        restart();
-       pidfile(NULL);
+       pidfile_write(pfh);
        event_loop();
        exit(EXIT_SUCCESS);
 }
index 690c61d..423d094 100644 (file)
@@ -1,29 +1,21 @@
-/*     $OpenBSD: authpf.c,v 1.104 2007/02/24 17:35:08 beck Exp $       */
-/*     $DragonFly: src/usr.sbin/authpf/authpf.c,v 1.2 2004/12/18 22:48:02 swildner Exp $ */
+/*     $OpenBSD: authpf.c,v 1.112 2009/01/10 19:08:53 miod Exp $       */
 
 /*
  * Copyright (C) 1998 - 2007 Bob Beck (beck@openbsd.org).
  *
- * 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.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
  *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD: head/contrib/pf/authpf/authpf.c 223637 2011-06-28 11:57:25Z bz $
  */
 
 #include <sys/param.h>
@@ -95,12 +87,12 @@ main(int argc __unused, char **argv __unused)
        char            *cp;
        gid_t            gid;
        uid_t            uid;
-       char            *shell;
+       const char      *shell;
        login_cap_t     *lc;
 
        config = fopen(PATH_CONFFILE, "r");
        if (config == NULL) {
-               syslog(LOG_ERR, "can not open %s (%m)", PATH_CONFFILE);
+               syslog(LOG_ERR, "cannot open %s (%m)", PATH_CONFFILE);
                exit(1);
        }
 
@@ -150,18 +142,16 @@ main(int argc __unused, char **argv __unused)
        else
                shell = pw->pw_shell;
 
-       login_close(lc);
+
 
        if (strcmp(shell, PATH_AUTHPF_SHELL)) {
                syslog(LOG_ERR, "wrong shell for user %s, uid %u",
                    pw->pw_name, pw->pw_uid);
-               if (shell != pw->pw_shell)
-                       free(shell);
+               login_close(lc);
                goto die;
        }
 
-       if (shell != pw->pw_shell)
-               free(shell);
+       login_close(lc);
 
        /*
         * Paranoia, but this data _does_ come from outside authpf, and
@@ -173,11 +163,11 @@ main(int argc __unused, char **argv __unused)
        }
 
        if ((n = snprintf(rulesetname, sizeof(rulesetname), "%s(%ld)",
-           luser, (long)getpid())) < 0 || n >= (int)sizeof(rulesetname)) {
+           luser, (long)getpid())) < 0 || (u_int)n >= sizeof(rulesetname)) {
                syslog(LOG_INFO, "%s(%ld) too large, ruleset name will be %ld",
                    luser, (long)getpid(), (long)getpid());
                if ((n = snprintf(rulesetname, sizeof(rulesetname), "%ld",
-                   (long)getpid())) < 0 || n >= (int)sizeof(rulesetname)) {
+                   (long)getpid())) < 0 || (u_int)n >= sizeof(rulesetname)) {
                        syslog(LOG_ERR, "pid too large for ruleset name");
                        goto die;
                }
@@ -244,9 +234,9 @@ main(int argc __unused, char **argv __unused)
                }
 
                /*
-                * we try to kill the previous process and acquire the lock
+                * We try to kill the previous process and acquire the lock
                 * for 10 seconds, trying once a second. if we can't after
-                * 10 attempts we log an error and give up
+                * 10 attempts we log an error and give up.
                 */
                if (++lockcnt > 10) {
                        syslog(LOG_ERR, "cannot kill previous authpf (pid %d)",
@@ -362,6 +352,8 @@ read_config(FILE *f)
                }
                i++;
                len = strlen(buf);
+               if (len == 0)
+                       continue;
                if (buf[len - 1] != '\n' && !feof(f)) {
                        syslog(LOG_ERR, "line %d too long in %s", i,
                            PATH_CONFFILE);
index 4419342..0cccc2d 100644 (file)
@@ -354,9 +354,12 @@ main(int argc, char **argv)
 #ifdef DEBUG
        if (f_debug == 0) {
 #endif
+               struct pidfh *pfh = NULL;
+
+               pfh = pidfile_open(NULL, 600, NULL);
                if (daemon(0, 0) == -1)
                        err(1, "daemon failed");
-               pidfile(NULL);
+               pidfile_write(pfh);
 #ifdef DEBUG
        }
 #endif
index 5d689e7..32a475f 100644 (file)
@@ -62,6 +62,8 @@ main(int argc, char *argv[])
        mode_t          mode;
        struct kevent   change;
        struct timespec timeout = { 0, 0 };
+       struct pidfh    *pfh = NULL;
+       const char      *pidfile = NULL;
 
        bdaddr_copy(&bdaddr, BDADDR_ANY);
        mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
@@ -129,9 +131,13 @@ main(int argc, char *argv[])
                exit(EXIT_FAILURE);
        }
 
-       if (detach && pidfile(NULL) < 0) {
-               syslog(LOG_ERR, "Could not create PID file: %m");
-               exit(EXIT_FAILURE);
+       if (detach) {
+               pfh = pidfile_open(pidfile, 600, NULL);
+               if (pfh == NULL) {
+                       syslog(LOG_ERR, "Could not create PID file: %m");
+                       exit(EXIT_FAILURE);
+               }
+               pidfile_write(pfh);
        }
 
        read_config_file();
index 86a43af..f0f70eb 100644 (file)
@@ -566,6 +566,7 @@ main(int argc, char **argv)
        int ch, np, ret, Xflag = 0;
        pcap_handler phandler = dump_packet;
        const char *errstr = NULL;
+       struct pidfh *pfh = NULL;
        char *pidf = NULL;
 
        ret = 0;
@@ -625,11 +626,12 @@ main(int argc, char **argv)
 
        if (!Debug) {
                openlog("pflogd", LOG_PID | LOG_CONS, LOG_DAEMON);
+               pfh = pidfile_open(pidf, 0600, NULL);
                if (daemon(0, 0)) {
                        logmsg(LOG_WARNING, "Failed to become daemon: %s",
                            strerror(errno));
                }
-               pidfile(pidf);
+               pidfile_write(pfh);
        }
 
        umask(S_IRWXG | S_IRWXO);
index ab23d6c..d7c00ce 100644 (file)
@@ -227,8 +227,10 @@ main(int argc, char *argv[])
        if (argc > 0)
                usage();
 #ifndef DEBUG
+        struct pidfh *pfh = NULL;
+        pfh = pidfile_open(NULL, 600, NULL);
        daemon(1, 0);
-       pidfile(NULL);
+        pidfile_write(pfh);
 #endif
        signal(SIGHUP, hup);
        openlog("rwhod", LOG_PID, LOG_DAEMON);
index 29a488e..2572247 100644 (file)
@@ -1,19 +1,16 @@
 #      @(#)Makefile    8.1 (Berkeley) 6/6/93
-# $FreeBSD: src/usr.sbin/syslogd/Makefile,v 1.14 2008/12/17 16:51:40 obrien Exp $
-# $DragonFly: src/usr.sbin/syslogd/Makefile,v 1.3 2004/08/09 20:11:19 dillon Exp $
+# $FreeBSD: head/usr.sbin/syslogd/Makefile 211055 2010-08-08 02:45:14Z imp $
 
-.PATH: ${.CURDIR}/../../usr.bin/wall ${.CURDIR}/../nscd ${.CURDIR}/../../usr.bin/who
+.PATH: ${.CURDIR}/../../usr.bin/wall
 
 PROG=  syslogd
 MAN=   syslog.conf.5 syslogd.8
-SRCS=  pidfile.c syslogd.c ttymsg.c utmpentry.c
+SRCS=  syslogd.c ttymsg.c
 
 DPADD= ${LIBUTIL}
 LDADD= -lutil
 
 CFLAGS+= -DINET6
 CFLAGS+= -I${.CURDIR}/../../usr.bin/wall
-CFLAGS+= -I${.CURDIR}/../../usr.bin/who -DSUPPORT_UTMP -DSUPPORT_UTMPX
-
 
 .include <bsd.prog.mk>
index 2dc61a8..29bbb53 100644 (file)
  * 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
+ * 3. 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.
  *
@@ -31,6 +27,7 @@
  * SUCH DAMAGE.
  *
  *     @(#)pathnames.h 8.1 (Berkeley) 6/6/93
+ * $FreeBSD: head/usr.sbin/syslogd/pathnames.h 133249 2004-08-07 04:28:56Z imp $
  */
 
 #include <paths.h>
index 5fa878c..51fb70d 100644 (file)
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)syslog.conf.5      8.1 (Berkeley) 6/9/93
-.\" $FreeBSD: src/usr.sbin/syslogd/syslog.conf.5,v 1.46 2008/12/23 17:39:24 trhodes Exp $
-.\" $DragonFly: src/usr.sbin/syslogd/syslog.conf.5,v 1.10 2008/04/20 21:14:39 swildner Exp $
+.\" $FreeBSD: head/usr.sbin/syslogd/syslog.conf.5 240409 2012-09-12 16:58:42Z eadler $
 .\"
-.Dd December 23, 2008
+.Dd September 12, 2012
 .Dt SYSLOG.CONF 5
 .Os
 .Sh NAME
@@ -323,7 +322,7 @@ A pathname (beginning with a leading slash).
 Selected messages are appended to the file.
 .Pp
 To ensure that kernel messages are written to disk promptly,
-.Xr syslogd 8
+.Nm
 calls
 .Xr fsync 2
 after writing messages from the kernel.
@@ -348,6 +347,14 @@ If a port number is added after a colon
 .Pq Ql :\&
 then that port will be used as the destination port
 rather than the usual syslog port.
+IPv6 addresses can be used
+by surrounding the address portion with
+square brackets
+.Po
+.Ql [\&
+and
+.Ql ]\&
+.Pc .
 .It
 A comma separated list of users.
 Selected messages are written to those users
@@ -356,14 +363,6 @@ if they are logged in.
 An asterisk.
 Selected messages are written to all logged-in users.
 .It
-A percent sign
-.Pq Dq \&% ,
-followed by a pathname (beginning with a leading slash).  Selected messages
-are written to a circular log file.
-See
-.Xr clog 8
-for a discussion of circular log files.
-.It
 A vertical bar
 .Pq Dq \&| ,
 followed by a command to pipe the selected
@@ -485,16 +484,16 @@ uucp,news.crit                                            /var/log/spoolerr
 # Pipe all authentication messages to a filter.
 auth.*                                 |exec /usr/local/sbin/authfilter
 
-# Save ftpd transactions along with mail and news
-!ftpd
-*.*                                                    /var/log/spoolerr
-
 # Log all security messages to a separate file.
 security.*                                             /var/log/security
 
 # Log all writes to /dev/console to a separate file.
 console.*                                              /var/log/console.log
 
+# Save ftpd transactions along with mail and news
+!ftpd
+*.*                                                    /var/log/spoolerr
+
 # Log ipfw messages without syncing after every message.
 !ipfw
 *.*                                                    -/var/log/ipfw
@@ -521,7 +520,6 @@ implement the same set of facilities.
 The facilities
 authpriv, cron, ftp, and ntp that are known to this implementation
 might be absent on the target system.
-Even worse, DEC
-.Ux
-uses facility number 10 (which is authpriv in this implementation) to
+Even worse, DEC UNIX uses
+facility number 10 (which is authpriv in this implementation) to
 log events for their AdvFS file system.
index 1742ede..eef8428 100644 (file)
@@ -26,7 +26,7 @@
 .\" SUCH DAMAGE.
 .\"
 .\"     @(#)syslogd.8  8.1 (Berkeley) 6/6/93
-.\" $FreeBSD: src/usr.sbin/syslogd/syslogd.8,v 1.64 2008/12/07 18:45:30 trhodes Exp $
+.\" $FreeBSD: head/usr.sbin/syslogd/syslogd.8 236509 2012-06-03 11:29:48Z joel $
 .\"
 .Dd May 13, 2008
 .Dt SYSLOGD 8
@@ -36,7 +36,7 @@
 .Nd log systems messages
 .Sh SYNOPSIS
 .Nm
-.Op Fl 468ACcdknosuv
+.Op Fl 468ACcdkNnosTuv
 .Op Fl a Ar allowed_peer
 .Op Fl b Ar bind_address
 .Op Fl f Ar config_file
@@ -171,10 +171,29 @@ The
 options are ignored if the
 .Fl s
 option is also specified.
-.It Fl b Ar bind_address
-Specify one specific IP address or hostname to bind to.
-If a hostname is specified,
-the IPv4 or IPv6 address which corresponds to it is used.
+.It Xo
+.Fl b
+.Sm off
+.Ar bind_address Op : Ar service
+.Sm on
+.Xc
+.It Xo
+.Fl b
+.Sm off
+.Li : Ar service
+.Sm on
+.Xc
+Bind to a specific address and/or port.
+The address can be specified as a hostname,
+and the port as a service name.
+If an IPv6 address is specified, it should be enclosed with
+.Ql \&[
+and
+.Ql \&] .
+The default
+.Ar service
+is
+.Ql syslog .
 .It Fl C
 Create log files that do not exist (permission is set to
 .Li 0600 ) .
@@ -208,6 +227,13 @@ facility is reserved for messages read directly from
 Select the number of minutes between
 .Dq mark
 messages; the default is 20 minutes.
+.It Fl N
+Disable binding on UDP sockets.  RFC 3164 recommends that outgoing
+syslogd messages should originate from the privileged port, this
+option
+.Em disables
+the recommended behavior.  This option inherits
+.Fl s .
 .It Fl n
 Disable dns query for every request.
 .It Fl o
index 9e57474..7f77fbc 100644 (file)
@@ -27,8 +27,7 @@
  * SUCH DAMAGE.
  *
  * @(#)syslogd.c       8.3 (Berkeley) 4/4/94
- * $FreeBSD: src/usr.sbin/syslogd/syslogd.c,v 1.163 2008/12/19 18:27:51 delphij Exp $
- * $DragonFly: src/usr.sbin/syslogd/syslogd.c,v 1.6 2007/08/09 02:17:46 dillon Exp $
+ * $FreeBSD: head/usr.sbin/syslogd/syslogd.c 258077 2013-11-13 01:04:02Z ian $
  */
 
 /*
@@ -55,7 +54,6 @@
  *   by Peter da Silva.
  * -u and -v by Harlan Stenn.
  * Priority comparison code by Harlan Stenn.
- * Ring buffer code by Jeff Wheelhouse.
  */
 
 #define        MAXLINE         1024            /* maximum line length */
 #define        DEFSPRI         (LOG_KERN|LOG_CRIT)
 #define        TIMERINTVL      30              /* interval for checking flush, mark */
 #define        TTYMSGTIME      1               /* timeout passed to ttymsg */
+#define        RCVBUF_MINSIZE  (80 * 1024)     /* minimum size of dgram rcv buffer */
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
+#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
@@ -76,7 +76,6 @@
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/syslimits.h>
-#include <sys/mman.h>
 #include <sys/types.h>
 
 #include <netinet/in.h>
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
-#include "utmpentry.h"
+#include <utmpx.h>
 
 #include "pathnames.h"
 #include "ttymsg.h"
-#include "../clog/clog.h"
-#include "../nscd/pidfile.h"
 
 #define SYSLOG_NAMES
 #include <sys/syslog.h>
 const char     *ConfFile = _PATH_LOGCONF;
 const char     *PidFile = _PATH_LOGPID;
 const char     ctty[] = _PATH_CONSOLE;
-const char     ring_magic[] = "CLOG";
 
 #define        dprintf         if (Debug) printf
 
@@ -164,7 +160,7 @@ struct filed {
 #define PRI_GT 0x4
        char    *f_program;             /* program this applies to */
        union {
-               char    f_uname[MAXUNAMES][32+1];
+               char    f_uname[MAXUNAMES][MAXLOGNAME];
                struct {
                        char    f_hname[MAXHOSTNAMELEN];
                        struct addrinfo *f_addr;
@@ -175,11 +171,6 @@ struct filed {
                        char    f_pname[MAXPATHLEN];
                        pid_t   f_pid;
                } f_pipe;
-               struct {
-                       char    f_rname[MAXPATHLEN];
-                       struct clog_footer *f_footer;
-                       size_t  f_size;
-               } f_ring;
        } f_un;
        char    f_prevline[MAXSVLINE];          /* last message logged */
        char    f_lasttime[16];                 /* time of last occurrence */
@@ -258,12 +249,10 @@ int       repeatinterval[] = { 30, 120, 600 };    /* # of secs before flush */
 #define F_USERS                5               /* list of users */
 #define F_WALL         6               /* everyone logged on */
 #define F_PIPE         7               /* pipe to program */
-#define F_RING         8               /* ring buffer (circular log) */
 
-const char *TypeNames[] = {
+const char *TypeNames[8] = {
        "UNUSED",       "FILE",         "TTY",          "CONSOLE",
-       "FORW",         "USERS",        "WALL",         "PIPE",
-       "RING"
+       "FORW",         "USERS",        "WALL",         "PIPE"
 };
 
 static struct filed *Files;    /* Log files that we write to */
@@ -278,6 +267,7 @@ static int  fklog = -1;     /* /dev/klog */
 static int     Initialized;    /* set when we have initialized ourselves */
 static int     MarkInterval = 20 * 60; /* interval between marks in seconds */
 static int     MarkSeq;        /* mark sequence number */
+static int     NoBind;         /* don't bind() as suggested by RFC 3164 */
 static int     SecureMode;     /* when true, receive only unix domain socks */
 #ifdef INET6
 static int     family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */
@@ -311,13 +301,13 @@ static void       cfline(const char *, struct filed *,
 static const char *cvthname(struct sockaddr *);
 static void    deadq_enter(pid_t, const char *);
 static int     deadq_remove(pid_t);
-static int     decode(const char *, CODE *);
+static int     decode(const char *, const CODE *);
 static void    die(int);
 static void    dodie(int);
 static void    dofsync(void);
 static void    domark(int);
 static void    fprintlog(struct filed *, int, const char *);
-static int     *socksetup(int, const char *);
+static int     *socksetup(int, char *);
 static void    init(int);
 static void    logerror(const char *);
 static void    logmsg(int, const char *, const char *, int);
@@ -327,8 +317,6 @@ static int  skip_message(const char *, const char *, int);
 static void    printline(const char *, char *, int);
 static void    printsys(char *);
 static int     p_open(const char *, pid_t *);
-ssize_t                rbwrite(struct filed *, char *, size_t);
-ssize_t                rbwritev(struct filed *, struct iovec *, int);
 static void    readklog(void);
 static void    reapchild(int);
 static void    usage(void);
@@ -337,7 +325,7 @@ static void unmapped(struct sockaddr *);
 static void    wallmsg(struct filed *, struct iovec *, const int iovlen);
 static int     waitdaemon(int, int, int);
 static void    timedout(int);
-static void    double_rbuf(int);
+static void    increase_rcvbuf(int);
 
 int
 main(int argc, char *argv[])
@@ -347,7 +335,8 @@ main(int argc, char *argv[])
        struct sockaddr_storage frominet;
        fd_set *fdsr = NULL;
        char line[MAXLINE + 1];
-       const char *bindhostname, *hname;
+       char *bindhostname;
+       const char *hname;
        struct timeval tv, *tvp;
        struct sigaction sact;
        struct funix *fx, *fx1;
@@ -356,7 +345,7 @@ main(int argc, char *argv[])
        socklen_t len;
 
        bindhostname = NULL;
-       while ((ch = getopt(argc, argv, "468Aa:b:cCdf:kl:m:nop:P:sS:Tuv"))
+       while ((ch = getopt(argc, argv, "468Aa:b:cCdf:kl:m:nNop:P:sS:Tuv"))
            != -1)
                switch (ch) {
                case '4':
@@ -435,6 +424,10 @@ main(int argc, char *argv[])
                case 'm':               /* mark interval */
                        MarkInterval = atoi(optarg) * 60;
                        break;
+               case 'N':
+                       NoBind = 1;
+                       SecureMode = 1;
+                       break;
                case 'n':
                        resolve = 0;
                        break;
@@ -494,12 +487,12 @@ main(int argc, char *argv[])
                endservent();
 
        consfile.f_type = F_CONSOLE;
-       strlcpy(consfile.f_un.f_fname, ctty + sizeof _PATH_DEV - 1,
+       (void)strlcpy(consfile.f_un.f_fname, ctty + sizeof _PATH_DEV - 1,
            sizeof(consfile.f_un.f_fname));
-       strlcpy(bootfile, getbootfile(), sizeof(bootfile));
-       signal(SIGTERM, dodie);
-       signal(SIGINT, Debug ? dodie : SIG_IGN);
-       signal(SIGQUIT, Debug ? dodie : SIG_IGN);
+       (void)strlcpy(bootfile, getbootfile(), sizeof(bootfile));
+       (void)signal(SIGTERM, dodie);
+       (void)signal(SIGINT, Debug ? dodie : SIG_IGN);
+       (void)signal(SIGQUIT, Debug ? dodie : SIG_IGN);
        /*
         * We don't want the SIGCHLD and SIGHUP handlers to interfere
         * with each other; they are likely candidates for being called
@@ -511,10 +504,10 @@ main(int argc, char *argv[])
        sact.sa_handler = reapchild;
        sact.sa_mask = mask;
        sact.sa_flags = SA_RESTART;
-       sigaction(SIGCHLD, &sact, NULL);
-       signal(SIGALRM, domark);
-       signal(SIGPIPE, SIG_IGN);       /* We'll catch EPIPE instead. */
-       alarm(TIMERINTVL);
+       (void)sigaction(SIGCHLD, &sact, NULL);
+       (void)signal(SIGALRM, domark);
+       (void)signal(SIGPIPE, SIG_IGN); /* We'll catch EPIPE instead. */
+       (void)alarm(TIMERINTVL);
 
        TAILQ_INIT(&deadq_head);
 
@@ -522,15 +515,15 @@ main(int argc, char *argv[])
 #define SUN_LEN(unp) (strlen((unp)->sun_path) + 2)
 #endif
        STAILQ_FOREACH_MUTABLE(fx, &funixes, next, fx1) {
-               unlink(fx->name);
+               (void)unlink(fx->name);
                memset(&sunx, 0, sizeof(sunx));
                sunx.sun_family = AF_LOCAL;
-               strlcpy(sunx.sun_path, fx->name, sizeof(sunx.sun_path));
+               (void)strlcpy(sunx.sun_path, fx->name, sizeof(sunx.sun_path));
                fx->s = socket(PF_LOCAL, SOCK_DGRAM, 0);
                if (fx->s < 0 ||
                    bind(fx->s, (struct sockaddr *)&sunx, SUN_LEN(&sunx)) < 0 ||
                    chmod(fx->name, fx->mode) < 0) {
-                       snprintf(line, sizeof line,
+                       (void)snprintf(line, sizeof line,
                                        "cannot create %s", fx->name);
                        logerror(line);
                        dprintf("cannot create %s (%d)\n", fx->name, errno);
@@ -540,8 +533,8 @@ main(int argc, char *argv[])
                                STAILQ_REMOVE(&funixes, fx, funix, next);
                                continue;
                        }
-                       double_rbuf(fx->s);
                }
+               increase_rcvbuf(fx->s);
        }
        if (SecureMode <= 1)
                finet = socksetup(family, bindhostname);
@@ -579,7 +572,7 @@ main(int argc, char *argv[])
        sact.sa_handler = init;
        sact.sa_mask = mask;
        sact.sa_flags = SA_RESTART;
-       sigaction(SIGHUP, &sact, NULL);
+       (void)sigaction(SIGHUP, &sact, NULL);
 
        tvp = &tv;
        tv.tv_sec = tv.tv_usec = 0;
@@ -918,7 +911,7 @@ logmsg(int pri, const char *msg, const char *from, int flags)
            msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
                flags |= ADDDATE;
 
-       time(&now);
+       (void)time(&now);
        if (flags & ADDDATE) {
                timestamp = ctime(&now) + 4;
        } else {
@@ -941,7 +934,7 @@ logmsg(int pri, const char *msg, const char *from, int flags)
 
        /* Check maximum facility number. */
        if (fac > LOG_NFACILITIES) {
-               sigsetmask(omask);
+               (void)sigsetmask(omask);
                return;
        }
 
@@ -974,12 +967,12 @@ logmsg(int pri, const char *msg, const char *from, int flags)
                f->f_file = open(ctty, O_WRONLY | O_NONBLOCK, 0);
 
                if (f->f_file >= 0) {
-                       strlcpy(f->f_lasttime, timestamp,
+                       (void)strlcpy(f->f_lasttime, timestamp,
                                sizeof(f->f_lasttime));
                        fprintlog(f, flags, msg);
-                       close(f->f_file);
+                       (void)close(f->f_file);
                }
-               sigsetmask(omask);
+               (void)sigsetmask(omask);
                return;
        }
        for (f = Files; f; f = f->f_next) {
@@ -1014,7 +1007,7 @@ logmsg(int pri, const char *msg, const char *from, int flags)
                    (flags & MARK) == 0 && msglen == f->f_prevlen &&
                    f->f_prevline && !strcmp(msg, f->f_prevline) &&
                    !strcasecmp(from, f->f_prevhost)) {
-                       strlcpy(f->f_lasttime, timestamp,
+                       (void)strlcpy(f->f_lasttime, timestamp,
                                sizeof(f->f_lasttime));
                        f->f_prevcount++;
                        dprintf("msg repeated %d times, %ld sec of %d\n",
@@ -1027,22 +1020,23 @@ logmsg(int pri, const char *msg, const char *from, int flags)
                         * in the future.
                         */
                        if (now > REPEATTIME(f)) {
-                               fprintlog(f, flags, NULL);
+                               fprintlog(f, flags, (char *)NULL);
                                BACKOFF(f);
                        }
                } else {
                        /* new line, save it */
                        if (f->f_prevcount)
-                               fprintlog(f, 0, NULL);
+                               fprintlog(f, 0, (char *)NULL);
                        f->f_repeatcount = 0;
                        f->f_prevpri = pri;
-                       strlcpy(f->f_lasttime, timestamp,
+                       (void)strlcpy(f->f_lasttime, timestamp,
                                sizeof(f->f_lasttime));
-                       strlcpy(f->f_prevhost, from, sizeof(f->f_prevhost));
+                       (void)strlcpy(f->f_prevhost, from,
+                           sizeof(f->f_prevhost));
                        if (msglen < MAXSVLINE) {
                                f->f_prevlen = msglen;
-                               strlcpy(f->f_prevline, msg, sizeof(f->f_prevline));
-                               fprintlog(f, flags, NULL);
+                               (void)strlcpy(f->f_prevline, msg, sizeof(f->f_prevline));
+                               fprintlog(f, flags, (char *)NULL);
                        } else {
                                f->f_prevline[0] = 0;
                                f->f_prevlen = 0;
@@ -1050,7 +1044,7 @@ logmsg(int pri, const char *msg, const char *from, int flags)
                        }
                }
        }
-       sigsetmask(omask);
+       (void)sigsetmask(omask);
 }
 
 static void
@@ -1062,7 +1056,7 @@ dofsync(void)
                if ((f->f_type == F_FILE) &&
                    (f->f_flags & FFLAG_NEEDSYNC)) {
                        f->f_flags &= ~FFLAG_NEEDSYNC;
-                       fsync(f->f_file);
+                       (void)fsync(f->f_file);
                }
        }
 }
@@ -1090,7 +1084,8 @@ fprintlog(struct filed *f, int flags, const char *msg)
                v->iov_len = snprintf(greetings, sizeof greetings,
                    "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
                    f->f_prevhost, f->f_lasttime);
-               if (v->iov_len > 0)
+               if (v->iov_len >= sizeof greetings)
+                       v->iov_len = sizeof greetings - 1;
                        v++;
                v->iov_base = nul;
                v->iov_len = 0;
@@ -1114,7 +1109,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
                char p_n[5];    /* Hollow laugh */
 
                if (LogFacPri > 1) {
-                 CODE *c;
+                 const CODE *c;
 
                  for (c = facilitynames; c->c_name; c++) {
                    if (c->c_val == fac) {
@@ -1232,8 +1227,10 @@ fprintlog(struct filed *f, int flags, const char *msg)
                                switch (errno) {
                                case ENOBUFS:
                                case ENETDOWN:
+                               case ENETUNREACH:
                                case EHOSTUNREACH:
                                case EHOSTDOWN:
+                               case EADDRNOTAVAIL:
                                        break;
                                /* case EBADF: */
                                /* case EACCES: */
@@ -1244,7 +1241,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
                                /* case ENOBUFS: */
                                /* case ECONNREFUSED: */
                                default:
-                                       dprintf("removing entry\n");
+                                       dprintf("removing entry: errno=%d\n", e);
                                        f->f_type = F_UNUSED;
                                        break;
                                }
@@ -1264,7 +1261,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
                         */
                        if (errno != ENOSPC) {
                                int e = errno;
-                               close(f->f_file);
+                               (void)close(f->f_file);
                                f->f_type = F_UNUSED;
                                errno = e;
                                logerror(f->f_un.f_fname);
@@ -1275,21 +1272,6 @@ fprintlog(struct filed *f, int flags, const char *msg)
                }
                break;
 
-       case F_RING:
-               dprintf(" %s\n", f->f_un.f_ring.f_rname);
-               v->iov_base = lf;
-               v->iov_len = 1;
-               if (rbwritev(f, iov, 7) == -1) {
-                       int e = errno;
-                       munmap(f->f_un.f_ring.f_footer,
-                               sizeof(struct clog_footer));
-                       close(f->f_file);
-                       f->f_type = F_UNUSED;
-                       errno = e;
-                       logerror(f->f_un.f_fname);
-               }
-               break;
-
        case F_PIPE:
                dprintf(" %s\n", f->f_un.f_pipe.f_pname);
                v->iov_base = lf;
@@ -1304,7 +1286,7 @@ fprintlog(struct filed *f, int flags, const char *msg)
                }
                if (writev(f->f_file, iov, IOV_SIZE) < 0) {
                        int e = errno;
-                       close(f->f_file);
+                       (void)close(f->f_file);
                        if (f->f_un.f_pipe.f_pid > 0)
                                deadq_enter(f->f_un.f_pipe.f_pid,
                                            f->f_un.f_pipe.f_pname);
@@ -1355,26 +1337,20 @@ static void
 wallmsg(struct filed *f, struct iovec *iov, const int iovlen)
 {
        static int reenter;                     /* avoid calling ourselves */
-
-       struct utmpentry *ep;
+       struct utmpx *ut;
        int i;
        const char *p;
 
        if (reenter++)
                return;
-
-       getutentries(NULL, &ep);
-       if (ep == NULL) {
-               logerror("getutentries");
-               reenter = 0;
-               return;
-       }
+       setutxent();
        /* NOSTRICT */
-       for (; ep; ep = ep->next) {
-               /* We must use strncpy since ut_* may not be NUL terminated. */
+       while ((ut = getutxent()) != NULL) {
+               if (ut->ut_type != USER_PROCESS)
+                       continue;
                if (f->f_type == F_WALL) {
-                       if ((p = ttymsg(iov, iovlen, ep->line, TTYMSGTIME)) !=
-                           NULL) {
+                       if ((p = ttymsg(iov, iovlen, ut->ut_line,
+                           TTYMSGTIME)) != NULL) {
                                errno = 0;      /* already in msg */
                                logerror(p);
                        }
@@ -1384,9 +1360,9 @@ wallmsg(struct filed *f, struct iovec *iov, const int iovlen)
                for (i = 0; i < MAXUNAMES; i++) {
                        if (!f->f_un.f_uname[i][0])
                                break;
-                       if (!strcmp(f->f_un.f_uname[i], ep->name)) {
-                               if ((p = ttymsg(iov, iovlen, ep->line, TTYMSGTIME))
-                                   != NULL) {
+                       if (!strcmp(f->f_un.f_uname[i], ut->ut_user)) {
+                               if ((p = ttymsg(iov, iovlen, ut->ut_line,
+                                   TTYMSGTIME)) != NULL) {
                                        errno = 0;      /* already in msg */
                                        logerror(p);
                                }
@@ -1394,6 +1370,7 @@ wallmsg(struct filed *f, struct iovec *iov, const int iovlen)
                        }
                }
        }
+       endutxent();
        reenter = 0;
 }
 
@@ -1404,7 +1381,7 @@ reapchild(int signo __unused)
        pid_t pid;
        struct filed *f;
 
-       while ((pid = wait3(&status, WNOHANG, NULL)) > 0) {
+       while ((pid = wait3(&status, WNOHANG, (struct rusage *)NULL)) > 0) {
                if (!Initialized)
                        /* Don't tell while we are initting. */
                        continue;
@@ -1417,7 +1394,7 @@ reapchild(int signo __unused)
                for (f = Files; f; f = f->f_next)
                        if (f->f_type == F_PIPE &&
                            f->f_un.f_pipe.f_pid == pid) {
-                               close(f->f_file);
+                               (void)close(f->f_file);
                                f->f_un.f_pipe.f_pid = 0;
                                log_deadchild(pid, status,
                                              f->f_un.f_pipe.f_pname);
@@ -1496,10 +1473,10 @@ logerror(const char *type)
                return;
        recursed++;
        if (errno)
-               snprintf(buf,
+               (void)snprintf(buf,
                    sizeof buf, "syslogd: %s: %s", type, strerror(errno));
        else
-               snprintf(buf, sizeof buf, "syslogd: %s", type);
+               (void)snprintf(buf, sizeof buf, "syslogd: %s", type);
        errno = 0;
        dprintf("%s\n", buf);
        logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
@@ -1519,21 +1496,21 @@ die(int signo)
        for (f = Files; f != NULL; f = f->f_next) {
                /* flush any pending output */
                if (f->f_prevcount)
-                       fprintlog(f, 0, NULL);
+                       fprintlog(f, 0, (char *)NULL);
                if (f->f_type == F_PIPE && f->f_un.f_pipe.f_pid > 0) {
-                       close(f->f_file);
+                       (void)close(f->f_file);
                        f->f_un.f_pipe.f_pid = 0;
                }
        }
        Initialized = was_initialized;
        if (signo) {
                dprintf("syslogd: exiting on signal %d\n", signo);
-               snprintf(buf, sizeof(buf), "exiting on signal %d", signo);
+               (void)snprintf(buf, sizeof(buf), "exiting on signal %d", signo);
                errno = 0;
                logerror(buf);
        }
        STAILQ_FOREACH(fx, &funixes, next)
-               unlink(fx->name);
+               (void)unlink(fx->name);
        pidfile_remove(pfh);
 
        exit(1);
@@ -1562,7 +1539,7 @@ init(int signo)
         * Load hostname (may have changed).
         */
        if (signo != 0)
-               strlcpy(oldLocalHostName, LocalHostName,
+               (void)strlcpy(oldLocalHostName, LocalHostName,
                    sizeof(oldLocalHostName));
        if (gethostname(LocalHostName, sizeof(LocalHostName)))
                err(EX_OSERR, "gethostname() failed");
@@ -1580,28 +1557,23 @@ init(int signo)
        for (f = Files; f != NULL; f = next) {
                /* flush any pending output */
                if (f->f_prevcount)
-                       fprintlog(f, 0, NULL);
+                       fprintlog(f, 0, (char *)NULL);
 
                switch (f->f_type) {
                case F_FILE:
                case F_FORW:
                case F_CONSOLE:
                case F_TTY:
-                       close(f->f_file);
+                       (void)close(f->f_file);
                        break;
                case F_PIPE:
                        if (f->f_un.f_pipe.f_pid > 0) {
-                               close(f->f_file);
+                               (void)close(f->f_file);
                                deadq_enter(f->f_un.f_pipe.f_pid,
                                            f->f_un.f_pipe.f_pname);
                        }
                        f->f_un.f_pipe.f_pid = 0;
                        break;
-               case F_RING:
-                       munmap(f->f_un.f_ring.f_footer,
-                               sizeof(struct clog_footer));
-                       close(f->f_file);
-                       break;
                }
                next = f->f_next;
                if (f->f_program) free(f->f_program);
@@ -1634,8 +1606,8 @@ init(int signo)
         *  Foreach line in the conf table, open that file.
         */
        f = NULL;
-       strlcpy(host, "*", sizeof(host));
-       strlcpy(prog, "*", sizeof(prog));
+       (void)strlcpy(host, "*", sizeof(host));
+       (void)strlcpy(prog, "*", sizeof(prog));
        while (fgets(cline, sizeof(cline), cf) != NULL) {
                /*
                 * check for end-of-section, comments, strip off trailing
@@ -1656,7 +1628,7 @@ init(int signo)
                        while (isspace(*p))
                                p++;
                        if ((!*p) || (*p == '*')) {
-                               strlcpy(host, "*", sizeof(host));
+                               (void)strlcpy(host, "*", sizeof(host));
                                continue;
                        }
                        if (*p == '@')
@@ -1674,7 +1646,7 @@ init(int signo)
                        p++;
                        while (isspace(*p)) p++;
                        if ((!*p) || (*p == '*')) {
-                               strlcpy(prog, "*", sizeof(prog));
+                               (void)strlcpy(prog, "*", sizeof(prog));
                                continue;
                        }
                        for (i = 0; i < NAME_MAX; i++) {
@@ -1709,7 +1681,7 @@ init(int signo)
        }
 
        /* close the configuration file */
-       fclose(cf);
+       (void)fclose(cf);
 
        Initialized = 1;
 
@@ -1743,10 +1715,6 @@ init(int signo)
                                }
                                break;
 
-                       case F_RING:
-                               printf("%s", f->f_un.f_ring.f_rname);
-                               break;
-
                        case F_PIPE:
                                printf("%s", f->f_un.f_pipe.f_pname);
                                break;
@@ -1768,7 +1736,7 @@ init(int signo)
         * Log a change in hostname, but only on a restart.
         */
        if (signo != 0 && strcmp(oldLocalHostName, LocalHostName) != 0) {
-               snprintf(hostMsg, sizeof(hostMsg),
+               (void)snprintf(hostMsg, sizeof(hostMsg),
                    "syslogd: hostname changed, \"%s\" to \"%s\"",
                    oldLocalHostName, LocalHostName);
                logmsg(LOG_SYSLOG|LOG_INFO, hostMsg, LocalHostName, ADDDATE);
@@ -1779,7 +1747,7 @@ init(int signo)
         * the prefix, and if this is *not* a restart.
         */
        if (signo == 0 && !use_bootfile) {
-               snprintf(bootfileMsg, sizeof(bootfileMsg),
+               (void)snprintf(bootfileMsg, sizeof(bootfileMsg),
                    "syslogd: kernel boot file is %s", bootfile);
                logmsg(LOG_KERN|LOG_INFO, bootfileMsg, LocalHostName, ADDDATE);
                dprintf("%s\n", bootfileMsg);
@@ -1797,7 +1765,6 @@ cfline(const char *line, struct filed *f, const char *prog, const char *host)
        const char *p, *q;
        char *bp;
        char buf[MAXLINE], ebuf[100];
-       struct stat sb;
 
        dprintf("cfline(\"%s\", f, \"%s\", \"%s\")\n", line, prog, host);
 
@@ -1894,7 +1861,8 @@ cfline(const char *line, struct filed *f, const char *prog, const char *host)
 
                        pri = decode(buf, prioritynames);
                        if (pri < 0) {
-                               snprintf(ebuf, sizeof ebuf,
+                               errno = 0;
+                               (void)snprintf(ebuf, sizeof ebuf,
                                    "unknown priority name \"%s\"", buf);
                                logerror(ebuf);
                                return;
@@ -1922,7 +1890,8 @@ cfline(const char *line, struct filed *f, const char *prog, const char *host)
                        } else {
                                i = decode(buf, facilitynames);
                                if (i < 0) {
-                                       snprintf(ebuf, sizeof ebuf,
+                                       errno = 0;
+                                       (void)snprintf(ebuf, sizeof ebuf,
                                            "unknown facility name \"%s\"",
                                            buf);
                                        logerror(ebuf);
@@ -1952,6 +1921,7 @@ cfline(const char *line, struct filed *f, const char *prog, const char *host)
        case '@':
                {
                        char *tp;
+                       char endkey = ':';
                        /*
                         * scan forward to see if there is a port defined.
                         * so we can't use strlcpy..
@@ -1960,9 +1930,19 @@ cfline(const char *line, struct filed *f, const char *prog, const char *host)
                        tp = f->f_un.f_forw.f_hname;
                        p++;
 
-                       while (*p && (*p != ':') && (i-- > 0)) {
+                       /*
+                        * an ipv6 address should start with a '[' in that case
+                        * we should scan for a ']'
+                        */
+                       if (*p == '[') {
+                               p++;
+                               endkey = ']';
+                       }
+                       while (*p && (*p != endkey) && (i-- > 0)) {
                                *tp++ = *p++;
                        }
+                       if (endkey == ']' && *p == endkey)
+                               p++;
                        *tp = '\0';
                }
                /* See if we copied a domain and have a port */
@@ -1997,53 +1977,17 @@ cfline(const char *line, struct filed *f, const char *prog, const char *host)
                                f->f_type = F_CONSOLE;
                        else
                                f->f_type = F_TTY;
-                       strlcpy(f->f_un.f_fname, p + sizeof(_PATH_DEV) - 1,
+                       (void)strlcpy(f->f_un.f_fname, p + sizeof(_PATH_DEV) - 1,
                            sizeof(f->f_un.f_fname));
                } else {
-                       strlcpy(f->f_un.f_fname, p, sizeof(f->f_un.f_fname));
+                       (void)strlcpy(f->f_un.f_fname, p, sizeof(f->f_un.f_fname));
                        f->f_type = F_FILE;
                }
                break;
 
-       case '%':
-               if ((f->f_file = open(p + 1, O_RDWR, 0 )) < 0) {
-                       f->f_type = F_UNUSED;
-                       logerror(p + 1);
-                       break;
-               }
-               if (fstat(f->f_file,&sb) < 0) {
-                       close(f->f_file);
-                       f->f_type = F_UNUSED;
-                       logerror(p+1);
-                       break;
-               }
-               f->f_un.f_ring.f_footer = 
-                       mmap(NULL, sizeof(struct clog_footer), 
-                            PROT_READ|PROT_WRITE, MAP_SHARED, 
-                            f->f_file, sb.st_size-sizeof(struct clog_footer));
-               if (f->f_un.f_ring.f_footer == NULL) {
-                       close(f->f_file);
-                       f->f_type = F_UNUSED;
-                       logerror(p + 1);
-                       break;
-               }
-               if (memcmp(&(f->f_un.f_ring.f_footer->cf_magic), MAGIC_CONST, 4) != 0) {
-                       munmap(f->f_un.f_ring.f_footer,
-                               sizeof(struct clog_footer));
-                       close(f->f_file);
-                       f->f_type = F_UNUSED;
-                       errno = ENODEV;
-                       logerror(p + 1);
-                       break;
-               }
-               f->f_un.f_ring.f_size = sb.st_size;
-               strcpy(f->f_un.f_ring.f_rname, p + 1);
-               f->f_type = F_RING;
-               break;
-
        case '|':
                f->f_un.f_pipe.f_pid = 0;
-               strlcpy(f->f_un.f_pipe.f_pname, p + 1,
+               (void)strlcpy(f->f_un.f_pipe.f_pname, p + 1,
                    sizeof(f->f_un.f_pipe.f_pname));
                f->f_type = F_PIPE;
                break;
@@ -2056,9 +2000,9 @@ cfline(const char *line, struct filed *f, const char *prog, const char *host)
                for (i = 0; i < MAXUNAMES && *p; i++) {
                        for (q = p; *q && *q != ','; )
                                q++;
-                       strncpy(f->f_un.f_uname[i], p, 32);
-                       if ((q - p) > 32)
-                               f->f_un.f_uname[i][32] = '\0';
+                       (void)strncpy(f->f_un.f_uname[i], p, MAXLOGNAME - 1);
+                       if ((q - p) >= MAXLOGNAME)
+                               f->f_un.f_uname[i][MAXLOGNAME - 1] = '\0';
                        else
                                f->f_un.f_uname[i][q - p] = '\0';
                        while (*q == ',' || *q == ' ')
@@ -2075,9 +2019,9 @@ cfline(const char *line, struct filed *f, const char *prog, const char *host)
  *  Decode a symbolic name to a numeric value
  */
 static int
-decode(const char *name, CODE *codetab)
+decode(const char *name, const CODE *codetab)
 {
-       CODE *c;
+       const CODE *c;
        char *p, buf[40];
 
        if (isdigit(*name))
@@ -2103,7 +2047,7 @@ markit(void)
        struct filed *f;
        dq_t q, next;
 
-       now = time(NULL);
+       now = time((time_t *)NULL);
        MarkSeq += TIMERINTVL;
        if (MarkSeq >= MarkInterval) {
                logmsg(LOG_INFO, "-- MARK --",
@@ -2116,7 +2060,7 @@ markit(void)
                        dprintf("flush %s: repeated %d times, %d sec.\n",
                            TypeNames[f->f_type], f->f_prevcount,
                            repeatinterval[f->f_repeatcount]);
-                       fprintlog(f, 0, NULL);
+                       fprintlog(f, 0, (char *)NULL);
                        BACKOFF(f);
                }
        }
@@ -2129,7 +2073,7 @@ markit(void)
                case 0:
                        /* Already signalled once, try harder now. */
                        if (kill(q->dq_pid, SIGKILL) != 0)
-                               deadq_remove(q->dq_pid);
+                               (void)deadq_remove(q->dq_pid);
                        break;
 
                case 1:
@@ -2142,7 +2086,7 @@ markit(void)
                         * drop it from the dead queue).
                         */
                        if (kill(q->dq_pid, SIGTERM) != 0)
-                               deadq_remove(q->dq_pid);
+                               (void)deadq_remove(q->dq_pid);
                        /* FALLTHROUGH */
 
                default:
@@ -2150,7 +2094,7 @@ markit(void)
                }
        }
        MarkSet = 0;
-       alarm(TIMERINTVL);
+       (void)alarm(TIMERINTVL);
 }
 
 /*
@@ -2192,14 +2136,14 @@ waitdaemon(int nochdir, int noclose, int maxwait)
                return (-1);
 
        if (!nochdir)
-               chdir("/");
+               (void)chdir("/");
 
        if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {